在一个闲暇的周五下午,和旁边的同事小A 边看报表边聊天(划水)。
小A : 没事我给你出一个题怎么样?你看能不能答上来?
我: 我怎么没事,我这么多事,哪像你天天划水?!嗯, 什么题,你说吧。
小A: 就知道你没有事,那我可出了啊。
我: 随便,你这水平能难倒我,我喊你爸爸。
小A:你说一说,B+树和 B 树的区别?
我: 这个题目太简单的吧,他们两个最大的区别,B+ 树数据存储在叶子节点,B 树的节点在所有的节点上。
我又babalala说了一堆他们的各自的优点和缺点,心想估计他自己都不知道这么多。
小A :厉害厉害,你再说说下, B+数如果来了一个新节点,是怎么旋转的?
这个题一步小心就掉坑里了,很可能会联想到二叉树的旋转,好在我还算是一个老司机。
我: 你小子不老实,B+ 插入的时候不是旋转,是靠节点分裂,少来误导我。
小A : 可以啊,老哥,这都被你猜破了。
我高兴的笑了笑,你这个问题太基础,要么我给你出一个"基础题"?
小A: 来啊来啊。
看这个小A一副骄傲的表情,我心想这次一定让你知道什么是真正的技术。
我 : 在InnerDB中,如果更新 1000w+ 数据,在更新的过程中服务器宕机了,会产生什么结果?
这个时候,我身后的小B 也来了兴趣,抢着说:这么简单的问题,事务没有提交,肯定是直接回滚啊。
我:给你一个表情,你自己体会。
这个时候小 A,也陷入了沉思,我估计是和小B 的答案一致。
他们俩又私下捣鼓了一阵,最后只好举手投降。
看着他们俩茫然的表情,我满意的挖苦到:这个都是很基础的知识,你们竟然不知道?!
小A : 要么你说下答案,让我们也学习下。
心想这下让你们开开眼界,我轻轻的喝了口水,然后慢慢的说道:
想要说明这个问题,首先要理解事务的原子性是怎么保证的?
小A:是 redo log 和 undo log?
我:回答正确!
但是仅仅知道这个还不够,还要了解他们的过程。例如:我们把数据库中 A=1 改成 A=2 经历了什么?
小B: 没图你说个毛线?!
我:......
说完后,我又给他们画出了一个流程图:
小A:流程我是看懂了,可是还是有点迷糊,如果事务不提交,数据还是需要回滚啊?redolog 又能有什么关键性的作用?
我:先别急,我们还需要再深入了解下 redo log。
我继续说道:
redo log 分为两个部分:日志缓冲(redo log buffer,简称 log buffer)和日志文件(redo log file),log buffer 日志在内存中存储是易丢失; log file 是存入了磁盘,是持久化存储。
我们再从 redo log 的角度看下问题更新的流程:
所以,在事务提交前我们已经修改的数据都 "记录"了下来,即使后面有故障我们也能回滚或者继续执行。
说道这里,我渐渐觉得他们的有点明白了 ,看来是时候再让他们再深入一下。
我:咳咳,问题还没有结束,到这里才能够回答上面那个问题的一半。
小A: TM 还有??
我:当然,这都是基础知识。。
下面我们还需要聊一下 redo log 的持久化策略,因为 redo log 保证了事务的原子性,怎么能保证 redo log 持久化到磁盘呢?
Redo log 的日志写入是调用操作系统的 fsync 操作。因为 MySQL 是工作在用户空间,MySQL 的 log buffer 处于用户空间的内存中。如果要写入到磁盘上的 log file 中 ,中间还要经过操作系统内核空间的 os buffer(系统缓冲区),调用 fsync() 的作用就是将 OS buffer 中的日志刷到磁盘上的 log file 中。
听到这个他们两个有点懵,为了不让小B 说话,我赶紧找了张图:
MySQL 支持用户修改参数,来控制 log buffer 如何写入到磁盘中。这个参数有三个值,分别是 0,1,2。
上面的 3 个参数,会对数据可靠性和性能带来不同的影响。
性能 | 可靠性 | |
---|---|---|
0 | 高 | 低,MySQL崩溃会丢失 1 s数据 |
1 | 低 | 高,不会丢失数据 |
2 | 中 | 中,MySQL 崩溃不会丢失数据,系统崩溃会丢失 1s数据 |
说道这里,你们应该都明白了吧。我说道
小B: 你快赶紧说完答案下班, 小B 不耐烦的说道
我们再回到问题本身:如果更新 1000w+ 数据,在更新的过程中服务器宕机了,会产生什么结果?
首先,log buffer 的写入方式的参数默认值是 1 ,我们默认没有修改过。
其次,我们需要知道宕机的类型,服务器僵死?还是 MySQL 崩溃?
最后,确定在更新的哪一步发生了崩溃。
我们在看这几个过程, 由于采用的 log buffer 参数为 1 ,即可靠性最高的等级,所以 MySQL 崩溃和服务器僵死产生的效果是一样的。
最终,可以得到结论:
如果崩溃发生在 5 之前,则事务没有提交,只能数据回滚
如果发生在 5 之后,则在重启后,可以选择继续提交事务或者回滚
如果发生在 6 之后,事务已经提交,重启后 MySQL 根据 redo log 把数据写入内存和刷入磁盘。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。