Spring Boot中READ_UNCOMMITTED事务隔离级别不生效问题排查
问题原因及解决方案
核心问题:Hibernate延迟Flush导致修改未同步到数据库
你遇到的问题本质是Hibernate的默认Flush行为:在bookTicket1中调用saveAll()后,Hibernate并不会立即将修改同步到数据库,而是将变更暂存在一级缓存中,直到事务提交前(或触发特定Flush条件时)才执行UPDATE语句。此时数据库中的数据仍为AVAILABLE,所以即使bookTicket2使用READ_UNCOMMITTED隔离级别,也读不到未提交的LOCKED状态。
具体验证与修复步骤
1. 手动触发Flush同步修改到数据库
在bookTicket1的saveAll()之后,调用Repository的flush()方法,强制Hibernate立即将缓存中的变更写入数据库:
showSeatRepository.saveAll(showSeats); // 新增手动flush,强制同步到数据库 showSeatRepository.flush(); System.out.println("Show Seats LOCKED. Not Committed yet.");
此时,即使事务未提交,数据库中已经存在未提交的UPDATE记录,bookTicket2的READ_UNCOMMITTED事务就能读到脏数据。
2. 确认数据库引擎支持事务与READ_UNCOMMITTED
确保你使用的数据库引擎支持事务和READ_UNCOMMITTED隔离级别:
- 若使用MySQL,需确认表的引擎为InnoDB(MyISAM不支持事务,隔离级别设置无效)。
- 可通过SQL查询当前数据库的全局隔离级别:
Spring的SELECT @@GLOBAL.tx_isolation;@Transactional(isolation = Isolation.READ_UNCOMMITTED)会覆盖全局设置,但需确保数据库本身支持该级别。
3. 验证Spring事务配置生效
确认Spring的事务管理器(如JpaTransactionManager)已正确配置,@Transactional注解能正常生效:
- 检查启动类是否添加了
@EnableTransactionManagement注解(Spring Boot默认已启用,但显式添加更稳妥)。 - 可通过日志验证事务的隔离级别是否被正确设置:在
application.yml中添加日志配置,查看事务创建时的隔离级别:logging: level: org.springframework.transaction: DEBUG org.hibernate.transaction: DEBUG
4. 排除缓存干扰
确保bookTicket2的查询是直接从数据库读取,而非缓存:
- Spring Data JPA的
findAllByIdIn默认会执行SQL查询,不会走二级缓存(除非你显式配置了二级缓存)。 - 若怀疑二级缓存影响,可临时禁用二级缓存,或在查询方法上添加
@QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_CACHEABLE, value = "false"))。
内容的提问来源于stack exchange,提问作者vipvipul1
相关产品推荐
相关产品推荐

