FGDDU 是一款由风哥自主研发的达梦数据库(DM Database)数据卸载与恢复工具,旨在达梦数据库无法启动且没有备份的情况焉,不依赖达梦数据库实例运行,绕过数据库引擎层,从底层进行数据库的数据抽取与灾难恢复场景。
目录
一、程序介绍
1.1 工具定位
在国产达梦数据库的实际运维中,DBA 经常会遇到数据库无法正常启动的极端故障:例如系统表空间(SYSTEM 表空间)数据文件损坏、控制文件 dm.ctl 丢失或损坏、参数文件 dm.ini 异常、在线日志文件(REDO LOG)损坏、数据文件物理坏块、人为误执行 DROP/TRUNCATE/DELETE 等致命操作。在这些场景下,传统的备份恢复、归档恢复手段往往束手无策,业务数据面临丢失的巨大风险。
FGDDU 正是为应对上述灾难场景而生:它不依赖达梦数据库实例运行,绕过数据库引擎层,直接以裸读取(raw read)的方式解析达梦数据文件(.DBF)的底层物理存储结构,逐页提取行数据,并将恢复结果导出为 DMP(自定义二进制格式)或 SQL(INSERT 语句)文件,最终导入到新建的达梦数据库实例中,从而实现"无数据库环境下的数据抢救"。
1.2 工作原理
FGDDU 的工作流程可以概括为"发现 → 识别 → 解析 → 提取 → 输出"五个阶段:
达梦数据文件 (.DBF)
↓
[1] 文件发现:扫描数据目录,定位所有 .DBF 文件
↓
[2] 自动识别:检测页大小(4K/8K/16K/32K)、DM 版本(DM7/DM8)、读取 dm.ini
↓
[3] 字典加载:从 SYSTEM.DBF 中解析表、列、用户、Schema 等元数据
↓
[4] 行数据提取:逐页扫描,解析行目录,解码各数据类型,并扫描空闲空间找回已删除行
↓
[5] 输出写入:每个表输出独立 DMP/SQL 文件,支持按用户分目录
↓
新建达梦库导入恢复
FGDDU 直接读取达梦底层存储结构,理解每一个页(Page)的组织方式:文件头页(File Header Page)、数据页(Data Page)、索引页(Index Page)、LOB 页(BLOB Page)、分配位图页(Allocation Bitmap)等。它通过解析行目录(Row Directory)定位每行数据的物理偏移,再根据列定义(数据类型、长度、精度)逐字段解码。
对于已删除的数据,FGDDU 会扫描数据页内的空闲空间(Free Space),从中识别尚未被覆盖的残余行数据,从而恢复 DELETE 操作删除的行;对于已 DROP 的表,FGDDU 通过孤儿页三级匹配算法(参数指定表名 → 页内表名字符精确匹配 → 数据签名启发式匹配)将孤立数据页关联到对应表结构。
1.3 适用场景
FGDDU 适用于但不限于以下场景:
| 场景类别 | 具体故障 |
|---|---|
| 数据库无法启动 | 系统表空间损坏、控制文件丢失、参数文件异常、在线日志损坏 |
| 物理坏块 | 数据文件出现 ORA-600 类似的页校验失败、坏块 |
| 人为误操作 | DELETE 误删行、DROP TABLE 误删表、TRUNCATE 误清空表 |
| 字典损坏 | SYSTEM.DBF 部分损坏,无法通过 SQL 访问元数据 |
| 数据迁移 | 数据库可启动但希望以裸文件方式快速导出全库数据 |
| 单文件恢复 | 仅剩单个 .DBF 文件,需要从中抢救数据 |
| 应急演练 | 在无备份、无归档的极端情况下做最大努力恢复 |
1.4 作者信息
FGDDU 全称 :FGEDU 达梦 DM DUL(Data UnLoader)
作者 :风哥
二、功能特性
2.1 核心功能概览
| 功能模块 | 说明 |
|---|---|
| 全库导出(export-all) | 指定数据目录即可导出整个数据库所有表数据,无需数据库运行 |
| 最大恢复(recover full) | 存活数据 + 已删除数据 + 孤儿数据,三级匹配最大化恢复 |
| 删除数据恢复(recover delete) | 扫描页内空闲空间,找回 DELETE 操作删除的行 |
| 丢弃表恢复(recover drop) | 扫描孤立数据页,恢复 DROP TABLE 删除的表数据 |
| 截断表恢复(recover truncate) | 查找 TRUNCATE 截断前的残留数据 |
| 原始扫描(recover raw) | 忽略系统字典,提取所有可识别行数据,适用于字典完全损坏 |
| 指定表导出(export) | 按表名 / schema.table 精确导出单张表 |
| 单文件导出(export-file) | 直接从单个 .DBF 文件导出所有表数据 |
| 裸设备恢复(RAW Device) | 直接读取 /dev/raw/rawN、/dev/sdX、/dev/dm-* 等裸设备 |
| ASM 磁盘恢复(--asm) | 读取 DmASM磁盘作为数据源 |
| 数据目录诊断(diagnose) | 诊断数据文件损坏情况,定位坏块位置 |
| 元数据浏览(scan / list / desc) | 扫描统计、列出对象、查看表结构 |
2.2 自动检测能力
FGDDU 内置强大的自动检测机制,最大限度减少 DBA 手工参数:
- 页大小自动识别 :支持 4KB / 8KB / 16KB / 32KB 四种达梦标准页大小,通过分析文件头与页结构自动判定,无需
--page-size手工指定。 - DM 版本自动识别:自动区分 DM7 与 DM8 的存储格式差异。
- dm.ini 自动读取:自动定位并解析数据目录下的 dm.ini 配置文件,提取页大小、实例名、版本等关键参数。
- 数据文件自动发现 :指定
-d数据目录后,自动递归扫描所有 .DBF 数据文件。 - 系统字典自动加载:自动从 SYSTEM.DBF 中解析表、列、用户、Schema、表空间等元数据。
- 裸设备自动识别 :当
-d或-f指向/dev/raw/rawN、/dev/sdX、/dev/dm-*、/dev/mapper/*、/dev/nvme*、/dev/vd*、/dev/loop*、/dev/cciss/*、/dev/zd*等裸设备路径时,FGDDU 自动识别为裸设备模式,通过ioctl(BLKGETSIZE64)获取设备大小,无需手工指定页大小。 - ASM 磁盘自动识别 :当
-d或-f指向以+开头的 ASM 磁盘组路径(如+DATA/DAMENG/SYSTEM.DBF)或ORCL:前缀的 ASM 磁盘名时,FGDDU 自动识别为 ASM 模式;也可通过--asm显式声明。
2.3 裸设备与 ASM 支持
FGDDU 支持直接从裸设备(RAW Device)和 ASM 磁盘读取数据,无需先将数据文件拷贝成普通文件。这对于达梦数据库使用裸设备或 DmASM 作为底层存储的生产环境尤为重要------DBA 无需额外准备磁盘空间做文件中转,FGDDU 直接对裸设备做只读扫描即可恢复数据。
2.3.1 支持的存储类型
| 存储类型 | 说明 | 识别方式 |
|---|---|---|
| 普通文件(FILE) | 标准 .DBF 数据文件 | 自动识别(.DBF 扩展名 + 文件头校验) |
| 数据目录(DIRECTORY) | 包含多个 .DBF 的目录 | -d <目录> 自动递归扫描 |
| 裸设备(RAW) | /dev/raw/rawN、/dev/sdX、/dev/dm-、/dev/mapper/、/dev/nvme* 等 | 路径前缀自动识别 + stat() 设备类型校验 + --raw-device 显式声明 |
| ASM 磁盘(ASM) | DmASM 磁盘、磁盘 | + 前缀 / ORCL: 前缀自动识别 + --asm 显式声明 |
2.3.2 裸设备大小解析机制
裸设备的特殊性在于 stat() 返回的 st_size 为 0,无法像普通文件那样直接获取大小。FGDDU 采用多级回退策略解析裸设备大小:
- 用户指定优先 :通过
--device-size <n>显式指定设备大小(支持 K/M/G/T 单位,如100G、500M)。这是最可靠的方式,推荐用于/dev/raw/rawN字符设备。 - ioctl(BLKGETSIZE64) :对块设备(
/dev/sdX、/dev/dm-*、/dev/loop*)通过BLKGETSIZE64ioctl 获取精确字节数。 - ioctl(BLKGETSIZE):旧版内核回退方案,返回扇区数(×512 字节)。
- EOF 二分探测 :对无法通过 ioctl 获取大小的字符设备,通过二分查找
pread的 EOF 位置估算可用大小。
2.3.3 ASM 磁盘处理说明
达梦 DmASM 与 在磁盘头部有独立的 AU(Allocation Unit)映射元数据,完整的 ASM 文件系统解析需要 ASM 客户端库。FGDDU 的 ASM 支持采用"整盘扫描"策略:
- 将 ASM 磁盘作为裸设备整体只读扫描,逐页解析达梦数据页结构。
- 通过
data_offset跳过 ASM 磁盘头(kfbh),从数据 AU 起始位置扫描。 - 适用于 ASM 磁盘可用但 ASM 实例未启动 / 损坏的灾难场景。
- 对于需要在 ASM 文件级别精确切片的场景,建议先用
dd或asmlib工具将 ASM 文件导出为普通文件,再用 FGDDU 处理。
2.3.4 裸设备/ASM 安全说明
- 只读访问 :FGDDU 始终以
O_RDONLY只读模式打开裸设备/ASM 磁盘,绝不写入或修改原始数据。 - 无缓冲刷新 :直接通过
pread读取,不修改设备游标,不影响其他进程对设备的访问。 - 权限要求:运行 FGDDU 的操作系统用户需对裸设备节点有读权限(通常需要 root 或 disk 组成员)。
- 建议先备份 :对生产裸设备操作前,建议通过
dd if=/dev/raw/raw1 of=/backup/raw1.img做一份物理备份。
2.4 恢复算法亮点
2.4.1 孤儿页三级匹配
当面对 DROP TABLE 或字典损坏场景时,部分数据页已经无法通过字典直接定位归属表。FGDDU 采用三级匹配算法进行关联:
第 1 级:参数指定表名匹配
↓ 不命中
第 2 级:页内表名字符精确匹配(边界匹配,避免子串误匹配)
↓ 不命中
第 3 级:数据签名启发式匹配(可打印字符串比例 + 行列数比例评分,≥50 分匹配)
↓ 仍不命中
写入 REMNANT_*.sql 通用残余文件,不丢失任何可读数据
该机制确保即便在极端损坏情况下,FGDDU 仍能将可识别的行数据保存到 REMNANT 表中,DBA 可在新库中人工筛选关联。
2.4.2 删除行残余扫描
DELETE 操作不会立即物理擦除行数据,而是将行标记为删除状态并释放空间。FGDDU 扫描数据页内的空闲空间区域,识别尚未被新数据覆盖的残余行数据,结合列定义重建行结构。此能力是 recover delete 与 recover full 模式的核心。
2.4.3 坏块自动跳过
遇到页校验失败、页头非法、页号越界等坏块时,FGDDU 默认开启 --continue-on-error,自动跳过坏块继续处理后续页,最大化恢复可读数据,避免因单页损坏导致整个文件恢复中断。
2.5 LOB 数据导出
达梦数据库的 BLOB / CLOB / TEXT 等 LOB 类型列数据通常存储在独立的 LOB 页中,行内仅保留引用指针。FGDDU 对 LOB 数据提供完整支持:
- 默认导出 LOB:无需额外参数,FGDDU 自动通过 LOB 页引用解析行外 LOB 数据。
- 行内 LOB:随行数据一起导出。
- 行外 LOB:通过 LOB 页引用解析后导出。
- 跳过 LOB :使用
--no-lob可跳过 LOB 提取以加快速度(LOB 列输出为 NULL 或引用标记)。 - 输出表示:SQL 格式中,BLOB 以十六进制字符串表示,CLOB 以文本表示。
2.6 多格式输出
| 格式 | 命令参数 | 适用场景 |
|---|---|---|
| DMP(默认) | --format dmp |
二进制紧凑格式,每个表一个 .dmp 文件,适合大数据量导出 |
| SQL | --format sql |
INSERT 语句格式,可直接导入新库,通用性最强 |
| CSV | --format csv |
逗号分隔文本,便于与表格工具、ETL 工具对接 |
| TXT | --format txt |
制表符分隔文本,便于人工查看 |
2.7 灵活的对象过滤
FGDDU 支持多维度对象过滤,便于精准恢复:
- 按用户名过滤 :
-u <用户名>,只导出该用户拥有的表。 - 按 Schema 过滤 :
-s <Schema名>,按 Schema 名过滤(Schema 名可能与用户名不同)。 - 按表名过滤 :
-t <表名>或-t <schema.table>,跨 Schema 匹配或精确匹配。 - 系统表过滤 :默认排除 SYS 系统表,使用
--system包含系统表。 - 按用户分目录 :
--by-user自动按 Schema/用户名创建子目录组织输出。
2.8 进度可视化
- 进度心跳日志:每处理 1000 页或恢复 1000 行自动输出进度信息,防止误判程序卡死。
- 进度条模式 :
--progress显示可视化进度条。 - 详细模式 :
-v输出每个数据文件、每个表的扫描详情。 - 日志文件 :
--log <file>将日志同时写入文件,便于事后审计。
2.9 安全与稳定性保障
| 保障项 | 实现方式 |
|---|---|
| 段错误保护 | 捕获 SIGSEGV / SIGBUS,输出说明后退出而非直接崩溃 |
| 优雅停止 | 第一次 Ctrl+C 请求优雅停止,刷新输出文件后退出 |
| 强制中止 | 连续两次 Ctrl+C 强制中止 |
| 坏块跳过 | 默认 --continue-on-error,自动跳过坏块 |
| 输入验证 | 所有命令行参数进行 NULL / 范围 / 合法性检查 |
| 整数溢出保护 | 页号计算等关键运算使用 FGDDU_RANGE_CHECK 宏进行溢出检测 |
| 堆内存管理 | 大数组使用堆分配,避免栈溢出导致的段错误 |
| 跨平台路径 | 同时支持 / 和 \ 路径分隔符 |
| 编译器安全加固 | Linux 使用 -fstack-protector-strong + -D_FORTIFY_SOURCE=2 + -z,relro,-z,now;Windows 使用 /GS + /sdl + /DYNAMICBASE + /NXCOMPAT |
2.10 技术特点汇总
- 跨平台支持:同时支持 Linux(RHEL/Ubuntu/SUSE/国产 OS)和 Windows(7/8/10/11/Server)。
- 完全静态链接:Linux 编译为单个静态可执行文件,零依赖;Windows 使用静态 CRT(/MT)。
- 平台兼容层 :通过
fgddu_platform.h抽象层,一套源码两个平台编译运行。 - 信号保护:SIGSEGV/SIGBUS 崩溃保护 + SIGINT/SIGTERM 优雅停止。
- 坏块跳过:遇到坏块自动跳过,最大化数据恢复。
- 自动检测:自动识别页大小(4K/8K/16K/32K),自动读取 dm.ini。
- 最大恢复引擎:正常扫描 + 空闲空间扫描 + 原始扫描 + 孤儿页三级匹配。
- 全库导出:指定目录即可导出全部数据,自动发现所有数据文件。
- 进度心跳日志:每处理 1000 页或恢复 1000 行自动报告进度。
- 输入验证:所有参数进行 NULL/范围/合法性检查。
- 整数溢出保护:页号计算等关键运算进行溢出检测。
- 堆内存管理:大数组使用堆分配,避免栈溢出导致的段错误。
- 跨平台路径 :同时支持
/和\路径分隔符。 - 编译器安全加固:Linux 与 Windows 均启用栈保护、ASLR、DEP 等安全机制。
- 裸设备/ASM 支持 :直接读取 /dev/raw/rawN、/dev/sdX、/dev/dm-* 等裸设备及 DmASM/磁盘,通过 ioctl(BLKGETSIZE64) 自动解析设备大小,支持
--device-size手工覆盖。
三、支持环境
3.1 支持的操作系统
Linux 系列
| 发行版 | 支持版本 |
|---|---|
| RHEL(Red Hat Enterprise Linux) | 5 / 6 / 7 / 8 / 9 / 10 |
| OEL(Oracle Enterprise Linux) | 5 / 6 / 7 / 8 / 9 / 10 |
| CentOS | 5 / 6 / 7 / 8 / 9 |
| Ubuntu | 12.04 - 24.04 |
| Debian | 8 及以上 |
| SUSE / openSUSE | 11 及以上 |
| Kylin(麒麟) | V7 / V10 / V10 SP1 / V10 SP2 / V10 SP3 |
| UOS(统信) | V20 / V25 |
| NeoKylin(中标麒麟) | V6 / V7 |
| 龙蜥 Anolis OS | 7 / 8 |
| openEuler | 20.03 / 22.03 / 24.03 |
| Rocky Linux / AlmaLinux | 8 / 9 |
| 通用 Linux x86_64 | 内核 2.6.32 及以上 |
Windows 系列
| 版本 | 支持情况 |
|---|---|
| Windows 7 / 8 / 8.1 / 10 / 11 | 完全支持 |
| Windows Server 2008 R2 | 完全支持 |
| Windows Server 2012 / 2012 R2 | 完全支持 |
| Windows Server 2016 | 完全支持 |
| Windows Server 2019 | 完全支持 |
| Windows Server 2022 | 完全支持 |
处理器架构
- x86_64 / AMD64:主推架构,性能最佳。
- x86(32 位):理论支持,需自行 32 位编译。
- ARM64 / aarch64:国产 CPU(鲲鹏、飞腾)需在目标平台原生编译。
- 龙芯 / MIPS:需在目标平台原生编译并测试。
3.2 支持的达梦数据库版本
| 达梦版本 | 支持情况 |
|---|---|
| DM7(达梦数据库 7) | 完全支持 |
| DM8(达梦数据库 8) | 完全支持(含 DM8.1.x) |
3.3 编译环境要求
Linux 编译要求
- 编译器 :GCC 4.1 及以上(推荐 GCC 11+,以获得更完善的
-fstack-protector-strong与-D_FORTIFY_SOURCE=2支持)。 - 构建工具:GNU Make 3.81+。
- 静态链接库(可选):glibc-static,用于生成完全静态零依赖可执行文件。
- CMake(可选):CMake 3.10+,用于跨平台构建。
Windows 编译要求
- 构建工具:CMake 3.10+。
- 编译器 (任选其一):
- MSVC :Visual Studio 2015 / 2017 / 2019 / 2022,使用静态 CRT(/MT)编译,生成零依赖
fgddu.exe。 - MinGW-w64:GCC 8+,生成单文件可执行程序。
- MSVC :Visual Studio 2015 / 2017 / 2019 / 2022,使用静态 CRT(/MT)编译,生成零依赖
3.4 运行时依赖
| 平台 | 运行时依赖 |
|---|---|
| Linux(完全静态编译) | 零依赖,单文件 fgddu 直接运行 |
| Linux(半静态编译) | 仅依赖 libc.so.6 |
| Windows(MSVC 静态 CRT) | 零依赖,单文件 fgddu.exe 直接运行 |
| Windows(MinGW) | 可能依赖 mingw 运行库 |
3.5 磁盘与内存建议
- 磁盘空间:输出目录预留源数据文件总大小的 1.5 - 3 倍空间(SQL 格式通常比源数据大 1.5-2 倍)。
- 内存:建议 1GB 以上可用内存(用于页缓冲、字典缓存、行重建)。
- CPU:单线程扫描,对 CPU 要求不高,任何现代 x86_64 CPU 均可。
四、程序使用
4.1 编译安装
4.1.1 Linux 编译
bash
# 解压源码
tar xzf fgddu.tar.gz
cd FGDDU
# 默认编译:完全静态单文件可执行程序(推荐)
make
# 调试版本
make debug
# 发布版本
make release
# 便携版本(尝试完全静态,失败则半静态)
make portable
# 清理
make clean
# 安装到 /usr/local/bin
make install
# 编译结果位置
ls -lh build/standalone/fgddu
4.1.2 Windows 编译
方法 1:使用批处理脚本(自动检测编译器)
cmd
build_windows.bat
:: 或指定编译器:
build_windows.bat msvc
build_windows.bat mingw
方法 2:使用 CMake 手动编译
cmd
:: MSVC(Visual Studio)
mkdir build_win && cd build_win
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
:: MinGW
mkdir build_win && cd build_win
cmake .. -G "MinGW Makefiles"
cmake --build . --config Release
编译结果位于 build_win\Release\fgddu.exe(MSVC)或 build_win\fgddu.exe(MinGW)。
4.1.3 安装 glibc-static(仅 Linux,可选)
要生成零依赖的完全静态可执行文件,需要安装 glibc-static:
bash
# RHEL / OEL / CentOS / Kylin / UOS
yum install glibc-static
# Ubuntu / Debian
apt-get install libc6-dev
# SUSE / openSUSE
zypper install glibc-devel-static
如果未安装 glibc-static,FGDDU 将自动回退到半静态链接(仅依赖 libc.so.6)。Windows 上使用 MSVC 编译时默认使用静态 CRT(/MT),生成零依赖的 fgddu.exe。
4.1.4 验证编译结果
Linux:
bash
# 检查是否完全静态
file build/standalone/fgddu
# 期望输出: statically linked
# 检查依赖
readelf -d build/standalone/fgddu | grep NEEDED
# 期望: 无输出(零依赖)
# 运行版本检查
./build/standalone/fgddu version
Windows:
cmd
build_win\Release\fgddu.exe version
4.1.5 部署到目标服务器
Linux:
bash
scp build/standalone/fgddu target-server:/opt/fgddu/
ssh target-server "/opt/fgddu/fgddu version"
Windows:
cmd
copy build_win\Release\fgddu.exe \\target-server\c$\fgddu\
4.2 命令总览
| 命令 | 说明 |
|---|---|
version |
显示版本信息 |
help |
显示帮助 |
scan |
扫描数据目录,显示统计信息 |
scan-file |
扫描单个数据文件 |
list |
列出数据库中的表 / 用户 / Schema |
desc |
查看表结构 |
recover |
恢复删除 / 丢弃 / 截断的数据(支持 full 最大恢复) |
export |
导出指定表的数据 |
export-all |
全库导出(指定目录,导出所有表数据,支持按用户/Schema过滤) |
export-file |
按数据文件导出(从单个 .DBF 文件导出所有表数据) |
diagnose |
诊断数据文件损坏情况 |
recover 子命令
| 子命令 | 说明 |
|---|---|
delete |
恢复 DELETE 删除的行数据(扫描页内空闲空间) |
drop |
恢复 DROP 删除的表数据(扫描孤立数据页) |
truncate |
恢复 TRUNCATE 截断的表数据(查找截断前残留数据) |
full |
最大恢复(正常数据 + 删除数据 + 孤儿数据,推荐) |
raw |
原始扫描(忽略字典,提取所有可读数据) |
4.3 通用选项
| 选项 | 说明 |
|---|---|
-d, --data-dir <dir> |
DM 数据目录路径 |
-f, --file <path> |
单个数据文件路径 |
-o, --output <dir> |
输出目录(默认: ./output) |
-u, --user <name> |
按用户名过滤 |
-s, --schema <name> |
按 Schema 过滤 |
-t, --table <name> |
按表名过滤(支持 schema.table) |
--format <fmt> |
输出格式: dmp(默认), sql, csv, txt |
--page-size <size> |
指定页大小 (4096/8192/16384/32768) |
--dm-version <ver> |
DM 版本 (7或8) |
--max-rows <n> |
最大恢复行数 (0=不限) |
--include-deleted |
包含已删除的行 |
--include-dropped |
包含已丢弃的表 |
--system |
包含系统表(SYS schema) |
--raw |
原始扫描模式 |
--continue-on-error |
遇到错误继续(默认开启) |
--no-continue |
遇到错误停止 |
--by-user |
按用户名/Schema 自动创建子目录组织输出 |
--progress |
显示进度条 |
--no-lob |
跳过 LOB 数据提取(LOB 默认导出) |
--asm |
将 -d/-f 输入作为 ASM 磁盘处理(DmASM / Oracle ASM) |
--raw-device |
将 -d/-f 输入作为裸设备处理(/dev/raw/*、/dev/sdX 等) |
--device-size <n> |
指定裸设备/ASM 设备大小(支持 K/M/G/T 单位,如 100G、500M) |
-v, --verbose |
详细输出 |
-c, --config <file> |
从配置文件加载选项 |
--log <file> |
日志输出到文件 |
-h, --help |
显示帮助 |
-V, --version |
显示版本 |
4.4 命令详解
4.4.1 version - 显示版本
bash
fgddu version
4.4.2 help - 显示帮助
bash
fgddu help
4.4.3 scan - 扫描数据目录
扫描数据目录,显示文件信息、页统计和字典摘要。
bash
fgddu scan -d <数据目录> [选项]
示例:
bash
fgddu scan -d /opt/dmdbms/data/DAMENG
fgddu scan -d /opt/dmdbms/data/DAMENG -v
4.4.4 scan-file - 扫描单个文件
bash
fgddu scan-file -f <数据文件路径>
示例:
bash
fgddu scan-file -f /opt/dmdbms/data/DAMENG/SYSTEM.DBF
4.4.5 list - 列出数据库对象
列出数据库中的用户、Schema 和表。
bash
fgddu list -d <数据目录> [过滤选项]
示例:
bash
fgddu list -d /opt/dmdbms/data/DAMENG
fgddu list -d /opt/dmdbms/data/DAMENG -s SYSDBA
fgddu list -d /opt/dmdbms/data/DAMENG -u SYSDBA
4.4.6 desc - 查看表结构
bash
fgddu desc -d <数据目录> -t <表名>
示例:
bash
fgddu desc -d /opt/dmdbms/data/DAMENG -t T_TEST
fgddu desc -d /opt/dmdbms/data/DAMENG -t SYSDBA.T_TEST
4.4.7 recover - 数据恢复
bash
fgddu recover <子命令> -d <数据目录> -o <输出目录> [选项]
示例:
bash
# 恢复已删除数据
fgddu recover delete -d /opt/dmdbms/data/DAMENG -o ./recovery
# 恢复已删除的表
fgddu recover drop -d /opt/dmdbms/data/DAMENG -o ./recovery
# 恢复截断的表
fgddu recover truncate -d /opt/dmdbms/data/DAMENG -o ./recovery
# 最大恢复(推荐)
fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery
# 原始扫描(字典损坏时使用)
fgddu recover raw -d /opt/dmdbms/data/DAMENG -o ./recovery
# 指定表恢复
fgddu recover full -d /opt/dmdbms/data/DAMENG -t T_TEST -o ./recovery
# 输出为 SQL 格式
fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
4.4.8 export - 导出指定表
bash
fgddu export -d <数据目录> -t <表名> -o <输出目录> [选项]
示例:
bash
fgddu export -d /opt/dmdbms/data/DAMENG -t T_TEST -o ./output
fgddu export -d /opt/dmdbms/data/DAMENG -t SYSDBA.T_TEST -o ./output --format sql
fgddu export -d /opt/dmdbms/data/DAMENG -s SYSDBA -t T_TEST -o ./output
fgddu export -d /opt/dmdbms/data/DAMENG -u SYSDBA -t T_TEST -o ./output
fgddu export -d /opt/dmdbms/data/DAMENG -t T_BLOB_DATA -o ./output --no-lob
4.4.9 export-all - 全库导出(核心命令)
导出整个数据库的所有表数据。当达梦数据库无法启动时,只需指定数据目录,FGDDU 自动扫描所有数据文件并导出。
bash
fgddu export-all -d <数据目录> -o <输出目录> [选项]
说明:
export-all使用 FULL 模式(存活行 + 已删除行)做最大恢复。- 自动发现数据目录下所有 .DBF 文件。
- 自动检测页大小,无需手动指定。
- 每个表输出独立的 DMP/SQL 文件。
- LOB 数据默认导出(使用
--no-lob关闭)。 - 使用
--by-user按用户名/Schema 自动创建子目录组织输出。
示例:
bash
# 全库导出(DMP 格式,默认)
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./full_export
# 全库导出(SQL 格式,可直接导入新库)
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./full_export --format sql
# 全库导出并显示详细进度
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./full_export -v --progress
# 全库导出但跳过 LOB(节省时间)
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./full_export --no-lob
# 按用户过滤导出
fgddu export-all -d /opt/dmdbms/data/DAMENG -u SYSDBA -o ./output
# 按 Schema 过滤导出
fgddu export-all -d /opt/dmdbms/data/DAMENG -s TEST_SCHEMA -o ./output
# 按用户名 unload,自动按用户创建子目录(推荐)
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./recovery --by-user --format sql
# 最大恢复 + 按用户分目录
fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --by-user --format sql
4.4.10 export-file - 按数据文件导出
直接从一个数据文件中导出所有表的数据,不需要扫描整个数据目录。
适用场景:
- 数据目录部分文件丢失,只想恢复某一个 .DBF 文件。
- 想单独测试某个数据文件的可恢复性。
- 数据文件被复制到其他位置后恢复。
bash
fgddu export-file -f <数据文件> -o <输出目录> [选项]
示例:
bash
# 从单个数据文件导出所有表数据(DMP 格式,默认)
fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output
# 从单个数据文件导出所有表数据(SQL 格式)
fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --format sql
# 同时提供数据目录,加载字典获取列信息(推荐)
fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF \
-d /opt/dmdbms/data/DAMENG -o ./output --format sql
# 从损坏数据目录中已备份的单独文件恢复
fgddu export-file -f /backup/USER01.DBF -o ./recovery --format sql -v
# 指定页大小(自动检测失败时使用)
fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --page-size 8192
# 使用原始扫描模式(字典完全损坏时)
fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --raw
4.4.11 diagnose - 诊断数据文件
bash
fgddu diagnose -d <数据目录>
fgddu diagnose -f <数据文件>
示例:
bash
fgddu diagnose -d /opt/dmdbms/data/DAMENG
fgddu diagnose -f /opt/dmdbms/data/DAMENG/USER01.DBF
4.5 输出文件命名规则
- DMP 格式 :
<表名>.<Schema名>.dmp(如T_TEST.SYSDBA.dmp) - SQL 格式 :
<表名>.<Schema名>.sql(如T_TEST.SYSDBA.sql) - 孤儿数据 :
REMNANT_NN.RAW_DATA.sql(无法匹配到表的残余数据) - 按用户分目录 :
<输出目录>/<用户名>/<表名>.<Schema名>.sql
4.6 数据导入新库
4.6.1 SQL 格式导入(推荐)
bash
# 使用达梦 disql 工具导入
disql SYSDBA/password@localhost:5236 `cat recovery/*.sql`
# 逐个文件导入
for f in recovery/*.sql; do
disql SYSDBA/password@localhost:5236 `cat $f`
done
4.6.2 创建目标表
如果目标数据库中没有对应的表结构,需要先创建表:
sql
CREATE TABLE "SYSDBA"."T_TEST" (
"ID" INT,
"NAME" VARCHAR(100),
"CREATE_TIME" DATETIME
);
五、达梦DM案例场景与操作过程
5.1 案例一:达梦DM数据库无法启动,指定目录全库导出(核心场景)
问题描述: 达梦数据库因系统表空间损坏、数据文件损坏、参数文件丢失等原因无法启动,需要导出全部数据用于新建库恢复。
解决方案: 指定数据目录,FGDDU 自动扫描所有数据文件并全库导出。
操作步骤:
bash
# 1. 停止数据库实例,避免数据文件被修改
systemctl stop DmServiceDAMENG
# 2. 备份原始数据文件(强烈建议)
cp -r /opt/dmdbms/data/DAMENG /backup/DAMENG_backup_$(date +%Y%m%d)
# 3. 确认数据文件位置
ls /opt/dmdbms/data/DAMENG/*.DBF
# 4. 全库导出(方法一:export-all,导出存活数据)
./fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 4. 全库导出(方法二:recover full,最大恢复,含已删除数据,推荐)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql -v
# 5. 检查输出
ls -la ./recovery/
# 输出文件示例:
# T_TEST.SYSDBA.sql
# T_USERS.SYSDBA.sql
# T_ORDERS.SYSDBA.sql
# ...
# 6. 导入到新数据库
disql SYSDBA/password@newhost:5236 `cat recovery/*.sql`
FGDDU 自动完成的工作:
- 发现数据目录下所有 .DBF 数据文件。
- 自动检测页大小(4K/8K/16K/32K)。
- 自动读取 dm.ini 获取配置参数。
- 自动识别 DM 版本(DM7/DM8)。
- 加载系统字典获取表结构信息。
- 跳过坏块,最大化数据恢复。
- 每个表输出独立的 DMP/SQL 文件。
5.2 案例二:达梦DM误删除数据恢复(DELETE)
问题描述: 用户误执行 DELETE 操作删除了重要数据,且已提交,数据库无法启动或不愿通过闪回恢复。
操作步骤:
bash
# 恢复 DELETE 删除的数据
./fgddu recover delete -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 查看恢复结果
head -20 ./recovery/*.sql
# 验证恢复数据条数
wc -l ./recovery/*.sql
原理说明: DELETE 操作不会立即物理擦除行数据,而是将行标记为删除状态并释放空间。FGDDU 扫描页内的空闲空间,找回这些被标记删除但尚未被覆盖的行数据。注意:如果删除后该页有大量新数据写入覆盖了原行,则可能无法恢复。
5.3 案例三:达梦DM误删除表恢复(DROP TABLE)
问题描述: 用户误执行 DROP TABLE 删除了表。
操作步骤:
bash
# 恢复 DROP 删除的表数据
./fgddu recover drop -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 如果知道表名,可指定表名提高恢复准确率
./fgddu recover drop -d /opt/dmdbms/data/DAMENG -t T_LOST_TABLE -o ./recovery --format sql
# 使用最大恢复确保不漏数据
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
原理说明: DROP TABLE 会从字典中删除表定义,但数据页可能尚未被覆盖。FGDDU 扫描所有数据页,通过孤儿页三级匹配算法将孤立数据页关联到对应表结构。
5.4 案例四:达梦DM误截断表恢复(TRUNCATE)
问题描述: 用户误执行 TRUNCATE TABLE 清空了表数据。
操作步骤:
bash
# 恢复 TRUNCATE 截断的数据
./fgddu recover truncate -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 指定表名精确恢复
./fgddu recover truncate -d /opt/dmdbms/data/DAMENG -t T_TRUNCATED -o ./recovery --format sql
原理说明: TRUNCATE 操作会重置表的高水位(HWM),但物理数据页可能尚未被覆盖。FGDDU 通过扫描被截断表的原数据页范围,找回截断前的行数据。
5.5 案例五:达梦DM字典损坏,原始扫描
问题描述: SYSTEM.DBF 严重损坏,无法加载字典,无法通过 SQL 访问任何表结构。
操作步骤:
bash
# 使用原始扫描模式,忽略字典
./fgddu recover raw -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 检查输出,包含 REMNANT 表(无法匹配字典的残余数据)
ls -la ./recovery/
# 输出文件示例:
# RECOVERED_DATA.RAW_DATA.sql (无法匹配表名的孤儿页数据)
# REMNANT_001.UNKNOWN.sql (残余数据)
原理说明: 原始扫描模式不依赖系统字典,直接扫描所有数据页,提取所有可识别的行数据。输出的数据以 RAW_DATA 列形式保存,DBA 可在新库中人工筛选关联。
5.6 案例六:达梦DM指定数据目录做最大恢复(自动检测)
问题描述: 只知道数据文件目录,不确定页大小和 DM 版本,希望 FGDDU 自动检测并做最大恢复。
操作步骤:
bash
# 自动检测页大小,全库最大恢复
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql -v
FGDDU 自动完成:
- 检测页大小(4K/8K/16K/32K)。
- 识别 DM 版本(DM7/DM8)。
- 扫描所有数据文件。
- 跳过坏块,最大化恢复。
5.7 案例七:达梦DM按用户导出该用户名下所有数据
问题描述: 数据库无法启动,只想导出某个特定用户(如 SYSDBA 或业务用户)名下的所有表数据。
解决方案: 使用 -u <用户名> 参数过滤,只导出该用户拥有的表。
操作步骤:
bash
# 1. 先用 list 查看数据库中的用户和表清单
./fgddu list -d /opt/dmdbms/data/DAMENG
# 2. 按用户名导出该用户的所有表数据
./fgddu export-all -d /opt/dmdbms/data/DAMENG -u SYSDBA -o ./recovery_sysdba --format sql
# 3. 导出业务用户的所有表数据
./fgddu export-all -d /opt/dmdbms/data/DAMENG -u BUSINESS_USER -o ./recovery_biz --format sql
# 4. 按用户导出含已删除数据(最大恢复)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -u SYSDBA -o ./recovery_sysdba --format sql
# 5. 检查输出
ls -la ./recovery_sysdba/
5.8 案例八:达梦DM按 Schema 导出所有数据
问题描述: 想按 Schema 而非用户过滤导出(Schema 名与用户名可能不同)。
操作步骤:
bash
# 按 Schema 名导出
./fgddu export-all -d /opt/dmdbms/data/DAMENG -s TEST_SCHEMA -o ./recovery_test --format sql
# 按 Schema + 最大恢复
./fgddu recover full -d /opt/dmdbms/data/DAMENG -s TEST_SCHEMA -o ./recovery_test --format sql
5.9 案例九:达梦DM按指定表名导出(单表/多表)
问题描述: 只想恢复某一张或多张特定表的数据。
操作步骤:
bash
# 导出单张表(仅表名,跨 Schema 匹配)
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_TEST -o ./output --format sql
# 按 schema.table 格式精确指定
./fgddu export -d /opt/dmdbms/data/DAMENG -t SYSDBA.T_TEST -o ./output --format sql
# 指定 Schema + 表名
./fgddu export -d /opt/dmdbms/data/DAMENG -s SYSDBA -t T_TEST -o ./output --format sql
# 导出单张表(含已删除数据,最大恢复)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -t T_TEST -o ./output --format sql
# 多张表导出(一次一张,循环执行)
for tbl in T_TEST T_USERS T_ORDERS; do
./fgddu export -d /opt/dmdbms/data/DAMENG -t $tbl -o ./output --format sql
done
5.10 案例十:达梦DM按数据文件导出所有表数据
问题描述: 数据目录中某个 .DBF 文件损坏或丢失,或只想从单个数据文件中恢复数据。
解决方案: 使用 export-file 命令,直接指定单个 .DBF 文件导出该文件中的所有表数据。
操作步骤:
bash
# 1. 先用 diagnose 诊断单个数据文件
./fgddu diagnose -f /opt/dmdbms/data/DAMENG/USER01.DBF
# 2. 从单个数据文件导出所有表数据(DMP 格式)
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output
# 3. 从单个数据文件导出所有表数据(SQL 格式)
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --format sql
# 4. 同时提供数据目录以加载字典(推荐,可获得列结构信息)
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF \
-d /opt/dmdbms/data/DAMENG -o ./output --format sql
# 5. 数据文件已备份到其他位置时恢复
./fgddu export-file -f /backup/USER01.DBF -o ./recovery --format sql -v
# 6. 字典损坏时使用原始扫描模式
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --raw --format sql
# 7. 检查输出
ls -la ./output/
# 输出文件示例:
# T_TEST.SYSDBA.sql
# RECOVERED_DATA.SYSDBA.sql (无法匹配表名的孤儿页数据)
5.11 案例十一:达梦DM含 LOB 数据的表导出
问题描述: 表中包含 BLOB/CLOB/TEXT 等 LOB 类型列,需要将 LOB 数据一起导出。
解决方案: FGDDU 默认导出 LOB 数据,无需额外参数。如需跳过 LOB 可使用 --no-lob。
操作步骤:
bash
# 默认导出含 LOB 数据(推荐)
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_BLOB_DATA -o ./output --format sql
# 全库导出含 LOB 数据(默认即含)
./fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./output --format sql
# 跳过 LOB 导出(节省时间,LOB 列输出为 NULL 或引用标记)
./fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./output --no-lob
# 从单个文件导出含 LOB 数据
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./output --format sql
LOB 导出说明:
- LOB 数据默认导出(
extract_lob = true)。 - 行内 LOB(inline LOB)随行数据一起导出。
- 行外 LOB(out-of-line LOB)通过 LOB 页引用解析。
- 使用
--no-lob可跳过 LOB 提取以加快速度。 - SQL 格式输出中,BLOB 以十六进制字符串表示,CLOB 以文本表示。
5.12 案例十二:达梦DM按用户名 unload 全库数据(按用户分目录)
问题描述: 达梦数据库无法启动,需要按用户名导出全库所有能导出的表,并按用户名自动创建子目录组织输出,便于按用户恢复。
解决方案: 使用 --by-user 选项,FGDDU 自动按 Schema/用户名创建子目录,每个用户的表数据放在独立目录中。
操作步骤:
bash
# 1. 全库 unload,按用户名自动创建子目录(推荐)
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./recovery --by-user --format sql
# 2. 按用户名 unload(只导出指定用户,并按用户分目录)
fgddu export-all -d /opt/dmdbms/data/DAMENG -u SYSDBA -o ./recovery --by-user --format sql
# 3. 最大恢复 + 按用户分目录(含已删除数据)
fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --by-user --format sql
# 4. 按用户名 unload + 含 LOB 数据(默认即含)
fgddu export-all -d /opt/dmdbms/data/DAMENG -u BUSINESS_USER -o ./recovery --by-user --format sql
# 5. 按用户名 unload + 详细输出
fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./recovery --by-user --format sql -v
输出目录结构示例:
./recovery/
├── SYSDBA/ # SYSDBA 用户的表
│ ├── T_TEST.SYSDBA.sql
│ ├── T_USERS.SYSDBA.sql
│ └── T_ORDERS.SYSDBA.sql
├── FGEDU/ # FGEDU 用户的表
│ ├── FGEDU01.FGEDU.sql
│ ├── FGEDU02.FGEDU.sql
│ └── FGEDU_LOB.FGEDU.sql
└── RECOVERED_DATA/ # 无法匹配用户的孤儿数据
└── REMNANT_001.UNKNOWN.sql
按用户恢复导入:
bash
# 只导入 SYSDBA 用户的数据
for f in ./recovery/SYSDBA/*.sql; do
disql SYSDBA/password@newhost:5236 `cat $f`
done
# 只导入 FGEDU 用户的数据
for f in ./recovery/FGEDU/*.sql; do
disql fgedu/fgedu123@newhost:5236 `cat $f`
done
说明:
--by-user会自动为每个 Schema/用户创建子目录。- 无法匹配到已知用户的孤儿数据放在
UNKNOWN或RECOVERED_DATA目录。 - 与
-u/-s/-t过滤选项可组合使用。 - 适用于
export-all、recover full、recover delete、recover drop等所有导出/恢复命令。
5.13 案例十三:达梦DM跨平台恢复(Linux 服务器 + Windows 工作站)
问题描述: 生产环境为 Linux 服务器,但 DBA 希望在 Windows 工作站上分析恢复数据。
操作步骤:
bash
# 1. 在 Linux 服务器上执行恢复,输出 SQL 格式
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql -v
# 2. 将恢复结果打包传输到 Windows 工作站
tar czf recovery.tar.gz recovery/
scp recovery.tar.gz dba@windows-workstation:/D:/recovery/
# 3. 在 Windows 工作站上直接使用 fgddu.exe 也能恢复(如果数据文件已备份到 Windows)
fgddu.exe recover full -d D:\backup\DAMENG -o .\recovery --format sql
跨平台注意事项:
| 项目 | Linux | Windows |
|---|---|---|
| 可执行文件 | fgddu |
fgddu.exe |
| 路径分隔符 | / |
\(或 /) |
| 数据目录示例 | /opt/dmdbms/data/DAMENG |
D:\dmdbms\data\DAMENG |
| 输出目录示例 | ./recovery |
.\recovery |
| 依赖 | 零依赖(静态链接) | 零依赖(静态 CRT) |
注意:FGDDU 在 Windows 上同时支持 / 和 \ 路径分隔符,用户可以自由使用。
5.14 案例十四:裸设备(RAW Device)直接恢复
问题描述: 达梦数据库使用裸设备(如 /dev/raw/raw1、/dev/sdb1、/dev/dm-0)作为数据文件存储,数据库无法启动,需要直接从裸设备读取数据恢复,不想额外占用磁盘空间将裸设备 dd 成普通文件。
解决方案: FGDDU 直接以只读方式打开裸设备节点,通过 ioctl(BLKGETSIZE64) 自动获取设备大小并扫描,无需中转文件。
操作步骤:
bash
# 1. 确认裸设备路径与权限
ls -l /dev/raw/raw1 /dev/sdb1 /dev/dm-0
# FGDDU 运行用户需对设备节点有读权限(通常需 root 或 disk 组)
# 2. 方式一:直接用 -d 指向裸设备(FGDDU 自动识别为裸设备)
./fgddu recover full -d /dev/raw/raw1 -o ./recovery --format sql -v
# 3. 方式二:用 -f 指向裸设备 + --raw-device 显式声明
./fgddu export-file -f /dev/sdb1 -o ./recovery --raw-device --format sql
# 4. 方式三:块设备 /dev/dm-*(自动通过 ioctl 获取大小)
./fgddu recover full -d /dev/dm-0 -o ./recovery --format sql -v
# 5. 字符设备 /dev/raw/rawN 若 ioctl 失败,用 --device-size 指定大小
./fgddu export-file -f /dev/raw/raw1 -o ./recovery \
--raw-device --device-size 100G --format sql
# 6. 诊断裸设备损坏情况
./fgddu diagnose -f /dev/raw/raw1 --raw-device
# 7. 扫描裸设备查看页统计
./fgddu scan-file -f /dev/sdb1 --raw-device -v
裸设备大小解析机制:
| 优先级 | 方式 | 适用设备 |
|---|---|---|
| 1 | --device-size <n> 用户指定 |
所有设备(最可靠,推荐字符设备) |
| 2 | ioctl(BLKGETSIZE64) |
块设备(/dev/sdX、/dev/dm-、/dev/loop) |
| 3 | ioctl(BLKGETSIZE) ×512 |
旧内核块设备回退 |
| 4 | EOF 二分探测 | 字符设备(/dev/raw/rawN)估算 |
说明:
- FGDDU 始终以
O_RDONLY只读模式打开裸设备,绝不修改原始数据。 - 对生产裸设备操作前,建议先用
dd if=/dev/raw/raw1 of=/backup/raw1.img做物理备份。 - 设备大小不是页大小整数倍时,FGDDU 自动处理末尾不完整页(零填充)。
--device-size支持 K/M/G/T 单位(如100G、500M、1T)或裸字节数。
5.15 案例十五:达梦DM ASM 磁盘恢复(DmASM)
问题描述: 达梦数据库使用 DmASM 或 作为底层存储,ASM 实例无法启动或 ASM 元数据损坏,但底层 ASM 磁盘可用,需要从 ASM 磁盘直接抢救达梦数据。
解决方案: FGDDU 将 ASM 磁盘作为裸设备整体只读扫描,逐页解析达梦数据页结构,跳过 ASM 磁盘头(kfbh),从数据 AU 起始位置扫描。
操作步骤:
bash
# 1. 确认 ASM 磁盘路径(DmASM 通常使用 /dev/raw/rawN 或 ASMLIB 磁盘)
ls -l /dev/raw/raw* /dev/oracleasm/disks/*
# 2. 方式一:用 --asm 显式声明 ASM 磁盘模式
./fgddu recover full -d /dev/raw/raw1 -o ./recovery --asm --format sql -v
# 3. 方式二:用 -f + --asm 从单个 ASM 磁盘导出
./fgddu export-file -f /dev/raw/raw2 -o ./recovery --asm --format sql
# 4. 方式三:ASM 磁盘大小已知时用 --device-size 指定
./fgddu recover full -d /dev/raw/raw1 -o ./recovery \
--asm --device-size 200G --format sql
# 5. 方式四:ASMLIB 磁盘路径(Oracle ASM)
./fgddu export-file -f /dev/oracleasm/disks/DISK1 -o ./recovery \
--asm --format sql
# 6. 诊断 ASM 磁盘
./fgddu diagnose -f /dev/raw/raw1 --asm
# 7. 多个 ASM 磁盘逐一恢复(DmASM 通常多磁盘组成磁盘组)
for disk in /dev/raw/raw1 /dev/raw/raw2 /dev/raw/raw3; do
echo "Recovering from ASM disk: $disk"
./fgddu export-file -f $disk -o ./recovery_$(basename $disk) \
--asm --format sql -v
done
ASM 整盘扫描说明:
- DmASM在磁盘头部维护 AU(Allocation Unit)映射,完整解析需要 ASM 客户端库。
- FGDDU 采用"整盘扫描"策略:跳过 ASM 磁盘头,把剩余空间当作连续数据页流扫描。
- 该策略适用于 ASM 实例未启动 / ASM 元数据损坏的灾难场景。
- 若需精确按 ASM 文件切片恢复,建议先用
dd或kfed/amdu工具导出 ASM 文件为普通文件,再用 FGDDU 处理:
bash
# 用 dd 将 ASM 磁盘导出为普通文件(需足够磁盘空间)
dd if=/dev/raw/raw1 of=/backup/asm_disk1.img bs=1M status=progress
# 再用 FGDDU 处理导出的普通文件
./fgddu recover full -d /backup/asm_disk1.img -o ./recovery --format sql -v
ASM 与裸设备选项对比:
| 选项 | 适用场景 | 区别 |
|---|---|---|
--raw-device |
/dev/raw/rawN、/dev/sdX 等纯裸设备 | 从设备起始位置(offset 0)扫描 |
--asm |
DmASM磁盘 | 跳过 ASM 磁盘头(kfbh),从数据 AU 起始扫描 |
| 无选项 + 路径自动识别 | 路径含 /dev/raw/、/dev/sd 等前缀 | FGDDU 自动判定为裸设备 |
六、常用问题与排查
6.1 段错误(Segmentation Fault)
现象: 程序运行中突然输出 Segmentation Fault 或 SIGSEGV 并退出。
原因分析: 数据文件严重损坏,页头非法或页号越界,导致解析时访问非法内存。
解决方案:
bash
# 1. 使用 --continue-on-error 跳过坏块(默认已开启)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --continue-on-error
# 2. 单独扫描定位问题文件
./fgddu scan -d /opt/dmdbms/data/DAMENG -v
# 3. 单独扫描定位问题页
./fgddu scan-file -f /opt/dmdbms/data/DAMENG/USER01.DBF
# 4. 使用 diagnose 诊断数据文件
./fgddu diagnose -d /opt/dmdbms/data/DAMENG
# 5. 对单个问题文件单独恢复
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./recovery --format sql
FGDDU 已内置信号保护机制(SIGSEGV/SIGBUS),遇到严重错误会输出提示信息而非直接崩溃。如仍出现段错误,请将问题数据文件、日志反馈给作者。
6.2 页大小检测失败
现象: 输出 Failed to detect page size 或恢复结果数据为空。
原因分析: 数据文件头损坏,无法自动识别页大小;或数据目录路径错误。
解决方案:
bash
# 1. 手动指定页大小
./fgddu scan -d /opt/dmdbms/data/DAMENG --page-size 8192
# 2. 确认 dm.ini 中的页大小配置
grep -i "PAGE_SIZE\|EXTENT_SIZE" /opt/dmdbms/data/DAMENG/dm.ini
# 3. 查看数据文件实际大小(应为页大小的整数倍)
ls -l /opt/dmdbms/data/DAMENG/*.DBF
# 4. 尝试所有页大小逐一测试
for ps in 4096 8192 16384 32768; do
echo "Testing page size: $ps"
./fgddu scan -d /opt/dmdbms/data/DAMENG --page-size $ps 2>&1 | head -5
done
6.3 找不到数据文件
现象: 输出 No data files found 或 Data directory not found。
原因分析: 数据目录路径错误,或数据文件扩展名不是 .DBF。
解决方案:
bash
# 1. 确认数据文件位置
find / -name "*.DBF" 2>/dev/null
find / -name "*.dbf" 2>/dev/null
# 2. 检查 DM 默认数据目录
ls -la /opt/dmdbms/data/
ls -la /opt/dmdbms/data/DAMENG/
# 3. 如果数据文件在不同位置,指定完整路径
./fgddu export-all -d /path/to/your/data/dir -o ./recovery
# 4. 从单个数据文件恢复(绕过目录扫描)
./fgddu export-file -f /path/to/your/USER01.DBF -o ./recovery --format sql
6.4 输出目录权限问题
现象: 输出 Permission denied 或 Cannot create output directory。
原因分析: 输出目录无写权限,或目录不存在。
解决方案:
bash
# 1. 创建输出目录
mkdir -p ./recovery
# 2. 修改权限
chmod 755 ./recovery
# 或所有者运行
chown $(whoami) ./recovery
# 3. 重新执行
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 4. 如果磁盘空间不足,更换输出位置
df -h
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o /backup/recovery --format sql
6.5 全库导出无数据输出
现象: 程序执行完成但输出目录为空,或只有少量 REMNANT 文件。
原因分析:
- 数据目录路径错误(指向了非数据目录)。
- 数据文件为空或全部损坏。
- 字典完全损坏,且未启用 RAW 模式。
- 页大小检测错误。
解决方案:
bash
# 1. 确认数据目录正确
ls -la /opt/dmdbms/data/DAMENG/*.DBF
# 应该看到 SYSTEM.DBF, USER01.DBF, ROLL.DBF 等
# 2. 先用 scan 检查数据文件
./fgddu scan -d /opt/dmdbms/data/DAMENG -v
# 3. 使用原始扫描模式(忽略字典)
./fgddu recover raw -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
# 4. 指定页大小重试
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --page-size 8192 --format sql
# 5. 从单个数据文件直接导出
./fgddu export-file -f /opt/dmdbms/data/DAMENG/USER01.DBF -o ./recovery --format sql
# 6. 开启详细模式查看执行过程
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql -v
6.6 LOB 数据未导出或损坏
现象: BLOB/CLOB 列值为 NULL 或显示为乱码。
原因分析:
- 使用了
--no-lob跳过 LOB 提取。 - LOB 页损坏或丢失。
- 行外 LOB 引用页无法定位。
解决方案:
bash
# 1. 确认未使用 --no-lob(默认即导出 LOB)
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_BLOB_DATA -o ./output --format sql
# 2. 检查输出日志中是否有 LOB 提取失败信息
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_BLOB_DATA -o ./output --format sql -v
# 3. 如果 LOB 页严重损坏,可接受不导出 LOB
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_BLOB_DATA -o ./output --format sql --no-lob
# 4. 使用 RAW 模式扫描 LOB 残余数据
./fgddu recover raw -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql
6.7 恢复速度慢
现象: 全库恢复耗时过长。
原因分析: 数据库规模大,或启用了不必要的恢复选项。
解决方案:
bash
# 1. 跳过 LOB 导出加快速度(如果不需要 LOB 数据)
./fgddu export-all -d /opt/dmdbms/data/DAMENG -o ./recovery --no-lob --format sql
# 2. 按用户/Schema 过滤,只恢复必要数据
./fgddu recover full -d /opt/dmdbms/data/DAMENG -u BUSINESS_USER -o ./recovery --format sql
# 3. 按表过滤,只恢复关键表
./fgddu export -d /opt/dmdbms/data/DAMENG -t T_CRITICAL_TABLE -o ./recovery --format sql
# 4. 限制恢复行数(抽样验证)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --max-rows 10000 --format sql
# 5. 使用 DMP 格式(比 SQL 格式更快)
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format dmp
# 6. 开启进度条监控
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --progress --format sql
6.8 恢复的 SQL 文件无法导入新库
现象: disql 执行恢复的 SQL 文件时报错。
原因分析:
- 目标库中不存在对应的表结构。
- 字符集不匹配。
- SQL 语句语法与目标 DM 版本不兼容。
解决方案:
bash
# 1. 在目标库先创建表结构
disql SYSDBA/password@localhost:5236 -e "
CREATE TABLE \"SYSDBA\".\"T_TEST\" (
\"ID\" INT,
\"NAME\" VARCHAR(100),
\"CREATE_TIME\" DATETIME
);"
# 2. 检查字符集是否一致(源库与目标库)
grep -i "CHARSET\|LANG" /opt/dmdbms/data/DAMENG/dm.ini
# 3. 逐个文件导入并查看错误
for f in recovery/*.sql; do
echo "Importing $f..."
disql SYSDBA/password@localhost:5236 \`cat $f\` 2>&1 | tail -5
done
# 4. 检查 SQL 文件头部是否有 SET 语句
head -5 recovery/T_TEST.SYSDBA.sql
6.9 Ctrl+C 中断后数据丢失
现象: Ctrl+C 中断后输出文件为空或不完整。
原因分析: 连续按了两次 Ctrl+C 触发强制中止,导致缓冲区数据未刷新。
解决方案:
- 只按一次 Ctrl+C,等待程序输出
Interrupt requested并自然退出。 - 重新执行恢复(FGDDU 会从头开始扫描,覆盖原输出文件)。
- 使用
--log选项记录完整日志,便于事后审计。
bash
# 正确的中断方式
# 按 Ctrl+C 一次
# 等待程序输出 "Interrupt requested" 并退出
# 重新执行恢复
./fgddu recover full -d /opt/dmdbms/data/DAMENG -o ./recovery --format sql -v --log ./fgddu.log
6.10 Windows 平台运行问题
现象: 在 Windows 上运行 fgddu.exe 时报错。
原因分析: 使用了 MinGW 编译版本(可能依赖 mingw 运行库),或路径包含中文/空格。
解决方案:
cmd
:: 1. 使用 MSVC 编译的版本(零依赖)
:: 优先使用 build_win\Release\fgddu.exe(MSVC 编译)
:: 2. 避免路径包含中文或空格
:: 错误: D:\我的目录\DM数据\DAMENG
:: 正确: D:\dm\data\DAMENG
:: 3. 使用引号包裹包含空格的路径
fgddu.exe recover full -d "D:\Program Files\dm\data\DAMENG" -o ".\recovery" --format sql
:: 4. 同时支持 / 和 \ 路径分隔符
fgddu.exe recover full -d D:/dm/data/DAMENG -o ./recovery --format sql
:: 5. 以管理员身份运行(如果数据文件受保护)
:: 右键 -> 以管理员身份运行 cmd.exe
6.11 裸设备/ASM 恢复问题排查
现象一:Cannot open '/dev/raw/raw1': Permission denied
原因分析: FGDDU 运行用户对裸设备节点无读权限。
解决方案:
bash
# 1. 检查设备节点权限
ls -l /dev/raw/raw1
# 通常显示: crw------- root root ...
# 2. 方式一:用 root 运行 FGDDU
sudo ./fgddu recover full -d /dev/raw/raw1 -o ./recovery --format sql
# 3. 方式二:将用户加入 disk 组
usermod -aG disk $(whoami)
# 重新登录后生效
# 4. 方式三:临时修改设备节点权限(生产慎用)
sudo chmod 644 /dev/raw/raw1
现象二:Cannot determine size of raw device 或恢复结果数据量异常少
原因分析: 字符设备(/dev/raw/rawN)无法通过 ioctl(BLKGETSIZE64) 获取大小,FGDDU 退回 EOF 二分探测估算的大小不准确。
解决方案:
bash
# 1. 用 --device-size 显式指定设备大小(最可靠)
./fgddu export-file -f /dev/raw/raw1 -o ./recovery \
--raw-device --device-size 100G --format sql
# 2. 查看裸设备实际大小
blockdev --getsize64 /dev/raw/raw1
# 或
cat /proc/partitions | grep sdX
# 3. 块设备(/dev/sdX、/dev/dm-*)通常无需 --device-size,
# FGDDU 会自动通过 ioctl 获取
./fgddu recover full -d /dev/sdb1 -o ./recovery --format sql -v
现象三:ASM 磁盘扫描结果全是 REMNANT 残余数据,无正常表数据
原因分析: ASM 磁盘头(kfbh)偏移与 FGDDU 默认 data_offset 不匹配,导致页对齐错位。
解决方案:
bash
# 1. 先用 dd 导出 ASM 磁盘为普通文件,再用 FGDDU 处理(最可靠)
dd if=/dev/raw/raw1 of=/backup/asm_disk1.img bs=1M status=progress
./fgddu recover full -d /backup/asm_disk1.img -o ./recovery --format sql -v
# 2. 用 kfed/amdu 工具解析 ASM 元数据,定位数据文件 AU 位置
# (需 Oracle 环境)
# 3. 多个 ASM 磁盘逐一恢复,合并结果
for disk in /dev/raw/raw1 /dev/raw/raw2; do
./fgddu export-file -f $disk -o ./recovery_$(basename $disk) \
--asm --format sql -v
done
现象四:'xxx' is not a directory or raw device
原因分析: -d 指定的路径既不是目录,也不被识别为裸设备/ASM 路径。
解决方案:
bash
# 1. 确认路径是否存在
ls -l /your/path
# 2. 若是裸设备但路径前缀不在自动识别列表,用 --raw-device 显式声明
./fgddu recover full -d /your/device/path -o ./recovery --raw-device
# 3. 若是 ASM 磁盘,用 --asm 显式声明
./fgddu recover full -d /your/asm/disk -o ./recovery --asm
# 4. 确认设备类型
file /dev/raw/raw1 # 应显示 character special
file /dev/sdb1 # 应显示 block special
6.12 常见错误码速查
| 错误码 / 错误信息 | 含义 | 解决方案 |
|---|---|---|
Segmentation Fault / SIGSEGV |
段错误,访问非法内存 | 使用 --continue-on-error,定位问题文件 |
SIGBUS |
总线错误,内存对齐问题 | 使用 --continue-on-error,定位问题文件 |
Failed to detect page size |
页大小检测失败 | 手动指定 --page-size |
No data files found |
未找到数据文件 | 确认数据目录路径,使用 find 定位 |
Permission denied |
权限不足 | chmod 修改权限或更换输出目录 |
Cannot load dictionary |
字典加载失败 | 使用 --raw 原始扫描模式 |
CORRUPT page |
页损坏 | 默认跳过,使用 --continue-on-error |
Out of memory |
内存不足 | 关闭其他程序,使用 --max-rows 限制 |
Interrupt requested |
收到中断请求 | 正常行为,已恢复数据已保存 |
6.12 恢复策略选择速查
| 场景 | 推荐命令 |
|---|---|
| 数据库无法启动,全库导出 | export-all 或 recover full |
| 指定数据目录做最大恢复 | recover full -d <目录> |
| 误删除数据 (DELETE) | recover delete |
| 误删除表 (DROP) | recover drop |
| 误截断表 (TRUNCATE) | recover truncate |
| 字典损坏 | recover raw |
| 指定表导出 | export -t <表名> |
| 指定用户/Schema恢复 | recover full -u <用户> / -s <Schema> |
| 单文件恢复 | export-file -f <文件> |
| 按用户分目录 | export-all --by-user |
6.13 最佳实践
恢复前准备
- 停止数据库:确保数据库已停止,避免数据文件被修改。
- 备份数据文件:复制一份原始数据文件到安全位置。
- 确认磁盘空间:确保输出目录有足够空间(建议源数据大小的 1.5-3 倍)。
bash
# 备份数据文件
cp -r /opt/dmdbms/data/DAMENG /backup/DAMENG_backup
# 检查磁盘空间
df -h /backup
输出格式选择
| 格式 | 优点 | 缺点 |
|---|---|---|
| DMP (默认) | 二进制紧凑,适合大数据量 | 需要配套工具导入 |
| SQL | 通用性强,可直接执行 | 文件较大,导入较慢 |
| CSV | 便于与表格工具对接 | 不支持复杂类型 |
| TXT | 便于人工查看 | 不适合数据导入 |
恢复流程建议
- 诊断阶段 :先用
scan和diagnose评估数据损坏情况。 - 抽样阶段 :先用
--max-rows 1000抽样恢复验证流程。 - 全量恢复 :确认流程无误后执行全量
recover full。 - 导入验证:在新库中导入并校验数据完整性。
- 业务验证:通知业务方验证数据准确性。
附录:联系方式
FGDDU 全称 :FGEDU 达梦 DM DUL(Data UnLoader)
作者 :风哥
附录:项目结构
FGDDU/
├── include/ # 头文件
│ ├── fgddu.h # 主头文件(类型、常量、结构体)
│ ├── fgddu_platform.h # 跨平台兼容层(Linux/Windows)
│ └── cli/
│ └── dm_cli.h # CLI 定义
├── src/ # 源代码
│ ├── main.c # 入口(信号处理)
│ ├── cli/dm_cli.c # 命令行解析与执行
│ ├── io/dm_io.c # 文件 I/O、页大小检测
│ ├── page/dm_page.c # 页解析、行目录提取
│ ├── dbdict/dm_dbdict.c # 系统字典解析
│ ├── row/dm_row.c # 数据类型解码
│ ├── scan/dm_scan.c # 扫描引擎(恢复核心)
│ ├── output/dmp_writer.c # DMP/SQL 输出
│ ├── utils/dm_utils.c # 工具函数
│ └── platform/ # 平台兼容层
│ └── fgddu_wincompat.c # Windows POSIX 兼容实现
├── docs/ # 文档
│ ├── README.md
│ ├── README-WEB.md # 本文档(Web 版详细手册)
│ ├── usage_manual.md
│ └── test_manual.md
├── Makefile # Linux 编译配置
├── CMakeLists.txt # CMake 编译配置(Windows/Linux 通用)
├── build_windows.bat # Windows 编译脚本
└── test/ # 测试数据