本次准备复现一下之前遇到的一个错误,因为硬盘的故障导致的 primary 实例上的 pg_class 表内容缺失,会造成在 master 主机查询报错。
在自己的测试机创建新的数据库和表,并将 psql 命令进入的默认数据库改为新创建的。
如果不指定的话执行 psql 命令就会报错
建表
查看指定模式下有多少张表
如果不确定表的模式名也可以这样,schema 就是模式名。
复现错误,删除 primary 实例上 pg_class 表中的内容。
获取表的 oid,比如 a,b 两表。oid 字段如果不指定的话是不会出现的。
登录任意 peimary 节点
标准语句
PGOPTIONS="-c gp_session_role=utility" psql -h ip -p 端口 -d 模式名
例如本次我想登录 gp1 主机上的 gpseg0 实例
在 gp_segment_configuration 表中也能查到端口
删除之前先备份使用 copy to 命令,可以看到备份的是两行数据。
备份的文件是在登录的指定主机上 我登录的是 gp1 主机备份的文件就在 gp1 主机的家目录下
需要注意的是如果没有指定 oid 字段,就需要加上参数指定 OIDS
删除 gpseg0 主机 pg_class 表中关于 a,b 两表的内容,此时在 gp1 主机上的 pg_class 表是没有 a,b 表的内容了,但是在 master 表是有的。并且此时被删除的表无法在 master 主机上删除。
master 主机
gp1 主机
无法删除
其中 set allow_system_table_mods=DML; 是允许对元数据进行修改,假如不设置的话就会提示没有权限。
以上的操作是为了复现当时的错误,正常情况下遇到这样的报错需要使用 gpcheckcat 命令来检验数据库目录表的不一致性。
有两个选择一个是在线检查,一个是全量检查 可以根据本身业务的需求选择使用。默认的输出目录是家目录下的 gpAdminLogs 目录
在线检查:
nohup $GPHOME/bin/lib/gpcheckcat -O -A -p 5432 2>&1 > gpcheckcat.date +%F_%s.log &
全量检查:注意全量检查需要加 master 的端口
nohup $GPHOME/bin/lib/gpcheckcat -A -p5432 2>&1 > gpcheckcat.date +%F_%s.log &
可以看到刚才删除的表名和 oid 和 segid
接下来就是修复鉴于 gp1 主机上只有一个 primary,所以尝试使用 gp2 主机 primary 的 pg_class
登录 gp2 主机
将 a,b 两表的内容 copy 到家目录
将文件从 gp2 传输到 gp1
登录 gp1 主机使用 copy 命令使用 gp2 主机的文件恢复并查询
master 主机查询