MySQL 事务是面试中的高频题,大厂社招、校招 90% 会问。
在面试时,面试官几乎都会问到一些 MySQL 事务面试题,以考察候选人的数据库知识和应用能力。
本文总结了22道MySQL事务面试题,全部来源大厂真题,附50+张手工图解、5万+字详解答案。
大家好,我是爱分享的程序员宝妹儿,分享即学习。
PS.
宝妹儿已将本文更新到《MySQL 大厂高频面试题大全》PDF了,方便系统学习、面试通关。
《MySQL 大厂高频面试题大全》PDF,目前已收录 100+ 道 MySQL 真题,一共 78 页,近 50000 字,文末自取。
吃透它,足以应付MySQL面试。
01
什么是数据库事务?
事务是数据库操作的一个基本单位,它由一系列的数据库操作组成,这些操作要么全部成功执行,要么全部失败回滚。
事务的目的是确保数据库操作的一致性和完整性。
例如:
张三向李四转账10元,过程是这样的:
- 张三账户余额扣除10元
- 李四账户增加10元
步骤一和步骤二是一组事务。
任何一个步骤执行失败,数据就需要回滚。张三和李四的账户余额都不能改变。
只有当两个步骤都执行成功了,这才是具有原子性的事务操作。
02
事务带来了哪些并发问题?
在事务并发执行的情况下,可能会出现脏读、幻读、不可重复读等问题。
2.1 脏读
脏读指在一个事务中读取了另一个事务未提交的数据,这将导致读取到不一致或无效的数据。
2.2 幻读
幻读指在一个事务中多次查询同一数据时,由于其他事务插入了新的数据,导致前后查询结果不一致。
2.3 不可重复读
不可重复读指在一个事务中多次读取同一数据,但在这个过程中,其他事务修改或删除了该数据,导致前后读取结果不一致。
03
介绍下事务的四大特性(ACID)?
MySQL 事务的 ACID 属性是指:原子性、一致性、隔离性和持久性。
一般来说,事务是必须满足这 4 个条件(ACID)。
3.1 原子性(Atomicity)
原子性指一个事务中的操作要么全部执行成功,要么全部回滚失败,不存在部分执行成功的情况。
事务中的任何一步操作失败,整个事务都将回滚到初始状态。
例如:当从一个银行账户转账到另一个账户时,要么转账成功并更新两个账户的余额,要么转账失败并保持原始状态。
3.2 一致性(Consistency)
一致性指事务将数据库从一种一致状态转换为另一种一致状态。
在事务执行期间,数据库始终保持一致的状态,不会因为部分操作的执行而导致数据不一致。
在事务开始之前和结束之后,数据库必须满足一定的约束条件。
例如:当向数据库插入一条订单记录(商品数量、客户信息)时,要保证订单的相关数据完整且符合业务规则。
3.3 隔离性(Isolation)
隔离性是指多个并发事务之间的操作互相隔离,每个事务都好像在独立运行,不受其他事务的影响,从而避免数据的干扰和冲突。
不同的事务隔离级别,提供了不同程度的隔离性。
例如:在高并发情况下,多个用户同时查询同一商品的库存数量,需要保证每个用户看到的库存数量是准确且独立的。
3.4 持久性(Durability)
持久性指一旦事务提交成功,其所做的数据修改将永久保存在数据库中,即使发生系统故障或重新启动,也能够恢复到提交后的状态。
例如:当用户成功下单并支付后,订单信息和支付记录需要被持久化保存,以防止数据丢失或不可恢复。
04
什么是事务的隔离级别?
针对事务的并发问题,MySQL 使用了四种事务的隔离级别,用来隔离并发运行各个事务,使得它们相互不受影响。
MySQL 事务隔离级别定义了事务之间的隔离程度、以及并发访问数据库时的行为。
MySQL 的四种事务隔离级别,隔离强度由低到高排序依次是:
- READ-UNCOMMITTED(读未提交)
- READ-COMMITTED(读已提交)
- REPEATABLE-READ(可重复读)
- SERIALIZABLE(串行化)
隔离强度越强,性能就越差。
其中,可重复读是 MySQL 的默认级别。
采用哪种隔离级别,具体需要根据系统需求权衡决定。
事务隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题。
4.1 读未提交(READ UNCOMMITTED)
- 读未提交是最低的隔离级别,允许读取尚未提交的数据变更。
- 在该隔离级别下,事务可以读取其他事务未提交的数据,可能会导致脏读,即读取到了未经验证的临时数据。
- 读未提交级别具有最高的并发性能,适用于对数据一致性要求较低的场景。
4.2 读已提交(READ COMMITTED)
- 读已提交级别是大多数数据库默认的隔离级别。
- 在该隔离级别下,事务只能读取已经提交的数据,避免了脏读问题,但是幻读或不可重复读仍有可能发生。
4.3 可重复读( REPEATABLE READ)
- 可重复读级别适用于对数据一致性要求较高的场景。
- 在该隔离级别下,事务在执行期间能够多次读取同一数据,并保持一致的结果。
- 事务期间,其他事务对数据的修改不会影响到当前事务,避免了不可重复读问题。但是,可能会出现幻读问题,即在同一个事务中多次执行同一个查询,但结果集不同。
4.4 串行化(SERIALIZABLE)
- 串行化是最高的隔离级别,也是完全服从 ACID 的隔离级别。
- 在该隔离级别下,事务按照串行的方式、依次逐个执行,确保每个事务之间互不干扰。避免了脏读、不可重复读和幻读问题,但牺牲了并发性能。
- 只有串行化的隔离级别解决了脏读、不可重复读和幻读问题这 3 个问题,其他 3 个隔离级别都有各自的缺陷。
- 串行化级别适用于对数据一致性要求非常高的场景。
注意:
在并发的环境下,每个隔离级别都有其特定的行为和影响。
选择隔离级别,需要根据业务需求和并发访问情况来决定。同时,还要注意避免长时间的事务和锁定,以避免对系统性能造成负面影响。
05
MySQL事务实现原理是什么?
事务的实现,是基于数据库的存储引擎 InnoDB 。
MySQL 中支持事务的存储引擎有两种:InnoDB 和 NDB。不同的存储引擎,对事务的支持程度不一样。
InnoDB 是高版本 MySQL 的默认存储引擎,我这里就以 InnoDB 的事务实现为例。
InnoDB 通过 MVCC 多版本并发控制,来解决不可重复读问题。
关于 MVCC ,可以看这篇:一次吃透MVCC原理,让MySQL并发性能飙升
InnoDB 通过间隙锁,即并发控制,来解决幻读问题。
InnoDB 的 RR 隔离级别实现了串行化级别的效果,并且保留了比较好的并发性能。
事务的隔离性是通过锁实现的,而事务的原子性、一致性和持久性,则是通过事务日志来实现的。
简单总结,实现事务使用了如下这些技术:
- 原子性:使用 undo log ,实现回滚;
- 持久性:使用 redo log,实现故障后恢复;
- 隔离性:使用锁、MVCC,实现读写分离、读读并行、读写并行等优化操作;
- 一致性:通过回滚、恢复,以及并发环境下的隔离,实现一致性。
06
MySQL 的默认隔离级别是什么?
MySQL InnoDB 存储引擎默认支持的隔离级别是可重复读(REPEATABLE-READ)。
通过SELECT @@tx_isolation;命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;
这里需要注意的是:
MySQL 默认采用可重复读隔离级别,Oracle 默认采用读已提交隔离级别。
MySQL 事务隔离机制的实现基于锁机制和并发调度。其中,并发调度使用的是 MVVC(多版本并发控制),通过保存修改的旧版本信息,来支持并发一致性读和回滚等特性。
因为隔离级别越低,事务请求的锁越少。所以,大部分数据库的隔离级别都是 读已提交内容。
但 InnoDB 存储引擎默认使用可重复读(REPEATABLE-READ),也不会有任何性能损失。
在分布式事务的情况下,InnoDB 存储引擎一般会用到可串行化(SERIALIZABLE) 隔离级别。
07
MySQL 隔离级别基于锁实现吗?
MySQL 的隔离级别是基于锁和 MVCC 机制共同实现的。
可串行化(SERIALIZABLE)隔离级别:是通过锁来实现的。
其他隔离级别:除了可串行化,都是基于 MVCC 实现。有时也可能会需要用到锁机制。例如, 可重复读在当前读情况下,就需要使用加锁读,来保证不会出现幻读。
08
MySQL中,什么情况会隐式提交?
事务除了显式提交和回滚外,还有隐式提交和回滚。
- 隐式提交:begin 后没有 commit 或 rollback ,而是又在当前事务中输入了一次 begin。
- 隐式回滚:在退出会话、连接超时,又或者关机后,MySQL 会自动回滚当前事务。
Oracle 中,事务不是自动提交。而 MySQL 中,事务是自动提交。
那到底要不要把 MySQL 中自动提交关闭呢?
- 事务自动提交的优点
可以多个事务一起提交,不用手动逐个提交,极大提高了事务的每秒处理能力。
- 事务自动提交的缺点
如果某个事务一致没有提交,此时就会出现行锁等待现象,其它事务必须等这个事务提交后,然后才可以提交,这样就会影响数据库的 TPS 值。
不建议关闭 MySQL 的自动提交,这里采用默认就好了。
09
什么是 MVCC ?
MVCC ,即多版本并发控制,全拼 Version Concurrency Control 。
在 MySQL InnoDB 引擎中,MVCC 为每个事务创建多个数据版本,每个版本对应一个特定时间点的数据库状态,不同事务可以基于各自的时间点来进行读取和写入操作,而不会相互干扰。
MVCC (多版本并发控制)主要解决并发访问数据库带来的一系列问题。
MVCC 的特点:
- 允许多个版本同时存在,并发执行。
- 不依赖锁机制,性能高。
- 只在读已提交和可重复读的事务隔离级别下工作。
10
MVCC 的作用是什么?
MVCC 主要解决并发访问数据库带来的一系列问题,避免同一个数据在不同事务之间的竞争,提高系统的并发性能。
例如:
- 读写之间阻塞的问题;
- 减少死锁的发生;
- 解决一致性读(快照读)的问题。
没有 MVCC 机制前:
仅读读之间的操作才能并发执行,读写,写读,写写操作都要阻塞,这样就会导致 MySQL 的并发性能极差。
采用 MVCC 机制后:
只有写写之间相互阻塞,其他三种操作都可以并行,极大提高了 MySQL 的并发性能。
11
说说 MVCC 的工作原理?
MVCC 的实现主要依赖于 InnoDB 为每行数据添加的三个隐藏字段、Undo log 、以及 ReadView。
InnoDB 存储引擎为每行数据添加的三个隐藏字段:
版本链在每次进行 update 或者 delete 操作时,会将每次的操作详细记录在 undo log 中。
每条 undo log 中,都记录了 rol_pointer 信息,通过 roll_pointer 进行关联,可以构成数据的版本链。
一个记录会被一堆事务进行修改,一个记录中就会存在很多 Undo log。
那对某个事务来说,这么多 Undo log,到底应该选择哪些 Undo log 执行回滚呢?
即,哪个版本可以被事务看到呢?
ReadView 机制 就是用来为事务做可见性判断的,它可以判断版本链中的哪个版本是当前事务可见的。
12
可重复读隔离级别下,MVCC 如何工作?
InnoDB 会根据以下条件检查每一行记录。
第一,InnoDB 只查找版本早于当前事务版本的数据行,确保了事务读取的行,要么是在开始事务之前已经存在,要么是事务自身插入或者修改过的。
第二,行的删除版本号要么未定义,要么大于当前事务版本号,确保了事务读取到的行,在事务开始之前未被删除。
INSERT:
InnoDB 为新插入的每一行保存当前系统版本号,作为行版本号。
DELETE:
InnoDB 为删除的每一行保存当前系统版本号,作为行删除标识。
UPDATE:
InnoDB 为插入的一行新纪录保存当前系统版本号,作为行版本号。同时保存当前系统版本号到原来的行,作为删除标识,保存这两个版本号,使大多数操作都不用加锁。
不足之处是:
每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作。
13
什么是 ReadView ?
ReadView (读视图)是 MVCC (多版本并发控制)中的一个重要概念,ReadView 用于控制事务读取数据的逻辑视图,确保事务在整个过程中看到一致的数据状态。
ReadView 4 个重要参数:
14
Undo log 的工作原理?
Undo Log 属于逻辑日志,记录一个变化过程。
例如:
- 执行一个 delete,Undo log 会记录一个 insert;
- 执行一个 update,Undo log 会记录一个相反的 update。
在更新数据之前,MySQL 会提前生成 Undo Log 日志,在事务提交时不会立即删除 Undo Log。
原因是之后可能还需要进行回滚操作,在执行回滚(ROLLBACK)操作时从缓存中读取数据。
Undo Log 日志的删除,是通过后台 purge 线程进行回收处理的。
下面用一张图来帮助理解,看一条 SQL 执行 update、select 的详细过程:
15
Undo log 的储存机制?
Undo Log 存储采用分段(segment)的方式管理和记录。
Undo log 的存储控制,可以通过下面这条参数实现:
show variables like '%innodb_undo%';
在 InnoDB 存储数据的文件中,包含了一种回滚段(Rollback Segment),每个回滚段中有 1024 个 Undo log segment(版本 5.5 后,可以支持 128 个 Rollback Segment)。
每个回滚段都对应一个或多个 Undo log 日志文件,用于记录事务执行前的数据快照、以及存储事务操作的详细信息,例如插入、更新或删除。
下面通过图例,来进一步理解 Undo log 的存储机制:
在 undo log 中,存放着数据更新前的记录,以及 RowID、事务ID、回滚指针的记录。
事务 ID 每次递增,如果回滚指针第一次是 insert 语句,回滚指针为 NULL,在第二次 update 之后,undo log 的回滚指针就会指向刚才的 undo log 日志。
以此类推,就形成了 undo log 的回滚链,这样就能十分便捷地查询到该条记录的历史版本了。
16
Undo log的作用?
Undo log 的两大作用分别是:提供数据回滚、多版本控制 MVCC。
16.1 提供数据回滚(原子性)
即:事务中的所有操作要么全部成功执行,要么全部回滚。
undo log(回滚日志)的回滚操作是实现原子性的关键,它保证了事务的 ACID 特性中的原子性(Atomicity)。
16.2 多个行版本控制 MVCC
undo log 还有一个作用,通过 ReadView + undo log 实现 MVCC。
详解篇:6 张图吃透Undo log,MySQL进阶必知必会!
17
说说 Bin log 的日志结构?
Bin log 日志文件包含了索引文件和具体日志文件。
- 索引文件用于跟踪日志文件,每行一个日志文件。默认情况下,索引文件名为{Host名}-bin.index。
- 日志文件是由一系列事件(Binary Log Events)组成。默认情况下,文件名为{Host名}-bin.NNNNNN。后缀六个数字,是编号,用于区分不同的日志文件。
详解篇:binlog从基础到精通,24张图全面总结,一文彻底吃透!
18
Bin log 有哪些模式,你的选型思路?
针对不同的应用场景,Bin log 推出了三种模式 Statement、Row、Mixed,以满足对数据库的需求。
Bin log 三种模式的优缺点:
- Statement: 基于 SQL 语句的模式,某些语句和函数如 UUID、LOAD DATA INFILE 等,在复制过程可能导致数据不一致、甚至出错。
- Row: 基于行的模式,记录的是行的变化,很安全。但是 Bin log 会比其他两种模式大很多,在一些大表中清除大量数据时,在 Bin log 中会生成很多条语句,可能导致从库延迟变大。
- Mixed: 混合模式,根据语句来选用是 Statement 、或 Row 模式。
Bin log 三种模式的选型思路:
- 使用 MySQL 特殊功能较少,例如存储过程、触发器、函数等,用 Statement 模式。
- 使用 MySQL 特殊功能较多,用 Mixed 模式。
- 使用 MySQL 特殊功能较多,同时希望数据最大化一致,用 Row 模式。
在实际应用场景中,请结合具体情况来合理选择。
19
Bin log 如何实现主从复制?
Bin log 是实现 MySQL 主从复制的关键,主数据库将修改操作记录到 Bin log 中,从数据库通过解析 Bin log 实现数据的同步。
MySQL 主从复制中的主要线程
- master(Bin log dump thread)
- slave(I/O thread 、SQL thread)
- Master 的一条线程
- Slave 中的两条线程
详解篇:基于Bin log实现MySQL复制,5个关键步骤务必掌握!
20
Bin log 增长过快,怎么办?
当 Bin log 增长过快时,磁盘空间占用过多,就会导致磁盘空间不足或性能下降等问题,影响数据库性能和稳定性。
Bin log(归档日志)增长过快的主要原因:
- 大事务
- 频繁的 DDL 操作
- 长时间的读事务
- 错误的配置参数
Bin log(归档日志)增长过快的解决方案:
- 拆分大事务
- 优化 DDL 操作
- 增加 binlog 的回滚点
- 定期清理和归档
- 将 Raw 模式改为 Statement 模式
21
说说 Redo log 的工作原理?
Redo Log 的工作原理是:通过记录事务的修改操作,将这些记录追加到日志文件中,确保数据的持久性和一致性。
在数据库系统发生故障时,Redo Log 可以帮助恢复数据,保障系统的可靠性。
Redo Log 的工作原理图:
详解篇:3分钟搞懂Redo log,MySQL持久性及一致性稳了
22
Binlog、Redolog、Undolog 的区别?
在 MySQL 数据库中,Bin log、Redo log 和 Undo log 都是极为重要的日志文件。
MySQL InnoDB 引擎:
- 使用 redo log (重做日志)保证事务的持久性。
- 使用 Undo log (回滚日志)来保证事务的原子性。
- 使用 Bin log(归档日志)同步数据,保证数据一致性。
详解篇:Bin log、redo log和Undo log的区别,2分钟彻底搞懂!
总结
本文总结了22道MySQL事务面试题,来源大厂真题,附50+张手工图解、万字详解答案。
MySQL 事务是面试中的高频题,大厂社招、校招 90% 会问。
建议收藏备用,谢谢您的关注、点赞、建议。
我是爱分享的程序员宝妹儿,分享即学习。
为了方便学习备面,宝妹儿已将本文归纳到《MySQL 面试题大全》 PDF,下图自取。