天天看點

異版本pg_resetxlog後導緻的問題處理

資料庫的redo日志損壞時,或者控制檔案損壞時,可能導緻資料庫無法啟動。

如果存放pg_xlog或者pg_control檔案的塊裝置遇到問題,可能引發這種情況。

遇到xlog或者控制檔案損壞的時候,怎麼處理呢?

資料庫正常關閉時會寫控制檔案,redo是在資料庫crash後需要用來恢複資料庫的,如果資料庫正常的關閉,實際上不需要從redo恢複。

postgresql 提供了一個工具,用來生成或改寫控制檔案,抹除指定的pg_xlog。

在資料庫因為控制檔案損壞,或者pg_xlog損壞,導緻資料庫不能正常啟動時使用。

使用後,資料庫起來之後,請務必邏輯導出後再導入一個新的叢集。

導出時最好設定跳過錯誤的塊(設定zero_damaged_pages=true),因為這種情況下十有八九塊會損壞。

同時,由于pg_resetxlog會改寫控制檔案,如果你使用的pg_resetxlog和資料庫的版本不一緻,會導緻生成的控制檔案版本跟随pg_resetxlog的版本,導緻後面一系列的問題。

檢視控制檔案的頭檔案,可以了解到控制檔案的内容定義

控制檔案的版本

控制檔案的檢查點資訊

控制檔案資料

通過pg_controldata指令則可以輸出控制檔案的内容,源碼如下。

src/bin/pg_controldata/pg_controldata.c

例子

如果資料庫叢集時9.5,而你使用其他版本的pg_resetxlog修改其控制檔案,結果會怎樣呢?

例如使用9.2的pg_resetxlog設定9.5叢集的pg_control檔案。

如果你使用-f選項強制刷了這個pg_control檔案,則版本号會變成9.2的,這個時候,你再使用9.5去啟動資料庫是會失敗的。

那麼使用9.2就能啟動成功了嗎?

當然也不行,因為資料庫還有其他地方記錄了版本号,那就是在$pgdata以及資料庫的資料檔案目錄對應的pg_version檔案。

這個檔案是不會被pg_resetxlog纂改的,因為可以用來追溯真正的版本。

被不同版本的pg_resetxlog強制重建控制檔案後,資料庫将無法啟動。

怎麼辦呢?

方法很簡單,使用pg_version對應版本的pg_resetxlog重新生成一遍控制檔案即可。

pg_resetxlog參數有幾個,分别用來設定控制檔案中對應的next xid , next oid, next multi-xact xid, ......

這些值有固定的算法,而且有安全範圍,例如,不能設定比實際已建立事務更小的事務号,否則會造成對應事務産生的資料在事務号未消耗前資料不可見。

安全值的計算方法,可以參考pg_resetxlog的說明。

其實就是使用xlog中的檔案名推算next xid。使用pg_multixact中的members , offsets推斷oldest multixact id, next multi-xact。等等。

推斷出正确的值後,就可以開始通過pg_resetxlog設定控制檔案了。

除了pg_controldata以外,還可以檢視檔案pg_version得到。

<a href="http://blog.163.com/digoal@126/blog/static/163877040201171233710582/">http://blog.163.com/digoal@126/blog/static/163877040201171233710582/</a>

<a href="http://blog.163.com/digoal@126/blog/static/16387704020130109400557/">http://blog.163.com/digoal@126/blog/static/16387704020130109400557/</a>

使用與資料檔案異版本的pg_resetxlog,将導緻資料檔案對應到 控制檔案損壞。 無法啟動資料庫。

解決版本,使用與資料檔案版本一緻的pg_resetxlog,重新生成控制檔案,需要加-f強制執行。

pg_resetxlog參數的安全值計算方法,見pg_resetxlog的參考手冊。

祝大家玩得開心,歡迎随時來 阿裡雲促膝長談業務需求 ,恭候光臨。

阿裡雲的小夥伴們加油,努力 做好核心與服務,打造最貼地氣的雲資料庫 。