PolarDB MySQL版优化了B-tree索引的并发控制机制,有效地提升了高并发读写场景下的性能。本文介绍了B-tree并发控制优化的使用方法和使用该机制的限制和前提条件等内容。
背景信息
InnoDB引擎使用索引来组织表结构,每张表的数据均放在一个对应的聚集索引(Clustered index)中,表中的其他索引称之为二级索引(Secondary Index)。InnoDB使用B-tree作为索引结构,扁平且平衡的树结构可以保证单次访问数据的IO次数较少且固定。
InnoDB采用加锁的方式对物理页(B-tree节点)的内存结构进行并发访问控制。每个物理页都有一个对应的读写锁(RW latch),而B-tree由多个节点和边组成,从整体上来看,对单个节点加锁并不能保证多线程访问时的读写一致性。例如,一个线程在做B-tree结构调整(SMO)时改动了多个物理页,此时,若有其他线程访问该B-tree结构,会访问到不正确的B-tree结构从而导致数据读写错误。
为了解决上述的数据读写错误问题,InnoDB采用同时持有多个节点锁的方式来保证B-tree并发读写的一致性,并设计了加锁规则以防止多个线程访问B-tree结构时出现死锁的问题。在B-tree并发控制算法的实现上,InnoDB进行了多次优化迭代,改进的目的都是为了提高B-tree的并发读写能力,但目前仍然存在以下问题:
SMO无法并发:即同一时刻只允许一个SMO执行,导致在高并发读写场景下index latch成为全局的瓶颈点。
线程加锁范围大:为了避免死锁,乐观操作要持有遍历路径上所有节点的S锁,悲观操作要持有所有可能修改节点的X锁。线程加锁范围大,且并发越高越会加剧锁与锁之间的竞争,尤其在一些关键节点的竞争会更明显。
PolarDB MySQL版针对性地优化了B-tree索引的并发控制机制,具体优化点如下:
提升并发度:允许所有操作并发访问B-tree,将线程间的冲突控制在Page级别。
降低锁粒度:所有的操作都实现了latch coupling,缩小加锁范围,降低线程间的冲突。
使用限制
该优化只针对B-tree主索引和二级索引,不包括全文索引和空间索引等。
使用B-tree并发控制优化机制时,需要将参数
innodb_adaptive_hash_index
的值设置为OFF。
版本限制
PolarDB MySQL版产品版本为企业版或标准版,且数据库引擎版本需满足如下要求:
数据库引擎版本为8.0.1,且小版本为8.0.1.1.28及以上。
数据库引擎版本为8.0.2,且小版本为8.0.2.2.17及以上。
您可以通过查询版本号来确认集群版本。
使用方法
登录PolarDB控制台。将参数loose_innodb_polar_blink_tree
的值设置为ON来开启B-tree并发控制优化机制。设置参数值的具体操作请参见设置集群参数和节点参数。loose_innodb_polar_blink_tree
参数的具体说明如下表:
参数名称 | 级别 | 参数说明 |
loose_innodb_polar_blink_tree | Global | B-tree并发控制优化机制控制开关。取值范围如下:
|
该优化机制默认关闭,修改参数loose_innodb_polar_blink_tree
的值后会自动重启集群,通常情况下,重启时服务闪断时间在一分钟以内,具体时间与数据量和表数量相关,建议您在业务低谷期进行操作,并确保应用程序具备重连机制。
性能测试
在高并发TPCC场景(1000 warehouse)下,开启和关闭B-tree并发控制优化机制的性能如下所示:
未开启B-tree并发控制优化机制时,InnoDB在并发数为128时达到了性能峰值。
开启B-tree并发控制优化机制后,InnoDB在并发数为256时达到了性能峰值,较未开启B-tree并发控制优化机制时的读写性能提升了140%。