MySQL 核心模块揭秘 | 09 期 | 二阶段提交 (3) flush、sync、commit 子阶段

1. 写在前面

经过上一篇文章的介绍,我们已经对 commit 阶段有了整体的认识。

这篇文章,我们一起进入各子阶段,看看它们都会干点什么,以及会怎么干。

为了方便理解,我们假设有 30 个事务,它们对应的用户线程编号也从 1 到 30。

2. flush 子阶段

用户线程 16 加入 flush 队列,成为 flush 队长,并且通过申请获得 LOCK_log 互斥量。

flush 队长收编用户线程 17 ~ 30 作为它的队员,队员们进入 flush 队列之后,就开始等待,收到 commit 子阶段的队长发来的通知才会结束等待。

flush 队长开始干活之前,会带领它的队员从 flush 队列挪出来,给后面进入二阶段提交的其它事务腾出空间。

从 flush 队列挪出来之后,flush 队长会触发操作系统,把截止目前产生的所有 redo 日志都刷盘。

这些 redo 日志,当然就包含了它和队员们在 prepare 阶段及之前产生的所有 redo 日志了。

触发 redo 日志刷盘之后,flush 队长会从它自己开始,把它和队员们产生的 binlog 日志写入 binlog 日志文件。

以队长为例,写入过程是这样的:

  • 从事务对应的 trx_cache 中把 binlog 日志读出来,存放到 trx_cache 的内存 buffer 中。
    每次读取 4096(对应代码里的 IO_SIZE)字节的 binlog 日志,最后一次读取剩余的 binlog 日志(小于或等于 4096 字节)。
  • 把 trx_cache 内存 buffer 中的 binlog 日志写入 binlog 日志文件。

队员们产生的 binlog 日志写入 binlog 日志文件的过程,和队长一样。队长把自己和所有队员产生的 binlog 日志都写入 binlog 日志文件之后,flush 子阶段的活就干完了。

flush 队长写完 binlog 日志之后,如果发现 binlog 日志文件的大小大于等于系统变量 max_binlog_size 的值(默认为 1G),会设置一个标志(rotate = true),表示需要切换 binlog 日志文件。后面 commit 子阶段会用到。

到这里,用户线程 16 作为队长的 flush 子阶段,就结束了。

3. sync 子阶段

为了剧情需要,我们假设用户线程 6 ~ 15 此刻还在 sync 队列中,用户线程 6 最先进入队列,是 sync 队长,用户线程 7 ~ 15 都是队员。

用户线程 16(flush 队长)带领队员们来到 sync 子阶段,发现 sync 队列中已经有先行者了。

有点遗憾,用户线程 16 不能成为 sync 子阶段的队长,它和队员们都会变成 sync 子阶段的队员。

此时,用户线程 6 是 sync 队长,用户线程 7 ~ 30 是队员。

进入 sync 子阶段之后,用户线程 16(flush 队长)会释放它在 flush 子阶段获得的 LOCK_log 互斥量,flush 子阶段下一屇的队长就可以获得 LOCK_log 互斥量开始干活了。

交待完用户线程 16(flush 队长)在 sync 子阶段要干的活,该说说 sync 队长了。

sync 队长会申请 LOCK_sync 互斥量,获得互斥量之后,就开始准备给自己和队员们干 sync 子阶段的活了。

队员们依然在一旁当吃瓜群众,等待 sync 队长给它们干活。它们会一直等待,收到 commit 子阶段的队长发来的通知才会结束等待。

就在 sync 队长准备甩开膀子大干一场时,它发现前面还有一个关卡:本次组提交能不能触发操作系统把 binlog 日志刷盘

sync 队长怎么知道自己能不能过这一关?

它会查看一个计数器的值(sync_counter),如果 sync_counter + 1 大于等于系统变量 sync_binlog 的值,就说明自己可以过关。

否则,不能通过这一关,用户线程 6 作为队长的 sync 子阶段就到此结束了,它什么都不用干。

如果 sync 队长过关了,它会想:好不容易过关,我要再收编一些队员,才不枉费我的好运气。

sync 队长会带领队员们继续在 sync 队列中等待,以收编更多队员。这个等待过程是有期限的,满足以下两个条件之一,就结束等待:

  • 已经等待了系统变量 binlog_group_commit_sync_delay 指定的时间(单位:微妙),默认值为 0。
  • sync 队列中的用户线程数量(sync 队长和所有队员加在一起)达到了系统变量 binlog_group_commit_sync_no_delay_count 的值,默认值为 0。

等待结束之后,sync 队长会带领队员们从 sync 队列挪出来,给后面进入二阶段提交的其它事务腾出空间。

接下来,sync 队长终于可以大干一场了,它会触发操作系统把 binlog 日志刷盘,确保它和队员们产生的 binlog 日志写入到磁盘上的 binlog 日志文件中。

这样即使服务器突然异常关机,binlog 日志也不会丢失了。

刷盘完成之后,用户线程 6 作为队长的 sync 子阶段,就到此结束。

介绍完 sync 子阶段的主要流程,我们再来说说 sync_counter

sync_counter 的值从 0 开始,某一次组提交的 sync 队长没有过关,不会触发操作系统把 binlog 日志刷盘,sync_counter 就加 1。

sync_counter 会一直累加,直到后续的某一次组提交,sync_counter + 1 大于等于系统变量 sync_binlog 的值,sync 队长会把 sync_counter 重置为 0,并且触发操作系统把 binlog 日志刷盘。

sync_counter 重置为 0 之后,sync 子阶段是否要触发操作系统把 binlog 日志刷盘,又会开始一个新的轮回。

4. commit 子阶段

同样,为了剧情需要,我们假设用户线程 1 ~ 5 此刻还在 commit 队列中,用户线程 1 最先进入队列,是 commit 队长,用户线程 2 ~ 5 都是队员。

用户线程 6(sync 队长)带领队员们来到 commit 子阶段,发现 commit 队列中也已经有先行者了。

用户线程 6 和队员们一起,都变成了 commit 子阶段的队员。

此刻,用户线程 1 是 commit 队长,用户线程 2 ~ 30 是队员。

进入 commit 子阶段之后,用户线程 6(sync 队长)会释放它在 sync 子阶段获得的 LOCK_sync 互斥量,sync 子阶段下一屇的队长就可以获得 LOCK_sync 互斥量开始干活了。

交待完用户线程 6(sync 队长)进入 commit 子阶段要干的活,该说说 commit 队长了。

commit 队长会申请 LOCK_commit 互斥量,获得互斥量之后,根据系统变量 binlog_order_commits 的值决定接下来的活要怎么干。

如果 binlog_order_commits = true,commit 队长会把它和队员们的 InnoDB 事务逐个提交,然后释放 LOCK_commit 互斥量。

提交 InnoDB 事务完成之后,commit 队长会通知它的队员们(用户线程 2 ~ 30):所有活都干完了,你们都散了吧,别围观了,该干啥干啥去。

队员们收到通知之后,作鸟兽散,它们的二阶段提交也都结束了。

如果 binlog_order_commits = false,commit 队长不会帮助队员们提交 InnoDB 事务,它提交自己的 InnoDB 事务之后,就会释放 LOCK_commit 互斥量。

然后,通知所有队员(用户线程 2 ~ 30):flush 子阶段、sync 子阶段的活都干完了,你们自己去提交 InnoDB 事务。

队员们收到通知之后,就各自提交自己的 InnoDB 事务,谁提交完成,谁的二阶段提交就结束了。

最后,commit 队长还要处理最后一件事。

如果用户线程 16(flush 队长)把 rotate 设置为 true 了,说明 binlog 日志文件已经达到了系统变量 max_binlog_size 指定的上限,需要切换 binlog 日志文件。

切换指的是关闭 flush 子阶段刚写入的 binlog 日志文件,创建新的 binlog 日志文件,以供后续事务提交时写入。

如果需要切换 binlog 日志文件,切换之后,还会根据系统变量 binlog_expire_logs_auto_purgebinlog_expire_logs_secondsexpire_logs_days 清理过期的 binlog 日志。

处理完切换 binlog 日志文件的逻辑之后,commit 队长的工作就此结束,它的二阶段提交就完成了。

5. 总结

flush 子阶段,flush 队长会把自己和队员在 prepare 阶段及之前产生的 redo 日志都刷盘,把事务执行过程中产生的 binlog 日志写入 binlog 日志文件。

sync 子阶段,如果 sync_counter + 1 大于等于系统变量 max_binlog_size 的值,sync 队长会把 binlog 日志刷盘。

commit 子阶段,如果系统变量 binlog_order_commits 的值为 true,commit 队长会把自己和队员们的 InnoDB 事务都提交,否则,commit 队长和队员各自提交自己的 InnoDB 事务。

本期问题:commit 子阶段这种清理过期 binlog 日志的逻辑,会有什么问题吗?欢迎留言交流。

下期预告:MySQL 核心模块揭秘 | 10 期 | binlog 怎么写入日志文件?

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。

SQLE 获取

类型地址
版本库https://github.com/actiontech/sqle
文档https://actiontech.github.io/sqle-docs/
发布信息https://github.com/actiontech/sqle/releases
数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

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

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

相关文章

Titanic数据分析项目——Kaggle数据分析项目实战1

目前预测准确度达到77.511%, 会持续优化并且更新。 一、特征工程: 1、先对缺失值进行填充,先找到缺失值的位置,数值型数据填充众数,字符数据或者是离散型数据则填充出现最多的数据。 2、标准化数值型数据, 根据标准化…

Vue使用L2Dwidget

1、在根文件index.html中引入live2dw/lib/L2Dwidget.min.js 下载模型的文件,放在本地或者cdn 切换不同的模型 模型地址:https://github.com/xiazeyu/live2d-widget-models showLive2d(name: String) {var live2dWidget document.querySelector("…

大数据开发(Hive面试真题-卷三)

大数据开发(Hive面试真题) 1、Hive的文件存储格式都有哪些?2、Hive的count的用法?3、Hive得union和unionall的区别?4、Hive的join操作原理,left join、right join、inner join、outer join的异同&#xff1…

专升本 C语言笔记-01 printf 占位符 转义符

目录 一.printf()函数简介 1.1作用 将格式化后的字符串输出(打印东西) 1.2函数原型 1.3返回值 二.常见占位符 2.1.占位符的使用 2.2.格式修饰符 2.3.输出格式说明 三.转义字符 一.printf()函数简介 1.1作用 将格式化后的字符串输出(打印东西) printf…

Python数值方法在工程和科学问题解决中的应用

💂 个人网站:【 海拥】【神级代码资源网站】【办公神器】🤟 基于Web端打造的:👉轻量化工具创作平台💅 想寻找共同学习交流的小伙伴,请点击【全栈技术交流群】 随着计算机技术的不断发展,Python作…

sqlserver语句中差集、并集、交集的用法

1、并集UNIONUNION 将两个查询的结果合并为一个结果集,并去除重复的行。 SELECT column1, column2 FROM Table1 UNION SELECT column1, column2 FROM Table2;2、交集INTERSECTINTERSECT 返回两个查询的结果中相同的行。 SELECT column1, column2 FROM Table1 IN…

C++之std::move

std::move 是C标准库中的一个函数模板,用于将其参数转换为右值引用。这通常用于移动语义,用于在避免不必要的复制的情况下,将资源(例如内存、文件句柄等)从一个对象转移到另一个对象。std::move 是C11引入的特性。 用…

【Python】新手入门学习:详细介绍开放封闭原则(OCP)及其作用、代码示例

【Python】新手入门学习:详细介绍开放封闭原则(OCP)及其作用、代码示例 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyT…

在Java中,Cloneable接口的作用,抛出CloneNotSupportedException的原因

文章目录 一、Cloneable接口的作用二、Cloneable接口的用法三、Cloneable的标记作用实现原理 一、Cloneable接口的作用 继承Cloneable接口并调用super.clone()是为了确保对象的克隆行为符合Java的规范。尽管Cloneable是一个空接口,没有定义任何方法,但如…

MQTT Topic通配符

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…

如何不依赖Unity直接解压unitypackage的内容

使用场景 我们都知道unity的资源导出是导出成.unitypackage文件,如果要里面的内容,得打开Unity,将unitypackage导入进去才能看到里面的内容。 但是很多时候我们下了几十个unitypackage资源包,又不清楚好不好用,而且导入之后编译特别慢,unity又不提供批量解压的功能,所…

雷达图相关

1.中间显示数字 title: {text: 88,x: center,y: center,textStyle: {color: #333,fontWeight: bolder,fontSize: 64,} } 2.提示信息 tooltip: {trigger: item, // 当鼠标悬浮在某个数据项上时触发}, 3.修改中间颜色 默认: splitArea: {areaStyle: {color: [rgba(…

三分钟搞定普通函数和箭头函数的this指向问题

记住两个口诀: 普通函数的this是:谁调用这个函数,函数的this就指向谁 箭头函数的this是:箭头函数定义时的执行上下文的this是谁,箭头函数的this就指向谁 实例代码: var name222var b {name:111,fn:()>{…

网康科技 NS-ASG 应用安全网关 SQL注入漏洞复现(CVE-2024-2330)

0x01 产品简介 网康科技的NS-ASG应用安全网关是一款软硬件一体化的产品,集成了SSL和IPSec,旨在保障业务访问的安全性,适配所有移动终端,提供多种链路均衡和选择技术,支持多种认证方式灵活组合,以及内置短信认证、LDAP令牌、USB KEY等多达13种认证方式。 0x02 漏洞概述 …

OPENCV(0-1之0.1)

OPENCV-0.1 学习安排计算机视觉简介是什么?应用领域基础概念 OpenCV简介历史背景和主要贡献者支持的语言和平台主要模块和功能 安装(windows_python)pip安装验证安装(记得安装jupyter) 第一个OpenCV程序实践练习 官方文档 学习安排 计算机视…

数据同步方案

目录 1 需求概述 1)时间戳 2)触发器 3)差异更新 4)日志解析 2 产品实施 1)数据同步 2)同步日志 3)流量统计 4)数据比对 1 需求概述 数据同步用于将不同数据库系统产生的数…

欧盟商标的申请流程

欧盟商标的申请流程 1、商标检索:在申请之前,我们建议您进行商标检索,以确定您的商标是否与已有商标存在冲突。 2、申请途径选择:您可以选择通过欧盟商标局的在线系统,或者通过邮寄纸质申请材料的方式进行申请。 3、…

讲讲分布式和集群那点事

本专栏简单讲讲那些特别散乱杂的知识,欢迎各位朋友订阅专栏 感谢一路相伴的朋友们 浅淡计算机系列第5篇 目录 前言 集群 啥是集群? 集群可以应用在哪里? 集群的好处和坏处 举个例子 分布式 啥是分布式?

java 操作JSON对象查找、删除、增加和修改等操作

对JSON的查找 格式: JSONObject.getString("value") 示例: info.getString("name") 删除JSON对象中的某个数据 格式: JSONObject.remove("value") 示例:info.remove("name") 增加和修改J…

2024腾讯云轻量应用服务器地域有什么区别?哪个好?

腾讯云轻量应用服务器地域如何选择?地域就近选择,北方选北京地域、南方选广州地域,华东地区选上海地域。广州上海北京地域有什么区别?哪个好?区别就是城市地理位置不同,其他的差不多,不区分好坏…