如何使用pgAdmin 4备份数据表?备份无数据问题求助
嘿,我之前也遇到过类似的情况——明明表有几百万行数据,pg_dump出来的文件却只有几KB,日志还没报错,确实挺让人头疼的。结合你给出的命令和日志,我来帮你排查几个最可能的原因,以及对应的解决办法:
1. 检查是否只备份了表结构,没包含数据
首先先确认pgAdmin的Backup配置有没有问题:打开Backup窗口后,切换到「Dump Options #1」标签,看看「Dump」选项是不是选了「Schema and Data」。如果不小心选了「Schema only」,那pg_dump只会导出表的结构,不会包含任何数据,文件自然很小。
如果是这个问题,重新选择「Schema and Data」再备份一次就行。
2. 目标表是分区表?
从你的日志看,pg_dump最后停在pg_dump: dumping contents of table "public.status",但没有后续的行统计信息,这很可能是因为status是分区表,而你的pg_dump版本没加分区数据导出的参数。
PostgreSQL 12及以上版本,pg_dump默认不会自动导出分区表的子分区数据,需要手动加上--include-partition-data参数。你可以手动在终端运行下面的命令试试:
/Applications/pgAdmin 4.app/Contents/SharedSupport/pg_dump --file "/Users/xxx/device_status_2m_full" --host "myhostname" --port "5432" --username "postgres" --no-password --verbose --format=c --blobs --table "public.status" --include-partition-data "mydatabasename"
如果是分区表的问题,加上这个参数后,备份文件的大小应该就正常了。
你也可以先通过SQL确认是不是分区表:
SELECT relname, relpartitioned FROM pg_class WHERE relname = 'status' AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public');
如果返回的relpartitioned是t,那就是分区表无疑了。
3. 目标表是外部表(Foreign Table)?
如果status是外部表(数据存储在其他数据源,比如另一台数据库或者文件里),pg_dump默认只会导出表的结构,不会导出外部数据源里的数据。
你可以用下面的SQL检查:
SELECT ftrelid::regclass AS foreign_table_name FROM pg_foreign_table WHERE ftrelid = (SELECT oid FROM pg_class WHERE relname = 'status' AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public'));
如果有结果返回,那就是外部表。这种情况下,你需要直接从外部数据源备份数据,或者用COPY命令把数据导出到本地文件:
COPY public.status TO '/Users/xxx/device_status_2m.csv' WITH (FORMAT csv, HEADER);
4. 手动验证数据导出情况
如果上面的排查都没问题,你可以先导出纯文本格式的数据,看看有没有实际内容:
/Applications/pgAdmin 4.app/Contents/SharedSupport/pg_dump --file "/Users/xxx/device_status_2m_data.sql" --host "myhostname" --port "5432" --username "postgres" --no-password --verbose --table "public.status" --data-only "mydatabasename"
打开这个SQL文件,如果里面没有INSERT语句或者只有空的结构,那说明pg_dump确实没读到表中的数据——这时候可能需要检查表的权限(虽然日志没报错,但可以确认下postgres用户有没有读取public.status的权限),或者是不是表的数据被意外清空了(不过你说有200万行,这个可能性不大)。
内容的提问来源于stack exchange,提问作者Chris Morgan

