为什么这段 SQL 代码在 Mysql 失效了, Mysql 不是阻塞的吗?

2022-03-31 11:04:04 +08:00
 Features
判断表中是否有记录:
SELECT * FROM `order` WHERE `member_id` = 39 AND `sn` = 20220331783;
无则插入
INSERT INTO `order` SET `sn` = 20220331783 , `member_id` = 39;
有则更新
UPDATE `order` SET `sum` = `sum`+1;

实际的结果是数据库中有多条相同的 member_id 和 sn
为什么会这样呢?
Mysql 不是阻塞的吗?
3961 次点击
所在节点    问与答
46 条回复
zw1one
2022-04-01 09:26:57 +08:00
SELECT * FROM `order` WHERE `member_id` = 39 AND `sn` = 20220331783;
->
SELECT * FROM `order` WHERE `member_id` = 39 AND `sn` = 20220331783 for update;
wangxin13g
2022-04-01 10:18:42 +08:00
唯一索引+事务
你这几条 sql 不是原子性的出现几条数据一样不是很正常么
jowan
2022-04-01 10:31:23 +08:00
这就是常见的并发问题 如果不考虑性能的话用 18#的方案可以解决 也就是无则插入有则更新
问这个问题说明你平时没有做过高并发且需要保证原子操作的功能
但绝大多数需要考虑性能问题的情况下 可以用分布式锁 比如 redlock
还有不管你用什么方式解决了重复插入的问题 但依然没解决重复更新的问题
比如这个场景可能是前端没有做节流限制或者客户端网络太差导致重复提交
LinsVert
2022-04-01 17:04:07 +08:00
@Features 并发处理肯定是后端处理,我只是举例实际应用场景中能触发的一种可能。
lyy16384
2022-04-01 18:29:01 +08:00
@micean #18 ON DUPLICATE KEY UPDATE 有个问题就是即使 update 也会消耗一个自增主键,在某些 update 特别多的情况下最好还是先 select 判断一下
CEBBCAT
2022-04-04 01:42:37 +08:00
@Features RocketMQ 是消息队列,你可以用它解决,这取决于你的业务设计。当你决定要使用 MQ 来 handle 并发的时候,新的问题随之产生:用户操作是否有延时?消息消费是否原子?如果某条消息消费到一半,机器断电了怎么办?

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

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

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

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

© 2021 V2EX