“这是我参与更文挑战的第5天,活动详情查看: 更文挑战”
前边一篇我们说了binLog是在MYSQL的server层记录的,redoLog和undoLog是在MYSQL引擎层记录的。问题是MYSQL怎么保证两个日志同时记录成功呢?
首先我们要知道如果binLog和redoLog不能同时记录成功,会有什么影响?
-
binLog记录成功redoLog记录失败,我们知道binLog其中一个功能是做数据库间的主从同步的, 如果binLog记录成功后自然就会同步到从库中,此时如果主库宕机redoLog没有记录导致数据无法持久化。(redoLog是保证MYSQL事务中持久性的)
-
binLog记录失败redoLog记录成功,将会导致主从数据不一致情况。
MYSQL为了解决以上两种情况提供了两段提交方式,两段提交分别为prepare阶段、commit阶段。
prepare阶段:
SQL执行成功后将生成事务ID(xid)写入redoLog、undoLog缓存中注意此时并没有落盘也就是说没有持久化。
commit阶段:
写binlog,调用write()将binlog内存日志数据写入文件系统缓存,再调用fsync()将binlog文件系统缓存日志数据永久写入磁盘。同时将redoLog、undoLog从缓存中刷入磁盘进行持久化。
既然是两段提交那么如果commit阶段宕机了呢?
这时候prepare阶段数据将会丢失,不会导致binLog和redoLog不一致情况。
那么如果commit阶段中binLog写入磁盘成功但是redoLog失败呢?
MYSQL再次启动的时候会将binLog中的事务ID取出来检查redoLog有没有落盘成功,如果没有会将数据进行再次落盘。
commit阶段为宕机为什么会导致redoLog数据丢失呢? 这里我们就要说一下redoLog落盘策略
mysql将redoLog buffer 写入 redoLog file 的时机,可以通过 innodb_flush_log_at_trx_commit 参数配置,各参数值含义如下: