Python MySQLdb не ждет результата

Я пытаюсь выполнить некоторые запросы, которые должны создать некоторые временные таблицы, а затем вернуть набор результатов, но я не могу сделать это с API MySQLdb.

Я уже копал что-то об этой проблеме, например здесь, но безуспешно.

Мой запрос выглядит так:

 create temporary table tmp1
 select * from table1;

 alter tmp1 add index(somefield);

 create temporary table tmp2
 select * from table2;

 select * from tmp1 inner join tmp2 using(somefield);

Это немедленно возвращает пустой набор результатов. Если я зайду в клиент mysql и сделаю show full processlist, я увижу выполнение моих запросов. Их выполнение занимает несколько минут. Почему курсор возвращается немедленно и не ждет выполнения запроса.

Если я попытаюсь выполнить другой запрос, у меня появится сообщение «Команды не синхронизированы, вы не можете запустить эту команду сейчас».

Я уже пытался поставить свое соединение с autocommit на True

db = MySQLdb.connect(host='ip',
                 user='root',
                 passwd='pass',
                 db='mydb',
                 use_unicode=True
    )
db.autocommit(True)

Или поместить каждое утверждение в собственное cursor.execute() и между ними db.commit(), но тоже безуспешно.

Можете ли вы помочь мне понять, в чем проблема? Я знаю, что mysql не поддерживает транзакции для некоторых операций, таких как изменение таблицы, но почему API не ждет, пока все не будет завершено, как это происходит с select?

Кстати, я пытаюсь сделать это на ноутбуке ipython.


person balsagoth    schedule 12.11.2013    source источник
comment
Фиксация должна выполняться дескриптором базы данных, а не курсором. db.commit() в приведенном выше коде. Это ты пробовал?   -  person erobbins    schedule 13.11.2013
comment
Да это опечатка. Когда я делаю db.commit(), я получаю ошибку синхронизации.   -  person balsagoth    schedule 13.11.2013


Ответы (1)


Я подозреваю, что вы передаете свою строку SQL с несколькими операторами непосредственно функции cursor.execute. Дело в том, что каждое из утверждений является самостоятельным запросом, поэтому неясно, что должен содержать результирующий набор.

Вот пример, чтобы показать, что я имею в виду. Первый случай - это передача набора операторов с точкой с запятой в execute, что, как я полагаю, у вас есть в настоящее время.

def query_single_sql(cursor):
    print 'query_single_sql'
    sql = []
    sql.append("""CREATE TEMPORARY TABLE tmp1 (id int)""")
    sql.append("""INSERT INTO tmp1 VALUES (1)""")
    sql.append("""SELECT * from tmp1""")

    cursor.execute(';'.join(sql))
    print list(cursor.fetchall())

Вывод:

query_single_sql
[]

Вы можете видеть, что ничего не возвращается, хотя в таблице явно есть данные и используется SELECT.

Во втором случае каждый оператор выполняется как независимый запрос, и результаты печатаются для каждого запроса.

def query_separate_sql(cursor):
    print 'query_separate_sql'
    sql = []
    sql.append("""CREATE TEMPORARY TABLE tmp3 (id int)""")
    sql.append("""INSERT INTO tmp3 VALUES (1)""")
    sql.append("""SELECT * from tmp3""")
    for query in sql:
        cursor.execute(query)
        print list(cursor.fetchall())

Вывод:

query_separate_sql
[]
[]
[(1L,)]

Как видите, мы использовали результаты курсора для каждого запроса, и окончательный запрос имеет ожидаемые результаты.

Я подозреваю, что даже если вы выдали несколько запросов, API имеет дескриптор только первого выполненного запроса и поэтому сразу же возвращается, когда CREATE TABLE выполняется. Я бы предложил сериализовать ваши запросы, как описано во втором примере выше.

person Austin Phillips    schedule 13.11.2013
comment
Да ты прав. За несколько мгновений до того, как вы опубликуете правильный ответ, я смог выполнить все запросы отдельно. Каким-то образом, когда я пробовал это раньше, у меня были ошибки, возможно, из-за использования старого соединения. Я очистил все (даже соединения mysql), и мне даже не нужно было делать промежуточные коммиты. - person balsagoth; 13.11.2013