原作者:许玉晨
1.背景概述
在进行Mogdb数据恢复操作过程中,误用omm用户rm -rf命令删除数据库主目录下/dbdata所有数据库相关目录,该目录下保存数据库数据文件,数据库可执行文件,备份文件等,该操作导致Mogdb数据库不可用。
经过24小时连续作业,所有数据表补数完成,业务侧复查数据无缺失。
后持续观察,数据库运行稳定,服务器负载正常,业务测反馈业务服务正常。
2.故障分析
2.1 故障现象
17时,收到用户通知,用户误将某表部分数据update,请求将表数据恢复到16时00分钟左右,使用brm备份进行基于时间点的不完全恢复,跟用户核对数据后,备份表数据,使用trucnate命令删除表数据后,将不完全恢复的数据导入。少时,用户发现某外检表数据也被清理,跟用户沟通后,将数据库数据重新恢复到17点15分。
基于对磁盘空间不足的考虑,准备删除基于16:00的不完全恢复目录,但是在删除时,误切换到上层目录,使用命令rm -rf ./*,删除了整个数据库的主数据目录,所有数据文件被删除。
误操作步骤:
# 建立不完全恢复库
/dbdata/app/brm/brm restore -i mogdb --recovery-target-time='2022-03-30 16:00:00' -D /dbdata/datarev
## 数据导出
vi /dbdata/datarev/postgresql.conf
sed -i s\port = 51000\port = 51002\g /dbdata/datarev/postgres.conf
gs_ctl start -D /dbdata/datarev
gsql -d owner -p 51002 -r
select count(*) from owner.a;
gs_dump -U owner -W owner@1234 -p 51002 -f /dbdata/dbback/a.sql owner -t a
gs_ctl stop -D /dbdata/datarev
## 删除数据
owner=> truncate table owner.a;
ERROR: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "b" references "a".
HINT: Truncate table "b" at the same time, or use TRUNCATE ... CASCADE.
owner=> truncate table owner.a cascade;
owner=> select count(*) from owner.a;
count
-------
0
(1 row)
## 导入数据并核对
\i /dbdata/dbback/a.sql
owner=> select count(*) from owner.a;
count
--------
170595
(1 row)
owner=> select status,count(1) from owner.a group by status;
status | count
--------+--------
5 | 17
3 | 50
4 | 164774
7 | 59
1 | 1505
-1 | 77
0 | 118
2 | 104
99 | 3891
(9 rows)
## 发现外键表数据缺失,重新建立17:15恢复库
gs_om -t stop
## 手动备份生产数据库
cp -r /dbdata/data /dbdata/data_bak
# 查看不完全恢复的文件目录
cd /dbdata/datarev
ls -ltr
cd ..
du -sh *
查看不完全恢复目录大小,此时操作目录位于数据文件目录,导致了之后的误操作
## 需要重新进行不完全恢复操作,操作前清理/dbdata/datarev文件目录
## 操作时,没有确认当前目录和目录下文件,就执行了rm -rf命令,导致故障的发生
rm -rf ./*
rm -rf 命令导致数据库运行的必要可执行文件,数据文件,备份文件遗失,引发数据库服务中断。**
2.2 故障处置
故障发生后,通过对现场情况评估后,制定三套故障恢复方案:
方案一:二线专家对当前系统fork住的gsql进程数据进行灾难性挽救
方案二:由专业的数据恢复工程师提供软件对数据目录进行恢复
方案三:从测试数据库提取2月备份数据,作为最后的后备方案
方案一:开始登录远程服务器,进行数据挽救,通过检查gsql fork进程,查询对应打开的句柄文件后,发现数据虽然存在挽救价值。但是句柄文件缓存目录/proc对应的数据文件已经非常琐碎,且存在数据遗失的可能,使用该数据进行数据恢复,存在不可预知性及大量困难。。
方案二:确认测试库2月备份集存在,并验证数据集有效性,开始远程对搭建数据恢复环境工程师开始进行数据镜像的制备,但是由于数据损坏严重,在启动数据库时,频繁出现文件块损坏及数据文件缺失的报错,需要不停试错,导致修复数据库进展缓慢,仍未能恢复数据库服务。
次日,方案二完成镜像,并预备抽取数据。放弃方案一,抽取数据库主目录文件,尝试启动数据库,发现数据恢复的数据库服务虽然较为完整,仍存在小部分文件缺失,制定两个新方案恢复数据库:
方案四:使用镜像抽取的主数据库数据进行恢复
方案五:使用镜像抽取的备份集数据进行恢复
由于方案四可以比较可以快得出结果,优先使用方案四进行数据恢复,1个小时的尝试后,发现进展缓慢后,更换为方案五进行恢复。
从镜像抽取的备份集较多,共4份,除其中一份缺失较为严重外,剩余三份备份集具备恢复价值,从距离故障节点最近的备份集开始依次尝试恢复数据。
恢复过程:
## 清理备份库
cd /dbdata/datarev
pwd
cd /dbdata/datarev_202203282330
pwd
rm -rf datarev/*
rm -rf datarev_202203282330/*
## 新建29日和30日备份库
gs_probackup restore --force --skip-block-validation -B /dbdata/dbback --instance=mogdb --recovery-target-time='2022-03-30 17:15:00' -D /dbdata/datarev
gs_probackup restore --force --skip-block-validation -B /dbdata/dbback --instance=mogdb --recovery-target-time='2022-03-29 23:30:00' -D /dbdata/datarev_202203282330
## 重置参数文件
cp ../pg_hba.conf .
cp ../postgresql.conf .
cp ../recovery.conf .
# 查找xlog对应关系,并将日志目录中的xlog匹配到还原点
cd /dbdata/dbback/wal/mogdb/
mv .. xlog
## 启动数据库
gs_ctl start -D /dbdata/datarev
gs_ctl start -D /dbdata/datarev_202203282330
## 提取对应数据
# 30日数据
gs_dump -h 127.0.0.1 -p 50004 -U owner -W owner@1234 -Fc -f /nas/backup/owner_0329.dump owner
# 29日数据
gs_dump -h 127.0.0.1 -p 41000 -U owner -W owner@1234 -Fc -f /nas/backup/owner_0330.dump owner
## 新建生产数据库
## 分别将数据导入
gs_restore -p 51000 -U owner -W owner@1234 -d owner2 /nas/backup/owner_0329.dump
gs_restore -p 51000 -U owner -W owner@1234 -d owner /nas/backup/owner_0330.dump
截止至晚18点,数据库服务恢复,用户初步确认数据可供业务正常使用。
4月1日早,跟用户沟通后,发现部分表数据有不一致的现象,继续进行数据挖掘,并提供相应的SQL进一步分析确认是否有其他表数据缺失,截至12点,完成所有数据表的比对和数据更新。
## 对比数据量
select relname,n_live_tup from pg_stat_user_tables where schemaname='owner';
select 'select count(*) as '||relname|| ' from '||schemaname||'.'||relname||';' from pg_stat_user_tables where schemaname='owner';
diff -u /home/omm/owner_30.sql /home/omm/owner_29.sql > /home/omm/2.log
## 补数
gs_dump -U owner -W owner@1234 -p 51000 -f /nas/backup/0401_add_02.sql owner2 -a -t a_activity_to_psn -t lib_doc_dn_act -t problem_worklog -t kb_solution_activity -t problem_activity -t kb_solution_comment -t problem_participator -t problem_activity_to_psn -t a_ticket_handler -t kb_knowledge_comment -t lib_doc -t problem_ref_chg -t problem_comment -t kb_knowledge_activity -t problem_handler -t kb_knowledge
create table ***_0401 as select * from ***_to_psn;
## 重新验证对比数据效果
gsql -p 51000 -U owner -W owner@1234 -d owner -f /nas/backup/0401_add_02.sql
diff -u /home/omm/owner_30.sql /home/omm/owner_29.sql > /home/omm/2.txt
3. 根本解决方案及建议
1、对之后现场的任何变更预写操作脚本,在测试服务器通过验证后。再与用户申请割接时间实施变更
2、谨慎使用“rm -rf *”命令,在rm之前先pwd,并ls验证文件后,使用rf -rf 文件的方式删除,也可以替换为mv命令
3、将数据文件和备份文件目录分离,最小化之间的影响
4、配置主备环境,从库可在主库故障时,开始接替数据服务,实现业务测的无感知切换
5、提供对NBU异地备份集的定期恢复测试




