在数据库事务中,**隔离级别(Isolation Level)**定义了多个并发执行的事务之间互相影响的程度。它是 ACID 特性中“隔离性(Isolation)”的具体实现,用于平衡数据的一致性(准确性)和数据库的并发性能。
简而言之,隔离级别决定了一个事务在执行过程中,可以看到其他并发事务的数据修改到何种程度。隔离级别越高,事务之间互相影响越小,数据一致性越强,但并发性能可能越低;隔离级别越低,并发性能越高,但可能出现更多的数据不一致性问题(如脏读、不可重复读、幻读)。
SQL 标准定义了四种隔离级别,它们从低到高(即从宽松到严格)依次是:
1. 读未提交(READ UNCOMMITTED)
隔离性最低。
允许脏读(Dirty Read): 一个事务可以读取到其他并发事务尚未提交的数据。如果这些未提交的数据最终被回滚,那么读取到的数据就是“脏数据”。
允许不可重复读(Non-repeatable Read): 同一个事务中,两次读取同一行数据,结果可能不同,因为另一个已提交事务修改了该行。
允许幻读(Phantom Read): 同一个事务中,两次执行相同的查询,第二次查询发现新增了符合条件的行,因为另一个已提交事务插入了新行。
并发性最高。
用途: 极少用于生产环境,除非在对数据一致性要求极低、但对读取速度要求极高的特定报告场景中(例如,粗略的统计数据)。
2. 读已提交(READ COMMITTED)
这是大多数数据库(如 SQL Server、Oracle、PostgreSQL)的默认隔离级别。
避免了脏读: 一个事务只能读取到其他事务已经提交的数据。当一个事务修改数据时,它通常会对所修改的数据加锁,直到事务提交或回滚,其他事务无法读取这些未提交的数据。
允许不可重复读: 同一个事务中,两次读取同一行 全球数据库中的海外华人 数据,结果可能不同。因为在第一次读取之后,第二个事务可能提交了对该行的修改。
允许幻读: 同一个事务中,两次执行相同的查询,第二次查询发现新增了符合条件的行。
并发性相对较高。
用途: 适用于大多数常规 OLTP(在线事务处理)应用,在数据一致性和并发性能之间取得了良好的平衡。
3. 可重复读(REPEATABLE READ)
这是 MySQL 的默认隔离级别(特指 InnoDB 存储引擎)。
避免了脏读和不可重复读: 在一个事务中,对同一数据的多次读取会得到相同的结果。数据库通常通过以下方式实现:
共享锁: 对读取的数据加共享锁(S 锁),阻止其他事务对这些数据进行修改。
MVCC(多版本并发控制): 读取数据时获取数据的快照,后续读取都基于这个快照,不受其他事务提交的影响。
可能允许幻读: 尽管避免了不可重复读,但在某些实现中,一个事务两次执行相同范围查询时,可能会发现有其他事务插入的新行(这就是幻读)。
注意: MySQL 的 InnoDB 引擎在 REPEATABLE READ 级别下,通过**间隙锁(Gap Lock)**和 Next-Key 锁(行锁+间隙锁)来避免幻读问题。
并发性中等。
用途: 适用于那些需要在一个事务内多次读取同一数据并期望得到一致结果的场景,例如报表生成或复杂计算。
4. 串行化(SERIALIZABLE)
隔离性最高。
避免了脏读、不可重复读和幻读: 这是最严格的隔离级别。事务之间完全隔离,就好像它们是串行(逐个)执行的一样。
实现: 通常通过对事务涉及的所有数据加锁(包括读锁和写锁,以及对查询范围的锁),以阻止任何可能导致数据不一致的并发修改。
并发性最低: 因为严格的锁机制,可能导致大量的锁等待和死锁,从而显著降低并发性能。
用途: 适用于对数据一致性要求极高、且并发冲突较少或对性能不那么敏感的场景。例如,金融系统中的核心账务处理。
隔离级别与并发问题的关系总结
隔离级别 脏读(Dirty Read) 不可重复读(Non-repeatable Read) 幻读(Phantom Read)
READ UNCOMMITTED 允许 允许 允许
READ COMMITTED 避免 允许 允许
REPEATABLE READ 避免 避免 可能允许(MySQL InnoDB避免)
SERIALIZABLE 避免 避免 避免
Export to Sheets
选择合适的隔离级别
选择事务隔离级别是一个权衡问题:
数据一致性 vs. 并发性能。
通常,READ COMMITTED 是一个好的默认选择,因为它在保证数据不提交不被读取(没有脏读)的同时,提供了相对较高的并发性。
如果应用程序对数据一致性有更高的要求(例如,在同一个事务中多次读取同一数据必须一致),则可能需要考虑 REPEATABLE READ。
SERIALIZABLE 提供最强的数据一致性,但可能会严重影响性能,应谨慎使用。
READ UNCOMMITTED 极少使用,因为数据可靠性太低。
理解并正确配置事务隔离级别,对于确保数据库应用程序的正确性和性能至关重要。