Python ", команды не синхронизированы, вы не можете запустить эту команду сейчас"

У меня есть хранимая процедура MySQL, которая выполняется из Python (завернутая в 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()

EDIT: меня попросили отправить процедуру MySQL. Я сделал это суперпростым, и я все еще вижу ту же проблему

delimiter $$
create procedure my_mysql_procedure(p_page_id int)
    begin

        select 1
        from dual; 

    end$$
delimiter ;

Ответ 1

Спасибо Джошуа Боши за его ответ, который решил проблему. После вызова процедуры мне пришлось закрыть курсор и снова открыть его, прежде чем использовать его для выполнения другого оператора:

cursor.close() 

cursor = connection.cursor() 

Курсор можно закрыть сразу после fetchall(). Результирующий набор все еще остается и может быть зациклен.

Ответ 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 repo - https://github.com/odmsolutions/mysql_python_out_of_sync_demo - чтобы продемонстрировать и проверить это.


Оригинальный ответ: Взгляните на https://github.com/farcepest/MySQLdb1/issues/28 для получения подробной информации о том, как я смог достоверно воспроизвести это с помощью трех строк кода:

Минимальный случай, чтобы воспроизвести это: (предположим, что у вас есть пустой db, и создали только соединение с db, называемое 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-клиенте, чтобы увидеть настоящую проблему.

Ответ 3

Я столкнулся с этой ошибкой при запуске следующего кода 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() разрешило проблему, а script все еще выполнялся с помощью cursor.fetchall()

Ответ 4

Это не проблема с python, а проблема mysql. Сделайте то же самое с perl, и вы получите ту же ошибку. В общем, я вижу это сообщение, когда запускаю консоль mysql, а затем убиваю его с другой консоли, а затем пытаюсь запустить запрос из убитой консоли.

Что-то убивает вашу связь между утверждениями. Вероятно, это ошибка в вашей процедуре. Проверьте журнал ошибок mysql.