V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
vcent
V2EX  ›  Python

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

  •  
  •   vcent · 2020-03-14 11:53:26 +08:00 · 3113 次点击
    这是一个创建于 1726 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    13 条回复    2020-03-14 22:39:34 +08:00
    ClericPy
        1
    ClericPy  
       2020-03-14 12:14:55 +08:00
    虽然没太看明白整个需求...

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

    如果更新失败表明有线程改动了,可以 for 循环处理 select update,设定最大次数
    vcent
        11
    vcent  
    OP
       2020-03-14 20:54:42 +08:00
    @CStarter 多谢
    vcent
        12
    vcent  
    OP
       2020-03-14 20:55:45 +08:00
    @neoblackcap 多谢🙏
    piglei
        13
    piglei  
       2020-03-14 22:39:34 +08:00 via Android
    搜索:select for update
    供参考。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3423 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:52 · PVG 19:52 · LAX 03:52 · JFK 06:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.