↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

第 26 章 备份和恢复

与任何保存重要数据的系统一样,PostgreSQL 数据库也应定期备份。虽然其过程基本简单,但清楚理解其底层技术和前提假设非常重要。

备份 PostgreSQL 数据主要有三种根本不同的方法:

  • SQL 转储

  • 文件系统级备份

  • 持续归档

每种方法都有各自的优缺点,下面各节将依次讨论。

26.1. SQL 转储 #

这种转储方法的思路是生成一个包含 SQL 命令的文件;将其重新送回服务器后,服务器就会把数据库重建为转储时的状态。PostgreSQL 为此提供了工具程序 pg_dump。该命令的基本用法是:

pg_dump dbname > dumpfile

如前所示,pg_dump 把结果写到标准输出。稍后我们会看到这一点有何用处。虽然上述命令会创建一个文本文件,但 pg_dump 也可以创建其他格式的文件,从而支持并行处理以及对对象恢复进行更细粒度的控制。

pg_dump 是一个普通的 PostgreSQL 客户端应用程序(尽管它实现得相当巧妙)。这意味着你可以从任何能够访问该数据库的远程主机执行这种备份过程。但请记住,pg_dump 并不会以特殊权限运行。特别是,它必须对你想要备份的所有表具有读权限,因此若要备份整个数据库,几乎总是必须以数据库超级用户身份运行它。(如果你没有足够权限备份整个数据库,仍然可以使用诸如 -n schema 或 -t table 的选项来备份你有权访问的那部分数据库。)

要指定 pg_dump 应连接哪个数据库服务器,请使用命令行选项 -h host 和 -p port。默认主机是本地主机,或者由环境变量 PGHOST 指定的主机。类似地,默认端口由环境变量 PGPORT 指定;如果未设置,则采用编译时内置的默认值。(方便的是,服务器通常也会使用同样的内置默认值。)

和其他 PostgreSQL 客户端应用程序一样,pg_dump 默认会以与当前操作系统用户名相同的数据库用户名进行连接。若要覆盖这一点,可以指定 -U 选项,或者设置环境变量 PGUSER。请记住,pg_dump 连接同样受常规客户端认证机制约束(见第 21 章)。

与后文介绍的其他备份方法相比,pg_dump 的一个重要优点在于,pg_dump 的输出通常可以重新装入较新版本的 PostgreSQL,而文件级备份和持续归档都高度依赖具体的服务器版本。pg_dump 也是在不同机器体系结构之间迁移数据库时唯一可行的方法,例如从 32 位服务器迁移到 64 位服务器。

由 pg_dump 创建的转储在内部是一致的,也就是说,该转储表示的是 pg_dump 开始运行时的数据库快照。pg_dump 在工作期间不会阻塞数据库上的其他操作。(例外是那些需要独占锁的操作,例如大多数形式的 ALTER TABLE。)

26.1.1. 恢复转储 #

由 pg_dump 创建的文本文件是为 psql 程序在默认设置下读取而设计的。恢复文本转储的一般命令形式是:

psql -X dbname < dumpfile

其中 dumpfile 是 pg_dump 命令输出的文件。数据库 dbname 不会由该命令创建,因此你必须先从 template0 创建它,然后再执行 psql(例如,使用 createdb -T template0 dbname)。为确保 psql 以默认设置运行,请使用 -X(--no-psqlrc)选项。psql 也支持与 pg_dump 类似的选项,用于指定要连接的数据库服务器以及所使用的用户名。更多信息参见 psql 参考页。

非文本格式的转储应当使用 pg_restore 工具恢复。

在恢复 SQL 转储之前,所有拥有对象或者在被转储数据库中曾被授予对象权限的用户都必须已经存在。否则,恢复将无法以原有所有权和/或权限重新创建这些对象。(有时这正是你想要的,但通常不是。)

默认情况下,psql 脚本在遇到 SQL 错误后仍会继续执行。你可能希望让 psql 在设置了 ON_ERROR_STOP 变量的情况下运行,以改变这一行为,并让 psql 在发生 SQL 错误时以退出状态码 3 退出:

psql -X --set ON_ERROR_STOP=on dbname < dumpfile

无论采用上述哪种方式,你最终只会得到一个部分恢复的数据库。另一种做法是指定将整个转储作为单个事务恢复,这样恢复要么全部完成,要么全部回滚。可以通过把 -1 或 --single-transaction 命令行选项传给 psql 来启用这种模式。使用这种模式时要注意,即便是一个很小的错误,也可能回滚一个已经运行了许多小时的恢复过程。不过,这仍可能比在部分恢复后手工清理一个复杂数据库更可取。

pg_dump 和 psql 能够写入或读取管道,这使得可以把数据库直接从一台服务器转储到另一台服务器,例如:

pg_dump -h host1 dbname | psql -X -h host2 dbname

重要

pg_dump 生成的转储是以 template0 为基准的。这意味着通过 template1 增加的任何语言、过程等也都会被 pg_dump 转储。因此,恢复时如果你使用的是定制过的 template1,就必须像上面的例子那样,从 template0 创建空数据库。

恢复完备份后,最好对每个数据库运行 ANALYZE,这样查询优化器就能拥有有用的统计信息;更多信息见第 25.1.3 节和第 25.1.6 节。关于如何高效地将大量数据装入 PostgreSQL,请参见第 14.4 节。

26.1.2. 使用 pg_dumpall #

pg_dump 一次只转储一个数据库,而且不会转储角色或表空间的信息(因为这些是整个集簇级别的,而不是每个数据库各自的)。为了方便地转储整个数据库集簇的全部内容,提供了 pg_dumpall 程序。pg_dumpall 会备份给定集簇中的每个数据库,并保留角色定义和表空间定义等集簇范围的数据。该命令的基本用法是:

pg_dumpall > dumpfile

生成的转储可以用 psql 恢复:

psql -X -f dumpfile postgres

(实际上,可以指定任意一个现有数据库名作为起点,但如果要装载到一个空集簇中,通常应使用 postgres。)恢复 pg_dumpall 转储时始终需要数据库超级用户权限,因为恢复角色和表空间信息必须使用该权限。如果使用了表空间,请确保转储中的表空间路径适合新的安装。

pg_dumpall 的工作方式是先发出重新创建角色、表空间和空数据库的命令,然后针对每个数据库调用 pg_dump。这意味着每个数据库本身都是内部一致的,但不同数据库的快照并不同步。

集簇范围的数据也可以单独使用 pg_dumpall 的 --globals-only 选项进行转储。如果你对各个数据库分别运行 pg_dump 命令,而又希望对整个集簇进行完整备份,这一步就是必需的。

26.1.3. 处理大型数据库 #

某些操作系统对文件大小有上限,这会在创建大型 pg_dump 输出文件时带来问题。幸运的是,pg_dump 可以把输出写到标准输出,因此你可以利用标准 Unix 工具绕过这个潜在问题。有几种可行方法:

使用压缩转储。.  你可以使用自己喜欢的压缩程序,例如 gzip:

pg_dump dbname | gzip > filename.gz

恢复时:

gunzip -c filename.gz | psql dbname

或者:

cat filename.gz | gunzip | psql dbname

使用 split。.  split 命令允许你把输出分割成文件系统可接受大小的较小文件。例如,要切分为 2 GB 的块:

pg_dump dbname | split -b 2G - filename

恢复时:

cat filename* | psql dbname

如果使用 GNU split,也可以把它和 gzip 结合起来:

pg_dump dbname | split -b 2G --filter='gzip > $FILE.gz'

恢复时可使用 zcat。

使用 pg_dump 的自定义转储格式。.  如果构建 PostgreSQL 所用的系统安装了 zlib 压缩库,自定义转储格式会在向输出文件写入数据时对其进行压缩。这会产生与使用 gzip 大致相同大小的转储文件,但额外的优点是其中的表可以有选择地恢复。下面的命令使用自定义转储格式转储数据库:

pg_dump -Fc dbname > filename

自定义格式的转储不是供 psql 执行的脚本,而必须通过 pg_restore 恢复,例如:

pg_restore -d dbname filename

详细信息见 pg_dump 和 pg_restore 参考页。

对于非常大的数据库,你可能需要把 split 与另外两种方法之一结合使用。

使用 pg_dump 的并行转储特性。.  为了加快大型数据库的转储速度,你可以使用 pg_dump 的并行模式。这会同时转储多个表。你可以通过 -j 参数控制并行度。并行转储只支持“目录”归档格式。

pg_dump -j num -F d -f out.dir dbname

你可以使用 pg_restore -j 并行恢复转储。这对于任何“自定义”或“目录”模式的归档都有效,无论它是否是用 pg_dump -j 创建的。

报告文档问题

阅读 上游文档. 通过 PostgreSQL 文档反馈表单.