PolarDB B-tree 并发控制优化

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%;

原文链接

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

几种常见的 MySQL/PolarDB-MySQL 回收表空间方法对比

背景 为什么需要回收表空间&#xff1f;任何一个存储或您购买的实例规格都有容量限制&#xff0c;并且根据存储介质不同&#xff0c;保存方式不同&#xff0c;相应地成本也会不同。在线数据库的存储成本是比较高的&#xff0c;所以架构师和DBA在系统设计之初就要考虑满足未来几…

Lindorm-Operator云原生实践

背景介绍&#xff1a; 随着 Kubernetes 使用的越来越广泛&#xff0c;k8s管理的native的对象资源有时并不能满足用户的需求&#xff0c;为了提高可扩展性&#xff0c;自 v1.7 以来&#xff0c;Kubernetes 引入了 CRD 机制&#xff08;CustomResourceDefinition&#xff09;&am…

客户端单元测试实践 — C++篇

背景 我们团队在手淘中主要负责BehaviX模块&#xff0c;代码主要是一些逻辑功能&#xff0c;很少涉及到UI&#xff0c;为了减少双端不一致问题、提高性能&#xff0c;我们采用了将核心代码C化的策略。 由于团队项目偏底层&#xff0c;测试同学难以完全覆盖&#xff0c;回归成…

MySQL 统计信息不准导致的性能问题

表的统计信息错误导致优化器选择错误的执行计划。 一个客户的性能优化案例: 没有修改数据库实例的任何配置参数以及业务代码没有变更的情况下&#xff0c;一条 sql 出现大幅性能下降。 我们来看看出问题的sql 以及他的执行计划: mysql> explain -> SELECT count(con.…

设z=〖(1+xy)〗^y,求 ∂z/∂y

z〖(1xy)〗^y lnzyln&#xff08;1&#xff0b;xy&#xff09; 两边同时对y求偏导&#xff0c;得 1/z ∂z/∂yln&#xff08;1&#xff0b;xy&#xff09;&#xff0b;y1/&#xff08;1&#xff0b;xy&#xff09; x 1/z ∂z/∂yln&#xff08;1&#xff0b;xy&#xff09;&…

基于 RTS 超低延时直播优化强互动场景体验

RTS 在阿里云视频直播的基础上进行底层技术优化&#xff0c;通过集成阿里云播放器 SDK&#xff0c;支持在千万级并发场景下节点间毫秒级延时直播的能力&#xff0c;弥补了传统直播存在 3~6 秒延时的问题&#xff0c;确保了超低延时、低卡顿、秒开流畅的直播观看体验。本文介绍了…

一文详解用 eBPF 观测 HTTP

前言 随着eBPF推出&#xff0c;由于具有高性能、高扩展、安全性等优势&#xff0c;目前已经在网络、安全、可观察等领域广泛应用&#xff0c;同时也诞生了许多优秀的开源项目&#xff0c;如Cilium、Pixie等&#xff0c;而iLogtail 作为阿里内外千万实例可观测数据的采集器&…

图像格式jpg、jpeg、jpe、gif、png、png等有何不同?ps中那种图片格式可以保留图层?

&#xff08;1&#xff09;jpg格式&#xff1a;即为jpeg格式&#xff0c;是通过压缩改变画质和文件尺寸的格式。压缩后恶化的图像无法还原&#xff0c;使用于数字图像及Web中的照片中。&#xff08;2&#xff09;jpeg格式&#xff1a;是目前网络上最流行的图像格式&#xff0c;…

面向云时代的龙蜥操作系统,是 CentOS 替代的最佳选择

2022 开放原子全球开源峰会 OpenAnolis 分论坛上&#xff0c;阿里云智能基础软件产品经理张鹏程做了《面向云时代的龙蜥操作系统&#xff0c;应对 CentOS 停服的最佳选择》的主题分享&#xff0c;介绍了操作系统产业迎来新发展格局&#xff0c;龙蜥致力于成为 CentOS 迁移的最佳…

数据库治理利器:动态读写分离

背景 在分布式系统架构中&#xff0c;业务的流量都是端到端的。每个请求都会经过很多层处理&#xff0c;比如从入口网关再到 Web Server 再到服务之间的调用&#xff0c;再到服务访问缓存或 DB 等存储。 对于我们的系统来说&#xff0c;数据库是非常重要的一块。因此无论是在稳…

const与define之间的区别?

const定义常量从汇编的角度来看&#xff0c;只是给出了对应的内存地址&#xff0c;而不是象#define一样给出的是立即数&#xff0c;所以&#xff0c;const定义的常量在程序运行过程中只有一份拷贝&#xff0c;而#define定义的常量在内存中有若干个拷贝。 举例&#xff1a;cons…

为什么我要迁移 SpringBoot 到函数计算

为什么要迁移&#xff1f; 我们的业务有很多对外提供服务的 RESTful API&#xff0c;并且要执行很多不同的任务&#xff0c;例如同步连锁 ERP 中的商品信息到美团/饿了么等平台&#xff0c;在线开发票等。由于各种 API 和任务执行的不确定性&#xff0c;经常会因为资源不足导致…

Ingress Nginx 接连披露高危安全漏洞,是否有更好的选择?

今年 K8s Ingress Nginx 项目接连披露了三个高危安全漏洞&#xff08;CVE-2021-25745[1], CVE-2021-25746[2], CVE-2021-25748[3]&#xff09;&#xff0c;该项目也在近期宣布将停止接收新功能 PR&#xff0c;专注修复并提升稳定性。Ingress Nginx 作为 K8s 项目自带的网关组件…

链表c++代码的实现

//说明:各位测试数据的时候&#xff0c;请严格按照主函数来测试数据。因为这个链表是假设所有输入数据正确的情况。。。假如随便乱输入的话。。我没写边界检查。 //本次写法是比较简洁的。方便大家学习。 #include "iostream" using namespace std; typedef struct …

浅谈数据仓库架构设计

1. 数据中台与DW/BI/DSS 个人认为数据中台本质上是一种新的适配大数据技术发展的新的“数据仓库-决策支持&#xff08;商业智能&#xff09;”架构。这个架构是构建在传统的架构基础之上&#xff0c;对传统架构的一种新的发展。 数据中台从企业的视角出发&#xff0c;要求企业…

RocketMQ 消息集成:多类型业务消息 - 定时消息

引言 Apache RocketMQ 诞生至今&#xff0c;历经十余年大规模业务稳定性打磨&#xff0c;服务了 100% 阿里集团内部业务以及阿里云数以万计的企业客户。作为金融级可靠的业务消息方案&#xff0c;RocketMQ 从创建之初就一直专注于业务集成领域的异步通信能力构建。 本篇将继续…

一文读懂 BizDevOps:数字化转型下的技术破局

我们正迈向数字经济时代&#xff0c;数字化转型成为普遍行动。未来绝大多数业务都将运行在数字基座之上&#xff0c;软件系统成为业务创新和发展的核心引擎。在这一趋势下&#xff0c;产品研发的交付能力面临巨大挑战&#xff0c;产品研发的交付实践和方法亟待变革。 BizDevOp…

栈c++代码实现

//实在不想写数组法了&#xff0c;写个常用的STL的吧 #include "iostream" #include "algorithm" #include "stack" using namespace std; void Init(stack <int> s) { while(!s.empty()) { s.pop(); } } int main() { stack …

地址标准化服务AI深度学习模型推理优化实践

导读 深度学习已在面向自然语言处理等领域的实际业务场景中广泛落地&#xff0c;对它的推理性能优化成为了部署环节中重要的一环。推理性能的提升&#xff1a;一方面&#xff0c;可以充分发挥部署硬件的能力&#xff0c;降低用户响应时间&#xff0c;同时节省成本&#xff1b;…

PS里建立工作路径对话框中的“容差”是干什么的?

这里的容差是指&#xff1a;将选区转换为路径时的平滑程度&#xff0c;容差越大&#xff0c;平滑越重&#xff1b;容差越小&#xff0c;越精确&#xff08;与原选区对照&#xff09;&#xff0c;越接近你画的选区。PS的容差用在不同的地方&#xff0c;有不同的用法&#xff0c;…