Redo log
又称为重做日志。我们知道数据库中更新数据需要访问磁盘IO并精确找到所在的行进行操作,这一过程耗时较长,对于用户来说体验很差,MySQL采用Redo log的方式对此进行了优化,将更新操作先记录在Redo log中,然后等到合适的时机再将操作刷到磁盘中去。这种优化又称为WLA:Write-Ahead Logging,核心思想在于先写日志,再写磁盘。InnoDB的Redo log大小是固定的,可以看做一个循环队列,如果写满了就需要进行擦除(写入磁盘)。如下图所示,代表一个Redo log。
为了实现日志的可持久化,Redo log 日志在写满之前需要写入到磁盘中(有同学可能有疑问,Redo log如果也写磁盘的话和直接更新数据不是一样了吗?其实不然,因为Redo log是连续存放的,所以写入磁盘的速度其实很快),其中check point
代表已经更新到磁盘中的数据文件的位置,write pos
代表现在能往Redo log中写的位置,也就是现在3,4,0块是可以写入的。通过这个写磁盘的方式,InnoDB实现了crash-safe,即使宕机也可以通过Redo log恢复到原来的状态,Redo log是InnoDB存储引擎特有的一种机制,那对于其他引擎来说,怎么实现可恢复呢?那就轮到binlog上场了。
binlog
称为归档日志,是属于Server层的日志,其与Redo log的区别主要如下:
- Redo log 是InnoDB所独有,binlog是所有引擎共用
- Redo log是物理日志,记录“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”
- Redo log循环写入,会用完空间,binlog追加写入,写一个文件再写一个文件(也就是说可以通过bin log使得数据库恢复到某一个具体的时间。
在对数据进行更新时,写磁盘的时候同时写Redo log(状态为prepare),然后再写binlog,最终再更新Redo log状态为commit,这一过程是一个两阶段提交。
总结
redo log用于保证crash-safe能力。innodb_flush_log_at_trx_commit
这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘。这个参数建议设置成1,这样可以保证MySQL异常重启之后数据不丢失。
sync_binlog
这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。这个参数也建议设置成1,这样可以保证MySQL异常重启之后binlog不丢失。
参考文献
MySQL实战45讲