问题:
- 什么是二阶段提交
- 为什么需要二阶段提交
- 二阶段提交流程
什么是二阶段提交?
### 假设原来id 为10 的记录age 为5
begin;
update student set age = 10 where id = 10;
commit;
复制代码
一般情况下,事务提交涉及redo log 和 binlog。
当commit 命令执行时,
- 先进入commit prepare 阶段,这个阶段事务中新生成的redo log 会被刷到磁盘,并将回滚段置为prepared状态。
- commit阶段:innodb释放锁,释放回滚段,设置redo log提交状态,binlog持久化到磁盘,然后存储引擎层提交。
为什么需要二阶段提交?
由于存在redo log 和 binlog ,而他们两是相互独立的。而事务提交必须确保两者同时有效
。不然会出现不一致的情形。
假如: redo log 有效,binlog 无对应记录
在上述例子中如果服务器从事务中回复,由于redo log 有效所以id为10的记录age仍然会是10,但是由于binlog日志没有记录,所以如果通过binlog 做主从,或者主备那么就会导致主从,主备不一致。
假如: redo log 失效,而binlog 有对应记录,
上述例子中,服务器中对应的id为10的日志age就会是修改前的5,而binlog中的日志会被传到其他从服务器,也会导致主从,主备不一致。
二阶段提交流程
时间点1 |
---|
prepare 阶段 |
时间点2 |
commit 阶段 |
时间点3 |
时间点1出现问题
这个时候redo log 和 binlog都在内存中,所以本次事务的相关操作都会消失,相对于事务回滚了,不影响数据的一致性。
时间点2出现问题
这个时候redo log已经到磁盘了。binlog没有刷到磁盘所以会消失。服务器从故障中恢复时,读取磁盘中的redo log ,但是由于对应的redo log项还是prepare状态,就要判断binlog 是否完整,如果binlog完整则提交事务,如果binlog不完整则回滚事务。
时间点3出现问题。
这个时候redo log 和 binlog都已经存磁盘,服务器从redo log恢复就好了。
binlog怎么判断完整性:
- statement 格式的 binlog,最后会有 COMMIT;
- row 格式的 binlog,最后会有一个 XID event
redolog 和binlog怎么联系起来:
它们有一个共同的数据字段,叫 XID。
崩溃恢复的时候,会按顺序扫描 redo log:如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务。