JPA读不到已提交事务的数据

15 篇文章 0 订阅

最近开发碰到一个问题,事务B中的查询需要用到事务A中提交的数据,所以我就让事务B循环查询数据库,等待事务A提交后再继续执行。但是最后发现事务B怎么等也等不到事务A的数据=.= (这里有个前提,事务AB所在方法都是主方法执行完毕后开启的异步方法,事务A和事务B无法控制开启的先后顺序),所以浅看了一下事务是怎么个回事。

这里首先要清楚事务的四种隔离级别:

事务隔离级别:

  • Read Uncommitted(未提交读);
  • Read Committed(已提交读):解决脏读;
  • Repeatable Read(可重复读):解决脏读、不可重复读;
  • Serializable(串行化):解决事务并发的所有问题。

脏读:读到其他事务未提交的数据(脏数据);

不可重复读:第一次读取独到其他事务提交前的数据,第二次读取读到该事务提交后的数据;

幻读:第一次读取未读到其他事务提交后新增的行数据,第二次读取读到其他事务提交后新增的行数据。

可重复读是InnoDB默认的隔离级别,看到这里问题原因大概就明晰了,可重复读这一隔离级别要求同一事务多次查询的结果是一致的,而我的事务B第一次查询执行的时候事务A还没有提交,那么事务B之后每次的查询都只能查到和第一次查询相同的数据,即使事务A提交的也查不到数据库中新增的数据。

所以要解决这个问题有两个方案:

  1. 把数据库的隔离级别降到已提交读:

相关命令:

1.查看当前会话隔离级别:

select @@tx_isolation;

2.查看系统当前隔离级别:

select @@global.tx_isolation;

3.设置当前会话隔离级别:

set session transaction isolatin level repeatable read;

4.设置系统当前隔离级别:

set global transaction isolation level repeatable read;
  1. 确保事务B执行开始于事务A提交后:

相关代码:

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
    @SneakyThrows
    @Override
    public void afterCompletion(int status) {
        if (status == STATUS_COMMITTED) {
            log.info("事务已提交,执行后续任务);
        }
    }
});

Mysql InnoDB对事务隔离级别的支持程度(并发性能由高到低):

事务隔离级别脏读不可重复读幻读
未提交读可能可能可能
已提交读不可能可能可能
可重复读(默认)不可能不可能对InnoDB不可能
串行化不可能不可能不可能

(在可重复读这一隔离级别,InnoDB通过间隙锁策略防止了幻读的出现)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值