这篇文档描述 MySQL 在处理一条修改数据的请求时,写入 redo log 及 binlog 的时序,以及如何达成 crash-safe。
分布式领域有 two-phase commit(2PC,二阶段提交),是一种为了保持多节点一致性的算法。MySQL 在它的内部实现中也大量借鉴了这种想法。以 InnoDB 为例,在 MySQL 收到一条 COMMIT
请求后,会有下列的过程发生:
- MySQL 要求存储引擎准备好(prepare)
InnoDB 调用
innobase_xa_prepare
,此时会将该事务写入 redo log 并保证它刷入了磁盘。此时这批 redo 会被标记为 prepared。如果此时 MySQL crash 了,即写 redo log 的过程中断了,此时 MySQL 重启后并不会继续提交,而是回到未提交前的状态。
- 存储引擎准备好后,MySQL 写 binlog
写 binlog 过程如果 crash 了,则 MySQL 重启时再从 redo log 中拿出相应的纪录再重新应用,重启写 binlog 即可。
- 写完 binlog 后,MySQL 要求存储引擎也提交相应的改动
如果写完 binlog 后就 crash 了,MySQL 仍然能从 binlog 中知道存储引擎应该提交哪些纪录。
InnoDB 在此时会将相应的数据落盘,并将相应的 redo log 标记为 committed。
References
- Fun MySQL fact of the day: everything is two-phase(网页,本地存档)
- 日志系统:一条SQL更新语句是如何执行的? - MySQL 实战 45 讲