来源:
notes/documents/干掉_SQLite_的可行性调研:Web_预览与事实源两条线.md干掉 SQLite 的可行性调研:Web 预览与事实源两条线
结论
分两条线看,可行性完全不同。
| 线 | 指的是什么 | 可行性 | 建议 |
|---|---|---|---|
| Web 侧 | 本地预览的日程读接口去读 SQLite | 可行,且是删代码(约 40 行) | 先做 |
| 工作区事实源 | data/daily_log.sqlite3 整个干掉,Neon 当权威源 |
技术上做得到,但推翻两条已定 ADR,涉及 71 个文件 | 现在不做 |
一句话:SQLite 不是历史包袱,它现在是「离线采集」与「不可重建台账」这两件事的唯一载体。 Neon 能替代读取面,替代不了这两件。
现状:SQLite 到底在扛什么
2026-09-26 实测 data/daily_log.sqlite3,2.0 MB,13 个表/视图:
| 表/视图 | 行数 | 性质 |
|---|---|---|
events / event_revisions / event_tags |
298 / 299 / 766 | 事件线与它的历史 |
notes / note_revisions |
125 / 317 | 笔记注册表(正文不落库) |
note_path_aliases |
71 | 改名过的旧链接 |
note_topics / note_sources / sources |
83 / 4 / 39 | 笔记与来源的关联 |
projection_state / entity_projection_state |
789 / 1709 | 各目的地台账(远端 target_id、projected revision、失败原因) |
calendar_entries(视图) |
400 | 日历取合规则的唯一实现,DDL 在 scripts/calendar_entries.py |
代码面:
- 71 个文件引用
event_store或daily_log.sqlite3。scripts/event_store.py1133 行是唯一的写入实现 (SQLiteEventStore);scripts/sync_to_feishu_base.py1380 行、scripts/note_cli.py651 行、26 个测试文件。 - 采集是硬依赖:cc-connect
/note→ Go worker →personal_assistant/plugins/personal-assistant-sync/cmd/personal-assistant-sync/main.go:503直接exec python3 scripts/capture_event.py --database data/daily_log.sqlite3。 - 线上不依赖它:笔记走构建产物(
web/docs/adr/0008),日程走 Neon 投影(web/docs/adr/0011)。 SQLite 只出现在本机与本地预览两处。
真正不可重建的只有三类:笔记身份(note_id 与路径别名)、各目的地台账、revisions 历史。
事件正文与笔记正文都不在库里。
方案 A:Web 预览不再读 SQLite(建议先做)
现状里有一处已经和文档不符:web/scripts/lib/ts-alias-hook.mjs:31 只要在本地预览进程里,就把
backend/src/lib/daily-store.ts 换成 preview-daily-store.mjs——于是预览的日程接口无条件读本地
SQLite,跟 DATABASE_URL 配没配无关;而 web/scripts/local-preview.mjs:167 仍按 DATABASE_URL
打印 daily api: live / unavailable,这句话已经不成立。
改动三处:
- 删
web/scripts/lib/preview-daily-store.mjs(35 行)。 - 删
ts-alias-hook.mjs里的那条 swap 分支,预览直接跑真实的daily-store.ts。 - 更新
web/docs/operations.md的「本地预览」一节,并删掉「投影时别让本地预览开着」那个坑: 预览不再持有数据库文件,就不会再撞database is locked。
代价:预览的日程模块从此需要 DATABASE_URL(.env.local 里已有)与网络。
收益:Web 侧对 SQLite 的依赖清零(local-daily-events.mjs 只服务投影,仍是必需),
预览看到的就是线上真正读的那份数据。
方案 B:Neon 当权威源(不建议现在做)
四条具体阻碍:
- 采集会变成联网写。
docs/adr/0011当初否掉这条路,理由就是「捕获从此依赖网络」—— 断网或 Neon 抖动等于记不下来。 - 隐私边界要重新划。 ADR 0011 只投影
internal/public,private不上网。Neon 当源之后,private要么也进第三方库,要么另留一份本地存储,那就等于没干掉。当前库里 298 条事件全是internal,但这条规则是写死过的。 - 工具链有缺口。 本机 Python 3.12.4 没有 Postgres 驱动(
psycopg/psycopg2都 import 失败), 而写入路径全在 Python;26 个测试现在跑InMemoryEventStore(sqlite :memory:), 换引擎需要一个本地 docker 或 Neon 分支。 - 备份语义要重做。 现在数据库跟着代码进 git,迁移前备份就是
cp;搬走要重建 PITR, 以及AGENTS.md「Storage Principle」里「迁移前先备份」那条流程。
真搬过去能得到的好处也是真的:灭掉 git 里的 2 MB 二进制与 AGENTS.md 里那段「SQLite 冲突按 union
merge」的人工规则;灭掉两台机器靠 commit 同步数据库、以及持锁那类并发坑;台账本来就是
「不可重建的状态进数据库」说的那种状态,进 Postgres 是顺的。
要做就分档:
| 档 | 做什么 | 保留什么 |
|---|---|---|
| 一档 | 只搬台账(projection_state / entity_projection_state)与笔记注册表(notes / note_path_aliases / note_revisions) |
事件与 revisions 留本地 |
| 二档 | 全搬,并给采集加重试队列 + 本地降级(离线先落本地队列,联网补写) | 这才谈得上「干掉」 |
下一步动作
- 方案 A:删 swap 与
preview-daily-store.mjs,改operations.md两处。约 40 行删除,风险低。 - 先决定两台机器同步
data/daily_log.sqlite3的方式是否还要保留——它决定方案 B 走一档还是二档。 - 真要做方案 B 之前先出一份 spec:把 71 个文件按「必须联网 / 可留本地」分档再估工期, 本文「现状」一节可直接当输入。
参考
- 工作区:
docs/adr/0003(SQLite 作为每日记录事实源)、docs/adr/0004(revision 化的增量投影与台账) - 网页版:
web/docs/adr/0008(不可重建的进数据库,可重建的进构建产物)、web/docs/adr/0011(日程走数据库投影) - 网页版:
web/docs/operations.md的「日程投影」与「本地预览」两节