redolog
为什么需要redolog,解决什么问题
mysql作为持久化数据库,每一次写操作如果都写入磁盘,磁盘也要每次都找到对应的记录再更新,整个成本很高。为了解决这个问题,mysql设计者就使用了WAL技术。即:Write-Ahead Logging, 其关键点在于先写日志,再写磁盘。
具体案例
当有一条记录需要更新的时候,InnoDB就会把记录先写进redolog,再更新内存,这时候更新就算完成了,同时InnoDB会在适当的时候,将操作记录更新到磁盘里面。这个更新往往是在系统比较空闲的时候。
redolog长啥样
如图:
- write pos表示redolog即将写入的位置
- check point是当前需要擦除的位置
- check point与write pos之间则是redolog还空着的部分,可以用来记录新的操作。
- 有了redolog,InnoDB就能保证即使数据库发生异常重启,之前提交的记录都不会丢失,也就是crash-safe能力。
binlog
从mysql总体来看,一公分为两大模块:一块是server层,主要做的事mysql功能层面的东西,还有一块是引擎层,负责存储相关事宜,redolog属于InnoDB引擎特有的日志,而server层也有自己的日志,成为binlog(归档日志)。
为什么两份日志
因为最开始mysql并没有InnoDB引擎,Mysql自带引擎为MyISAM,但是MyISAM没有crash-safe能力,binlog只能用于归档,而InnoDB是另一家公司以插件形式引入Mysql的,既然只靠binlog无法实现crash-safe,那就只能使用另一套日志系统: redolog来实现crash-safe。
redolog与binlog有何不同
- redolog为InnoDB特有的,只有Innodb能使用,binlog为server层实现的,所有引擎都可以使用。
- redolog是物理日志,记录的是在某个数据页上做了什么修改。binlog是逻辑日志,记录的是语句的愿是逻辑,如“给id=2这一行的C字段加上1”
- redolog是循环写的,空间固定会用完;binlog是可以追加写的,“追加写”是指binlog在文件写到一定大小之后,并不会覆盖以前的日志。
更新语句是如何执行的
mysql> update T set c=c+1 where ID=2;
- 执行器先找引擎取ID=2这一行,如果ID=2这一行所在数据本来就存在内存中,就返回给执行器,否则需要先从磁盘中读入内存,然后再返回。
- 执行器拿到引擎返回的数据,把这个值加上1,得到新的一行数据,再调用引擎接口写入这行数据。
- 引擎将这行数据更新到内存中,同时将这个更新操作记录到redolog中,此时redolog处于prepare状态,然后告知执行器执行完成了,随时可以提交事物。
- 执行器生成这个操作的binlog,并把binlog写入磁盘。
- 执行器调用引擎提供的事物提交接口,引擎把刚刚写入的redolog改成提交(commit)状态,更新完成。
这个语句执行流程如下:
### 两阶段提交
可能你注意到了,redolog将写入拆分成了两个步骤:prepare 和 commit。这就是“两阶段提交”
为什么要有两阶段提交
- 先写binlog,再写redolog,这样会有什么问题?
- 先写redolog,再写binlog,又会有什么问题?
答案是,如果再两个log写入的过程中发生了crash,会导致两份日志恢复出来的数据不一致。
小结
- redolog用于保证crash-safe的能力,innodb_flush_log_at_trx_commit这个参数设置为1,表示每次事物的redolog都会持久化到磁盘,这个参数建议设置为1,保证数据库异常重启之后数据不丢失。
- sync_binlog建议你也设置为1,表示每次事物的binlog都持久化到磁盘,可以保证Mysql异常重启之后binlog不丢失。