受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

Chapter 25. 备份和恢复

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

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

  • SQL转储

  • 文件系统级备份

  • 持续归档

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

25.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连接同样受常规客户端认证机制约束(见Chapter 20)。

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

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

25.1.1. 恢复转储 #

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

psql -X dbname < dumpfile

其中dumpfilepg_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_dumppsql能够写入或读取管道,这使得可以把数据库直接从一台服务器转储到另一台服务器,例如:

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

Important

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

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

25.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命令,而又希望对整个集簇进行完整备份,这一步就是必需的。

25.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_dumppg_restore参考页。

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

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

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

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

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。