标签:
原理
回滚日志的方法是把为改变的数据库文件内容写入日志里,然后把改变后的内容直接写到数据库文件中去。在系统crash或掉电的情况下,日志里的内容被重新写入数据库文件中。日志文件被删除,标志commit着一次commit的结束。
WAL模式于此此相反。原始为改变的数据库内容在数据库文件中,对数据库文件的修改被追加到单独的WAL文件中。当一条记录被追加到WAL文件后,标志着一次commit的结束。因此一次commit不必对数据库文件进行操作,当正在进行写操作时,可以同时进行读操作。多个事务的内容可以追加到一个WAL文件的末尾。
激活和配置WAL模式
PRAGMA journal_mode=WAL;
,如果成功,会返回"wal"。
自动checkpoint
可以手动checkpoint
sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb)
配置checkpoint
sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
Application-Initiated Checkpoints
可以在任意一个可以进行写操作的数据库连接中调用sqlite3_wal_checkpoint_v2()
或sqlite3_wal_checkpoint()
。
WAL模式的持久性
当一个进程设置了WAL模式,关闭这个进程,重新打开这个数据库,仍然是WAL模式。
如果在一个数据库连接中设置了WAL模式,那么这个数据库的所有连接都将被设为WAL模式。
只读数据库
如果数据库需要恢复,而你只有读权限,没有写权限,那么你不能读取这个数据库,因为进行读操作的第一步就是恢复数据库。
类似的,因为WAL模式下的数据库进行读操作时,需要类似数据库恢复的操作,因此如果只有读权限,也不能对打开数据库。
WAL的实现需要有一个基于WAL文件的哈希表在共享内存中。在Unix和Windows的VFS实现中,是基于MMap的。将共享内存映射到同目录下的"-shm"文件中。因此即使是对WAL模式下的数据库文件进行读操作,也需要写权限。
为了把数据库文件转化为只读的文件,需要先把这个数据库的日志模式改为"delete".
避免过大的WAL文件
WAL-index的共享内存实现
在WAL发布之前,曾经尝试过将wal-index映射到临时目录,如/dev/shm或/tmp。但是不同的用户看到的目录是不同的,所以此路不通。
后来尝试将wal-index映射到匿名的虚拟内存块中,但是无法在不用的Unix版本中保持一致。
最终决定采用将wal-index映射到同目录下。这样子会导致不必要的磁盘IO。但是问题不大,是因为wal-index很少超过32k,而且从不会调用sync操作。此外,最后一个数据库连接关闭以后,这个文件会被删除。
如果这个数据库只会被一个进程使用,那么可以使用heap memory而不是共享内存。
不用共享内存实现WAL
在3.7.4版本以后,只要SQLite的lock mode被设为EXCLUSIVE,那么即使共享内存不支持,也可以使用WAL模式。
换句话说,如果只有一个进程使用SQLite,那么不用共享内存也可以使用WAL。
此时,将lock mode改为normal是无效的,需要实现取消WAL模式。
标签:
原文地址:http://www.cnblogs.com/huahuahu/p/sqlite-zhiWAL-mo-shi.html