MySQL日志系统
MySQL备份数据由binlog和redolog实现。binlog属于Server层,redolog属于InnoDB独有。
redolog
redolog是innoDB特有的,记录某个数据页上的修改动作,环形固定空间,有两个指针,write pos指向当前写位置,check point为刷新位置。write-check为空闲空间,check-write为需要刷盘的记录。
binlog
binlog属于Server层,记录这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”,非固定空间,追加写入。
update执行过程
- 执行器调用引擎接口找到ID=2这行。其中因为ID是主键,引擎树搜索确定这一行,如果这行所在的数据页原本就在内存中,直接返回给执行器,否则从磁盘读入内存再返回。
- 执行器获得引擎返回的行数据,对其进行修改,再调用引擎数据写入。
- 引擎将这行数据存到内存中,并将该行写入redolog,redolog中该事务处于prepare状态,告知执行器执行完成。
- 执行器生成事务对应的binlog,并把binlong写入磁盘。
- 执行器调用引擎提交事务的接口,引擎把redolog中该事务改成commit状态。
其中3.4.5被称为两阶段提交。
两阶段提交
保证两份日志之间逻辑一致,可防止恢复或者备份时数据不一致问题。
假设ID=2的行,c的值为0,不进行两阶段提交,在第二个日志还没写完期间发生了crash:
先写redo在写binlog,redo写完并提交其中状态为commit,所以恢复的时候c为1。binlog没写完其中就没有这一条更新语句,如果以binlog恢复,c的值为0,与原库不同。
先写binlog再写redo,binlog写完之后,由于redolog没写完,所以这一行的值为0,此时如果用binlog进行恢复,c的值就变为1,与原库不同。
个人想法
为何需要两份日志?
首先binlog是先出现的,属于server层,redolog是随着innodb出现的。
1. 如果没有redolog,此时的update执行流程应该是执行器通过执行引擎更新完成后再生成binlog,那么如果在binlog生成前,系统发生崩溃,就会变成数据已经记录但是binlog无数据的情况。
2. “但是binlog有着redo log无法替代的功能,binlog的主要作用是归档,redo log是循环写,写到末尾是要回到开头继续写的。
MySQL系统依赖于binlog,mysql系统高可用的基础就是依赖于binlog复制;”
innodb_flush_log_at_trx_commit设置为1,表示每次事务redo log都直接持久化到磁盘,可保证异常重启之后数据不丢失。
sync_binlog设置为1,表示每次事务的binlog都持久化到磁盘,可以保证异常重启之后binlog不丢失。