选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.3 已于 2018 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

第 24 章 备份和恢复

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

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

  • SQL转储

  • 文件系统级备份

  • 持续归档

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

24.1. SQL转储 #

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

pg_dump dbname > dumpfile

如前所示,pg_dump把结果写到标准输出。稍后我们会看到这一点有何用处。

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

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

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

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

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

重要

如果你的数据库模式依赖 OID(例如作为外键),必须让pg_dump把 OID 一并转储出来。为此,请使用命令行选项-o

24.1.1. 恢复转储 #

pg_dump 创建的文本文件供 psql 程序读取。恢复转储的通用命令格式是

psql dbname < dumpfile

其中,dumpfile 是由 pg_dump 命令输出的文件。数据库 dbname 不会由此命令创建,因此必须自行基于 template0 创建它,再执行 psql(例如使用 createdb -T template0 dbname)。 psql 支持与 pg_dump 类似的选项,用于指定要连接的数据库服务器及所用的用户名。更多信息参见 psql 参考页面。

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

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

psql --set ON_ERROR_STOP=on dbname < dumpfile

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

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

pg_dump -h host1 dbname | psql -h host2 dbname

重要

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

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

24.1.2. 使用pg_dumpall #

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

pg_dumpall > dumpfile

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

psql -f dumpfile postgres

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

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

24.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命令允许你把输出分割成文件系统可接受大小的较小文件。例如,要切分为 1 MB 的块:

pg_dump dbname | split -b 1m - filename

恢复时:

cat filename* | psql dbname

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

pg_dump -Fc dbname > filename

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

pg_restore -d dbname filename

详细信息见pg_dumppg_restore参考页。

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

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

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

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

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。