SQLite 完全指南 / 10 - PRAGMA 配置
10 - PRAGMA 配置:journal_mode、synchronous、cache_size
10.1 PRAGMA 概述
PRAGMA 是 SQLite 特有的配置指令,用于控制数据库引擎的行为和查询数据库的内部状态。
10.1.1 语法
-- 设置值
PRAGMA name = value;
-- 查询值
PRAGMA name;
-- 列表形式(部分 PRAGMA 支持)
PRAGMA pragma_list;
10.1.2 PRAGMA 分类
| 类别 | 说明 | 示例 |
|---|---|---|
| 可写 PRAGMA | 可以设置值 | journal_mode, synchronous |
| 只读 PRAGMA | 只能查询 | page_count, freelist_count |
| 连接级 PRAGMA | 每个连接独立设置 | foreign_keys |
| 数据库级 PRAGMA | 持久存储在数据库中 | journal_mode, page_size |
10.2 核心 PRAGMA 详解
10.2.1 journal_mode(日志模式)
控制事务日志的模式。
-- 查看当前模式
PRAGMA journal_mode;
-- 设置模式
PRAGMA journal_mode = DELETE; -- 默认:事务后删除 journal
PRAGMA journal_mode = WAL; -- 推荐:写前日志
PRAGMA journal_mode = MEMORY; -- journal 保存在内存(不安全)
PRAGMA journal_mode = OFF; -- 无 journal(不安全)
PRAGMA journal_mode = TRUNCATE; -- 事务后截断 journal
PRAGMA journal_mode = PERSIST; -- 事务后保留 journal(标记为无效)
| 模式 | 安全 | 并发 | 性能 | 说明 |
|---|---|---|---|---|
DELETE | ✅ | 读写互斥 | 一般 | 默认,传统模式 |
WAL | ✅ | 读写并发 | 好 | 推荐使用 |
MEMORY | ❌ | — | 最快 | 崩溃可能丢数据 |
OFF | ❌ | — | 最快 | 完全无保护 |
TRUNCATE | ✅ | 读写互斥 | 较好 | 截断而非删除 |
PERSIST | ✅ | 读写互斥 | 较好 | 保留文件但标记无效 |
⚠️
MEMORY和OFF仅适用于临时数据或可丢数据的场景。
10.2.2 synchronous(同步模式)
控制 SQLite 将数据刷入磁盘的频率。
PRAGMA synchronous;
PRAGMA synchronous = FULL; -- 默认:每次提交都 fsync
PRAGMA synchronous = NORMAL; -- WAL 模式下推荐
PRAGMA synchronous = OFF; -- 最快,但崩溃可能丢数据
PRAGMA synchronous = EXTRA; -- 比 FULL 更严格
| 模式 | 安全性 | 性能 | 说明 |
|---|---|---|---|
FULL | 最高 | 一般 | 每次事务提交都 fsync |
NORMAL | 高 | 好 | WAL 模式下足够安全 |
OFF | 低 | 最快 | OS 崩溃可能丢数据(应用崩溃安全) |
EXTRA | 最高 | 最慢 | 比 FULL 更严格 |
-- ⚡ 高性能配置(WAL + NORMAL)
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
💡 WAL + NORMAL 是大多数场景的最佳组合——兼顾安全性和性能。
10.2.3 cache_size(缓存大小)
控制页面缓存的大小。
-- 查看当前缓存大小
PRAGMA cache_size;
-- 设置缓存大小(单位:页)
PRAGMA cache_size = 10000; -- 10000 页 × 4KB = ~40MB
-- 负值表示 KB
PRAGMA cache_size = -2000; -- 约 2MB 缓存
| 设置 | 内存使用 | 适用场景 |
|---|---|---|
2000(默认) | ~8MB | 一般应用 |
10000 | ~40MB | 中等负载 |
-50000 | ~50MB | 大量读取 |
100000 | ~400MB | 内存充足、大量查询 |
10.2.4 mmap_size(内存映射大小)
控制使用内存映射 I/O 的数据量。
-- 查看
PRAGMA mmap_size;
-- 设置(单位:字节)
PRAGMA mmap_size = 268435456; -- 256MB
-- 关闭内存映射
PRAGMA mmap_size = 0;
💡 内存映射可以显著加速大数据库的读取性能,但在高并发写入时可能不适用。
10.2.5 foreign_keys(外键约束)
-- 开启外键约束(默认关闭!)
PRAGMA foreign_keys = ON;
-- 查看状态
PRAGMA foreign_keys; -- 0=关闭, 1=开启
⚠️ 每次连接都需要设置——外键设置不会持久存储。
10.2.6 busy_timeout(忙等待超时)
-- 设置超时(毫秒)
PRAGMA busy_timeout = 5000; -- 等待 5 秒
-- 查看
PRAGMA busy_timeout;
10.3 数据库信息 PRAGMA
10.3.1 表和索引信息
-- 表信息
PRAGMA table_info(users);
-- cid | name | type | notnull | dflt_value | pk
-- 0 | id | INTEGER | 0 | NULL | 1
-- 1 | name | TEXT | 1 | NULL | 0
-- 2 | email | TEXT | 1 | NULL | 0
-- 完整表信息(包含外键、CHECK 约束等)
PRAGMA table_xinfo(users);
-- 索引列表
PRAGMA index_list(users);
-- seq | name | unique | origin | partial
-- 0 | sqlite_autoindex_users_1 | 1 | u | 0
-- 索引列信息
PRAGMA index_info(idx_users_email);
-- 外键信息
PRAGMA foreign_key_list(orders);
-- id | seq | table | from | to | on_update | on_delete | match
-- 0 | 0 | users | user_id | id | NO ACTION | CASCADE | NONE
10.3.2 数据库状态
-- 页面大小
PRAGMA page_size;
-- 页面数量
PRAGMA page_count;
-- 空闲页面数量
PRAGMA freelist_count;
-- 数据库大小计算
SELECT
page_count * page_size / 1024.0 AS size_kb,
freelist_count * page_size / 1024.0 AS free_kb,
(page_count - freelist_count) * page_size / 1024.0 AS used_kb
FROM pragma_page_count(), pragma_page_size(), pragma_freelist_count();
-- 数据库文件列表
PRAGMA database_list;
-- seq | name | file
-- 0 | main | /path/to/mydb.db
-- 2 | temp |
-- 编译选项
PRAGMA compile_options;
10.3.3 表统计
-- 表的行数估算(快速)
PRAGMA stats;
-- B-Tree 深度和单元格信息
PRAGMA btree_info; -- 需要特定编译选项
10.4 性能相关 PRAGMA
10.4.1 完整性能配置
-- ⚡ 生产环境推荐配置
PRAGMA journal_mode = WAL; -- WAL 模式
PRAGMA synchronous = NORMAL; -- WAL 配合 NORMAL
PRAGMA cache_size = -2000; -- 2MB 缓存
PRAGMA foreign_keys = ON; -- 开启外键
PRAGMA busy_timeout = 5000; -- 5 秒忙等待
PRAGMA wal_autocheckpoint = 1000; -- WAL 自动 checkpoint
PRAGMA temp_store = MEMORY; -- 临时表存内存
PRAGMA mmap_size = 268435456; -- 256MB 内存映射
10.4.2 批量导入配置
-- ⚡ 大量数据导入时的优化配置
PRAGMA journal_mode = WAL;
PRAGMA synchronous = OFF; -- 临时关闭同步
PRAGMA cache_size = 100000; -- 大缓存
PRAGMA temp_store = MEMORY;
PRAGMA locking_mode = EXCLUSIVE; -- 独占锁
PRAGMA mmap_size = 536870912; -- 512MB
BEGIN;
-- ... 大量 INSERT ...
COMMIT;
-- 恢复安全设置
PRAGMA synchronous = NORMAL;
PRAGMA locking_mode = NORMAL;
10.4.3 temp_store(临时表存储)
PRAGMA temp_store; -- 0=DEFAULT, 1=FILE, 2=MEMORY
PRAGMA temp_store = MEMORY; -- 临时表存内存(推荐)
| 值 | 说明 |
|---|---|
0 (DEFAULT) | 由编译选项决定 |
1 (FILE) | 临时表存储在磁盘临时文件 |
2 (MEMORY) | 临时表存储在内存中 |
10.4.4 locking_mode(锁模式)
PRAGMA locking_mode; -- NORMAL(默认)
PRAGMA locking_mode = EXCLUSIVE; -- 独占模式
| 模式 | 说明 |
|---|---|
NORMAL | 每次 SQL 完成后释放锁 |
EXCLUSIVE | 获取排他锁后保持,直到连接关闭 |
⚠️
EXCLUSIVE模式阻止所有其他进程访问数据库——仅适用于单进程场景。
10.5 安全相关 PRAGMA
-- 加密(仅 SQLCipher / SEE)
PRAGMA key = 'my-secret-key';
PRAGMA rekey = 'new-secret-key';
-- 忽略 CHECK 约束(危险!)
PRAGMA ignore_check_constraints = ON;
-- 信任外键约束的声明(不实际检查)
PRAGMA trusted_schema = ON; -- 默认 ON
10.6 PRAGMA 速查表
10.6.1 配置类
| PRAGMA | 默认值 | 持久 | 说明 |
|---|---|---|---|
journal_mode | DELETE | ✅ | 日志模式 |
synchronous | FULL | ❌ | 同步级别 |
cache_size | 2000 | ❌ | 页面缓存大小 |
mmap_size | 0 | ❌ | 内存映射大小 |
foreign_keys | OFF | ❌ | 外键约束 |
busy_timeout | 0 | ❌ | 忙等待超时 |
temp_store | DEFAULT | ❌ | 临时表存储 |
locking_mode | NORMAL | ❌ | 锁模式 |
page_size | 4096 | ✅ | 页面大小 |
auto_vacuum | NONE | ✅ | 自动清理 |
wal_autocheckpoint | 1000 | ❌ | WAL 自动 checkpoint |
defer_foreign_keys | OFF | ❌ | 延迟外键检查 |
10.6.2 信息类
| PRAGMA | 说明 |
|---|---|
page_count | 数据库页面总数 |
freelist_count | 空闲页面数 |
page_size | 页面大小 |
table_info(table) | 表的列信息 |
index_list(table) | 表的索引列表 |
index_info(index) | 索引的列信息 |
database_list | 已附加的数据库 |
compile_options | 编译选项 |
sqlite_version | SQLite 版本 |
stats | 统计信息 |
10.6.3 控制类
| PRAGMA | 说明 |
|---|---|
wal_checkpoint(mode) | 执行 WAL checkpoint |
optimize | 优化数据库 |
integrity_check | 完整性检查 |
quick_check | 快速完整性检查 |
shrink_memory | 释放内存 |
vacuum | 清理碎片 |
analysis_limit | ANALYZE 采样限制 |
10.7 完整性检查
-- 快速检查(遇到第一个错误就停止)
PRAGMA quick_check;
-- 完整检查(检查所有页面)
PRAGMA integrity_check;
-- 只检查指定表
PRAGMA integrity_check(users);
-- 输出示例(正常):
-- ok
-- 输出示例(异常):
-- Page 123: invalid page type at offset 456
⚠️ 注意事项
foreign_keys每次连接都要设置——不持久存储在数据库中synchronous = OFF可能丢数据——仅在可接受数据丢失时使用page_size只能在建表之前修改——修改后需要 VACUUMjournal_mode = WAL是持久设置——存储在数据库文件中locking_mode = EXCLUSIVE会阻止其他进程——Web 应用不要使用mmap_size在 32 位系统上有限制——不能超过虚拟地址空间
💡 技巧
- WAL + NORMAL + 大缓存是大多数读密集应用的最佳组合
- 批量导入时临时调整设置——完成后恢复安全设置
- 使用
PRAGMA optimize自动优化数据库(SQLite 3.18.0+) PRAGMA quick_check比integrity_check快得多- 使用
PRAGMA stats快速估算表的行数
📌 业务场景
场景一:Web 应用配置
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA cache_size = -4000;
PRAGMA foreign_keys = ON;
PRAGMA busy_timeout = 3000;
PRAGMA temp_store = MEMORY;
场景二:数据迁移脚本
PRAGMA journal_mode = WAL;
PRAGMA synchronous = OFF;
PRAGMA locking_mode = EXCLUSIVE;
PRAGMA cache_size = 100000;
BEGIN;
-- ... 大量 INSERT ...
COMMIT;
PRAGMA synchronous = NORMAL;
PRAGMA locking_mode = NORMAL;
🔗 扩展阅读
📖 下一章:11 - 全文搜索 —— FTS5、分词器、高亮、性能优化