Python SQL炼金术关系加载器在表上留下锁?

Python SQL炼金术关系加载器在表上留下锁?,python,mysql,sqlalchemy,Python,Mysql,Sqlalchemy,我有非常简单的代码导致MySQL数据库挂起: import sqlalchemy as sa from sqlalchemy import orm # creating the engine, the base, etc import utils import config utils.base_init(config) Base = config.Base class Parent(Base): __tablename__ = 'Parents' id = sa.Colu

我有非常简单的代码导致MySQL数据库挂起:

import sqlalchemy as sa
from sqlalchemy import orm

# creating the engine, the base, etc
import utils
import config

utils.base_init(config)
Base = config.Base

class Parent(Base):
    __tablename__ = 'Parents'
    id = sa.Column(sa.Integer, primary_key=True)
    children = orm.relationship('Child', backref='parent')

class Child(Base):
    id = sa.Column(sa.Integer, primary_key=True)
    parent_id = sa.Column(sa.Integer)

    __tablename__ = 'Children'

    __table_args__ = (sa.ForeignKeyConstraint(
        ['parent_id'],
        ['Parents.id'],
        onupdate='CASCADE', ondelete='CASCADE'),{})

Base.metadata.create_all()

session = orm.sessionmaker(bind=config.Base.metadata.bind)()
p = Parent(id=1)
c1 = Child(id=1)
c2 = Child(id=2)
session.add(p)
session.add(c1)
session.add(c2)
session.commit()

# Works
# Base.metadata.drop_all()

c1.parent
# 2012-08-17 20:16:21,459 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
# 2012-08-17 20:16:21,460 INFO sqlalchemy.engine.base.Engine SELECT `Children`.id AS `Children_id`, `Children`.parent_id AS `Children_parent_id` 
# FROM `Children` 
# WHERE `Children`.id = %s
# 2012-08-17 20:16:21,460 INFO sqlalchemy.engine.base.Engine (1,)



Base.metadata.drop_all()
# hangs until i kill the connection above.
# server status: 'Waiting for table metadata lock'
在发出加载关系属性所需的select查询后,SQL Alchemy似乎没有释放元数据锁?我怎样才能让它释放它?我甚至不明白为什么select语句首先需要锁定表


当然,我可以通过关闭会话来实现这段特定的代码,但这在我的实际程序中并不实用。

在调用
.drop\u all()
之前,需要启动一个新的事务;MySQL看到您在此事务中从表中读取数据,并锁定该表以防被删除:

session.commit()
Base.metadata.drop_all()
提交事务隐式地开始新事务

MySQL保证事务隔离;您的事务将读取一致的数据,并且在启动新事务之前不会看到其他事务提交的更改。然而,
DROP TABLE
语句使MySQL无法保持这些保证,因此表被锁定

或者,您可以更改事务隔离级别,告诉MySQL您不关心隔离保证。由于会话连接是池连接,因此只能对所有连接或根本没有连接执行此操作;使用
isolation\u level
参数:


有关每个隔离级别的详细信息,请参阅。

是否确定在
之前提交。drop_all()
调用?我在添加后提交。我刚刚尝试在select之后提交,它确实有效。不过有点让我震惊,为什么我需要在选择后提交?请参阅下面我的答案,了解原因,再加上解决方法。
engine = create_engine(
    'mysql://username:passwd@localhost/databasename',
    isolation_level='READ UNCOMMITTED')