java事务隔离级别由数据库实现,java仅声明需求;jdbc用settransactionisolation()、spring用@transactional(isolation=...)设置;四级依次增强:read_uncommitted(全不防)、read_committed(防脏读)、repeatable_read(防脏读和不可重复读)、serializable(全防);实际效果依赖数据库机制如mvcc、间隙锁等。

Java 中事务隔离级别不是靠 Java 自己“实现”的,而是通过声明要求,由底层数据库来执行保障。设置对了,才能有效解决脏读、不可重复读和幻读这三类并发问题。
怎么在 Java 里设置隔离级别
主要有两种常用方式,都需确保数据库驱动和存储引擎实际支持该级别:
-
JDBC 层设置:获取 Connection 后调用
setTransactionIsolation(),例如:conn.setTransactionIsolation(Connection.TRANSACTION_ISOLATION_REPEATABLE_READ); -
Spring 声明式事务:在
@Transactional注解中指定,例如:@Transactional(isolation = Isolation.REPEATABLE_READ)
注意:若数据库不支持所设级别(如 H2 不支持 SERIALIZABLE),可能静默降级或抛异常,建议结合数据库日志或文档确认实际生效级别。
不同隔离级别分别防什么问题
四种标准级别逐级增强约束,也带来更高开销:
- READ_UNCOMMITTED:不阻止任何问题,允许脏读、不可重复读、幻读;极少使用
- READ_COMMITTED:阻止脏读;但同一事务内多次查同一条记录可能结果不同(不可重复读),也可能看到新插入的行(幻读)
- REPEATABLE_READ:阻止脏读和不可重复读;MySQL InnoDB 默认级别,配合 MVCC + 间隙锁,通常能抑制幻读(但快照读下仍可能因新插入出现)
- SERIALIZABLE:完全串行化,三类问题全防;性能最低,只用于极敏感场景(如金融核心账务)
光设级别还不够:得靠数据库机制落地
Java 设置只是“提需求”,真正起作用的是数据库内部实现:
- MySQL InnoDB 在 REPEATABLE_READ 下默认用 MVCC 提供一致性快照,避免前两类问题;对范围查询加间隙锁(Gap Lock)或临键锁(Next-Key Lock)来压制幻读
- PostgreSQL 的 READ_COMMITTED 每次 SELECT 都新建快照,不会不可重复读,但幻读仍可能发生
- Oracle 默认 READ_COMMITTED,不支持标准 REPEATABLE_READ,其“可重复读”靠 SCN 快照实现,也不发生幻读
隔离级别搞不定时,可以加点手动控制
当业务逻辑对数据一致性要求极高,仅靠隔离级别不够稳,可补充以下手段:
- 关键查询后加
SELECT ... FOR UPDATE,触发行级写锁,阻塞其他事务修改或插入相关数据 - 对高频变更的统计类查询(如“当前订单总数”),改用带版本号或时间戳的缓存,避开实时数据库幻读
- 在应用层做乐观锁(如 version 字段校验)或业务重试机制,降低强一致性依赖
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











