简体   繁体   English

Python/SQLite3:无法提交 - 没有活动的事务

[英]Python/SQLite3: cannot commit - no transaction is active

I'm trying to code a book indexer using Python (traditional, 2.7) and SQLite (3).我正在尝试使用 Python(传统,2.7)和 SQLite(3)编写书籍索引器

The code boils down to this sequence of SQL statements:代码归结为以下 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

The isolation level is 'DEFERRED' ('EXCLUSIVE' is no better).隔离级别是“DEFERRED”(“EXCLUSIVE”也好)。

I've attempted to use connection.commit() instead of cursor.execute('commit') - nothing useful happened.我尝试使用 connection.commit() 而不是 cursor.execute('commit') - 没有发生任何有用的事情。

  • Sure, I've searched stackoverflow and the Net, but the answers found are irrelevant.当然,我已经搜索过 stackoverflow 和网络,但找到的答案是无关紧要的。
  • Autocommit mode is unacceptable for performance reason.出于性能原因,自动提交模式是不可接受的。
  • I use the only database file at a time.我一次只使用一个数据库文件。
  • My code runs in single thread.我的代码在单线程中运行。
  • All the SQL execution is being done via single function that ensures that I have no more than only one cursor open at a time.所有 SQL 执行都是通过单个函数完成的,以确保我一次打开的游标不超过一个

So, what's wrong with transaction here?那么,这里的交易有什么问题呢?

If I use connection.commit() (note: there is no connection.begin method!), then I merely lose my data.如果我使用 connection.commit()(注意:没有 connection.begin 方法!),那么我只会丢失我的数据。

Sure, I've double/triple/d checked file permissions on the database file and its directory.当然,我已经双重/三重/d 检查了数据库文件及其目录的文件权限。

Well, as it often happens I found the solution just a minutes after posing the question.好吧,正如经常发生的那样,我在提出问题后仅几分钟就找到了解决方案。

The solution was found here and consists of the only idea:解决方案是在这里找到的,包括唯一的想法:

Never use BEGIN/COMMIT in non-autocommit mode in Python application - use db.commit() and db.rollback() only!切勿在 Python 应用程序的非自动提交模式下使用 BEGIN/COMMIT - 仅使用 db.commit() 和 db.rollback()!

It sounds odd, but it works.这听起来很奇怪,但确实有效。

This is a pretty late response, but perhaps take a look at APSW if you want finer-grain control over transactions.这是一个相当晚的响应,但如果您想要对事务进行更细粒度的控制,也许可以看看APSW I ran a few tests on deferred transactions involving reads on pysqlite, and it just doesn't seem to perform correctly.我对涉及 pysqlite 读取的延迟事务进行了一些测试,但它似乎无法正确执行。

cursor=connection.cursor()
cursor.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
connection.commit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM