配合视频效果更佳: www.itlaoqi.com/chapter.htm…
为什么会产生并发冲突?
先查询后更新的场景在遇到并发场景时都可能会产生并发冲突写入脏数据
常见的解决办法是通过for update子句将查询语句hang住,这样并行处理就变为串行执行,这种处理方式被称为“悲观锁”
悲观锁并发性太差,高并发场景用户体验差
实现目标:既要保证用户体验也要实现数据可靠
示例表样:增加_version字段,通过版本实现乐观锁版本控制
事务开始,初始版本为1,更新后版本变为2
如果执行过程中出现并发问题,在执行过程中因为其他线程已将版本变化,原线程更新时找到对应版本,因此无法更新数据
如果遇到冲突后该怎么办? 前端应用提示“数据正在处理,请稍后再试!” 附加spring-retry在service上进行方法重试
@Transactional
@Retryable(value = {VersionException.class}, maxAttempts = 3)
public void updateBal(){
Account acc = 执行:”select id,bal,_version from acc where id = 1001”;
acc.setBal(acc.getBal() + 400);
int count = 执行:“update acc set bal = ${acc.bal} , _version=_version + 1
where id = 1001 and _version=${acc.version}”;
if(count == 0) { throw new VersionException(“产生并发异常”) };
}