日志或预写日志是解决操作系统中文件系统不一致问题的复杂解决方案。受数据库管理系统的启发,这种方法首先将要执行的操作的摘要写到“日志”中,然后再将它们实际写入磁盘。因此名称为“预写日志记录”。在崩溃的情况下,操作系统可以简单地检查这个日志并从它停止的地方开始。这节省了多次磁盘扫描以修复不一致,就像 FSCK 的情况一样。
实现数据日志的系统的好例子包括 Linux ext3 和 ext4 文件系统,以及 Windows NTFS。
数据日志:
日志存储在称为日志的简单数据结构中。下图显示了它的结构,它由三个组件组成。
- TxB(交易开始块):
这包含事务 ID 或 TID。 - 索引节点、位图和数据块(元数据):
这三个块包含磁盘中要更新的块内容的副本。 - TxE(交易结束块)
这只是标记由 TID 标识的事务的结束。
一旦请求更新,它就会写入日志,然后写入文件系统。一旦所有这些写入成功,我们就可以说我们已经到达检查点并且更新完成。
如果在日记过程中发生崩溃怎么办?
有人可能会争辩说,日记本身并不是原子性的。因此,系统如何处理未检查点的写入?为了克服这种情况,日志分为两个步骤:同时写入 TxB 和以下三个块,然后写入 TxE。该过程可以总结如下。
- 杂志写:
将 TxB、inode、位图和数据块内容写入日志(日志)。 - 期刊提交:
将 TxE 写入日志(日志)。 - 检查点:
将inode、位图和数据块的内容写入磁盘。
日志记录过程中的不同点可能会发生崩溃。如果在步骤 1 发生崩溃,即在 TxE 之前,我们可以简单地完全跳过此事务并且文件系统保持一致。
如果在第 2 步发生崩溃,则意味着尽管该事务已被记录,但尚未完全写入磁盘。我们无法确定这三个块(inode、位图和数据块)中的哪一个被实际更新,哪些发生了崩溃。在这种情况下,系统会扫描日志以查找最近的事务,并再次执行上一个事务。这确实会导致冗余磁盘写入,但可确保一致性。此过程称为重做日志记录。
使用日志作为循环缓冲区:
由于进行了许多事务,因此日志日志可能会用完。为了解决这个问题,我们可以将日志日志用作循环缓冲区,其中新事务以循环方式不断替换旧事务。下图显示了日志的整体视图,tr1 为最旧的事务,tr5 为最新的事务。
超级块维护指向最旧和最新交易的指针。一旦交易完成,它就会被标记为“空闲”并且超级块被更新到下一个交易。