SQLite WAL 调研总结

  • iOS 系统从iOS 7版本自带的SQLite数据库默认为开启WAL模式,即journal_mode=WAL
  • iOS 版本4.3 以上系统自带SQLite版本为3.7.0以上(SQLite 3.7.0开始支持WAL)
  • 在创建数据库连接时,执行
    [conn executeUpdate:[NSString stringWithFormat:@”PRAGMA journal_mode=WAL”]];
    即可
  • 使用注意,在开启数据库时,不能只读打开。
  • 低版本的SQLite不能读取高版本的SQLite生成的WAL文件,但是数据库文件是通用的。这种情况在用户进行iOS降级时可能会出现,可以把模式改成delete,再改回WAL来修复。
  • iOS 版本的SQLite是线程安全的(db 连接不要多线程共享)。详情

WAL 工作原理:

开启WAL模式后, 会有3个文件:

{<1>}database

.db 为数据库文件


-shm 为每个数据库文件的共享内存文件


-wal 对数据库的修改操作于此文件

修改并不直接写入到数据库文件中,而是写入到另外一个称为WAL的文件中;如果事务失败,WAL中的记录会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。

同步WAL文件和数据库文件的行为被称为checkpoint(检查点),它由SQLite自动执行,默认是在WAL文件积累到1000页修改的时候;当然,在适当的时候,也可以手动执行checkpoint,SQLite提供了相关的接口。执行checkpoint之后,WAL文件会被清空。

在读的时候,SQLite将在WAL文件中搜索,找到最后一个写入点(end mark),记住它,并忽略在此之后的写入点(这保证了读写和读读可以并行执行);随后,它确定所要读的数据所在页是否在WAL文件中,如果在,则读WAL文件中的数据,如果不在,则直接读数据库文件中的数据。为了避免每次读操作都遍历整个WAL文件去查找,SQLite使用了一种叫做wal-index的数据结构(保存于-shm)用于提高查找效率同时减少磁盘I/O。

在写的时候,SQLite将之写入到WAL文件尾即可,读写互不影响,所以渡河写可以同时执行。因为只有一个WAL文件,所以必须保证一次只执行一次写操作,因此写操作之间不能并行执行

checkpoint的时候,将WAL中的数据同步回数据库中。checkpoint操作可以与读操作并行,但,如果有读操作正在读checkpoint要更新的数据库中的数据时,checkpoint操作会停止,直到读操作完成。

WAL在实现的过程中,使用了共享内存技术,因此,所有的读写进程必须在同一个机器上,否则,无法保证数据一致性。

WAL相关使用配置:

启动: PRAGMA journal_mode=WAL;

自动checkpoint操作:

默认情况下,SQLite 自动触发checkpoint操作

  • 当一个COMMIT时,WAL文件的page数超过1000(可配置)
  • database连接关闭时。

手动触发checkpoint操作:详情

  • PRAGMA wal_autocheckpoint;
  • PRAGMA wal_autocheckpoint=N;
  • SQLite3_wal_checkpoint()

参考资料