
1.redo log
如果熟悉MySQL你肯定知道MySQL能过对数据进行恢复(前提是开启bin log日志),当然这要归功于bin log日志。但是你可曾听过redo log呢?
首先redo log是innodb引擎特有的,需要注意的是innodb是MySQL的一个插件。
什么是redo log呢?有啥用?实际上当我们执行一条修改语句,难道每次都要落盘吗?显然是不可能的,如果每次都需要落盘,首先数据量大的时候每次都要去对这么大的文件进行io操作,显然在效率上是不可行的。
那么redo log是怎么操作的呢?redo log首先是一个环形的文件,可以设置每个文件大小,同时是循环写入的,当对数据进行修改后会先写入到redo log,如果开启了bin log那么会再写入到bin log,最后根据实际情况来写入磁盘。这样就算MySQL异常重启了也能够保证数据不丢失,这种功能称之为crash-safe能力。
究竟什么时候写入到磁盘?
写入磁盘的实际是由MySQL决定的,例如现在不忙了。或者现在redo log要写满了。此时MySQL会主动进行触发写入到磁盘。
如下所示,write pos是当前写入的位置,而check point则是redo log落盘后对redo log进行清理后的位置。可以看出write pos和check point中间这一部分就是剩余可以写的内容。

深入理解redo log
借用丁奇的话说,redo log就像是一个古代的酒店老板,因为乡里乡亲的所以难免会有一些赊账,但是每次赊账和还账掌柜都需要去翻阅那厚厚的记账本,你想一下是不是找都不好找,同时现在客人太多了又一直催你,老板你能不能快点,我们还要付钱呢?
此时能不能来个黑板,黑板比较小很好找,忙的时候先写到黑板上,等不忙了或者黑板写不下了再把黑板上的账单和账本核算一下,同时把核算好的账单从黑板上擦除,方便后面继续用。
2.bin log
说完了redo log接下来看看bin log;bin log是MySQL的server层所持有的,也就是说是MySQL本来就有的。那bin log是干什么的呢?
bin log主要记录的是每条sql的操作,用于防止MySQL数据丢失后能够进行找回。
为什么会有两个日志?
原因是MySQL最开始自带的存储引擎是MyISAM,而MyISAM用的则是bin log但是并不具备crash-safe的能力。而后面引入的innodb则是新增了redo log来解决这个问题。所以存在两个日志。
redo log和bin log区别?
1.redo log是innodb特有的
2.bin log是MySQL的server层持有的,也就是所有存储引擎都可以使用
3.bin log记录的是归档日志也就是物理日志“在某个数据页上做了什么修改”,redo log记录的是逻辑日志,记录的是对这条数据的操作。
4.redo log是循环的,而bin log则不是
3.两阶段提交
在了解两阶段提交之前,首先先看一下一条修改SQL是怎么执行的?
1.客户端和连接器进行连接。
2.连接器获取用户权限。
3.分析器对修改语句进行语法检测。
4.优化器选择索引。
5.执行器对语句进行执行,同时先逐条比较(没有索引)找到那条数据进行修改。并写入到内存(buffer pool)最后将结果返回给客户端。
除了上面说的这些步骤实际上还有redo log和bin log的写入。
6.写入到redo log同时redo log此时为准备状态。
7.写入到bin log,写入完成后直接提交事务变为commit状态。

4.为什么需要两阶段提交
所谓的两阶段提交就是指先写入了redo log后变为就绪状态,然后写入bin log后再提交事务变为commit状态。
原因是因为如果修改数据id为2的变为3,如果先写入了redo log后此时异常重启,由于crash-safe能力会将数据变成3,但是bin log却没有记录此时如果后续数据恢复那么id为3的会变成2。
如果先写入bin log后写redo log在修改数据id为2的变成3,如果写了bin log此时并没有写入到redo log,在后续数据恢复时会将id为2的数据变成3,此时你会发现数据和原来的不一致了。
5.建议
1.开启bin log日志,同时做定期全量备份防止数据丢失后能够找回,sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。设置成 1,这样可以保证 MySQL 异常重启之后 binlog 不丢失。
2.将nnodb_flush_log_at_trx_commit这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘,保证 MySQL 异常重启之后数据不丢失。
参考文献:极客时间-丁奇《MySQL实战》