此转储方法的思路是生成一个包含 SQL 命令的文件,将该文件反馈给服务器后,将在转储时的时间点以相同状态重新创建数据库。 PostgreSQL 提供了实用程序 pg_dump 以达到此目的。此命令的基本用法是
pg_dumpdbname
>dumpfile
您会发现,pg_dump 会将结果写入标准输出。我们会在下面看到这么做的好处。虽然上述命令会创建一个文本文件,但 pg_dump 还能创建其他格式的文件,以便并行操作,并可以更精细地控制对象还原。
pg_dump 是一个普通的 PostgreSQL 客户端应用程序(尽管它是特别聪明的应用程序)。这意味着您可以使用能够访问该数据库的任何远程主机执行此备份程序。但请记住,pg_dump 并未具有特殊权限。具体而言,它必须具有您希望备份的所有表的读取访问权限,因此,为了备份整个数据库,您几乎总是必须以数据库超级用户的身份来运行它。(如果您没有足够的权限备份整个数据库,您仍然可以使用选项(例如 -n
或 架构
-t
),备份您有权访问的数据库部分。)表
要指定 pg_dump 应该联系哪个数据库服务器,请使用命令行选项 -h
和 主机
-p
。默认主机是本地主机或 端口
PGHOST
环境变量指定的主机。同样,默认端口由 PGPORT
环境变量指定,如果没有指定,则由编译内默认值指定。(通常情况下,服务器也有相同的编译内默认值,这很方便。)
与任何其他 PostgreSQL 客户端应用程序类似,pg_dump 默认会使用等于当前操作系统用户名的数据库用户名进行连接。要覆盖此默认设置,请指定 -U
选项或设置环境变量 PGUSER
。请记住,pg_dump 连接需遵守标准的客户端身份验证机制(请参阅 第 20 章 了解详细信息)。
pg_dump 比后面描述的其他备份方法有一个重要优势,即 pg_dump 的输出通常可以重新加载到 PostgreSQL 的较新版本中,而文件级备份和连续归档都与特定服务器版本紧密相关。pg_dump 也是唯一一个在将数据库传输到不同计算机架构时有效的方法,例如从 32 位服务器传输到 64 位服务器时。
由 pg_dump 创建的转储内容是内部一致的,这意味着转储内容表示 pg_dump 开始运行时数据库的快照。在 pg_dump 工作时,它不会阻止数据库上的其他操作。(但需要使用独占锁来执行的操作除外,如大多数形式的 ALTER TABLE
)。
由 pg_dump 创建的文本文件将由 psql 程序读入。要还原转储内容的一般命令形式如下:
psqldbname
<dumpfile
其中 dumpfile
是由 pg_dump 命令输出的文件。此命令不会创建数据库 dbname
,因此您必须从 template0
中自己创建该数据库,然后再执行 psql(例如,使用 createdb -T template0
)。psql 支持与 pg_dump 类似的选项,用于指定要连接的数据库服务器和要使用的用户名。有关更多信息,请参见 psql 参考页。使用 pg_restore 实用程序还原非文本文件转储内容。dbname
在还原 SQL 转储内容之前,必须先创建转储数据库中拥有对象或被授予对象权限的所有用户。如果未创建,则还原操作将无法重建拥有权和/或权限与之前相同的对象。(有时这是您想要的,但通常不是。)
默认情况下,在遇到 SQL 错误之后,psql 脚本将继续执行。您可能希望在将 ON_ERROR_STOP
变量设为更改该行为后运行 psql,如果发生 SQL 错误,则让 psql 退出并显示退出状态为 3
psql --set ON_ERROR_STOP=ondbname
<dumpfile
无论采用哪种方式,您都只能还原部分数据库。或者,您可以指定将整个转储内容还原为单一事务,以便完全完成还原或完全回滚还原。可以通过将 -1
或 --single-transaction
命令行选项传递给 psql 来指定此模式。在使用此模式时,即使是次要错误也可能会回滚已运行了很长时间的还原操作。但是,这可能仍然优于在部分还原转储之后手动清理复杂数据库。
由于 pg_dump 和 psql 可以写入管道或从管道读取数据,因此可以将数据库从一台服务器直接转储到另一台服务器,例如:
pg_dump -hhost1
dbname
| psql -hhost2
dbname
pg_dump 生成的转储相对于 template0
。这意味着通过 template1
添加的任何语言、过程等也将被 pg_dump 转储。因此,在恢复时,如果您正在使用自定义的 template1
,则必须从 template0
中创建空的数据库,如同上面的示例所示。
在恢复备份后,最好在每个数据库上运行 ANALYZE
,以便查询优化器具备有用的统计信息;有关详细信息,请参见 第 24.1.3 节 和 第 24.1.6 节。有关如何高效地将大量数据加载到 PostgreSQL 的更多建议,请参阅 第 14.4 节。
pg_dump 每次只转储一个数据库,并且不转储有关角色或表空间的信息(因为这些信息是针对整个集群的,而不是针对每个数据库的)。为了支持方便地转储整个数据库集群的内容,提供了 pg_dumpall 程序。 pg_dumpall 会备份给定集群中的每个数据库,还会保留角色和表空间定义等集群级数据。此命令的基本用法为:
pg_dumpall > dumpfile
可以使用 psql 恢复生成的转储
psql -f dumpfile
postgres
(实际上,您可以指定从任何现有数据库名称开始,但如果要加载到空集群中,则通常应使用 postgres
。)在恢复 pg_dumpall 转储时,始终需要具有数据库超级用户访问权限,因为需要恢复角色和表空间信息。如果您使用表空间,请确保转储中的表空间路径适用于新的安装。
pg_dumpall 通过发出命令重新创建角色、表空间和空数据库,然后为每个数据库调用 pg_dump 来工作。这意味着尽管每个数据库在内部是一致的,但是不同数据库的快照并不同步。
可以使用 pg_dumpall --globals-only
选项仅将集群级数据转储出来。如果对各个数据库运行 pg_dump 命令,这对于完全备份集群是必要的。
某些操作系统具有最大文件大小限制,在创建大型 pg_dump 输出文件时会导致问题。幸运的是,pg_dump 可以写入标准输出,因此你可以使用标准 Unix 工具来解决此潜在问题。有几种可能的方法
使用压缩转储。你可以使用你喜欢的压缩程序,例如 gzip
pg_dumpdbname
| gzip >filename
.gz
使用以下方法重新加载
gunzip -cfilename
.gz | psqldbname
或
catfilename
.gz | gunzip | psqldbname
使用 split
。 split
命令允许你将输出拆分成较小的文件,其大小可以被底层文件系统接受。例如,要制作 2 吉字节块
pg_dumpdbname
| split -b 2G -filename
使用以下方法重新加载
catfilename
* | psqldbname
如果使用 GNU split,就可以同时使用它和 gzip
pg_dump dbname
| split -b 2G --filter='gzip > $FILE.gz'
可以使用 zcat
对其进行还原。
使用 pg_dump 的自定义转储格式。如果 PostgreSQL 是在安装了 zlib 压缩库的系统上构建的,则自定义转储格式在将数据写入输出文件时会对其进行压缩。这将生成与使用 gzip
类似的转储文件大小,但具有表可以选择性还原的附加优点。以下命令使用自定义转储格式转储数据库
pg_dump -Fcdbname
>filename
自定义格式的转储不是 psql 的脚本,而是必须使用 pg_restore 进行还原,例如
pg_restore -ddbname
filename
有关详细信息,请参阅 pg_dump 和 pg_restore 参考页。
对于非常大的数据库,你可能需要将 split
与其他两种方法之一结合使用。
使用 pg_dump 的并行转储功能。要加快大型数据库的转储速度,可以使用 pg_dump 的并行模式。这将同时转储多个表。可以使用 -j
参数控制并行度。仅对“目录”存档格式支持并行转储。
pg_dump -jnum
-F d -fout.dir
dbname
可以使用 pg_restore -j
并行还原转储。对于任何“自定义”或“目录”存档模式的存档,无论是否使用 pg_dump -j
创建的,这都适用。