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
祝大家玩得開心,歡迎随時來 阿裡雲促膝長談業務需求 ,恭候光臨。
阿裡雲的小夥伴們加油,努力 做好核心與服務,打造最貼地氣的雲資料庫 。