Linux核心脑损伤臭虫可能促使PostgreSQL资料遗失且没有任何错误通知

人工智能2021-03-01 10:04:38
最佳答案

PostgreSQL社群发现,在Linux上使用PostgreSQL,有机会发生核心处理I/O错误造成资料遗失,且系统不会回报任何的错误讯息,PostgreSQL执行缓冲I/O的方式恶化了这个错误,Linux社群表示,这并非Linux独有的问题,OpenBSD和NetBSD都可能受影响而且很难解决。

PostgreSQL支援工程师Craig Ringer在3月的时候,于pgsql-hackers邮件列表首次回报了这个问题。简单来说,当fsync()被呼叫,PostgreSQL便会假设所有资料都成功写入到永久储存中,但事实并非总是如此。

当由硬体错误引发的缓冲I/O写入失败时,档案系统会作出不同的回应,而这个动作通常包括丢弃受影响页面,并将页面的资料标示为清空,所以之前写入资料的区块,可能回传除了写入资料之外的内容。

由于Linux社群在档案系统的错误报告还未达成共识,以至于错误报告在去年LSFMM会议上被人指称一团乱,这也让应用程式很难正确地获得通知,在核心4.13版本对此问题做了部分补丁,但是仍然没有提供完整的解决方案,而这样的情况发生在PostgreSQL,便会造成无警示的资料失败。

PostgreSQL社群对Linux这样的问题多表达不满,他们认为,无法写入的页面应该保存在记忆体内,将状态标记为Dirty并在稍后再次尝试,而且相关的档案描述符( File Descriptor)状态也应该设为永久错误,让PostgreSQL伺服器不会错过这个存在的问题。

开源软体知名贡献者Tom Lane表示,这样的错误根本是核心脑损伤(Kernel Brain Damage),而EnterpriseDB副总裁同时也是PostgreSQL社群重要成员Robert Haas则认为,会发生这样的问题百分之一百不合理。

Robert Haas进一步解释错误发生的细节,PostgreSQL伺服器服务由一群程序集合而成,许多程序都能执行资料库档案I/O,而呼叫fsync()工作由一个称为Checkpointer的程序执行,该程序负责确保硬碟上的资料一致性,以便在错误发生时回复。而Checkpointer不会总是一直开启所有的相关档案,通常只会在呼叫fsync()前打开文件。

而这就是问题发生的地方,Robert Haas表示,即便在4.13或是更高的核心版本,Checkpointer在打开档案之前,不会知道有任何错误发生,如果Checkpointer在真正执行开启档案之前,系统发生了错误,fsync()呼叫仍会回传成功。Robert Haas认为,这样的核心设计,也会对其他应用程式造成问题,不仅是PostgreSQL。

Linux社群讨论提到,Google有自己的I/O错误处理机制,核心会透过Netlink socket回报I/O错误,这样的处理方式对于PostgreSQL可能是完美的,因此暂时解决办法可能採取这个方向进行。

而Linux社群对于该问题的解决方案,普遍共识认为应该让PostgreSQL执行直接I/O(Direct I/O,DIO),一般来说直接I/O可以更容易控制回写以及I/O,也能存取I/O操作所发生的错误讯息。但是他们也同意这项工作是大工程,不会很快被实现。

但无论是哪一种的解决办法,更新都需要在新一版的核心才会出现。

免责声明:本文由用户上传,如有侵权请联系删除!