2011-03-16 7 views
3

ランダムなデータを持つ行をmysqlデータベースに挿入します。いくつかの行を挿入した後、接続時にgreenletがハングします。統計情報を出力するグリーンレットの実行が続行するsqlalchemy + mysqlデッドロック

これは、mysql-connectorとmysqldbの両方のドライバを使用する任意の数のワーカー(1つを含む)で発生します。 sqliteは正常に動作します。何が起きている

def patch(): 
    from gevent import monkey 
    monkey.patch_all() 

    # fix https://bugs.launchpad.net/myconnpy/+bug/712037 
    from mysql.connector.connection import MySQLConnection 
    MySQLConnection.get_characterset_info = MySQLConnection.get_charset 
patch() 

from sqlalchemy import MetaData, Table, Column, Integer, String, create_engine 
from gevent import spawn, sleep 
from random import randrange 
from time import time 

class Stats(object): 
    def __init__(self): 
     self.inserts, self.faults = 0, 0 

    def run(self): 
     while True: 
      sleep(1) 
      print "%d %d %d" % (time(), self.inserts, self.faults) 
      self.inserts, self.faults = 0, 0 

class Victim(object): 
    metadata = MetaData() 
    Entry = Table(
     'entry', metadata, 
     Column('id', Integer, primary_key=True), 
     Column('junk', String(128), unique=True) 
    ) 

    def __init__(self, cs, stats): 
     self.e = create_engine(cs) 
     self.metadata.drop_all(self.e) 
     self.metadata.create_all(self.e) 
     self.stats = stats 

    def add(self, junk, i): 
     print i, 'connecting' 
     c = self.e.connect() 
     print i, 'connected' 
     t = c.begin() 
     try: 
      q = self.Entry.insert().values(junk=junk) 
      c.execute(q) 
      t.commit() 
      self.stats.inserts += 1 
     except Exception as e: 
      print i, 'EXCEPTION: ', e 
      t.rollback() 
      self.stats.faults += 1 
     print i, 'done' 

def flood(victim, i): 
    a, z, l = ord('a'), ord('z')+1, 100 
    while True: 
     victim.add(''.join(chr(randrange(a, z)) for _ in xrange(l)), i) 
     sleep(0) 

def main(n_threads, cs): 
    stats = Stats() 
    victim = Victim(cs, stats) 
    threads = [ spawn(flood, victim, i) for i in xrange(n_threads) ] 
    threads.append(spawn(stats.run)) 
    [t.join() for t in threads] 

#main(2, 'mysql://root:[email protected]/junk') 
main(1, 'mysql+mysqlconnector://root:[email protected]/junk') 

(私はそれはすでに新しいgeventに固定されて理解される)

This

は効果がありませんか?再試験を


、エラーはおそらく、geventせずに私はチェックされませ-で決してバックプールに接続して、使用する接続を解放するのを忘れサーバ構成

+0

"任意の数のワーカー"には正確に1人のワーカーが含まれていますか? – Romain

+0

はい(固定質問) – ymv

答えて

1

で何かを持続します。 ...

def add(self, junk, i): 
    print i, 'connecting' 
    c = self.e.connect() 
    ... 
    try: 
     ... 
    except Exception as e: 
     ... 
    finally: 
     c.close() # <-- this returns conenction into pool 
    print i, 'done' 
関連する問題