43

Pythonから実行されるMySQLストアドプロシージャがあります(Djangoでラップされています)。2番目のステートメントを実行しようとすると、「コマンドが同期していません。このコマンドを今すぐ実行できません」というエラーが表示されます。この時点ではトランザクションをコミットできません。これは、プロシージャを呼び出すときにのみ問題になります。何をすべきか?

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 ;
4

5 に答える 5

62

問題を解決した JoshuaBoshi の回答に感謝します。プロシージャを呼び出した後、別のステートメントを実行するためにカーソルを使用する前に、カーソルを閉じてから再度開く必要がありました。

cursor.close() 

cursor = connection.cursor() 

の直後にカーソルを閉じることができますfetchall()。結果セットはまだ残っており、ループすることができます。

于 2012-07-21T07:21:40.983 に答える
17

この主な原因は、新しいクエリが作成される前にカーソルから取得されなかった結果です。複数の結果セットが存在する場合があります。

エラーを停止するには、.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()

私の場合、これは実際には、後続のクエリが作成されるまで Python エラーとして選択されない SQL クエリの他の問題の指標になる可能性があることがわかりました。複数の結果セットが生成されました。

これを以下の例 (同じエラーが発生した場所) に適用すると、

>>> 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

ここで - 解析エラー (コードで改ざんされた信頼できる入力データ) がそのセミコロンと新しいステートメントにつながるため、これにより複数の結果セットが生成されました。このステートメントではエラーは発生しませんが、カーソルでコマンドを実行しようとする次のステートメントではエラーになります。

これを実証およびテストするために、https://github.com/odmsolutions/mysql_python_out_of_sync_demoという github リポジトリを作成しました。


元の回答: 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 クライアントで実行してみてください。

于 2013-09-04T15:48:07.153 に答える
4

これは Python の問題ではなく、mysql の問題です。perl から同じことをすると、同じエラーが発生します。一般に、mysql コンソールを実行し、別のコンソールからそれを強制終了し、強制終了されたコンソールからクエリを実行しようとすると、このメッセージが表示されます。

何かがステートメント間の接続を切断しています。手順に誤りがある可能性があります。mysql エラー ログを確認します。

于 2012-07-20T16:17:50.730 に答える
2

次の 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()を介して実行されました

于 2016-02-27T00:33:07.250 に答える