我知道 PostgreSQL 数据文件存在“撕裂写入”(aka,“部分写入”)问题,为了防止这种情况,采用了 FPW(整页写入)机制。
那么 WAL 段文件是否也存在某种“部分写入”问题?如果是这样,是否有任何机制来阻止它?如果没有预防,这意味着提交的事务会在“WAL 段文件部分写入”时丢失?
其实我也有关于FPW的疑问。让我们基于通常的现代 Linux,检查点通常采用“同步”模式,对吗?如果是这样,8K 写入只会返回两个 4K OS 页面写入的成功,对吗?如果是这样,“部分写入”怎么可能发生?请纠正我的理解。
提前致谢!
更新:
jjanes 回答我说:
WAL 页面上的部分写入在读回时会使校验和失败,因此将被解释为刚好超出 WAL 的末尾。因此,不会重播任何部分记录。
我想我可以理解这一点,但这不会导致任何数据丢失吗?特别是 WAL 部分写入发生在已提交的事务上,然后重新启动重放,这可能吗,尽管很少见?
WAL 页面上的部分写入在读回时会使校验和失败,因此将被解释为刚好超出 WAL 的末尾。因此,不会重播任何部分记录。
部分写入只能作为崩溃或严重错误的一部分发生。但我们希望能够从那些...
除非 synchronous_commit 被关闭,否则在 WAL 记录被完全写入和同步之前,事务不会被报告为已提交。因此,丢失的数据将是最初从未报告为已提交的数据。如果您发出 COMMIT 并且由于系统首先崩溃而没有返回成功消息,那么您不知道系统恢复后数据是否还存在。
现在,如果系统声称数据已写入并同步,但实际上并没有,这可能会导致提交的数据丢失,但这并不是撕裂写入所特有的——这只是操作系统引起的数据损坏。如果操作系统说“出了点问题”,数据库需要能够恢复。但是,如果操作系统声称一切正常,甚至认为它没有,那么你就完蛋了。数据库无法解决这个问题,预计也不会。
校验和方法不适用于数据文件,因为它们可以被覆盖。因此,错误的校验和会告诉您当前数据页已损坏,但如果没有 FPW,就无法检索未损坏的旧值来恢复它。由于 WAL 从未正式被覆盖,因此问题不会在那里发生。