mysql 存在则更新,不存在则插入的并发问题

发布于 2022-09-06 10:58:45 字数 740 浏览 14 评论 0

比如有这样的场景:

  1. 操作一:检查表 table 中的 id=2 记录是否存在,存在,则更新这条记录,否则插入一条记录
  2. 操作二:检查表 table 中的 id=2 记录是否存在,存在,则更新这条记录,否则插入一条记录

有多中这样的操作,分别被封装进不同的服务里,请问有哪些方法可以防止同时插入两(多)条呢?
开发环境:Spring boot + mybatis
自己看了下,可以用
@Transactional(isolation = Isolation.Serializable) 注解;或是将 id 设置为 unique;或是用复合 sql 语句(exist 之类的),请问哪种更好,或是有没有更好的方法。

各位大神,交流的时候突然又想起一个场景:

  1. 操作一:检查表 table 中的 id=2 记录是否存在,存在,则直接返回id,否则插入一条记录
  2. 操作二:检查表 table 中的 id=2 记录是否存在,存在,则直接返回id,否则插入一条记录

有多中这样的操作,分别被封装进不同的服务里,请问有哪些方法可以防止同时插入两(多)条呢?有查询到 insert ignore 但是这个方法,如果发现已有数据,会返回0,假如操作1和操作2同时查询id=2的记录发现不存在,然后操作1插入了一条记录,并返回自增id,操作2若用insert ignore则返回0,感觉就不对了,会造成误解,请问有没有什么好的方法呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一指流沙 2022-09-13 10:58:45

隔离级别设置为可串行化很可能会影响数据库性能。
id设为unique

INSERT INTO t1 (a, b, c) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE a=1, b=2, c=3;

参考:insert on duplicate

雪花飘飘的天空 2022-09-13 10:58:45

我的做法,可不使用@Transactional注解:

INSERT INTO t1 (a, b, c) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE id=last_insert_id(id), a=1, b=2, c=3;

这样执行完查询后可以直接使用Statement.getGeneratedKeys获取到插入的自增ID或更新的记录ID

红ご颜醉 2022-09-13 10:58:45

如果你的使用场景是高并发的话,单纯的读库是会有性能问题的,因为可能牵涉到mysql锁的使用,个人建议配合redis集合使用,通过集合的唯一性来解决这个问题。
在执行操作的时候先尝试向集合中添加元素,添加成功则说明不存在,添加失败则说明已存在。希望对你有帮助

孤檠 2022-09-13 10:58:45

replace into t1(id, column) values(2, column)
这个对于性能来说更好。

狼亦尘 2022-09-13 10:58:45

我是直接加了一个锁,但这样会影响性能。 若对性能要求不高可以用我这个方法。
https://kyle.net.cn/2017/11/0...

泪之魂 2022-09-13 10:58:45

第二种场景是不是可以考虑设置 unique key,使用普通 insert,发生异常后延迟重试的机制。

江湖正好 2022-09-13 10:58:45

这个就是很典型的并发问题啊,队列就解决了。

先把记录全部入队,然后统一出队。

夏日浅笑〃 2022-09-13 10:58:45

可以尝试REDIS来进行缓存并去重操作 定时再将数据插入数据库

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文