SQLite 从日志模式(journal_mode) 、同步模式(synchronous) 、访问模式 两个维度划分,工程上最核心是 journal_mode,其次是synchronous。
一、Journal 日志模式
(核心,决定锁机制、读写并发、掉电安全)
1. DELETE(删除模式,默认旧版)
PRAGMA journal_mode;
-
原理:传统回滚日志。写事务前把原始数据写入
xxx-journal文件;事务提交后,直接删除journal文件。 -
锁:全局库锁,写的时候所有读阻塞。
-
特点:
-
无额外shm/wal文件
-
读写互斥,并发差
-
事务崩溃恢复依赖journal
-
-
✅适用:低频率写入,简单日志
-
❌不推荐你的场景:高频JT808/J1939报文写入,容易
database is locked
2. WAL 预写日志模式
PRAGMA journal_mode=WAL;
-
原理:修改先写入wal文件(xxx-wal),不直接改写主db;读从主文件读,写追加到wal。检查点(checkpoint)时机,把wal数据合并入主库。
-
锁机制:读和写可以并发,写仍然是串行(同一时间只能一个写事务)
-
产生文件:
xxx.db+xxx.db-wal+xxx.db-shm(共享内存文件) -
优势:
-
大幅降低
database is locked,一边写报文、一边查询待上传数据互不阻塞 -
事务提交更快
-
-
缺点:
-
多2个附属文件,异常断电wal文件可能残留
-
只读文件系统不能使用WAL
-
-
WAL三个检查点模式:PASSIVE / FULL / RESTART / TRUNCATE
PRAGMA wal_autocheckpoint=1000;写满N页自动触发checkpoint
3. PERSIST 持久日志
journal文件提交后不删除,仅清空内容,减少文件创建销毁开销。锁机制同DELETE。
适合大量短事务频繁开关场景,现在WAL基本替代它。
4. TRUNCATE 截断日志
提交事务时把journal文件截断为0,不是删除。和DELETE行为接近。
5. MEMORY 内存日志
回滚日志直接放在内存,磁盘只存主db。
-
崩溃直接丢事务数据,掉电不安全
-
速度快;只适合临时内存数据库,车载业务禁止。
二、Synchronous 同步模式
(掉电安全等级,配合WAL一起配置)
PRAGMA synchronous = ?;控制操作系统刷盘策略
| 模式 | 说明 | 掉电风险 | 性能 | 推荐场景 |
|---|---|---|---|---|
| FULL | 每次事务提交强制刷磁盘,OS缓存落盘 | 最低 | 最慢 | 关键数据,安全优先 |
| NORMAL | WAL模式:仅checkpoint阶段刷盘;事务提交不强制刷盘 | 中等 | 均衡 | ✅车载终端推荐 |
| OFF | 完全不刷盘,交给OS缓存 | 极高,断电极易库损坏 | 最快 | 仅临时日志,禁止存原始报文 |
工程最佳组合:
journal_mode=WAL+synchronous=NORMAL兼顾写入速度 + 崩溃恢复能力,商用车盒子通用方案。
三、数据库访问模式(打开模式)
-
File-based 文件模式 (你在用的)
jdbc:sqlite:/data/vehicle/terminal.db,持久化到闪存,重启数据保留。 -
内存模式
:memory:数据库完全在内存,无磁盘文件,进程退出/断电全部丢失。 适合临时统计、临时缓存,不能存JT808原始报文。 -
只读打开模式
PRAGMA query_only = true;或连接串指定只读。用于单独读取待上传数据,不允许写入。
四、锁模式补充(WAL下的锁)
WAL模式下有4种锁,按顺序:
-
SHARED 共享锁:读
-
RESERVED:准备写
-
PENDING:等待现有读结束
-
EXCLUSIVE排他锁:写事务执行阶段
WAL读不阻塞写,写不阻塞读 ,但是同一时刻只能1个写事务。所以业务层依然要做单写队列,防止多线程并发写报locked。
五、其它重要PRAGMA配套(车载常用)
-- WAL开启
PRAGMA journal_mode=WAL;
-- 同步等级
PRAGMA synchronous=NORMAL;
-- 缓存页大小
PRAGMA cache_size=-2000; -- 单位KB,设置缓存
-- 开启外键(默认关闭,业务不需要可以关掉节省开销)
PRAGMA foreign_keys=OFF;
-- 自动checkpoint
PRAGMA wal_autocheckpoint=500;
六、选型决策表(直接用于方案文档)
| 方案组合 | 并发读写 | 掉电安全 | 写入性能 | 适用场景 |
|---|---|---|---|---|
| DELETE + FULL | 读写互斥,差 | 高 | 慢 | 极少写入,简单日志 |
| WAL + FULL | 读写并发 | 高 | 中等 | ADAS报警事件(重要告警不能丢) |
| WAL + NORMAL | 读写并发 | 中等 | 优秀 | ✅JT808/J1939高频报文,断网缓存 |
| WAL + OFF | 读写并发 | 低 | 极快 | 临时统计数据,原始报文不可用 |
七、工程坑点
-
WAL模式下直接复制db文件备份会损坏,备份前要执行
PRAGMA wal_checkpoint(FULL); -
只读分区无法启用WAL,会自动回退DELETE模式,锁冲突大量出现
-
shm/wal文件权限问题:车载linux下进程要有读写权限,否则WAL启用失败
-
WAL会持续增大wal文件,需要定时checkpoint,不然占用存储空间
如果你需要,我可以补充:
-
Java启动SQLite时自动设置WAL+同步模式代码
-
WAL checkpoint自动回收脚本
-
数据库损坏检测与修复SQL脚本。