PostgreSQL狀態變遷
typedef enum DBState { DB_STARTUP = 0, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DB_SHUTDOWNING, DB_IN_CRASH_RECOVERY, DB_IN_ARCHIVE_RECOVERY, DB_IN_PRODUCTION } DBState;
PostgreSQL啟動以及關閉或執行過程中的狀態包括以上七種。在pg_controldata獲取的內容Database cluster state一欄顯示的是DB的狀態。其中:
DB_STARTUP:表示資料庫正在啟動狀態,實際上沒有使用該狀態。
DB_SHUTDOWNED:資料庫例項正常關閉(非standby)控制檔案寫入的狀態就是這個狀態
DB_SHUTDOWNED_IN_RECOVERY:standby例項正常關閉,控制檔案寫入的狀態是這個狀態。是由CreateRestartPoint修改該狀態。
DB_SHUTDOWNING:非standby例項在關閉時,做checkpoint:CreateCheckPoint,開始做時修改為該狀態,做完後修改為DB_SHUTDOWNED狀態。
DB_IN_CRASH_RECOVERY:例項異常關閉,重啟後,恢復時需要將例項先置為該狀態
DB_IN_ARCHIVE_RECOVERY:standby例項重啟後置為該狀態。
DB_IN_PRODUCTION:非standby例項正常重啟後就是這個狀態,standby是DB_IN_ARCHIVE_RECOVERY
分析
1、DB_STARTUP
initdb->BootStrapXLOG: memset(ControlFile, 0, sizeof(ControlFileData)); ... ControlFile->state = DB_SHUTDOWNED; ... WriteControlFile();
初始化時,首先將其狀態初始化為DB_STARTUP,然後立即置成DB_SHUTDOWNED並將其刷寫到磁碟。
2、StartupXLOG
StartupXLOG-> ReadControlFile(); ... readRecoveryCommandFile();-> |--... | for (item = head; item; item = item->next){ | if (strcmp(item->name, "restore_command") == 0){ | ... | }... | else if (strcmp(item->name, "standby_mode") == 0){ | if (!parse_bool(item->value, &StandbyModeRequested)) | }... | } | ... |-- ArchiveRecoveryRequested = true; ... if (ArchiveRecoveryRequested && (ControlFile->minRecoveryPoint != InvalidXLogRecPtr || ControlFile->backupEndRequired || ControlFile->backupEndPoint != InvalidXLogRecPtr || ControlFile->state == DB_SHUTDOWNED)){ InArchiveRecovery = true; if (StandbyModeRequested) StandbyMode = true; } ... record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, true); ... if (InRecovery){ if (InArchiveRecovery)//何時? ControlFile->state = DB_IN_ARCHIVE_RECOVERY; else ControlFile->state = DB_IN_CRASH_RECOVERY; ... UpdateControlFile(); replay... } ... LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->state = DB_IN_PRODUCTION; UpdateControlFile(); LWLockRelease(ControlFileLock); ...
只要有recovery.conf檔案,ArchiveRecoveryRequested即為TRUE->InArchiveRecovery = true,配置了standby_mode=on,那麼StandbyMode=TRUE。這樣standby啟動後,ControlFile->state為DB_IN_ARCHIVE_RECOVERY狀態。
3、checkpoint
CheckpointerMain-> for (;;){ ... if (shutdown_requested){ ShutdownXLOG(0, 0);-> |--if (RecoveryInProgress()){ | CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); | }else{ | CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); | } |--... proc_exit(0); } ... if (do_checkpoint){ do_restartpoint = RecoveryInProgress(); ... if (flags & CHECKPOINT_END_OF_RECOVERY)//flags從哪來? do_restartpoint = false; ... if (!do_restartpoint){ CreateCheckPoint(flags); ckpt_performed = true; } else ckpt_performed = CreateRestartPoint(flags); } }
備機上做checkpoint呼叫CreateRestartPoint,主機做checkpoint呼叫CreateCheckPoint
CreateCheckPoint(int flags)-> if (flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY)) shutdown = true; else shutdown = false; ... if (shutdown){ LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->state = DB_SHUTDOWNING; ControlFile->time = (pg_time_t) time(NULL); UpdateControlFile(); LWLockRelease(ControlFileLock); } ... LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); if (shutdown) ControlFile->state = DB_SHUTDOWNED; ... UpdateControlFile(); LWLockRelease(ControlFileLock);
shutdown時,先將狀態置為DB_SHUTDOWNING,最後將狀態置為DB_SHUTDOWNED
CreateRestartPoint(int flags)-> LWLockAcquire(CheckpointLock, LW_EXCLUSIVE); SpinLockAcquire(&XLogCtl->info_lck); lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr; lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr; lastCheckPoint = XLogCtl->lastCheckPoint; SpinLockRelease(&XLogCtl->info_lck); if (!RecoveryInProgress()){ LWLockRelease(CheckpointLock); return false; } ... if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||lastCheckPoint.redo <= ControlFile->checkPointCopy.redo){ UpdateMinRecoveryPoint(InvalidXLogRecPtr, true); if (flags & CHECKPOINT_IS_SHUTDOWN){ LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; ControlFile->time = (pg_time_t) time(NULL); UpdateControlFile(); LWLockRelease(ControlFileLock); } LWLockRelease(CheckpointLock); return false; } ... LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY && ControlFile->checkPointCopy.redo < lastCheckPoint.redo){ ... if (flags & CHECKPOINT_IS_SHUTDOWN) ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; UpdateControlFile(); } LWLockRelease(ControlFileLock); ...
備機shutdown,將狀態置為DB_SHUTDOWNED_IN_RECOVERY
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31493717/viewspace-2212617/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PV 與 PVC 狀態遷移
- 狀態變化模式模式
- PostgreSQL的idle in transaction連線狀態SQL
- React專題:可變狀態React
- 用設計模式去掉沒必要的狀態變數 —— 狀態模式設計模式變數
- win10怎麼把狀態列變透明_win10狀態列變透明方法Win10
- 多級稽核狀態的變更
- 獲取Mysql的狀態、變數MySql變數
- 讓 Promise 的狀態變成可控的Promise
- Linux下共享VG改變活動狀態Linux
- Zustand 讓 React 狀態變得太簡單React
- 2020DevOps狀態報告——變更管理dev
- 使用列舉實現狀態機來優雅你的狀態變更邏輯
- Flutter改變狀態列字型、狀態列背景顏色、Appbar背景顏色的方式FlutterAPP
- 執行緒的6種狀態以及轉變執行緒
- HarmonyOS 實踐之應用狀態變數共享變數
- C++ 接受狀態變數的lambda表示式C++變數
- flink學習(加餐)——job任務狀態變化
- MySQL 變數及效能狀態檢視知識技巧MySql變數
- “遷移策略+新容器執行時”應對有狀態應用的冷熱遷移挑戰
- 前端狀態管理與有限狀態機前端
- React專案實踐(二)一個登入頁面的狀態遷移React
- 使用GoldenGate 遷移Oracle到PostgreSQL/LightDBGoOracleSQL
- Android 沉浸式狀態列 漸變顏色的實現Android
- React 狀態管理:狀態與生命週期React
- [二、狀態管理]2管理元件擁有的狀態(5)@Observed裝飾器和@ObjectLink裝飾器:巢狀類物件屬性變化元件Object巢狀物件
- 狀態機
- 狀態列
- 狀態碼
- 狀態管理
- 頁面狀態改變會觸發的一些事件事件
- HarmonyOS NEXT應用開發案例—狀態列顯隱變化
- 變電站刀閘開合閘狀態識別系統
- Android的標題欄,狀態列圖示文字顏色及背景動態變化Android
- Vuex 單狀態庫 與 多模組狀態庫Vue
- 有限狀態機
- Vuex狀態管理Vue
- 調整狀態