转载,来自:http://blog.zheezes.com/sqlite-wal-principles-and-use.html
1. 前言
sqlite-v3.7.0之后引入了新的事务设计WAL(Write-Ahead Logging),修改数据库时会在数据库目录下生成”-wal”和”-shm”两个文件,而且数据库文件并不会实时修改(文件时间戳不变),如果修改数据库之后立刻将数据库文件拷贝到其他目录,查看数据库会发现仍然是过期的旧数据,原因是sqlite把对数据库的修改缓存在”-wal”和”-shm”两个文件中了。
2. SQLite设计
2.1.Journal原理
v3.7.0之前的数据文件方案,通过一个Journal文件来保证事务即使在断电情况下保持原子性,每次开启一个事务时,首先向Journal文件写入需要修改page的原内容,并且flush到硬盘,然后向数据库文件写入新的内容,最后删掉Journal文件中的内容完成一次事务。
但要注意SQLite的Journal设计与ext3的Journal设计不一样,ext3的Journal保存的是全量可重做日志,SQLite恢复是备份恢复,ext3恢复时是重做流水日志。
2.2.WAL原理
v3.7.0之后的数据文件方案,首先把修改内容写入日志(-wal),为了提高性能创建一个内存索引(-shm),映射每一个page是否dirty,读取时先看需要的page是否在WAL日志中,然后再读取。当达到一定条件后SQLite会自动将数据flush到数据库文件,也可以通过命令或接口手动flush到数据库文件。
2.3.Page
Page是SQLite的基本数据存储单元,类似于文件系统的block,SQLite中Page大小为[512, 65536]Byte。
3. SQLite工具
3.1.开启关闭WAL
PRAGMA [database.]journal_mode[=DELETE|TRUNCATE|PERSIST|MEMORY|WAL|OFF];
用于查询开启关闭事务模式,v3.7.0之前默认为DELETE,之后默认为WAL。要注意如果某些情况下修改事务模式可能会失败,比如数据库正被使用时。
3.2.WAL手动flush
PRAGMA [database.]wal_checkpoint[(PASSIVE|FULL|RESTART)];
用于将WAL文件同步到数据库文件,执行之后会返回一行三列的操作结果,返回比较复杂,具体的参考文档。
3.3.WAL自动flush的page数
PRAGMA wal_autocheckpoint[=N];
用于查看或设置自动flush的page数,即当-wal文件中的page到达参数时,自动flush日志到数据库文件,默认值为1000。
3.4.WAL文件大小
PRAGMA journal_size_limit[=N];
用于查看或设置-wal文件的大小(Byte),当-wal大小超过N时会自动的flush,然后truncat文件,如果N<0表示no limit。
4. Reference
(1)Write-Ahead Logging
(2)The SQLite Database File Format
(3)sqlite rollback journal
(4)SQLite PRAGMA Statements