READ_UNCOMMITTED隔离级别下事务无法读取未提交变更问题
READ_UNCOMMITTED隔离级别未生效的常见原因
- 使用的数据库不支持READ_UNCOMMITTED语义
比如PostgreSQL底层实现就不支持读未提交,你声明Isolation.READ_UNCOMMITTED的时候,它会自动降级为READ_COMMITTED,自然无法读取到其他事务未提交的变更;如果使用MySQL,还要确认表的存储引擎是支持事务的InnoDB,MyISAM引擎本身不支持事务,隔离级别的配置也不会生效。 - ORM层延迟刷写导致插入语句未同步到数据库
你在transactionB里执行testEntityDao.insert(newEntity)之后,要是用的是JPA、Hibernate这类ORM框架,默认会把变更先存在会话的持久化上下文中,等到事务提交的时候才会把SQL语句刷到数据库执行。也就是说你日志里打印的PERSISTED NEW ENTITY只代表实体被加入了持久化上下文,数据库层面还没执行插入语句,transactionA自然查不到对应记录。
修复方法是在insert语句之后手动触发刷写,比如Spring Data JPA中可以调用testEntityDao.flush(),强制框架把插入SQL立刻发送到数据库执行。 - Spring声明式事务未实际生效
Spring的@Transactional是基于AOP代理实现的,只有通过代理对象调用的标注方法才会开启事务。如果你的transactionA和transactionB是在同一个类中,通过类内部方法调用触发的,事务注解会直接失效,隔离级别的配置自然也不会生效。另外还要确认你是否正确开启了事务管理功能,比如有没有加@EnableTransactionManagement注解。 - 全局事务配置覆盖了方法级隔离级别
如果你在事务管理器、JPA厂商适配器等位置配置了全局的默认隔离级别,优先级会高于方法上的isolation参数,导致READ_UNCOMMITTED配置被覆盖,你可以检查下全局的事务相关配置。 - 两个事务复用了同一个数据库连接
极端情况下如果连接池配置异常,两个事务拿到了同一个数据库连接,会属于同一个事务上下文,也会导致你预期的跨事务读未提交效果无法复现。
内容的提问来源于stack exchange,提问作者Tabish Mir
相关产品推荐
相关产品推荐

