点击下方“IT牧场”,选择“设为星标”
前言
今天来聊聊InnoDB
是如何保证redo log
与binlog
两份日志之间的逻辑一致。
两阶段提交
redo log
(重做日志)让InnoDB
存储引擎拥有了崩溃恢复能力。
binlog
(归档日志)保证了MySQL
集群架构的数据一致性。
虽然它们都属于持久化的保证,但是则重点不同。
在执行更新语句过程,会记录redo log
与binlog
两块日志,以基本的事务为单位,redo log
在事务执行过程中可以不断写入,而binlog
只有在提交事务时才写入,所以redo log
与binlog
的写入时机不一样。
![](https://i-blog.csdnimg.cn/blog_migrate/473e3932187484be47b00ac3fb4cccc0.png)
回到正题,redo log
与binlog
两份日志之间的逻辑不一致,会出现什么问题?
我们以update
语句为例,假设id=2
的记录,字段c
值是0
,把字段c
值更新成1
,SQL
语句为update T set c=1 where id=2
。
假设执行过程中写完redo log
日志后,binlog
日志写期间发生了异常,会出现什么情况呢?
![](https://i-blog.csdnimg.cn/blog_migrate/84380d503380dc2dc1cb0cc45769f258.png)
由于binlog
没写完就异常,这时候binlog
里面没有对应的修改记录。因此,之后用binlog
日志恢复数据时,就会少这一次更新,恢复出来的这一行c
值是0
,而原库因为redo log
日志恢复,这一行c
值是1
,最终数据不一致。
![](https://i-blog.csdnimg.cn/blog_migrate/b88d947a9a1d0a3193d05da8c9fc9a0d.png)
为了解决两份日志之间的逻辑一致问题,InnoDB
存储引擎使用两阶段提交方案。
原理很简单,将redo log
的写入拆成了两个步骤prepare
和commit
,这就是两阶段提交。
![](https://i-blog.csdnimg.cn/blog_migrate/950d25040e73e5576879588d2e8d2cc3.png)
使用两阶段提交后,写入binlog
时发生异常也不会有影响,因为MySQL
根据redo log
日志恢复数据时,发现redo log
还处于prepare
阶段,并且没有对应binlog
日志,就会回滚该事务。
![](https://i-blog.csdnimg.cn/blog_migrate/2b167c3c0620550246b79b8a2e0388a0.png)
再看一个场景,redo log
设置commit
阶段发生异常,那会不会回滚事务呢?
![](https://i-blog.csdnimg.cn/blog_migrate/71a77193053cfa044feb1ea7d7e06116.png)
并不会回滚事务,它会执行上图框住的逻辑,虽然redo log
是处于prepare
阶段,但是能通过事务id
找到对应的binlog
日志,所以MySQL
认为是完整的,就会提交事务恢复数据。
站在巨人的肩膀上
《MySQL实战45讲》
《从零开始带你成为MySQL实战优化高手》
《MySQL技术Innodb存储引擎》
MySQL好文推荐
关于我
阿星是一个热爱技术的 Java
程序猿,公众号「程序猿阿星」定期分享有趣有料的精品原创文章!
![](https://i-blog.csdnimg.cn/blog_migrate/84562a9d2562399b5055a3b842c76283.gif)
非常感谢各位小哥哥小姐姐们能看到这里,原创不易,文章有帮助可以关注、点个赞、分享与评论,都是支持(莫要白嫖)!
愿你我都能奔赴在各自想去的路上,我们下篇文章见。
干货分享
最近将个人学习笔记整理成册,使用PDF分享。关注我,回复如下代码,即可获得百度盘地址,无套路领取!
•001:《Java并发与高并发解决方案》学习笔记;•002:《深入JVM内核——原理、诊断与优化》学习笔记;•003:《Java面试宝典》•004:《Docker开源书》•005:《Kubernetes开源书》•006:《DDD速成(领域驱动设计速成)》•007:全部•008:加技术群讨论
加个关注不迷路
喜欢就点个"在看"呗^_^