在日常数据库运维中,数据页损坏是较为严重的故障场景。当数据库中某个对象所在的数据页损坏,且该业务表有数据读写操作时,会导致数据库宕机。更严重的是,守护进程在拉起数据库进行回滚的过程中,如果涉及损坏的数据页,将导致数据库启动失败,整个集群无法恢复正常运行。
本文基于实际故障处理经验,详细记录MPP主备集群数据页损坏的修复流程,包括故障现象、恢复步骤、风险提示等关键信息。
当数据页损坏的业务表有数据读写时,数据库日志会报错如下:
图1:数据页损坏时的读写报错日志
[错误信息示例]
数据页校验失败,xdec_move_from_nrec......
数据库异常宕机后,守护进程尝试拉起数据库,但在回滚过程中涉及损坏的数据页,导致数据库启动失败,报错示例如下:
图2:数据库启动失败报错日志
[启动失败日志]
回滚过程中发现数据页损坏,无法继续恢复
整个恢复流程分为以下几个关键步骤:
首先尝试通过监视器命令进行主备切换:
-- 切换指定组的指定库为PRIMARY库
switchover [group_name[.]] [db_name]
-- 使用指定组的指定库接管故障PRIMARY库
takeover [group_name[.]] [db_name]
-- 强制接管故障PRIMARY库
takeover force [group_name[.]] [db_name]
注意事项:
# 备份日志示例
cp -r /dm8/data/DAMENG/dmarch /dm8/data/DAMENG/dmarch_bak
cp -r /home/dmdba/dmdbms/log /home/dmdba/dmdbms/log_bak
cp dm8/data/DAMENG/logcommit dm8/data/DAMENG/logcommit_bak
修改数据页损坏节点的dm.ini文件:
port_num = 6666 # 防止应用自动重连
pseg_recv = 0 # 跳过回滚
mal_ini = 0 # 关闭MAL系统
mpp_ini = 0 # 关闭MPP配置
ARCH_INI = 0 # 关闭归档,切断与其他节点通信
以MOUNT模式启动数据页损坏节点主库,修改数据库状态为NORMAL并强制OPEN:
-- 启动数据库后执行
SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 1);
alter database normal;
ALTER DATABASE OPEN FORCE;
SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 0);
使用命令正常停止数据库:
SHUTDOWN IMMEDIATE;
关键检查点:确认数据库日志显示"shutdown successfully",非正常停库的实例无法进行dmdbchk检查。
直接对整个数据库进行校验(适用于数据量较小的情况):
./dmdbchk path=/dm8/data/DAMENG/dm.ini
通过系统视图获取索引ID范围,分组进行多线程检查(适用于数据量较大的情况):
-- 获取最大最小索引ID
SELECT MIN(ID), MAX(ID) FROM SYSINDEXES;
假设ID范围差值为1059,分两组(500/559)进行检查:
# 第一组:ID 1-500
./dmdbchk PATH=/dm8/data/DAMENG/dm.ini START_INDEXID=1 END_INDEXID=500
# 第二组:ID 500-1059
./dmdbchk PATH=/dm8/data/DAMENG/dm.ini START_INDEXID=500 END_INDEXID=1059
dmdbchk输出日志示例:
检查结果
启动数据页损坏节点数据库服务,通过dmdbchk日志获取数据库中损坏的对象ID,通过SYSOBJECTS视图获取对应报错对象。对于索引进行删除后重建,业务表重命名后重建:
-- 通过对象ID获取对象名和对应模式
SELECT
owner,
table_name,
table_owner,
INDEX_NAME,
INDEX_type
FROM dba_indexes
WHERE INDEX_NAME IN (
SELECT NAME
FROM SYSOBJECTS
WHERE ID IN (对象ID1, 对象ID2, 对象ID3, ...)
);
处理完损坏对象后,正常停库,然后恢复dm.ini原始配置:
port_num = 5236 # 恢复原端口
pseg_recv = 3 # 启用回滚
mal_ini = 1 # 启用MAL系统
mpp_ini = 1 # 启用MPP配置
ARCH_INI = 1 # 启用归档
对于损坏的业务表,采用重命名后重建的方式:
-- 1. 重命名原表
ALTER TABLE 模式名.表名 RENAME TO 表名_BAK;
-- 示例
ALTER TABLE FJQ.T1 RENAME TO T1_BAK_20231101;
对于损坏的索引,删除后重建:
-- 1. 删除损坏的索引
DROP INDEX "模式名"."索引名";
-- 2. 如果是主键索引,先去掉主键约束
ALTER TABLE "模式名"."表名" DROP PRIMARY KEY;
-- 3. 重建索引(使用原索引DDL)
CREATE INDEX "模式名"."索引名" ON "模式名"."表名"(列名);
-- 4. 如果是主键,重新添加主键约束
ALTER TABLE "模式名"."表名" ADD PRIMARY KEY(列名);
踢出对应节点的备库,后续通过备份主库,还原备库方式恢复集群:
-- 在监视器中执行
detach DATABASE 组名.实例名
备库踢出后,需要通过主库备份进行备库还原,恢复完整的集群架构:
本文档中的适配方法适用于所有DM8数据库版本以及数据架构。
达梦数据页损坏的修复是一个复杂且风险较高的操作,需要严格按照步骤执行。关键点包括:
建议在日常运维中加强监控和备份,防患于未然,降低数据页损坏带来的业务风险。
文章
阅读量
获赞
