情景: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 2020-03-14 12:14:55 +08:00
虽然没太看明白整个需求...
不过操作 mysql 避免脏读什么的一般我也就三个套路: 锁写缓存读, 偶尔用队列, 重要操作丢给事务... |
2
littlewing 2020-03-14 12:31:02 +08:00 via iPhone
串行化隔离级别 (手动狗头)
|
3
vcent OP @littlewing 还有其他方法么 在代码层面解决的
|
4
vcent OP @ClericPy 😂我以为我说清了,就是根据 where 条件用 limit 先取第一条数据 然后在更新这条数据,并发了就会发生后者覆盖前者的数据,就是这么个问题 。。。
|
5
vanillaxxx 2020-03-14 13:30:07 +08:00 via iPhone
乐观锁了解一下
|
6
boobo 2020-03-14 13:40:18 +08:00
楼主不知道悲观锁和乐观锁么?
去了解下... |
7
neoblackcap 2020-03-14 13:44:07 +08:00
当你将锁竞争放在数据库解决的时候,你已经错了。特别是你用的数据库不是 Oracle 跟 SQL Server,那更加是错上加错。
你自己在外部建一个队列以及一个进程,只有这个进程才能读写数据库,不比你这样的锁竞争快? |
8
fmumu 2020-03-14 13:50:32 +08:00 via Android
乐观锁就好了
|
9
whalegao 2020-03-14 17:55:47 +08:00 via iPhone
上周一个同事就这么搞的 sql。 然后活锁了
|
10
CStarter 2020-03-14 19:17:07 +08:00 via Android
表加一个 version 字段,查出 id version,更新的时候
set version=version+1 where version = 原值 如果更新失败表明有线程改动了,可以 for 循环处理 select update,设定最大次数 |
12
vcent OP @neoblackcap 多谢🙏
|
13
piglei 2020-03-14 22:39:34 +08:00 via Android
搜索:select for update
供参考。 |