Skip to content

[storage] The newly created index.db actually ends up with auto_vacuum=0: this pragma is placed after journal_mode=WAL, | [storage] 新建的 index.db 实际是 auto_vacuum=0:这条 pragma 排在 journal_mode=WAL 之后,--vacuum incremental 什么都回收不了 #6323

Open

Description

@BBleae

结论

storagePragmas() 先设 WAL、后设 auto_vacuum,所以新建的 index.db 文件头里是 auto_vacuum = 0(跑一次完整的 VACUUM 之前都是),--vacuum incremental 跑成功但一页都不回收。只影响磁盘占用,不丢数据、不损坏数据。

版本

master 的 c26c31a(2026-11-11)。已发布的 0.1.213 在 dist/ 里也是同样的 pragma 顺序。

现象

src/storage/schema.ts 里的 storagePragmas() 第一条是 PRAGMA journal_mode = WAL,最后一条才是 PRAGMA auto_vacuum = INCREMENTAL。

SQLite 只在数据库文件还是空的时候才认 auto_vacuum。切到 WAL 时已经写了第 1 页,所以在全新的 index.db 上,后面那条 auto_vacuum 被静默忽略,文件头里留着 auto_vacuum = 0。

auto_vacuum = 0 时,PRAGMA incremental_vacuum 什么也不做。而 gc({ vacuum: "incremental" })、bili storage gc --vacuum incremental 和 ?vacuum=incremental 背后执行的正是这条语句。

影响

复现

只用 SQLite,不涉及项目代码:

import { DatabaseSync } from "node:sqlite";
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

const dir = mkdtempSync(join(tmpdir(), "av-"));
const orders = {
    "wal-first": ["PRAGMA journal_mode = WAL", "PRAGMA auto_vacuum = INCREMENTAL"],
    "auto_vacuum-first": ["PRAGMA auto_vacuum = INCREMENTAL", "PRAGMA journal_mode = WAL"],
};
for (const [name, order] of Object.entries(orders)) {
    const db = new DatabaseSync(join(dir, `${name}.db`));
    for (const p of order) db.exec(p);
    db.exec("CREATE TABLE t (x BLOB)");
    const ins = db.prepare("INSERT INTO t VALUES (zeroblob(100000))");
    for (let i = 0; i < 100; i++) ins.run();
    db.exec("DELETE FROM t");
    db.exec("PRAGMA incremental_vacuum");
    const n = (p) => Object.values(db.prepare(`PRAGMA ${p}`).get())[0];
    console.log(`${name}: auto_vacuum=${n("auto_vacuum")} page_count=${n("page_count")} freelist_count=${n("freelist_count")}`);
    db.close();
}

输出(Node 22,node:sqlite):

wal-first: auto_vacuum=0 page_count=2452 freelist_count=2450
auto_vacuum-first: auto_vacuum=2 page_count=3 freelist_count=0

在 master 上走 UnifiedStore(写入 20 个会话、全部删掉,再 gc({ vacuum: "incremental" })):auto_vacuum=0,前后都是 431 页,其中 392 页在空闲页链表上,文件大小不变。

建议的修法

把 PRAGMA auto_vacuum = INCREMENTAL 放到 PRAGMA journal_mode = WAL 前面。随后提 PR。

已有的库在跑一次完整的 VACUUM 之前仍是 auto_vacuum = 0;要不要提示已有安装的用户(在 gc 输出里加一行,或在 README 里加一句),请维护者定。

相关:#3463、#3901、#3911、#4612。

Activity

  1. changed the title [-][storage] 新建的 index.db 实际是 auto_vacuum=0:这条 pragma 排在 journal_mode=WAL 之后,`--vacuum incremental` 什么都回收不了[/-] [+][storage] The newly created index.db actually ends up with auto_vacuum=0: this pragma is placed after journal_mode=WAL, | [storage] 新建的 index.db 实际是 auto_vacuum=0:这条 pragma 排在 journal_mode=WAL 之后,`--vacuum incremental` 什么都回收不了[/+] on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions