【超详细】MySQL事务面试题
目录
1.讲一下MySQL的事务?
2.数据库事务的隔离级别有什么?
3.为什么事务会有隔离性,要设置隔开级别?
4.什么是脏读、不可重复读、幻读?
5.讲一下事务的四个隔离级别的实现原理?
6.MVCC 是什么?
7.MySQL中长事务是什么?可能会导致哪些问题?如何预防?
8.MySQL二级索引有MVCC快照吗?
9.如果MySQL中没有MVCC,会有什么影响?
10.MySQL默认的事务隔离级别是什么?为什么选择这个级别?
11.为什么MySQL的隔离级别可重复读不会导致幻读?
1.讲一下MySQL的事务?
是什么:MySQL事务是一组sql语句的组合,这些语句看成一个整体,要么全部执行成功,要么全部不执行
有什么用:简单说就保证多步数据库操作的 “原子性、一致性、隔离性、持久性”,避免数据出现错误,也避免出现并发问题
事务的特性:
1.原子性,一个事务中的语句要么全部执行,要么都不执行,在中间某个环节发送错误会进行回滚。
2,持久性:一旦一个事务处理结束,那么在这个事务中对数据的修改就是永久的,即使系统崩溃也不会丢失。
3.隔离性:隔离可以防止多个事务并发执行时可能会导致数据不一致的问题(虽然说在上层看来事务是原子的操作,但在事务执行内部是有多条语句的)。
事务分为四个隔离级别:
- 1.读未提交:所有事务都可以看见别的事务还没有提交的数据,会出现脏读,不可重复读等问题,基本上不使用。
- 2.读提交:一个事务只能看见别的已提交的事务的数据,可能会出现不可重复读问题.
- 3.可重复读:指在一个事务的执行周期中,多次读取数据会看见同样的结果。(会有幻读,看见别的事务的插入操作,但MySQL不会)
- 4.串行化:强制事务排序,使其不可能发生冲突。
4.一致性:在执行事务前以及结束事务后,数据库的完整性没有遭到破
2.数据库事务的隔离级别有什么?
读未提交(Read Uncommitted): 在该隔离级别下,所有的事务都可以看到其他事务没有提交的执行结果,实际生产中不可能使用这种隔离级别,因为这种隔离级别相当于没有任何隔离性,会存在很多并发问题,如脏读、幻读、不可重复读等。
读提交(Read Committed): 该隔离级别是大多数数据库的默认隔离级别,但它不是MySQL默认的隔离级别,它满足了隔离的简单定义:一个事务只能看到其他已经提交的事务所做的改变,但这种隔离级别存在不可重复读和幻读的问题。
可重复读(Repeatable Read): 这是MySQL默认的隔离级别,该隔离级别确保同一个事务在执行过程中,多次读取操作数据时会看到同样的数据,即解决了不可重复读的问题,但这种隔离级别下仍然存在幻读的问题。
串行化(Serializable): 这是事务的最高隔离级别,该隔离级别通过强制事务排序,使之不可能相互冲突,从而解决了幻读问题。它在每个读的数据行上面加上共享锁,但是可能会导致超时和锁竞争问题,这种隔离级别太极端,实际生成中基本不使用。
3.为什么事务会有隔离性,要设置隔开级别?
数据库为了保证事务执行过程中尽量不受干扰,于是出现了隔离性的概念,而数据库为了允许事务在执行过程中受到不同程度的干扰,于是出现了隔离级别的概念
4.什么是脏读、不可重复读、幻读?
脏读:一个事务读取到了另一个事务未提交的修改数据(该数据可能后续被回滚,属于 “临时无效数据”)。
不可重复读:同一事务内,对同一数据多次查询,结果不一致(因其他事务提交了更新 / 删除操作),针对
幻读:同一事务内,对同一范围数据多次查询,结果的行数不一致(因其他事务提交了插入操作)
5.讲一下事务的四个隔离级别的实现原理?
1.隔离级别是通过MVCC实现的,对于MVCC,我想说三个点:表的三个隐藏字段,undo_log 和 read_view
 2.表中有三个隐藏字段:最近修改该记录的事务ID,隐式主键和回滚指针
 3. undo_log本质上就是一段MySQL维护的内存缓冲区,用于对已经执行的操作进行回滚,保证事务的原子性,数据在修改前会被先记录到redo_log 中,形成历史版本链
 4. Read_view是事务在执行快照读时,生成的一个读视图,它是一个数据结构RR(可重复读)与RC(读提交)的本质区别就是,可重复读不管进行多少次快照读,使用的readview是一样的,而读提交中每一次进行快照读都会生成一份新的readview,来更新两段快照读之间已提交的事务
6.MVCC 是什么?
前面第5点回回答
7.MySQL中长事务是什么?可能会导致哪些问题?如何预防?
长事务是指长时间没有提交的事务
问题:
1.占用锁资源,引发阻塞,长事务会持续持有锁,阻塞其他事务的写入操作。严重时会导致大量事务排队等待,系统响应变慢,甚至出现死锁。
2.拖慢 MVCC 机制,占用 undo 日志,InnoDB 的 MVCC 依赖 undo 日志保存数据历史版本,长事务会阻止 undo 日志被清理。占用大量磁盘空间
3.影响数据库恢复效率,数据库崩溃后恢复时,需回滚未提交的事务,长事务会大幅延长恢复时间,导致服务不可用时长增加。
预防:
1.确保事务只包含最必要的数据库操作,尽快提交。
2.设置超时时间
3.建立对长事务的监控,一旦发现长时间运行的事务,立即触发告警
8.MySQL二级索引有MVCC快照吗?
回答:MySQL InnoDB 的二级索引没有独立的 MVCC 快照,其快照依赖主键索引的 MVCC 机制实现。二级索引的叶子节点仅存储主键值,不存储完整数据或版本信息。当通过二级索引查询时,InnoDB 会先通过二级索引找到对应的主键值,再到主键索引(聚簇索引)中获取数据及版本链。MVCC 的快照判断(是否可见)仅在主键索引中进行,二级索引本身不参与版本判断,仅提供主键定位功能
解释:
主键索引是 MVCC 版本信息的存储载体,InnoDB 的主键索引(聚簇索引)叶子节点存储完整数据行,同时每行数据会附加隐藏列:
- DB_TRX_ID:最后修改该数据的事务 ID;
- DB_ROLL_PTR:指向 undo 日志的指针(用于构建历史版本链)。这些信息是 MVCC 判断 “数据版本是否对当前事务可见” 的依据 —— 没有主键索引中存储的版本信息,MVCC 就无法定位历史版本,机制也就无法生效。
主键索引叶子节点:存储的是数据的当前最新版本,包含完整数据行 +DB_TRX_ID(最后修改的事务 ID)+DB_ROLL_PTR(指向 undo log 中 “上一个历史版本” 的指针)。
undo log:存储的是数据的历史版本,即每次修改前的旧值,以及该版本对应的DB_TRX_ID和DB_ROLL_PTR(形成版本链)
二级索引的查询流程:二级索引定位主键 → 主键索引查询数据 + 版本校验 → 返回符合快照的结果
主键索引的查询流程: 主键索引查询数据 + 版本校验 → 返回符合快照的结果
9.如果MySQL中没有MVCC,会有什么影响?
如果没有MVCC,系统必须频繁地对读写操作进行加锁来保证数据的正确性,因为增加了锁的获取和释放的开销,会导致整体系统响应速度变慢,这种实现叫LBCC (Lock-Based Concurrent Control)。
10.MySQL默认的事务隔离级别是什么?为什么选择这个级别?
默认隔离级别是可重复读(RR)。
选择原因:
- 平衡一致性与并发性能,避免脏读、不可重复读,InnoDB 还通过临键锁避免幻读;
- 无需像串行化那样牺牲并发,也不像读已提交那样存在数据一致性短板,适配多数业务。
11.为什么MySQL的隔离级别可重复读不会导致幻读?
因为 InnoDB 的Next-Key Lock(临键锁) 机制,会锁定记录及间隙,阻止其他事务插入新数据,从根源避免幻读。
