尼恩说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,很多小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试机会,遇到很多很重要的面试题:
事务ACID,底层是如何实现的?
ACID靠什么保证的?
ACID的一致性是指什么?是如何实现的?
ACID中的持久性是指什么?是如何实现的?
ACID中的隔离性是指什么?是如何实现的?
最近有小伙伴在面试阿里,又遇到了MVCC相关的面试题。小伙伴 支支吾吾的说了几句,没说清楚,面试挂了。
所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
这里,尼恩团队把MVCC/ 事务 进行了全面的梳理,穿透式的梳理,
梳理为一个PDF文档 《MVCC 学习圣经:一次穿透MYSQL MVCC 》, 并且持续迭代。
这个文档将成为大家 面试的杀手锏, 此文当最新PDF版本,可以找40岁老架构师尼恩获取。

当然,上面的面试题以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V171版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
本文作者:
- 第一作者 Moen (负责写初稿 )
- 第二作者 尼恩 (40岁老架构师, 负责提升此文的 技术高度,让大家有一种 俯视 技术的感觉)
什么是事务
事务(Transaction)是数据库管理系统执行过程中的一个逻辑单位,它由一个有限的数据库操作序列构成。
事务(Transaction)是访问和更新数据库的程序执行单元;
事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。
这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
事务的目的是确保数据的完整性和一致性,它通过一系列的操作,将数据库从一个一致性状态转换到另一个一致性状态。
首先回顾一下MySQL事务的基础知识。
MySQL逻辑架构和存储引擎

如上图所示,MySQL服务器逻辑架构从上往下可以分为三层:
(1)第一层:处理客户端连接、授权认证等。
(2)第二层:服务器层,负责查询语句的解析、优化、缓存以及内置函数的实现、存储过程等。
(3)第三层:存储引擎,负责MySQL中数据的存储和提取。
MySQL 中服务器层不管理事务,事务是由存储引擎实现的。
MySQL支持事务的存储引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛;其他存储引擎不支持事务,如MyIsam、Memory等。
如无特殊说明,后文中描述的内容都是基于InnoDB。
innodb 一个数据库事务( transaction)的执行过程
数据库事务( transaction) 是指作为一个逻辑工作单元执行的一系列数据库操作,这些操作要么全部成功,要么全部失败,是一个不可分割的工作单元。
事务是在事务开始和事务结束之间执行的一系列数据库操作。
事务的目的是确保数据库操作的一致性和完整性,同时提供对并发访问的隔离性和恢复能力。
图解:一个简化版的执行过程
下面是一个简化版的执行过程

注意:请点击图像以查看清晰的视图!
图解:一个详细版的一个数据库事务( transaction)的执行过程
下面是一个详细版的一个数据库事务( transaction)的执行过程

注意:请点击图像以查看清晰的视图!
InnoDB的一次更新事务涉及到多个组件和步骤,包括Buffer Pool、BinLog、UndoLog、RedoLog以及物理磁盘。
下面是一次完整的事务更新操作过程:
step1. 开始数据,InnoDB 收到更新请求
执行SQL,收到事务的更新请求
step2. 加载数据到缓存中(Buffer Pool)
在进行数据更新时,InnoDB首先在缓冲池(Buffer Pool)中查找待更新记录是否已经在内存中。若记录不在内存中,InnoDB会将记录从磁盘文件读取到缓冲池(Buffer Pool)中。
缓冲池是InnoDB存储引擎提供的临时存储区,用于提升数据读取和修改的速度。将数据加载到缓冲池后,后续的更新操作均在缓冲池内进行。这样可以减少磁盘I/O操作,从而提高事务处理速度。缓冲池在内存中存储数据,可以降低磁盘I/O的开销,提高数据读取和写入的速度,从而优化事务处理性能。
step3. 写入Undo Log
在更新数据之前,InnoDB会将原始数据的副本写入Undo Log(回滚日志)。
Undo Log是保证事务回滚和并发控制的关键部分,也是确保事务原子性和一致性的重要机制。Undo Log记录了事务开始前的数据状态,以便在需要回滚时进行数据恢复。通过记录撤销日志,InnoDB能够实现事务的滚动回滚,提高事务处理的灵活性。撤销日志在事务处理过程中起到了关键作用,它记录了事务的修改过程,使得事务能够在需要时回滚到之前的状态,保证数据的一致性和完整性。
step4. 更新内存数据,包括 Buffer Pool和 Redo Log Buffer
接下来,InnoDB会在缓冲池中更新数据。
这意味着,当执行update语句时,InnoDB会先更新已经读取到Buffer Pool中的数据,修改操作会直接在内存中进行,而不是立即写入磁盘。
此时,缓冲池中的数据被标记为"脏页",表示与磁盘上的数据不一致。脏页是缓冲池中已经被修改但尚未写入磁盘的数据页,它需要后续的处理才能将修改同步到磁盘,保证数据的持久性。
更新Buffer Pool和Redo Log Buffer通常是数据库系统内部的操作,这些操作可以作为事务处理的一部分。
更新Buffer Pool和Redo Log Buffer的一般步骤:
第一步:Buffer Pool更新:
缓冲池 (Buffer Pool) 是数据库系统中用于存储数据页的内存区域。当需要读取或写入数据时,数据库系统首先会检查缓冲池,如果数据页已经在缓冲池中,就可以直接进行访问,而不必去访问磁盘。
要更新Buffer Pool,首先需要确定要读取或写入的数据页。如果数据页已经在缓冲池中,可以直接进行读取或写入操作;如果数据页不在缓冲池中,则需要将其从磁盘加载到缓冲池中。
更新Buffer Pool的过程通常是由数据库系统自动管理的,但也可以通过合适的API或查询语句手动进行。
第二步:Redo Log Buffer更新:
重做日志(Redo Log)是数据库系统用于持久化事务操作的一种技术。
当事务进行数据更新时,数据库系统会首先将更新操作记录到Redo Log中,以确保即使在系统崩溃时也能够恢复到事务之前的状态。
Redo Log Buffer是一个内存区域,用于暂时存储事务更新操作的日志记录。在事务进行数据更新时,数据库系统会将更新操作记录到Redo Log Buffer中,然后定期将其写入到磁盘的Redo Log文件中。
更新Redo Log Buffer通常是在事务进行提交(Commit)时完成的。
当事务提交时,数据库系统会确保将Redo Log Buffer中的所有日志记录写入到磁盘中,以保证事务的持久性。
在更新Buffer Pool和Redo Log Buffer时,数据库系统通常会采取一些优化措施,例如异步写入、批量提交等,以提高性能和减少IO开销。同时,数据库管理员也可以通过调整参数和配置来优化Buffer Pool和Redo Log Buffer的性能。
step5 写入Redo Log 文件
为了保证事务的持久性,InnoDB在Buffer Pool中记录修改操作的同时,InnoDB会先将更新操作写入Redo Log(重做日志)。
Redo Log是一种物理日志,它记录了事务对数据库的修改操作。
通过Redo Log,即使系统发生故障,也可以通过重做日志来恢复事务修改后的状态。
这一机制保证了事务的可靠性,降低了系统故障带来的风险。
重做日志是保证数据持久性和恢复性的关键,它记录了事务的修改过程,使得事务的修改能够在故障恢复后得到恢复。
step6. 提交事务
当事务完成所有的更新操作后,事务被提交。
在提交事务时,InnoDB会将事务标记为"准备提交"状态。
此时,事务的修改操作仍然在缓冲池中,尚未写入磁盘。
事务提交是事务处理的重要环节,它标志着事务处理完毕,可以进行后续的提交操作。
在提交之前,事务的修改操作需要得到处理,保证数据的完整性和一致性。
step7. 写入BinLog
在事务提交之后,InnoDB会将事务的修改操作写入BinLog(归档日志)。
BinLog是MySQL的二进制日志,用于记录数据库的所有修改操作。
在归档日志中记录的信息包括:事务开始的时间、数据库名、表名、事务ID、SQL语句等。
它可以用于数据恢复、主从复制、数据分析和同步等场景。
归档日志在数据库中起到了关键作用,它记录了数据库的修改过程,使得数据库的修改能够在故障恢复后得到恢复。
step8. 刷新脏页到磁盘
最后,在提交过程完成后,InnoDB会将缓冲池(Buffer Pool)中的脏页刷新到物理磁盘上的数据文件中。
这个过程称为"刷脏"。
通过刷脏操作,将缓冲池中的修改操作同步到磁盘,确保数据的持久性。
然而,这个写入过程并非立即执行,而是由后台线程异步执行的,因此可能会有一定的延迟。
总而言之,MySQL会在适当的时机选择将数据写入磁盘以进行持久化。
典型的MySQL事务
典型的 MySQL 事务通常包括以下步骤:
- 开始事务:使用
START TRANSACTION或BEGIN命令来开始一个新的事务。这将确保接下来的操作将被视为一个事务单元,并且要么全部成功提交,要么全部失败回滚。 - 执行SQL操作:在事务中执行各种SQL操作,例如插入、更新或删除数据,查询等。这些操作可能会涉及一个或多个数据库表。
- 数据处理与验证:在执行SQL操作之前或之后,进行数据处理和验证。这可能包括检查约束条件、验证输入数据的有效性等。
- 提交或回滚事务:如果所有的数据库操作都成功,并且通过了数据验证步骤,那么事务可以被提交(
COMMIT)。这将导致所有的更改永久地应用到数据库中。如果在任何时候出现了错误或者违反了事务的约束条件,那么整个事务将会被回滚(ROLLBACK),所有的更新将被撤销,数据库将恢复到事务开始之前的状态。 - 结束事务:一旦事务被提交或者回滚,事务就结束了。可以使用
COMMIT或ROLLBACK命令来结束事务。此时数据库会释放任何由事务占用的资源。
以下是一个典型的MySQL事务的示例:
START TRANSACTION;
-- 执行SQL操作
INSERT INTO orders (customer_id, total_amount) VALUES (123, 100);
UPDATE customers SET points = points + 10 WHERE id = 123;
-- 数据处理与验证
IF (SELECT total_amount FROM orders WHERE id = LAST_INSERT_ID()) > 50 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
-- 提交或回滚事务
COMMIT;
在这个示例中,事务首先通过 START TRANSACTION 开始,然后执行一系列SQL操作,包括向 orders 表中插入一条新的订单记录和更新 customers 表中客户的积分。接着进行了数据处理和验证,如果订单的总金额大于50,则提交事务,否则回滚事务。最后使用 COMMIT 命令提交事务。
典型的MySQL事务是如下操作的:
START TRANSACTION;
-- 执行SQL操作
-- 提交
COMMIT;
其中start transaction标识事务开始,commit提交事务,将执行结果写入到数据库。
如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。
START TRANSACTION;
-- 执行SQL操作
-- 回滚
ROLLBACK;
当然,也可以在事务中直接使用rollback语句进行回滚。
MySQL自动提交
在 MySQL 中,默认情况下是开启了自动提交(Auto-Commit)模式的。

最低0.47元/天 解锁文章
3678

被折叠的 条评论
为什么被折叠?



