前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >乐观锁原理与实战演练

乐观锁原理与实战演练

作者头像
加多
发布2018-09-06 14:41:35
5440
发布2018-09-06 14:41:35
举报
文章被收录于专栏:Java编程技术Java编程技术

一、 前言

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

二、 乐观锁实现方式

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

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

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

id

comment

status

1

123456

new

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

这时候就可以使用status这个字段的值来实现乐观锁,具体来说: 对于A类人来说更新使用: update 表 set comment='',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,因为并不是所有业务场景都会有一个状态枚举值来做乐观控制

id

comment

status

version

1

123456

new

1

如图初始化版本号为1,这时候: 对于A类人来说更新使用: update 表 set comment='',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场景介绍

  • 概念模型

image.png

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

  • 审批流程

image.png

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

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

  • 问题与解决

__ 问题一__ 首先审批人都有自己的审批列表,对应一个审批任务来说,假如一级审批有两个人A和B,那么A和B打开自己的审批列表时候都会看到一个审批任务如下,都一个审批按钮,单击审批按钮就会进入审批页面

image.png

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

下面在说下A和B同时进入审批页面后,A审批后,那么B在审批如何正常处理。 考虑在A和B进入页面时候去合同基本信息里面根据id获取当前version然后把version加密后的值encversion存在前端审批页面,当审批时候在使用该version进行乐观锁控制。 update 表 set version=version+1,.... where id = *,version = encversion; 这样两个人同时审批时候只有一个人能审批成功。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.05.12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、 前言
  • 二、 乐观锁实现方式
    • 2.1 使用业务状态来实现乐观锁
      • 2.2 使用版本来实现乐观锁
      • 三、 实战演练
        • 3.1场景介绍
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档