複製不是備份。 或不? 以下是我們如何使用延遲複製來從意外刪除的快捷方式中恢復。
複製不是備份資料庫的一種方式(gitlab-ce
通過延遲副本,我們僅用了 1,5 小時就恢復了數據。 看看它是怎麼發生的。
使用 PostgreSQL 進行時間點恢復
PostgreSQL 有一個內建函數可以將資料庫的狀態還原到特定時間點。 它被稱為
為了使用此功能進行冷備份,我們定期進行基本的數據庫備份並將其存儲在存檔中(GitLab 存檔位於
什麼是延遲複製?
延遲複製是延遲應用 WAL 變更。 即交易在一小時內發生 X
,但它會延遲出現在副本中 d
一個小時內 X + d
.
PostgreSQL 有兩種設定實體資料庫副本的方法:備份還原和流複製。
如何設置從存檔延遲恢復
recovery.conf
. 例子:
standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'
使用這些參數,我們配置了具有備份恢復功能的延遲副本。 這裡用到的是 restore_command
)從存檔中,更改將在八小時後應用(recovery_min_apply_delay
)。 副本將監視存檔中的時間軸更改,例如由於群集故障轉移(recovery_target_timeline
).
С recovery_min_apply_delay
您可以設定延遲的串流複製,但這裡存在一些與複製槽、熱備用回饋等相關的陷阱。 WAL 檔案可讓您避免它們。
參數 recovery_min_apply_delay
僅出現在 PostgreSQL 9.3 中。 在以前的版本中,對於延遲複製,您需要配置組合 pg_xlog_replay_pause(), pg_xlog_replay_resume()
) 或在延遲期間將 WAL 段保留在檔案中。
PostgreSQL 是如何做到這一點的呢?
看看 PostgreSQL 如何實現延遲復原很有趣。 讓我們看看 recoveryApplyDelay(XlogReaderState)
static bool
recoveryApplyDelay(XLogReaderState *record)
{
uint8 xact_info;
TimestampTz xtime;
long secs;
int microsecs;
/* nothing to do if no delay configured */
if (recovery_min_apply_delay <= 0)
return false;
/* no delay is applied on a database not yet consistent */
if (!reachedConsistency)
return false;
/*
* Is it a COMMIT record?
*
* We deliberately choose not to delay aborts since they have no effect on
* MVCC. We already allow replay of records that don't have a timestamp,
* so there is already opportunity for issues caused by early conflicts on
* standbys.
*/
if (XLogRecGetRmid(record) != RM_XACT_ID)
return false;
xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
if (xact_info != XLOG_XACT_COMMIT &&
xact_info != XLOG_XACT_COMMIT_PREPARED)
return false;
if (!getRecordTimestamp(record, &xtime))
return false;
recoveryDelayUntilTime =
TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);
/*
* Exit without arming the latch if it's already past time to apply this
* record
*/
TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
&secs, µsecs);
if (secs <= 0 && microsecs <= 0)
return false;
while (true)
{
// Shortened:
// Use WaitLatch until we reached recoveryDelayUntilTime
// and then
break;
}
return true;
}
最重要的是,延遲是基於事務提交時間戳中記錄的物理時間(xtime
)。 正如您所看到的,延遲僅適用於提交,不會影響其他條目 - 所有更改都直接應用,並且提交被延遲,因此我們只會看到配置的延遲之後的更改。
如何使用延遲副本恢復數據
假設我們有一個數據庫集群和一個生產延遲八小時的副本。 讓我們通過一個例子來看看如何恢復數據
當我們了解這個問題後,我們
SELECT pg_xlog_replay_pause();
暫停後,我們就不會有副本重複請求的風險 DELETE
。 如果您需要時間來解決所有問題,這很有用。
關鍵是延遲的副本必須到達請求之前的時刻 DELETE
。 我們大致知道搬遷的實際時間。 我們已經刪除了 recovery_min_apply_delay
並且添加了 recovery_target_time
в recovery.conf
。 這就是副本如何毫不延遲地到達正確時刻的方式:
recovery_target_time = '2018-10-12 09:25:00+00'
有了時間戳,最好減少多餘的部分,以免錯過。 確實,減少的幅度越大,我們遺失的資料就越多。 再說一遍,如果我們錯過了請求 DELETE
,所有內容都將被再次刪除,您將不得不重新開始(甚至為 PITR 進行冷備份)。
我們重新啟動了延遲的 Postgres 實例,並且重複 WAL 段直到指定的時間。 您可以通過詢問以下問題來跟踪此階段的進度:
SELECT
-- current location in WAL
pg_last_xlog_replay_location(),
-- current transaction timestamp (state of the replica)
pg_last_xact_replay_timestamp(),
-- current physical time
now(),
-- the amount of time still to be applied until recovery_target_time has been reached
'2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
如果時間戳不再改變,則恢復完成。 動作可自訂 recovery_target_action
數據庫返回到該不幸請求之前的狀態。 例如,現在您可以導出數據。 我們導出了已刪除的標籤數據以及問題和合併請求的所有鏈接,並將它們移至生產數據庫中。 如果損失規模較大,可以簡單地推廣副本並將其作為主副本。 但是,我們恢復到的點之後的所有更改都將丟失。
最好使用事務 ID,而不是時間戳。 記錄這些 ID 很有用,例如對於 DDL 語句(例如 DROP TABLE
), 通過使用 log_statements = 'ddl'
。 如果我們有交易 ID,我們會採取 recovery_target_xid
並在請求之前運行所有事務 DELETE
.
恢復工作非常簡單:刪除所有更改 recovery.conf
並重新啟動 Postgres。 副本很快就會再次出現八小時的延遲,我們已經做好了應對未來麻煩的準備。
恢復福利
使用延遲副本而不是冷備份,您不必花費數小時從存檔中恢復整個映像。 例如,我們需要五個小時才能獲得整個基本的 2 TB 備份。 然後你仍然需要應用整個每日 WAL 來恢復到所需的狀態(在最壞的情況下)。
延遲副本在兩個方面優於冷備份:
- 無需從存檔中刪除整個基本備份。
- WAL 段有一個固定的八小時窗口,必須重複。
我們也不斷檢查是否可以從 WAL 產生 PITR,並且透過監視延遲副本的滯後,我們很快就會注意到 WAL 存檔的損壞或其他問題。
在這個例子中,我們花了 50 分鐘來恢復,這意味著速度是每小時 110 GB 的 WAL 資料(存檔仍然在
結果:延遲副本在哪裡有用(以及在哪裡沒有用)
如果您意外丟失數據並在配置的延遲內發現此問題,請使用延遲複製作為急救措施。
但請記住:複製不是備份。
備份和復制有不同的目的。 如果您不小心創建了冷備份,那麼冷備份會派上用場 DELETE
或 DROP TABLE
。 我們從冷存儲中進行備份並恢復表或整個數據庫的先前狀態。 但同時要求 DROP TABLE
幾乎立即在工作叢集上的所有副本中複製,因此普通複製在這裡沒有幫助。 當租用單一伺服器並分配負載時,複製本身可以保持資料庫可用。
即使使用延遲副本,如果資料中心發生故障、隱藏損壞或其他無法立即註意到的事件發生,我們有時確實需要在安全的地方進行冷備份。 單獨的複製在這裡是沒有用的。
注意。 上
來源: www.habr.com