背景介绍

redo log 和 binlog都是记录数据库操作内容的,只是形式不同,redo log 是 引擎层 记物理操作,改了哪个表,偏移量,也就意味着只能本数据库使用。而 binlog 在 sever 层存的是 sql 语句,可以迁移给其他数据库使用,允许不同版本,只要能处理 sql 语句的就行。两个日志都可以保证数据库的内容正常,但显然 redolog 同步只能给自己,而 binlog 更偏向记录到底哪个表改了啥,也就可以发给从库同步使用。

这两个日志的不同也就引出了同步问题,假设, redo log 刷盘了, binlog 宕机丢了; redo 断电了, binlog 刷盘了,到底以谁为准。所以提出了两阶段提交。

两阶段提交

  1. redolog 打 prepare 标记事务XID 刷盘
  2. binlog 打 commit 标记事务XID 刷盘
  3. redolog 打 commit 标记(实际上是弱实现,写在 page cache 上,不用刷盘)

规定了 redo 先 binlog 后的原则。宕机重启后也就拿 redo prepare 标记和 binlog`的 commit 标记比较,一样说明刷盘成功,事务实际上完成。如果 binlog 的 commit 找不到,说明同步失败, redolog 也得回滚。
最后将 redolog 设置为 commit 是一种优化手段,当宕机时, mySQL 去检查 prepare 阶段的 redo 就行了,不用急头白脸的全部对比,打成 commit 也就意味着事务已经完美同步。

为什么 先 redo 再 binlog

  1. binlog 一般用于主从复制,如果 binlog 刷成功了,从库也刷成功了, redo 宕机了,那主库没数据,从库有数据。
  2. binlog 记录的是事务结束后的执行记录,而 redo 在 innoDB 记得是操作, redo 需要和 undolog 一起受到版本控制进行更具体的操作,如果 binlog 已经刷盘, redo 未刷盘,需要回滚。但 binlog 显然不在 innoDB 体系中,也就无法去执行什么回滚。

组优化

一个个来太慢了,理所当然的引入了组来优化IO效率
flush 阶段:两件事,组合更多 binlog ,写入 binlog 的文件 cache 中;完成 redo 的 prepare 组提交也就是刷盘所有 redo 。
sync 阶段: binlog 组合可以和其他事务的 binlog 组合进一步组合在一起刷盘,进一步优化IO
commit 阶段:回调 redo 设为 commit 。

总结

redo 是保证数据库自己数据一致性的方案。而binlog是一种高级功能,负责生产出可复用的sql语句,表明刚刚我干了啥,可以用于全量 / 增量备份恢复,或者主从复制。这一点从 binlog 功能是可开关的也可以看出来。