Chapter 22. 备份和恢复

Table of Contents
22.1. SQL 转储
22.1.1. 从转储中恢复
22.1.2. 使用 pg_dumpall
22.1.3. 处理大数据库
22.1.4. 注意
22.2. 文件系统级别的备份
22.3. 在线备份以及即时恢复(PITR)
22.3.1. 设置 WAL 归档
22.3.2. 进行一次基础备份
22.3.3. 从在线备份中恢复
22.3.4. 时间线
22.3.5. 注意
22.4. 在不同版本之间迁移

和任何包含珍贵数据的东西一样,PostgreSQL 数据库也应该经常备份。尽管这个过程相当简单, 但是我们还是应该理解做这件事所用的一些技巧和假设。

备份 PostgreSQL 数据有三种完全不同的方法:

每种备份都有自己的优点和缺点。

22.1. SQL 转储

SQL 转储的方法采用的主意是创建一个文本文件,这个文本里面都是 SQL 命令,当把这个文件回馈给服务器时,将重建与转储时状态一样的数据库。 PostgreSQL 为这个用途提供了应用工具 pg_dump。这条命令的基本用法是:

pg_dump dbname > outfile

正如你所见,pg_dump 把结果输出到标准输出。 我们下面就可以看到这样做有什么好处。

pg_dump 是一个普通的 PostgreSQL 客户端应用(尽管是个相当聪明的东西。)这就意味着你可以从任何可以访问该数据库的远端主机上面进行备份工作。 但是请记住 pg_dump 不会以任何特殊权限运行。具体说来, 就是它必须要有你想备份的表的读权限,因此,实际上你几乎总是要成为数据库超级用户。

要声明 pg_dump 应该以哪个用户身份进行联接,使用命令行选项 -h host-p port。 缺省主机是本地主机或你的环境变量PGHOST声明的值。 类似,缺省端口是环境变量PGPORT或(如果它不存在的话)编译好了的缺省值。 (服务器通常有相同的缺省,所以还算方便。)

和任何其他 PostgreSQL 客户端应用一样, pg_dump 缺省时用与当前操作系统用户名同名的数据库用户名进行联接。 要覆盖这个名字,要么声明 -U 选项, 要么设置环境变量PGUSER。 请注意 pg_dump 的联接也和普通客户应用一样要通过客户认证机制(在 Chapter 19)里描述。

pg_dump 创建的备份在内部是一致的, 也就是说,在pg_dump运行的时候对数据库的更新将不会被转储。 pg_dump 工作的时候并不阻塞其他的对数据库的操作。 (但是会阻塞那些需要排它锁的操作,比如 VACUUM FULL。)

Important: 如果你的数据库结构依赖于 OID (比如说用做外键),那么你必须告诉 pg_dump 把 OID 也倒出来。 要倒 OID,可以使用 -o 命令行选项。 缺省时也不会转储"大对象"。如果你使用大对象,请参考 pg_dump 的命令手册页。

22.1.1. 从转储中恢复

pg_dump 生成的文本文件可以由 psql 程序读取。 从转储中恢复的常用命令是

psql dbname < infile

这里的 infile 就是你给pg_dump命令的 outfile参数。这条命令不会创建数据库 dbname,你必须在执行psql 前自己从template0创建(也就是说,用命令 createdb -T template0 dbname)。 psql 支持类似 pg_dump 的选项用以控制数据库服务器位置和用户名。 参阅 psql 的手册获取更多信息。

在开始运行恢复之前,目标库和所有在转储出来的库中拥有对象的用户, 以及曾经在某些对象上被赋予权限的用户都必须已经存在。 如果这些不存在,那么恢复将失败,因为恢复过程无法把这些对象恢复成原有的所有权和/或权限。 (有时候你希望恢复权限,不过通常你不需要这么做。)

一旦完成恢复,在每个数据库上运行 ANALYZE 是明智的举动, 这样优化器就有有用的统计数据了。你总是可以运行 vacuumdb -a -zVACUUM ANALYZE 所有数据库;这个等效于手工运行 VACUUM ANALYZE

pg_dumppsql 可以通过管道读写, 这样我们就可能从一台主机上将数据库目录转储到另一台主机上,比如

pg_dump -h host1 dbname | psql -h host2 dbname

Important: pg_dump生成的转储输出是相对于template0的。这就意味着任何 加入到template1的语言,过程等都会经由 pg_dump 转储。结果是,在恢复的时候,如果你使用的是客户化的template1, 那么你必须从template0中创建空的数据库,就象我们上面的例子那样。

有关如何有效地向 PostgreSQL 里装载大量数据的建议, 请参考 Section 13.4

22.1.2. 使用 pg_dumpall

上面的方法在备份整个数据库集群的时候比较麻烦而且不方便。因此我们提供了 pg_dumpall 程序。 pg_dumpall 备份一个给出的集群中的每个数据库,同时还确保保留象用户和组这样的全局数据状态。 这个命令的基本用法是:

pg_dumpall > outfile

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

psql template1 < infile

(实际上,你可以声明任意现有的数据库进行连接,但是如果你是向一个空的数据库装载,那么 template1 是你唯一的选择。) 恢复pg_dumpall的转储的时候通常需要数据库超级用户权限,因为我们需要它来恢复用户和组信息。

22.1.3. 处理大数据库

因为 PostgreSQL 允许表的大小大于你的系统允许的最大文件大小, 可能把表转储到一个文件会有问题,因为生成的文件很可能比你的系统允许的最大文件大。 因为 pg_dump 输出到标准输出,你可以用标准的 Unix 工具绕开这个问题:

使用压缩的转储. 使用你熟悉的压缩程序,比如说 gzip

pg_dump dbname | gzip > filename.gz

用下面命令恢复:

createdb dbname
gunzip -c filename.gz | psql dbname

或者

cat filename.gz | gunzip | psql dbname

使用 split。. split 命令允许你 你用下面的方法把输出分解成操作系统可以接受的大小。 比如,让每个块大小为 1 兆字节:

pg_dump dbname | split -b 1m - filename

用下面命令恢复:

createdb dbname
cat filename* | psql dbname

使用客户化转储格式. 如果PostgreSQL是在一个安装了zlib 压缩库的系统上制作的, 那么客户化转储格式将在写入输出文件的时候压缩数据。 它会生成和使用 gzip 类似大小的转储文件, 但是还附加了一个优点:你可以有选择地恢复库中的表。 下面的命令用客户化转储格式转储一个数据库:

pg_dump -Fc dbname > filename

客户化格式的转储不是脚本,不能用于 psql, 而是需要使用 pg_restore 转储。 请参考 pg_dumppg_restore 的手册获取细节。

22.1.4. 注意

出于向下兼容的考虑,缺省的时候 pg_dump 并不转储大对象。 要转储大对象,你必须使用客户化或者 tar 输出格式, 并且在 pg_dump 中使用-b选项。 参阅 pg_dump 手册获取详细信息。 在 PostgreSQL 源码树的 contrib/pg_dumplo 路径里也包含一个可以转储大对象的程序。

请熟悉一下 pg_dump 的手册页。