mysql事务隔离级别有哪些
MySQL的事务隔离级别定义了多个并发事务之间如何相互影响,特别是涉及数据读取和写入时的可见性与一致性。MySQL支持四种标准的事务隔离级别(从最低隔离到最高隔离):
1. 读未提交 (READ UNCOMMITTED)
定义:事务可以读取其他尚未提交的事务修改的数据。
允许的现象:
脏读 (Dirty Read):读取到其他未提交事务修改的中间状态数据(这些数据可能被回滚,因此是“脏”的)。
不可重复读 (Non-repeatable Read):同一事务内多次读取同一数据,结果可能不同(因为其他已提交事务修改了该数据)。
幻读 (Phantom Read):同一事务内多次执行相同查询,返回的结果集行数可能不同(因为其他已提交事务插入或删除了满足查询条件的行)。
使用场景:很少使用,对数据一致性要求极低且能容忍脏读的场景。性能通常最高(因为几乎没有锁或版本控制开销)。
2. 读已提交 (READ COMMITTED)
定义:事务只能读取其他已经提交的事务修改的数据。这是Oracle等数据库的默认级别,但不是MySQL InnoDB的默认级别。
允许的现象:
不可重复读 (Non-repeatable Read):事务A第一次读取数据后,事务B修改并提交了该数据,事务A再次读取会看到修改后的值。
幻读 (Phantom Read):事务A第一次查询后,事务B插入或删除了满足查询条件的行并提交,事务A再次执行相同查询会看到不同的行集。
防止的现象:
脏读 (Dirty Read)
实现 (InnoDB):通常使用快照读(每个
SELECT
语句看到的是语句开始时已提交的最新数据版本)或锁定读(如SELECT ... FOR UPDATE
/SHARE
使用记录锁)。使用场景:需要避免脏读,但对不可重复读和幻读有一定容忍度的场景。比
REPEATABLE READ
锁竞争少一些。
3. 可重复读 (REPEATABLE READ)
定义:MySQL InnoDB存储引擎的默认隔离级别。确保在同一个事务中多次读取相同数据时,结果是一致的。
允许的现象:
幻读 (Phantom Read):理论上允许,但InnoDB通过Next-Key Locks机制在很大程度上防止了幻读的发生(这是MySQL InnoDB对标准SQL隔离级别的扩展增强)。
防止的现象:
脏读 (Dirty Read)
不可重复读 (Non-repeatable Read)
实现 (InnoDB):
快照读:事务的第一次
SELECT
操作会建立一个一致性读视图。后续在该事务内的普通SELECT
操作(快照读)都基于这个视图,看到的是事务开始时的数据快照,不受其他已提交事务影响。当前读:对于加锁的读(
SELECT ... FOR UPDATE
/SHARE
)、UPDATE
、DELETE
语句,InnoDB使用Next-Key Locks(记录锁+间隙锁)来锁定扫描到的索引记录和范围,从而阻止其他事务在锁定范围内插入新数据,有效防止了幻读。使用场景:需要保证在事务内多次读取相同数据结果一致(避免不可重复读),并且InnoDB的Next-Key Locking机制也极大减少了幻读发生的可能性。这是MySQL最常用的隔离级别。
4. 串行化 (SERIALIZABLE)
定义:最严格的隔离级别。强制事务串行执行(如同单线程),通过加锁完全禁止并发问题。
防止的现象:
脏读 (Dirty Read)
不可重复读 (Non-repeatable Read)
幻读 (Phantom Read)
实现 (InnoDB):所有普通的
SELECT
语句都会被隐式转换为SELECT ... FOR SHARE
(类似LOCK IN SHARE MODE
),对读取的记录加共享锁。这会阻塞其他事务修改这些数据,也会在可能影响结果集的地方加间隙锁防止插入,从而完全避免幻读。锁竞争最激烈。使用场景:对数据一致性要求极高,完全不能容忍任何并发异常(脏读、不可重复读、幻读),且可以接受显著性能下降的场景。
注意:
InnoDB的默认级别是
REPEATABLE READ
。InnoDB在
REPEATABLE READ
下通过Next-Key Locks有效防止了幻读,使其实际表现比标准SQL定义的REPEATABLE READ
更严格(接近SERIALIZABLE
),但性能更好。READ COMMITTED
在InnoDB中通常使用“语句级”快照(每个SELECT
看到的是语句开始时已提交的数据),而REPEATABLE READ
使用“事务级”快照(第一次SELECT
建立视图,后续都沿用)。隔离级别与锁:隔离级别越高,数据库为保证一致性通常需要加更多的锁或维护更长的快照历史,这可能导致更高的锁争用、回滚段维护开销和潜在的性能下降。选择时需要权衡一致性和性能。
设置隔离级别:
sql
-- 设置当前会话的隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 设置下一个事务的隔离级别 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- 查看当前会话和全局隔离级别 SELECT @@SESSION.transaction_isolation, @@GLOBAL.transaction_isolation;