SQLite PRAGMA 与配置调优详解
详解 SQLite PRAGMA 语句的全部常用参数:journal_mode(删除/wal/内存)、synchronous、cache_size、page_size、temp_store、auto_vacuum、foreign_keys、busy_timeout、wal_autocheckpoint、mmap_size、locking_mode、user_version 等,含默认值、设置语法与实测效果。基于 SQLite 3.53.4 实时环境实测。
SQLite PRAGMA 与配置调优详解
目标:掌握 SQLite 通过
PRAGMA语句查看与调整数据库运行时行为的全部常用参数。PRAGMA 是 SQLite 特有的配置指令,可直接在命令行或程序内执行,用于控制事务模式、缓存、并发、外键、内存映射等。本文所有默认值、设置语法与效果均在 SQLite 3.53.4 环境实测。
环境信息
| 信息项 | 值 |
|---|---|
| SQLite 版本 | 3.53.4(源码编译) |
| 操作系统 | Ubuntu 22.04.5 LTS |
| 演示库 | /tmp/p.db(磁盘库) |
一、PRAGMA 基本用法
PRAGMA 有两种形态:
- 标量查询:
PRAGMA 参数;返回当前值。 - 设置:
PRAGMA 参数=值;或PRAGMA 参数(值);。 - 部分参数还以表值函数形式提供:
SELECT * FROM pragma_xxx;(如pragma_journal_mode、pragma_cache_size)。
示例:
PRAGMA journal_mode; -- 查看
PRAGMA journal_mode=WAL; -- 设置
SELECT * FROM pragma_journal_mode; -- 表值形式
设置仅对当前连接生效(除非是 journal_mode、page_size 等持久化到数据库文件头部的参数)。
二、核心参数详解(含默认值与实测)
下表为 3.53.4 磁盘库(新建)的实测默认值:
| PRAGMA | 默认值 | 说明 |
|---|---|---|
journal_mode | delete(磁盘)/ memory(内存库) | 提交前 WAL 日志模式 |
synchronous | 2(FULL) | 落盘同步级别 |
cache_size | -2000(2000 页 ≈ 8 MB) | 页面缓存大小;负数为 KB,正数为页数 |
page_size | 4096 | 逻辑页大小(字节) |
temp_store | 0(DEFAULT) | 临时表/排序文件存放 |
auto_vacuum | 0(NONE) | 自动回收删除空间 |
foreign_keys | 0(OFF) | 外键约束开关 |
read_uncommitted | 0 | 读未提交隔离 |
busy_timeout | 0 | 写锁等待毫秒数 |
journal_size_limit | -1(无限) | 日志文件大小上限 |
wal_autocheckpoint | 1000 | WAL 自动 checkpoint 页数 |
locking_mode | normal | 锁模式:normal/exclusive |
mmap_size | 0 | 内存映射大小限制 |
secure_delete | 0(OFF) | 删除覆盖原数据 |
user_version | 0 | 用户自定义版本号 |
integrity_check | ok | 检查库完整性 |
quick_check | ok | 快速完整性检查 |
三、常用调优参数详解
3.1 journal_mode(日志模式)
delete(默认):事务用回滚日志文件,提交后删除,多写者并发受限。wal:预写式日志,读与写并发更好,写性能高,推荐多读少写或要求并发读的场景。memory:日志放内存,最快但崩溃可能丢数据。off:完全关闭日志,最快但最不安全。
查看与切换(切换是持久化的):
PRAGMA journal_mode; -- delete
PRAGMA journal_mode=WAL; -- 返回 wal
PRAGMA wal_autocheckpoint; -- 1000
实测切换输出:
delete
wal
1000
启用 WAL 后目录下会多出 -wal 与 -shm 两个文件。
⚠️ 在 WAL 模式下,只有一个写入者;无法同时打开两个客户端向同一 WAL 库写入。可通过
PRAGMA busy_timeout缓解写等待。
3.2 synchronous(同步级别)
可选 0(OFF) / 1(NORMAL) / 2(FULL) / 3(EXTRA):
OFF(0):完全不等待落盘,最快但崩溃可能丢失最近提交。NORMAL(1):大多数情况安全,WAL 模式下故障几乎不丢。FULL(2)(默认):每次提交等落盘,最安全。EXTRA(3):更进一步,极端谨慎。
PRAGMA synchronous; -- 2
PRAGMA synchronous=NORMAL; -- 1
调优建议:WAL + NORMAL 是"高写并发 + 可接受少量丢失"的常见组合;需严格持久化用 FULL。
3.3 cache_size(页面缓存)
缓存页数;当值为负时表示 KB(-2000 ≈ 2000 KB = 8 MB 于 4096 页),为正是页数(2000 ≈ 2000 页 = 8 MB)。
PRAGMA cache_size; -- -2000
PRAGMA cache_size=-8000; -- 8 MB(-8000 KB)
PRAGMA cache_size=8000; -- 8000 页
调大缓存可显著提升重复查询性能,尤其配合 mmap 使用。
3.4 page_size(页面大小)
只能在空库上在建表前设置,例如 PRAGMA page_size=8192;。较大的页面减少大 BLOB/长行随机 IO。
3.5 temp_store(临时文件)
0DEFAULT:默认(内存映射/页文件)1FILE:用磁盘临时文件2MEMORY:全部用内存
PRAGMA temp_store=2; -- 排序放内存,更快但更占内存
3.6 auto_vacuum(自动回收)
0NONE(默认):删除后文件不自动缩小。1FULL:自动回收空间回尾部。2INCREMENTAL:配合PRAGMA incremental_vacuum;手动回收。
必须在建表前设置,否则需 VACUUM 重建。
3.7 foreign_keys(外键约束)
默认关闭。需显式在每个连接开启,否则外键失效:
PRAGMA foreign_keys=ON;
⚠️ 它不是持久化的,每条连接都要开。应用层可每次建立连接执行。
3.8 busy_timeout(写锁等待)
等待被占用锁的毫秒数,避免并发写立刻报 database is locked:
PRAGMA busy_timeout=3000; -- 等待 3 秒
3.9 mmap_size(内存映射)
把数据库映射进地址空间,加速只读访问:
PRAGMA mmap_size=268435456; -- 256 MB
映射大小受 PRAGMA max_mmap_size 限制,-1 表示按需。
3.10 wal_autocheckpoint(WAL 自动检查点)
WAL 文件累积到 N 页时自动执行 checkpoint,把日志合并回主库。默认 1000;设 0 关闭(需要手动 PRAGMA wal_checkpoint;)。
PRAGMA wal_autocheckpoint=1000;
PRAGMA wal_checkpoint(PASSIVE); -- 手动 checkpoint
3.11 user_version(用户版本标记)
用作 schema 版本号做迁移管理:
PRAGMA user_version=3;
PRAGMA user_version; -- 3
3.12 完整性检查
PRAGMA integrity_check; -- ok(库损坏时输出错误列表)
PRAGMA quick_check; -- ok
损坏时 integrity_check 会列出损坏页,常用于备份恢复后校验。
四、实测:默认值一览
统一查看当前库各参数默认值:
PRAGMA journal_mode;
PRAGMA synchronous;
PRAGMA cache_size;
PRAGMA page_size;
PRAGMA temp_store;
PRAGMA auto_vacuum;
PRAGMA foreign_keys;
PRAGMA busy_timeout;
PRAGMA journal_size_limit;
PRAGMA wal_autocheckpoint;
PRAGMA locking_mode;
PRAGMA mmap_size;
PRAGMA secure_delete;
PRAGMA user_version;
实测输出(3.53.4 新建磁盘库):
delete
2
-2000
4096
0
0
0
0
-1
1000
normal
0
0
0
五、生产环境推荐组合
针对「高并发读 + 可接受少量写丢失」的典型服务:
PRAGMA journal_mode=WAL; -- 读多写少,允许并发读
PRAGMA synchronous=NORMAL; -- WAL 下安全且更快
PRAGMA busy_timeout=5000; -- 写竞争等待 5 秒
PRAGMA cache_size=-16384; -- 16 MB 缓存
PRAGMA mmap_size=536870912; -- 512 MB 内存映射
PRAGMA foreign_keys=ON; -- 每次连接开启
针对「严格持久化」的可靠性要求:
PRAGMA journal_mode=DELETE; -- 或 WAL
PRAGMA synchronous=FULL; -- 每次提交落盘
PRAGMA busy_timeout=3000;
六、常见问题(FAQ)
1. 设置了 journal_mode 为何重启后又变回?
换存储介质或新连接不继承未持久化参数。journal_mode 是持久化到库文件的;synchronous、busy_timeout、foreign_keys 等只对当前连接,需在每次连接重设(应用里写初始化 SQL)。
2. 报 database is locked?
另一个连接正持有写锁。设置 PRAGMA busy_timeout=3000; 让本连接等待锁释放。
3. 想回收文件大小但 DELETE 没变小?
默认 auto_vacuum=NONE,删除只标记空闲页不缩小文件。执行 VACUUM; 或改为 INCREMENTAL 后 PRAGMA incremental_vacuum;。参考《SQLite 备份与恢复指南》中 VACUUM 章节。
4. PRAGMA 的英文词大小写敏感吗?
不敏感,PRAGMA/pragma 均可,参数名也大小写不敏感。
七、小结
PRAGMA 是 SQLite 配置与调优的唯一入口:journal_mode/synchronous/cache_size/mmap_size 决定读写性能与并发,busy_timeout/locking_mode 处理锁竞争,foreign_keys 保证数据完整性,integrity_check/quick_check 校验健康状态。结合《SQLite 命令行与工具详解》与《SQLite 备份与恢复指南》可组成完整运维闭环。