赞
踩
MySQL是通过2PC来保证写数据一致性的,具体步骤如下。
redo-log
里面,此时 redo-log
是 prepare
状态。然后告知执行器执行完成了,可以 commit
事务。binlog
,并把 binlog
写入磁盘。redo-log
改成 commit
状态,更新完成。如果在 redolog_prepare → binlog
发生崩溃,因为事务没有提交,所以直接回滚就行,不会产生任何影响。
如果在 binlog → redolog_commit
发生崩溃,MySQL的判断逻辑如下:
redo-log
是否完整(是否处于commit状态),如果是就直接提交。redo-log
处于 prepare
状态,这时候会判断 binlog
是否完整(如果格式是statement,完整日志最后会有COMMIT
标识,如果格式是row,完整日志最后会有一个XID event
),如果完整就提交redo-log
,不完整就回滚事务。这里的其他方式指除2PC(
redolog_prepare → binlog→ redolog_commit
)外的redolog→ binlog
和binlog→ redolog
两种方式。
我们可以简单用分布式事务来理解,MySQL的执行器和执行引擎是两个系统,必须保证这两个系统写数据的一致性。
或者采用反证法,一共就3种可能性,除了redolog_prepare → binlog → redolog_commit
之外还有另外两种:
redolog_full(redolog_prepare → redolog_commit) → binlog
redolog
没写完就挂了,则一点影响都没有(redolog没成功写入意味着事务没有提交,就当这件事没发生过,redolog的写入机制决定了其一旦写入成功就不允许回滚了,如果回滚就可能会覆盖其他的事务 → 不同事务共用一块 redolog buffer
,在落盘时还会顺带提交)。redo-log
,机器挂了,binlog
日志没有写入,那么机器重启后,这台机器会通过 redo-log
恢复数据,但是因为 binlog
并没有写入,因此后续进行备份或主从复制的时候,就会丢失相关记录 → 相当于少执行了一个事务。binlog → redolog_full
binlog
,机器异常重启了,由于没有 redo-log
,这个事务是无法恢复的,但是 binlog
又有记录,那么和上面同样的道理,会产生数据不一致 → 相当于多了一个事务。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。