mysql 并发更新某个字段引发的问题和思考

2022 年 11 月 1 日
 U87

mysql 并发更新某个字段(调一次接口,数据库里的 click 字段加一),用 wrk 并发测试工具测试, -t 10 -c 500 -d 30s ,最后 30 秒大概 3000 个请求,我理解 click 应该增加了 3000 ,但实际只增加了几十。 另外说一下,先查询再 update 的。查询的时候用了 with_for_update()

2587 次点击
所在节点    MySQL
12 条回复
linauror
2022 年 11 月 1 日
直接 update xxx set click = click + 1 where id = xxx 呢
pota
2022 年 11 月 1 日
你 select 大量查询拿到了同一个基数啊。+1 都是一个数
U87
2022 年 11 月 1 日
@pota 不是吧,我 select 的时候用了 for update
kele1997
2022 年 11 月 1 日
for update 可以防止并发读。
第一个请求假如读到 1 ,程序里面准备发送 update xxx set click = 2,但是还未发送。
第二个请求此时也读取 mysql ,读到的结果也是 1 , 程序里面也准备发送 update xxx set click = 2
最后等两条 sql 都运行完了,click 有可能只加了一次

正常的操作应该是读和写在一个事务里面吧,单行 sql 直接 update 肯定是一个事务。
但是拆开 select 和 update 有可能不在一个事务中吧
zjj19950716
2022 年 11 月 1 日
考虑 redis 的 incr 吗
wushigejiajia01
2022 年 11 月 1 日
上锁呗
F281M6Dh8DXpD1g2
2022 年 11 月 1 日
你的隔离级别是啥
盲猜你得改成 rc
optional
2022 年 11 月 1 日
不会没开启事务吧,另外楼上说的对,得改成 rc 级别 mysql 默认记得是 rr
thinkershare
2022 年 11 月 1 日
加读写锁, 或者使用版本戳,乐观并发并发冲突后抛异常重试。
simple2025
2022 年 11 月 1 日
直接用 redis 锁吧,mysql 搞那么复杂干嘛?
xuanbg
2022 年 11 月 2 日
1 楼已经给了正确答案
U87
2022 年 11 月 2 日
@optional 用的 ORM,事务开启的,找到问题所在了。原来我们的测试库引擎是 myISAM 。。。。。

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

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

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

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

© 2021 V2EX