概述
客户的GP节点磁盘遭遇损坏,导致数据丢失。gprecoverseg命令无法恢复节点后做的一次非常规Greenplum恢复操作。
使用背景
在某次紧急运维下,我发现用户GP的某一个primary节点的状态异常,已经显示down掉,在确认所在的机器和磁盘没有异常后,我使用gprecoverseg命令去同步已经down的primary节点。但是失败了,在使用gpstate -e查看到的同步进度中看到同步了一会儿,但是随后失败了。(失败的原因是因为该mirror节点的磁盘曾经坏过,做过恢复,但是恢复的数据不是很完全,导致同步时校验出错),在该mirror节点的日志信息中查看到下面这段信息:
2019-03-16 21:30:35.341666 CST,,,p108637,th-1138622144,,,,0,,cmd126,seg-1,,,,,"ERROR","58P01","could not open relation 1663/43186/8782691: No such file or directory",,,,,,"(null)",0,,"md.c",1371,"Stack trace:
1 0xaf75c6 postgres errstart + 0x1f6
2 0x9f62ca postgres <symbol not found> + 0x9f62ca
3 0x9f7980 postgres mdnblocks + 0xf0
gprecoverseg命令会去从mirror节点获取数据去恢复primary节点,获取的数据多少在GP master的元数据表中都有记录,但是此时,mirror上的数据已经丢失,同步数据的进程到这里出错,因为找不到要找的表的数据,就直接退出,不再同步数据了,导致命令失败。
这种情况下,其实Greenplum的一主一备的高可用已经被破坏。数据已经永久丢失了,Greenplum本身没有什么好的办法恢复集群的状态了。
另辟蹊径
客户机器在mirror的支持下,依然是可以运行的,数据库的使用是正常的,但是客户担忧负载在一台机器磁盘上,依然会有风险,需要把GP恢复到完备的状态,其实我们还是有一个强行恢复Greenplum的方法
因为Greenplum的primary和mirror的文件目录的信息是完全一致的,不论是参数文件还是数据文件。我们完全可以手动将mirror上的文件目录拷贝过来,作为primary使用。但是要想让greenplum在下次启动时默认primary是好的去运行,还得做一些操作,完整如下:
将数据库先关闭,保证业务停止,mirror的数据目录不再有数据变化
gpstop -m fast
将mirror的数据目录完整发送到primary的目录
scp -r gpseg12 @sdw2:/data/primary/gpseg12 :示例
完成之后,再单独将master节点启动
gpstart -m
进入到master数据库中(其实master数据库有三个template0,template1和postgres,这三个是全局的,进哪一个都一样)
PGOPTIONS='-c gp_session_role=utility' psql template1
获取系统表的DML权限,以便后续修改状态
set allow_system_table_mods='dml';
预防起见,将数据库的该系统表做一次备份
create table 16_gp_segment_configuration as select * from gp_segment_configuration
将坏的节点全部状态信息改为正常,人为修改它的状态
update gp_segment_configuration SET status='u' where dbid=3;
退出后关闭master节点
gpstop -m
最后将数据库正常启动
gpstart -a
启动完成之后,再看看集群的状态全部正常了。数据库也正常运行了。
后记
此种恢复的方法,关键点在于需要保证mirror作为数据目录,是可以正常运行的,也得保证将此目录完整的拷贝到primary中。