Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

断电时写到一半怎么办

复习

  • 文件分配与空闲空间:数据块怎样找到、占用和回收
  • 缓冲与页面缓存:内存怎样减少缓慢的设备访问
  • 共享内存与内存映射:把文件访问与共享页面统一起来

TL;DR

  • 一次修改往往涉及多处磁盘结构,不可能一瞬间全部完成
  • 如果崩溃发生在“改了一半”时,磁盘上的结构就可能不一致
  • 这个问题叫崩溃一致性(crash consistency)
  • 关键不只是“写没写”,还有“按什么顺序写

正文

  前面一直默认:写下去,就写好了。可现实里有个躲不开的意外——断电、崩溃,可能正好发生在写到一半的那一刻。

改一处,其实牵动多处

  别以为“写文件”只是写一段数据那么简单。考虑在文件里追加一点内容,背后至少要做几件事:

  1. 找空闲块,把新数据写进去
  2. 更新 inode:文件变大了、数据块变多了
  3. 更新空闲空间的管理信息:这些块不再空闲

  这几步分散在磁盘的不同位置,磁盘一次只能写一处,没法“唰”地一下全部同时完成。于是就有了一个危险的时间窗口。

崩溃的时机

  假设在第 1 步之后、第 2 步之前断电了:

  • 数据块已经写进去了,可 inode 还不知道
  • 结果:这些块既没被任何文件引用,也没被标记为空闲——凭空消失了一块空间

  再假设在第 2 步之后、第 3 步之前断电:

  • inode 说“我用了这些块”,可空闲管理信息里这些块还标着“空闲”
  • 结果:同一块可能被分配两次,两个文件的内容互相覆盖
正确顺序:写数据 → 更新 inode → 更新空闲信息
              ↑ 崩溃点前后不一致 ↑

  这些“半成品”状态,就叫不一致。文件系统一旦不一致,轻则丢文件、浪费空间,重则全面错乱。

光“最终写完”还不够

  你可能会想:那等它慢慢写完不就行了?

  不行。因为崩溃可能恰好卡在中间,而恢复后系统只看得到“当前磁盘上的样子”,无从知道那次修改原本打算做到哪一步。问题不在于能不能写,而在于写到一半被打断后,磁盘上留下的是一团自相矛盾的状态。

  那能不能想办法,让“要么全做完、要么像没做过”?这正是下一章的主题——用日志来保证崩溃一致性。

思考题

  一个修改牵涉好几处磁盘结构时,为什么“调整写入顺序”有时能减轻不一致?如果崩溃发生在最坏的位置,光靠顺序能彻底解决吗?

小结

知识点

  • 一次修改涉及多处磁盘结构,无法原子完成
  • 崩溃可能发生在写到一半,导致结构不一致
  • 可能出现空间凭空消失、块被重复分配等后果
  • 关键不仅是写没写,还有写入顺序

参考资料

  1. Wikipedia(zh):崩溃一致性:crash consistency
  2. Wikipedia(zh):文件系统:一致性

思考题答案(仅供参考)

  调整顺序,可以把“最危险的交错”尽量排到不容易发生的位置。比如先写数据、再更新 inode、最后更新空闲信息,能让崩溃后出现的多是“浪费一点空间”这种较轻的后果,而不是“块被重复分配”这种严重错误。但光靠顺序不能彻底解决:无论怎么排,总有一个“改了一部分”的瞬间可被崩溃打断。要做到“要么全做、要么像没做”,还需要日志或写时复制这类更高层的机制——下一章就讲这个。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪