Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : 数据库的事务隔离级别有哪些?
【简要回答】
- Read Uncommitted : 该隔离级别下的事务可以读到其他事务未提交和已提交的操作所改变的数据。
- Read Committed : 该隔离级别下的事务可以读到其他事务已提交的修改,删除,增加操作所改变的数据。
- Repeatable Read : 这是MySQL默认的隔离级别(一般不做修改)。该隔离级别下的事务可以读到启动事务时刻数据库中的数据,并且不会被其他事务所进行的DML操作所影响。
- Seralizable : 该隔离级别隔离程度最高,事务要对某数据库中的指定表进行访问时,会先判断当前表有没有其他事务正在操作,如果有,当前事务就会一直等待,直到没有其他事务操作该表时,才能访问成功,该隔离级别下读取到的数据是其他事务修改后的数据,但是由于最后已经没有其他事务操作要访问的数据,所以不会出现返回的查询结果不一致的情况。
【详细回答】
- Read Uncommitted (读未提交):
- 这是最低的隔离级别。在该级别下,一个事务可以读取到其他事务尚未提交的数据。
- 会导致严重的并发问题——脏读 (Dirty Read) 。即如果一个事务读取了另一个事务未提交的数据,而后者最终回滚,那么前一个事务读取的数据就是无效的“脏”数据。
- 并且,由于没有进行任何锁定或版本控制,Read Uncommitted 隔离级别同样也会发生不可重复读 和 幻读问题。
- Read Committed (读已提交):
- 在该级别下,一个事务只能读取到其他事务已经提交的数据,从而解决了“脏读”问题。
- 然而,在该级别下,仍然可能出现不可重复读 (Non-repeatable Read) 问题。这是指在一个事务内,多次读取同一行数据时,可能会得到不同的结果,因为其他事务在两次读取之间修改并提交了该行数据。
- 同时,Read Committed 隔离级别也会发生幻读 (Phantom Read) 问题。
- Repeatable Read (可重复读):
- 这是 MySQL InnoDB 存储引擎的默认隔离级别。
- 在该级别下,一个事务在整个执行过程中,多次读取同一行数据时,结果始终保持一致。这主要通过 MVCC (多版本并发控制) 机制来实现,事务在开始时会创建一个数据快照,后续的读取操作都基于这个快照。这有效地解决了不可重复读问题。
- 根据 SQL 标准,Repeatable Read 隔离级别是允许幻读的。然而,MySQL 的 InnoDB 存储引擎通过 Next-Key Lock(行锁和间隙锁的组合)机制,在 Repeatable Read 级别下,在一定程度上避免了幻读问题。 当执行范围查询时,InnoDB 会对查询范围内的记录及其之间的间隙加锁,阻止其他事务在该范围内插入新的记录。
- 因此,在 MySQL 中,Repeatable Read 隔离级别基本上可以避免脏读、不可重复读和幻读。
- Serializable (串行化):
- 它是最高的隔离级别。在该级别下,事务是完全隔离的,就像它们串行执行一样。
- Serializable 隔离级别通过对所有读写操作加锁来实现。当一个事务访问某个数据时,会对该数据加锁,阻止其他事务同时访问。
- 在该隔离级别下,不会出现脏读、不可重复读和幻读问题。
- 然而,由于需要进行严格的锁定,Serializable 隔离级别会显著降低数据库的并发性能,因此在实际应用中很少使用,除非对数据一致性有极高的要求。
【知识拓展】
-
MySQL四种隔离级别的分类,如下表所示:
-
脏读(Dirty Read) 示意图如下:
-
面试官可能的追问1: “你能简要解释一下脏读、不可重复读和幻读这三种并发问题吗?”
- 简答:
① 脏读是指一个事务读取到另一个事务未提交的数据;
② 不可重复读是指在一个事务内,多次读取同一行数据,结果不一致(由于其他事务的修改或删除);
③ 幻读是指在一个事务内,多次执行同一个查询,返回的行数不一致(由于其他事务的插入或删除)。
- 简答:
-
面试官可能的追问2: “MySQL 的 Repeatable Read 隔离级别是如何在一定程度上避免幻读的?”
- 简答: MySQL 的 InnoDB 存储引擎在 Repeatable Read 级别下,通过 Next-Key Lock 机制来解决幻读。Next-Key Lock 是行锁和间隙锁的组合,它不仅锁定查询到的记录,还会锁定记录之间的间隙,从而阻止其他事务在这些间隙中插入新的记录,避免了幻读的发生。
-
面试官可能的追问3: “你提到了 MVCC,它在 Repeatable Read 级别下有什么作用?”
- 简答: MVCC (多版本并发控制) 是 InnoDB 在 Repeatable Read 级别下实现可重复读的关键机制。它通过保存数据的多个版本,使得事务在读取数据时可以读取到事务开始时的版本,从而保证了在事务执行期间多次读取同一行数据时结果的一致性,解决了不可重复读问题。