前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >提升性能与一致性:MySQL 5.7中的组提交与两阶段提交机制解析

提升性能与一致性:MySQL 5.7中的组提交与两阶段提交机制解析

作者头像
@派大星
发布2024-07-26 15:03:17
170
发布2024-07-26 15:03:17
举报
文章被收录于专栏:码上遇见你

MySQL 的组提交(Group Commit)是一项优化技术,旨在提升数据库系统的性能与事务处理效率。它通过将多个事务的提交操作合并为一个批处理操作,减少磁盘 IO 和锁定开销,从而加速事务处理。

我们的数据库需频繁执行数据变更操作,并将变更数据持久化,以便进行崩溃恢复、主从同步及回滚等,这涉及到 binlog、redolog 及 undolog 的写入。频繁的文件写入会触发频繁的磁盘操作。为降低提交操作的开销,MySQL 引入了组提交技术,将多个事务的提交操作合并为一个批处理操作,以减少磁盘 IO 次数。此批处理操作包含多个事务的修改,并一次性写入二进制日志。

通过以下命令可以查看组提交的配置:

代码语言:javascript
复制
mysql> show variables like '%group_commit%';
+-----------------------------------------+-------+
| Variable_name                           | Value |
+-----------------------------------------+-------+
| binlog_group_commit_sync_delay          | 0     |
| binlog_group_commit_sync_no_delay_count | 0     |
+-----------------------------------------+-------+
2 rows in set (0.00 sec)
  • binlog_group_commit_sync_delay
    • 延迟多长时间再通过 fsync 进行刷盘,将数据持久化
  • binlog_group_commit_sync_no_delay_count
    • 累积多少次操作后再通过 fsync 进行刷盘,将数据持久化

注意,这两个条件是或的关系,只要满足其一,即会触发提交动作。

说到这里我们不得不提一下什么是事务的两阶段提交。

什么是事务的 2 阶段提交?

所谓的 MySQL 事务的两阶段提交,是在更新过程中,确保 binlog 和 redolog 一致性的一种手段。

上图中右侧部分即为两阶段提交。其过程如下:

  • Prepare 阶段
    • 此阶段 SQL 已成功执行并生成 redolog,处于准备阶段。
  • BinLog 持久化
    • binlog 提交,通过 write() 将 binlog 内存日志数据写入文件缓冲区;
    • 通过 fsync() 将 binlog 从文件缓冲区永久写入磁盘。
  • Commit
    • 在执行引擎内部执行事务操作,更新 redolog,处于提交阶段。

write 和 fsync 是与文件系统和磁盘 IO 相关的两个不同操作。 write 操作将数据写入文件的缓冲区,这意味着 write 操作完成后,并不一定立即将数据持久化到磁盘上,而是将数据暂时存储在内存中。 fsync 用于强制将文件的修改持久化到磁盘上。它通常与 write 配合使用,以确保文件的修改在 fsync 操作完成后被写入磁盘。

那么,为什么这个过程需要用两阶段提交的方式呢?

假设我们执行一条 SQL 语句,修改它的 name 为 Paidaxing :update user set name = 'paidaxing' where id = 10

如果先写入 redo log 成功,但还未写入 bin log 时系统崩溃。MySQL 重启后,可以根据 redolog 将记录更新为'paidaxing'。但由于 binlog 未成功写入,无法记录这次变更,主备同步时缺少这条 SQL,导致主备库之间数据不一致。

反之,先写入 binlog 成功,但未及写入 redolog 时系统崩溃。MySQL 重启后,由于 redo log 未写入,数据库记录保持旧值。但 binlog 已成功写入,主备同步时将新值同步到备库,导致主备库之间数据不一致。

如上述例子所示,如果不引入两阶段提交,在 bin log 和 redo log 无法保证一致性的情况下,主备库之间的数据会不一致

为了解决这一问题,引入了两阶段提交,以整体控制 redo log 和 bin log 的一致性写入。

2 阶段如何保证一致性的?

引入两阶段提交之后,事务的提交过程可能有以下三种情况:

情况一:一阶段提交之后崩溃 即在写入 redo log,处于 prepare 状态的时候崩溃。此时已经写了 redo log,并处于 prepare 状态,但 binlog 还没写入。此时如果崩溃恢复,直接回滚事务即可,这样主备库是一致的,都没有执行这个事务。

情况二:一阶段提交成功,写完 binlog 之后崩溃此时,redo log 处于 prepare 状态,binlog 已写入。这时检查 binlog 中的事务是否存在并且完整。如果存在且完整,则直接提交事务;如果不存在或者不完整,则回滚事务。

情况三:redolog 处于 commit 状态时崩溃 重启后的处理方案同情况二。

由此得出结论,两阶段提交能够确保数据的一致性。

如何判断 binlog 和 redolog 达成一致了?

当 MySQL 写完 redo log 并将其标记为 prepare 状态时,会在 redo log 中记录一个 XID,该 XID 全局唯一地标识着这个事务。而当你设置 sync_binlog=1 时,在完成上述第一阶段写 redo log 后,MySQL 会对应 binlog 并将其直接刷新到磁盘中。

下图展示了磁盘上的 row 格式的 binlog 记录。在 binlog 结束的位置也记录了一个 XID。

只要这个 XID 与 redo log 中记录的 XID 一致,MySQL 就会认为 binlog 和 redo log 在逻辑上是一致的。

言归正传:

在引入组提交之后,两阶段提交的过程会发生一些变化,因为日志的刷盘过程会因组提交而需要等待,因此情况会变成这样:

这里的 write 和 fsync 是与文件系统和磁盘 IO 相关的两个不同操作。

write 操作将数据写入文件的缓冲区,这意味着 write 操作完成后,数据并不一定立即持久化到磁盘,而是暂时存储在内存中。

fsync 用于强制将文件的修改持久化到磁盘上。它通常与 write 配合使用,以确保文件的修改在 fsync 操作完成后被写入磁盘。

因此,用于将缓冲区内容持久化到磁盘的 fsync 步骤被延迟了。它会等待一个组中的多个事务都处于 Prepare 阶段后,再进行一次组提交,即将日志一次性持久化到磁盘中。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是事务的 2 阶段提交?
  • 2 阶段如何保证一致性的?
  • 如何判断 binlog 和 redolog 达成一致了?
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档