2016-07-14 385 views
8

使用SQLAlchemy的查询MySQL数据库,我收到以下错误:忽略锁定在MySQL数据库中的SQLAlchemy查询

sqlalchemy.exc.OperationalError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (_mysql_exceptions.OperationalError) (1205, 'Lock wait timeout exceeded; try restarting transaction')

首先,我认为错误消息的评论“考虑使用session.no_autoflush块如果此刷新过早发生“是关于放置锁的其他会话,而不是我用于当前查询的会话?如果我遵循这个建议,这将有助于避免在数据库上锁定一般?其次,我只需要阅读并不需要对查询结果进行修改,所以我想知道如何忽略锁并只读数据库中的当前内容。我相信SQL是NOWAIT,但我没有看到在sqlalchemy API中如何做到这一点。

+0

请提供所涉及的SQL语句(在两个连接上),以及'SHOW CREATE TABLE'和'SHOW ENGINE = InnoDB STATUS;'(如果可能,当问题发生时)。从你提供的内容来看,我们不能说出它为什么锁定,还有很多其他重要细节。 –

+0

也提供有关sqlalchemy的“no_autoflush”的信息;我们需要弄清楚什么是MySQL构造。 –

+0

@RickJames没有SQL构造underly [autoflush](http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush)。这正是SQLAlchemy会话处理状态的方式。如果会话有未挂起的更改尚未刷新到数据库(插入,更新,删除),则会在运行下一个查询(如果使用autoflush)之前将其刷新到数据库。但是,如果没有mcve,不能帮助OP,在某些查询正在使用锁定的某些内容之前,某事正在锁定某些内容并发出刷新... –

回答

1

假设您使用的是mysql.connectorautocommit属性的默认值为False,这可能会导致脚本因其他正在等待完成的会话而挂起。

SQLAlchemy使用BEGIN statements,(的START TRANSACTION化名)造成采集表/数据库锁定会话,并且您的连接将等到锁将得到批准。

为了克服这个问题(并且由于事实,你说你只需要在会议期间读取数据),您可以设置自动提交=真正的创建Session时:

Session = sessionmaker(bind=engine, autocommit=True) 

另一种选择 - 在你创建您可以执行SET AUTOCOMMIT=1会话:

s = Session() 
s.execute("SET AUTOCOMMIT=0") 

You can also try to set the autocommit property directly in the connection string:

engine = create_engine("mysql+mysqlconnector://user:[email protected]/dbname?autocommit=1") 

However I didn't test it. According to the documentations it should work.

+0

将欣赏任何解释任何投票 – Dekel

+1

提到的第一件事[在sqla文档](http:// docs。sqlalchemy.org/en/latest/orm/session_transaction.html#autocommit-mode)是:“**警告**”自动提交“模式不应被视为通用**。” –

+0

@IljaEverilä,autocommit = True实际上并不是一个好习惯,这就是为什么它在文档中被这样提及的原因,但是,如果不需要事务代码(例如只读脚本),它将会很多服务器使用autocommit = True进行交易更便宜。 SQLAlchemy对每个会话都有autocommit = False的事实并不总是这样的一个好习惯。而且 - 如果你使用的是MyISAM引擎,那么交易就没有意义了,那么autocommit = True就更好了。 – Dekel