想必隔离级别一直是一个诸多程序员避而不谈的问题,对各种脏读、不可重复度、幻读的问题也是一知半解
我以库存扣减为例子大概来阐述rc rr对应的解决方案
RC级别
start transactionTA;
start transactionTB;
TA query store=100;
TB query store=100;
TB update set store=store-20 where sku=1 and store=100; affect 1;
TA update set store=store-10 where sku=1 and store=100; affect 0;
TA在执行后发现sku 1库存已经为80,所以不会有 affect 0,此时程序重新查询后 再进行 update便可执行成功
RR级别
在上述案例中,TB重新查询后store永远都是100,然而每次重试后永远都是affect 0;这时就需要重新开启事务来处理;
@Override
@Retryable(value = BizsException.class)//重试
public Boolean updateBalance(Balance balance) throws BizsException {
//查询数据
BalanceVO balanceVO = readCommitService.searchBalanceById(balance.getId());
Integer result = balanceDao.updateBalance(balanceVO);
//发现通过乐观锁没有更新到数据则抛出异常驱动retryable重新调用接口
if (result < 1) {
throw new BizsException(ResultEnum.BALANCE_OPERATE_ERROR);
}
return true;
}
//强制不启动事务 不指定可能外层嵌套事务后存在一些问题
***如果隔离界别为rc级别无需此步***
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public BalanceVO searchBalanceById(Long balanceId) {
return balanceDao.searchBalanceById(balanceId);
}
maven dependency
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
如果对此文章有任何疑问请联系本人qq:1808568908