Greenplum的元数据错误也会影响到数据备份过程,在使用pg_dump进行数据结构备份时,会由于分布策略的缺失导致备份失败,本文介绍此错误的解决办法。
现象
使用pg_dump命令备份整个Greenplum数据库的数据结构时:
pg_dump -f /data/dailybak/dw-nodata-$(date +%Y%m%d%H%M%S) -v -F c -p 5432 -h masterhostname -C -d databasename -s
报出如下错误后,备份进程终止:
pg_dump: query to obtain distribution policy of table "table1" returned no data
分析
出现此错误后,从pg_class元数据表中找到此relation的oid:
psql databasename -c "select oid,* from pg_class where relname='table1';"
假定输出的oid为1234,relnamespace为5678,如果有多条,就逐条处理,从gp_distribution_policy中查找localoid为此oid的记录:
psql databasename -c "select oid,* from gp_distribution_policy where localoid=1234;"
此查询应返回0条记录,从pg_namespace中找到此表所属namespace名称:
psql databasename -c "select * from pg_namespace where oid=5678;"
假定nspname为ns1,至此,证明ns1.table1没有分布策略,因此备份失败
解决
基本思路是为ns1.table1设置分布策略:
- root登陆master host
- 切换到Greenplum的管理员用户,比如gpadmin:
su - gpadmin
- 使用psql连接数据库:
psql databasename
- 设置随机分布策略
alter table ns1.table1 set distributed randomly;
或者设置指定列为分布依据
databasename=# alter table ns1.table1 set distributed by (column1);
如果此修改报错:
ERROR: SET DISTRIBUTED BY not supported on non-distributed tables
则放弃下一步重分布,drop掉ns1.table1重建吧
- 重分布
databasename=# alter table ns1.table1 set with(reorganize=true);
- 重建完或重分布完,查看修改结果:
databasename=# \d ns1.table1
应返回表的基本信息
databasename=# select oid,* from pg_class where relname='table1';
如重建过,假定返回的oid为12345,否则就是1234
databasename=# select oid,* from gp_distribution_policy where localoid=12345;
应返回这个表的分布策略
- pg_dump是个讨厌的家伙,它一遇到错误就停止,解决了它才会继续向下,如果再遇到错误再停止,为了避免此类型的错误继续出现,可使用如下命令查询ns1中没有分布键值的表,此输出中可能包含视图,挑选需要处理的用户表按照上面的步骤进行处理:
databasename=# select relname from pg_class where relnamespace=5678 and oid not in (select localoid from gp_distribution_policy);
其他
附送两个pg_dump的其他问题:
- 提示pg_class.oid是不存在的字段,如果遇上了,去查一下错误信息中只是的namespace里是不是有叫pg_class的用户自定义表,如果有,重命名或drop它吧,为什么要建也system catalog一样名字的表呢。。。三天啊,整整三天。。。
pg_dump: SQL command failed
pg_dump: Error message from server: ERROR: column c.oid does not exist
LINE 1: ...spname='dataservice' AND c.relnamespace=n.oid AND c.oid = p....
^
pg_dump: The command was: SELECT attrnums from pg_namespace as n, pg_class as c, gp_distribution_policy as p WHERE c.relname = 'table1' AND n.nspname='ns1' AND c.relnamespace=n.oid AND c.oid = p.localoid
pg_dump: *** aborted because of error
- 在使用-o参数进行pg_dump时,提示某些表不存在,但是这些表在任何节点的pg_class中都不存在,也无法drop,办法是把丫创建出来
pg_dump: SQL command failed
pg_dump: Error message from server: ERROR: relation "ns1.table1" does not exist
pg_dump: The command was: LOCK TABLE ns1.table1IN ACCESS SHARE MODE
pg_dump: *** aborted because of error