暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

CirroData技术课堂(二):InnoDB之B+树的并发控制(1)

334

全文约1418字,阅读约9分钟


B+树作为InnoDB存储引擎的存储结构,它的并发程度能够极大的影响着数据库的并发性能。本篇以MySQL 8.0为例,探究B+树并发控制中的一些原理。


B+树中的并发控制是为了解决并发读写中遇到的两个问题:



正在读取/写入的结点被并发线程篡改,读到不一致的结点状态
例如正在读或写一个结点的数据,恰好这时有另外一个并发写线程,在这个结点上插入新的数据,结点内的数据发生移动,导致读到了错误的数据或把结点数据写坏了。换句话说,读写并发和写写并发都要保证/维持结点数据的一致性。


子结点指针失效
刚从父结点读到了子结点的指针,这时有一个并发写线程把子结点写满了,子结点发生了 split,一部分数据挪到了子结点右边的新结点上去了。要读的数据就在这些被挪走的数据之中,接下来拿着子结点的指针去访问子结点,就找不到要读的数据了,这就产生了一个错误的结果。(子结点发生 merge 也会导致类似的问题)‍‍

我们知道,在InnoDB中,有两种锁:

Lock用来锁一些逻辑的对象(如表锁,行锁)以支持事务并发控制;

Latch,用来锁一些物理的数据结构(如Page)以实现数据结构的正确读写。在InnoDB 中latch又可以分为mutex和rwlock。

在InnoDB的实现中,B+树上的并发控制涉及到两种 latch:index latch 和 page latch。index latch是索引的锁,也就是B树级别的一把大锁;page latch是页面上的锁。

这里以InnoDB 8.0.18为例,分析B+树上的加锁规则。

在B+ Tree上共有三种基本操作:

  • 读(BTR_SEARCH_LEAF ):分为点查询和范围查询;
  • 乐观写(BTR_MODIFY_LEAF):仅影响到一个索引页的增删改;
  • 悲观写(BTR_MODIFY_TREE):影响到超过一个索引页的增删改(如insert,delete操作导致了页的分裂或合并)。
点查询
  1. 获得索引的 S lock;
  2. 由上至下依次获取搜索路径节点的 S lock,直至叶子节点;
  3. 释放索引和中间节点的 S lock,仅保留叶子节点;
  4. 读叶子节点的内容;
  5. 释放叶子节点 S lock

以查找以上第4和第5点为例:

乐观写
  1. 获得索引的S lock;
  2. 由上至下 依次获取搜索路径节点的 S lock;
  3. 叶子节点获得 X lock
  4. 释放索引和中间节点的 S lock,仅保留叶子节点;
  5. 修改叶子节点的内容;
  6. 释放叶子节点 X lock

悲观写

这个 latch mode 对应于一次会引起 SMO 的 操作。(SMO,split merge operation,即树的分裂或者合并操作)。在尝试修改一条记录时,会先进行乐观插入,如果乐观插入会引起B+树的结构变化,则重新进行一次悲观插入。

  1. 获得索引的 SX lock

  2. 由上至下依次获取 可能引起分裂或合并的节点(如P1)的 X lock

  3. 依次获得叶子节点左兄弟、自身、右兄弟X lock

  4. 修改索引结构和叶子节点的内容;

  5. 释放所有X lock

相关的代码实现在btr_cur_search_to_nth_level函数中。

优缺点:
  • SMO 操作的过程中允许有read 和 乐观写入操作。sx lock和 s lock不冲突,提高了并发度;

  • SMO操作无法并行,sx lock和 sx lock是冲突的。

在后续篇幅中,将会跟大家分享B+树并发控制中的一些细节,以及一些其他B+树加锁方式,敬请期待!

文章转载自东方国信大数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论