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

2022 年 3 月 31 日
 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 不是阻塞的吗?
4872 次点击
所在节点    问与答
46 条回复
zjj19950716
2022 年 3 月 31 日
看到沙发还在,我准备抢一楼,有人也准备抢一楼,那么谁是一楼呢
xzh20121116g
2022 年 3 月 31 日
90%的概率:代码没有考虑并发,跟 mysql 没关系
sun1991
2022 年 3 月 31 日
MySQL 不是阻塞的. (陈述句)
任何上规模数据库都不可能简简单单就阻塞.
livenux
2022 年 3 月 31 日
这个用 upsert 不就好了?
gtchan13579
2022 年 3 月 31 日
直接用 replace into
Feiex
2022 年 3 月 31 日
开启事务了吗,什么级别?
Features
2022 年 3 月 31 日
@xzh20121116g
@sun1991
测试环境是单库,发出多个请求就会导致数据重复
假设有 1,2,3 个请求
请求 1 返回成功结果,这时候服务端应该把数据插入表中了
请求 2 和请求 3 应该能 SELECT 到正确的数据啊?
Features
2022 年 3 月 31 日
@Feiex 没设置事务
Jooooooooo
2022 年 3 月 31 日
@Features 请求 2 等待请求 1 成功再做吗?
turan12
2022 年 3 月 31 日
使用 select for update 不知能否解决问题?
Features
2022 年 3 月 31 日
@Jooooooooo 好像确实不是的
Ritter
2022 年 3 月 31 日
两个请求同时进来 同时查到没有记录呗
Feiex
2022 年 3 月 31 日
@Features mysql 执行语句默认不是阻塞的,不然数据库做不了并发;
#7 典型的事务隔离问题;

语句开启需要事务,rc 级别即可:
begin transaction;
//for update 注意是关键!!!
SELECT * FROM `order` WHERE `member_id` = 39 AND `sn` = 20220331783 for update;
INSERT INTO `order` SET `sn` = 20220331783 , `member_id` = 39;
UPDATE `order` SET `sum` = `sum`+1;
commit;
Features
2022 年 3 月 31 日
@Ritter 是的,因为 Mysql 是远程的,把这个问题暴露出来了,以前没注意到。。。
Features
2022 年 3 月 31 日
@Feiex 感谢
Features
2022 年 3 月 31 日
@turan12 应该不行,因为多个请求并发,可能前一个请求的数据还 没到达服务器 /存储成功 /未更新
应该要从其他地方解决问题
wowo243
2022 年 3 月 31 日
接口幂等问题?加个锁或者标记位,比如在 redis 中存一个 key 为 member_id+sn 的数据,接口先访问 redis 看 key 是否存在,不存在则设置 key 并执行逻辑,执行完逻辑后删除 key ;存在则等待标记位清除,再设置 key 并执行逻辑。
micean
2022 年 3 月 31 日
sn 和 member_id 建唯一索引

然后 INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c = c+1
Pythoner666666
2022 年 3 月 31 日
考虑下是不是异步 + 并发的问题
JeromeCui
2022 年 3 月 31 日
@micean 这才是正确的方式

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

https://study.congcong.us/t/844048

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

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

© 2021 V2EX