複雑なプロジェクトから次のコードがあります。
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
その後、プログラムがハングします。その理由は、最初の greenlet が update ステートメントを実行した後に mysql が行をロックするため、他の greenlet の更新がブロックされることを知っています。しかし、gevent は、他のグリーンレットがソケットでブロックされた後、最初のグリーンレットに制御を戻さないのはなぜですか? そして、ロックを使用するか、前にコミットする以外に、適切な解決策があるのだろうgevent.sleep
か?
ps 元の状況は、Web サイト プロジェクトにあります。私は pymongo と SQLAlchemy の操作を混合し、gunicorn を使用してサイトにサービスを提供しました。しかし、並列リクエストが永久にブロックされる可能性があることがわかりました。長時間のデバッグの後、これは pymongo がいくつかのソケット操作を使用したためであることが最終的にわかりました。これにより、gevent が別の greenlet に切り替わり、上記のコードが示すようにデッドロックが発生しました。
ありがとう!