Python Mysql,“命令不同步;您现在无法运行此命令”
Posted
技术标签:
【中文标题】Python Mysql,“命令不同步;您现在无法运行此命令”【英文标题】:Python Mysql, "commands out of sync; you can't run this command now" 【发布时间】:2012-07-19 22:48:51 【问题描述】:我有一个从 Python 执行的 mysql 存储过程(包装在 Django 中)。当我尝试执行第二条语句时,我收到错误“命令不同步;您现在无法运行此命令”。此时我无法提交交易。这只是我调用过程时的问题。怎么办?
cursor.callproc('my_mysql_procedure', [some_id,])
result = cursor.fetchall()
for r in result:
do something
cursor.execute("select * from some_table")
result = cursor.fetchall()
编辑:我被要求发布 MySQL 程序。我把它做得超级简单,但我仍然看到同样的问题
delimiter $$
create procedure my_mysql_procedure(p_page_id int)
begin
select 1
from dual;
end$$
delimiter ;
【问题讨论】:
发布您的存储过程代码。这就是问题所在 在 php 中,为了执行更多的 sql 代码,我必须在调用存储过程后清理/关闭游标。也许这是同一个问题。 JoshuaBoshi:这完全成功了,谢谢。 cursor.close() 然后再次打开: cursor = connection.cursor() 你想把它作为答案发布吗?select 1 from dual
是甲骨文主义;在 mysql 中,只需使用select 1
。
【参考方案1】:
感谢 JoshuaBoshi 的回答,解决了这个问题。调用该过程后,我不得不关闭游标并再次打开它,然后才能使用它执行另一条语句:
cursor.close()
cursor = connection.cursor()
光标可以在fetchall()
之后立即关闭。结果集仍然存在,可以循环访问。
【讨论】:
这没有意义 - 有谁知道为什么? 另外需要指出的是,MySQLDB/SQLAlchemy 不能为每个字符串处理多个查询。即“选择1;选择1”会导致这个问题。更糟糕的是,评论也可能导致这种情况!说真的!:“选择 1;--随便” 根据我的经验,我不需要在本地计算机上执行此操作,但是当我将代码移植到 pythonanywhere 时,我不得不这样做并且它工作了 (+1)。 mycursor.close() 然后 mycursor = mydb.cursor() 给我错误...“mysql.connector.errors.ProgrammingError: Cursor is not connected”。【参考方案2】:造成这种情况的主要原因是在进行新查询之前未从游标中获取结果。可能有多个结果集。
要停止错误,您必须确保每次都使用 .nextset 使用结果集。如果它产生多个结果集,您甚至可能需要做一些。
cursor.callproc('my_mysql_procedure', [some_id,])
result = cursor.fetchall()
for r in result:
do something
cursor.nextset()
cursor.execute("select * from some_table")
result = cursor.fetchall()
在我的例子中,我发现这实际上可以指示 sql 查询中的其他问题,这些问题在进行后续查询之前不会被选为 python 错误。他们产生了多个结果集。
将此应用于下面的示例(我看到相同的错误),
>>> import MySQLdb
>>> conn = MySQLdb.connect(passwd="root", db="test")
>>> cur = conn.cursor()
>>> cur.execute("insert into foo values (1););")
1L
>>> cur.nextset()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 107, in nextset
nr = db.next_result()
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
这里 - 因为解析错误(一些受信任的输入数据,被代码修改)导致该分号,然后是一个新语句 - 这产生了多个结果集。这条语句不会产生错误,但下一个试图在光标上运行命令的语句会产生错误。
我创建了一个 github 存储库 - https://github.com/odmsolutions/mysql_python_out_of_sync_demo - 来演示和测试这一点。
原答案: 看看https://github.com/farcepest/MySQLdb1/issues/28,详细了解我是如何用 3 行代码可靠地重现这一点的:
重现这个的最小案例: (假设你有一个空白数据库,并且只创建了一个到数据库的连接,称为 conn)
>>> conn.query("Create table foo(bar int(11))")
>>> conn.query("insert into foo values (1););")
>>> conn.query("insert into foo values (2););")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
_mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now")
生成的语法错误,从错误中我无法判断这是问题所在。
尝试按照 Bukzor 的建议检查最后一个查询或过程 - 并尝试在原始 mysql 客户端中运行它以查看真正的问题。
【讨论】:
您好,感谢您的推荐。我试过增加缓冲区大小,超时......我正在查询一个有时返回一个列表而不是一行的选择,然后执行 fetchone 似乎会在队列中留下行:O。您的回答对我有帮助,现在我在每个新查询之前执行 cur.nextset()。【参考方案3】:这不是python问题,而是mysql问题。从 perl 做同样的事情,你会得到同样的错误。通常,我在运行 mysql 控制台时看到该消息,然后从另一个控制台将其终止,然后尝试从终止的控制台运行查询。
有些东西正在扼杀你的陈述之间的联系。这可能是您的程序中的错误。检查你的mysql错误日志。
【讨论】:
【参考方案4】:我在运行以下 Python (2.7) 代码时遇到了这个错误:
def _execute(self, query, params, is_destructive):
try:
cursor = self.con.cursor()
cursor.execute(query, params)
if is_destructive:
self.con.commit()
return cursor.fetchall()
finally:
cursor.close()
问题源于 self.con.commit() 调用。我们是防御性的,并且在关闭游标之前进行了破坏性(写入)操作的编码。 MySql 不喜欢这样。删除调用的 commit() 解决了问题,脚本仍然通过 cursor.fetchall() 执行
【讨论】:
【参考方案5】:由于我现在已经用谷歌搜索了几次,登陆同一个 SO 问题(这里),但没有一个答案是有帮助的,这里是我未来的建议:
此错误是 MySQL 未获取响应的来源。也就是说,我们发送了请求,得到了一些东西,但并不关心阅读它。
req = "UPDATE data SET h1='qwertyuioasdasdasda' WHERE id=1;commit;"
在我的情况下,删除 commit
后,我能够看到这个错误:
Warning: (1265L, "Data truncated for column 'h1' at row 1")
它是因为我试图写h1
这对于数据类型来说太长了。但是,commit
阻止我取回这些信息。
【讨论】:
以上是关于Python Mysql,“命令不同步;您现在无法运行此命令”的主要内容,如果未能解决你的问题,请参考以下文章
Mysql 错误 #2014 - 命令不同步;您现在无法在存储过程中运行此命令