本文已更新至
dmdul v0.8.0。新版补充了 DMASM 多数据库自动发现、两阶段离线坏页诊断,以及 DM8 HUGE/HFS 列存储表的字典、DDL 和数据恢复能力。
做达梦运维时,最棘手的情况往往不是误删一张表,而是数据库已经无法正常 open:控制文件、ROLL、REDO 或归档链路出现问题,DMRMAN 也无法完成常规恢复。此时手里可能只剩下一组 .DBF 文件,甚至只剩下离线 DMASM 成员盘,但业务数据仍然存在于物理介质中。
dmdul 就是为这类场景准备的。它不连接数据库实例,也不修改原始介质,可以从两类离线来源读取数据:
SYSTEM.DBF、可选的 dm.ctl、用户表空间 DBF,以及 HUGE 表需要的 HFS 目录;*-flat.vmdk,无需启动 DMASMSVR,也无需先执行 asmcmd cp。使用边界:
dmdul不是常规备份恢复工具,不能替代 DMRMAN、归档恢复、闪回、dexp或达梦原厂恢复流程。它定位于常规手段无法继续时的离线只读救援。所有导出结果都必须先在隔离测试库中验证。
当前能力链有两条输入路径。文件系统 DBF 可以直接进入字典恢复;DMASM 成员盘则先恢复磁盘组目录、INODE、AU 映射、副本和条带,再把其中的数据库文件作为只读逻辑 DBF 使用。两条路径最终共用同一套 bootstrap、字典和数据解析器。
文件系统离线快照 离线 DMASM 成员盘
SYSTEM.DBF / 用户 DBF / HFS 裸设备 / *-flat.vmdk
| |
| v
| DMASM 元数据与 AU 映射
| INODE / 副本 / 条带
| |
| v
| ASM 逻辑 DBF
| |
+-------------------+---------------------+
|
v
统一只读离线数据源
DBF + 可选的 HFS 根目录
|
v
Standard Bootstrap + SYSTEM 物理预检
|
v
Dictionary Recovery
|
+----------+----------+
| | |
v v v
DDL / SQL dmfldr Native DMP
| |
v v
dmfldr dimp
| |
+------+------+
|
v
隔离达梦测试库
目前的核心能力包括:
SYSTEM.DBF 中恢复 SYSOBJECTS、SYSINDEXES 等系统字典,优先沿 storage root -> internal refs -> leaf chain 下载字典数据;dmdul_dict/*.tsv。字典可以人工审核和修订,再通过 load dictionary; 复用;INSERT SQL,也可以生成 dmfldr 文本与控制文件,或生成由官方 dimp 识别的原生 DMP;recover table 可以尝试读取 DELETE、DROP、TRUNCATE 后尚未被覆盖的残留页,并记录物理来源证据。普通行表的数据位于 DBF 的段和数据页中。HUGE 表建立在混合表空间上,完整 section 的列数据位于 Huge File System(HFS)目录,尚未整理的事务增量则位于普通 DBF 中的内部辅助表。
因此,只扫描 MAIN.DBF 会漏掉 HFS 主体数据;只读取 HFS 文件又会漏掉新增、删除和更新增量。v0.8.0 按下面的关系恢复逻辑行:
SYSTEM.DBF 字典
|
+-- HUGE 主表
+-- 表$AUX section 位置、列号、偏移和行数
+-- 表$RAUX 尚未进入完整 section 的尾部行
+-- 表$DAUX 逻辑删除范围
+-- 表$UAUX 更新后的列值
|
v
HFS/SCH#########/TAB####/COL####_##########.dta
|
v
HFS section + RAUX - DAUX + UAUX
|
v
统一逻辑行 -> SQL / dmfldr / DMP
bootstrap 会识别 HUGE 主表及四类辅助对象,并把 HUGE 标志、SECTION、FILESIZE、WITH DELTA 和辅助表 ID 写入 dmdul_dict/tables.tsv。DDL 可以恢复已经验证的存储属性:
CREATE HUGE TABLE SYSDBA.DMDUL_HUGE_SIMPLE (
ID INT NOT NULL,
VAL VARCHAR(20),
TAG CHAR(1)
)
STORAGE(SECTION(1024), FILESIZE(16), WITH DELTA, ON MAIN);
数据卸载按 section 流式读取 .dta,不会把整个 HFS 文件一次性装入内存;随后读取 RAUX、DAUX 和 UAUX,合并为表的最终逻辑结果。
当前已经完成以下实机验证:
MINUS=0;MINUS=0;MINUS=0;dimp REMAP_SCHEMA 导入 1499 行,与同快照 SQL 回灌表双向 MINUS=0。这项能力仍然有明确边界。当前验证范围是未压缩、未加密的单一 HFS path,已验证 HFS 列类型为非空 INT 和可空/非空 VARCHAR/CHAR。压缩、加密、未验证的可空定长列或类型会在输出第一行前明确失败,不会生成看似成功但内容不可信的结果。DMASM 裸盘路径当前只映射 DBF,HFS 目录仍需另外提供。
DMASM 支持不是把裸盘当成普通 DBF 全盘搜索。dmdul 会解析磁盘头、目录、INODE、描述 AU、数据 AU、副本数组和条带规则,再按 ASM 文件逻辑偏移读取 DBF。
目前已验证的能力包括:
执行 set asm_disk 后,工具会立即扫描全部磁盘组的 INODE 目录,列出每个 SYSTEM.DBF 候选及其数据库名、字符集、页大小和对应 DBF 集合。只有一个候选时会自动选中;存在多个数据库时不会猜测,必须使用 set system <ASM path>; 明确选择。
候选证据会保存到:
dmdul_dict/asm_databases.tsv
dmdul_dict/asm_datafiles.tsv
如果其他工具需要普通 DBF,可以使用 cp:
DMDUL> cp +NORM4/data/MIRRORDB/SYSTEM.DBF /recovery/dbf/SYSTEM.DBF;
DMDUL> cp datafile /recovery/dbf;
复制过程使用固定大小缓冲区,先写临时文件,完成同步后再改名,并输出字节数、耗时和 SHA-256。DMASM 解析仍属于实验性能力,成员盘必须来自同一时点且已经停止写入。工具当前不重放 DMASM 元数据事务。
恢复流程不要求用户在 bootstrap 前重复执行检查命令。v0.7.3 起,bootstrap; 会先自动完成 SYSTEM 文件的纯物理预检,再尝试恢复字典。
| 阶段 | 入口 | 范围 | 字典依赖 | 何时执行 |
|---|---|---|---|---|
| 第一阶段 | bootstrap; 自动执行 |
完整 SYSTEM.DBF |
不依赖 | 每次从当前快照重建字典时自动执行 |
| 第二阶段 | check pages; |
全部或指定 DBF | 物理检查不依赖;对象归属依赖当前会话字典 | SYSTEM 预检告警、整库恢复、介质可疑或需要审计报告时 |
第一阶段发现坏页时,bootstrap 会尽量继续读取仍可用的字典,并以 SUCCESS_WITH_WARNINGS 提示进入第二阶段。如果字典无法建立,check pages; 仍能完成纯物理扫描,但无法可靠归属的坏页会标记为 UNATTRIBUTED。
第二阶段会生成三份报告:
output/check_summary.md
output/check_bad_pages.tsv
output/check_affected_objects.tsv
报告包含文件、页号、绝对字节偏移、损坏类型、storage ID、可能受影响的对象和归属置信度。独立检查只使用当前会话通过 bootstrap 或显式 load dictionary 加载的字典,不会偷偷套用目录中残留的旧字典。
对于普通表,数据定位按下面的顺序执行:
1. 根据 storage root、internal refs 和 leaf chain 生成 page plan
2. page plan 完整时,仅用 ReadAt 读取计划页
3. 根页损坏或断链时,扫描同 group 文件并匹配 storage_id
4. storage_id 回退仍失败时,按段范围读取
5. 只有 recover table 才允许全文件残留页扫描
每次卸载都会记录实际路径:
planned pages: 12
direct pages read: 12
fallback pages scanned: 0
fallback reason: none
这些信息不仅用于观察性能,也用于判断恢复证据强弱。出现 fallback 时,应结合原因、失败行数、坏页报告和目标库核对结果共同评估。
最短流程是把 dmdul.exe、SYSTEM.DBF、全部用户表空间 DBF 和可选的 dm.ctl 放在同一个可写目录。目标包含 HUGE 表时,还要放入同一快照的完整 HFS 根目录,例如 HMAIN/。
D:\recovery> dmdul.exe
DMDUL> list datafile;
DMDUL> bootstrap;
DMDUL> list user;
DMDUL> list table HR_TEST;
DMDUL> describe HR_TEST.EMP_INFO;
DMDUL> set data_format dmp;
DMDUL> unload user HR_TEST;
DMDUL> exit;
dm.ctl 仅作为 group/file/表空间映射的增强核对来源。恢复目录存在同名 DBF 时,工具优先读取用户准备的离线副本,不会跟随控制文件中的原绝对路径回到在线文件。
DMDUL> set data_dir /recovery/asm-work;
DMDUL> set asm_disk /dev/dmasm/ext4a,/dev/dmasm/ext4b,/dev/dmasm/norm4a,/dev/dmasm/norm4b;
DMDUL> list asmfile;
唯一数据库候选会自动选中。如果输出多个候选,先核对数据库名、页大小、字符集和完整 DBF 集合,再选择目标:
DMDUL> set system +NORM4/data/MIRRORDB/SYSTEM.DBF;
DMDUL> list datafile;
DMDUL> bootstrap;
DMDUL> unload user ASMTEST;
独立 check pages; 当前扫描文件系统 data_dir。需要对 ASM 中全部逻辑 DBF 做第二阶段检查时,先执行 cp datafile <directory>;,再切换到复制目录检查。
# 默认:可审查的 INSERT SQL
DMDUL> set data_format sql;
DMDUL> unload table HR_TEST.EMP_INFO;
# 分隔文本 + 每表 dmfldr 控制文件
DMDUL> set data_format fldr;
DMDUL> unload user HR_TEST;
# 达梦原生逻辑 DMP
DMDUL> set data_format dmp;
DMDUL> unload table HR_TEST.EMP_INFO;
DMDUL> unload user HR_TEST;
DMDUL> unload schema HR_TEST;
DMDUL> unload database;
默认输出位于启动目录的 output/。DMP 对应达梦 TABLES / OWNER / SCHEMAS / FULL 四种互斥逻辑级别,可由官方 dimp 导入。FLDR 模式会为每张非空表生成 .txt 和 .ctl,先执行 _ddl.sql 建表,再调用:
dmfldr USERID=SYSDBA/password@127.0.0.1:5236 CONTROL="'HR_TEST_EMP_INFO_data.ctl'"
CONTROL 外层双引号用于把内部单引号原样交给 dmfldr,不是排版错误。
项目曾使用 DM8 单表 1000 万行、13 列、约 2.13 GiB 表空间、4 核 4 GiB 主机做专项测试。下表记录的是 v0.5.8 阶段的实测,不是对 v0.8.0 的重新跑分:
| 场景 | 早期实现 | 优化后 |
|---|---|---|
| SQL 卸载(4 核) | 内存溢出退出 | 87 秒 |
| DMP 卸载(4 核) | 内存溢出退出 | 116 秒 |
| SQL 卸载(8 核) | 未测试 | 49 秒 |
这些改进已经保留在当前版本中:page plan 按批次并行解码,worker 根据 CPU 和任务规模自适应;writer 按序合并,保证并行与顺序输出确定;在飞字节背压限制大 LOB 和大表的峰值内存;DMP 使用缓冲写、worker 侧预编码和多 phase 输出。
实际速度仍会受到磁盘介质、页分布、行宽、LOB 比例、fallback 程度和输出格式影响,不能把这组数据当作所有生产库的性能承诺。
| 场景 | dmdul 可以做什么 |
|---|---|
数据库无法 open |
从仍可读的离线文件尝试恢复字典、DDL 和表数据 |
| 常规恢复链路失败 | 在保留官方恢复优先级的前提下,提供只读物理抽取路径 |
| 只剩 DBF | 从 SYSTEM 和用户表空间文件恢复对象及数据 |
| 只剩 DMASM 成员盘 | 解析已验证的 DMASM 布局,直接读取或复制逻辑 DBF |
| 部分页损坏 | 定位坏页、尝试对象归属,并继续抽取其他可读页 |
| DROP / TRUNCATE 后救援 | 原数据页未被覆盖时尝试残留恢复 |
| HUGE 列存储表 | 合并 HFS section 与 RAUX/DAUX/UAUX,输出 DDL 和逻辑数据 |
离线抽取不等于事务一致性恢复。普通 unload 已收紧为 slot-only,但 slot-only 不等于 committed-only;未提交事务的最终可见性仍需要完整事务状态和 Undo 证据。损坏页、断链、多版本残留以及未验证的存储格式也可能降低结果可信度。
请始终保留原始介质的只读副本,优先尝试官方恢复路径。导出后至少核对对象数量、表行数、关键列、分区分布、LOB 长度与哈希,再决定如何使用结果。
项目使用 Go 编写,提供 Windows x64 和 Linux x64 预编译包,采用 MIT 许可证。
欢迎试用和提交 Issue,也欢迎提供可脱敏的失败案例、存储格式差分样本与导入验证结果。离线恢复工具的可靠性,最终来自可重复的物理证据和回灌核对,而不是对未知格式的大胆猜测。
文章
阅读量
获赞
