美团面试:事务提交了,数据丢失 了 ?大概的原因是什么?

本文 的 原文 地址

本文 的 原文 地址

尼恩说在前面:

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、shopee、百度、网易的面试资格,遇到很多很重要的面试题:

  • MySQL崩溃,重启后发现有些已经提交的事务对数据的修改丢失了? 你分析一下 是什么原因。

  • 什么情况导致了“事务已经提交,数据却丢失”呢?

前几天 小伙伴面试 美团,遇到了这个问题。但是由于 没有回答好,导致面试挂了。

小伙伴面试完了之后,来求助尼恩。那么,遇到 这个问题,该如何才能回答得很漂亮,才能 让面试官刮目相看、口水直流。

所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典》V145版本PDF集群,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,后台回复:领电子书

原始的 面试问题

下面是小伙伴面试遇到的问题:

MySQL崩溃,重启后发现有些已经提交的事务对数据的修改丢失了,不是说事务能保证ACID一致性么,什么情况导致了“事务已经提交,数据却丢失”呢?

事务提交,数据为什么会丢失?

大家知道, 在 mysql 三大日志中,通过 redo log 保证ACID了 持久性。

MySQL三大日志 详细内容,参考 尼恩团队的文章: 美团面试:binlog、redolog、undo log底层原理是啥?分别实现ACID哪个特性?(尼恩图解,史上最全)

mysql崩溃恢复时,使用的是redo log 恢复 。

但是redo log日志有一个内存优化机制,根据参数,可能每隔1S从 log buffer 写入 os cache,然后刷盘,

这时如果崩溃,redo log日志在缓存中,有可能丢失1S的数据。

为什么要有redo log ?

事务提交后,必须将事务对数据页的修改刷(fsync)到磁盘上,才能保证事务的ACID特性。

这个刷盘,是一个随机写,随机写性能较低,如果每次事务提交都刷盘,会极大影响数据库的性能。

随机写性能差,有什么优化方法呢?

架构设计中有两个常见的优化方法:

  • 先写日志(Write-Ahead Logging 预写日志),将随机写优化为顺序写;
  • 将每次写优化为批量写;

这两个优化,mysql都用上了。

先说第一个优化,将对数据的修改先顺序写到日志里,这个日志就是redo log。

假如某一时刻,数据库崩溃,还没来得及将数据页刷盘,数据库重启时,会重做redo log里的内容,以保证已提交事务对数据的影响被刷到磁盘上。

一句话,redo log是为了保证已提交事务的ACID的一致性,同时能够提高数据库性能的技术。

既然redo log能保证事务的ACID的一致性,那为什么还会出现,“事务提交了,数据库崩溃,丢数据”的问题呢?继续看redo log刷盘实现细节。

redo log是怎么刷盘的?

image-20250523205949515

通过上面的示意图,简单说明下redo log的三层架构:

(1) 粉色,是InnoDB的一项很重要的内存结构(In-Memory Structure),日志缓冲区(Log Buffer),这一层,是MySQL应用程序用户态;
(2) 黄色,是操作系统的缓冲区(OS cache),这一层,是OS内核态;
(3) 蓝色,是落盘的日志文件;

redo log最终落盘的步骤如何?

**第一步:**事务提交的时候,会写入Log Buffer,这里调用的是MySQL自己的函数WriteRedoLog;

**第二步:**只有当MySQL发起系统调用写文件write时,Log Buffer里的数据,才会写到OS cache。

注意,MySQL系统调用完write之后,就认为文件已经写完,如果不flush,什么时候落盘,是操作系统决定的;

比如:有时候打日志,明明printf了,tail -f却看不到,就是这个原因,操作系统还没有刷盘。

**第三歩:**由操作系统(当然,MySQL也可以主动flush)将OS cache里的数据,最终fsync到磁盘上;

思考下面问题?

(1)操作系统为什么要缓冲数据到OS cache里,而不直接刷盘呢?

这里就是将“每次写”优化为“批量写”,以提高操作系统性能。

(2)数据库为什么要缓冲数据到Log Buffer里,而不是直接write呢?

这也是“每次写”优化为“批量写”思路的体现,以提高数据库性能。

这个优化思路,非常常见,高并发的MQ落盘,高并发的业务数据落盘,都可以使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值