SQLite文档说(这里)您可以通过在单独的线程上运行检查点来避免wal模式下的检查点暂停。我试过了,它似乎不起作用:' -wal
'文件增长没有绑定,目前还不清楚是否有任何东西实际上被复制回主数据库文件,并且(最重要的)-wal
文件已经足够大(超过千兆字节)后,主线线程开始等待检查指针。
在我的应用程序中,主线程不断地做一些本质上等同于此的事情,其中generate_data
将吐出要插入的一百万行的顺序:
db = sqlite3.connect("database.db")
cursor = db.cursor()
cursor.execute("PRAGMA wal_autocheckpoint = 0")
for datum in generate_data():
# It is a damned shame that there is no way to do this in one operation.
cursor.execute("SELECT id FROM strings WHERE str = ?", (datum.text,))
row = cursor.fetchone()
if row is not None:
id = row[0]
else:
cur.execute("INSERT INTO strings VALUES(NULL, ?)", (datum.text,))
id = cur.lastrowid
cursor.execute("INSERT INTO data VALUES (?, ?, ?)",
(id, datum.foo, datum.bar))
batch_size += 1
if batch_size > batch_limit:
db.commit()
batch_size = 0
,检查点线程这样做:
db = sqlite3.connect("database.db")
cursor = db.cursor()
cursor.execute("PRAGMA wal_autocheckpoint = 0")
while True:
time.sleep(10)
cursor.execute("PRAGMA wal_checkpoint(PASSIVE)")
(在不同的线程上,它们必须有单独的连接到数据库,因为pysqlite不支持在多个线程之间共享连接。)更改为FULL或RESTART检查点没有帮助-然后检查点失败。
我如何使它实际工作?期望的是:1)主线程永远不会等待,2)日志文件不会在没有绑定的情况下增长。
检查点需要锁定整个数据库,因此必须阻塞所有其他读和写操作。(被动检查点会终止)
所以在单独的线程中运行检查点不会增加并发性。(SQLite文档建议这样做只是因为主线程可能没有设计成在空闲时刻处理检查点。)
如果您持续访问数据库,则无法检查点。如果批处理操作使WAL文件变得太大,则应该在该循环中插入显式检查点(或依赖于自动检查点)。