2012-02-04 86 views
1

我正在研究Linux的數據庫引擎,並且對於將一個系統調用寫入內核的許多塊有一致性問題。我用O_DIRECT打開設備。使用O_DIRECT一致地寫入很多塊

設備寫入數據塊,具體取決於它可能是512,2048或4096的硬件。比方說,我會在一次系統調用中寫入2個512字節的塊。如果在磁盤寫入1個塊後系統完全關閉,會發生什麼情況?在正常操作期間,write()系統調用將返回所寫入數據的大小,因此當2個值(被詢問vs返回)不匹配時,我可以比較並生成一個錯誤,但電源關閉會變得複雜。它更復雜,因爲內核可能會向設備發送寫請求,而不是按照您的要求發送請求,所以請求的尾部可能會寫在磁頭之前,然後關閉電源。

請考慮數據庫引擎寫入事務日誌。假設一個事務約爲4096個字節,引擎將需要寫入8個512字節的塊。突然之間,我們停電並且只有一半的請求被寫入。數據庫如何處理這些問題?我想要解決這個問題,你首先需要寫出你打算寫入磁盤上另一個位置的塊的數量。一旦您收到正確的返回值,您可以編寫數據。然後,在收到確認信息後,您必須發送另一個寫入磁盤,以更新所有您想要寫入的塊實際上已成功寫入的信息。所以,這需要3次寫入操作,如果內核正在從另一個進程寫入磁盤,這很可能會導致3次查找。效率太低。

我正在尋找一種方法來實現只有一次寫操作到磁盤的許多塊的一致寫入。 (一個write()系統調用)這可能嗎?

+0

爲什麼不只是有足夠的電池或電容器充電,你有時間檢測電源故障,並停止服務器乾淨? – 2012-02-04 02:19:09

+0

@R,其實這是個好主意。只需要一臺UPS,我就可以緩存輔助磁盤塊,並用一次尋道寫入實際數據。不適用於所有人,但這是一個很好的解決方案,可以在緊急情況下提供快速的日常操作並提供備份。 – Nulik 2012-02-04 13:36:15

回答

0

模一些速度攻擊,你所描述的寫兩次行爲正是數據庫所做的。它被稱爲write-ahead logging,它涉及一個單獨的緩衝區,它通過操作按順序寫入,偶爾會將內存緩衝區刷新到磁盤,同時將相應的刷新條目寫入日誌。然後,當數據庫系統開始運行時,它會檢查日誌中可能沒有刷新到磁盤的條目,並將這些值刷新到磁盤(因爲條目在日誌中)。

這實際上比立即寫入數據更高效。日誌是一個順序文件,因此向其添加數據不需要查找,只需要循環延遲。此外,您不必立即將數據寫入實際數據文件,因爲您始終可以從日誌中恢復數據。然後,當沒有任何請求進入時,您將數據刷新到磁盤並向日志中寫入一個刷新條目。這樣,DBMS尋找的唯一時間是1)當系統安靜時,以及2)當DMBS用完存儲器以保存修改後的數據時。只要你的機器中有足夠的內存,這個磁盤根本就沒有很多的查找,而這些查詢在DBMS不繁忙的時候就會發生。

-1

在關閉系統之前,您需要首先關閉數據庫引擎!關閉引擎時,應首先完成所有寫入,同步(刷新緩衝區)並使引擎正常停止。在關閉系統之前,您還可以在系統關閉腳本中包含一個命令,先關閉引擎。