SQLite WAL 模式踩坑笔记:高并发读写下的几个细节

最近把一个内部服务的存储从 PostgreSQL 换成 SQLite + WAL 模式,跑了一个多月,遇到几个不太显眼但挺关键的坑,记录一下。

为什么用 WAL

默认的 rollback journal 模式在写事务期间会阻塞所有读,对我们这种"读多写少但读不能停"的场景非常不友好。WAL(Write-Ahead Logging)的好处是:

  • 读和写互不阻塞

  • 多个读事务可以并发执行

  • 写性能在多数场景下更好

开启方式很简单:

```sql

PRAGMA journal_mode=WAL;

```

这个 pragma 是持久的,设一次后数据库文件本身的 header 就改了,下次连接不用重设。

坑 1:`-shm` 和 `-wal` 文件不能漏

WAL 模式下数据库会变成三个文件:

```

mydb.sqlite

mydb.sqlite-shm

mydb.sqlite-wal

```

备份脚本如果只复制主文件,恢复出来的数据会是上次 checkpoint 时的状态,**最近的写会全部丢**。正确做法是先调用 `PRAGMA wal_checkpoint(TRUNCATE);` 把 WAL 落盘清空,再复制主文件。或者直接用 SQLite 的在线备份 API(`sqlite3_backup_init`)。

坑 2:`busy_timeout` 必须显式设

WAL 不是万能的。写事务之间还是互斥的,如果两个进程同时尝试写,后来的会立即拿到 `SQLITE_BUSY`。默认 busy handler 直接返回错误,应用层就要写一堆重试逻辑。更好的做法是:

```sql

PRAGMA busy_timeout=5000;

```

这样 SQLite 会在内部等待最多 5 秒,期间持续重试拿写锁。注意这是**每个连接**都要单独设的,不会从某个全局配置继承。

坑 3:长读事务会让 WAL 无限增长

WAL checkpoint 只能 checkpoint 那些已经被所有 reader 看完的页。如果有一个长读事务一直挂着(比如一个忘记关掉的 cursor),WAL 文件会持续增长,永远 checkpoint 不掉。我们生产环境出现过 WAL 涨到 30GB 的情况。

排查方法是查看 `PRAGMA wal_checkpoint(PASSIVE);` 的返回值,第一个数字是 WAL 中的总页数,第二个是已 checkpoint 的页数,第三个是已 checkpoint 但还没复用的页数。如果第二个长期远小于第一个,就说明有 reader 卡住。

坑 4:`synchronous=NORMAL` vs `FULL`

WAL 模式下默认的 `synchronous=FULL` 仍然会在每次提交都 fsync WAL 文件,性能损失比较大。官方文档明确说:在 WAL 模式下用 `NORMAL` 是安全的,崩溃恢复仍然能保证一致性,只是断电瞬间最后那个事务可能丢失。

```sql

PRAGMA synchronous=NORMAL;

```

我们的测试里这个改动让批量插入吞吐量提升了大概 3 倍。

总结

切到 WAL 之后整体延迟和并发表现都好了很多,但 SQLite 的"省心"是建立在你理解它内部行为的前提下的。建议至少把 `journal_mode`、`busy_timeout`、`synchronous`、`wal_autocheckpoint` 这几个 pragma 的语义看一遍再上生产。

相关推荐
苍何12 小时前
免费版 Typeless来了,不限额度,夯!
后端
“AI国潮设计-小江”12 小时前
【Python/SDXL实战】潮汕国潮IP视觉落地:普宁英歌舞猫IP & 创意甜品设计(附ComfyUI工作流与商业授权说明)
开发语言·人工智能·python·prompt·aigc
529宝宝起名网12 小时前
用 Python 分析汉字字源与起名用字的关联规律:从六书结构到文化寓意的起名偏好洞察
开发语言·python
linx29513 小时前
单元九 · 零基础路线图-第 7–9 周·类与 RAII
c语言·开发语言·数据结构·c++·嵌入式硬件·算法
Charlie_Byte13 小时前
Integer 缓存机制(JDK 17 源码)
后端
梨涡泥窝13 小时前
JavaWeb——基于 Spring Boot + Vue 的图书管理系统的设计与实现
vue.js·spring boot·后端
白色的北极熊14 小时前
c语言 输出菱形字符串
c语言·开发语言
jsl_jsl_jsl14 小时前
LLM工具调用速记
后端
YIAN14 小时前
手撸社区后端:一套可落地的用户 - 文章 - 互动体系 MySQL 表设计与优化思路
后端·mysql
学习智者14 小时前
《玄》IDE v3.6.3重磅发布:全功能修复与性能飞跃
开发语言·c++·ide·算法·中文语言 玄