MySQL 事务是面试中的高频题,大厂社招、校招 90% 会被问。
在技术面试中,面试官几乎都会问到一些 MySQL 事务面试题,以考察候选人的数据库知识和应用能力。
本文总结的 22 道 MySQL 事务面试题,全部是大厂真题,50+ 张手工图解、万字详解答案。
建议收藏备用,划走就再也找不到啦。
大家好,我是爱分享的程序员宝妹儿,分享即学习。
PS.
宝妹儿已将本文更新到《MySQL 大厂高频面试题大全》PDF了,方便系统学习、面试通关。
《MySQL 大厂高频面试题大全》PDF,已收录 100+ 道 MySQL 真题,一共 78 页,近 50000 字,文末自取。
吃透它,足以应付MySQL面试。
1. 什么是数据库事务?
事务是数据库操作的一个基本单位,它由一系列的数据库操作组成,这些操作要么全部成功执行,要么全部失败回滚。
事务的目的是确保数据库操作的一致性和完整性。
例如:
张三向李四转账10元,过程是这样的:
- 张三账户余额扣除10元
- 李四账户增加10元
步骤一和步骤二是一组事务。
任何一个步骤执行失败,数据就需要回滚。张三和李四的账户余额都不能改变。
只有当两个步骤都执行成功了,这才是具有原子性的事务操作。
2. 事务带来了哪些并发问题?
在事务并发执行的情况下,可能会出现脏读、幻读、不可重复读等问题。
2.1 脏读
脏读指在一个事务中读取了另一个事务未提交的数据,这将导致读取到不一致或无效的数据。
2.2 幻读
幻读指在一个事务中多次查询同一数据时,由于其他事务插入了新的数据,导致前后查询结果不一致。
2.3 不可重复读
不可重复读指在一个事务中多次读取同一数据,但在这个过程中,其他事务修改或删除了该数据,导致前后读取结果不一致。
3. 介绍下事务的四大特性(ACID)?
MySQL 事务的 ACID 属性是指:原子性、一致性、隔离性和持久性。
一般来说,事务是必须满足这 4 个条件(ACID)。
下面对每个属性进行简要说明:
3.1 原子性(Atomicity)
原子性指一个事务中的操作要么全部执行成功,要么全部回滚失败,不存在部分执行成功的情况。
事务中的任何一步操作失败,整个事务都将回滚到初始状态。
例如:
当从一个银行账户转账到另一个账户时,要么转账成功并更新两个账户的余额,要么转账失败并保持原始状态。
3.2 一致性(Consistency)
一致性指事务将数据库从一种一致状态转换为另一种一致状态。
在事务执行期间,数据库始终保持一致的状态,不会因为部分操作的执行而导致数据不一致。
在事务开始之前和结束之后,数据库必须满足一定的约束条件。
例如:
当向数据库插入一条订单记录(商品数量、客户信息)时,要保证订单的相关数据完整且符合业务规则。
3.3 隔离性(Isolation)
隔离性是指多个并发事务之间的操作互相隔离,每个事务都好像在独立运行,不受其他事务的影响,从而避免数据的干扰和冲突。
不同的事务隔离级别,提供了不同程度的隔离性。
例如:
在高并发情况下,多个用户同时查询同一商品的库存数量,需要保证每个用户看到的库存数量是准确且独立的。
3.4 持久性(Durability)
持久性指一旦事务提交成功,其所做的数据修改将永久保存在数据库中,即使发生系统故障或重新启动,也能够恢复到提交后的状态。
例如:
当用户成功下单并支付后,订单信息和支付记录需要被持久化保存,以防止数据丢失或不可恢复。
4. 什么是事务的隔离级别?
针对事务的并发问题,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 个隔离级别都有各自的缺陷。
串行化级别适用于对数据一致性要求非常高的场景。
注意:
在并发的环境下,每个隔离级别都有其特定的行为和影响。选择隔离级别需要根据业务需求和并发访问情况来决定。同时,还要注意避免长时间的事务和锁定,以避免对系统性能造成负面影响。
5. MySQL 事务实现原理是什么?
事务的实现是基于数据库的存储引擎 InnoDB 。
不同的存储引擎对事务的支持程度不一样,MySQL 中支持事务的存储引擎有 InnoDB 和 NDB。
InnoDB 是高版本 MySQL 的默认存储引擎,我这里就以 InnoDB 的事务实现为例。
InnoDB 通过多版本并发控制(MVCC,Multiversion Concurrency Control )解决不可重复读问题,加上间隙锁(也就是并发控制)解决幻读问题。因此,InnoDB 的 RR 隔离级别实现了串行化级别的效果,并且保留了比较好的并发性能。事务的隔离性是通过锁实现的,而事务的原子性、一致性和持久性,则是通过事务日志来实现的。
简单总结,实现事务使用了如下这些技术:
- 原子性:使用 undo log ,从而达到回滚;
- 持久性:使用 redo log,从而达到故障后恢复;
- 隔离性:使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行;
- 一致性:通过回滚,以及恢复,和在并发环境下的隔离做到一致性。
6. MySQL的默认隔离级别是什么?
MySQL InnoDB 存储引擎默认支持的隔离级别是 REPEATABLE-READ(可重复读)。
我们可以通过SELECT @@tx_isolation;
命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;
这里需要注意的是:
MySQL 默认采用的 REPEATABLE_READ 隔离级别,Oracle 默认采用的 READ_COMMITTED 隔离级别。
事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是 MVVC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED(读取提交内容)。
但 InnoDB 存储引擎默认使用 REPEATABLE-READ(可重复读),也不会有任何性能损失。
InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE(可串行化) 隔离级别。
7. MySQL 的隔离级别是基于锁实现的吗?
MySQL 的隔离级别是基于锁和 MVCC 机制共同实现的。
SERIALIZABLE 隔离级别是通过锁来实现的。
除了 SERIALIZABLE 隔离级别,其他的隔离级别都是基于 MVCC 实现。
不过, SERIALIZABLE 之外的其他隔离级别可能也需要用到锁机制,例如 REPEATABLE-READ 在当前读情况下,就需要使用加锁读来保证不会出现幻读。
8. 在 MySQL 中,什么情况下会产生隐式提交?
事务除了显式提交和回滚外,还有隐式提交和回滚。
- 隐式提交:begin 后没有 commit 或 rollback ,而是又在当前事务中输入了一次 begin。
- 隐式回滚:在退出会话、连接超时,又或者关机后,MySQL 会自动回滚当前事务。
Oracle 中事务不是自动提交,而 MySQL 中事务是自动提交。
那到底要不要把 MySQL 中自动提交关闭呢?
优点:事务自动提交是有好处的,这样就不用手动一个个提交了。可以多个事务一起提交,这样会提高事务的每秒处理能力。
缺点:但在这个过程中,如果某个事务一致没有提交此时就会出现行锁等待现象,其它事务必须等这个事务提交后才可以提交,这样会影响数据库的 TPS 值。
不建议关闭 MySQL 的自动提交,这里采用默认就好了。
9. 什么是 MVCC?
MVCC ,即多版本并发控制,全拼 Version Concurrency Control 。
在 MySQL InnoDB 引擎中,MVCC 为每个事务创建多个数据版本,每个版本对应一个特定时间点的数据库状态,不同事务可以基于各自的时间点来进行读取和写入操作,而不会相互干扰。
MVCC (多版本并发控制)主要解决并发访问数据库带来的一系列问题。
它的特点如下:
- 允许多个版本同时存在,并发执行。
- 不依赖锁机制,性能高。
- 只在读已提交和可重复读的事务隔离级别下工作。
10. 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. REPEATABLE READ(可重复读)隔离级别下,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 的详细过程:
……
查看详解版:3分钟深剖Undo log 的储存机制及工作原理
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。
- 提供数据回滚(原子性)
即:事务中的所有操作要么全部成功执行,要么全部回滚。
undo log(回滚日志)的回滚操作是实现原子性的关键,它保证了事务的 ACID 特性中的原子性(Atomicity)。
- 多个行版本控制 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
。 后缀六个数字,是编号,用于区分不同的日志文件。
每个 Bin log 事件由四个部分组成:
…….
详解篇:Binlog从基础到精通,24张图吃透,MySQL调优必看
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 模式。
…….
19. MySQL 中,Bin log 如何实现主从复制?
Bin log 是实现主从复制的关键,主数据库将修改操作记录到 Bin log 中,从数据库通过解析 Bin log 实现数据的同步。
MySQL 主从复制中的主要线程
- master(Bin log dump thread)
- slave(I/O thread 、SQL thread)
- Master 的一条线程
- Slave 中的两条线程
……
详解篇:Binlog实现MySQL复制,5个关键步骤,务必掌握!
20. Bin log(归档日志)增长过快,怎么办?
当 Bin log 增长过快时,磁盘空间占用过多,就会导致磁盘空间不足或性能下降等问题,影响数据库性能和稳定性。
Bin log(归档日志)增长过快的主要原因:
- 大事务
- 频繁的 DDL 操作
- 长时间的读事务
- 错误的配置参数
Bin log(归档日志)增长过快的解决方案:
- 拆分大事务
……
21. 说说 Redo log 的工作原理?
Redo Log 的工作原理是通过记录事务的修改操作,将这些记录追加到日志文件中,确保数据的持久性和一致性。
在数据库系统发生故障时,Redo Log 可以帮助恢复数据,保障系统的可靠性。
Redo Log 的工作原理图:
……
详解篇:3分钟搞懂Redo log,MySQL持久性及一致性稳了
22. Bin log、redolog 和 undolog 有哪些区别?
在 MySQL 数据库中,Bin log、Redo log 和 Undo log 都是极为重要的日志文件。
MySQL InnoDB 引擎:
- 使用 redo log (重做日志)保证事务的持久性。
- 使用 Undo log (回滚日志)来保证事务的原子性。
- 使用 Bin log(归档日志)同步数据,保证数据一致性。
……
详解篇:MySQL的Bin log、redo log和Undo log的区别,2分钟彻底搞懂!
最后
建议收藏备用,划走就再也找不到了。
我是爱分享的程序员宝妹儿,分享即学习。
谢谢您的关注、点赞、建议,支持宝妹儿坚持前行。
PS.
本文已收录于宝妹儿精编的 2023版《MySQL 大厂高频面试题大全》PDF。
《MySQL 大厂高频面试题大全》一共 78 页,近50000 字,图文并茂,长期持续更新。
吃透它,足以应对 MySQL 面试。