关于数据库层面上锁,解决程序并发插入多条重复数据

公司的app新版本上线,其中有一个摇一摇的功能,由于安卓端没有做好处理,导致在同一时间数据post提交了2次。在后台判断发现并没有插入的数据,然后啪啪啪一下子插入了2条。也就是在插入前没有判断是否插过了。当时出了这个bug我懵逼了,什么鬼!!后来上网查了一下以及问了主管,这个这个程序端是不好控制并发的(我目前的理解也是这样的),我目前能想到并且理解的也就只有这个了。好了BBBB说了一大堆。现在开始说解决方法。  在数据库层面上乐观锁对于update那个是很简单的,无非在设计表的时候新增一个字段,如:version 这个字段用来记录更新的次数,只加不减,就是用来防止程序多次更新某条数据,然后出现问题。  举个例子吧,对自己的理解也有帮助。 比如某一张表 有id,name,status,version  一共四个字段,假设这是订单表,其中订单表有 未发货、已发货、已签收、拒发货这四个状态。有2个管理员,同时操作某个用户,一个是操作为已发货,一个是操作未拒发货。这时候程序是不管的,就按照先后顺序直接执行一遍。这时双方都是互相不知道对方做了什么操作,都以为自己操作成功了。但是肯定是有一个管理员得到结果不是自己想要的,那么这个时候是不是应该出现提示,说订单状态已经被改变了,然后最后操作的那个管理员需要确认后才能进行操作。那么如何避免呢?这时候就需要用上version了。 假设初始化的时候version是1。在做了一次update操作后version的次数就变成2了。那么version也是要成为where的条件之一。

update table set status='已发货',version = version+1 where version=1

当时2个管理员看到的肯定是version为1的数据,那么他们同时操作,update安装这个写的话就只有第一个管理员会操作成功了。因为第二次操作的时候version已经变成2了。当然这只是一个很小的例子。实际情况实际考虑,解决方法应该是和这个类似的。


可是我今天遇到是insert,这时候就懵逼了,怎么解决呢?由于我们这个业务的特殊性,一个用户一条最多只能摇一次,那么也就是说insert每天最多执行一次。

我们正好有个数据的createDate,那么可以利用起这个字段,条件是今日是否已经插入了一条

insert into `table` (createDate,字段2,字段3,字段4,user_id)
select now(),值2,值3,值4,#{user_id}
from dual where not exists(
select * from `table` where DATE(createDate) = DATE(now()) and 
user_id = #{user_id}
)
这样就可以避免同一用户,一天能够插入2条数据的尴尬情况。个人认为这个是很好的利用了数据库的原子性(不知道这样说会不会有问题)。sql执行语句的时候是严格按照先后顺序来的,只有前一条执行完成了,然后这个时候才执行下一条。正是利用了关系型数据的这个特点,才能在数据库层面解决一些并发问题。对数据的改动基本就是insert和update,只不过insert在插入的时候顺便查了一遍是否已经存在类似的数据罢了。这样就完美解决了这个bug。也不知道有没有其他的解决方法。

引用zyyr365的一段笔记吧:

使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值