强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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读写互斥较好保留文件但标记无效

⚠️ MEMORYOFF 仅适用于临时数据或可丢数据的场景。

10.2.2 synchronous(同步模式)

控制 SQLite 将数据刷入磁盘的频率。

PRAGMA synchronous;
PRAGMA synchronous = FULL;     -- 默认:每次提交都 fsync
PRAGMA synchronous = NORMAL;   -- WAL 模式下推荐
PRAGMA synchronous = OFF;      -- 最快,但崩溃可能丢数据
PRAGMA synchronous = EXTRA;    -- 比 FULL 更严格
模式安全性性能说明
FULL最高一般每次事务提交都 fsync
NORMALWAL 模式下足够安全
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_modeDELETE日志模式
synchronousFULL同步级别
cache_size2000页面缓存大小
mmap_size0内存映射大小
foreign_keysOFF外键约束
busy_timeout0忙等待超时
temp_storeDEFAULT临时表存储
locking_modeNORMAL锁模式
page_size4096页面大小
auto_vacuumNONE自动清理
wal_autocheckpoint1000WAL 自动 checkpoint
defer_foreign_keysOFF延迟外键检查

10.6.2 信息类

PRAGMA说明
page_count数据库页面总数
freelist_count空闲页面数
page_size页面大小
table_info(table)表的列信息
index_list(table)表的索引列表
index_info(index)索引的列信息
database_list已附加的数据库
compile_options编译选项
sqlite_versionSQLite 版本
stats统计信息

10.6.3 控制类

PRAGMA说明
wal_checkpoint(mode)执行 WAL checkpoint
optimize优化数据库
integrity_check完整性检查
quick_check快速完整性检查
shrink_memory释放内存
vacuum清理碎片
analysis_limitANALYZE 采样限制

10.7 完整性检查

-- 快速检查(遇到第一个错误就停止)
PRAGMA quick_check;

-- 完整检查(检查所有页面)
PRAGMA integrity_check;

-- 只检查指定表
PRAGMA integrity_check(users);

-- 输出示例(正常):
-- ok

-- 输出示例(异常):
-- Page 123: invalid page type at offset 456

⚠️ 注意事项

  1. foreign_keys 每次连接都要设置——不持久存储在数据库中
  2. synchronous = OFF 可能丢数据——仅在可接受数据丢失时使用
  3. page_size 只能在建表之前修改——修改后需要 VACUUM
  4. journal_mode = WAL 是持久设置——存储在数据库文件中
  5. locking_mode = EXCLUSIVE 会阻止其他进程——Web 应用不要使用
  6. mmap_size 在 32 位系统上有限制——不能超过虚拟地址空间

💡 技巧

  1. WAL + NORMAL + 大缓存是大多数读密集应用的最佳组合
  2. 批量导入时临时调整设置——完成后恢复安全设置
  3. 使用 PRAGMA optimize 自动优化数据库(SQLite 3.18.0+)
  4. PRAGMA quick_checkintegrity_check 快得多
  5. 使用 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、分词器、高亮、性能优化