首页 >> 基础教程

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)、UPDATEDELETE语句,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),对读取的记录加共享锁。这会阻塞其他事务修改这些数据,也会在可能影响结果集的地方加间隙锁防止插入,从而完全避免幻读。锁竞争最激烈。

  • 使用场景:对数据一致性要求极高,完全不能容忍任何并发异常(脏读、不可重复读、幻读),且可以接受显著性能下降的场景。

注意:

  1. InnoDB的默认级别是REPEATABLE READ

  2. InnoDB在REPEATABLE READ下通过Next-Key Locks有效防止了幻读,使其实际表现比标准SQL定义的REPEATABLE READ更严格(接近SERIALIZABLE),但性能更好。

  3. READ COMMITTED在InnoDB中通常使用“语句级”快照(每个SELECT看到的是语句开始时已提交的数据),而REPEATABLE READ使用“事务级”快照(第一次SELECT建立视图,后续都沿用)。

  4. 隔离级别与锁:隔离级别越高,数据库为保证一致性通常需要加更多的锁或维护更长的快照历史,这可能导致更高的锁争用、回滚段维护开销和潜在的性能下降。选择时需要权衡一致性和性能。

  5. 设置隔离级别

    sql

    -- 设置当前会话的隔离级别
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
    -- 设置下一个事务的隔离级别
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    -- 查看当前会话和全局隔离级别
    SELECT @@SESSION.transaction_isolation, @@GLOBAL.transaction_isolation;


最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1