Python/SQLite3: невозможно зафиксировать - транзакция не активна
Я пытаюсь закодировать индексатор книг, используя 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()!
Звучит странно, но это работает.
Ответы
Ответ 1
Ну, как это часто бывает, я нашел решение через минуту после постановки вопроса.
Решение было найдено здесь и состоит из единственной идеи:
Никогда не используйте BEGIN/COMMIT в неавтоматическом режиме в приложении Python - используйте только db.commit() и db.rollback()!
Звучит странно, но работает.
Ответ 2
Это довольно поздний ответ, но, возможно, стоит взглянуть на APSW, если вы хотите более детальный контроль над транзакциями. Я провел несколько тестов по отложенным транзакциям, включающим чтение по pysqlite, и, похоже, он работает неправильно.
Ответ 3
cursor=connection.cursor()
cursor.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
connection.commit()