当前位置: 首页 > news >正文

mysql 2阶段提交(一)

MySQL 的二进制日志(binlog)、重做日志(redolog)以及保证它们之间数据一致性的关键机制——两阶段提交(2PC, Two-Phase Commit)

核心概念

首先,我们必须理解这两个日志的根本区别:

特性 重做日志 (Redo Log) 二进制日志 (Binlog)
所属层 InnoDB 存储引擎层 实现的日志 MySQL Server 层 实现的日志,所有存储引擎都可以使用
日志类型 物理日志
记录的是“在某个数据页上做了什么修改”
(例如:给第xx表空间的第yy数据页的第zz偏移量写了什么数据)
逻辑日志
记录的是语句的原始逻辑(Statement)或行更改后的值(Row)
(例如:UPDATE t SET c=c+1 WHERE id=2; 或 更新前后两行的数据)
用途 崩溃恢复 (Crash Recovery)
确保事务的持久性 (Durability)。在数据库宕机重启后,将已提交但未刷盘的数据重新应用(redo)到数据页。
主从复制 (Replication) & 数据恢复 (Point-in-Time Recovery)
记录所有更改数据库数据的操作,用于将数据同步到从库,或基于时间点的数据恢复。
写入方式 循环写
空间固定,写满后回头覆盖(但覆盖前必须确保对应脏页已刷盘)。
追加写
文件不断增长,通过 max_binlog_size 控制单个文件大小,写满后切换到下一个文件。
刷盘时机 innodb_flush_log_at_trx_commit 参数控制,事务提交时可以选择如何刷盘,对数据安全性至关重要。 sync_binlog 参数控制,事务提交后可以选择如何刷盘,影响主从数据一致性。

为什么需要两阶段提交 (2PC)?

想象一下,如果只有一个日志,或者两个日志独立写入,会有什么问题?

不一致的场景:

  1. 先写 binlog,后写 redolog:

    • 假设 binlog 写完,但 redolog 还没写完,数据库崩溃了。
    • 重启后:InnoDB 发现 redolog 中这个事务不完整,会将其回滚。
    • 后果:binlog 里已经记录了这个事务,但数据库实际数据没有改变。如果用这个 binlog 去搭建从库或恢复数据,从库的数据会比主库多,造成数据不一致。
  2. 先写 redolog,后写 binlog:

    • 假设 redolog(prepare状态)写完,但 binlog 还没写完,数据库崩溃了。
    • 重启后:InnoDB 发现 redolog 是 prepare 状态,会去检查 binlog 是否完整。
    • 如果 binlog 不完整(这个事务没写进去),InnoDB 会回滚该事务。
    • 后果:redolog 中的事务被回滚了。但如果 binlog 已经写完了呢?
    • 另一种情况:redolog(prepare)和 binlog 都写完了,但在 redolog commit 前崩溃。
    • 重启后:InnoDB 发现 redolog 是 prepare 状态且 binlog 是完整的,它会自动提交该事务
    • 看起来没问题? 但如果 binlog 没写完,事务就被回滚了。数据库内部数据一致,但 binlog 缺失了这个事务。用这个 binlog 恢复的从库或数据库会缺少这个事务,造成数据不一致。

为了解决这两个日志之间的一致性问题,MySQL 引入了内部的两阶段提交协议。它的核心思想是将事务的提交过程拆分成了两个阶段,让两个日志的写入“纠缠”在一起,形成一个原子操作


两阶段提交 (2PC) 详细流程

两阶段提交将一个事务的提交过程分为 PrepareCommit 两个阶段。下图直观地展示了其工作流程与崩溃恢复逻辑:

flowchart TD A[事务执行UPDATE语句] --> B[InnoBuffer Pool中修改数据页<br>生成Redo Log并写入Log Buffer]B --> C[用户执行COMMIT] C --> Stage1[阶段一: Prepare]subgraph Stage1[阶段一: Prepare]direction LRS1[将Log Buffer中的Redo Log<br>强制刷盘(fsync)] --> S2[将Redo Log记录的事务状态<br>标记为'PREPARE'] endStage1 --> Stage2[阶段二: Commit]subgraph Stage2[阶段二: Commit]direction LRT1[写Binlog到文件] --> T2[将Binlog文件强制刷盘(fsync)<br>(依赖sync_binlog参数设置)]T2 --> T3[将Log Buffer中的Redo Log(含COMMIT标记)<br>强制刷盘(fsync)] endStage2 --> D[事务提交完成<br>返回用户成功]C --> CrashPoint1[崩溃点A<br>(Redo Log Prepare前)] CrashPoint1 --> Recovery1[重启恢复: 回滚事务]Stage1 --> CrashPoint2[崩溃点B<br>(Binlog写入前)] CrashPoint2 --> Recovery2[重启恢复: 回滚事务]T2 --> CrashPoint3[崩溃点C<br>(Redo Log Commit前)] CrashPoint3 --> Recovery3subgraph Recovery3[重启恢复: 检查Binlog]R1[根据XID查找Binlog] --> R2{Binlog是否存在且完整?}R2 -- 是 --> R3[提交事务]R2 -- 否 --> R4[回滚事务] end

结合流程图,我们来看每个阶段的具体工作:

第一阶段:Prepare(准备阶段)

  1. 用户发出 COMMIT 请求。
  2. InnoDB 开始进行两阶段提交。
  3. 写 redolog:将当前事务产生的 redolog 从 log buffer 写入磁盘(fsync 操作,取决于 innodb_flush_log_at_trx_commit 设置),并将日志记录的状态标记为 PREPARE。此时,事务还没有真正提交。

第二阶段:Commit(提交阶段)

  1. 写 binlog:将事务的二进制日志(binlog)从 binlog cache 写入到磁盘上的 binlog 文件(fsync 操作,取决于 sync_binlog 设置)。
  2. 写 redolog (commit标记):在刚才写入的 redolog 中打上一个 COMMIT 标记,表示事务正式提交。(注意:在 MySQL 5.7 及以后,为了优化性能,这一步的刷盘操作有时可以被省略,依赖于 binlog 是否已经成功持久化)。

注意:步骤 1 和 2 之间的时刻,就是流程图中的“崩溃点C”,是崩溃恢复时判断事务状态的关键。


崩溃恢复 (Crash Recovery) 过程

这是两阶段提交最精彩的部分。数据库重启时,会进入恢复模式:

  1. 扫描 redolog:数据库启动时,InnoDB 会扫描最后的 redolog 文件,收集所有处于 PREPARE 状态的事务(XID)。
  2. 对于每一个 PREPARE 状态的事务(XID
    • 情况一:Binlog 完整提交事务
      • 如果发现该事务的 XID 也存在于 binlog 中(说明在崩溃前,binlog 已经成功写入并刷盘),那么 InnoDB 会认为这个事务是有效的,应该被提交
      • 操作:重新写下一条 redolog 记录,状态为 COMMIT,然后完成事务的提交(应用修改到数据页)。
    • 情况二:Binlog 不完整回滚事务
      • 如果在该事务对应的 binlog 中找不到完整的 XID 记录(说明在崩溃前,binlog 可能没写完),那么 InnoDB 会认为这个事务是无效的,应该被回滚
      • 操作:根据 undolog 来回滚该事务在 Prepare 阶段所做的所有修改。

通过这个恢复机制,它完美地解决了上述两种不一致的场景:

  • 保证了只要 binlog 里有的,redolog 最终也一定会提交 -> 主从数据一致。
  • 保证了 binlog 里没有的,redolog 即使 prepare 了也会被回滚 -> 主从数据一致。

总结与要点

  1. 目的:两阶段提交的唯一目的是保证 binlog 和 redolog 这两个日志的逻辑一致性,从而确保:

    • 主从复制的数据一致性。
    • 崩溃恢复后,基于 binlog 的点播恢复和数据库内部数据的一致性。
  2. 角色

    • Redo Log (Prepare):表示“我准备好了,我保证我的修改能力是有效的”。
    • Binlog (Write & Fsync):表示“我记录了,这个操作可以对外发布了”。
    • Redo Log (Commit):表示“好的,基于 binlog 的记录,我正式提交”。
  3. 性能影响:两阶段提交意味着一次事务提交需要多次刷盘(fsync),这是 MySQL 写操作的主要性能瓶颈所在。优化手段就是调整 innodb_flush_log_at_trx_commitsync_binlog 参数,在性能数据安全性之间做出权衡。

简单来说,两阶段提交是 MySQL 协调 Server 层和 InnoDB 存储引擎层,使用两种不同性质的日志,最终达成数据一致性目标的精妙协议

http://www.sczhlp.com/news/49020/

相关文章:

  • 莱芜政府网官方网站招聘信息seo搜索排名优化方法
  • 精准软件seo是什么软件
  • 自助广告位网站源码seo推广经验
  • 免费简单网站软文营销的技巧有哪些
  • 无锡手机网站建设方案自己怎么开网站
  • 网站首页 模板简易的旅游网页制作
  • 哈尔滨手机网站制作seo平台怎么样
  • Xhell添加推广域名
  • Layui
  • 覆盖索引,索引合并,索引跳跃扫描,自适应哈希索引
  • 9.9.7 放置已分配的块
  • mysql三大日志 redolog undolog binlog
  • 做网站需要写代码吗新媒体营销六种方式
  • 南京市网站建设公司陕西seo推广
  • 企业网站管理系统 开源百度网盘官网下载
  • 射洪哪里可以做网站护肤品软文推广
  • 给别人生日做网站网站免费发布与推广
  • 【NCS随笔】添加SPI主机和SPI从机例程
  • 观察题
  • Codeforces 1129 / 1130 (D-E) 解题报告
  • 接单做网站的浏览器广告投放
  • 成立一间网站开发公司职业培训机构排名
  • 学平面设计的网站c盘优化大师
  • 新疆自治区建设厅官方网站网络营销软文范例500字
  • 乐清站在哪百度热搜榜小说排名
  • sns网站社区需求分析文档什么是百度指数
  • 网站建设方案书个人定制化网站建设
  • 棋牌论坛网站怎么做seo技巧分享
  • Sass
  • InnoDB Buffer Pool 以及 数据变更流程