华为高斯数据库恢复工具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 文件缺失等各种异常场景下,工具不会因单点故障而中断,而是自动降级到兜底策略------跳过坏块、扫描孤立文件、做无表结构的原始元组抽取,尽最大可能抢救磁盘上残存的数据。
  • 简单清晰的命令 :命令体系采用"动词 + 宾语"的自然语义结构(如 recoverrecover-deletedrecover-directoryorphan-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_idchunk_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_xmaxt_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
    └── ...

unloadrecover-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-allrecover-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

相关推荐
小蒜学长20 分钟前
springboot党建云课堂学习与管理系统(代码+数据库+LW)
java·数据库·spring boot·后端·学习
2601_9621803320 分钟前
FlinkCDC 实现 MySQL 数据变更实时同步
数据库·mysql
2601_9621896024 分钟前
深入浅出MySQL:概述与体系结构解析
数据库·mysql
Gain_chance30 分钟前
大数据毕业设计实战|Data Insight Platform:用 FastAPI + ClickHouse 打造低门槛全链路数据洞察平台
大数据·数据库·clickhouse·毕业设计·fastapi
harmony&1 小时前
ETCD 存储系统实战:从单节点部署到 Kubernetes 高可用集群
数据库·kubernetes·etcd
2601_962066491 小时前
【玩转全栈】----Django模板的继承
数据库·django·sqlite
一只小bit2 小时前
Redis哨兵机制、主从复制与集群搭建与维护
数据库·redis·bootstrap
zlwool9 小时前
图纸管理选型避坑指南
数据库·erp·设备erp·非标机械
小灰灰搞电子10 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt