避免MySQLdb“命令不同步;现在无法运行此命令”异常的方法
下面的代码在使用 Python 2.6.6 和 MySQLdb 1.2.2 时,会出现一个错误:命令不同步;你现在不能运行这个命令。
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 数据库 API 期望的,这种方法在使用其他数据库接口时相对中立,并且可以解决 MySQLdb 的问题?
提前感谢你的时间和帮助 :)
编辑: 在我发布问题后,我开始阅读 Python 数据库 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
)。我应该朝这个方向深入研究吗?我的意思是,我是否应该理解这些集合的概念,以找到解决我问题的方法?
1 个回答
10
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一样……