SQL Alchemy Relationship loader deja un candado en la mesa?

Tengo un código muy simple que hace que mi db MySQL se cuelgue:

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' 

Parece que SQL Alchemy no libera un locking de metadatos después de emitir la consulta de selección necesaria para cargar un atributo de relación. ¿Cómo puedo conseguirlo para lanzarlo? ¡Ni siquiera entiendo por qué una statement de selección tendría que bloquear la tabla en primer lugar!

Por supuesto, puedo hacer que funcione este código específico cerrando la sesión, pero eso no es práctico en mi progtwig real.

.drop_all() iniciar una nueva transacción antes de la llamada .drop_all() ; MySQL te ve leer de la tabla en esta transacción y bloquea la tabla para evitar que se caiga:

 session.commit() Base.metadata.drop_all() 

Cometer una transacción implícitamente comienza una nueva transacción.

MySQL garantiza el aislamiento de las transacciones; su transacción leerá datos consistentes y no verá cambios confirmados por otras transacciones hasta que inicie una nueva transacción. Sin embargo, una statement DROP TABLE hace que MySQL no pueda mantener estas garantías, por lo que la tabla se está bloqueando.

Alternativamente, puede alterar el nivel de aislamiento de la transacción y decirle a MySQL que no le importan las garantías de aislamiento. Debido a que las conexiones de sesión están agrupadas, esto solo se puede hacer para todas las conexiones o ninguna; use el argumento isolation_level para create_engine() :

 engine = create_engine( 'mysql://username:passwd@localhost/databasename', isolation_level='READ UNCOMMITTED') 

Consulte la documentación de SET TRANSACTION para obtener detalles sobre cada nivel de aislamiento.