SQL处理并发之乐观锁

问题描述

在使用mysql数据库存储数据的前提下,有一个抢任务系统,一个任务只能分配给n个人,如果有高并发请求,如何保证数据完整性?


一般做法

在不考虑到数据是否完整的情况下,我们一般只会按照以下思维开发:

  1. 用户请求抢任务接口
  2. 读取数据库剩余数量
  3. 如果大于0,剩余数量减1,更新数据库剩余数量(update task set count=count-1 where id=‘任务id’)
  4. 返回数据

出现的问题以及使用乐观锁概念解决

为什么上面的做法不对呢?我们举个例子,假设用户1和用户2同时调用请求抢任务接口,并且数据库只剩下一个任务可抢,任务剩余数量使用count字段保存;
用户1和用户2请求接口情况模拟,表格的每一行表示一个时间点

用户1用户2
执行1执行1
执行2执行2
执行3(更新count为0)
执行3(更新count为-1)
执行4执行4

通过以上的问题,我们不难知道,本来只有一个任务可抢的,现在被两个用户同时抢了,而且数据库还出现了-1的情况,而这种情况再高并发的时候经常会遇到。

要解决高并发带来的问题,就可以利用乐观锁的概念来解决。
将上面中的第3个步骤中是sql语句改为(update task set count=count-1 where id=1 and count=1)
当然,其中的count=1中的1是步骤2读取出来的数据总数。
或者可以给表加一个版本号version字段,默认为1,每次执行更新的时候自增1,并在where语句后带上读取到的版本号,以免再读取和更新数据之间,有第三者更新了数据库。

用户1用户2
执行1执行1
执行2执行2
执行3(更新count,dao层返回1,表示更新成功)
执行3(更新count,dao层返回0,表示更新失败)
执行4执行4

最后结果

  1. 用户请求抢任务接口
  2. 读取数据库剩余数量
  3. 如果大于0,剩余数量减1,更新数据库剩余数量(update task set count=count-1 where id=‘任务id’ and count=‘读取到的剩余数量’)
  4. 返回数据
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值