在 Sqlalchemy 查询中忽略 MYSQL 数据库中的锁

Posted

技术标签:

【中文标题】在 Sqlalchemy 查询中忽略 MYSQL 数据库中的锁【英文标题】:Ignore Lock in MYSQL Database in Sqlalchemy Query 【发布时间】:2016-11-17 19:59:11 【问题描述】:

使用 SQLAlchemy 查询 mysql 数据库我收到以下错误:

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 现在是现在,但我看不到如何在 sqlalchemy API 中执行此操作。

【问题讨论】:

请提供涉及的 SQL 语句(在两个连接上),以及SHOW CREATE TABLESHOW ENGINE=InnoDB STATUS;(如果可能,在问题发生时)。根据您提供的信息,我们无法判断它为何被锁定,也无法提供许多其他重要细节。 还提供有关 sqlalchemy 的“no_autoflush”的信息;我们需要弄清楚 MySQL 的内部构造是什么。 闻起来像是 SqlAlchemy 的味道妨碍了 对我来说,闻起来就像 OP 甚至不确定他们在做什么:“首先,我假设 ... 是关于另一个会话放置锁,而不是我正在使用的会话我当前的查询?”还有什么会议?如前所述:提供minimal, complete and verifiable example 会有所帮助。 或者也许得到一个合适的 DBMS,比如 PostgreSQL 无论如何***.com/questions/5836623/… 可能会有帮助 【参考方案1】:

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

要克服这种行为(并且由于您说您只需要在会话期间读取数据),您可以在创建会话时设置 autocommit=True:

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

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

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

你也可以尝试直接在连接字符串中设置autocommit属性:

engine = create_engine("mysql+mysqlconnector://user:pass@localhost/dbname?autocommit=1")

但是我没有测试它。根据文档,它应该可以工作。

【讨论】:

in the sqla documentation 提到的第一件事是:“警告“自动提交”模式不应被考虑用于一般用途。”跨度> @IljaEverilä, autocommit=True 真的不是一个好习惯,这就是为什么在文档中这样提到它的原因,但是,如果不需要事务代码(只读脚本,例如)服务器使用 autocommit=True 进行交易会便宜得多。 SQLAlchemy 对每个会话都有 autocommit=False 的事实并不总是这样的好习惯。此外 - 如果您使用的是 MyISAM 引擎,那么进行事务处理是没有意义的,自动提交=True 会更好。 有人可能会说使用 MyISAM 没有意义。处理事务可以对只读会话有益——想想可重复读取。这一切都取决于。总而言之,如果锁定事务在另一个会话中,自动提交在这里甚至没有帮助,因为自动提交只是一个短暂的事务。尽管 OP 说他们只读取,但在查询发出写入之前似乎是刷新。使用自动提交,刷新仍然发生在事务中。也许他们没有考虑就修改了一些实例,但我们无法知道。

以上是关于在 Sqlalchemy 查询中忽略 MYSQL 数据库中的锁的主要内容,如果未能解决你的问题,请参考以下文章

通过 sqlalchemy 映射类在 MySQL JSON 字段中插入键而不进行查询

使用 sqlalchemy 连接到 mysql 并查询

在 sqlalchemy 映射类构造函数中忽略额外关键字的选项?

需要帮助将带有自连接的 MySQL 查询转换为 SQLAlchemy

如何在flask-sqlalchemy查询最后一条记录

重试失败的 sqlalchemy 查询