25.3. 连续归档和时间点恢复(PITR)

PostgreSQL 始终在集群数据目录的pg_wal/子目录中维护* WAL(预写日志)*。日志记录了对数据库数据文件所做的所有更改。该日志主要用于崩溃安全目的:如果系统崩溃,则可以通过“重播”自上一个检查点以来创建的日志条目来恢复数据库的一致性。但是,日志的存在使得可以使用第三种策略来备份数据库:我们可以将文件系统级备份与 WAL 文件备份结合在一起。如果需要恢复,我们将还原文件系统备份,然后从备份的 WAL 文件中重播以使系统进入当前状态。与以前的任何一种方法相比,这种方法的 Management 更为复杂,但具有一些明显的好处:

  • 我们不需要完美一致的文件系统备份作为起点。备份中的任何内部不一致都会通过日志重播进行纠正(这与崩溃恢复期间发生的变化没有太大的不同)。因此,我们不需要文件系统快照功能,而只需 tar 或类似的存档工具。

  • 由于我们可以组合无限长的 WAL 文件序列进行重放,因此只需 continue 存档 WAL 文件就可以实现连续备份。这对于大型数据库来说尤其有价值,在大型数据库中,经常进行完整备份可能不方便。

  • 不必一直重复播放 WAL 条目。我们可以在任何时候停止重播,并保持数据库当时的一致快照。因此,该技术支持时间点恢复:自从进行基本备份以来,可以随时将数据库恢复到其状态。

  • 如果我们将一系列 WAL 文件连续提供给另一台已加载了相同基本备份文件的计算机,则我们将拥有一个* warm Standby *系统:在任何时候,我们都可以启动第二台计算机,而该计算机将具有近乎最新的状态。数据库副本。

Note

pg_dump 和 pg_dumpall 不会产生文件系统级的备份,因此不能用作连续归档解决方案的一部分。这样的转储是“逻辑的”,并且没有包含足够的信息以供 WAL 重放使用。

与普通文件系统备份技术一样,此方法只能支持还原整个数据库群集,而不能还原子集。此外,它还需要大量 Files 存储:基本备份可能很庞大,并且繁忙的系统将生成许多 MB 的 WAL 流量,必须对其进行存档。尽管如此,在许多需要高可靠性的情况下,它还是首选的备份技术。

要使用连续归档(许多数据库供应商也称为“在线备份”)成功恢复,您需要连续的 WAL 归档文件序列,该序列至少可以延伸到备份的开始时间。因此,开始之前,您应该在进行第一次基本备份之前*设置并测试用于存档 WAL 文件的过程。因此,我们首先讨论归档 WAL 文件的机制。

25 .3.1. 设置 WAL 归档

从抽象的意义上说,运行中的 PostgreSQL 系统会产生无限长的 WAL 记录序列。系统从物理上将此序列划分为 WAL 段文件,通常每个 16MB(尽管在构建 PostgreSQL 时可以更改段大小)。段文件被赋予数字名称,以反映它们在抽象 WAL 序列中的位置。当不使用 WAL 归档时,系统通常只创建几个段文件,然后通过将不再需要的段文件重命名为较高的段号来“回收”它们。假定不再关注其内容在 checkpoint-before-last 之前的段文件,可以对其进行回收。

归档 WAL 数据时,我们需要在每个段文件填充后捕获其内容,并将该数据保存在回收段文件以供重用之前的某个位置。根据应用程序和可用硬件的不同,可以有许多不同的“将数据保存到某处”的方式:我们可以将段文件复制到另一台计算机上 NFS 挂载的目录中,然后将它们写入磁带驱动器(确保您拥有一种识别每个文件的原始名称的方法),或将它们一起批处理并刻录到 CD 上,或完全刻录成其他东西。为了给数据库 Management 员提供灵 Active,PostgreSQL 尝试不对如何完成归档做任何假设。相反,PostgreSQL 让 Management 员指定要执行的 shell 命令,以将完整的段文件复制到需要的位置。该命令可以像cp一样简单,也可以调用复杂的 shell 脚本-一切由您决定。

要启用 WAL 归档,请将wal_level配置参数设置为replica或更高版本,将archive_mode设置为on,并在archive_command配置参数中指定要使用的 shell 命令。实际上,这些设置将始终放在postgresql.conf文件中。在archive_command中,将%p替换为要归档的文件的路径名,而将%f仅替换为文件名。 (路径名相对于当前工作目录,即集群的数据目录.)如果需要在命令中嵌入实际的%字符,请使用%%。最简单的有用命令是:

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  # Unix
archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows

它将可归档的 WAL 段复制到目录/mnt/server/archivedir。 (这是一个示例,不作为建议,并且可能不适用于所有平台.)替换了%p%f参数后,实际执行的命令可能如下所示:

test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065

将为每个要归档的新文件生成一个类似的命令。

将以运行 PostgreSQL 服务器的同一用户的所有权执行 archive 命令。由于要归档的一系列 WAL 文件实际上包含数据库中的所有内容,因此您将要确保已归档的数据受到保护,以免被窥探;例如,存档到没有组或世界读取访问权限的目录中。

重要的是,归档存档命令只有在成功时才返回零退出状态。结果为零时,PostgreSQL 将假定该文件已成功归档,并将删除或回收它。但是,非零状态会告诉 PostgreSQL 该文件尚未归档。它将定期重试,直到成功。

通常应将 archive 命令设计为拒绝覆盖任何先前存在的归档文件。这是一项重要的安全功能,可以在 Management 员出错(例如将两个不同服务器的输出发送到同一存档目录)时保持存档的完整性。

建议测试建议的归档命令以确保它确实不会覆盖现有文件,并且在这种情况下返回非零状态。上面用于 Unix 的示例命令通过包含一个单独的test步骤来确保这一点。在某些 Unix 平台上,cp具有诸如-i之类的开关,这些开关可用于更轻松地完成相同的操作,但是在不验证是否返回正确的退出状态的情况下,请勿依赖这些开关。 (特别是,当使用-i并且目标文件已经存在时,GNU cp将返回状态零,这不是*所需的行为.)

在设计归档设置时,请考虑如果由于某些方面需要操作员干预或归档空间不足而导致归档命令反复失败会发生什么情况。例如,如果您在没有自动转换器的情况下写入磁带,则可能会发生这种情况。当磁带装满时,在交换磁带之前,无法进一步存储任何内容。您应该确保适当地报告任何错误情况或对操作员的要求,以便可以迅速地解决问题。 pg_wal/目录将 continue 填充 WAL 段文件,直到问题解决。 (如果包含pg_wal/的文件系统被填满,PostgreSQL 将关闭 PANIC.不会丢失任何已提交的事务,但是数据库将保持脱机状态,直到您释放一些空间.)

归档命令的速度并不重要,只要它能跟上服务器生成 WAL 数据的平均速率即可。即使归档过程落后一点,正常操作仍会 continue。如果归档明显滞后,这将增加发生灾难时丢失的数据量。这也意味着pg_wal/目录将包含大量尚未归档的段文件,这些文件最终可能会超出可用磁盘空间。建议您监视归档过程,以确保它按预期工作。

在编写归档命令时,应假定要归档的文件名最长为 64 个字符,并且可以包含 ASCII 字母,数字和点的任意组合。不必保留原始的相对路径(%p),但必须保留文件名(%f)。

请注意,尽管 WAL 归档将允许您恢复对 PostgreSQL 数据库中的数据所做的任何修改,但不会恢复对配置文件(即postgresql.confpg_hba.confpg_ident.conf)所做的更改,因为这些更改是手动而不是通过 SQL 编辑的。操作。您可能希望将配置文件保存在将由常规文件系统备份过程备份的位置。有关如何重新放置配置文件,请参见Section 19.2

仅在完成的 WAL 段上调用 archive 命令。因此,如果您的服务器仅产生很少的 WAL 流量(或在此期间有闲置时间),则在事务完成和将其安全记录到归档存储之间可能会有很长的延迟。要限制未归档数据的可用时间,可以设置archive_timeout强制服务器至少经常切换到新的 WAL 段文件。请注意,由于强制切换而提前存档的存档文件的长度仍然与完全完整的文件相同。因此,设置一个非常短的archive_timeout是不明智的,它会使 Files 存储空间过大。 archive_timeout一分钟左右的设置通常是合理的。

此外,如果要确保尽快完成刚刚完成的 Transaction,可以使用pg_switch_wal手动强制进行分段切换。与 WALManagement 有关的其他 Util 功能在Table 9.79中列出。

wal_levelminimal时,将优化某些 SQL 命令以避免 WAL 日志记录,如Section 14.4.7中所述。如果在执行这些语句之一的过程中打开了归档或流复制,则 WAL 将没有足够的信息来进行归档恢复。 (崩溃恢复不受影响.)因此,只能在服务器启动时更改wal_level。但是,archive_command可以通过重新加载配置文件来更改。如果您希望暂时停止存档,一种方法是将archive_command设置为空字符串('')。这将导致 WAL 文件在pg_wal/中累积,直到重新构建有效的archive_command

25 .3.2. 进行基本备份

执行基本备份的最简单方法是使用pg_basebackup工具。它可以将基本备份创建为常规文件或 tar 存档。如果需要的灵 Active 比pg_basebackup所提供的更大,则还可以使用低级 API 进行基本备份(请参见Section 25.3.3)。

不必担心进行基本备份所花费的时间。但是,如果通常在禁用full_page_writes的情况下运行服务器,则在备份运行时可能会注意到性能下降,因为在备份模式下有效地启用了full_page_writes

要使用备份,您将需要保留在文件系统备份期间和之后生成的所有 WAL 段文件。为了帮助您执行此操作,基本备份过程将创建一个备份历史文件,该文件将立即存储到 WAL 存档区域中。该文件以文件系统备份所需的第一个 WAL 段文件命名。例如,如果起始 WAL 文件是0000000100001234000055CD,则备份历史记录文件将被命名为0000000100001234000055CD.007C9330.backup。 (文件名的第二部分代表 WAL 文件中的确切位置,通常可以忽略.)一旦安全地归档了文件系统备份和备份期间使用的 WAL 段文件(在备份历史 Logging 指定)文件),则不再需要使用名称在数字上较少的所有已归档 WAL 段来恢复文件系统备份,并且可以将其删除。但是,您应该考虑保留几个备份集,以确保可以恢复数据。

备份历史记录文件只是一个小文本文件。它包含您提供给pg_basebackup的标签字符串,以及备份的开始和结束时间以及 WAL 段。如果使用标签来标识关联的转储文件,则存档的历史文件足以告诉您要还原哪个转储文件。

由于必须将所有已归档的 WAL 文件保留到最后一次基本备份,因此通常应根据要在已归档的 WAL 文件上花费多少存储空间来选择基本备份之间的间隔。您还应该考虑准备花多长时间恢复,如果有必要恢复的话-系统将必须重播所有这些 WAL 段,如果距离上次基本备份已经很长时间了,那可能要花一些时间。

25 .3.3. 使用低级 API 进行基本备份

使用低级 API 进行基本备份的过程比pg_basebackup方法包含更多步骤,但是相对简单。依次执行这些步骤,并在 continue 进行下一步之前验证步骤的成功是非常重要的。

低级基础备份可以以非排他或排他的方式进行。建议使用非排他性方法,不建议使用排他性方法,最终将其删除。

25 .3.3.1. 进行非排他的低级备份

非排他性低级备份是一种允许其他并发备份正在运行的备份(使用相同备份 API 启动的备份和使用pg_basebackup启动的备份)。

  • 确保已启用 WAL 归档并且可以正常工作。

  • 以具有运行 pg_start_backup 的权限的用户(超级用户,或已在函数中被授予 EXECUTE 的用户)身份连接到服务器(无论哪个数据库),并发出以下命令:

SELECT pg_start_backup('label', false, false);

其中label是您要用来唯一标识此备份操作的任何字符串。必须维持调用pg_start_backup的连接,直到备份结束,否则备份将自动中止。

默认情况下,pg_start_backup可能需要很长时间才能完成。这是因为它执行检查点,并且检查点所需的 I/O 将在相当长的一段时间内分散,默认情况下为检查点间间隔的一半(请参阅配置参数checkpoint_completion_target)。通常这就是您想要的,因为它最大程度地减少了对查询处理的影响。如果要尽快开始备份,请将第二个参数更改为true,它将使用尽可能多的 I/O 发出立即检查点。

第三个参数false告诉pg_start_backup启动非独占的基本备份。

  • 使用任何方便的文件系统备份工具(例如 tar 或 cpio(而不是 pg_dump 或 pg_dumpall))执行备份。在执行此操作时,既没有必要也不要停止数据库的正常运行。有关此备份期间要考虑的事项,请参见Section 25.3.3.3

  • 在与以前相同的 Connecting,发出命令:

SELECT * FROM pg_stop_backup(false, true);

这将终止备份模式。在主数据库上,它还会自动切换到下一个 WAL 段。在备用数据库上,无法自动切换 WAL 段,因此您可能希望在主数据库上运行pg_switch_wal以执行手动切换。进行此切换的原因是安排备份间隔期间写入的最后一个 WAL 段文件准备好存档。

pg_stop_backup将返回包含三个值的一行。这些字段中的第二个字段应写入备份根目录中名为backup_label的文件中。除非该字段为空,否则应将第三个字段写入名为tablespace_map的文件。这些文件对于备份的工作至关重要,必须编写且未经修改。

  • 一旦备份期间激活的 WAL 段文件被存档,就完成了。 pg_stop_backup的第一个返回值标识的文件是形成完整备份文件集所需的最后一个段。在主数据库上,如果启用了archive_modewait_for_archive参数为true,则pg_stop_backup直到归档最后一个段才返回。在备用数据库中,archive_mode必须是always才能使pg_stop_backupawait。由于已经配置archive_command,因此将自动进行这些文件的归档。在大多数情况下,这种情况很快发生,但建议您监视存档系统以确保没有延迟。如果由于归档命令失败而导致归档过程落后,它将 continue 重试,直到归档成功并且备份完成为止。如果希望对pg_stop_backup的执行设置时间限制,请设置适当的statement_timeout值,但请注意,如果pg_stop_backup终止,则您的备份可能无效。

如果备份过程监视并确保成功备份所需的所有 WAL 段文件,则可以将wait_for_archive参数(默认为 true)设置为 false,以在停止备份记录写入 WAL 后立即返回pg_stop_backup。 。默认情况下,pg_stop_backup将 await 直到所有 WAL 被存档为止,这可能需要一些时间。必须谨慎使用此选项:如果未正确监视 WAL 归档,则备份可能不包括所有 WAL 文件,因此备份将不完整且无法还原。

25 .3.3.2. 进行独家低级备份

排他备份的过程与非排他备份的过程基本相同,但是在几个关键步骤上有所不同。这种类型的备份只能在主数据库上进行,不允许同时进行备份。在 PostgreSQL 9.6 之前,这是唯一可用的低级方法,但是现在建议所有用户升级他们的脚本,以尽可能使用非排他性备份。

  • 确保已启用 WAL 归档并且可以正常工作。

  • 以具有运行 pg_start_backup 的权限的用户(超级用户,或已在函数中被授予 EXECUTE 的用户)身份连接到服务器(无论哪个数据库),并发出以下命令:

SELECT pg_start_backup('label');

其中label是您要用来唯一标识此备份操作的任何字符串。 pg_start_backup在群集目录中创建一个名为backup_label的* backup label 文件,其中包含有关备份的信息,包括开始时间和标签字符串。如果存在一个或多个这样的链接,该函数还将在群集目录中创建一个名为tablespace_map tablespace map *文件,其中包含有关pg_tblspc/中的表空间符号链接的信息。如果您需要从备份中恢复,这两个文件对于备份完整性至关重要。

默认情况下,pg_start_backup可能需要很长时间才能完成。这是因为它执行检查点,并且检查点所需的 I/O 将在相当长的一段时间内分散,默认情况下为检查点间间隔的一半(请参阅配置参数checkpoint_completion_target)。通常这就是您想要的,因为它最大程度地减少了对查询处理的影响。如果要尽快开始备份,请使用:

SELECT pg_start_backup('label', true);

这迫使检查点尽快完成。

  • 使用任何方便的文件系统备份工具(例如 tar 或 cpio(而不是 pg_dump 或 pg_dumpall))执行备份。在执行此操作时,既没有必要也不要停止数据库的正常运行。有关此备份期间要考虑的事项,请参见Section 25.3.3.3

请注意,如果服务器在备份过程中崩溃,则必须先从PGDATA目录中手动删除backup_label文件,然后才能重新启动。

  • 再次以具有运行 pg_stop_backup 权限的用户身份(超级用户或已被授予执行该功能的用户的身份)连接到数据库,并发出以下命令:
SELECT pg_stop_backup();

此功能终止备份模式,并自动切换到下一个 WAL 段。进行此切换的原因是安排备份间隔期间写入的最后一个 WAL 段准备好存档。

  • 一旦备份期间激活的 WAL 段文件被存档,就完成了。用pg_stop_backup的结果标识的文件是形成完整备份文件集所需的最后一个段。如果启用了archive_mode,则pg_stop_backup在归档最后一个段之前不会返回。由于已配置archive_command,因此将自动进行这些文件的归档。在大多数情况下,这种情况很快发生,但建议您监视存档系统以确保没有延迟。如果由于归档命令失败而导致归档过程落后,它将 continue 重试,直到归档成功并且备份完成为止。如果希望对pg_stop_backup的执行设置时间限制,请设置适当的statement_timeout值,但请注意,如果pg_stop_backup终止,则您的备份可能无效。

25 .3.3.3. 备份数据目录

如果某些文件系统备份工具尝试复制的文件在复制进行过程中发生更改,则会发出警告或错误。对活动数据库进行基本备份时,这种情况是正常现象,而不是错误。但是,您需要确保可以将此类投诉与实际错误区分开。例如,某些版本的 rsync 会为“消失的源文件”返回单独的退出代码,并且您可以编写驱动程序脚本以将该退出代码作为非错误情况接受。另外,如果 tar 复制文件时文件被截断,则某些版本的 GNU tar 返回的错误代码与致命错误没有区别。幸运的是,如果在备份过程中更改了文件,则 GNU tar 版本 1.16 和更高版本以 1 退出,而其他错误则退出 2.在 GNU tar 版本 1.23 和更高版本中,您可以使用警告选项--warning=no-file-changed --warning=no-file-removed隐藏相关的警告消息。

请确保您的备份包含数据库集群目录(例如/usr/local/pgsql/data)下的所有文件。如果您使用的表空间不位于此目录下,则还应小心地将它们包括在内(并确保备份将符号链接归档为链接,否则还原将破坏您的表空间)。

但是,您应该从备份中忽略群集的pg_wal/子目录中的文件。这种轻微的调整是值得的,因为它减少了还原时出错的风险。如果pg_wal/是指向群集目录外部某个位置的符号链接,则这很容易安排,出于性能原因,这是常见的设置。您可能还希望排除postmaster.pidpostmaster.opts,它们记录有关正在运行的邮局主管的信息,而不是有关最终将使用此备份的邮局主管的信息。 (这些文件会混淆 pg_ctl.)

通常,最好也从备份中省略群集的pg_replslot/目录中的文件,以使主服务器上存在的复制插槽不会成为备份的一部分。否则,随后使用备份创建备用数据库可能会导致 WAL 文件无限期保留在备用数据库上,并且如果启用了热备用反馈,可能会导致主数据库上的膨胀,因为使用这些复制插槽的 Client 端仍将连接并更新主服务器(而不是备用服务器)上的插槽。即使备份仅用于创建新的主服务器,复制复制插槽也不会特别有用,因为在新主服务器上线时,这些插槽的内容可能已经严重过时。

可以从备份中省略目录pg_dynshmem/pg_notify/pg_serial/pg_snapshots/pg_stat_tmp/pg_subtrans/的内容(但不能删除目录本身),因为它们将在邮局主管启动时初始化。如果设置了stats_temp_directory并且位于数据目录下,则该目录的内容也可以省略。

备份中可以省略以pgsql_tmp开头的任何文件或目录。这些文件将在邮局主管启动后删除,并且将根据需要重新创建目录。

备份标签文件包括您提供给pg_start_backup的标签字符串,运行pg_start_backup的时间以及起始 WAL 文件的名称。因此,在出现混乱的情况下,可以查看备份文件内部并准确确定转储文件来自哪个备份会话。表空间 Map 文件包含目录pg_tblspc/中存在的符号链接名称以及每个符号链接的完整路径。这些文件不仅供您参考。它们的存在和内容对于系统恢复过程的正常运行至关重要。

服务器停止时也可以进行备份。在这种情况下,您显然不能使用pg_start_backuppg_stop_backup,因此您将被留在自己的设备上以跟踪哪个备份是哪个备份以及关联的 WAL 文件返回多长时间。通常最好遵循上面的连续归档过程。

25 .3.4. 使用连续存档备份进行恢复

好的,最糟糕的事情发生了,您需要从备份中恢复。步骤如下:

  • 停止服务器(如果正在运行)。

  • 如果有足够的空间,请将整个群集数据目录和所有表空间复制到一个临时位置,以备日后需要时使用。请注意,此预防措施将要求您系统上有足够的可用空间来容纳现有数据库的两个副本。如果没有足够的空间,则至少应保存集群的pg_wal子目录的内容,因为它可能包含在系统关闭之前尚未归档的日志。

  • 删除集群数据目录下以及正在使用的任何表空间的根目录下的所有现有文件和子目录。

  • 从文件系统备份中还原数据库文件。确保使用正确的所有权(数据库系统用户,而不是root!)和正确的权限还原它们。如果使用表空间,则应验证pg_tblspc/中的符号链接是否已正确还原。

  • 删除pg_wal/中存在的所有文件;这些来自文件系统备份,因此可能已过时而不是最新。如果您根本没有存档pg_wal/,请使用适当的权限重新创建它,请小心确保如果您之前已进行过设置,则应将其重新构建为符号链接。

  • 如果您具有在步骤 2 中保存的未存档 WAL 段文件,请将其复制到pg_wal/。 (最好复制它们,而不是移动它们,因此,如果出现问题并且必须重新开始,您仍然拥有未修改的文件.)

  • 在集群数据目录中创建恢复命令文件recovery.conf(请参见Chapter 27)。您可能还需要临时修改pg_hba.conf,以防止普通用户连接,直到您确定恢复成功。

  • 启动服务器。服务器将进入恢复模式,并 continue 读取所需的已归档 WAL 文件。如果恢复由于外部错误而终止,则只需重启服务器即可 continue 恢复。恢复过程完成后,服务器会将recovery.conf重命名为recovery.done(以防止以后意外重新进入恢复模式),然后开始正常的数据库操作。

  • 检查数据库的内容,以确保您已恢复到所需状态。如果不是,请返回步骤 1.如果一切正常,请通过将pg_hba.conf恢复为正常状态来允许您的用户进行连接。

所有这一切的关键部分是构建一个恢复配置文件,该文件描述了您要如何恢复以及恢复应该运行多远。您可以使用recovery.conf.sample(通常位于安装的share/目录中)作为原型。绝对必须在recovery.conf中指定的一件事是restore_command,它告诉 PostgreSQL 如何检索已归档的 WAL 文件段。像archive_command一样,这是一个 shell 命令字符串。它可以包含%f(用所需的日志文件的名称替换)和%p(用路径名复制的日志文件复制到)。 (路径名相对于当前工作目录,即集群的数据目录.)如果需要在命令中嵌入实际的%字符,则 Importing%%。最简单的有用命令是:

restore_command = 'cp /mnt/server/archivedir/%f %p'

它将从目录/mnt/server/archivedir复制以前存档的 WAL 段。当然,您可以使用更复杂的方法,甚至可以使用 shell 脚本来要求操作员安装适当的磁带。

重要的是,该命令在失败时返回非零退出状态。命令被称为请求 Files 中不存在的文件;要求时,它必须返回非零。这不是错误情况。exception 是,如果命令被 signal 终止(SIGTERM 除外,SIGTERM 用作数据库服务器关闭的一部分)或 Shell 程序出错(例如未找到命令),则恢复将中止,服务器将终止无法启动。

并非所有请求的文件都是 WAL 段文件。您还应该期望后缀为.history的文件的请求。另请注意,%p路径的基本名称将与%f不同;不要期望它们可以互换。

在 Files 中找不到的 WAL 段将在pg_wal/中搜索;这允许使用最近未归档的段。但是,存档中可用的段将优先于pg_wal/中的文件使用。

通常,恢复将在所有可用的 WAL 段中进行,从而将数据库还原到当前时间点(或在可用的 WAL 段中尽可能接近)。因此,正常恢复将以“找不到文件”消息结束,错误消息的确切文本取决于您对restore_command的选择。您还可能在恢复开始时看到名为00000001.history之类的文件的错误消息。这也是正常现象,在简单的恢复情况下并不表示有问题;参见Section 25.3.5进行讨论。

如果要恢复到以前的某个时间点(例如,在初级 DBA 删除主事务表之前),只需在recovery.conf中指定所需的stopping point即可。您可以按日期/时间,命名的还原点或通过完成特定的事务 ID 指定停止点,称为“恢复目标”。在撰写本文时,只有日期/时间和命名的还原点选项非常有用,因为没有工具可以帮助您准确地确定要使用的 TransactionID。

Note

停止点必须在基本备份的结束时间之后,即pg_stop_backup的结束时间之后。您不能使用基本备份恢复到正在进行该备份的时间。 (要恢复到这样的时间,您必须返回到以前的基本备份并从那里前滚.)

如果恢复发现损坏的 WAL 数据,恢复将在此时停止,服务器将无法启动。在这种情况下,可以从头开始重新运行恢复过程,在损坏点之前指定“恢复目标”,以使恢复可以正常完成。如果恢复由于外部原因(例如系统崩溃)或 WAL 存档变得不可访问而失败,则可以简单地重新启动恢复,并且恢复几乎从失败的地方重新开始。恢复重新启动的工作原理与正常操作中的检查点很像:服务器会定期将其所有状态强制进入磁盘,然后更新pg_control文件以指示无需再次扫描已处理的 WAL 数据。

25.3.5. Timelines

将数据库还原到先前时间点的能力产生了一些复杂性,类似于有关时间旅行和 Parallel 宇宙的科幻小说故事。例如,在数据库的原始历史 Logging,假设您在星期二晚上 5:15 PM 删除了一个关键表,但是直到星期三中午才意识到自己的错误。无需担心,您可以备份并恢复到星期二晚上 5:14 的时间点,并开始运行。在数据库 Universe 的“此”历史 Logging,您从未删除过表。但是,假设您后来意识到这并不是一个好主意,并且想回到原始历史中的星期三上午。您将无法在数据库启动和运行时覆盖某些 WAL 段文件,这些文件导致您现在希望回到原来的时间。因此,为避免这种情况,您需要将时间点恢复后生成的一系列 WAL 记录与原始数据库历史 Logging 生成的 WAL 记录区分开。

为了解决这个问题,PostgreSQL 有一个* timelines 的概念。每当 Files 恢复完成时,都会创建一个新的时间表来标识在恢复之后生成的一系列 WAL 记录。时间线 ID 号是 WAL 段文件名的一部分,因此新的时间线不会覆盖以前时间线生成的 WAL 数据。实际上,可以存档许多不同的时间表。尽管这似乎是一个无用的功能,但它通常是救生员。考虑一下您不太确定要恢复到哪个时间点的情况,因此必须通过反复试验进行几次时间点恢复,直到找到从旧历史中找到最佳分支为止。没有时间表,这个过程很快就会造成混乱。使用时间轴,您可以恢复到任何*先前的状态,包括您先前放弃的时间轴分支中的状态。

每次创建新的时间线时,PostgreSQL 都会创建一个“时间线历史记录”文件,该文件显示它从何时何地分支出来的时间线。从包含多个时间轴的存档中恢复时,这些历史文件对于使系统选择正确的 WAL 段文件是必需的。因此,它们像 WAL 段文件一样被归档到 WAL 归档区域中。历史记录文件只是很小的文本文件,因此可以无限期地保持它们的便宜和适当(与大的段文件不同)。如果愿意,可以将 Comments 添加到历史记录文件中,以记录有关如何以及为何创建此特定时间轴的 Comments。当您因实验而有不同的时间表时,此类 Comment 将特别有价值。

恢复的默认行为是按照进行基本备份时的当前时间线进行恢复。如果希望恢复到某个子时间轴(即,要返回到尝试恢复后本身生成的某种状态),则需要在recovery.conf中指定目标时间轴 ID。您无法恢复到比基本备份更早分支的时间表。

25 .3.6. 提示与范例

这里提供了一些配置连续归档的技巧。

25 .3.6.1. 独立热备份

可以使用 PostgreSQL 的备份工具来生成独立的热备份。这些备份不能用于时间点恢复,但是与 pg_dump 转储相比,备份和恢复通常要快得多。 (它们也比 pg_dump 转储大得多,因此在某些情况下,速度优势可能会被抵消.)

与基本备份一样,生成独立热备份的最简单方法是使用pg_basebackup工具。如果在调用时包含-X参数,则使用备份所需的所有预写日志将自动包含在备份中,并且不需要特殊操作即可还原备份。

如果在复制备份文件时需要更大的灵 Active,则也可以将较低级别的过程用于独立的热备份。要准备低级别的独立热备份,请确保将wal_level设置为replica或更高,将archive_mode设置为on,并设置archive_command仅在* switch 文件*存在时才执行归档。例如:

archive_command = 'test ! -f /var/lib/pgsql/backup_in_progress || (test ! -f /var/lib/pgsql/archive/%f && cp %p /var/lib/pgsql/archive/%f)'

/var/lib/pgsql/backup_in_progress存在时,此命令将执行归档,否则将以静默方式返回零退出状态(允许 PostgreSQL 回收不需要的 WAL 文件)。

通过此准备,可以使用如下脚本来进行备份:

touch /var/lib/pgsql/backup_in_progress
psql -c "select pg_start_backup('hot_backup');"
tar -cf /var/lib/pgsql/backup.tar /var/lib/pgsql/data/
psql -c "select pg_stop_backup();"
rm /var/lib/pgsql/backup_in_progress
tar -rf /var/lib/pgsql/backup.tar /var/lib/pgsql/archive/

首先创建交换文件/var/lib/pgsql/backup_in_progress,从而可以将完整的 WAL 文件存档。备份后,将删除交换文件。然后将已归档的 WAL 文件添加到备份中,以便基本备份和所有必需的 WAL 文件都属于同一 tar 文件。请记住要在备份脚本中添加错误处理。

25 .3.6.2. 压缩 Files 日志

如果需要考虑归档文件的存储大小,则可以使用 gzip 压缩归档文件:

archive_command = 'gzip < %p > /var/lib/pgsql/archive/%f'

然后,您将需要在恢复过程中使用 gunzip:

restore_command = 'gunzip < /mnt/server/archivedir/%f > %p'

25 .3.6.3. archive_command 脚本

许多人选择使用脚本来定义自己的archive_command,因此他们的postgresql.conf条目看起来非常简单:

archive_command = 'local_backup_script.sh "%p" "%f"'

每次在归档过程中要使用多个命令时,建议使用单独的脚本文件。这允许在脚本中 Management 所有复杂性,该脚本可以用流行的脚本语言(如 bash 或 perl)编写。

脚本中可以解决的需求示例包括:

  • 复制数据以保护异地数据存储

  • 批处理 WAL 文件,以便每三个小时传输一次,而不是一次传输一次

  • 与其他备份和恢复软件的接口

  • 与监控软件接口以报告错误

Tip

使用archive_command脚本时,最好启用logging_collector。然后,从脚本写入 stderr 的所有消息都将出现在数据库服务器日志中,从而使复杂的配置在失败时易于诊断。

25.3.7. Caveats

在撰写本文时,连续归档技术存在一些局限性。这些可能会在将来的版本中修复:

  • 如果在进行基本备份时执行了CREATE DATABASE命令,然后在仍在进行基本备份的同时修改了CREATE DATABASE复制的模板数据库,则恢复很可能会使这些修改传播到创建的数据库中也一样这当然是不希望的。为避免这种风险,最好在进行基本备份时不要修改任何模板数据库。

  • CREATE TABLESPACE命令使用 Literals 绝对路径进行 WAL 记录,因此将被重播为具有相同绝对路径的表空间创建。如果正在其他计算机上重播日志,则这可能是不希望的。即使在同一台计算机上重播日志,但是将日志重播到新的数据目录中,也可能很危险:重播仍将覆盖原始表空间的内容。为了避免这种潜在的麻烦,最佳实践是在创建或删除表空间之后进行新的基本备份。

还应注意,默认 WAL 格式相当庞大,因为它包含许多磁盘页面快照。这些页面快照旨在支持崩溃恢复,因为我们可能需要修复部分写入的磁盘页面。根据系统硬件和软件的不同,部分写入的风险可能很小,可以忽略不计,在这种情况下,您可以使用full_page_writes参数关闭页面快照,从而大大减少归档日志的总量。 (在这样做之前,请先阅读Chapter 30中的 Comments 和警告。)关闭页面快照并不能防止将日志用于 PITR 操作。Future 的 Developing 领域是即使full_page_writes处于打开状态,也可以通过删除不必要的页面副本来压缩已归档的 WAL 数据。同时,Management 员可能希望通过尽可能增加检查点间隔参数来减少 WAL 中包含的页面快照的数量。