从 PostgreSQL fsync EIO 失败处理说起
内容提要
2018年,PostgreSQL发现fsync()失败可能导致数据静默丢失,称为“fsyncgate”。该问题揭示了Linux内核与数据库在I/O错误处理上的矛盾,尤其在云存储环境中更为突出。PostgreSQL采取了PANIC策略应对fsync失败,但在云环境下可用性风险增加,需改进错误处理机制。
关键要点
-
2018年,PostgreSQL发现fsync()失败可能导致数据静默丢失,称为“fsyncgate”。
-
fsyncgate揭示了Linux内核与数据库在I/O错误处理上的矛盾,尤其在云存储环境中更为突出。
-
PostgreSQL采取了PANIC策略应对fsync失败,但在云环境下可用性风险增加。
-
Craig Ringer报告了fsync失败导致数据丢失的案例,指出PostgreSQL的处理方式存在缺陷。
-
Linux内核在fsync失败后将dirty page标记为clean,导致PostgreSQL重试fsync时误认为数据已成功写入。
-
PostgreSQL开发者对内核行为表示愤怒,认为fsync失败后应保持page的dirty状态。
-
FreeBSD的fsync处理方式与Linux不同,保持page为dirty以便后续重试。
-
内核开发者面临的挑战是平衡不同用户场景的需求,数据库开发者要求数据持久化的严格性。
-
PostgreSQL在2018年11月合入了PANIC on fsync failure的策略,避免静默数据损坏。
-
PANIC策略的代价是可用性下降,导致数据库实例崩溃和WAL恢复时间延长。
-
Direct I/O被认为是长期解决方案,但PG开发者认为实施难度大。
-
Wisconsin大学的研究表明,许多数据库在fsync失败时的错误处理不足,无法保证数据持久性。
-
fsyncgate并非PostgreSQL第一次因对OS层行为做过多假设而导致问题,历史上还有其他类似问题。
-
在云原生时代,fsync失败的语义变化使得I/O错误频率显著增加,影响数据库可用性。
-
PlanetScale的实证数据表明,云存储的性能降级率远超本地存储,导致数据库面临更高的可用性风险。
-
CloudJump提出了针对云存储特性进行数据库层面系统性适配的优化准则。
-
在云环境中,EIO的瞬态性改变了fsync失败处理的决策框架,PostgreSQL的PANIC策略代价过高。
-
改进思路是区分WAL和数据文件的fsync失败处理,WAL文件的fsync失败应PANIC,而数据文件可考虑重试。
-
Direct I/O被认为是解决fsync失败后优雅重试的根本出路,能够避免状态不一致的问题。
-
云厂商可以提供更丰富的错误语义,帮助数据库更好地处理瞬态错误。
-
长期缺失的文档和指导使得数据库开发者难以理解内核的行为,导致错误处理不足。
-
依赖OS层的隐式保证是危险的,云原生时代的高频瞬态I/O错误暴露了这一问题。
延伸问答
fsyncgate是什么问题,它对PostgreSQL有什么影响?
fsyncgate是PostgreSQL在2018年发现的一个问题,fsync()失败可能导致数据静默丢失,揭示了Linux内核与数据库在I/O错误处理上的矛盾,尤其在云存储环境中影响更大。
PostgreSQL是如何应对fsync失败的?
PostgreSQL采取了PANIC策略应对fsync失败,这意味着在fsync失败时会导致整个数据库实例崩溃,以避免静默数据损坏。
fsync失败后,Linux内核是如何处理dirty page的?
Linux内核在fsync失败后会将相关的dirty page标记为clean,这导致PostgreSQL在重试fsync时误认为数据已成功写入。
为什么PostgreSQL的PANIC策略会导致可用性下降?
PANIC策略会导致数据库实例崩溃,并需要进行WAL恢复,这可能耗时数分钟到数十分钟,从而降低了可用性。
在云存储环境中,fsync失败的语义有什么变化?
在云存储环境中,fsync失败的瞬态性增加,导致I/O错误频率显著上升,这对数据库的可用性构成了更高的风险。
如何改进PostgreSQL对fsync失败的处理?
改进思路是区分WAL和数据文件的fsync失败处理,WAL文件的fsync失败应PANIC,而数据文件可考虑重试。