等待 PostgreSQL 19:为 pg_dumpall 添加非文本输出格式
2026年2月26日,Andrew Dunstan 提交了补丁:
为 pg_dumpall 添加非文本输出格式
现在,pg_dumpall 除了纯文本 SQL 脚本外,还可以生成 custom(自定义)、directory(目录)或 tar 格式的输出。当使用非文本格式时,pg_dumpall 会创建一个包含以下内容的目录:
toc.glo:全局数据(角色和表空间),采用 custom 格式map.dat:数据库 OID 和名称之间的映射关系databases/:子目录,包含按 OID 命名的每个数据库的归档文件
pg_restore 已扩展为能够处理这些 pg_dumpall 归档文件,先恢复全局对象,然后恢复每个数据库。可以使用 --globals-only 选项仅恢复全局对象。
这实现了对 pg_dumpall 输出的并行恢复,以及从集群级备份中选择性地恢复单个数据库。
作者:Mahendra Singh Thalor mahi6run@gmail.com
合著者:Andrew Dunstan andrew@dunslane.net
评审者:Tushar Ahuja tushar.ahuja@enterprisedb.com
评审者:Jian He jian.universality@gmail.com
评审者:Vaibhav Dalvi vaibhav.dalvi@enterprisedb.com
评审者:Srinath Reddy srinath2133@gmail.com
讨论:https://postgr.es/m/cb103623-8ee6-4ba5-a2c9-f32e3a4933fa@dunslane.net
这是一个巨大的改进。
长期以来,我们显然有 pg_dump------它非常适合转储单个数据库,可能支持并行、压缩,并且可以部分恢复。我们还有 pg_dumpall------一个有趣的工具,很多刚接触 PostgreSQL 的人会使用它。但我个人从未真正考虑过用它。我的意思是,我确实用它来转储全局对象(主要是角色),但我不会用它来转储实际的数据库。
原因很简单------它很慢,并且生成基于文本的输出,我无法选择要加载什么。至少不经过对转储文件进行某种"解析"是不行的。这很不理想。
但现在,我与它相关的所有问题,按理说都已经解决了。
现在,让我们看看基准情况。运行:
bash
=$ vtime pg_dumpall -f dump.all.plain
real 104.565s
=$ ls -ldh dump.all.plain
-rw-rw-r-- 1 depesz depesz 70G Mar 17 10:53 dump.all.plain
好的。104秒,生成一个70GB的单一文件。当然我可以压缩它,但这是默认输出。
显然,即使使用 -Fd 格式转储,pg_dumpall 也无法利用多个并行工作进程。那么,让我们试试转储为 custom 格式,看看效果如何:
bash
=$ vtime pg_dumpall -Fc -f dumpall-fc
real 759.551s
=$ ls -ldh dumpall-fc
drwx------ 3 depesz depesz 4.0K Mar 17 11:01 dumpall-fc/
=$ fd . dumpall-fc/ -X ls -lhd
drwx------ 2 depesz depesz 4.0K Mar 17 11:14 dumpall-fc/databases
-rw-rw-r-- 1 depesz depesz 4.0G Mar 17 11:08 dumpall-fc/databases/16386.dmp
-rw-rw-r-- 1 depesz depesz 1.6K Mar 17 11:01 dumpall-fc/databases/1.dmp
-rw-rw-r-- 1 depesz depesz 1.1K Mar 17 11:14 dumpall-fc/databases/5.dmp
-rw-rw-r-- 1 depesz depesz 11K Mar 17 11:08 dumpall-fc/databases/740752.dmp
-rw-rw-r-- 1 depesz depesz 1.2K Mar 17 11:01 dumpall-fc/databases/740820.dmp
-rw-rw-r-- 1 depesz depesz 4.0G Mar 17 11:14 dumpall-fc/databases/740829.dmp
-rw-rw-r-- 1 depesz depesz 469 Mar 17 11:14 dumpall-fc/map.dat
-rw-rw-r-- 1 depesz depesz 2.5K Mar 17 11:14 dumpall-fc/toc.glo
这次花费的时间明显更长,并生成了一组文件。我们可以用它们做什么呢?
首先,看看里面有什么。有两个文件,以及一个包含六个 .dmp 文件的目录。让我们来探究一下......
databases 目录中的 dmp 文件是每个数据库独立的、使用 pg_dump -Fc 格式的简单转储。然后,您可以使用它们列出其内容,或者可能只加载部分内容:
bash
=$ pg_restore -l dumpall-fc/databases/740829.dmp | grep -v TABLE.DATA > list.just.table
=$ pg_restore -L list.just.table -f - dumpall-fc/databases/740829.dmp
--
-- PostgreSQL database dump
--
\restrict D1GT0oDrsj9xgHrP27Km4hzhdMQLRWqngWnGgYgLKVkJ6NuOoNresbSwqDJuL4r
-- Dumped from database version 19devel
-- Dumped by pg_dump version 19devel
SET statement_timeout = 0;
...
SET default_table_access_method = heap;
--
-- Name: plans; Type: TABLE; Schema: public; Owner: depesz
--
CREATE TABLE public.plans (
id text NOT NULL,
...
entered_from inet
);
ALTER TABLE public.plans OWNER TO depesz;
--
-- PostgreSQL database dump complete
--
\unrestrict D1GT0oDrsj9xgHrP27Km4hzhdMQLRWqngWnGgYgLKVkJ6NuOoNresbSwqDJuL4r
很好。
那么另外两个文件呢?
map.dat 是一个非常简单的文件,它告诉我们转储时哪个数据库具有哪个 OID,这反过来告诉我们哪个文件包含哪个数据库的转储:
bash
=$ cat dumpall-fc/map.dat
#################################################################
# map.dat
#
# This file maps oids to database names
#
# pg_restore will restore all the databases listed here, unless
# otherwise excluded. You can also inhibit restoration of a
# database by removing the line or commenting out the line with
# a # mark.
#################################################################
1 template1
740820 depesz
16386 depesz_explain
740752 test
740829 pgdba
5 postgres
=$ ls -l dumpall-fc/databases/740829.dmp
-rw-rw-r-- 1 depesz depesz 4198979861 Mar 17 11:14 dumpall-fc/databases/740829.dmp
这里我们看到 740829.dmp 包含了 pgdba 数据库的转储。很好。
最后是 toc.glo,它是另一个 pg_dump -Fc 类型的转储,包含所有全局对象的信息:
bash
=$ pg_restore -l dumpall-fc/toc.glo
;
; Archive created at 2026-03-17 11:01:42 CET
; dbname: postgres
; TOC Entries: 13
; Compression: none
; Dump Version: 1.16-0
; Format: CUSTOM
; Integer: 4 bytes
; Offset: 8 bytes
; Dumped by pg_dump version: 19devel
;
;
; Selected TOC Entries:
;
1; 0 0 default_transaction_read_only - default_transaction_read_only
2; 0 0 client_encoding - client_encoding
3; 0 0 standard_conforming_strings - standard_conforming_strings
4; 0 0 DROP_GLOBAL - DATABASE depesz
5; 0 0 DROP_GLOBAL - DATABASE depesz_explain
6; 0 0 DROP_GLOBAL - DATABASE test
7; 0 0 DROP_GLOBAL - DATABASE pgdba
8; 0 0 DROP_GLOBAL - ROLE depesz
9; 0 0 DROP_GLOBAL - ROLE depesz_explain
10; 0 0 DROP_GLOBAL - ROLE pgdba
11; 0 0 ROLE - ROLE depesz
12; 0 0 ROLE - ROLE depesz_explain
13; 0 0 ROLE - ROLE pgdba
以上就是所有内容。
我实际上非常希望 pg_dumpall 能支持 --jobs=X 参数,但我想它会随着时间的推移而实现。目前,这已经是对我的工具箱的一个很好的补充,并且确实使 pg_dumpall 成为考虑进行简单备份时的一个严肃工具。
感谢所有参与的人,非常棒的工作 🙂