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操作所發生的錯誤訊息。但是他們也同意這項工作是大工程,不會很快被實現。

但無論是哪一種的解決辦法,更新都需要在新一版的核心才會出現。


Advertisement

更多 iThome相關內容