【问题标题】:how to solve this deadlock with gevent and oursql如何用 gevent 和 oursql 解决这个死锁
【发布时间】:2013-03-21 09:56:21
【问题描述】:

我有一个复杂项目的以下代码:

from gevent import monkey
monkey.patch_all()
import gevent

import oursql

def run(num):
    conn = oursql.connect(host = ...)
    cursor = conn.cursor()
    cursor.execute('start transaction')
    for i in range(2):
        print num, i
        cursor.execute('UPDATE userobj SET timestamp=(timestamp + 1) WHERE id = 1')
        gevent.sleep()

    cursor.execute('rollback')


proc = [gevent.spawn(run, i) for i in range(2)]
gevent.wait(proc)

引擎是InnoDB,输出是:

0 0
1 0

然后程序挂起。我知道原因是mysql在第一个greenlet执行更新语句后锁定了行,所以另一个greenlet中的更新会阻塞。但是为什么 gevent 在另一个阻塞套接字之后不将控制权转移回第一个 greenlet 呢?我想知道除了在gevent.sleep之前使用锁或提交之外,还有什么优雅的解决方案吗?

附言 原来的情况是在一个网站项目中。我混合了 pymongo 和 SQLAlchemy 操作,并使用 gunicorn 为站点提供服务。但我发现并行请求可能会永远阻塞。调试了半天,终于发现这是因为pymongo使用了一些socket操作,导致gevent切换到另一个greenlet,导致死锁,如上代码所示。

谢谢!

【问题讨论】:

  • 看起来oursql是使用Cython/C实现的,并且使用libmysqlclient,所以它不兼容gevent和monkey补丁(补丁Python库,而不是外部C/C++库)。 This seems to confirm my suspicion.
  • @robertklep 是的,你是对的:) 我以前看过那个页面,在替换列中看到了 oursql,认为它应该是兼容的。但是刚才发现oursql其实就是oursql.so……
  • 该页面比较混乱,但是在它的末尾有一条评论指出oursql与gevent不兼容。

标签: python deadlock gevent oursql


【解决方案1】:

感谢@robertklep,一种可能的解决方案是将oursql 替换为一些纯python 驱动程序,例如pymysql。事实上oursql 是用C 编写的,因此与gevent 不兼容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 2021-06-06
    • 2020-01-24
    相关资源
    最近更新 更多