SQLite 的 WAL 模式与并发写

2026 / 10 / 09#sqlite#并发#wal

默认模式的问题

SQLite 默认用 rollback journal:写事务进行时,数据库文件被锁,读也得排队。单用户无所谓,几个人同时访问就能感觉到卡。

WAL 改了什么

PRAGMA journal_mode=WAL; 之后,修改先写入 -wal 文件,读操作从"已提交的快照"读,所以:

  • 读不阻塞写
  • 写不阻塞读
  • 同一时刻仍然只有一个写者

最后一条是很多人误解的地方。WAL 解决的是"读写互相排队",不是"支持并行写"。第二个写入者会等待,超时就报 SQLITE_BUSY。

必配的两个参数

PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
  • busy_timeout:拿不到写锁时最多等多久(毫秒),而不是立刻失败。不设这个,稍微并发一下就报错。
  • synchronous = NORMAL:WAL 模式下通常足够安全(断电可能丢最后一个事务,但不会损坏数据库),换来明显的写性能提升。要求零丢失再改回 FULL。

什么时候够用,什么时候不够

场景 判断
单机、内网几个人用 完全够
读多写少的管理系统 很合适
高频写入(每秒几十次以上) 谨慎,考虑换 PostgreSQL
多台服务器同时访问同一个库文件 不行,文件锁跨网络不可靠

备份别直接 cp

WAL 模式下直接复制 .sqlite 文件会漏掉 -wal 里未合并的数据,甚至拷到写一半的状态。正确做法:

sqlite3 app.db ".backup 'backup.db'"
# 或
sqlite3 app.db "VACUUM INTO 'backup.db';"

这两条都在数据库连接层面做一致性快照,可以一边服务一边备份。

本文为个人学习记录,可能存在错误或已过时,仅供参考。
← 返回笔记列表