<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 前言 PostgreSQL standby 可以通過兩種方法來激活成為主庫: 1. trigger file,配置在recovery.conf中。 2. pg_ctl promote發送SIGUSR1信號給postmaster進程。 同時,PostgreSQL支持快速激活(fast promote)和非快速激活(fallback promote): 1. fast promote?開啟數據庫讀寫前,不需要做檢查點。而是推到開啟讀寫之后執行一個CHECKPOINT_FORCE檢查點。 2. fallback_promote?在開啟數據庫讀寫前,需要先做一個檢查點,現在這個模式已經不對用戶開放,需要修改代碼,只是用作調試。 ## 實現分析 激活數據庫的代碼分析如下: 激活過程,根據fast_promote變量判斷是否需要先做檢查點,再激活。 ~~~ src/backend/access/transam/xlog.c if (InRecovery) { if (bgwriterLaunched) { if (fast_promote) // 如果是快速promote,在打開數據庫讀寫前,不需要創建檢查點。只需要創建一個recovery結束標記 { checkPointLoc = ControlFile->prevCheckPoint; record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, false); if (record != NULL) { fast_promoted = true; CreateEndOfRecoveryRecord(); } } if (!fast_promoted) // 如果是fallback_promote模式,須先創建一個檢查點,再開啟讀寫模式。 RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY | CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT); } ... InRecovery = false; // 開啟讀寫模式,允許接收用戶寫請求. LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->state = DB_IN_PRODUCTION; // 改寫控制文件的數據庫狀態 ControlFile->time = (pg_time_t) time(NULL); UpdateControlFile(); // 更新控制文件 LWLockRelease(ControlFileLock); ... if (fast_promoted) // 如果是快速promote,在允許用戶寫請求后,在這里執行一個檢查點。所以提高了數據庫的可用時間。 RequestCheckpoint(CHECKPOINT_FORCE); ...... ~~~ 通過pg_ctl命令行工具,向postmaster發SIGUSR1信號,通知它激活數據庫。 首先會寫一個promote文件,告訴postmaster,是fast_promote。 ~~~ src/bin/pg_ctl/pg_ctl.c /* * promote */ static void do_promote(void) { FILE *prmfile; pgpid_t pid; struct stat statbuf; pid = get_pgpid(false); ...... sig = SIGUSR1; if (kill((pid_t) pid, sig) != 0) // 發送SIGUSR1信號,通知postmaster激活數據庫。 { write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); if (unlink(promote_file) != 0) write_stderr(_("%s: could not remove promote signal file \"%s\": %s\n"), progname, promote_file, strerror(errno)); exit(1); } print_msg(_("server promoting\n")); } ~~~ 數據恢復時,檢查standby是否收到promote請求或是否存在trigger文件。 如果是promote請求,則檢查有沒有promote文件,或者fallback_promote文件,如果有promote文件,則是fast_promote請求。如果有fallback_promote文件,則不是fast_promote請求(實際上根本不可能檢測到fallback_promote文件,因為沒有寫這個文件的操作)。所以通過pg_ctl promote來激活,一定是fast promote的,即不需要先做檢查點再激活。 如果檢查到trigger文件,同樣也是fast promote激活模式。 ~~~ src/backend/access/transam/xlog.c #define PROMOTE_SIGNAL_FILE "promote" #define FALLBACK_PROMOTE_SIGNAL_FILE "fallback_promote" /* * Check to see whether the user-specified trigger file exists and whether a * promote request has arrived. If either condition holds, return true. */ static bool CheckForStandbyTrigger(void) { struct stat stat_buf; static bool triggered = false; if (triggered) return true; if (IsPromoteTriggered()) // 檢查是否收到pg_ctl promote信號 { ...... if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0) // 先檢查promote文件是否存在 { unlink(PROMOTE_SIGNAL_FILE); unlink(FALLBACK_PROMOTE_SIGNAL_FILE); fast_promote = true; // 快速promote } else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) // 否則再檢查fallback_promote文件是否存在 { unlink(FALLBACK_PROMOTE_SIGNAL_FILE); fast_promote = false; // 先執行checkpoint再promote } ereport(LOG, (errmsg("received promote request"))); ResetPromoteTriggered(); triggered = true; return true; } if (TriggerFile == NULL) // 檢查recovery.conf是否配置了trigger_file return false; if (stat(TriggerFile, &stat_buf) == 0) { ereport(LOG, (errmsg("trigger file found: %s", TriggerFile))); unlink(TriggerFile); triggered = true; fast_promote = true; // 快速promote return true; } else if (errno != ENOENT) ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat trigger file \"%s\": %m", TriggerFile))); return false; } src/backend/postmaster/startup.c pqsignal(SIGUSR2, StartupProcTriggerHandler); // 注冊SIGUSR2信號處理函數 /* SIGUSR2: set flag to finish recovery */ static void StartupProcTriggerHandler(SIGNAL_ARGS) { int save_errno = errno; promote_triggered = true; WakeupRecovery(); errno = save_errno; } bool IsPromoteTriggered(void) { return promote_triggered; } ~~~ postmaster收到SIGUSER1信號后,檢查是否收到promote信號,判斷當前的狀態是否處于恢復中的任意狀態,然后向startup進程發一個SIGUSR2的信號,觸發promote。 ~~~ src/backend/postmaster/postmaster.c pqsignal(SIGUSR1, sigusr1_handler); /* message from child process */ // 注冊SIGUSR1信號處理函數 /* * sigusr1_handler - handle signal conditions from child processes */ static void sigusr1_handler(SIGNAL_ARGS) { ...... if (CheckPromoteSignal() && StartupPID != 0 && (pmState == PM_STARTUP || pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY)) { /* Tell startup process to finish recovery */ signal_child(StartupPID, SIGUSR2); // 向startup進程發SIGUSR2信號,通知它處理promote } ...... src/backend/access/transam/xlog.c /* * Check to see if a promote request has arrived. Should be * called by postmaster after receiving SIGUSR1. */ bool CheckPromoteSignal(void) { struct stat stat_buf; if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 || stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0) return true; return false; } ~~~ 最后提一點, 9.3以前,曾經出現過pg_ctl promote -m 來指定是否需要fast promote或者fallback promote。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看