乐观锁维护原则
使用版本号的乐观锁 SQL
update tab_xxx
set column1=#{field1Value}, column2=#{field2Value},…
sys_version=sys_version+1, update_pin=#{updatePin}, update_time=now()
where id=#{id} and sys_version=#{sysVersion} and yn=0程序处理流程
- 判断SQL更新影响行数。如果为 0,说明这条数据已经被其它线程更新,并发更新失败
- 反查数据。因为乐观锁导致,更新条数为0时(并发更新)要反查数据,如果已经改为目标结果,返回“已被他人执行成功”的结果,不能直接返回失败,也不能直接返回成功。
- 重试更新操作。具体重试采取系统再次取数据后更新的方式,还是提示给客户重新操作的方式,每个系统视具体场景而定。
常见问题
- 有sysVersion却在update语句里没体现
- sql体现了sysVersion,在程序里没对更新结果条数做判断
- 对更新结果条数做了判断,但是只要条数为0就抛异常(实际可能已经被其它线程执行成功),没有就地反查比对结果
- 就地反查比对结果了,当前状态和预期状态一致就返回执行成功,没有告知是其它线程执行成功的,导致当前线程的调用方认为是自己执行成功的,进而执行后续逻辑(实际已经被其它相同逻辑的线程执行过)。