我有一个复杂项目的以下代码:
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
吗?
ps 原来的情况是在一个网站项目中。我混合了 pymongo 和 SQLAlchemy 操作,并使用 gunicorn 为站点提供服务。但我发现并行请求可能会永远阻塞。调试了半天,终于发现这是因为pymongo使用了一些socket操作,导致gevent切换到另一个greenlet,导致死锁,如上代码所示。
谢谢!