Spring新增数据后立即查询,但是查询不到#Mybatis新增数据丢失

您所在的位置:网站首页 mysql读取最新数据 Spring新增数据后立即查询,但是查询不到#Mybatis新增数据丢失

Spring新增数据后立即查询,但是查询不到#Mybatis新增数据丢失

2023-12-03 22:12| 来源: 网络整理| 查看: 265

项目中遇到的问题, spring先新增了一条记录, 然后立即进行查询,但打死查询不到。

这里简单进行总结记录一下。

首先说可能的原因:

主从数据同步延迟导致代码事务控制有问题其他应用删除了目标数据

这里直接说结论, 我这边时事务的隔离级别有问题。

好了, 接下来复原一下当时的场景:

代码中会新增数据, 然后再进行查询; 代码示例如下:

@Transactional(propagation = Propagation.REQUIRED) public PayedResult saveWithdrawOrder(Integer fastOrderNo) { // 先插入数据, 插入后使用数据库工具进行查询可以查询到数据 methodA(); // 根据ID获取数据, 这里打死获取不到 getById(); } @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public PayedResult methodA(Integer fastOrderNo) { // 这里是新增数据代码 } @Transactional(propagation = Propagation.REQUIRES, rollbackFor = Exception.class) public PayedResult getById(Integer fastOrderNo) { // 这里根据ID进行查询, 此时使用数据库工具可以查询到新增的数据 }

代码大概就像上面的, 但是死活拿不到数据。 然后新增一个线程可以获取到数据。

因为新增使用的传播机制是 requires_new, 所以肯定是数据已经提交。

此时要注意的是数据隔离级别。 默认是 

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)

此种注解, 隔离级别是使用的数据库默认的。 

然后就去查一下数据库隔离级别, 

select @@global.tx_isolation;

特么的居然是

 此时就什么都明白了, 当前事务使用的是可重复读, 即:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。所以是肯定读取不到数据的。

另外也复习一下下隔离级别:

读未提交(READ UNCOMMITTED):一个事务还没提交时,它做的变更就能被别的事务看到。

读提交(READ COMMITTED):一个事务提交之后,它做的变更才会被其他事务看到。

可重复读(REPEATABLE READ):一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。

串行化(SERIALIZABLE):对于同一行记录,“写”会加“写锁”,“读”会加“读锁”,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

修改方案也简单了,将读取方法事务隔离级别修改为 read_commited; 修改如下即可:

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW) public PayedResult getById(Integer fastOrderNo) { // 这里根据ID进行查询, 此时使用数据库工具可以查询到新增的数据 }

因为spring事务传播级别, 如果不新开事务, 那么也会继承父级的事务隔离级别。 所以这里必须使用 required_new;



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3