「SQLite 只适合做原型」这句话我信了很多年,直到我看见一个日 PV 三十万的站点跑在 SQLite 上,而且跑得很稳。
关键不是引擎,是模式¶
SQLite 默认配置偏向安全与省电,直接拿来跑 Web 会踩坑。真正需要改的只有三个参数:
PRAGMA journal_mode = WAL; -- 读写不互相阻塞
PRAGMA synchronous = NORMAL; -- WAL 下的性价比最优解
PRAGMA busy_timeout = 5000; -- 遇到写锁等 5 秒而不是立刻报错
journal_mode = WAL 是分水岭。默认的 rollback journal 模式下,写操作会锁住整库,读请求全部排队;切到 WAL 之后,读者完全不阻塞写者,这对博客这种「写一次读一万次」的场景几乎是量身定制。
一组实测数据¶
在我这台机器上,5000 篇文章、每张表都建了索引的情况下:
| 操作 | 平均耗时 |
|---|---|
| 首页列表查询(8 条 + count) | 0.42 ms |
| 按标签过滤 | 0.61 ms |
| 全文 LIKE 搜索 | 3.8 ms |
| 单篇详情 | 0.19 ms |
3.8 毫秒的 LIKE 搜索是最差的一项,但注意这是没有建任何全文索引的结果。真要做搜索,加一张 FTS5 虚拟表就能把它压到亚毫秒级:
CREATE VIRTUAL TABLE posts_fts USING fts5(title, summary, body, content='posts');
什么时候别用 SQLite¶
三条硬边界
- 多机部署。SQLite 的文件锁只在单机有效,一旦你的应用跑在两个容器里并且都要写,就必须换 Postgres。
- 高并发写入。WAL 只有一个写者,每秒几百次以上的持续写入会开始排队。
- 需要细粒度权限。SQLite 没有用户体系,谁拿到文件谁就是 root。
博客、内部看板、小型 SaaS 的元数据、边缘节点上的缓存——这些场景里 SQLite 不仅够用,而且因为没有网络往返,通常比同机的 Postgres 更快。
备份比你想的简单¶
因为整个数据库就是一个文件,备份可以退化成一行 shell:
sqlite3 blog.db ".backup '/backup/blog-$(date +%F).db'"
.backup 是官方推荐的在线备份方式,不需要停服,也不会破坏事务一致性。对比一下 pg_dump 加定时任务的组合,这种简单本身就是一种可靠性。