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中,而文件级备份和连续归档都极大地依赖于服务器版本。当将数据库传输到不同的机器架构(例如从 32 位服务器转到 64 位服务器)时,pg_dump也是唯一可行的方法。
由pg_dump创建的转储在内部是一致的,这意味着,转储表示pg_dump开始运行时数据库的快照。pg_dump在工作时不会阻止对数据库的其他操作。(例外情况是需要以独占锁操作的操作,例如大多数形式的ALTER TABLE
。)
26.1.1. 还原转储#
pg_dump创建的文本文件旨在由psql程序读取。还原转储的一般命令格式为
psql dbname < dumpfile
其中*dumpfile
是pg_dump命令输出的文件。此命令不会创建数据库dbname
*,因此您必须在执行psql之前从template0
中创建它(例如,使用createdb -T template0*
dbname*
)。psql支持类似于pg_dump的选项,用于指定要连接的数据库服务器和要使用的用户名。有关更多信息,请参阅psql参考页。使用pg_restore实用程序还原非文本文件转储。
在还原 SQL 转储之前,所有拥有对象或被授予转储数据库中对象权限的用户必须已经存在。如果他们不存在,则还原将无法使用原始所有权和/或权限重新创建对象。(有时这是您想要的,但通常不是。)
默认情况下,在遇到 SQL 错误后,psql脚本将继续执行。您可能希望使用ON_ERROR_STOP
变量运行psql以更改该行为,并在发生 SQL 错误时让psql以退出状态 3 退出
psql --set ON_ERROR_STOP=on dbname < dumpfile
无论哪种方式,您都只会拥有部分还原的数据库。或者,您可以指定将整个转储还原为单个事务,以便还原完全完成或完全回滚。可以通过将-1
或--single-transaction
命令行选项传递给psql来指定此模式。使用此模式时,请注意,即使是轻微的错误也可能回滚已经运行了数小时的还原。但是,这可能仍然优于在部分还原转储后手动清理复杂数据库。
由于pg_dump和psql具有写入或读取管道的能力,因此可以将数据库直接从一台服务器转储到另一台服务器,例如
pg_dump -h host1 dbname | psql -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 -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
如果使用 GNUsplit,则可以同时使用它和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
创建。