PostgreSQL 增量备份与恢复

Trove 目前仅支持使用 PostgreSQL 客体代理进行完全备份和恢复。

Launchpad 蓝图:https://blueprints.launchpad.net/trove/+spec/postgresql-incremental-backup

问题描述

目前,PostgreSQL 中的备份使用 pg_dumppg_restore 工具完成,这些工具可以生成高效的逻辑备份。不幸的是,它们不能作为增量备份或时间点恢复的基础。

提议的变更

PostgreSQL 日志记录

与 MySQL 相比,PostgreSQL 使用相同的基础来支持恢复、复制和增量备份。其中核心是预写式日志 (WAL) 1。每次更新数据库时,都会创建一个 WAL 条目。WAL 内容会定期检查点到数据库目录中的主数据文件,并最终根据系统配置被清除。

在系统崩溃的情况下,恢复过程通过重放自上次检查点以来的 WAL 内容来进行。相同的机制以“连续”的方式用于复制,以及直到特定 WAL 条目的时间点恢复 2

因此,为了支持增量备份,需要两个部分

  • 基本备份,即 pgsql 数据目录的文件系统内容的快照

  • 自上次备份以来到所需时间点的 WAL 文件

基本备份

基本备份使用 pg_basebackup 文件系统级别备份工具 3 拍摄。 pg_basebackup 创建 PostgreSQL 集群数据目录中二进制文件的副本,以及足够的 WAL 段,以便将数据库恢复到一致状态。每个备份都与一个日志位置相关联,通常由 WAL 文件名和文件内的位置指示。

时间点恢复和 WAL 归档

可以通过引导恢复系统使 PostgreSQL 支持 Trove 的增量备份和恢复概念。在 PostgreSQL 中,从先前的备份恢复增量备份就是重放 WAL 条目到指定的时间点——所有需要的只是最新的基本备份以及自那时起写入的所有 WAL 文件。

在数据库的正常运行过程中,WAL 数据被写入并检查点到数据文件,不需要的文件会被清除。PostgreSQL 还可以配置为自动归档 WAL 文件,然后这些文件可以用于时间点恢复的目的。

PostgreSQL 有两个重要的配置参数,用于管理 WAL 归档和 WAL 检索以进行恢复:archive_commandrecovery_command

这些参数允许在处理 WAL 文件方面具有很大的灵活性——唯一的要求是该命令仅在文件成功传输的情况下返回 0。一个简单的例子

archive_command = 'test ! -f /mnt/arch/%f && cp %p /mnt/arch/%f'

上面的命令检查文件在归档目录 /mnt/arch 中是否存在(以避免覆盖现有文件),然后将其复制进去。

类似地,对于恢复

restore_command = 'cp /mnt/arch/%f "%p"'

上面的命令假定 /mnt/arch 可访问,并且对于恢复,包含适当的 WAL 文件。

原则上 archive_command 可以是任何内容,但有一些重要的注意事项

  • archive_command 的速度必须足够快,才能跟上 WAL 文件持续生成的速度

  • 恢复命令必须能够反转应用于归档上的 WAL 文件的任何操作

假设已经建立了适当的机制来归档和检索 WAL 文件,增量备份和恢复将成为简单的操作:增量“备份”是通过使用 pg_start_backup('my_restore_pt') 创建恢复点来完成的,等效的恢复是通过在 recovery.conf 文件中以 recovery_target_name = 'my_restore_pt' 的方式重新启动服务器来完成的。

增量收集 WAL 文件

考虑以下可能在 PostgreSQL WAL 归档目录中找到的一系列 WAL 文件

$ ls -lh /mnt/wal_arch
-rw------- 1 postgres postgres  16M Oct 27 19:11 000000010000000000000016
-rw------- 1 postgres postgres  16M Oct 27 19:11 000000010000000000000017
-rw------- 1 postgres postgres  16M Oct 27 19:12 000000010000000000000018
-rw------- 1 postgres postgres  16M Oct 27 19:12 000000010000000000000019
-rw------- 1 postgres postgres  16M Oct 27 19:12 00000001000000000000001A

WAL 条目流可以可视化为

--------------------------------------------------------
|   16   |    17    |   18   |    19    |    1A   | ...
--------------------------------------------------------
     ^                  ^                    ^
    B1                  I1                   I2

假设基本备份 B1 在文件 16 位置 48 拍摄,增量备份 I1 在文件 18 位置 30 拍摄,增量备份 I2 在文件 1A 位置 20 拍摄。

I1 将由 WAL 文件 16 到 18 组成:在 B1 拍摄的位置 48 之后的文件 16 中的条目是需要的,以及文件 18 的内容直到位置 30。

I2 将由 WAL 文件 18 到 1A 组成。

这种方法的好处是与 Trove 当前用于增量备份和恢复的范例一致。主要的缺点是 WAL 数据必须分两个阶段归档:首先由 PostgreSQL 本地归档到实例,然后由 Trove 归档到对象存储。这增加了复杂性并增加了实例上的存储需求。

配置

需要添加新的增量备份和恢复策略。

数据库

无。

公共 API

无。

公共 API 安全

无。

Python API

无。

CLI (python-troveclient)

实施后,以下 CLI 命令将起作用

trove backup-create <inst> <inc_backup> --parent <backup_id>
trove create <inst> .. --backup <inc_backup_id>

内部 API

无。

Guest Agent

将添加基于 pg_basebackup 的新的备份和恢复策略。

备选方案

更紧密的 PostgreSQL - Swift 集成

一个更简单的方法是绕过两阶段归档过程,让 PostgreSQL 自动管理 WAL 归档过程与对象存储之间的过程。例如,archive 命令可以将 WAL 文件通过快速压缩器(如 Snappy 或 LZOP)运行,加密然后直接发送到 Swift,并对恢复进行相应的反向过程。

这样做的好处是实现起来更简单,因为大部分日志处理都推送到 PostgreSQL,但有一个重要的副作用是引入了从 PostgreSQL 客体到 Swift 的相对连续的 WAL 数据流,这可能是不期望的,并且与在其他数据存储上进行增量备份的方法不一致。

Dashboard 影响 (UX)

待定 (在批准后添加的部分)

实现

负责人

主要负责人

atomic77

里程碑

mitaka-1

工作项

  • pg_basebackup 完全备份

  • 增量备份

  • 集成测试

升级影响

使用旧的 PgDump 策略拍摄的备份与此新策略不兼容。

依赖项

能够在通用的 int-test 框架中创建 pgsql 实例。

测试

新的通用 int-test 框架中目前不存在增量备份的集成测试,并将添加。将根据需要添加单元测试。

文档影响

需要更新文档以反映新的备份和恢复策略。

附录

N/A