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

华为高斯数据库恢复工具FGOGDU(FGEDU openGauss DUL)

FGOGDU(全称 **FGEDU openGauss DUL**)是一款专门面向 openGauss 数据库的离线数据抽取与恢复工具,将“绕过数据库实例、直接从底层数据文件中读取并还原数据”这一经典思路移植到 openGauss 生态,填补了 openGauss 在“数据库无法启动”这一极端故障场景下数据抢救工具的空白。

 

 

## 目录

 

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

 

 

## 一、程序介绍

 

### 1.1 工具概述

 

FGOGDU(全称 **FGEDU openGauss DUL**)是一款专门面向 openGauss 数据库的离线数据抽取与恢复工具,,将“绕过数据库实例、直接从底层数据文件中读取并还原数据”这一经典思路移植到 openGauss 生态,填补了 openGauss 在“数据库无法启动”这一极端故障场景下数据抢救工具的空白。

 

在传统的运维与故障恢复流程中,当 openGauss 数据库实例因为控制文件损坏、参数文件丢失、系统表空间坏块、redo 日志断裂、升级失败或人为误操作等原因而无法正常启动时,运维人员通常只能依赖物理备份(全量备份 + 归档日志)或逻辑备份(gs_dump 导出文件)进行恢复。然而现实情况往往是:备份策略不完备、备份介质同样损坏、备份时间点与故障点之间存在较大数据落差,甚至根本没有可用备份。此时数据库实例无法启动,意味着所有 SQL 接口(gsql、JDBC、ODBC)全部失效,业务数据被“锁”在磁盘上的数据文件中而无法访问。

 

FGOGDU 正是为解决这一痛点而生。它不依赖 openGauss 实例运行,也不依赖任何数据库客户端库,而是直接以文件方式读取 `base/`、`global/` 目录下的数据文件,按照 openGauss/PostgreSQL 的 Astore heap 存储格式逐页、逐元组地解析,将磁盘上残存的数据还原为可读的 SQL 文本或自描述的 DMP 二进制文件,供运维人员导入到新的、健康的数据库实例中,从而完成数据的最终恢复。

 

工具编译后生成单个约 2MB 的完全静态链接可执行文件 `fgogdu`,不依赖任何动态共享库(.so),可直接通过 scp/U 盘等方式拷贝到任意 Linux 服务器上运行,真正做到“即拷即用、零安装、零依赖”。这一特性在故障应急场景下尤为重要:恢复现场的服务器往往环境残缺、无法联网安装依赖,而 FGOGDU 单文件部署的方式极大降低了恢复门槛。

 

### 1.2 设计理念

 

FGOGDU 在设计上遵循以下核心理念:

 

– **数据安全优先**:工具只读不写,绝不在源数据文件上做任何修改,所有恢复结果均输出到独立的输出目录,确保故障现场不被二次破坏,便于多次尝试不同的恢复策略。
– **尽最大可能恢复**:在坏块、系统目录损坏、TOAST 文件缺失等各种异常场景下,工具不会因单点故障而中断,而是自动降级到兜底策略——跳过坏块、扫描孤立文件、做无表结构的原始元组抽取,尽最大可能抢救磁盘上残存的数据。
– **简单清晰的命令**:命令体系采用“动词 + 宾语”的自然语义结构(如 `recover`、`recover-deleted`、`recover-directory`、`orphan-scan`),主命令使用完整英文单词而非晦涩缩写,降低运维人员的记忆与使用成本。
– **双格式导出**:同时支持 SQL 文本格式与 DMP 二进制格式输出。SQL 格式便于人工阅读、审计与跨版本导入;DMP 格式保留原始二进制数据,适合程序化高速导入。
– **完全静态、零依赖**:编译期完成全部静态链接,运行期无任何外部库依赖,保证在任意老旧或国产化 Linux 发行版上均可稳定运行。

 

### 1.3 作者信息

 

作者:风哥
官方网站: http://www.fgedu.net.cn ,  http://www.itpux.com
数据库教程:  https://edu.51cto.com/lecturer/8020378.html

 

### 1.4 适用人群

 

FGOGDU 主要面向以下人员:

 

– **数据库运维 DBA**:负责 openGauss 日常运维与故障应急处置,是本工具的核心使用者。
– **数据恢复工程师**:在客户现场执行紧急数据抢救任务,需要一款便携、可靠、零依赖的恢复工具。
– **系统管理员**:在数据库实例无法启动时,需要从数据目录中提取关键业务数据。
– **数据库研发与测试人员**:用于验证数据存储格式、构建恢复测试用例、研究 openGauss 底层存储机制。

 

### 1.5 名词解释

 

| 名词 | 说明 |
|——|——|
| DUL | Data UnLoad,数据卸载工具,源自 Oracle 领域的离线数据抽取工具 |
| Astore | openGauss 的默认行存储引擎,其堆表页格式与 PostgreSQL 兼容 |
| Ustore | openGauss 的 inplace update(原地更新)存储引擎,本工具暂不支持 |
| TOAST | The Oversized-Attribute Storage Technique,超长字段外存机制 |
| LOB | Large Object,大字段,泛指 text/varchar/bytea 等超长变长字段 |
| 数据目录(datadir) | openGauss 的数据目录,包含 base/、global/、pg_control 等 |
| 系统目录 | pg_database、pg_class、pg_attribute 等存储元数据的系统表 |
| 孤立文件 | base/ 目录下未被 pg_class 引用的数据文件,通常是被 DROP/TRUNCATE 的表 |

 

 

## 二、程序功能与特性

 

### 2.1 核心功能概览

 

FGOGDU 围绕“离线数据抽取与恢复”这一核心目标,提供了一套完整的命令体系,覆盖从只读查看到精细恢复再到一键全量恢复的完整链路:

 

| 功能类别 | 代表命令 | 说明 |
|———-|———-|——|
| 信息查看 | `version` / `help` | 查看工具版本与帮助 |
| 目录探查 | `databases` / `schemas` / `tables` | 列出数据目录中的数据库、模式、表 |
| 诊断分析 | `blocksize` / `page` | 检测块大小、查看数据页结构 |
| 单表恢复 | `recover` / `recover-deleted` | 恢复单个表的活跃数据或含已删除数据 |
| 批量恢复 | `recover-all` / `unload` | 按数据库或按用户名导出所有表 |
| 最大恢复 | `recover-directory` | 一键恢复数据目录下的全部数据 |
| 文件级恢复 | `recover-file` | 用手动模式文件恢复单个原始数据文件 |
| 孤立扫描 | `orphan-scan` | 查找被 DROP/TRUNCATE 的孤立数据文件 |

 

### 2.2 功能特性详解

 

#### 2.2.1 完全静态链接,单文件部署

 

FGOGDU 在编译阶段通过 `-static -static-libgcc -static-libstdc++` 选项完成全部静态链接,生成的 `fgogdu` 可执行文件约 2MB,不依赖任何动态共享库(.so)。通过 `ldd ./fgogdu` 验证应输出“not a dynamic executable”。这意味着:

 

– 无需安装 openGauss 客户端库(libpq 等)
– 无需安装任何第三方运行时库
– 可直接拷贝到任意 Linux 服务器运行,适合故障现场的“裸环境”部署
– 不受目标服务器 glibc 版本差异影响(在编译机 glibc 版本范围内)

 

#### 2.2.2 跨平台与国产化支持

 

工具在 RHEL/OEL/麒麟/欧拉等主流 Linux 发行版上完成编译与验证,覆盖国产化操作系统场景:

 

– 支持 RHEL 6/7/8/9/10 全系列
– 支持 Oracle Linux(OEL)各版本
– 支持麒麟操作系统(Kylin)
– 支持欧拉操作系统(openEuler)
– 支持 CentOS 7/8 及其衍生版

 

由于采用静态链接,同一份二进制可在上述所有平台间直接拷贝使用,无需针对不同发行版重新编译。

 

#### 2.2.3 自动识别数据块大小

 

openGauss 的数据块大小(blocksize)在初始化时确定,常见取值为 8192(8KB),但也可能配置为 16384(16KB)、32768(32KB)、65536(64KB)。FGOGDU 在读取每个数据文件时会自动检测块大小,无需用户手动指定,检测策略为:

 

1. 读取页头 `pd_pagesize_version` 字段,从高 15 位提取块大小
2. 若失败,依次尝试常见块大小:8192、16384、32768、65536、4096、2048、1024
3. 对每个候选块大小,验证页头字段(pd_lower、pd_upper、pd_special)的合理性
4. 选定首个通过验证的块大小

 

对于特殊场景,用户也可通过 `-b/–blocksize` 参数强制指定块大小。

 

#### 2.2.4 LOB/TOAST 大字段恢复

 

当 text、varchar、bytea 等变长字段数据超过约 2KB 时,openGauss 会自动将其迁移到 TOAST 表中分块存储。FGOGDU 默认启用 LOB 恢复,无需额外参数,自动完成以下工作:

 

1. 从 `pg_class` 读取表的 `reltoastrelid`,定位关联的 TOAST 表
2. 读取 TOAST 表的数据文件,按 `chunk_id` 和 `chunk_seq` 顺序重组分块数据
3. 检测数据是否被 pglz 压缩,若压缩则调用内置 pglz 解压器还原原始数据
4. 兼容新旧两种 varatt_external 指针格式(12 字节旧格式 / 16 字节 PG14+ 新格式)
5. 将还原的 LOB 数据导出到 SQL/DMP 文件

 

单个 LOB 数据最大支持 256MB,防止内存溢出。当 TOAST 表文件缺失或损坏时,对应字段标记为 `<TOASTED>` 而非中断恢复。

 

#### 2.2.5 多种恢复模式

 

FGOGDU 提供四种层次的恢复模式,适应不同的故障严重度与数据抢救需求:

 

– **活跃数据恢复(recover)**:仅恢复表中当前有效的数据行,是最常规的恢复模式。
– **已删除数据恢复(recover-deleted)**:同时恢复活跃数据与已被 DELETE 删除但尚未被新数据覆盖的数据行,用于误删数据的抢救。已删除行在输出文件中标记 `[was-deleted]`。
– **DROP/TRUNCATE 恢复(orphan-scan + recover-file)**:表被 DROP 或 TRUNCATE 后,系统目录中已无该表信息,但底层数据文件可能仍残留在磁盘上。通过孤立文件扫描定位这些文件,再用手动模式文件恢复。
– **全库最大恢复(recover-directory)**:一键恢复数据目录下的全部数据,包含所有数据库的所有表、已删除数据、global/ 共享系统表、孤立文件,并在系统目录损坏时自动兜底。这是应急场景下的首选命令。

 

#### 2.2.6 系统目录自动解析

 

FGOGDU 通过读取 openGauss 系统目录自动还原表结构,无需用户手动提供模式定义:

 

– 从 `global/1262`(pg_database)读取数据库列表与 OID
– 从各数据库的 `pg_class`(OID 1259)读取表信息(表名、OID、filenode、TOAST 关联)
– 从 `pg_attribute`(OID 1249)读取列定义(列名、类型 OID、是否可空、顺序)
– 从 `pg_namespace` 读取模式(schema)名

 

基于系统目录解析,工具能够自动生成 `CREATE TABLE` 语句并按列顺序正确解码元组数据。

 

#### 2.2.7 共享目录支持

 

openGauss 的 `global/` 目录下存放跨数据库共享的系统表(如 pg_database、pg_shadow、pg_tablespace 等)。FGOGDU 在 `recover-directory` 最大恢复模式下会自动恢复 global/ 目录下的共享系统表,确保恢复结果完整。

 

#### 2.2.8 系统目录损坏兜底恢复

 

当系统目录因坏块而无法读取时,FGOGDU 会自动降级到兜底策略,尽最大可能抢救数据:

 

– **pg_database 不可读**:自动扫描 `base/` 目录下的数字子目录,将每个数字子目录名作为数据库 OID 继续恢复。
– **pg_class 不可读**:对该数据库下所有数据文件做无表结构的原始元组抽取,以十六进制原始数据形式导出到 `_orphan/` 目录,保留磁盘上残存的所有信息。
– **坏块自动跳过**:遇到损坏的数据页时自动跳过,继续恢复后续正常页,避免单点故障导致整表恢复失败。

 

#### 2.2.9 丰富的数据类型支持

 

FGOGDU 支持 openGauss 常用的全部基础数据类型,包括:

 

| 类型 | OID | 说明 |
|——|—–|——|
| boolean | 16 | 布尔值 |
| bytea | 17 | 二进制数据 |
| char | 18 | 单字节字符 |
| name | 19 | 64 字节固定长度名称 |
| int8 / bigint | 20 | 8 字节整数 |
| int2 / smallint | 21 | 2 字节整数 |
| int4 / integer | 23 | 4 字节整数 |
| text | 25 | 变长文本 |
| oid | 26 | 对象标识符 |
| float4 / real | 700 | 单精度浮点 |
| float8 / double | 701 | 双精度浮点 |
| bpchar | 1042 | 定长字符 |
| varchar | 1043 | 变长字符 |
| nvarchar2 | 4191 | openGauss nvarchar2 |
| date | 1082 | 日期 |
| time | 1083 | 时间 |
| timestamp | 1114 | 时间戳 |
| timestamptz | 1184 | 带时区时间戳 |
| numeric | 1700 | 精确数值 |
| uuid | 2950 | UUID |
| json | 114 | JSON |
| jsonb | 3802 | 二进制 JSON |
| xml | 142 | XML |

 

特别地,numeric 类型采用按十进制位渲染的算法,正确处理 openGauss/PostgreSQL 12+ 的 NumericShort 与 NumericLong 两种磁盘格式,以及 NaN / ±Infinity 特殊值,兼容老版本(pre-PG12)的 8 字节头格式作为回退。

 

#### 2.2.10 双格式导出(SQL + DMP)

 

– **SQL 格式(.sql)**:每个表生成一个 SQL 文本文件,包含 `CREATE TABLE` 语句(自动还原表结构)和 `INSERT INTO` 语句(每行一条),便于人工阅读、审计与跨版本导入。
– **DMP 格式(.dmp)**:自描述的二进制格式,文件头标识 `FGOGDUMP`,包含版本号、标志位、表名、列定义、每行数据的原始二进制值以及恢复元数据(块号、偏移、删除状态),适合程序化高速导入。
– 默认同时导出两种格式(`-f both`),也可通过 `-f sql` 或 `-f dmp` 仅导出一种格式以减少 I/O。

 

#### 2.2.11 实时进度显示

 

恢复过程中工具会实时输出进度信息,包括:

 

– 当前正在扫描/导出的数据库名与 OID
– 当前正在导出的表名、模式名
– 每个表导出的行数
– 文件扫描进度与跳过的坏块提示
– 兜底恢复触发时的告警信息

 

便于运维人员实时掌握恢复进展与故障范围。

 

### 2.3 支持环境

 

#### 2.3.1 编译环境要求

 

| 项目 | 要求 |
|——|——|
| 操作系统 | Linux(x86_64) |
| 编译器 | GCC 4.8+(需支持 C++17 标准) |
| 静态链接库 | glibc-static、libstdc++-static |
| 构建工具 | GNU Make |
| 可选依赖 | 无(不依赖 libpq 或任何 openGauss 客户端库) |

 

#### 2.3.2 运行环境要求

 

| 项目 | 要求 |
|——|——|
| 操作系统 | RHEL 6/7/8/9/10、OEL、CentOS 7/8、麒麟(Kylin)、欧拉(openEuler)等 Linux x86_64 |
| 运行时依赖 | 无(完全静态链接,零依赖) |
| 目标数据库 | openGauss 3.x / 5.x(Astore heap 存储格式) |
| 存储引擎 | 仅支持 Astore(openGauss 默认行存格式);不支持 Ustore |
| 权限要求 | 对 openGauss 数据目录有读权限;对输出目录有写权限 |
| 磁盘空间 | 输出目录需预留约源数据体积 1~2 倍的空间(同时导出 SQL+DMP 时) |

 

#### 2.3.3 已验证环境

 

– RHEL 7.9 / GCC 9 / openGauss 3.0+
– RHEL 8.6 / GCC 11 / openGauss 5.0+
– Oracle Linux 9 / GCC 12 / openGauss 5.0+
– 麒麟 V10 / GCC 10 / openGauss 5.0+
– 欧拉 22.03 / GCC 10 / openGauss 5.0+

 

### 2.4 技术架构

 

FGOGDU 采用模块化 C++ 设计,源代码组织清晰,各模块职责单一:

 

| 模块 | 源文件 | 职责 |
|——|——–|——|
| 公共定义 | common.h | 页结构、常量、工具函数 |
| 类型系统 | types.h / types.cpp | OID 枚举、列定义、值结构、varlena/numeric/日期/pglz 解码、TOAST 解析 |
| 页面解析 | page.h / page.cpp | 块大小检测、页头验证、元组提取 |
| 关系模型 | relation.h / relation.cpp | Schema、RecoveredRow、元组解码、关系文件扫描 |
| 系统目录 | catalog.h / catalog.cpp | pg_database、pg_class、pg_attribute 解析 |
| 恢复引擎 | recovery.h / recovery.cpp | 单表、全库、孤立文件、TOAST/LOB 恢复 |
| 导出器 | exporter.h / exporter.cpp | SQL/DMP 导出实现 |
| 命令分发 | commands.h / commands.cpp | 命令行解析与执行 |
| 程序入口 | main.cpp | argv 转发与异常处理 |

 

恢复数据流:数据文件 → 页面解析 → 元组提取 → 类型解码(含 TOAST 重组与 pglz 解压)→ 导出器(SQL/DMP)→ 输出文件。

 

### 2.5 恢复原理

 

1. **系统目录解析**:从 `global/1262`(pg_database)读取数据库列表,从各数据库的 `pg_class`(OID 1259)和 `pg_attribute`(OID 1249)读取表结构与列定义。
2. **数据页解析**:读取 Astore heap 格式的数据页,解析页头、行指针(line pointer)与元组头。
3. **元组解码**:根据列定义与数据类型,逐列解码元组数据,正确处理定长与变长(varlena)字段。
4. **已删除数据恢复**:通过 `t_xmax` 与 `t_infomask` 标志识别已删除但尚未被覆盖的元组。
5. **孤立文件恢复**:扫描 `base/<dboid>/` 目录中未被 `pg_class` 引用的数据文件,定位被 DROP/TRUNCATE 的表。
6. **系统目录损坏兜底**:pg_database 不可读时扫描 `base/` 数字子目录;pg_class 不可读时做无表结构原始元组抽取。
7. **LOB/TOAST 恢复**:解析 varatt_external 指针(12/16 字节),读取 TOAST 表文件按 chunk 顺序重组,通过内置 pglz 解压器还原压缩数据。

 

### 2.6 已知限制

 

– 仅支持 Astore 存储引擎(openGauss 默认行存格式);不支持 Ustore 原地更新存储引擎。
– 不支持 LZ4 压缩的 TOAST 数据(openGauss 默认使用 pglz,已支持)。
– 内联压缩的 varlena 数据(非 TOAST)标记为 `<COMPRESSED>`,暂不支持解压。
– 已被新数据物理覆盖的删除行无法恢复。
– TOAST 表文件缺失时,对应 LOB 字段标记为 `<TOASTED>`,不影响其他字段与其他行的恢复。

 

 

## 三、程序使用

 

### 3.1 编译与安装

 

#### 3.1.1 环境准备

 

确保编译机已安装 GCC(支持 C++17)及静态链接库:

 

“`bash
# RHEL/OEL/CentOS
dnf install gcc gcc-c++ glibc-static libstdc++-static make

 

# Oracle Linux 需启用 CodeReady Builder 仓库
dnf config-manager –set-enabled ol9_codeready_builder
dnf install glibc-static libstdc++-static
“`

 

#### 3.1.2 一键编译

 

“`bash
cd /path/to/FGOGDU
./build.sh
“`

 

`build.sh` 会自动执行:清理旧目标 → 并行编译 → 验证静态链接 → 运行版本自检。

 

#### 3.1.3 手动编译

 

“`bash
make clean && make -j$(nproc)
“`

 

#### 3.1.4 验证静态链接

 

“`bash
ldd ./fgogdu
# 期望输出: not a dynamic executable(或:不是动态可执行文件)
“`

 

#### 3.1.5 部署

 

编译完成后生成 `fgogdu` 可执行文件(约 2MB),直接拷贝到目标服务器即可使用:

 

“`bash
scp fgogdu user@target:/tmp/
ssh user@target “chmod +x /tmp/fgogdu && /tmp/fgogdu version”
“`

 

### 3.2 命令总览

 

“`
USAGE:  fgogdu <command> [options]

 

COMMANDS (simple & clear):
  version                       显示版本信息
  help                          显示帮助
  databases <datadir>           列出数据目录中的所有数据库
  schemas   <datadir> <db>      列出数据库中的模式
  tables    <datadir> <db> [schema]   列出表(可按模式过滤)
  blocksize <file>              自动检测数据文件的块大小
  page      <file> <blkno> [blocksize]  查看数据页信息(诊断用)

 

RECOVERY (export to SQL/DMP, one file per table):
  recover          <datadir> <db> <schema> <table>   恢复单个表的活跃数据
  recover-deleted  <datadir> <db> <schema> <table>   恢复活跃+已删除数据
  recover-all      <datadir> [db] [–max]            全库导出
  unload           <datadir> <db> [-o outdir] [-f fmt] [–max]  按用户名 unload
  recover-directory <datadir>                        最大恢复:按目录导出所有数据
  recover-file     <file> -s <schemafile> [name]     用模式文件恢复原始数据文件
  orphan-scan      <datadir> <db>                    查找孤立文件
“`

 

### 3.3 查看命令详解

 

#### 3.3.1 version – 显示版本信息

 

“`bash
./fgogdu version
“`

 

输出示例:
“`
FGOGDU 1.0  (FGEDU openGauss DUL)
openGauss data unload & recovery tool (Astore heap format)
Static build, no runtime dependencies.
“`

 

#### 3.3.2 help – 显示帮助

 

“`bash
./fgogdu help
“`

 

显示所有命令与选项的简要说明。

 

#### 3.3.3 databases – 列出数据库

 

“`bash
./fgogdu databases /opengauss/data
“`

 

输出示例:
“`
OID        NAME
14448      postgres
1          template1
14447      template0
“`

 

`<db>` 参数既可使用数据库名称,也可直接使用 OID 数字。

 

#### 3.3.4 schemas – 列出模式

 

“`bash
./fgogdu schemas /opengauss/data postgres
“`

 

输出示例:
“`
NSPOID     NAME
11         pg_catalog
2200       public
16384      my_schema
“`

 

#### 3.3.5 tables – 列出表

 

“`bash
# 列出所有表
./fgogdu tables /opengauss/data postgres

 

# 列出指定模式下的表
./fgogdu tables /opengauss/data postgres public
“`

 

输出示例:
“`
OID        FILENODE   SCHEMA               TABLE              COLS
16384      16384      public               users              5
16385      16385      public               orders             8
16390      16390      my_schema            products           4
“`

 

#### 3.3.6 blocksize – 检测块大小

 

“`bash
./fgogdu blocksize /opengauss/data/base/14448/16384
# 输出: 8192
“`

 

通常无需手动指定,工具会自动检测。此命令用于诊断目的。

 

#### 3.3.7 page – 查看数据页

 

“`bash
./fgogdu page /opengauss/data/base/14448/16384 0
./fgogdu page /opengauss/data/base/14448/16384 5 8192
“`

 

输出示例:
“`
block 0  size=8192 lower=48 upper=7920 special=8192 version=4
lineptrs=6 normal=6 redirect=0 dead=0 unused=0 tuples=6
  off=1  len=64   xmin=1000   xmax=0      natts=5  live
  off=2  len=64   xmin=1001   xmax=2000   natts=5  del
“`

 

用于诊断数据页结构与元组状态(live/del/DEAD)。

 

### 3.4 恢复命令详解

 

#### 3.4.1 recover – 恢复单个表

 

“`bash
./fgogdu recover <datadir> <db> <schema> <table> [-o outdir] [-f fmt] [–max]
“`

 

参数说明:
– `<datadir>`:openGauss 数据目录(包含 base/ 和 global/)
– `<db>`:数据库名或 OID
– `<schema>`:模式名(如 public)
– `<table>`:表名

 

示例:
“`bash
# 恢复 public.orders 表
./fgogdu recover /opengauss/data postgres public orders -o /backup

 

# 仅导出 SQL 格式
./fgogdu recover /opengauss/data postgres public orders -o /backup -f sql

 

# 最大恢复模式(包含已删除数据,遇到错误继续)
./fgogdu recover /opengauss/data postgres public orders -o /backup –max
“`

 

输出:在输出目录中生成 `schema.table.sql` 和/或 `schema.table.dmp` 文件。

 

#### 3.4.2 recover-deleted – 恢复已删除数据

 

“`bash
./fgogdu recover-deleted <datadir> <db> <schema> <table> [-o outdir] [-f fmt]
“`

 

恢复活跃数据 + 已删除数据(UNDELETE)。已删除的行在 SQL 文件中标记为:
“`sql
— recovered row blk=0 off=2 [was-deleted]
INSERT INTO public.orders (…) VALUES (…);
“`

 

#### 3.4.3 recover-all – 全库导出

 

“`bash
# 导出单个数据库
./fgogdu recover-all <datadir> <db> [-o outdir] [–max]

 

# 导出所有数据库
./fgogdu recover-all <datadir> [-o outdir] [–max]
“`

 

– `–max` 模式包含已删除数据、孤立文件扫描,遇到错误继续。
– 每个数据库的数据导出到 `<outdir>/<dbname>_<dboid>/` 子目录。

 

#### 3.4.4 unload – 按用户名 unload

 

“`bash
./fgogdu unload <datadir> <db> [-o outdir] [-f fmt] [–max]
“`

 

| 参数 | 说明 |
|——|——|
| `<datadir>` | openGauss 数据目录 |
| `<db>` | 数据库名(在 openGauss 中用户名通常对应数据库名) |
| `-o` | 输出目录(默认 ./recover_out) |
| `-f` | 输出格式:sql / dmp / both(默认 both) |
| `–max` | 最大恢复:包含已删除数据 |

 

示例:
“`bash
# 按用户名 unload,导出 fgedudb 下所有表(SQL + DMP)
./fgogdu unload /opengauss/data fgedudb -o /backup -f both

 

# 最大恢复模式(包含已删除数据)
./fgogdu unload /opengauss/data fgedudb -o /backup –max
“`

 

输出目录结构:
“`
/backup/
└── fgedudb/                          # 以用户名(数据库名)命名的子目录
    ├── fgeduschema.fgedu01.sql       # 每个表一个 SQL 文件
    ├── fgeduschema.fgedu01.dmp       # 每个表一个 DMP 文件
    ├── fgeduschema.fgedu02.sql
    └── …
“`

 

`unload` 是 `recover-all <datadir> <db>` 的语义化命令,必须指定用户名/数据库名,语义更明确,专为“按用户名 unload”场景设计。

 

#### 3.4.5 recover-directory – 按目录最大恢复

 

“`bash
./fgogdu recover-directory <datadir> [-o outdir] [-f fmt]
“`

 

此命令自动执行:
1. 导出所有数据库的所有表(含 LOB/TOAST 数据)
2. 包含已删除的数据行
3. 恢复 global/ 目录下的共享系统表
4. 扫描并导出孤立文件(DROP/TRUNCATE 的表)
5. 系统目录损坏时自动兜底恢复

 

输出目录结构:
“`
/backup/recovery/
├── postgres_14448/
│   ├── public.orders.sql
│   ├── public.orders.dmp
│   ├── public.customers.sql
│   ├── _orphan/
│   │   └── orphan_12345.sql
│   └── …
├── template1_1/
└── template0_14447/
“`

 

#### 3.4.6 recover-file – 按数据文件恢复

 

“`bash
./fgogdu recover-file <file> -s <schemafile> [name] [-o outdir] [-b blocksize] [–max]
“`

 

参数说明:
– `<file>`:数据文件路径
– `-s <schemafile>`:模式文件路径(定义表结构)
– `[name]`:输出文件名(格式:schema.table)
– `-b <blocksize>`:强制指定块大小(默认自动检测)

 

示例:
“`bash
./fgogdu recover-file /opengauss/data/base/14448/16384 \
  -s myschema.schema public.mytable -o /backup
“`

 

#### 3.4.7 orphan-scan – 查找孤立文件

 

“`bash
./fgogdu orphan-scan <datadir> <db>
“`

 

扫描数据库目录中未被 pg_class 引用的数据文件(DROP/TRUNCATE 的表)。输出示例:
“`
orphan (candidate dropped/truncated) files:
  /opengauss/data/base/14448/12345
  /opengauss/data/base/14448/12346

 

To recover one, build a .schema file and run:
  fgogdu recover-file <file> -s <schemafile> <schema.table>
“`

 

### 3.5 通用选项

 

| 选项 | 说明 |
|——|——|
| `-o, –outdir <dir>` | 输出目录(默认 ./recover_out) |
| `-f, –format <fmt>` | 输出格式:sql / dmp / both(默认 both) |
| `-s, –schema-file <f>` | 手动模式文件(用于 recover-file) |
| `-b, –blocksize <n>` | 强制指定块大小(默认自动检测) |
| `–max` | 最大恢复:包含已删除数据,遇到错误继续 |
| `-v, –verbose` | 详细输出,显示更多诊断信息 |

 

### 3.6 输出格式说明

 

#### 3.6.1 SQL 格式(.sql)

 

每个表生成一个 SQL 文件,包含 `CREATE TABLE` 语句(自动还原表结构)与 `INSERT INTO` 语句(每行一条),已删除行有恢复标记注释:

 

“`sql
— FGOGDU export: public.orders
— Source: openGauss data file (Astore heap)
— Generated by FGOGDU v1.0

 

CREATE TABLE public.orders (
    id integer NOT NULL,
    customer_id integer,
    order_date timestamp,
    total_amount numeric,
    status character varying(20)
);

 

INSERT INTO public.orders (id, customer_id, order_date, total_amount, status)
  VALUES (1, 100, ‘2024-01-15 10:30:00’, ‘199.99’, ‘pending’);
— recovered row blk=0 off=2 [was-deleted]
INSERT INTO public.orders (id, customer_id, order_date, total_amount, status)
  VALUES (2, 101, ‘2024-02-20 14:00:00’, ‘299.50’, ‘shipped’);

 

— end of public.orders: 2 rows
“`

 

#### 3.6.2 DMP 格式(.dmp)

 

自描述的二进制格式,包含:
– 文件头标识 `FGOGDUMP`
– 版本号、标志位
– 表名、列定义
– 每行数据的原始二进制值
– 恢复元数据(块号、偏移、删除状态)

 

DMP 格式保留原始二进制数据,适合程序化导入。

 

#### 3.6.3 特殊标记

 

| 标记 | 说明 |
|——|——|
| `<TOASTED>` | TOAST 表文件缺失或损坏,无法恢复 LOB 数据 |
| `<COMPRESSED>` | 内联压缩的 varlena 数据(非 TOAST),无法解压 |
| `[was-deleted]` | 该行为已删除但未被覆盖的数据 |
| `[partial]` | 该行部分列无法解码,以 NULL 填充 |

 

### 3.7 模式文件格式

 

用于 `recover-file` 命令手动指定表结构:

 

“`
# 注释行以 # 开头
# 格式: 列名 类型 [NOT NULL]
# 类型可使用名称或数字 OID
# 列顺序必须与原表一致

 

id integer NOT NULL
name text
price numeric
created_at timestamp
data bytea
“`

 

支持的类型名称:boolean、bytea、char、name、bigint/smallint/int8、smallint/int2、integer/int/int4、text、oid、real/float4、double/float8、bpchar/character、varchar/character varying、nvarchar2、date、time、timestamp、timestamptz、numeric、uuid、json、jsonb、xml。

 

 

## 四、程序各种案例场景与操作过程

 

### 场景一:openGauss数据库无法启动,全库一键导出

 

**背景**:openGauss 数据库因控制文件损坏、参数文件丢失或 redo 断裂等原因无法启动,需要尽快导出全部业务数据。

 

**操作步骤**:

 

“`bash
# 1. 确认数据目录位置(应包含 base/、global/、pg_control 等)
ls /opengauss/data

 

# 2. 执行全库最大恢复
./fgogdu recover-directory /opengauss/data -o /backup/recovery

 

# 3. 查看恢复结果
ls /backup/recovery/
# postgres_14448/  template1_1/  template0_14447/

 

# 4. 查看某个数据库的恢复结果
ls /backup/recovery/postgres_14448/
# public.orders.sql  public.orders.dmp  public.customers.sql  …

 

# 5. 恢复到新数据库
createdb newdb
psql -d newdb -f /backup/recovery/postgres_14448/public.orders.sql
“`

 

**说明**:`recover-directory` 是应急场景下的首选命令,会自动执行全库导出、已删除数据恢复、孤立文件扫描、global/ 共享表恢复,并在系统目录损坏时自动兜底。

 

### 场景二:openGauss数据库无法启动,按用户(数据库)导出所有数据

 

**背景**:在 openGauss 中用户通常对应一个数据库,只需导出特定用户(数据库)的数据。

 

**操作步骤**:

 

“`bash
# 1. 查看数据目录中有哪些数据库(用户)
./fgogdu databases /opengauss/data
# OID        NAME
# 14448      postgres
# 1          template1
# 14447      template0

 

# 2. 导出指定数据库(用户)的所有表数据
./fgogdu recover-all /opengauss/data postgres -o /backup –max

 

# 3. 也可使用 OID 导出
./fgogdu recover-all /opengauss/data 14448 -o /backup –max

 

# 4. 查看导出结果
ls /backup/postgres_14448/
# public.orders.sql  public.customers.sql  …

 

# 5. 恢复到新数据库
psql -d newdb -f /backup/postgres_14448/public.orders.sql
“`

 

也可使用语义更明确的 `unload` 命令按用户名导出所有表:

 

“`bash
# 按用户名 unload,导出 fgedudb 下所有表(SQL + DMP)
./fgogdu unload /opengauss/data fgedudb -o /backup -f both

 

# 最大恢复模式(包含已删除数据)
./fgogdu unload /opengauss/data fgedudb -o /backup –max
“`

 

### 场景三:openGauss数据库无法启动,按表精确导出数据

 

**背景**:仅需恢复特定的一个或几个表的数据。

 

**操作步骤**:

 

“`bash
# 1. 查看数据库中有哪些表
./fgogdu tables /opengauss/data postgres
# OID        FILENODE   SCHEMA   TABLE    COLS
# 16384      16384      public   users    5
# 16385      16385      public   orders   8

 

# 2. 查看指定 schema 下的表
./fgogdu tables /opengauss/data postgres public

 

# 3. 恢复单个表
./fgogdu recover /opengauss/data postgres public orders -o /backup

 

# 4. 恢复单个表(包含已删除的数据)
./fgogdu recover-deleted /opengauss/data postgres public orders -o /backup

 

# 5. 恢复多个表(循环执行)
for table in orders customers products; do
  ./fgogdu recover /opengauss/data postgres public $table -o /backup
done

 

# 6. 恢复到新数据库
psql -d newdb -f /backup/public.orders.sql
“`

 

### 场景四:openGauss数据库无法启动,直接按数据文件导出所有表数据

 

**背景**:系统目录损坏,无法通过表名定位表,需要直接从数据文件恢复。

 

**操作步骤**:

 

“`bash
# 方式1:最大恢复模式,自动扫描所有数据文件(推荐)
./fgogdu recover-directory /opengauss/data -o /backup

 

# 方式2:恢复指定的单个数据文件(需手动提供表结构)
#   先创建模式文件:
cat > myschema.schema << ‘EOF’
id integer NOT NULL
name text
content text
created_at timestamp
EOF

 

#   然后恢复:
./fgogdu recover-file /opengauss/data/base/14448/16384 \
  -s myschema.schema public.mytable -o /backup

 

# 方式3:查找孤立文件(被 DROP/TRUNCATE 的表)
./fgogdu orphan-scan /opengauss/data postgres
# orphan (candidate dropped/truncated) files:
#   /opengauss/data/base/14448/12345

 

# 方式4:恢复找到的孤立文件
./fgogdu recover-file /opengauss/data/base/14448/12345 \
  -s myschema.schema public.dropped_table -o /backup
“`

 

### 场景五:openGauss DELETE 误删数据恢复

 

**背景**:误执行 DELETE 操作,需要恢复被删除的数据行。

 

**操作步骤**:

 

“`bash
# 1. 立即停止数据库写入(防止被删除数据被新数据物理覆盖)

 

# 2. 恢复活跃+已删除数据
./fgogdu recover-deleted /opengauss/data postgres public orders -o /backup

 

# 3. 查看恢复结果,已删除的行标记为 [was-deleted]
grep “was-deleted” /backup/public.orders.sql
# — recovered row blk=0 off=2 [was-deleted]
# INSERT INTO public.orders (…) VALUES (…);

 

# 4. 筛选出已删除的行(用于确认数据)
grep -A1 “was-deleted” /backup/public.orders.sql > /backup/deleted_rows.sql

 

# 5. 恢复到数据库(注意:需手动筛选需要的数据)
psql -d postgres -f /backup/public.orders.sql
“`

 

**要点**:DELETE 删除的数据只有在未被新数据物理覆盖前才能恢复,因此误删后应立即停止数据库写入操作。

 

### 场景六:openGauss DROP/TRUNCATE 表恢复

 

**背景**:表被 DROP 或 TRUNCATE,系统目录中已无该表信息,但底层数据文件可能仍残留在磁盘上。

 

**操作步骤**:

 

“`bash
# 1. 查找孤立文件
./fgogdu orphan-scan /opengauss/data postgres
# orphan (candidate dropped/truncated) files:
#   /opengauss/data/base/14448/12345

 

# 2. 创建模式文件(根据原表结构)
cat > orders.schema << ‘EOF’
id integer NOT NULL
customer_id integer
order_date timestamp
total_amount numeric
status varchar(20)
EOF

 

# 3. 使用模式文件恢复
./fgogdu recover-file /opengauss/data/base/14448/12345 \
  -s orders.schema public.orders -o /backup

 

# 4. 恢复到新数据库
psql -d newdb -f /backup/public.orders.sql
“`

 

**自动恢复**:使用 `recover-directory` 命令会自动扫描孤立文件并以原始格式导出:

 

“`bash
./fgogdu recover-directory /opengauss/data -o /backup
“`

 

### 场景七:openGauss LOB/大字段恢复

 

**背景**:表中包含 text、varchar、bytea 等大字段,数据存储在 TOAST 表中。

 

**说明**:FGOGDU 默认支持 LOB 恢复,无需额外参数。当变长字段超过约 2KB 时,openGauss 会将其存储到 TOAST 表中,FGOGDU 会自动读取 TOAST 表并重组数据。

 

**操作步骤**:

 

“`bash
# 1. 恢复含大字段的表(LOB 自动恢复)
./fgogdu recover /opengauss/data postgres public documents -o /backup

 

# 2. 查看恢复结果(大字段数据已完整导出)
head -50 /backup/public.documents.sql
# CREATE TABLE public.documents (
#     id integer NOT NULL,
#     title varchar(200),
#     content text,
#     attachment bytea
# );
# INSERT INTO public.documents (id, title, content, attachment) VALUES
#   (1, ‘doc1’, ‘这是一段很长的文本内容…’, ‘\x89504E47…’);

 

# 3. 全库恢复(所有表的 LOB 数据都会自动恢复)
./fgogdu recover-directory /opengauss/data -o /backup

 

# 4. 验证 LOB 数据完整性
#   SQL 文件中:text/varchar 以引号字符串形式存储
#   SQL 文件中:bytea 以 ‘\x’ 十六进制形式存储
#   DMP 文件中:以原始二进制形式存储
“`

 

### 场景八:openGauss系统目录损坏时的兜底恢复

 

**背景**:系统目录(pg_database、pg_class)因坏块无法读取。

 

**操作步骤**:

 

“`bash
# 1. 使用最大恢复模式(自动处理系统目录损坏)
./fgogdu recover-directory /opengauss/data -o /backup

 

# 2. 查看恢复日志
#   如果 pg_database 损坏,会看到:
#   WARNING: pg_database catalog unreadable; falling back to direct base/ directory scan
#
#   如果 pg_class 损坏,会看到:
#   pg_class unreadable for dboid XXXX; performing raw file scan (no schema).

 

# 3. 查看恢复结果
#   系统目录损坏时,数据以原始元组形式导出到 _orphan/ 目录
ls /backup/postgres_14448/_orphan/
# orphan_12345.sql  orphan_12346.sql  …

 

# 4. 查看原始元组数据
head -20 /backup/postgres_14448/_orphan/orphan_12345.sql
# — FGOGDU orphan recovery: /opengauss/data/base/14448/12345
# — Block size: 8192
# — No schema available (dropped/truncated table). Raw tuple dump.
# — block=0 off=1 xmin=1000 xmax=0 natts=5 hoff=32 live
# — raw(64 bytes): 0A000000…
“`

 

**兜底策略**:
– pg_database 不可读 → 自动扫描 `base/` 下的数字子目录作为数据库 OID
– pg_class 不可读 → 对该库所有数据文件做无表结构的原始元组抽取
– 坏块自动跳过,继续恢复后续数据

 

### 场景九:openGauss坏块处理

 

**背景**:数据文件中部分数据页损坏。

 

**说明**:FGOGDU 在最大恢复模式下会自动跳过坏块,继续恢复后续数据。

 

**操作步骤**:

 

“`bash
# 1. 使用最大恢复模式
./fgogdu recover /opengauss/data postgres public orders -o /backup –max

 

# 2. 查看哪些块被跳过(使用 verbose 模式)
./fgogdu recover /opengauss/data postgres public orders -o /backup –max -v

 

# 3. 诊断特定块
./fgogdu page /opengauss/data/base/14448/16384 5
# 如果输出 “block 5: not a valid page”,说明该块损坏

 

# 4. 全库恢复时自动跳过坏块
./fgogdu recover-directory /opengauss/data -o /backup
“`

 

### 场景十:openGauss指定输出格式

 

**背景**:只需 SQL 文件或只需 DMP 文件。

 

“`bash
# 仅导出 SQL 文件
./fgogdu recover /opengauss/data postgres public orders -o /backup -f sql

 

# 仅导出 DMP 文件
./fgogdu recover /opengauss/data postgres public orders -o /backup -f dmp

 

# 同时导出两种格式(默认)
./fgogdu recover /opengauss/data postgres public orders -o /backup -f both
“`

 

### 场景十一:openGauss按用户名 unload 导出所有表

 

**背景**:数据库无法启动,需按用户名(数据库)unload 导出该用户下所有表,要求显示详细的导出进度(表名、导出行数等)。

 

**操作步骤**:

 

“`bash
# 1. 查看数据目录中的数据库(用户)列表
./fgogdu databases /opengauss/data
# OID        NAME
# 16385      fgedudb

 

# 2. 按用户名 unload,导出 fgedudb 下所有表(SQL + DMP),实时显示每表导出进度
./fgogdu unload /opengauss/data fgedudb -o /backup -f both

 

# 3. 最大恢复模式(包含已删除数据,遇到错误继续)
./fgogdu unload /opengauss/data fgedudb -o /backup –max

 

# 4. 查看导出结果
ls /backup/fgedudb/
# fgeduschema.fgedu01.sql  fgeduschema.fgedu01.dmp
# fgeduschema.fgedu02.sql  fgeduschema.fgedu02.dmp
# fgeduschema.fgedu_lob.sql  fgeduschema.fgedu_lob.dmp

 

# 5. 导入到新数据库
psql -d newdb -f /backup/fgedudb/fgeduschema.fgedu01.sql
“`

 

**进度输出示例**(运行时实时显示):
“`
[unload] database=fgedudb (oid=16385) outdir=/backup/fgedudb
[unload] scanning pg_class … found 3 tables
[unload] exporting fgeduschema.fgedu01 … 10 rows exported
[unload] exporting fgeduschema.fgedu02 … 10 rows exported
[unload] exporting fgeduschema.fgedu_lob … 3 rows exported (LOB recovered)
[unload] done. 3 tables, 23 rows total.
“`

 

### 场景十二:openGauss多数据库批量恢复

 

**背景**:数据目录下有多个业务数据库,需要一次性导出全部。

 

**操作步骤**:

 

“`bash
# 1. 查看所有数据库
./fgogdu databases /opengauss/data
# OID        NAME
# 14448      postgres
# 16385      fgedudb
# 16390      report_db

 

# 2. 一次性导出所有数据库(最大恢复模式)
./fgogdu recover-all /opengauss/data -o /backup –max

 

# 3. 查看恢复结果
ls /backup/
# postgres_14448/  fgedudb_16385/  report_db_16390/
“`

 

### 场景十三:openGauss诊断数据页问题

 

**背景**:恢复结果异常,需要诊断具体数据页的状态。

 

**操作步骤**:

 

“`bash
# 1. 检测数据文件块大小
./fgogdu blocksize /opengauss/data/base/14448/16384
# 8192

 

# 2. 查看第 0 页(首页)
./fgogdu page /opengauss/data/base/14448/16384 0
# block 0  size=8192 lower=48 upper=7920 special=8192 version=4
# lineptrs=6 normal=6 redirect=0 dead=0 unused=0 tuples=6
#   off=1  len=64   xmin=1000   xmax=0      natts=5  live
#   off=2  len=64   xmin=1001   xmax=2000   natts=5  del

 

# 3. 查看指定块(如怀疑第 5 块损坏)
./fgogdu page /opengauss/data/base/14448/16384 5 8192
# 如果输出 “block 5: not a valid page”,说明该块损坏

 

# 4. 使用 verbose 模式恢复,查看跳过的坏块
./fgogdu recover /opengauss/data postgres public orders -o /backup –max -v
“`

 

### 场景十四:openGauss恢复结果验证

 

**背景**:恢复完成后,需要验证数据完整性。

 

**操作步骤**:

 

“`bash
# 1. 统计恢复的行数
grep -c “^INSERT” /backup/public.orders.sql

 

# 2. 查看恢复的表结构
grep “CREATE TABLE” /backup/public.orders.sql

 

# 3. 导入到新数据库验证
createdb testdb
psql -d testdb -f /backup/public.orders.sql
psql -d testdb -c “SELECT count(*) FROM public.orders;”

 

# 4. 对比源库与恢复库的行数(若源库可读)
# 源库:SELECT count(*) FROM public.orders;
# 恢复库:SELECT count(*) FROM public.orders;
“`

 

### 场景十五:openGauss强制指定块大小

 

**背景**:自动检测块大小失败(如页头损坏),需手动指定。

 

**操作步骤**:

 

“`bash
# 1. 尝试常见块大小(8192 最常见)
./fgogdu recover-file /opengauss/data/base/14448/16384 \
  -s myschema.schema public.mytable -o /backup -b 8192

 

# 2. 若 8192 失败,尝试 16384 / 32768 / 65536
./fgogdu recover-file /opengauss/data/base/14448/16384 \
  -s myschema.schema public.mytable -o /backup -b 16384
“`

 

 

## 五、常用问题与排查

 

### 5.1 编译相关问题

 

#### 问题 1:编译报错 `找不到 -lstdc++` 或 `-lc` 或 `-lm`

 

**原因**:缺少静态链接库。

 

**解决**:安装静态链接库:

 

“`bash
# RHEL/OEL/CentOS
dnf install glibc-static libstdc++-static

 

# Oracle Linux 需启用 CodeReady Builder 仓库
dnf config-manager –set-enabled ol9_codeready_builder
dnf install glibc-static libstdc++-static
“`

 

#### 问题 2:编译报错 `g++: command not found`

 

**原因**:未安装编译器。

 

**解决**:

 

“`bash
dnf install gcc gcc-c++ make
“`

 

#### 问题 3:编译报错 `g++: error: unrecognized option ‘-std=c++17’`

 

**原因**:GCC 版本过低,不支持 C++17。

 

**解决**:升级 GCC 至 4.8 以上版本(建议 GCC 9+):

 

“`bash
# RHEL 8/9
dnf install gcc-toolset-11
scl enable gcc-toolset-11 bash
“`

 

### 5.2 运行环境问题

 

#### 问题 4:运行报错 `./fgogdu: /lib64/libc.so.6: version ‘GLIBC_2.28’ not found`

 

**原因**:在比编译机 glibc 版本更旧的目标服务器上运行静态链接二进制。

 

**解决**:在 glibc 版本更低的服务器上重新编译,或使用更旧的编译机进行编译。

 

#### 问题 5:运行报错 `Permission denied`

 

**原因**:对数据目录无读权限,或对输出目录无写权限。

 

**解决**:

 

“`bash
# 确认对数据目录有读权限
ls -l /opengauss/data/base/

 

# 确认对输出目录有写权限
touch /backup/test && rm /backup/test

 

# 必要时使用具有权限的用户执行
sudo ./fgogdu recover-directory /opengauss/data -o /backup
“`

 

### 5.3 恢复问题

 

#### 问题 6:`database not found: postgres`

 

**原因**:数据库名拼写错误,或数据目录路径不正确。

 

**解决**:

 

1. 确认数据目录路径正确
2. 使用 `databases` 命令查看可用数据库
3. 使用 OID 代替数据库名

 

“`bash
./fgogdu databases /opengauss/data
./fgogdu recover /opengauss/data 14448 public orders -o /backup
“`

 

#### 问题 7:`no relations discovered for dboid XXXX`

 

**原因**:该数据库的系统目录(pg_class)损坏,无法读取表信息。

 

**解决**:使用最大恢复模式,自动兜底处理:

 

“`bash
./fgogdu recover-directory /opengauss/data -o /backup
“`

 

#### 问题 8:恢复出的数据显示 `<TOASTED>`

 

**原因**:TOAST 表文件缺失或损坏。可能原因:
1. TOAST 表文件被删除
2. TOAST 表数据文件损坏
3. reltoastrelid 在 pg_class 中不可读

 

**解决**:使用 `recover-directory` 命令进行最大恢复,它会尝试所有可能的恢复路径。若 TOAST 文件已物理丢失,则该 LOB 字段无法恢复,但其他字段与其他行不受影响。

 

#### 问题 9:恢复出的数据显示 `<COMPRESSED>`

 

**原因**:该值使用了内联压缩(非 TOAST 压缩),FGOGDU 目前不支持内联压缩的解压。通常发生在较老的 PostgreSQL 版本中。

 

**解决**:此类数据暂无法通过 FGOGDU 解压恢复,可尝试使用其他专业工具。

 

#### 问题 10:恢复行数少于预期

 

**可能原因**:
1. 部分数据页损坏(坏块),被自动跳过
2. 部分数据行已被物理覆盖(DELETE 后被新数据覆盖)
3. 表存在分区,未恢复到所有分区文件
4. 使用了 `recover` 而非 `recover-deleted`,未包含已删除数据

 

**排查步骤**:

 

“`bash
# 1. 使用 verbose 模式查看跳过的坏块
./fgogdu recover /opengauss/data postgres public orders -o /backup –max -v

 

# 2. 包含已删除数据
./fgogdu recover-deleted /opengauss/data postgres public orders -o /backup

 

# 3. 诊断特定数据页
./fgogdu page /opengauss/data/base/14448/16384 0

 

# 4. 使用最大恢复模式兜底
./fgogdu recover-directory /opengauss/data -o /backup
“`

 

#### 问题 11:`block N: not a valid page`

 

**原因**:指定块损坏或块大小不正确。

 

**解决**:

 

“`bash
# 1. 检测正确的块大小
./fgogdu blocksize /opengauss/data/base/14448/16384

 

# 2. 用正确块大小查看
./fgogdu page /opengauss/data/base/14448/16384 5 8192

 

# 3. 若确实损坏,使用 –max 模式跳过坏块继续恢复
./fgogdu recover /opengauss/data postgres public orders -o /backup –max
“`

 

#### 问题 12:恢复出的表结构缺失列或列顺序错误

 

**原因**:系统目录中 pg_attribute 信息部分损坏。

 

**解决**:

 

1. 使用 `page` 命令查看元组的 `natts`(实际列数)
2. 根据业务知识手动编写模式文件
3. 使用 `recover-file` 命令按手动模式恢复

 

“`bash
./fgogdu page /opengauss/data/base/14448/16384 0
# 查看 natts=X,确定列数

 

cat > mytable.schema << ‘EOF’
id integer NOT NULL
name varchar(50)
EOF

 

./fgogdu recover-file /opengauss/data/base/14448/16384 \
  -s mytable.schema public.mytable -o /backup
“`

 

#### 问题 13:`unload` 命令报 `database not found`

 

**原因**:`unload` 必须指定用户名/数据库名,且该名称需与 `databases` 命令输出的名称一致。

 

**解决**:

 

“`bash
# 先查看可用数据库名
./fgogdu databases /opengauss/data
# 再用正确的名称 unload
./fgogdu unload /opengauss/data fgedudb -o /backup -f both
“`

 

### 5.4 数据验证问题

 

#### 问题 14:导入 SQL 文件时报语法错误

 

**可能原因**:
1. 恢复的数据中包含特殊字符(如单引号未正确转义)
2. 表结构与目标库不兼容(如类型差异)
3. 恢复过程中部分行部分列解码失败

 

**排查**:

 

“`bash
# 1. 查看出错的行
psql -d newdb -f /backup/public.orders.sql 2>&1 | grep ERROR

 

# 2. 查看是否有 [partial] 标记的行
grep “partial” /backup/public.orders.sql

 

# 3. 检查特殊字符
grep -n “\\\\” /backup/public.orders.sql | head
“`

 

#### 问题 15:DMP 文件无法导入

 

**原因**:DMP 是 FGOGDU 自定义的二进制格式,需使用配套的导入工具,不兼容 gs_dump/pg_dump 的 DMP 格式。

 

**解决**:优先使用 SQL 格式导入(`-f sql`),或使用配套的 DMP 导入程序。

 

### 5.5 性能问题

 

#### 问题 16:恢复速度慢

 

**优化建议**:

 

– 使用 `-f sql` 或 `-f dmp` 只导出一种格式,减少 I/O
– 对于大型数据库,使用 `recover-all` 或 `recover-directory` 而非逐表恢复
– 输出目录建议使用高速磁盘(SSD/NVMe)
– LOB 恢复会增加内存使用,单 LOB 上限 256MB
– 在内存充足的服务器上运行,避免因内存不足导致频繁 swapping

 

### 5.6 故障排查通用流程

 

当恢复结果与预期不符时,建议按以下流程排查:

 

1. **确认数据目录路径**:`ls /opengauss/data`,应看到 base/、global/、pg_control 等。
2. **查看可用数据库**:`./fgogdu databases <datadir>`,确认目标数据库存在。
3. **查看表列表**:`./fgogdu tables <datadir> <db>`,确认目标表存在且列数正确。
4. **诊断数据页**:`./fgogdu page <file> 0`,查看首页结构与元组状态。
5. **使用 verbose + max 模式恢复**:`./fgogdu recover … –max -v`,查看详细日志与跳过的坏块。
6. **对比行数**:统计恢复的 INSERT 行数,与源库(若可读)对比。
7. **兜底恢复**:若以上均不理想,使用 `recover-directory` 进行最大恢复兜底。

 

 

## 六、附录

 

### 6.1 命令速查表

 

| 场景 | 命令 |
|——|——|
| 查看版本 | `fgogdu version` |
| 查看帮助 | `fgogdu help` |
| 查看数据库 | `fgogdu databases <datadir>` |
| 查看模式 | `fgogdu schemas <datadir> <db>` |
| 查看表 | `fgogdu tables <datadir> <db> [schema]` |
| 检测块大小 | `fgogdu blocksize <file>` |
| 诊断数据页 | `fgogdu page <file> <blkno> [blocksize]` |
| 恢复单表 | `fgogdu recover <datadir> <db> <schema> <table> -o <outdir>` |
| 恢复已删除 | `fgogdu recover-deleted <datadir> <db> <schema> <table> -o <outdir>` |
| 按数据库导出 | `fgogdu recover-all <datadir> <db> -o <outdir> –max` |
| 按用户名 unload | `fgogdu unload <datadir> <db> -o <outdir> -f both [–max]` |
| 全库导出 | `fgogdu recover-all <datadir> -o <outdir> –max` |
| 一键最大恢复 | `fgogdu recover-directory <datadir> -o <outdir>` |
| 按文件恢复 | `fgogdu recover-file <file> -s <schemafile> <name> -o <outdir>` |
| 查找孤立文件 | `fgogdu orphan-scan <datadir> <db>` |

 

### 6.2 选项速查表

 

| 选项 | 说明 |
|——|——|
| `-o, –outdir <dir>` | 输出目录(默认 ./recover_out) |
| `-f, –format <fmt>` | 输出格式:sql / dmp / both(默认 both) |
| `-s, –schema-file <f>` | 手动模式文件(用于 recover-file) |
| `-b, –blocksize <n>` | 强制指定块大小(默认自动检测) |
| `–max` | 最大恢复:包含已删除数据,遇到错误继续 |
| `-v, –verbose` | 详细输出 |

 

### 6.3 特殊标记速查表

 

| 标记 | 说明 |
|——|——|
| `<TOASTED>` | TOAST 表文件缺失或损坏,无法恢复 LOB 数据 |
| `<COMPRESSED>` | 内联压缩的 varlena 数据(非 TOAST),无法解压 |
| `[was-deleted]` | 该行为已删除但未被覆盖的数据 |
| `[partial]` | 该行部分列无法解码,以 NULL 填充 |

 

### 6.4 项目结构

 

“`
FGOGDU/
├── src/
│   ├── common.h       # 公共定义:页结构、常量、工具函数
│   ├── types.h        # 类型定义:OID枚举、列定义、值结构、ToastResolver
│   ├── types.cpp      # 类型解码:varlena、numeric、日期时间、pglz解压、TOAST解析
│   ├── page.h         # 页面解析器接口
│   ├── page.cpp       # 页面解析实现:块大小检测、页头验证、元组提取
│   ├── relation.h     # 关系模型:Schema、RecoveredRow、文件读取
│   ├── relation.cpp   # 元组解码、关系文件扫描
│   ├── catalog.h      # 系统目录读取器接口
│   ├── catalog.cpp    # 系统目录解析:pg_database、pg_class、pg_attribute
│   ├── recovery.h     # 恢复操作接口
│   ├── recovery.cpp   # 恢复实现:单表、全库、孤立文件、TOAST/LOB恢复
│   ├── exporter.h     # 导出器接口
│   ├── exporter.cpp   # SQL/DMP 导出实现
│   ├── commands.h     # 命令分发接口
│   ├── commands.cpp   # 命令行解析和执行
│   └── main.cpp       # 程序入口
├── docs/
│   └── README-WEB.md  # 本说明手册
├── Makefile           # 编译规则(静态链接)
├── build.sh           # 一键编译脚本
├── README.md          # 项目 README
├── usage_manual.md    # 详细使用手册
└── testdoc.md         # 实验测试手册
“`

 

### 6.5 许可证

 

FGEDU(FG Education)内部工具,仅供内部数据恢复与应急演练使用。
作者:风哥
官方网站: 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,节假日休息