pymysql 如何避免高并发处理同一条数据问题 谢大佬

2020-03-14 11:53:26 +08:00
 vcent

情景: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” 情况略有改善,但问题并没解决。

请问大佬,该如何彻底解决这种情况呢?谢谢!!🙏

3131 次点击
所在节点    Python
13 条回复
ClericPy
2020-03-14 12:14:55 +08:00
虽然没太看明白整个需求...

不过操作 mysql 避免脏读什么的一般我也就三个套路: 锁写缓存读, 偶尔用队列, 重要操作丢给事务...
littlewing
2020-03-14 12:31:02 +08:00
串行化隔离级别 (手动狗头)
vcent
2020-03-14 13:14:22 +08:00
@littlewing 还有其他方法么 在代码层面解决的
vcent
2020-03-14 13:18:10 +08:00
@ClericPy 😂我以为我说清了,就是根据 where 条件用 limit 先取第一条数据 然后在更新这条数据,并发了就会发生后者覆盖前者的数据,就是这么个问题 。。。
vanillaxxx
2020-03-14 13:30:07 +08:00
乐观锁了解一下
boobo
2020-03-14 13:40:18 +08:00
楼主不知道悲观锁和乐观锁么?
去了解下...
neoblackcap
2020-03-14 13:44:07 +08:00
当你将锁竞争放在数据库解决的时候,你已经错了。特别是你用的数据库不是 Oracle 跟 SQL Server,那更加是错上加错。
你自己在外部建一个队列以及一个进程,只有这个进程才能读写数据库,不比你这样的锁竞争快?
fmumu
2020-03-14 13:50:32 +08:00
乐观锁就好了
whalegao
2020-03-14 17:55:47 +08:00
上周一个同事就这么搞的 sql。 然后活锁了
CStarter
2020-03-14 19:17:07 +08:00
表加一个 version 字段,查出 id version,更新的时候
set version=version+1 where version = 原值

如果更新失败表明有线程改动了,可以 for 循环处理 select update,设定最大次数
vcent
2020-03-14 20:54:42 +08:00
@CStarter 多谢
vcent
2020-03-14 20:55:45 +08:00
@neoblackcap 多谢🙏
piglei
2020-03-14 22:39:34 +08:00
搜索:select for update
供参考。

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

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

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

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

© 2021 V2EX