1. 首页 > 软件下载 > 正文

达梦DM数据库恢复工具FGDDU(FGEDU DM DUL)


FGDDU 是一款由风哥自主研发的达梦数据库(DM Database)**数据卸载与恢复工具**,旨在达梦数据库无法启动且没有备份的情况焉,不依赖达梦数据库实例运行,绕过数据库引擎层,从底层进行数据库的数据抽取与灾难恢复场景。

## 目录

1. [程序介绍](#一程序介绍)
2. [功能特性](#二功能特性)
3. [支持环境](#三支持环境)
4. [程序使用](#四程序使用)
5. [案例场景与操作过程](#五案例场景与操作过程)
6. [常用问题与排查](#六常用问题与排查)

## 一、程序介绍

### 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)
> **作者**:风哥
> **联系方式**:Q113257174 / 微itpux-com
> **官方网站** :   http://www.fgedu.net.cn ,   http://www.itpux.com
> **数据库教程** :   https://edu.51cto.com/lecturer/8020378.html

## 二、功能特性

### 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 / Oracle ASM 磁盘作为数据源 |
| 数据目录诊断(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 磁盘、Oracle ASM 磁盘 | `+` 前缀 / `ORCL:` 前缀自动识别 + `–asm` 显式声明 |

#### 2.3.2 裸设备大小解析机制

裸设备的特殊性在于 `stat()` 返回的 `st_size` 为 0,无法像普通文件那样直接获取大小。FGDDU 采用多级回退策略解析裸设备大小:

1. **用户指定优先**:通过 `–device-size <n>` 显式指定设备大小(支持 K/M/G/T 单位,如 `100G`、`500M`)。这是最可靠的方式,推荐用于 `/dev/raw/rawN` 字符设备。
2. **ioctl(BLKGETSIZE64)**:对块设备(`/dev/sdX`、`/dev/dm-*`、`/dev/loop*`)通过 `BLKGETSIZE64` ioctl 获取精确字节数。
3. **ioctl(BLKGETSIZE)**:旧版内核回退方案,返回扇区数(×512 字节)。
4. **EOF 二分探测**:对无法通过 ioctl 获取大小的字符设备,通过二分查找 `pread` 的 EOF 位置估算可用大小。

#### 2.3.3 ASM 磁盘处理说明

达梦 DmASM 与 Oracle ASM 在磁盘头部有独立的 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 技术特点汇总

1. **跨平台支持**:同时支持 Linux(RHEL/Ubuntu/SUSE/国产 OS)和 Windows(7/8/10/11/Server)。
2. **完全静态链接**:Linux 编译为单个静态可执行文件,零依赖;Windows 使用静态 CRT(/MT)。
3. **平台兼容层**:通过 `fgddu_platform.h` 抽象层,一套源码两个平台编译运行。
4. **信号保护**:SIGSEGV/SIGBUS 崩溃保护 + SIGINT/SIGTERM 优雅停止。
5. **坏块跳过**:遇到坏块自动跳过,最大化数据恢复。
6. **自动检测**:自动识别页大小(4K/8K/16K/32K),自动读取 dm.ini。
7. **最大恢复引擎**:正常扫描 + 空闲空间扫描 + 原始扫描 + 孤儿页三级匹配。
8. **全库导出**:指定目录即可导出全部数据,自动发现所有数据文件。
9. **进度心跳日志**:每处理 1000 页或恢复 1000 行自动报告进度。
10. **输入验证**:所有参数进行 NULL/范围/合法性检查。
11. **整数溢出保护**:页号计算等关键运算进行溢出检测。
12. **堆内存管理**:大数组使用堆分配,避免栈溢出导致的段错误。
13. **跨平台路径**:同时支持 `/` 和 `\` 路径分隔符。
14. **编译器安全加固**:Linux 与 Windows 均启用栈保护、ASLR、DEP 等安全机制。
15. **裸设备/ASM 支持**:直接读取 /dev/raw/rawN、/dev/sdX、/dev/dm-* 等裸设备及 DmASM/Oracle ASM 磁盘,通过 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+,生成单文件可执行程序。

### 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 案例十五:ASM 磁盘恢复(DmASM / Oracle ASM)

**问题描述:** 达梦数据库使用 DmASM 或 Oracle ASM 作为底层存储,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 / Oracle ASM 在磁盘头部维护 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 / Oracle ASM 磁盘 | 跳过 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. **停止数据库**:确保数据库已停止,避免数据文件被修改。
2. **备份数据文件**:复制一份原始数据文件到安全位置。
3. **确认磁盘空间**:确保输出目录有足够空间(建议源数据大小的 1.5-3 倍)。

“`bash
# 备份数据文件
cp -r /opt/dmdbms/data/DAMENG /backup/DAMENG_backup

# 检查磁盘空间
df -h /backup
“`

#### 输出格式选择

| 格式 | 优点 | 缺点 |
|——|——|——|
| DMP (默认) | 二进制紧凑,适合大数据量 | 需要配套工具导入 |
| SQL | 通用性强,可直接执行 | 文件较大,导入较慢 |
| CSV | 便于与表格工具对接 | 不支持复杂类型 |
| TXT | 便于人工查看 | 不适合数据导入 |

#### 恢复流程建议

1. **诊断阶段**:先用 `scan` 和 `diagnose` 评估数据损坏情况。
2. **抽样阶段**:先用 `–max-rows 1000` 抽样恢复验证流程。
3. **全量恢复**:确认流程无误后执行全量 `recover full`。
4. **导入验证**:在新库中导入并校验数据完整性。
5. **业务验证**:通知业务方验证数据准确性。

## 附录:项目结构

“`
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/                  # 测试数据
“`

## 附录:联系方式
> **FGDDU 全称**:FGEDU 达梦 DM DUL(Data UnLoader)
> **作者**:风哥
> **联系方式**:Q113257174 / 微itpux-com
> **官方网站** :   http://www.fgedu.net.cn ,   http://www.itpux.com
> **数据库教程** :   https://edu.51cto.com/lecturer/8020378.html

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息