GBase 8a数据库集群在某台服务器彻底故障时,需要通过节点替换操作进行恢复。对新机器的操作系统,配置,当前集群状态等有些要求可以提前准备。
目录导航
故障恢复机器要求
准备好文件系统
- 新机器的操作系统要和老机器的一致,不要混合操作系统版本。
- 文件系统做好。
- mount目录, 注意打开读、写和运行权限,并写入启动文件,比如/etc/fstabs。
- 操作系统root和gbase(如果存在的话)密码要统一。
- 如果节点【操作系统都重做了】,且使用的是8.6.2Build20 系列老版本,那么请提前在新节点手工建好gbase操作系统用户,而且确保是带-m主目录创建的,主目录下有.bash_profile和.bashrc的默认环境变量参数。因为一些老版本有BUG,会用gbase用户ssh连接来检查磁盘可用空间,而不是root。 8.6.2Build43等新版本无这个问题。
- 如果节点【操作系统都重做了】,老节点的操作系统root和gbase用户主目录/.ssh/known_hosts要删掉和故障IP相关内容,或者干脆这个文件删掉,否则当通过ssh连接时,会报认证错误(见图1)。
- 如果数据库集群修改过tmpdir等配置参数,且指向了新节点默认不存在的目录,请提前创建,否则数据库虽然能启动,但不能查询(tmpdir不存在),导致在检查是否各节点表数量一致时失败。
- sshd的超时参数要确认足够长。避免ClientAliveInterval 这类参数太小,导致执行过程中出现连接断开。如果修改参数无效,可能需要联系安全加固人员协助。
- ssh的超时参数要确认足够长。避免ServerAliveInterval 这类参数太小,导致执行过程中出现连接断开。如果修改参数无效,可能需要联系安全加固人员协助。
- sshd的默认连接数要足够。默认的10个太少了,建议修改100个以上。
老机器要求
- 各节点操作系统用户root和gbase的密码不能过期。
- 各节点操作系统用户root和gbase的密码和新节点保持一致。chage -l USERNAME 查看。 如果修改密码,记得要保持和原有密码一致。
- 现有集群的操作系统gbase用户的安装时的密码保存在 .gbase_profile下。 在某些老版本集群里,一些命令不能指定dbaPassword, 所以如果dbauser的密码修改过,要【临时】还原回来,或者更正环境变量文件里的参数。参考 【GBase 8a集群扩容注意事项】第3条。
- 现有集群的管理节点的源数据库gbase(GCLUSTER_HOME/userdata/gcluster/gbase),里面的审计日志表audit_log类等占用空间非常大的表,要提前清理,整个gbase元数据库容量建议不要超过200M。如果太大,比如10G,会增加打包和传输数据到故障恢复节点的时间。
- 老集群可能打过补丁,有些参数可能标准版本不支持。 需要申请新的版本,或者暂时将老集群的参数注释掉,等替换完成了,再恢复回来。
集群要求
- 集群的event如果很多,要提前清理,因为替换时会清理event,但占用了申请的操作时间。至少要避免出现主副本全部为1的情况
- 如果系统有长时间运行的DDL语句,请提前结束。避免占用了节点替换的操作时间。
- 所有调度节点 information_schema.tables表数量必须相同,否则在替换完成最后一步会因为这个原因报错而失败。 select count(*) from information_schema.tables
- 查看event, 如果有主副本都被设置标志时,先处理。 https://www.gbase8.cn/4822
意外处理
- 在节点替换过程中,如果出现 replace.py 命令故障,比如屏幕被关了,机器断电等,集群如果处于 READONLY 状态,可以使用 gcadmin switchmode normal 恢复集群状态。 故障节点的状态是replace状态,不用管它,可以再次执行 replace.py 命令的。
- 如果是8.6.2Build20等古老的版本执行,看到replace.log里执行到 gcadmin showcluser f 等任何操作系统命令都卡住时,需要替换InstallFuns.py里面的如下代码
def ExecCMD(cmd,withlog=True):
logger.debug(cmd)
args = shlex.split(cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = True)
[rv, out, err] = [p.wait(), p.stdout.read(), p.stderr.read()]
if(rv and withlog):
logger.error(out)
logger.error(err)
return [rv, out, err]
改成如下的新版集群的。有效变动就是红色代码部分。
def ExecCMD(cmd,withlog=True):
if withlog:
logger.debug(cmd)
args = shlex.split(cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = True)
out,err = p.communicate()
rv = p.returncode
if(rv and withlog):
logger.error(out)
logger.error(err)
return [rv, out, err]