天天看點

使用pg_resetxlog修複PostgreSQL控制檔案的方法

postgresql 控制檔案在$pgdata/global目錄下名為pg_control.

控制檔案中記錄了以下三部分資訊 :

1. initdb時生成的靜态資訊 :

以上資訊可以使用pg_controldata從pg_control擷取 :

如果控制檔案$pgdata/global/pg_control損壞或丢失, 資料庫将運作異常, 無法啟動.

如何修複? 關鍵在于恢複write-ahead logging以及checkpoint的動态資訊.

這些資訊可以從pg_xlog, pg_clog, pg_multixact這些目錄的檔案中解析出來。

pg_xlog的檔案名解析可參看, 不同的段大小, 命名大不相同, pg_resetxlog的幫助檔案适用16mb的段大小, 如果是其他大小, 需要重新計算名字 :

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

接下來介紹一下使用pg_resetxlog重建pg_control的方法.

pg_resetxlog功能如下 :

pg_resetxlog的用法 :

參數具體含義 :

測試步驟如下(基于postgresql 9.2.1) :

建立測試資料, 用到with oids的表, 因為oid無法确定, 看看是否會有異常.

關閉資料庫

記下pg_controldata資訊, 友善修複後進行比對

删除$pgdata/global/pg_control

開啟資料庫觀察報錯輸出

touch $pgdata/global/pg_control

使用pg_resetxlog修複pg_control

記下pg_controldata資訊, 與前面的pg_controldata輸出進行比對

啟動資料庫

檢視測試資料是否正常, 新插入資料

關閉資料庫, 并記下pg_controldata的資訊, 看看有何變化.

測試過程 :

1. 測試資料

2. 關閉資料

3. 記下pg_controldata資訊, 友善修複後進行比對

4. 删除$pgdata/global/pg_control

5. 開啟資料庫觀察報錯輸出

接下來進行修複 :

6. touch $pgdata/global/pg_control

7. 使用pg_resetxlog修複pg_control

首先确定-l timelineid,fileid,seg的資訊 :

-l timelineid,fileid,seg 的資料來自pg_xlog檔案名的三個部分, 分别占用8個16進制位.

段大小為16mb, 是以末端最大為0xff.

得出-l 0x1,0x96e8,0x60

接下來确定-x xid的資訊

來自pg_clog

取最大值加1然後乘以1048576.

轉換成16進制的話相當于取最大值加1然後末尾添加5個0

得到-x 0x046a00000

接下來确定-m xid的資訊

來自pg_multixact/offsets

取最大值加1然後乘以65536.

轉換成16進制的話相當于取最大值加1然後末尾添加4個0

沒有檔案的話使用0加1, 然後末尾添加4個0

得到-m 0x10000

接下來确定-o offset的資訊

來自pg_multixact/members

得到-o 0x10000

最後, 不确定的值有2個 :

可以先不管這兩個值.

執行pg_resetxlog 如下 :

8. 記下pg_controldata資訊, 與前面的pg_controldata輸出進行比對

注意修複後從控制檔案讀取到的不确定的-e xidepoch和-o oid資訊如下 :

也就是initdb後的初始值.

與修複pg_control前發生了變化的值如下 :

修複前

修複後

9. 啟動資料庫

10. 檢視測試資料是否正常, 然後新插入資料

資料可以正常通路.

新插入資料 :

注意oid出現了重複, 印證了postgresql中的說明, oid不確定唯一性.

11. 關閉資料庫, 并記下pg_controldata的資訊, 看看有何變化.

關閉資料庫後與剛修複好時的控制檔案資訊變化如下 :

開庫前 :

關庫後 :

1. 使用pg_resetxlog後, 先檢查資料一緻性, 必要時将資料導出, 使用initdb建立資料庫, 再導入.

2. 如果控制檔案丢失, 并且沒有備份的話, pg_resetxlog你不知道該填啥, 但是可以從pg_xlog目錄中獲得大概的redo location, 或者pg_resetxlog 會猜測一些值, 直接-f生成控制檔案, 啟動資料庫後, 可能由于xid回歸到以前的xid而緻使資料"消失", 你可以使用txid_current()函數不斷的消耗xid來得到一緻的值.

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

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

使用pg_xlogdump從xlog中抽取資訊, 包括txid.

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

pg_resetxlog的版本必須要與資料庫叢集的版本一緻。

控制檔案和postgresql的大版本相關,建議使用者使用pg_resetxlog前,看一看對應版本的使用說明。

1. man pg_controldata

2. man pg_resetxlog

9. src/bin/pg_resetxlog/pg_resetxlog.c

10. src/include/catalog/pg_control.h

11. src/bin/pg_controldata/pg_controldata.c

12. src/backend/access/transam/clog.c

13. src/include/access/clog.h

14. src/backend/access/transam/xlog.c

15. src/include/access/xlog.h

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

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