达梦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)

作者 :风哥

官方网站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磁盘作为数据源
数据目录诊断(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 采用多级回退策略解析裸设备大小:

  1. 用户指定优先 :通过 --device-size <n> 显式指定设备大小(支持 K/M/G/T 单位,如 100G500M)。这是最可靠的方式,推荐用于 /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 与 在磁盘头部有独立的 AU(Allocation Unit)映射元数据,完整的 ASM 文件系统解析需要 ASM 客户端库。FGDDU 的 ASM 支持采用"整盘扫描"策略:

  • 将 ASM 磁盘作为裸设备整体只读扫描,逐页解析达梦数据页结构。
  • 通过 data_offset 跳过 ASM 磁盘头(kfbh),从数据 AU 起始位置扫描。
  • 适用于 ASM 磁盘可用但 ASM 实例未启动 / 损坏的灾难场景。
  • 对于需要在 ASM 文件级别精确切片的场景,建议先用 ddasmlib 工具将 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 deleterecover 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/磁盘,通过 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/用户创建子目录。
  • 无法匹配到已知用户的孤儿数据放在 UNKNOWNRECOVERED_DATA 目录。
  • -u/-s/-t 过滤选项可组合使用。
  • 适用于 export-allrecover fullrecover deleterecover 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 单位(如 100G500M1T)或裸字节数。

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 文件切片恢复,建议先用 ddkfed/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 FaultSIGSEGV 并退出。

原因分析: 数据文件严重损坏,页头非法或页号越界,导致解析时访问非法内存。

解决方案:

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 foundData 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 deniedCannot 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-allrecover 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. 诊断阶段 :先用 scandiagnose 评估数据损坏情况。
  2. 抽样阶段 :先用 --max-rows 1000 抽样恢复验证流程。
  3. 全量恢复 :确认流程无误后执行全量 recover full
  4. 导入验证:在新库中导入并校验数据完整性。
  5. 业务验证:通知业务方验证数据准确性。

附录:联系方式

FGDDU 全称 :FGEDU 达梦 DM DUL(Data UnLoader)

作者 :风哥

官方网站http://www.fgedu.net.cn , http://www.itpux.com

数据库教程https://edu.51cto.com/lecturer/8020378.html

附录:项目结构

复制代码
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/                  # 测试数据

相关推荐
2601_960017621 小时前
啤酒行业PLM突围战:一半科技以配方与工艺数字化重构酿造食品研发体系
数据库·科技·重构
GIS数据转换器1 小时前
智慧林草“一张图“平台
java·大数据·服务器·前端·javascript·数据库·人工智能
gis开发之家1 小时前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端
李兆龙的博客2 小时前
问津集 #12:Calcspar:相同 Paid IOPS 下的 RocksDB 尾延迟优化
数据库
智购科技自动售卖机厂家2 小时前
2026自动售货机云端数据备份策略:从全量备份到增量恢复的工程实践~YH
数据库·stm32·嵌入式硬件·物联网·架构·零售
笔头子3 小时前
【Caché】数据库基础操作
数据库
上火的金鱼妹3 小时前
redis集群部署与连接
数据库·redis·缓存
程序员-Benothing3 小时前
MySQL 二级索引有 MVCC 快照吗?
数据库·mysql
xiaoxiangsiyan3 小时前
网络智能化转型核心模块全解析
运维·服务器·网络·数据库·学习·架构·php