Python / SQLite3: невозможно зафиксировать - ни одна транзакция не активна - PullRequest
16 голосов
/ 19 марта 2012

Я пытаюсь закодировать индексатор книг , используя Python (традиционный, 2.7) и SQLite (3).

Код сводится к следующей последовательности операторов SQL:

'select count(*) from tag_dict' ()
/* [(30,)] */
'select count(*) from file_meta' ()
/* [(63613,)] */
'begin transaction' ()
'select id from archive where name=?' ('158326-158457.zip',)
/* [(20,)] */
'select id from file where name=? and archive=?' ('158328.fb2', 20)
/* [(122707,)] */
'delete from file_meta where file=?' (122707,)
'commit transaction' ()
# error: cannot commit - no transaction is active

Уровень изоляции - «ОТЛОЖЕН» («ИСКЛЮЧИТЕЛЬНО» не лучше).

Я пытался использовать connection.commit () вместо cursor.execute ('commit') - ничего полезного не произошло.

  • Конечно, я искал stackoverflow и Сеть, но найденные ответы не имеют значения.
  • Автокоммит режим недопустим по причинам производительности.
  • Я использую единственный файл базы данных одновременно.
  • Мой код выполняется в одном потоке.
  • Все выполнение SQL выполняется с помощью одной функции, которая гарантирует, что у меня не более только один открытый курсор за раз.

Итак, что не так с транзакцией здесь?

Если я использую connection.commit () (примечание: нет метода connection.begin!), Тогда я просто потеряю свои данные.

Конечно, я проверил двойные / тройные / d права доступа к файлу базы данных и его директории.


Ну, как это часто бывает, я нашел решение всего через несколько минут после постановки вопроса.

Как новичок, я не могу ответить на свой вопрос в течение 8 часов ... Итак, ответ теперь есть:

Решение было найдено здесь и состоит из единственной идеи:

Никогда не используйте BEGIN / COMMIT в режиме без автоматической фиксации в приложении Python - используйте только db.commit () и db.rollback ()!

Звучит странно, но работает.

Ответы [ 3 ]

12 голосов
/ 20 марта 2012

Ну, как это часто бывает, я нашел решение всего через несколько минут после постановки вопроса.

Решение было найдено здесь и состоит из единственной идеи:

Никогда не используйте BEGIN / COMMIT в неавтоматическом режиме в приложении Python - используйте только db.commit () и db.rollback ()!

Звучит странно, но работает.

3 голосов
/ 27 августа 2013

Это довольно поздний ответ, но, возможно, взгляните на APSW , если вы хотите более точный контроль над транзакциями.Я провел несколько тестов с отложенными транзакциями, включающими чтение по pysqlite, и, похоже, он работает неправильно.

0 голосов
/ 11 декабря 2013
cursor=connection.cursor()
cursor.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
connection.commit()
...