MySQL 核心模块揭秘 | 07 期 | 二阶段提交 (1) prepare 阶段

MySQL Prepared语句(Prepared Statements) 在数据库应用中,很多SQL语句都会重复执行很多次,每次执行可能只是where条件中的变量值不同,但MySQL依然会解析SQL语法并生成执行计划。对于这类情况,可以利用prepared语句来避免重复解析SQL的开销。 阅读详情

二阶段提交的 prepare 阶段,binlog 和 InnoDB 各自会有哪些动作?

本文基于 MySQL 8.0.32 源码,存储引擎为 InnoDB。

在这里插入图片描述

1. 二阶段提交

二阶段提交,顾名思义,包含两个阶段,它们是:

  • prepare 阶段。
  • commit 阶段。

我们只考虑 SQL 语句操作 InnoDB 表的场景,对于用户事务,是否使用二阶段提交,取决于是否开启了 binlog。

因为 MySQL 把 binlog 也看作一个存储引擎,开启 binlog,SQL 语句改变(插入、更新、删除)InnoDB 表的数据,这个 SQL 语句执行过程中,就涉及到两个存储引擎。

使用二阶段提交,就是为了保证两个存储引擎的数据一致性。

用户事务提交分为两种场景,如果开启了 binlog,它们都会使用二阶段提交。

场景 1:通过 BEGIN 或其它开始事务的语句,显式开始一个事务,用户手动执行 COMMIT 语句提交事务。

场景 2:没有显式开始的事务,一条 SQL 语句执行时,InnoDB 会隐式开始一个事务,SQL 语句执行完成之后,自动提交事务。

如果没有开启 binlog,SQL 语句改变表中数据,不产生 binlog,不用保证 binlog 和表中数据的一致性,用户事务也就不需要使用二阶段提交了。

InnoDB 内部事务是个特例,不管是否开启了 binlog,改变表中数据都不会产生 binlog 日志,所以内部事务不需要使用二阶段提交。

2. prepare 阶段

以下代码中,ha_prepare_low() 会调用 binlog 和 InnoDB 处理 prepare 逻辑的方法。

int MYSQL_BIN_LOG::prepare(THD *thd, bool all) {
  ...
  thd->durability_property = HA_IGNORE_DURABILITY;
  ...
  int error = ha_prepare_low(thd, all);
  ...
}

调用 ha_prepare_low() 之前,用户线程对象的 durability_property 属性值会被设置为 HA_IGNORE_DURABILITY。

这个属性和 redo 日志刷盘有关,InnoDB prepare 会用到。

2.1 binlog prepare

binlog 被看作一种存储引擎,它也有 prepare 阶段,代码如下:

// sql/binlog.cc
static int binlog_prepare(handlerton *, THD *thd, bool all) {
  DBUG_TRACE;
  if (!all) {
    thd->get_transaction()->store_commit_parent(
        mysql_bin_log.m_dependency_tracker.get_max_committed_timestamp());
  }
  return 0;
}

二阶段提交时,all = true,不会命中分支 if (!all)。也就是说,在 prepare 阶段,binlog 什么也不会干。

2.2 InnoDB prepare

二阶段提交的 prepare 阶段,InnoDB 主要做五件事。

第 1 件,把分配给事务的所有 undo 段的状态从 TRX_UNDO_ACTIVE 修改为 TRX_UNDO_PREPARED。

进入二阶段提交的事务,都至少改变过(插入、更新、删除)一个用户表的一条记录,最少会分配 1 个 undo 段,最多会分配 4 个 undo 段。

具体什么情况分配多少个 undo 段,后续关于 undo 模块的文章会有详细介绍。

不管 InnoDB 给事务分配了几个 undo 段,它们的状态都会被修改为 TRX_UNDO_PREPARED。

第 2 件,把事务 Xid 写入所有 undo 段中当前提交事务的 undo 日志组头信息。

InnoDB 给当前提交事务分配的每个 undo 段中,都会有一组 undo 日志属于这个事务,事务 Xid 就写入 undo 日志组的头信息。

对于第 1、2 件事,如果事务改变了用户普通表的数据,修改 undo 段状态、把事务 Xid 写入 undo 日志组头信息,都会产生 redo 日志。

第 3 件,把内存中的事务对象状态从 TRX_STATE_ACTIVE 修改为 TRX_STATE_PREPARED。

前面修改 undo 状态,是为了事务提交完成之前,MySQL 崩溃了,下次启动时,能够从 undo 段中恢复崩溃之前的事务状态。

这里修改事务对象状态,用于 MySQL 正常运行过程中,标识事务已经进入二阶段提交的 prepare 阶段。

第 4 件,如果当前提交事务的隔离级别是读未提交(READ-UNCOMMITTED)或读已提交(READ-COMMITTED),InnoDB 会释放事务给记录加的共享、排他 GAP 锁。

虽然读未提交、读已提交隔离级别一般都只加普通记录锁,不加 GAP 锁,但是,外键约束检查、插入记录重复值检查这两个场景下,还是会给相应的记录加 GAP 锁。

第 5 件,调用 trx_flush_logs(),处理 redo 日志刷盘的相关逻辑。

static void trx_flush_logs(trx_t *trx, lsn_t lsn) {
  ...
  switch (thd_requested_durability(trx->mysql_thd)) {
    case HA_IGNORE_DURABILITY:
      /* We set the HA_IGNORE_DURABILITY
      during prepare phase of binlog group commit
      to not flush redo log for every transaction here. 
      So that we can flush prepared records
      of transactions to redo log in a group
      right before writing them to binary log
      during flush stage of binlog group commit. */
      break;
    case HA_REGULAR_DURABILITY:
      ...
      trx_flush_log_if_needed(lsn, trx);
  }
}

从名字上看,trx_flush_logs() 的作用是把事务产生的 redo 日志刷盘。

前面介绍过,MYSQL_BIN_LOG::prepare() 调用 ha_prepare_low() 之前,就已经把当前事务所属用户线程对象的 durability_property 属性设置为 HA_IGNORE_DURABILITY 了。

从上面的代码可以看到,用户线程对象的 durability_property 属性值为 HA_IGNORE_DURABILITY,prepare 阶段并不会把 redo 日志刷盘。

3. 总结

开启 binlog 的情况下,用户事务需要使用二阶段提交来保证 binlog 和 InnoDB 表的数据一致性。

binlog prepare 什么也不会干。

InnoDB prepare 会把分配给事务的所有 undo 段的状态修改为 TRX_UNDO_PREPARED,把事务 Xid 写入 undo 日志组的头信息,把内存中事务对象的状态修改为 TRX_STATE_PREPARED。

本期问题:二阶段提交的 prepare 阶段为什么不把 redo 日志刷盘?欢迎大家留言交流。

下期预告:MySQL 核心模块揭秘 | 08 期 | 二阶段提交 (2) commit 阶段。

更多技术文章,请访问: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
MySQL进阶【十一】—— Innodb 事务的两阶段提交 两阶段提交 阅读详情

相关推荐

“我这显示转账成功了你没收到钱?“--MySQL Redo Log和binlog两阶段提交到底在防什么?

今天,我们就用一次真实转账,探索一下MySQL里的Redo Log、Binlog以及所谓的两阶段提交(2PC)--这套被无数大厂面试官反复追问、却少有人真正清楚理解的底层逻辑。Binlog 是 MySQL Server 的“操作录像”:它记录你执行了什么 SQL(或具体哪行变了),专门给从库看,也用于备份恢复。Redo Log 是 InnoDB 的“后悔药”:它先把你改的数据“记一笔账”,哪怕机器炸了,重启后也能照着日志把数据补回来。生成 Redo Log(内存)和 Binlog(内存)

gjc592的博客 868

mysql set语句_MySQL Prepared语句简介

之前的MySQL版本4.1,查询以文本格式发送到MySQL服务器。 之后,MySQL服务器使用文本协议将数据返回给客户端。MySQL必须完全解析查询,并将结果集转换为字符串,然后再将其返回给客户端。 文本协议具有严重的性能问题。为了解决这个问题,MySQL自版本4.1以来添加了一个名为prepare语句的来实现一些新功能。prepare语句利用客户端/服务器二进制协议。 它将包含占位符(?)的查询...

weixin_39755853的博客 506

MySQL分布式事务中的两阶段提交接口XAConnection

XA是X/Open组织提出的分布式事务处理标准,MySQL通过XA协议支持分布式事务的两阶段提交(2PC)。

rgbcn65848的博客 2045

mysql的预查询prepare

1、Prepare 介绍 Prepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。

陈嘉怡的专栏 5168

CCS软件仿真插件移植避坑指南:从CCS5.5到7.4的完整流程

本文详细介绍了将CCS软件仿真插件从CCS5.5迁移至CCS7.4的完整流程与避坑指南。针对TMS320F28335等C2000系列芯片,重点解析了仿真核心文件、配置数据库、连接定义及驱动文件的移植步骤,并通过两个实战Demo验证了移植后仿真环境的可用性,帮助开发者在无硬件条件下继续高效进行算法验证与调试。

defi6farmer的博客 456

不用写代码!用AIStarter 5.0.0离线包部署InfiniteTalk的完整指南(Windows/Mac/Linux全平台)

本文详细介绍了如何使用AIStarter 5.0.0离线包在Windows、Mac和Linux平台上零代码部署InfiniteTalk数字人。从环境准备、离线资源获取与验证,到全平台部署实操指南,提供了完整的本地化安装流程和优化建议,帮助用户快速实现AI项目的一键部署。

weixin_30275415的博客 272

MySQL预处理语句(PREPARE)和动态SQL

通过存储过程接收一个字符串形式的SQL条件(where后的条件),并将其直接用于SELECT语句的WHERE子句中,使用预处理语句(PREPARE)和动态SQL来实现这一功能。 通过存储过程,将处理结果返回。

六月闻君 1365

FPGA实战:AXI BRAM Controller写时序避坑指南(附Vivado配置步骤)

本文深入探讨了FPGA开发中AXI BRAM Controller的写时序实战要点与常见陷阱。文章聚焦于写地址与写数据通道的握手机制,详细解析了AWREADY、WVALID等关键信号的处理,并提供了Vivado中流水线深度、ECC等关键参数的配置步骤与优化建议,旨在帮助开发者有效规避时序问题,提升系统性能。

weixin_32306683的博客 170

通用:MySQL之BinLog与RedoLog二阶段提交机制

性能问题:两个日志的写入机制不同(RedoLog 是循环写,BinLog 是追加写),强制同时写入会导致 IO 阻塞,降低并发性能;实现复杂度:InnoDB 是第三方存储引擎(后被 MySQL 收购),与服务器层(负责 BinLog)属于不同模块,"一阶段"需要强耦合两者的写入逻辑,难以维护。二阶段提交通过"松耦合"的方式协调两个模块,既保证了一致性,又保留了各自的独立性。:通过二阶段提交保证事务一致性,RedoLog 保障本地持久性,BinLog 保障主从同步与恢复。

weixin_45149504的博客 961

STM32驱动WS2812B实现音乐频谱可视化系统

本文详细介绍了基于STM32驱动WS2812B灯带实现音乐频谱可视化系统的设计与实现。通过FFT算法实时分析音频信号,将频谱映射到炫彩灯光控制系统,结合PWM和DMA技术实现低延迟响应。系统支持多模式切换和动态亮度调节,适用于创意灯光秀和智能家居场景。

weixin_29171129的博客 301

单细胞测序避坑指南:为什么你的免疫组库数据总出问题?5‘转录组7个关键细节

本文深度解析了5'端单细胞测序技术在免疫组库研究中的应用与常见问题。文章从5'端建库的分子机制入手,重点剖析了其在捕获TCR/BCR序列上的独特优势,并系统梳理了从样本处理、文库构建到数据质控全流程中7个最易出错的细节,为研究者提供了一份实用的避坑指南,旨在帮助提升免疫组库数据的质量和可靠性。

weixin_29208327的博客 482

Redo Log两阶段提交: 断电重启时,MySQL如何保证事务不丢失?

步骤 | 操作 | 位置 | 是否刷盘 || 1 | 修改数据页 | Buffer Pool | 否(内存) || 2 | 写Undo Log | Undo Tablespace | 是 || 3 | 写Redo Log | Redo Log Buffer | 否(内存) || 4 | PREPARE | Redo Log磁盘 |是(fsync)| 5 | 写Binlog | Binlog磁盘 |是(fsync)| 6 | COMMIT标记 | Redo Log磁盘 | 随下次fsync |

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 1583

Android实战——白天黑夜模式设置

白天黑夜模式是一种动态的UI模式,根据当前时间或用户设置的偏好,在白天和黑夜之间进行切换。它通过调整应用程序的颜色、亮度和其他可视化元素来提供更加舒适和易读的用户界面。

小旭的专栏 5225

详解MySQL二阶段提交(2PC):核心原理与实战要点

MySQL 2PC的核心是协调双日志提交,解决数据一致性问题,是“一致性优先”场景下的核心机制。其本质是牺牲部分性能换取数据可靠,理解其流程和参数,能快速排查主从同步、崩溃恢复等常见问题,助力高可用MySQL架构设计。思考:高并发、允许少量数据丢失的场景,如何通过参数优化2PC性能?欢迎交流。(注:文档部分内容可能由 AI 生成)

赵树祥的博客 614

深入浅出:大型语言模型(LLM)的全面解读

在当今的数字化时代,人工智能技术已经成为各行各业的核心驱动力之一。而在人工智能的领域中,大型语言模型(LLM)作为一种引人瞩目的技术,正在以其强大的语言理解和生成能力引领着一场革命。本文旨在深入浅出地解读大型语言模型,探讨其背后的原理、技术突破、应用场景以及未来发展趋势。

fudaihb的博客 10万+

基于ART算法和SIRT算法的超声CT反演及MATLAB代码实现

在超声CT中,反演算法起着至关重要的作用,它通过从测量数据中恢复出目标物体的内部结构。本文将介绍基于ART算法(Algebraic Reconstruction Technique)和SIRT算法(Simultaneous Iterative Reconstruction Technique)的超声CT反演方法,并提供相应的MATLAB代码实现。本文介绍了基于ART算法和SIRT算法的超声CT反演方法,并提供了相应的MATLAB代码示例。基于ART算法和SIRT算法的超声CT反演及MATLAB代码实现。

2301_79326510的博客 566

什么是TCC?什么是二阶段提交?三阶段提交?

通过协调者(Coordinator)分两个阶段协调所有参与者(Participants)的事务操作,保证所有节点要么全部提交,要么全部回滚。三阶段提交(3PC)**是解决分布式事务一致性的核心协议。它们的核心目标是协调多个参与节点的事务操作,确保数据最终一致性。,并引入超时机制,降低阻塞风险。、**二阶段提交(2PC)在 2PC 的基础上增加。

大户影视的博客 1481

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Mysql Binlog 和 Redolog二阶段提交以及三大日志的区别

通过二阶段提交协同工作,共同保证数据的高可靠性和主从一致性。Redo Log 关注“数据不丢”,Binlog 关注“数据复制”。:在事务中协同工作。修改数据时,先写 Undo Log 用于回滚和 MVCC,再写 Redo Log 保证这个修改持久化。它们共同保证了事务的A(原子性)和D(持久性)。:没有直接关系。Binlog 用于 Server 层的复制和恢复,Undo Log 是 InnoDB 引擎内部用于事务控制和多版本的机制。

qq_37733625的博客 965

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

MySQL 的两阶段提交(Two-Phase Commit, 2PC)

阶段主要操作目的关键日志控制参数PrepareRedo Log 写盘 +fsync+ 标记 PREPARE确保事务修改的物理页变更持久化,为提交或回滚做准备Redo LogBinlog 写盘 +fsync(根据设置)确保事务的逻辑操作记录持久化,用于复制和恢复BinlogCommitRedo Log 标记 COMMIT (通常异步刷盘)在引擎层正式提交事务,释放资源,数据可见Redo Log (状态更新)只要 Binlog 成功写入并刷盘,该事务在引擎层一定可以成功提交。

csdn_tom_168的博客 1371

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

聊聊 MySQL 事务二阶段提交

每个事务线程中都有一个 commit_low 属性,如果 leader 线程已经把 follower 线程的事务也一起提交了,会把 follower 线程的该属性值设置为 false,follower 线程在执行收尾工作的时候,就不需要再提交自己的事务了。如果 flush 子阶段的 leader 线程加入 sync 队列之前,sync 队列是空的,那么它又会成为 sync 子阶段的 leader 线程,否则,它和它的所有 follower 线程都会成为 sync 子阶段的 follower 线程。

m0_67322837的博客 1527

数据库面试必备:MySQL事务的二阶段提交机制详解

MySQL事务的二阶段提交是指在MySQL中,为了确保redolog(重做日志)和binlog(二进制日志)之间的一致性,使用的一种机制。MySQL通过二阶段提交来保证在crashrecovery(崩溃恢复)时,不会出现数据丢失或数据不一致的情况。

qq_58299462的博客 1697

详解Mysql redo log与binlog的两阶段提交(2PC)

详解Mysql redo log与binlog的两阶段提交(2PC)

m0_66220639的博客 918

MySQL两阶段提交(2PC)深度解析:从原理到实战,一篇文章搞懂!

MySQL中的两阶段提交(Two-Phase Commit, 2PC)是一种分布式事务一致性保障机制,主要用于协调事务日志(如redo log、undo log)与二进制日志(binlog)的原子性提交,确保在主从复制、XA事务等场景下数据的一致性。本文将从核心概念、应用场景、执行流程、失败处理及注意事项等方面详细解析。

weixin_42148384的博客 1337

MySQL事务的二阶段提交机制:保障数据一致性的关键技术

在分布式数据库架构中,数据一致性是一道必须攻克的难题。本文深入剖析了MySQL事务处理的核心机制——二阶段提交(2PC),揭示它如何巧妙协调binlog和redolog两套日志系统,确保数据在任何情况下都保持一致。 您是否好奇为何MySQL必须先将redolog标记为"prepare"状态,而不是直接提交事务?又或者,系统崩溃后重启时,MySQL如何决定是提交还是回滚未完成的事务? 文章通过电商订单系统和金融交易场景的实例,展示了二阶段提交在高并发、高可靠性要求环境下的实际应用。

猫步轻移,以学求知。余于此方寸之地,如猫观鼠,细察技艺所得,思维所悟。灵思如猫之警觉,日积月累,终成智海; 2082

MySQL两阶段提交:日志刷盘、崩溃恢复与数据一致性的终极指南​

MySQL通过两阶段提交协议(Prepare→Commit)保障事务原子性,协调binlog(逻辑日志)与redolog(物理日志)的刷盘顺序,解决数据不一致风险。Prepare阶段预写redolog并强制刷盘,Commit阶段写入binlog后更新日志状态,确保崩溃恢复时通过XID校验事务完整性。单日志场景会导致主从差异或数据丢失,而参数如sync_binlog=1与innodb_flush_log_at_trx_commit=1可平衡性能与安全。

qq_21330821的博客 1005
上一篇: MySQL8.3 可以给 GTID 打标签了!
下一篇: MySQL 添加主键可以节省磁盘空间吗?
爱可生开源社区
博客等级 码龄8年 1936粉丝 1004原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值