Mysql的redolog:MySQL的redo log-优快云博客(重做日志)让InnoDB
存储引擎有崩溃恢复能力。
Mysql的binlog:MySQL的binlog-优快云博客(归档日志)保证了MySQL
集群架构数据的一致性。
上一篇提到两种日志的写入顺序可能导致不一致:
redo log 先写:
如果事务已写入 Redo Log,但 Binlog 还未写入磁盘,系统崩溃后,Binlog 丢失,导致主从复制的数据不一致。假设执行update user set name = "张三" where id = 2
(name原值为李四),假如执行过程中写完redo log
日志后,在写入binlog
的时候发生了异常,那么从机拉去binlog去执行的时候就不会执行这一句SQL,值还是李四,而主机是张三。
binlog 先写:
如果事务已写入 binlog,但 redo Log 未写入,崩溃恢复后,事务数据不完整。
需要MySQL 中的两阶段提交来解决
MySQL 的两阶段提交:流程
在 MySQL 中,两阶段提交贯穿 Redo Log 和 Binlog 的写入过程,由 MySQL Server 层 和 InnoDB 存储引擎层 协同完成。
1. 准备阶段(Prepare Phase)
-
InnoDB 生成 Redo Log:
当事务准备提交时,InnoDB 会将事务的 Redo Log 写入磁盘,状态标记为prepare
,并记录事务的全局事务 ID(GTID)。此时,数据尚未对外可见,事务未正式提交。 -
通知 MySQL Server:
Redo Log 的prepare
写入完成后,InnoDB 通知 MySQL Server 层,表示事务可以写入 Binlog。
2. 提交阶段(Commit Phase)
-
MySQL Server 写入 Binlog:
MySQL Server 根据收到的通知,将事务的逻辑信息写入 Binlog,并同步到磁盘。 -
InnoDB 更新 Redo Log 状态:
在 Binlog 写入完成后,InnoDB 将 Redo Log 的状态从prepare
修改为commit
,标记事务完成。
两阶段提交如何解决数据一致性问题?
事务一致性保证:
- Redo Log 和 Binlog 的写入是分阶段的原子操作:
- 如果在 Prepare 阶段崩溃:Redo Log 尚未标记为
commit
,事务未生效。 - 如果在 Commit 阶段崩溃:Binlog 写入完成,Redo Log 在恢复时可用于重做事务。
- 如果在 Prepare 阶段崩溃:Redo Log 尚未标记为
主从复制的一致性保证:
- Binlog 是主从复制的核心,确保 Binlog 和 Redo Log 一致,可以让从库和主库保持一致的数据状态。
两阶段提交的实际表现
1. 日志写入顺序
1.Redo Log 的 prepare
必须在 Binlog 写入之前完成。
2.Binlog 写入成功后,Redo Log 的 commit
才能进行。
2. 崩溃恢复
通过检查 Redo Log 的状态(prepare
或 commit
),决定事务是否需要提交或回滚。
1.如果 Binlog 写入成功,Redo Log 的 commit
操作未完成,恢复时将完成事务提交。
2.如果 Redo Log 停留在 prepare
状态,且 Binlog 未写入,恢复时回滚事务。
总结
MySQL 的两阶段提交是为了确保 Binlog 和 Redo Log 数据的一致性,避免崩溃时主从复制或事务恢复出现数据错误。它通过分为 Prepare 阶段 和 Commit 阶段 的原子操作,严格保证事务的持久性和原子性。
这种机制是 MySQL 实现可靠事务管理的重要组成部分,也是分布式系统中常见的事务一致性方案的具体实现之一。