很多人看到"SQLite 开了 WAL 就能扛并发",默认它现在能跟 Postgres 一样接住一堆写请求。这是个误会。WAL 确实治好了老毛病——写堵读、读堵写,但它没打算解决另一件事:同一时刻,SQLite 仍然只允许一个写事务存在。第二个写请求撞上来,不排队,直接收到 SQLITE_BUSY。
这不是"配置没调好"的问题,是架构本身的边界。SQLite 能不能上生产,真正要看的是负载:是不是单节点、是不是读多写少、数据量是不是装得下一块盘。这三条成立,你换来的是低延迟;不成立,你要自己扛下备份、故障转移和临时磁盘失效的责任。
速读:WAL 治好了读写打架,没治好写写打架
- 默认模式下,写堵读、读堵写.WAL 把写操作挪到独立的
.sqlite-wal文件,读写从此互不阻塞。 - 但写和写之间没这待遇.两个写事务同时到,一个拿锁,另一个立刻收到
SQLITE_BUSY。 busy_timeout让第二个写请求先等一会儿再重试,BEGIN IMMEDIATE提前占锁、避免两个连接互相干等死锁——都是缓解手段,不是消除写竞争的开关。- 写多的场景,单写者上限迟早显形。
配置边界:参数要按负载实测,不是抄一份清单
检查点(checkpoint)把 WAL 内容合并回主库,防止文件无限膨胀。但只要有活跃的长读事务占着旧页面,PASSIVE 检查点就合不进去,WAL 照样涨。journal_size_limit 只能限制文件大小上限,拦不住它涨——真正要处理的是那个不肯结束的长读事务。
synchronous = NORMAL 能省掉每次提交同步磁盘的开销,在 WAL 模式下也不会导致数据库文件损坏。但完整性和持久性是两件事:完整性没问题,持久性会打折扣。服务器一旦崩溃,还没落盘的已提交事务可能丢失。这笔账要提前算,不是"绝对安全"四个字能盖过去的。
mmap 也不等于"整个数据库常驻内存"。它只是把文件映射交给操作系统页缓存去管,数据库大小超过 mmap_size,该从磁盘读的还是要读。
| 工具 | 复制机制 | 适用场景 |
|---|---|---|
| Litestream | 复制 WAL 增量帧 | 单机持续备份、灾难恢复 |
| LiteFS | 主要基于 FUSE 拦截文件系统操作 | 多副本读扩展,云上是否使用取决于具体平台承诺 |
两者机制不同,不能都归成"VFS 层"打包讲。云环境下用不用它们,要看具体平台的持久化承诺,不是一律强制。
本地盘换来的低延迟,把备份、故障转移、临时磁盘失效的风险也一并转移给了应用方自己。
两类读者:上线前分别要做什么
后端和基础设施工程师最该问的,不是这篇文章说得对不对,是上线前有没有测过这四件事:
- 压测真实写入并发,看
SQLITE_BUSY出现的频率,而不是理论上会不会出现。 - 手写
busy_timeout重试逻辑,并且真的验证过——SQLite 不保证退避策略,重试节奏要自己设计。 - 定期做一次真实的备份恢复演练,而不是只确认备份文件存在。
- 监控 WAL 文件大小趋势和检查点执行情况,不要等磁盘写满才发现问题。
评估单机架构的技术负责人,决策点在写入增长曲线,不在今天的 QPS 数字。
| 信号 | 还能用 SQLite | 该考虑迁移 |
|---|---|---|
| 写入来源 | 单节点写入 | 需要多地域同时写入 |
| 高可用要求 | 可接受分钟级故障切换 | 需要秒级 SLA |
| 数据规模 | 装得进一块本地盘 | 持续增长,单机存不下 |
| 写竞争 | SQLITE_BUSY 偶发 | 频繁出现,重试队列开始堆积 |
这张表不是选型公式,是筛子。任何一行滑到右边,继续留在 SQLite 上,承担的就不再是"性能取舍",而是"故障半径"。
接下来真正该盯的不是 SQLite 本身的版本更新,是团队自己的写入曲线:写入 QPS 每周涨多少,busy_timeout 重试率有没有抬头,WAL 文件峰值有没有越来越难压平。这三条同时往上走,就是该迁移到 client-server 数据库的信号,不必等到服务整体卡死才反应。
我的判断:这是架构取舍,不是 PRAGMA 点石成金
"天下大势,分久必合,合久必分。"数据库这几十年也是这个套路——大型机时代数据集中一处,client-server 架构把"合"制度化;现在 NVMe 和边缘部署让本地存取变便宜,SQLite 被重新提起,走的是"分"的方向。这个类比不完全一样,今天的推力是硬件成本,不是治乱循环,顶多三成像。但架构在集中和分散之间来回摆,这个规律没变。
低延迟是真的,账也是真的。本地读通常能比经网络访问的数据库快出一个数量级,具体数字取决于硬件和负载,没有放之四海而皆准的基准,不该被当成人人适用的承诺。
SQLite 适合的场景很具体:单节点、读多写少、数据量装得进一块盘。这些条件成立,省掉网络往返换来的低延迟就是实打实的收益。条件不成立——需要跨地域写入、需要强 SLA 的高可用——client-server 数据库仍然是对的工具。
先问自己是不是单节点、读多写少、数据量装得下一块盘,再决定要不要为这份低延迟接下运维责任。省下来的每一毫秒,最终都要在这份责任清单里找平。
