复制不是备份。 或不? 以下是我们如何使用延迟复制来从意外删除的快捷方式中恢复。
复制不是备份数据库的一种方式(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
几乎立即在工作集群上的所有副本中复制,因此普通复制在这里没有帮助。 当租用单个服务器并分配负载时,复制本身可以保持数据库可用。
即使使用延迟副本,如果数据中心发生故障、隐藏损坏或其他无法立即注意到的事件发生,我们有时也确实需要在安全的地方进行冷备份。 单独的复制在这里是没有用的。
注意。 上
来源: habr.com