mysql 并发更新某个字段(调一次接口,数据库里的 click 字段加一),用 wrk 并发测试工具测试, -t 10 -c 500 -d 30s ,最后 30 秒大概 3000 个请求,我理解 click 应该增加了 3000 ,但实际只增加了几十。 另外说一下,先查询再 update 的。查询的时候用了 with_for_update()
1 linauror 2022-11-01 17:50:28 +08:00 直接 update xxx set click = click + 1 where id = xxx 呢 |
![]() | 2 pota 2022-11-01 17:50:51 +08:00 ![]() 你 select 大量查询拿到了同一个基数啊。+1 都是一个数 |
![]() | 4 kele1997 2022-11-01 18:11:00 +08:00 for update 可以防止并发读。 第一个请求假如读到 1 ,程序里面准备发送 update xxx set click = 2,但是还未发送。 第二个请求此时也读取 mysql ,读到的结果也是 1 , 程序里面也准备发送 update xxx set click = 2 最后等两条 sql 都运行完了,click 有可能只加了一次 正常的操作应该是读和写在一个事务里面吧,单行 sql 直接 update 肯定是一个事务。 但是拆开 select 和 update 有可能不在一个事务中吧 |
5 zjj19950716 2022-11-01 18:13:59 +08:00 考虑 redis 的 incr 吗 |
![]() | 6 wushigejiajia01 2022-11-01 18:14:35 +08:00 上锁呗 |
![]() | 7 F281M6Dh8DXpD1g2 2022-11-01 18:16:05 +08:00 你的隔离级别是啥 盲猜你得改成 rc |
8 optional 2022-11-01 18:19:37 +08:00 不会没开启事务吧,另外楼上说的对,得改成 rc 级别 mysql 默认记得是 rr |
9 thinkershare 2022-11-01 18:19:42 +08:00 加读写锁, 或者使用版本戳,乐观并发并发冲突后抛异常重试。 |
10 chenqh 2022-11-01 18:26:30 +08:00 直接用 redis 锁吧,mysql 搞那么复杂干嘛? |
![]() | 11 xuanbg 2022-11-02 09:55:53 +08:00 1 楼已经给了正确答案 |