SQLite WAL模式,后台线程上的检查点,wal-journal永远不会缩小

时间:2014-03-26 21:52:23

标签: python multithreading sqlite journal

SQLite文档说(here)您可以通过在单独的线程上运行检查点来避免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检查点没有帮助 - 那么检查点只是失败。

如何让它真正起作用? Desiderata是:1)主线程永远不必等待,2)日志文件不会无限制地增长。

1 个答案:

答案 0 :(得分:4)

检查点需要锁定整个数据库,因此必须阻止所有其他读取和写入。 (被动检查点只是中止。)

因此,在单独的线程中运行检查点不会增加并发性。 (SQLite文档建议这只是因为主线程可能不会设计为在空闲时刻处理检查点。)

如果您持续访问数据库,则无法检查点。 如果您的批处理操作使WAL文件变得太大,您应该在该循环中插入显式检查点(或依赖于autocheckpointing)。