2011-03-16 3 views
3

J'insère des lignes avec des données aléatoires dans la base de données mysql. Après l'insertion de quelques lignes, greenlet se bloque lors de la connexion. Les statistiques d'impression de greenlet continuent de tournersqlalchemy + deadlocks mysql

Cela se produit avec n'importe quel nombre de travailleurs (dont un), à la fois avec les pilotes mysql-connector et mysqldb. sqlite fonctionne très bien.

This n'a pas d'effet (comme je comprends qu'il est déjà fixé dans la nouvelle gevent)

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') 

Qu'est-ce qui se passe?


retesté, sans erreur persiste gevent, probablement quelque chose avec la configuration du serveur

+0

Juste pour confirmer, est-ce que «Un nombre quelconque de travailleurs» comprend exactement 1 travailleur? – Romain

+0

Oui (question fixe) – ymv

Répondre

1

Je viens oublié de libérer les connexions utilisées, de sorte que les connexions où jamais en arrière le check-in dans la piscine. ...

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'