sqlalchemy + mysql死锁

时间:2011-03-16 11:07:28

标签: python mysql sqlalchemy

我将带有随机数据的行插入到mysql数据库中。插入一些行后,greenlet挂起连接。统计打印greenlet一直在运行

任何数量的工作者(包括一个)都会发生这种情况,包括mysql-connector和mysqldb驱动程序。 sqlite工作正常。

This没有效果(据我所知,它已在新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:root@localhost/junk')
main(1, 'mysql+mysqlconnector://root:root@localhost/junk')

发生了什么事?


重新测试,错误在没有gevent的情况下仍然存在,可能是服务器配置

1 个答案:

答案 0 :(得分: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'