Chapter 8. 备份和恢复

Table of Contents
8.1. SQL 倾倒
8.1.1. 从倾倒中恢复
8.1.2. 使用 pg_dumpall
8.1.3. 大数据库
8.1.4. 注意
8.2. 文件系统级别的备份
8.3. 在不同版本之间迁移

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

备份 Postgres 数据有两个完全不同的方法:

8.1. SQL 倾倒

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

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

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

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

和任何其他 Postgres 客户端应用一样, pg_dump 缺省时用与当前 UNIX 用户名同名的数据库用户 名进行联接.要覆盖这个名字,要么声明 -u 选项, 以强迫提示输入用户名,要么设置环境变量PGUSER. 请注意 pg_dump 的联接也和普通客户应用一样要 通过客户认证机制(在 Chapter 4)里描述.

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

Important: 如果你的数据库结构依赖于 OID (比如说用做外键),那么你必须告诉 pg_dump 把 OID 也倒出来. 要倒 OID,可以使用 -o 命令行选项.

8.1.1. 从倾倒中恢复

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

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

如果在原先数据库里的对象属于不同的用户,那么倾倒的文件会指示 psql 以各个受影响的用户轮流联接然后再创建相关的对象. 这样就保留了原来的所有权属性.不过这样也意味着所有这些用户必须 已经存在,而且你还必须能够以每个用户的身份联接. 所以我们可能需要临时放松一下客户认证的设置.

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

pg_dump -h host1 dbname | psql -h host2 dbname

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

8.1.2. 使用 pg_dumpall

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

pg_dumpall > outfile
象上面描写的那样,倾倒出的文件可以用 psql 恢复. 不过这时候你绝对需要数据库超级用户权限,因为我们需要它来恢复 用户和组信息.

pg_dumpall 有一个小毛病:它不能为所倾倒 的每个数据库做交互的认证.如果你使用口令认证,那你需要设置 环境变量 PGPASSWORD,以便给下面干活的 pg_dump 传递口令.更严重的是,如果你为不同的数据库设置了不同的口令, 那 pg_dumpall 会失效.你可以为备份设置不同 的认证机制或者你也可以修改 pg_dumpall 脚本,使之符合你的要求.

8.1.3. 大数据库

致谢: 最早由 Hannu Krosing ()写于 1999-06-19。

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

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

pg_dump dbname | gzip > filename.gz
用下面命令恢复:
createdb dbname
gunzip -c filename.gz | psql dbname
或者
cat filename.gz | gunzip | psql dbname

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

pg_dump dbname | split -b 1m - filename

用下面命令恢复:

createdb dbname
cat filename.* | psql dbname

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

pg_dump -Fc dbname > filename

请参考 pg_dumppg_restore 的手册获取细节.

8.1.4. 注意

pg_dump (以及建筑在其上的 pg_dumpall))有几个限制,这些限制的来源是 我们很难从系统表中 重构某些信息.

具体说来,pg_dump 写对象的顺序并不复杂.这样可能 导致问题,比如说当把函数用做字段缺省值时.唯一的解决方法是 手工为倾倒重新排序.如果你在数据库设计里面创建了循环依赖 关系,那你就有更多事要做了.

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

请熟悉一下 pg_dump 的手册页.