断电时写到一半怎么办
复习
- 文件分配与空闲空间:数据块怎样找到、占用和回收
- 缓冲与页面缓存:内存怎样减少缓慢的设备访问
- 共享内存与内存映射:把文件访问与共享页面统一起来
TL;DR
- 一次修改往往涉及多处磁盘结构,不可能一瞬间全部完成
- 如果崩溃发生在“改了一半”时,磁盘上的结构就可能不一致
- 这个问题叫崩溃一致性(crash consistency)
- 关键不只是“写没写”,还有“按什么顺序写”
正文
前面一直默认:写下去,就写好了。可现实里有个躲不开的意外——断电、崩溃,可能正好发生在写到一半的那一刻。
改一处,其实牵动多处
别以为“写文件”只是写一段数据那么简单。考虑在文件里追加一点内容,背后至少要做几件事:
- 找空闲块,把新数据写进去
- 更新 inode:文件变大了、数据块变多了
- 更新空闲空间的管理信息:这些块不再空闲
这几步分散在磁盘的不同位置,磁盘一次只能写一处,没法“唰”地一下全部同时完成。于是就有了一个危险的时间窗口。
崩溃的时机
假设在第 1 步之后、第 2 步之前断电了:
- 数据块已经写进去了,可 inode 还不知道
- 结果:这些块既没被任何文件引用,也没被标记为空闲——凭空消失了一块空间
再假设在第 2 步之后、第 3 步之前断电:
- inode 说“我用了这些块”,可空闲管理信息里这些块还标着“空闲”
- 结果:同一块可能被分配两次,两个文件的内容互相覆盖
正确顺序:写数据 → 更新 inode → 更新空闲信息
↑ 崩溃点前后不一致 ↑
这些“半成品”状态,就叫不一致。文件系统一旦不一致,轻则丢文件、浪费空间,重则全面错乱。
光“最终写完”还不够
你可能会想:那等它慢慢写完不就行了?
不行。因为崩溃可能恰好卡在中间,而恢复后系统只看得到“当前磁盘上的样子”,无从知道那次修改原本打算做到哪一步。问题不在于能不能写,而在于写到一半被打断后,磁盘上留下的是一团自相矛盾的状态。
那能不能想办法,让“要么全做完、要么像没做过”?这正是下一章的主题——用日志来保证崩溃一致性。
思考题
一个修改牵涉好几处磁盘结构时,为什么“调整写入顺序”有时能减轻不一致?如果崩溃发生在最坏的位置,光靠顺序能彻底解决吗?
小结
知识点
- 一次修改涉及多处磁盘结构,无法原子完成
- 崩溃可能发生在写到一半,导致结构不一致
- 可能出现空间凭空消失、块被重复分配等后果
- 关键不仅是写没写,还有写入顺序
参考资料
- Wikipedia(zh):崩溃一致性:crash consistency
- Wikipedia(zh):文件系统:一致性
思考题答案(仅供参考)
调整顺序,可以把“最危险的交错”尽量排到不容易发生的位置。比如先写数据、再更新 inode、最后更新空闲信息,能让崩溃后出现的多是“浪费一点空间”这种较轻的后果,而不是“块被重复分配”这种严重错误。但光靠顺序不能彻底解决:无论怎么排,总有一个“改了一部分”的瞬间可被崩溃打断。要做到“要么全做、要么像没做”,还需要日志或写时复制这类更高层的机制——下一章就讲这个。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪