二阶段提交

redolog (prepare) → 写binlog → 设置redolog为提交状态(commit)
binlog 主要用来主从同步,事务最终提交前写入的
redolog,是innodb特有的,记录的是物理日志,记录的是 “ 在某个数据页上做了什么修改 ”。 事务执行过程中 会不断的写入

更新时,先改内存中的数据页,将更新操作写入redo log日志,此时redo log进入prepare状态,然后通知MySQL Server执行完了,随时可以提交,MySQL Server将更新的SQL写入bin log,然后调用innodb接口将redo log设置为提交状态,更新完成。

为什么需要2种日志?只要binlog可以吗?

  1. 只要binlog, 因为前期binlog设计的时候,binlog主要是用来做归档。不具有crash safe 的作用。需要有redolog
  2. redolog是循环写的,不持久保存,binlog的“归档”这个功能,redolog是不具备的

反证法,为什么需要二阶段提交


如果只是写了bin log就提交,那么忽然发生故障,主节点可以根据redo log恢复数据到最新,但是主从同步时会丢掉这部分更新的数据。
先写redo log后写bin log, redo log写完时,准备写bin log发送故障,导致redo log 和bin log日志记录的数据不一致(先写 bin log后写redo log 同理)。中间加入个预提交阶段,就可以保证一致性。如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致

MySQL崩溃后,事务恢复时的判断规则是怎么样的?(以redolog是否commit或者binlog是否完整来确定)

  1. 如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交;
  2. 如果 redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整:
    1. a. 如果是,则提交事务;
    2. b. 否则,回滚事务

MySQL崩溃后,事务恢复时的判断规则是怎么样的?(以redolog是否commit或者binlog是否完整来确定)

redo log状态 | binlog是否完整 | 事务是否提交

redo log prepare | bin log 不完整 | 回滚事务

redo log prepare | bin log 完整 | 事务提交

redo log commit | bin log 完整 | 提交事务

QA

  1. 怎么知道binlog的完整性?binlog的结构里,有个commited标识。

参考

[玩转MySQL之八]MySQL日志分类及简介 - 知乎
讲讲一条MySQL更新语句是怎么执行的? - 掘金