后端工程师的高阶面经
邓明
前 Shopee 高级工程师,Beego PMC
6888 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
后端工程师的高阶面经
15
15
1.0x
00:00/00:00
登录|注册

14|数据库事务:事务提交了,你的数据就一定不会丢吗?

主从节点的写入成功定义
sync_binlog 和 innodb_flush_log_at_trx_commit 的调整
分布式环境下的写入语义
定时和定量刷新数据到磁盘
中间件的写入语义
sync_binlog 参数
刷新到磁盘的时机
两阶段提交
用途
两个例外情况
redo log buffer
innodb_flush_log_at_trx_commit 参数
刷新到磁盘的时机
UPDATE 对应的 undo log
DELETE 对应的 undo log
INSERT 对应的 undo log
未提交读和已提交读的隔离性
中间件处理刷盘的方式
调整刷盘时机
写入语义
binlog
事务执行过程
undo log 和 redo log
ACID 特性
异常情况处理
sync_binlog 和 innodb_flush_log_at_trx_commit 的配置
ACID 特性
binlog
redo log
undo log
事务执行过程
ACID 特性
思考题
亮点方案
基本思路
面试准备
数据库事务

该思维导图由 AI 生成,仅供参考

你好,我是邓明。今天我们来学习数据库中非常重要的一部分——数据库事务。这节课的内容和前面 MVCC 的内容联系很紧密,你要结合在一起学习。
数据库事务在面试中占据了比较重的分量。如果你面的是非常初级的岗位,那么可能就是问问事务的 ACID 特性。不然的话,基本上都要深入 redo log 和 undo log 这种事务实现机制上去。所以这一节课我会带你深入分析 redo log 和 undo log。同时我也会告诉你,哪些知识是比较基础的,你一定要掌握;哪些知识是比较高级的,你尽量记住,面试时作为亮点来展示。
最后我会给出两个比较高级的方案,一个是侧重理论的写入语义大讨论,一个是侧重实践的调整 MySQL 参数。我们先从上一节课已经初步接触过的 undo log 开始说起。

前置知识

undo log

上一节课,我说过版本链是存放在的 undo log 里面的。那么 undo log 到底是什么呢?
undo log 是指回滚日志,用一个比喻来说,就是后悔药,它记录着事务执行过程中被修改的数据。当事务回滚的时候,InnoDB 会根据 undo log 里的数据撤销事务的更改,把数据库恢复到原来的状态。
既然 undo log 是用来回滚的,那么不同的语句对应的 undo log 形态会不一样。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了数据库事务的实现机制,着重介绍了undo log和redo log的作用和机制。undo log记录了事务执行过程中被修改的数据,用于事务回滚时恢复数据库到原始状态;而redo log则记录了数据库的更改操作,以便在数据库发生崩溃或其他问题时进行重做。文章还介绍了InnoDB引擎如何综合利用undo log和redo log来实现事务,并详细描述了事务执行过程中的重要子流程。此外,还介绍了binlog的作用和与redo log的关系,以及事务的ACID特性。对于面试准备,文章提供了基本思路和亮点方案,帮助读者准备数据库事务相关的面试问题。整体而言,本文内容涵盖了数据库事务的核心概念和实现细节,适合读者快速了解数据库事务的重要概念和实现原理。文章还提到了中间件的写入语义和在分布式环境下的写入语义,以及调整刷盘时机的技巧,为读者提供了实用的技术知识和面试准备建议。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端工程师的高阶面经》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(18)

  • 最新
  • 精选
  • sheep
    "等到事务结束之后,就把 buffer pool 的数据刷新到磁盘里面" 这里buffer pool刷盘一般是由于redo log 日志满了、Buffer Pool 空间不足或者MySQL空闲时候,才进行的刷盘吧。事务提交的其中一个操作是,由于innodb_flush_log_at_trx_commit=1,此时事务提交之后,需要将redo log进行刷盘

    作者回复: 是的,我在这个上下文里面只是想表达这里还有一个刷盘的动作。后续的内容也是讨论了刷盘的具体参数问题。

    2023-10-11归属地:广东
    3
  • Geek_be29f8
    每次提交的时候刷新到磁盘上,也就是最安全的选项,InnoDB 的默认值。 是redolog刷新到磁盘这个行为成功,事务才会返回成功吗,因此宕机也不丢失数据? 如果是异步操作,redolog没真正刷盘成功,事务返回成功了的话,看起来还是会丢失数据呀

    作者回复: 对的,所以以前就很喜欢问这种刁钻的问题,什么我提交了就一定不会丢失之类的在实践中没啥意义的问题。

    2024-01-08归属地:北京
    1
  • sheep
    "在聊到隔离性和隔离级别的时候我说到一个个人观点,即未提交读和已提交读,不能看作完全实现了隔离性,你怎么看待这两者?" 这个得从隔离级别的含义说起,"隔离其他事务的干扰,也就是不同事务之间不会相互影响",未提交隔离级别下的修改,事务之间都是可见的;读提交隔离级别下的修改,一个事务提交之后,对另外一个事务就是可见的了。因此,这两个隔离级别下,很明显不满足事务的隔离性

    作者回复: 赞!哈哈哈,这就是一个辩经问题,我也比较赞同你的观点。

    2023-10-12归属地:广东
    1
  • 文敦复
    “即便是在 SSD 上,顺序写也能比随机写速度快上一个数量级。” 这里想说的是机械硬盘HDD?

    作者回复: 是的,HDD。

    2023-10-20归属地:四川
  • 隰有荷
    老师,我看文中说到 "redo log 本身也是先写进 redo log buffer,后面再刷新到操作系统的 page cache,或者一步到位刷新到磁盘。" 请问在什么情况下可以从 redo log buffer 一步刷到位的刷到磁盘?

    作者回复: 一步到位的意思,并不是说绕过了 page cache,而是说刷新到 page cache 之后立刻又刷新到磁盘。倒是不能直接绕开 page cache。

    2023-10-16归属地:广东
  • 隰有荷
    老师,关于undo log中的最后一个图中,数据的隐藏字段ROLL_PTR的指向是不是当前数据行的undo log的信息?您图中所述的第一个是指最新的一个undo log 还是最旧的一个undo log?

    作者回复: 是指向当前行的,应该是最新的。

    2023-10-12归属地:广东
  • Geek_7b73be
    老师想问一下 之所以以 binlog 为判断标准,是因为在两阶段提交里面,两个参与方 binlog 和 redo log 中,binlog 已经提交成功了,那么 redo log 自然可以认为也提交成功了 redo log的Commit不是在binlog的后边吗 为什么binlog提交成功了就可以认为redo log也提交成功了?

    作者回复: 核心就是你得有一个标准,要么用 binlog,要么用 redolog。但是你考虑到,MySQL 的引擎,不是所有的都有 redolog,因此考虑不同引擎,并且考虑语义的话,还是只能以 binlog 为准。 binlog 标记提交了,redolog 就要利用已有的信息修复数据。

    2023-09-25归属地:上海
    2
  • 爱吃锅巴的沐泡
    磁盘中的redo log文件和真实库表数据文件idb可不是一个文件,redo log是为了故障恢复用的,里面记录的是内存页的修改物理内容,比如修改了第5号表空间中页号为100的页上偏移量20字节的位置上由3改为1 这样一句话,redolog从log Buffer中刷盘是顺序刷盘的,只是记录日志,并不会修改真实库表文件idb的。库表数据修改了是在内存Buffer pool中记录的,会有IO线程定期刷盘Buffer pool到库表idb文件中的,这个刷盘是随机IO的。

    作者回复: 是的,只有真实修改那一步是随机,毕竟你数据放哪里这是一个难以转成顺序写的事情。只是说你不修改配置的话,在提交的时候不一定触发了刷盘,那么你就相当于只是顺序写了 log,所以性能比较好。

    2023-08-24归属地:北京
  • tyro
    老师我有两个疑问: Q1:redo log可能是在事务执行过程中(也就是事务提交之前)就已经被后台线程持久化硬盘了,但可能这个事务此时还没有执行完,Mysql就崩溃了。重启恢复的时候回放redo log,是能读到这个事务前半段的redo log的,这个时候数据应该回滚吧。那Mysql是怎么判断redo log中这些日志,哪些要回滚哪些要提交呢? Q2:在两阶段提交中,是需要用XID来关联redo log和bin log的吧。这样才能在故障恢复的时候识别出redo log存在的记录在bin log中是否页存在。那这个XID是在什么时候生成的呢,又是在什么时候写入redo log和bin log中的呢。是在事务开启时就生成好了,并在两种log写入的过程中一直伴随着log到buffer、到硬盘的吗?还是在事务提交阶段才开启内部事务,并生成的XID呢?如果是后者,那又回到了Q1,redo log在事务提交之前可能已经持久化到硬盘,这个时候是没有XID的,怎么和bin log关联呢? 求老师解惑,谢谢🙏

    作者回复: 1. 看 redo log 中有没有 commit 这一条 log,严格来说应该是看和 redo log 配对的那个 bin log 里面有没有 commit 这一条,如果是 row,就会有一个 XID 的 event。 2. 这个地方我给你看一段它 binlog_recover 的原文注释: After a crash, storage engines may contain transactions that are prepared but not committed (in theory any engine, in practice InnoDB). This function uses the binary log as the source of truth to determine which of these transactions should be committed and which should be rolled back. The function collects the XIDs of all transactions that are completely written to the binary log into a hash, and passes this hash to the storage engines through the ha_recover function in the handler interface. This tells the storage engines to commit all prepared transactions that are in the set, and to roll back all prepared transactions that are not in the set.

    2023-08-23归属地:广东
  • Geek_9af983
    XID你没说呀,很重要

    作者回复: 你说的是 binlog 里面的 XID 吗?貌似不讲它也不影响理解这篇文章。

    2023-07-30归属地:北京
收起评论
显示
设置
留言
18
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部