概述
journal功能属于Pager模块的子模块,用于事务的回滚。
概念
Journal模式
第一个事务开始时,会创建一个journal文件。
- journal = DELETE时,每次提交事务后,SQLite会删除journal文件。
- journal = TRUNCATE,每次提交事务后,SQLite会将journal文件截断为零长度,但保留文件。
- journal = PERSIST, 每次提交事务后,SQLite会将journal文件保留并重用以加快写入性能。这适用于需要频繁提交事务的场景。
- journal = MEMORY,不会写入journal文件,所有事务直接写入数据库文件。
- journal = WAL, SQLite会生成一个“-wal”文件和一个“-shm”文件(共享内存文件)。这种模式可以提高写入性能,并允许读操作与写操作并发执行。
- journal = OFF, 关闭回滚日志,事务中断,可能导致数据库不一致。
写入回滚日志的页面与事务开始时数据库中的内容完全一致
super-journal文件
在SQLite中,当使用attach命令操作多个数据库时,为了保持这些数据库之间的一致性,SQLite会创建一个super-journal文件。这个文件并不会包含页数据,而是包含每个数据库的日志文件的名称。每个数据库的日志文件同时也会包含该super-journal文件的名称。这样,在需要回滚时,SQLite可以根据super-journal文件中的信息,找到所有相关的日志文件,并进行相应的回滚操作,以确保所有数据库的一致性。
super-journal 的文件格式:
db1的 journal 文件名 | db2的 journal 文件名 | db3的 journal 文件名 | db4的 journal 文件名 | …
hot-journal
在事务未完全提交时保留的日志文件,用于崩溃恢复后回滚未完成的事务。
finalize journal
个人翻译为删除Journal日志,事实上是根据journal模式对journal文件进行删除或者截断、清零操作。事务提交或者回滚后,需要将Undo日志删除,防止下一次读到Undo日志,将已经完成或回滚的事务回滚。
Journal文件格式
Journal日志头格式
MagicNum | 记录条数 | 随机值 | db文件大小 | 扇区大小 | 页大小
8字节 | 4 字节 | 4字节 | 4字节 | 4字节 | 4字节
数据页的journal日志格式
PgNo | pageData | checkSum
4字节 | pageSize | 4 字节
super-journal文件信息格式
lckPgno | super-journal 文件名 | 文件名长度 | cksum | magicNum
4 | len | 4 | 4 | 8
Journal文件格式:
Journal日志头 | Journal日志 | Journal 日志 | … | Journal日志头 | Journal日志 | …|super-journal文件信息(如果有的话)|
| 事务的完整Journal日志 |
sub-journal 文件格式
pgNo | pageData | pgNo | pageData | …
4 pageSize
super-journal 文件格式
journal文件名1 | \0 | journal文件名2 | \0 | …
接口
pagerAddPageToRollbackJournal
int pagerAddPageToRollbackJournal(PgHdr *pPg);
作用:数据页的内容按照journal日志格式写入journal文件
writeJournalHdr
int writeJournalHdr(Pager *pPager)
作用:写入Journal文件头
readJournalHdr
int readJournalHdr(Pager *pPager, int isHot, i64 journalSize, u32 *pNRec, u32 *pDbSize)
作用:从Journal中读取Journal头信息。
参数 | 含义 |
---|---|
pPager | Pager上下文。 |
isHot | 是否是hot-journal |
journalSize | journal文件大小 |
pNRec | 当前事务的journal日志条数 |
pDbSize | 当前事务的journal日志中页的大小 |
syncJournal
int syncJournal(Pager *pPager, int newHdr)
writeSuperJournal
int writeSuperJournal(Pager *pPager, const char *zSuper)
作用:向journal文件尾写入super-journal文件名信息
参数 | 含义 |
---|---|
pPager | Pager上下文。 |
zSuper | super -journal文件名 |
提交的一阶段在sync journal之前写入。 |
readSuperJournal
int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper)
作用:从journal文件尾读取super-journal文件名信息
参数 | 含义 |
---|---|
pPager | Pager上下文。 |
zSuper | 输出,super -journal文件名 |
nSuper | zSuper的长度 |
subjournalPageIfRequired
int subjournalPageIfRequired(PgHdr *pPg)
作用:只要有一个还原点没有写过pg,就将页内容写入sub-journal文件
pager_delsuper
int pager_delsuper(Pager *pPager, const char *zSuper)
作用:当多个数据库的事务都被回滚时,删除super-journal文件