原文地址:http://blog.csdn.net/qq_14874941/article/details/52230257
在数据库层面上乐观锁对于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,那么可以利用起这个字段,条件是今日是否已经插入了一条
这样就可以避免同一用户,一天能够插入2条数据的尴尬情况。个人认为这个是很好的利用了数据库的原子性(不知道这样说会不会有问题)。sql执行语句的时候是严格按照先后顺序来的,只有前一条执行完成了,然后这个时候才执行下一条。正是利用了关系型数据的这个特点,才能在数据库层面解决一些并发问题。对数据的改动基本就是insert和update,只不过insert在插入的时候顺便查了一遍是否已经存在类似的数据罢了。这样就完美解决了这个bug。也不知道有没有其他的解决方法。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} )
引用zyyr365的一段笔记吧:使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。