该问题应该可以归纳为并发导致的数据库数据重复

问题描述:在给移动端做一个收藏功能的时候,正常情况下,登录人点击收藏按钮调用收藏接口,再点击调用取消收藏接口,收藏时不能重复收藏(这个开始时是在程序里做的判断,即添加数据的时候根据登录人id和被收藏人的id来判断是否要收藏该人)。但是,当移动端猛戳收藏按钮的时候,就出现数据重复的情况。


解决办法:使用Hibernate 注释 唯一键约束 uniqueConstraints

@Table 注解包含一个schema和一个catelog 属性,使用@UniqueConstraints 可以定义表的唯一约束。

所以采用的是联合约束:

@Table(name="t_collection",
  uniqueConstraints = {@UniqueConstraint(columnNames={"登录人id", "被收藏人id"})})

添加了注解之后,在数据库里会出现索引信息


如果是单一字段约束可以用

@Table(name="tbl_sky",
  uniqueConstraints = {@UniqueConstraint(columnNames="month")})


网上其他分析及解决办法:

1、解决方法无非就是程序端控制和数据库本身来控制,程序端控制可以用同步锁或者自编的线程锁,或者有避免重复提交的拦截器等等,数据库控制就是使用唯一性标识,当sql中包含唯一性主键标识时,数据库执行n条sql还是会有先后的,这样后面的语句执行就会失败。

2、通过数据库表的唯一索引解决,虽然不能保证判断后可以插入(并发的问题)。 
但是肯定不会有重复记录

如果并发量非常小的话,线程就可以解决。

3、问题很简单:查询重复和真正的Insert并非原子操作(我说的是二者加在一起不是原则操作),因此如果两个线程在insert之前都做了同一个Key的查询,结果都是False,这时两个线程都做insert,问题就产生了: 

回避的方法: 
1、数据库字段设置唯一性,这样一定有一个是insert失败的; 
2、程序操作加Synchronized,但是不支持集群; 
3、使用分布式锁,比如Zookeeper(操作之前获取一把锁) 

注意的是这里实际上是无法使用select for update的,因为数据还没有,所以也没法加锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值