简介: PolarDB 解决了 InnoDB 在 B-tree 并发控制上的限制,解决 index lock 竞争问题,并支持了 latch coupling。

InnoDB 索引

InnoDB 引擎使用索引组织表,每个表的数据都放在一个对应的索引中,该索引称为聚集索引(clustered index),使用索引组织表的目的是:

  • 动态地组织磁盘文件结构,维护数据记录有序;
  • 借助索引快速定位记录;

除了 clustered index,一个表中的其它索引称为二级索引(secondary indexes)。二级索引的每个 record 除了包含本身的 columns,还包含其对应的数据行的 primary key,InnoDB 可以利用 primary key 去主索引找到完整的 row。

InnoDB 使用 B-tree 作为索引的数据结构,B-tree 本质是多级索引,扁平且平衡的树结构可以保证单次访问数据的 IO 次数较小且固定。

InnoDB 实现的 B-tree 结构有几点特性:

  • 实际数据全部存储在 leaf 层(即 B+ tree,降低树高度、优化顺序访问);
  • non-leaf 层只存储索引项(key, page no),每个索引项指向唯一一个 child 节点;
  • 一个索引项的 key 为 P,它的 child 节点只能存 >= P 并且 < P1 的记录,其中 P1 是下一个索引项的 key;
  • 每层节点通过双向链表串起来;

B-tree 并发控制

如果把 B-tree 索引看成一个黑盒,不关心内部具体的数据结构,外面看来只有有序排列的 record,所有的读取、插入、删除等操作都能原子地一步完成。这时多线程并发操作不会感知到索引结构,只需要考虑事务层面的约束,例如 InnoDB 中一个事务对 record 加逻辑锁(lock)阻止其它事务访问。

但是实际的 B-tree 操作不是原子的,例如,一个线程在做结构调整(SMO)时会涉及多个页面的改动,此时另外一个线程进来会访问到不正确的 B-tree 结构而产生错误,另外,页面内部的数据结构改动也不能多线程并发执行。

InnoDB 是采用 page 加锁的方式对 B-tree 进行并发控制,每个 page 有一个对应的物理读写锁(rw latch),线程读取一个 page 要先加 S latch,修改 page 时要加 X latch。

因为 B-tree 索引的访问和修改流程是确定的,所以 InnoDB 有一套设计好的加锁规则,防止多线程死锁。与之对应的是,事务锁(lock)是用户层面的,加锁顺序不可控,因此需要死锁检测机制。

并发瓶颈

InnoDB 对 B-tree 的并发控制实现细节可以参考 InnoDB btree latch 优化历程 这篇文章,可以看到多次优化改进的目的都是为了提高 B-tree 的并发访问能力,即尽量减小每个操作的加锁范围和时间。

目前 8.0 版本在 B-tree 并发上还有一些限制:

  • SMO 无法并发:同一时刻只允许有一个 SMO 进行(SMO 线程持有 index SX latch),导致在大批量插入场景下 index latch 会成为全局的瓶颈点,MySQL 官方性能测试人员 Dimitrick 也指出 TPCC 场景下最大的瓶颈在于 index lock contention(MySQL Performance : TPCC "Mystery" [SOLVED])。设想一下,如果将这个限制放开,多个做 SMO 的线程会同时进入 B-tree,每个线程要拿多个 page,如何设计加锁规则避免线程间死锁,有很多细节需要处理。
  • 加锁范围大:为了避免死锁,乐观读写操作要持有遍历路径上所有 non-leaf page 的 S latch,SMO 操作要持有所有可能修改的 page 的 X latch。单一操作的加锁范围比较大,并发操作越多越会加剧锁竞争,在某些关键节点(例如,root、internal node)的竞争会更明显。理论上采用 latch coupling 的方式可以减小加锁范围,遍历过程中最多同时持有 2 个 page 的锁(即沿着一个指针从一个节点到另一个节点时,不能有其他线程去改变这个指针,因此要拿到后一个节点的 latch 再放开前一个 latch),有利于降低并发操作的竞争。

PolarDB 并发控制优化

PolarDB 解决了 InnoDB 在 B-tree 并发控制上的限制:

  1. 提升并发度:去除 index 锁,允许所有操作并发访问 B-tree,线程间冲突只在 page 级别;
  2. 降低锁粒度:所有操作都实现了 latch coupling,减小锁范围,大大降低线程间冲突;

PolarDB 设计了页级别的 B-tree 并发控制,对索引页的加锁规则如下:

规则 1:所有操作采用 latch coupling 形式遍历 B-tree,遍历过程中对非目标节点加 S latch(相当于读取节点指针),直到找到目标节点,根据操作读/写类型对目标节点加 S latch 或 X latch(SMO 操作涉及邻居节点更新,还需要加左右邻居节点的 latch);

为了避免死锁,规定加锁方向为,自上而下,从左到右。而 SMO 操作是自下而上的,即 SMO 的加锁方向是破坏规则的,会造成死锁(InnoDB 的 SMO 操作不使用 latch coupling 方式,开始就从上到下拿到所有相关节点的 latch,从而避免死锁)。

规则 2:在 SMO 操作中间,申请父节点或左邻居节点的 latch 之前,对当前持有 X latch 的 page 做 SMO 标记,并释放这些 latch。

这里借鉴了 B-link 的设计,将 SMO 操作划分为两个阶段,第一阶段完成提前释放 latch,避免了 SMO 操作反向加锁。这样,在 SMO 中间状态没有持有任何 latch。

SMO 中间状态节点设置一个指向其右侧节点的指针(side link),其它读操作访问到 SMO 中间状态的节点,并可以同时在其 right page 中检索,解决了 B-tree 结构不完整的问题。

其它写操作不应该修改处于 SMO 中间状态的节点,因为之前 SMO 操作还没提交。因此,其它线程的写操作遇到 SMO 节点,要等待其 SMO 完成。

规则 3: 其它线程遍历到有 SMO 标记的节点,并想要修改该节点时:立即释放掉已持有的 latch,等待该节点 SMO 完成再从 root 重试;

如果其它线程不释放已持有的 latch,相当于跟 SMO 线程之间互相占有并等待,造成死锁。

性能对比

采用上述的 B-tree 并发控制机制,在高并发 TPCC 场景(1000 warehouse)下:

  1. 当并发小于 64 时,InnoDB 与 Polar index 性能结果接近,InnoDB 在并发 128 时达到性能峰值;
  2. Polar index 在并发 256 时达到峰值,可以看到 Polar index 相比于 InnoDB,峰值提高 141%;

原文链接:https://click.aliyun.com/m/1000352071/

本文为阿里云原创内容,未经允许不得转载。

PolarDB B-tree 并发控制优化的更多相关文章

  1. 【LeetCode】Balanced Binary Tree 算法优化 解题报告

    Balanced Binary Tree Better Solution [LeetCode] https://leetcode.com/submissions/detail/40087813/ To ...

  2. 深度 | 带领国产数据库走向世界,POLARDB底层逻辑是什么?

    POLARDB 是阿里云自主研发的下一代云原生分布式数据库,100%兼容MySQL.PostgreSQL等开源数据库,高度兼容Oracle语法,使用RDS服务的客户不需要修改应用代码,可以一键迁移到P ...

  3. 云栖干货回顾 | 云原生数据库POLARDB专场“硬核”解析

    POLARDB是阿里巴巴自主研发的云原生关系型数据库,目前兼容三种数据库引擎:MySQL.PostgreSQL.Oracle.POLARDB的计算能力最高可扩展至1000核以上,存储容量可达100TB ...

  4. PolarDB PostgreSQL 架构原理解读

    背景 PolarDB PostgreSQL(以下简称PolarDB)是一款阿里云自主研发的企业级数据库产品,采用计算存储分离架构,兼容PostgreSQL与Oracle.PolarDB 的存储与计算能 ...

  5. webpack优化相关操作

    1.缩小文件搜索的范围 • 优化loader配置 尽量精确使用 include 只命中需要的文件.    module.exports = {      module: {        rules: ...

  6. 配置Tree Shaking来减少JavaScript的打包体积

    译者按: 用Tree Shaking技术来减少JavaScript的Payload大小 原文: Reduce JavaScript Payloads with Tree Shaking 译者: Fun ...

  7. 浅谈webpack4.0 性能优化(转)

    前言:在现实项目中,我们可能很少需要从头开始去配置一个webpack 项目,特别是webpack4.0发布以后,零配置启动一个项目成为一种标配.正因为零配置的webpack对项目本身提供的“打包”和“ ...

  8. 965. Univalued Binary Tree

    题目来源: https://leetcode.com/problems/univalued-binary-tree/submissions/ 自我感觉难度/真实难度: 题意: 分析: 自己的代码: c ...

  9. 897. Increasing Order Search Tree

    题目来源: https://leetcode.com/problems/increasing-order-search-tree/ 自我感觉难度/真实难度:medium/easy 题意: 分析: 自己 ...

  10. ML-凸优化初识

    ML问题 = 模型 + 优化 类似于, 程序 = 数据结构 + 算法 模型(objective): DL, LR, SCV, Tree, XGBoost..... 优化(train): GD/SGD, ...

随机推荐

  1. 反编译和逆向出现:java.lang.VerifyError(新问题样本)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  2. Python 潮流周刊第 42 期(摘要)+ 赠书《流畅的Python》6本

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...

  3. Harris/Shi-Tomasi角点检测

    机器视觉--角点检测 什么是角点检测 在几何学里,我们会看到各种各样的三角形.多边形等,它们都有一个显著的特征:包含了角点信息.比如在三角形里,我们有三个角:在矩形里,我们有四个角.我们将找到这些图像 ...

  4. NJUPT第一次积分赛

    NJUPT第一次积分赛 最近在忙第二次积分赛以及一些很复杂的队友关系(人际关系好复杂,好想电赛出个单机模式),但最后结果还是很满意的. 突然想起来第一次积分赛写的屎山,遂拿出来给大火闻闻 没啥很新颖的 ...

  5. 喜报|3DCAT成为国内首批适配Vision Pro内容开发者

    近日,苹果在上海总部举办了国内首场 Apple Vision Pro 开发者实验室活动,3DCAT作为国内领先的实时渲染云平台参与了此次活动,成为国内首批适配 Vision Pro 的内容开发者之一. ...

  6. 04.JavaIO流问题

    目录介绍 4.0.0.1 说一下Java IO里面的常见类,字节流,字符流.接口.实现类.方法阻塞? 4.0.0.2 什么是比特(Bit),什么是字节(Byte),什么是字符(Char),它们长度是多 ...

  7. Snackbar源码分析

    目录介绍 1.最简单创造方法 1.1 Snackbar作用 1.2 最简单的创建 1.3 Snackbar消失的几种方式 2.源码分析 2.1 Snackbar的make方法源码分析 2.2 对Sna ...

  8. AI实用指南:5分钟搭建你自己的LLM聊天应用

    今天,我们将迅速着手搭建一个高效且富有创意的混元聊天应用,其核心理念可以用一个字来概括--快.在这个快节奏的时代,构建一个基础的LLM(Large Language Model,大型语言模型)聊天应用 ...

  9. Markdown文档图片展示问题解决方案

    微信不支持Markdown排版 目前来看微信公众号是不支持Markdown语法的,所以就会出现Markdown预览,复制在粘贴完成吧. 从资料收集来看有一款出现频率比较高的插件 Markdown ni ...

  10. 探索Avalonia:C#跨平台UI框架的力量

    随着跨平台应用的需求不断增长,开发人员需要一种能够在不同操作系统上运行的用户界面(UI)框架. Avalonia 是一种引人注目的选择.在本文中,我们将深入了解 Avalonia 是什么,它与 WPF ...