乐观锁原理与实战演练

一、 前言

最近在做一个简单审批流程的项目,由于只有固定二级审批所以没有使用集团工作流bpms,然后就遇到一个审批节点捞单时候,多个人同时审批时候如何保证业务正常运行的问题,我采用的就是乐观锁来解决的。所谓捞单就是一个审批节点可以同时由多个人同时审批。

二、 乐观锁实现方式

乐观锁意思是说多个事务修改数据库中同一条记录时候,并不是在一个事务中使用 for update 锁定这条记录从而防止其他事务在本事务提交前访问这条记录,而是在具体执行更新语句时候进行判断,并通过更新结果影响的行数来判断当前更新是否有效。具体来说有两种实现方式:

2.1 使用业务状态来实现乐观锁

比如一个任务表里面包含如下字段:

idcommentstatus
1123456new

一个任务的status有:new,operator,manager状态。new状态下有多个A人可以去更新这条记录的comment并且把status更新为operator,但是只能有一个人能成功。operator状态下可以多个B人去更新这题记录的comment并且status更新为manager但是只有一个人能更新成功。

这时候就可以使用status这个字段的值来实现乐观锁,具体来说:‘,status=’operator’ where status = ‘new’ and id = 1;
对应B类型来说更新使用: update 表 set comment=’
‘,status=’manager’ where status = ‘operator’ and id = 1;

假如多个A类人同时去更新数据时候,第一个执行更新语句的人会锁住该条记录,更新status=’operator”,这时候其他事务是访问不了该记录的,直到当前事务提交返回结果1。当前事务提交后,然后其他事务在执行这条语句,这时候由于根据条件status = ‘new’ and id = 1获取到0条记录,所以返回0.所以如果更新结果返回1,则提示当前A类人数据更新成功,返回0的操作人则提示当前任务已经被捞单人员处理过了,无须在处理。同理B类人也是这样。

2.2 使用版本来实现乐观锁

相比于2.1 要在任务表添加一个字段version,因为并不是所有业务场景都会有一个状态枚举值来做乐观控制

idcommentstatusversion
1123456new1

如图初始化版本号为1,这时候:‘,status=’operator’,version=version+1 where version = 1 and id = 1;
对应B类型来说更新使用: update 表 set comment=’
‘,status=’manager’,version=version+1 where version = 2 and id = 1;

三、 实战演练

3.1场景介绍

  • 概念模型

0?wx_fmt=png

如图,一个合同基本信息对应多个审批任务

  • 审批流程

0?wx_fmt=png

如图三级审批,假设三级审批都是捞单角色。只有三级都审批通过后合同基本信息的状态才是审批结束,只有一个审批节点的人审批驳回后,合同基本信息状态才是驳回状态,只有申请人撤回了申请,当前状态才是撤回。其他状态下都是审批中状态,也就是说即使一级,二级审批通过了,当前合同基本信息状态是审批中状态。

所以由于一级二级审批时候当前状态都是审批中,所以没办法用2.1的方式,所以使用version的方式。

  • 问题与解决

问题一0?wx_fmt=png

考虑A和B都看到了同一个审批任务,其中A单击了审批按钮,进入了审批页面,并且审批了该任务A任务状态从new->done,取消了其他捞单任务B的任务状态new->cancel。但是此时B的审批列表里面该任务还是处于审批状态,因为他没有刷新页面,假如这时候B单击审批时候如果不做任何处理将会出现问题,所以在进入审批页面时候还需要再次校验下B的任务当前状态是否还是new。

下面在说下A和B同时进入审批页面后,A审批后,那么B在审批如何正常处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值