Spring事务隔离级别共5种,对应解决脏读、不可重复读、幻读问题:READ_UNCOMMITTED允许三者;READ_COMMITTED仅防脏读;REPEATABLE_READ防前两者;SERIALIZABLE彻底防止三者;DEFAULT沿用数据库默认级别。

Spring 事务隔离级别通过约束事务间的数据可见性,直接对应解决脏读、不可重复读和幻读这三类并发问题。每种隔离级别在“数据一致性”和“并发性能”之间做不同权衡,关键在于理解它**禁止什么、允许什么**。
READ_COMMITTED:防止脏读
这是大多数数据库(如 Oracle、SQL Server)的默认级别,也是 Spring 中最常用且推荐的起点。
- 它确保一个事务只能读取**已提交**的数据,其他事务未提交的修改对当前事务完全不可见
- 因此,不会出现“读到回滚前的中间值”——脏读被彻底杜绝
- 但同一事务内两次查询同一行,可能因其他事务已提交更新而得到不同结果 → 不可重复读仍存在
- 范围查询时,其他事务插入/删除数据并提交后,再次查询可能行数变化 → 幻读也仍存在
用法示例:@Transactional(isolation = Isolation.READ_COMMITTED)
REPEATABLE_READ:防止脏读 + 不可重复读
MySQL InnoDB 默认使用该级别,Spring 中启用后能保证“同一个事务中多次读同一行,结果不变”。
立即学习“Java免费学习笔记(深入)”;
- 底层通常结合 MVCC(多版本并发控制)与行锁实现:首次读取时生成快照,后续读沿用该快照
- 即使其他事务更新并提交了某行,当前事务仍看到原始值 → 不可重复读被阻止
- 注意:标准 SQL 定义下,它不解决幻读;但 MySQL 的 InnoDB 通过间隙锁(Gap Lock)+ Next-Key Lock实际覆盖了大部分幻读场景(如范围查询中的插入)
- 不过,在纯 INSERT 场景或某些特定条件(如无索引查询)下,仍可能出现幻读
用法示例:@Transactional(isolation = Isolation.REPEATABLE_READ)
SERIALIZABLE:彻底防止三类问题
这是最高隔离级别,事务完全串行执行,从逻辑上消除了所有并发干扰。
- 对读操作加共享锁,对写操作加排他锁,且锁会覆盖整个扫描范围(包括不存在的记录间隙)
- 因此,其他事务无法在当前事务读取的范围内插入、更新或删除任何数据 → 脏读、不可重复读、幻读全部杜绝
- 代价是显著降低并发能力,容易引发锁等待甚至死锁,吞吐量大幅下降
- 一般只用于极少数强一致性要求、且并发压力不高的业务环节(如金融核心账务校验)
用法示例:@Transactional(isolation = Isolation.SERIALIZABLE)
DEFAULT 和 READ_UNCOMMITTED:慎用
DEFAULT 表示交由数据库决定,默认行为取决于具体 DBMS(如 MySQL 是 REPEATABLE_READ,Oracle 是 READ_COMMITTED),适合开发环境快速启动,但不利于跨库迁移和统一管控。
READ_UNCOMMITTED 允许读未提交数据,三种问题全部可能发生,几乎不用于生产系统,仅限特殊调试或日志类低一致性要求场景。


















