关于数据库层面上锁,解决程序并发插入多条重复数据
2017-09-26 14:07
701 查看
原文地址:http://blog.csdn.net/qq_14874941/article/details/52230257
在数据库层面上乐观锁对于update那个是很简单的,无非在设计表的时候新增一个字段,如:version 这个字段用来记录更新的次数,只加不减,就是用来防止程序多次更新某条数据,然后出现问题。 举个例子吧,对自己的理解也有帮助。 比如某一张表 有id,name,status,version 一共四个字段,假设这是订单表,其中订单表有 未发货、已发货、已签收、拒发货这四个状态。有2个管理员,同时操作某个用户,一个是操作为已发货,一个是操作未拒发货。这时候程序是不管的,就按照先后顺序直接执行一遍。这时双方都是互相不知道对方做了什么操作,都以为自己操作成功了。但是肯定是有一个管理员得到结果不是自己想要的,那么这个时候是不是应该出现提示,说订单状态已经被改变了,然后最后操作的那个管理员需要确认后才能进行操作。那么如何避免呢?这时候就需要用上version了。
假设初始化的时候version是1。在做了一次update操作后version的次数就变成2了。那么version也是要成为where的条件之一。
当时2个管理员看到的肯定是version为1的数据,那么他们同时操作,update安装这个写的话就只有第一个管理员会操作成功了。因为第二次操作的时候version已经变成2了。当然这只是一个很小的例子。实际情况实际考虑,解决方法应该是和这个类似的。
可是我今天遇到是insert,这时候就懵逼了,怎么解决呢?由于我们这个业务的特殊性,一个用户一条最多只能摇一次,那么也就是说insert每天最多执行一次。
我们正好有个数据的createDate,那么可以利用起这个字段,条件是今日是否已经插入了一条
在数据库层面上乐观锁对于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 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。
相关文章推荐
- 关于数据库层面上锁,解决程序并发插入多条重复数据
- mysql并发插入重复数据问题的解决思路
- 并发下,使用redis防止数据重复插入(数据库未对表字段设置唯一情况下)
- java 解决分布式环境中 高并发环境下数据插入重复问题
- 关于.net程序中读取不规则的excle表格中的数据,并插入到数据库的方法
- 关于防止并发插入重复数据
- 关于数据库循环插入大量对象数据的解决办法
- 数据库并发插入避免重复数据的问题
- Java多线程:解决高并发环境下数据插入重复问题
- 数据库---并发控制及其带来的问题丢失修改,读脏数据,不可重复读及解决(程序员级)
- C# 多线程并发处理数据库数据,发送信号等待处理完统一插入.
- 程序返回插入数据库成功,但是数据库内却没有数据
- T-SQL 语句插入中文数据时数据库显示全是问号“???”的解决方法(数据库编码规则)
- 关于数据库并发处理数据的问题
- 关于程序中传null插入数据库
- C# 多线程并发处理数据库数据,发送信号等待处理完统一插入.(转)
- 程序返回插入数据库成功,但是数据库内却没有数据
- 并发的批量插入数据的应用,app,db层面的优化
- 关于如何获得数据库插入操作中数据的自增长主键的值
- 关于用java对excel数据扫描到数据库中然后在导出来后用excel打开的程序: