從數據庫啟動日志看PostgreSQL的崩潰恢復
瀏覽量: 次 發布日期:2023-09-12 21:35:13
從數據庫啟動日志看PostgreSQL的崩潰恢復
作者:吳聰
背景
今天碰到朋友問我個問題,數據庫啟動時日志中的這個“invalid record length at 3/EAA68B8: wanted 24, got 0”里面的wanted 24是啥意思。
而數據庫正常啟動時的日志其實并不是上面那樣,而是如下圖所示:
上圖的日志是因為數據庫異常關閉后重啟導致的,例如進程直接被kill。
為了搞清楚上面日志中的那條記錄是啥意思,我們來一起研究下數據庫異常關閉后恢復的過程。
陸家嘴數據恢復崩潰恢復概述
首先我們要清楚數據庫異常關閉和正常的停庫有啥區別。當數據庫異常關閉時,數據庫的共享緩沖區中的數據還沒有來得及刷到磁盤中,必然是會丟失,這個時候啟動數據庫便是從不正常的狀態去啟動,也就是我們要研究的崩潰恢復。
之前我也介紹過checkpoint相關的內容, 當PostgreSQL數據庫崩潰恢復時,會以最近的checkpoint為基礎,不斷應用這之后的XLOG日志。為了更好地理解PostgreSQL數據庫從崩潰中恢復的過程,我們需要弄清楚以下幾個問題:
數據庫操作系統如何識別到自己是非正常狀態(崩潰狀態)
數據庫如何找到合適的checkpoint作為基礎
為什么應用XLOG日志可以恢復數據庫數據
數據庫如何應用XLOG日志
數據庫狀態
無錫數據恢復在pg中數據庫狀態分為以下幾種(可以通過控制文件查看數據庫狀態):
當數據庫正常關閉時,數據庫狀態便是shut down,如果是異常關閉,可能會如下所示:
Database cluster state: in production
而每次當PostgreSQL數據庫啟動時,會首先讀取控制文件獲取數據庫的狀態,如果為非正常關閉狀態,則會執行崩潰恢復邏輯。
chekpoint相關結構
當數據庫進行崩潰恢復時,因為需要恢復異常關閉時丟失的共享內存中的數據,所以需要通過checkpoint來作為基礎,不斷的應用wal日志來恢復。而checkpoint相關的信息在pg中是存放在控制文件中的,由ControlFileData結構體存儲:
例如下圖所示:
一般來說都會選取最近一次的checkpoint作為恢復點,但是會存在一種情況:在執行最近一次的checkpoint是數據庫異常關閉了,那么這個檢查點可能是不完整的。因此一般還會多存儲一個檢查點的位置,即prevCheckPoint。
在數據庫崩潰恢復過程中,PostgreSQL規定了三個在啟動之前必須恢復到的最小位點:
minRecoveryPoint:
數據庫在歸檔恢復過程中,minRecoveryPoint被更新為最新被刷新到磁盤的LSN。每次數據庫啟動時必須已經replay該位置的XLOG日志記錄。
backupStartPoint:
數據庫在線備份開始時,會調用pg_start_backup函數執行一次checkpoint,并生成backup_label文件。當使用在線備份集進行恢復時,backupStartPoint就是上述checkpoint記錄對應的LSN,當達到了該LSN,該值置為0,在置為0之前,數據庫不能啟動。該值被記錄在backup_label文件中如下,直到在線備份結束,pg_stop_backup將該文件刪除。這樣就保證了在備份過程中,數據庫崩潰了,可以默認從備份開始時的日志檢查點開始恢復。
backupEndPoint:
當數據庫從一個備庫做的在線備份集進行恢復時,backupEndPoint表示備份結束的LSN,當達到該LSN,該值置為0,在置為0之前,數據庫不能啟動。
崩潰恢復具體過程:
每次postmaster進程啟動時,都會調用StartupXLOG函數對數據庫崩潰進行恢復。
其恢復過程大致為:
初始化內存,啟動后臺進程。
pg在啟動時讀取pg_control文件內容。如果state為’in production’,PostgreSQL將進入恢復模式,因為這意味著數據庫沒有正常停止;如果為’shutdown’,將進入正常啟動模式。
pg從相應的WAL段文件中讀取最新的檢查點記錄(位于pg_control文件中),并從記錄中獲取重做點。如果最新的檢查點記錄無效(invalid),pg將讀取前一個檢查點的記錄。如果兩個記錄都不可讀,將放棄恢復。注意,從11版本開始不會再存儲前一個檢查點的記錄信息。
使用合適的資源管理器從重做點開始按順序讀取和重放WAL記錄,直到最新WAL文件的最后位置。當遇到備份塊時,無論其LSN如何,都會將覆蓋相應表的頁面。否則僅當此wal記錄LSN>相應頁面的pd_lsn時,才會重放該WAL記錄。
崩潰恢復日志
介紹了這么多,我們再來看看為什么在崩潰恢復時數據庫的日志中輸出內容是那樣的。
因為檢測到數據庫為異常狀態,所以需要從最近一次檢查點開始按順序讀取wal日志:
當檢測到沒有wal日志可以重放時,便會拋出前面的提示:“invalid record length at 3/EAA6580: wanted 24, got 0”。那你可能要問為啥為wanted 24,不是25,26。。。
那我們接著看:
顯然這里的24就是SizeOfXLogRecord,其計算方法如下:
這里需要注意,XLogRecord結構體中有2bytes的填充位。
總結
一個簡單的數據庫啟動日志竟然包含著這么多知識!
參考鏈接:
https://www.pgcon.org/2012/schedule/attachments/258_212_Internals%20Of%20PostgreSQL%20Wal.pdf
上海數據恢復http://mysql.taobao.org/monthly/2017/05/03/
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogreader.c
規模空前,再創歷史 | 2020 PG亞洲大會圓滿結束PG ACE計劃的正式發布三期PostgreSQL國際線上沙龍活動的舉辦六期PostgreSQL國內線上沙龍活動的舉辦
中國PostgreSQL分會與騰訊云戰略合作協議簽訂
PostgreSQL 13.0 正式版發布通告
深度報告:開源協議那些事兒
從“非主流”到“潮流”,開源早已值得擁有
Oracle中國正在進行新一輪裁員,傳 N+6 補償
PostgreSQL與MySQL版權比較
新聞|Babelfish使PostgreSQL直接兼容sql server應用程序
四年三冠,PostgreSQL再度榮獲“年度數據庫”
更多新聞資訊,行業動態,技術熱點,請關注中國PostgreSQL分會官方網站
https://www.postgresqlchina.com
中國PostgreSQL分會生態產品
https://www.pgfans.cn
中國PostgreSQL分會資源下載站
https://www.postgreshub.cn