PolarDB auto_inc 场景性能优化之路

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介: 在数据库的使用场景中, 最常见的场景是并发插入或者导入数据场景, 在该场景中并不指定自增id, 由数据库自动生成自增id, 然后插入到数据库中, 因此我们也叫auto_inc 场景的数据插入.典型的业务场景如: 游戏行业开服过程中的大批的登录注册场景, 电商活动中给商家后台推单场景等等.我们看看PolarDB 是如何优化针对这种并发插入场景进行优化的.背景知识:在这种并发

在数据库的使用场景中, 最常见的场景是并发插入或者导入数据场景, 在该场景中并不指定自增id, 由数据库自动生成自增id, 然后插入到数据库中, 因此我们也叫auto_inc 场景的数据插入.

典型的业务场景如: 游戏行业开服过程中的大批的登录注册场景, 电商活动中给商家后台推单场景等等.

我们看看PolarDB 是如何优化针对这种并发插入场景进行优化的.

背景知识:

在这种并发插入场景中, 自增id 是递增的, 因此插入的时候其实是插入到btree 最右边的Page 中去的.

直观感受上这种场景是插入到btree 最右一个page, 真的是这样么?

其实不是, 这种场景并不能保证插入数据是连续的, 因此有可能要插入的值比最右Page 最小值小, 插入右边第2个page. 因此这种场景其实是插入最右的多个page.

原因是thread 获得auto_inc 值以后, 到真正进行insert 这一段代码并没有加锁, 因此thread 获得auto_inc 以后被调度走, 反而后面获得auto_inc thread 先进行最后的insert 操作.

所以这样的场景是允许出现的: 并发Insert 时, 后续有可能插入比当前 auto_inc value 小的行

因为这个原因允许Level 0 存在多个page 同时进行插入情况, 允许我们有性能优化的空间. 否则仅仅插入最右page, 就相当于排队对最右Page 进行插入, 没有优化空间.

因此会出现以下场景

image-20230312042949995

在上图中, 此时有3个thread 进行乐观插入, 插入的value 14, 25, 36. 那么此时可以持有各自page x lock, 实现3 个page 同时并发插入.

如果thread = 1, 那么只有最右page 进行插入, 性能一定是不如3个page 同时并发插入来得好.

理论上允许同时插入的leaf page 越多, 并发越高, 性能越好.

那么如果实现允许同时插入的leaf page 越多呢?

尽早进行SMO 操作, 最右Page 尽早分裂, 那么就有更多未被插满的Page 允许用户同时进行插入

所以接下来我们的优化点就是

尽早进行SMO 操作

尽早进行SMO 操作

尽早进行SMO 操作

那么在并发插入场景中, InnoDB 中实际情况是怎样的?

image-20230312043008614

在我们测试中, 发现可能存在因为调度问题造成auto_inc 差值差不多能够造成同时3~4 个page 允许同时插入, 上图也是这样的初始场景.

阶段1: 当前有3个thread 分别乐观插入到3个不同的level 0 leaf page 中, 并持有3个 leaf page x lock. 同时还有N 个thread 持有Level 1 page s lock, 等待在level 0 leaf page x lock 上, 即等当前3 个thread 完成插入以后N 个thread再进行插入.

阶段2: 此时SMO thread 要进行悲观插入, 持有index sx lock 和 Level 2 page x lock, 等待在持有Level 1 Page 的x lock 上, 但当前Level 1 page 上面已经有N 个乐观插入持有page s lock 在等待

阶段3: SMO thread 需要等待之前N 个乐观插入thread完成以后(这里最右Page 的乐观插入大概率是失败, 因为这次SMO 操作就是为了做最右Page 的SMO, 那么乐观插入失败以后会转换成悲观插入), 获得了Level 1 Page x lock, 然后再等待Level 0 leaf page 上的X lock 以后, 完成加锁操作然后进行SMO 操作, SMO 完成.

这里可以看到SMO thread 需要等待N 个Thread 完成乐观插入尝试以后, 才可以进行SMO 操作, 并发度越高, 乐观插入thread 越多, 那么SMO thread 等待的时间越长, SMO 越不能尽早执行, 导致性能无法提升.

那么为什么限制了Innodb_thread_concurrency 以后, 可以获得更好的性能呢?

从上面的分析可以看到, 其实在auto_inc 场景, 允许并发插入的page 并不多, 差不多只有3~4 个page 允许同时插入, 过多的线程会导致SMO 线程必须等这些乐观插入线程插入尝试完成以后才能进行插入, 乐观插入thread 越多, 等待的时间越长. 最理想的情况是此时最右Page 上没有乐观插入在等待, 那么SMO thread 可以不需要等待任何thread, 实现了尽早进行SMO 操作 这个目标. 而限制了Innodb_thread_concurrency 相当于限制了这里乐观插入thread 数目, 因此实现了更好的性能.

实际测试中Innodb_thread_concurrency = 8 就可以几乎最好的性能了.

1678689543197-aa2a84c1-7296-4b91-af05-40dd12c93940

那么Blink-tree 如何改进这种情况呢?

我们分析现有InnoDB Btree 版本存在的问题的时候提出解决方案通过设置 Innodb_thread_concurrency = 8 来降低并发进入到InnoDB thread num 从而保证高性能的插入, 但是Innodb_thread_concurrency = 8 太低, 正常系统使用的过程中还有查询操作, 因此实际上很少会进行这样的设置, 那么Blink-tree 最后是如何实现允许大量并发线程并能够实现高性能auto_inc 插入呢?

  1. Blink-tree 天然允许SMO 并发, 现有InnoDB Btree 同一时刻只能允许一个SMO 进行, 允许了SMO 并发执行相当于尽早进行SMO 操作
  2. 增加了SMO thread 还不够, 如果SMO thread 和上述InnoDB btree 实现一样, 需要等待乐观插入完成才能进行SMO 操作, 那么其实多个SMO 操作也是串行的, 仅仅增加一点提前执行SMO 的时间.

    因此我们在Blink-tree 上实现锁的优先级调度, 从而实现尽早进行SMO 操作.

    在上述阶段3 中SMO thread 需要和乐观插入thread 去争抢执行优先级, 导致SMO thread 执行效率不高. 通过锁的优先级调度, 给SMO thread 最高优先级, 先唤醒等待在Page x lock 上的SMO thread, 然后再唤醒等待在address lock 上的乐观insert thread, 从而实现尽早进行SMO 操作

具体实现方式如下图所示:

image-20230312051344937

Blink-tree 通过Lock coupling 进行加锁, 即使在悲观插入场景中, 对Level 1 依然是 S lock.

阶段1: 当前有3个SMO thread 正在并发进行SMO. 因为Blink-tree 实现SMO 和Btree 类似, 需要持有中右page lock, 因此只有SMO 1 能够执行, 而SMO 2/SMO 3 等待在右Page Xlock 上.

阶段2: 有N thread 尝试进行乐观插入操作, 乐观插入的时候发现Page 1/2/3 都在进行SMO 操作, 只有Page 4 没有, 因此想插入Page 1/2/3 threads 放弃当前Page s lock, 等待在Page 1/2/3 的address lock 上. 想插入Page 4 thread 等在Page 4 x lock 上.

阶段3: SMO 1 执行完成SMO, 通知SMO 2 进行, 然后唤醒等待在Page 1 address lock 上的乐观插入thread, 由于SMO 2 还在进行中, 持有Page 1 X lock, 因此乐观插入thread 需要等SMO 2执行结束才可以执行. 等SMO 2执行结束通知SMO 3执行, 同时唤醒等待在Page 2 address lock 上的乐观插入, 但是由于SMO 3正在进行中, 持有Page 2 X lock, 因此乐观插入Page 2 因为SMO 3 持有Page 2 X lock, 是无法进行的. 但是此时对Page 1 乐观插入已经可以进行了.最后等SMO 3 也完成, Page 2/3 的乐观插入也就可以进行了

可以看到blink-tree 通过增加并发SMO thread 同时引入锁的优先级调度从而实现尽早进行SMO 操作. 从而实现比InnoDB Btree 更高的性能.

这里其实还有一个与InnoDB Btree 实现的区别, 等待在address 唤醒之后的乐观插入 thread 执行的依然是乐观插入操作, 而InnoDB Btree 在等待Page lock 被唤醒之后执行的是悲观插入操作. 悲观插入加锁的范围广开销大, 因此性能进一步退化.

具体测试场景的数据如下:

img

总结:

可以看到在Blink-tree 场景中. 在并发auto_inc场景中, Blink-tree 是官方Btree版本的2倍, 同时比开启 Innodb_thread_concurrency 也有13% 左右提升.

那么Bw-tree 如何改进这种情况呢?

看下一篇文章...

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
6天前
|
关系型数据库 分布式数据库 PolarDB
PolarDB 开源基础教程系列 7.2 应用实践之 跨境电商场景
本文介绍了如何在跨境电商场景中快速判断商标或品牌侵权,避免因侵权带来的法律纠纷。通过创建品牌表并使用PostgreSQL的pg_trgm插件和GIN索引,实现了高性能的字符串相似匹配功能。与传统方法相比,PolarDB|PostgreSQL的方法不仅提升了上万倍的查询速度,还解决了传统方法难以处理的相似问题检索。具体实现步骤包括创建品牌表、插入随机品牌名、配置pg_trgm插件及索引,并设置相似度阈值进行高效查询。此外,文章还探讨了字符串相似度计算的原理及应用场景,提供了进一步优化和扩展的方向。
35 11
|
6天前
|
SQL 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 7.5 应用实践之 TPCH性能优化
PolarDB在复杂查询、大数据量计算与分析场景的测试和优化实践.
33 7
|
6天前
|
搜索推荐 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 7.3 应用实践之 精准营销场景
本文介绍了基于用户画像的精准营销技术,重点探讨了如何通过标签组合快速圈选目标人群。实验分为三部分: 1. **传统方法**:使用字符串存储标签并进行模糊查询,但性能较差,每次请求都需要扫描全表。 2. **实验1**:引入`pg_trgm`插件和GIN索引,显著提升了单个模糊查询条件的性能。 3. **实验2**:改用数组类型存储标签,并结合GIN索引加速包含查询,性能进一步提升。 4. **实验3**:利用`smlar`插件实现近似度过滤,支持按标签重合数量或比例筛选。
26 3
|
1月前
|
NoSQL 关系型数据库 MySQL
阿里云PolarDB游戏场景最佳实践
阿里云PolarDB游戏场景最佳实践涵盖了数据库体系演进、行业优化、Redis解决方案、性能优化、备份还原及全球部署等内容。PolarDB通过共享存储、物理复制等技术提升读扩展和大容量支持,针对游戏行业的高IO需求进行优化,提供秒级备份与快速恢复能力。同时,PolarDB for Redis实现了一写多读架构,支持百TB级别的高性能存储,具备成本优势。该方案已在米哈游等大型游戏中广泛应用,确保了高并发下的稳定性和数据一致性,满足游戏行业的特殊需求。
79 36
|
5月前
|
存储 SQL 安全
应用案例|开源 PolarDB-X 在互联网安全场景的应用实践
中盾集团采用PolarDB-X云原生分布式数据库开源版本,有效解决了大数据量处理、复杂查询以及历史数据维护等难题,实现了业务的高效扩展与优化。
|
2月前
|
资源调度 关系型数据库 MySQL
PolarDB MySQL场景评测
PolarDB具备快速资源弹升能力,支持5秒探测窗口和1秒内完成资源扩展,适合电商促销和流量波动型SaaS应用。资源伸缩范围广泛,支持0-256核,适用于中小型企业到大型企业。资源伸缩过程中业务无感知,具有高稳定性和成熟性。支持最小0.5 PCU的资源颗粒度,确保成本控制和使用效率。此外,PolarDB支持所有只读节点的数据强一致性,性能不受影响。
65 0
|
5月前
|
关系型数据库 MySQL 分布式数据库
【开发者评测】PolarDB MySQL场景评测获奖名单公布
PolarDB MySQL场景评测获奖名单公布!!
105 0
|
6月前
|
C# Windows IDE
WPF入门实战:零基础快速搭建第一个应用程序,让你的开发之旅更上一层楼!
【8月更文挑战第31天】在软件开发领域,WPF(Windows Presentation Foundation)是一种流行的图形界面技术,用于创建桌面应用程序。本文详细介绍如何快速搭建首个WPF应用,包括安装.NET Framework和Visual Studio、理解基础概念、创建新项目、设计界面、添加逻辑及运行调试等关键步骤,帮助初学者顺利入门并完成简单应用的开发。
228 0
|
1月前
|
Cloud Native 关系型数据库 分布式数据库
让PolarDB更了解您--PolarDB云原生数据库核心功能体验馆
让PolarDB更了解您——PolarDB云原生数据库核心功能体验馆,由阿里云数据库产品事业部负责人宋震分享。内容涵盖PolarDB技术布局、开源进展及体验馆三大部分。技术布局包括云计算加速数据库演进、数据处理需求带来的变革、软硬协同优化等;开源部分介绍了兼容MySQL和PostgreSQL的两款产品;体验馆则通过实际操作让用户直观感受Serverless、无感切换、SQL2Map等功能。
107 7
|
6天前
|
存储 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 8 数据库生态
PolarDB是一款开源的云原生分布式数据库,源自阿里云商业产品。为降低使用门槛,PolarDB携手伙伴打造了完整的开源生态,涵盖操作系统、芯片、存储、集成管控、监控、审计、开发者工具、数据同步、超融合计算、ISV软件、开源插件、人才培养、社区合作及大型用户合作等领域。通过这些合作伙伴,PolarDB提供了丰富的功能和服务,支持多种硬件和软件环境,满足不同用户的需求。更多信息请访问[PolarDB开源官方网站](https://openpolardb.com/home)。
38 4