一尘不染

避免MySQLdb的“命令不同步;您不能立即运行此命令”(2014年)例外

mysql

以下代码,使用python 2.6.6和MySQLdb 1.2.2导致 命令不同步; 您不能立即运行此命令 MySQLdb异常:

import MySQLdb

conn = MySQLdb.connect( db="test", user="root" )
cursor = conn.cursor( MySQLdb.cursors.DictCursor )

cursor.execute( "BEGIN; CREATE TABLE t1 ( t1_id INT PRIMARY KEY AUTO_INCREMENT ); COMMIT;" )
cursor.execute( "BEGIN; CREATE TABLE t2 ( t2_id INT PRIMARY KEY AUTO_INCREMENT ); COMMIT;" )

在执行第二个查询期间引发异常。如我所读,异常通常是由MySQL的C API实现的限制引起的,该限制不允许并发查询执行。

如果我在上述两个查询之间重新创建游标对象,则会解决此问题,但不幸的是,该解决方案对我而言似乎并不完美。对于数据库连接和查询执行,我有一个非常简单的摘要,并且宁愿不要在每次查询执行后重新创建游标,因为它将(据我所知)会提交当前事务并可能产生其他副作用。

因此,我的问题是:避免此异常的其他方法有哪些?如何准备游标对象以执行下一个查询?也许Python DB
API期望有某种方法,当使用其他数据库接口时该方法相对中性,并且在MySQLdb的情况下可以解决该问题?

预先感谢您的时间和帮助:)

编辑: 发布问题后,我开始阅读Python DB API规范以了解游标破坏的副作用(我不太确定事务提交是否足够:)),然后发现以下替代解决方法:

cursor.execute( "BEGIN; CREATE TABLE t1 ( t1_id INT PRIMARY KEY AUTO_INCREMENT ); COMMIT;" )
while cursor.nextset() is not None: pass
cursor.execute( "BEGIN; CREATE TABLE t2 ( t2_id INT PRIMARY KEY AUTO_INCREMENT );

问题是我不知道它是做什么的(它返回1两次,然后返回None)。我应该深入研究这个方向吗?我的意思是,我应该了解这些集合的概念以找到解决问题的方法吗?


阅读 381

收藏
2020-05-17

共1个答案

一尘不染

DB-API尝试自行处理事务,在第一个命令上启动事务,并拥有自己的API调用来提交它,因此:

cursor.execute( "CREATE TABLE t1 ( t1_id INT PRIMARY KEY AUTO_INCREMENT )" )
cursor.commit()
cursor.execute( "CREATE TABLE t2 ( t2_id INT PRIMARY KEY AUTO_INCREMENT )" )
cursor.commit()

在我看来,这是Python DB-
API的一个严重的,明显的设计错误,这使得在事务之外执行命令并对事务进行适当控制变得非常麻烦。使用类似SQLite的东西BEGIN EXCLUSIVE TRANSACTION。就像没有真正数据库经验的人被允许设计API一样…

2020-05-17