MySQL 两阶段提交的不同瞬间,MySQL 发生异常重启,是怎么保证数据完整性的
时刻A:binlog没写,不会传到备库里,redolog未提交,崩溃恢复的时候事务就会回滚
时刻B:如果redo log 已经由commit标识,直接提交。如果只有完整的prepare,则判断binlog。
binlog完整则提交,否则回滚事务
1 MySQL 怎么知道binlog是完整的
statement格式的最后会有COMMIT,row格式的最后会有一个XID event,5.6之后可以用checksum的结果来看
2 redo log 和 binlog是怎么关联起来的
它们有一个共同的数据字段,叫XID。崩溃恢复的时候,会按顺序扫描redo log;
如果碰到既有prepare 、又有commit的redo log,就直接提交
如果碰到只有prepare,没有commit的redo log,就拿着XID去binlog找对应的事务
3 处理prepare的redo log 加上完整的binlog,重启就能恢复,MySQL为什么要这样设计
binlog已经传递到从库,为了保证主备一致,就需要主库上也提交这个事务
4 为什么要两阶段提交
事务的持久性问题:redo log 提交之后就不允许回滚,回滚会覆盖其他事务,而redo log直接提交,然后binlog写入的时候失败,InnoDB又回滚不了,数据和binlog日志又不一致了,两阶段提交就是给所有人一个机会,当每个人说我OK的时候,再一起提交
5 只用binlog 来支持崩溃恢复,可行吗
不可行,现在binlog的能力,还不够支持崩溃恢复
如果发生了crash,那么事务1也可能会丢失
6 那能不能反过来,只用redo log,不要binlog
如果只是崩溃恢复的话可以,但是归档还是要用binlog的
7 正常运行中的实例,数据写入后的最终落盘,是从redo log更新过来的,还是从buffer pool更新过来的呢?
redo log 并没有纪录数据页的完整数据,所以没有能力去更新磁盘数据页,
1 数据页被修改,跟磁盘数据不一致,称为脏页,数据落盘是通过内存中的数据页写盘。
2 崩溃恢复中,InnoDB 判断一个数据页可能在崩溃恢复的时候丢失了更新,就会将它读到内存,然后让redo log更新内存内容,更新完成后,就会到了第一种状态
8 redo log buffer是什么?是先修改内存还是先写redo log文件
没commit的时候写入 buffer中,commit的时候会 写入redo log