
情景:A 表有个字段 status 值为 1 或 0 默认值 0 需求:首先 select 表 A 获取 status=0 的记录,但是弱水三千只取一条,然后 update 这条记录。 第一步我用了 ”select id from A where status=0 limit 0,1“ 语法,拿到 id 后 update。
问题:这样在甲乙两用户同时请求下不可避免的发生了数据错误,随后将第一步换成了“select id from A where status=0 limit 0,1 for update” 情况略有改善,但问题并没解决。
请问大佬,该如何彻底解决这种情况呢?谢谢!!
1 ClericPy Mar 14, 2020 虽然没太看明白整个需求... 不过操作 mysql 避免脏读什么的一般我也就三个套路: 锁写缓存读, 偶尔用队列, 重要操作丢给事务... |
2 littlewing Mar 14, 2020 via iPhone 串行化隔离级别 (手动狗头) |
3 vcent OP @littlewing 还有其他方法么 在代码层面解决的 |
4 vcent OP @ClericPy 我以为我说清了,就是根据 where 条件用 limit 先取第一条数据 然后在更新这条数据,并发了就会发生后者覆盖前者的数据,就是这么个问题 。。。 |
5 PEPEXXX Mar 14, 2020 via iPhone 乐观锁了解一下 |
6 boobo Mar 14, 2020 楼主不知道悲观锁和乐观锁么? 去了解下... |
7 neoblackcap Mar 14, 2020 当你将锁竞争放在数据库解决的时候,你已经错了。特别是你用的数据库不是 Oracle 跟 SQL Server,那更加是错上加错 你自己在外部建一个队列以及一个进程,只有这个进程才能读写数据库,不比你这样的锁竞争快? |
8 fmumu Mar 14, 2020 via Android 乐观锁就好了 |
9 whalegao Mar 14, 2020 via iPhone 上周一个同事就这么搞的 sql。 然后活锁了 |
10 CStarter Mar 14, 2020 via Android 表加一个 version 字段,查出 id version,更新的时候 set version=version+1 where version = 原值 如果更新失败表明有线程改动了,可以 for 循环处理 select update,设定最大次数 |
12 vcent OP @neoblackcap 多谢 |
13 piglei Mar 14, 2020 via Android 搜索:select for update 供参考。 |