msyql 除了加唯一索引,又其他办法防止同一时刻写入重复数据么?

2019-06-29 10:27:40 +08:00
 dyllen

情况是这样的,有些 api,第三方系统会推数据过来,有两个不同的 api,这两个 api 都会往一个表里面写同样的数据,两边业务逻辑上都有查重的,现在查历史记录,看见在有同时推数据到这两个接口的请求,导致写入重复的数据,创建时间都一样。除了加唯一索引有没有其他什么办法避免?

8794 次点击
所在节点    MySQL
43 条回复
Navee
2019-06-29 12:22:00 +08:00
何必为难自己
yiplee
2019-06-29 13:06:07 +08:00
建一新张表它的主键当唯一索引用。插入的时候开启事务,先插入新表,如果插入成功了,再插入现有的业务表。
qf19910623
2019-06-29 13:16:32 +08:00
做一个短时间的缓存锁队列
agui2200
2019-06-29 14:21:59 +08:00
用 for update + 事务,查询共有的全局锁表,做悲观锁
agui2200
2019-06-29 14:22:20 +08:00
@agui2200 这个方案实施起来比较简单,但是性能差一些
Asice
2019-06-29 14:36:20 +08:00
@agui2200 #24 已经是高并发才会出现重复了,还悲观锁,要搞死数据库吗
lihongjie0209
2019-06-29 14:50:12 +08:00
只能用队列了
Kylinsun
2019-06-29 15:20:41 +08:00
建议增加一个字段,然后需要加唯一键的列加强这个辅助唯一键作为唯一键。
hosaos
2019-06-29 15:53:20 +08:00
针对你该条数据的业务唯一建做分布式锁,抢锁成功后先查后插入
karllynn
2019-06-29 15:57:44 +08:00
开分布式锁或者串行化

或者你新建一张表 /加个字段,然后把原来的数据处理一下迁移过来
Cbdy
2019-06-29 16:07:34 +08:00
把其中一个 API 的请求代理另一个 API
linbiaye
2019-06-29 16:45:49 +08:00
笨方法:分布式锁,可以基于数据库做,不需要引入其它组件。
begin(read committed 级别即可)
1. 插入锁表
2. 根据待插入数据 count 是否已存在,存在则 rollback
4. 插入数据
5. 删除锁
commit
个人倾向的方法:表新加个唯一 column
passerbytiny
2019-06-29 18:05:34 +08:00
悲观锁方式:查重的时候直接锁表(因为后面是要新增数据的,所以只能锁表),新增数据或超时后解锁。此方式基本没人用。
变相乐观锁方式:第三方直接推送,若收到“有重复数据”错误再做后续处理;你这边单事务内查重加插入。此方式没啥特殊性,就是注册用户判断重复的逻辑,但是若你这个业务是高并发并且冲突情况占比大,此方式也不是太合适。

如果是高并发场景,并且第三方确实会发送重复数据,建议还是允许重复数据的好。或者,给第三方分配 ID,表中加一列“来源”,这样就不会出现重复数据了。

你的描述少了一个关键场景:第三方查重后如果发现重复了,是怎么处理的。
Takamine
2019-06-29 18:54:36 +08:00
得看具体业务,乐观一点或者悲观一点。
jaskle
2019-06-30 07:03:51 +08:00
你无法保证外部数据是否有重复,就算你有队列和分布式锁,但是他就是发了两个一样的,所以加唯一索引是最佳选择,如果旧数据过多可以考虑双联合索引,手动差异化一下。
msg7086
2019-07-01 03:35:50 +08:00
要避免同时写入那就只能串行化。串行化要么加锁,要么队列。
qsbaq
2019-07-01 09:42:38 +08:00
唯一索引是最佳选择。
justRua
2019-07-01 11:48:15 +08:00
这是发生幻读了吧,把数据库隔离级别设置成串行化,也可以用队列在业务层串行化,唯一索引貌似是最方便的。
werty
2019-07-01 11:52:47 +08:00
写之前全表加锁, 然后再 select 一次, 看看有没有主键重复, 最后 insert;
只需要改改 DAO 层就够了
IamUNICODE
2019-07-01 13:04:57 +08:00
用 redis 的话,setnx 一下?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/578494

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX