FGOGDU(全称 FGEDU openGauss DUL)是一款专门面向 openGauss 数据库的离线数据抽取与恢复工具,将"绕过数据库实例、直接从底层数据文件中读取并还原数据"这一经典思路移植到 openGauss 生态,填补了 openGauss 在"数据库无法启动"这一极端故障场景下数据抢救工具的空白。
目录
一、程序介绍
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 在读取每个数据文件时会自动检测块大小,无需用户手动指定,检测策略为:
- 读取页头
pd_pagesize_version字段,从高 15 位提取块大小 - 若失败,依次尝试常见块大小:8192、16384、32768、65536、4096、2048、1024
- 对每个候选块大小,验证页头字段(pd_lower、pd_upper、pd_special)的合理性
- 选定首个通过验证的块大小
对于特殊场景,用户也可通过 -b/--blocksize 参数强制指定块大小。
2.2.4 LOB/TOAST 大字段恢复
当 text、varchar、bytea 等变长字段数据超过约 2KB 时,openGauss 会自动将其迁移到 TOAST 表中分块存储。FGOGDU 默认启用 LOB 恢复,无需额外参数,自动完成以下工作:
- 从
pg_class读取表的reltoastrelid,定位关联的 TOAST 表 - 读取 TOAST 表的数据文件,按
chunk_id和chunk_seq顺序重组分块数据 - 检测数据是否被 pglz 压缩,若压缩则调用内置 pglz 解压器还原原始数据
- 兼容新旧两种 varatt_external 指针格式(12 字节旧格式 / 16 字节 PG14+ 新格式)
- 将还原的 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 恢复原理
- 系统目录解析 :从
global/1262(pg_database)读取数据库列表,从各数据库的pg_class(OID 1259)和pg_attribute(OID 1249)读取表结构与列定义。 - 数据页解析:读取 Astore heap 格式的数据页,解析页头、行指针(line pointer)与元组头。
- 元组解码:根据列定义与数据类型,逐列解码元组数据,正确处理定长与变长(varlena)字段。
- 已删除数据恢复 :通过
t_xmax与t_infomask标志识别已删除但尚未被覆盖的元组。 - 孤立文件恢复 :扫描
base/<dboid>/目录中未被pg_class引用的数据文件,定位被 DROP/TRUNCATE 的表。 - 系统目录损坏兜底 :pg_database 不可读时扫描
base/数字子目录;pg_class 不可读时做无表结构原始元组抽取。 - 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]
此命令自动执行:
- 导出所有数据库的所有表(含 LOB/TOAST 数据)
- 包含已删除的数据行
- 恢复 global/ 目录下的共享系统表
- 扫描并导出孤立文件(DROP/TRUNCATE 的表)
- 系统目录损坏时自动兜底恢复
输出目录结构:
/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
原因:数据库名拼写错误,或数据目录路径不正确。
解决:
- 确认数据目录路径正确
- 使用
databases命令查看可用数据库 - 使用 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 表文件缺失或损坏。可能原因:
- TOAST 表文件被删除
- TOAST 表数据文件损坏
- reltoastrelid 在 pg_class 中不可读
解决 :使用 recover-directory 命令进行最大恢复,它会尝试所有可能的恢复路径。若 TOAST 文件已物理丢失,则该 LOB 字段无法恢复,但其他字段与其他行不受影响。
问题 9:恢复出的数据显示 <COMPRESSED>
原因:该值使用了内联压缩(非 TOAST 压缩),FGOGDU 目前不支持内联压缩的解压。通常发生在较老的 PostgreSQL 版本中。
解决:此类数据暂无法通过 FGOGDU 解压恢复,可尝试使用其他专业工具。
问题 10:恢复行数少于预期
可能原因:
- 部分数据页损坏(坏块),被自动跳过
- 部分数据行已被物理覆盖(DELETE 后被新数据覆盖)
- 表存在分区,未恢复到所有分区文件
- 使用了
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 信息部分损坏。
解决:
- 使用
page命令查看元组的natts(实际列数) - 根据业务知识手动编写模式文件
- 使用
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 文件时报语法错误
可能原因:
- 恢复的数据中包含特殊字符(如单引号未正确转义)
- 表结构与目标库不兼容(如类型差异)
- 恢复过程中部分行部分列解码失败
排查:
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 故障排查通用流程
当恢复结果与预期不符时,建议按以下流程排查:
- 确认数据目录路径 :
ls /opengauss/data,应看到 base/、global/、pg_control 等。 - 查看可用数据库 :
./fgogdu databases <datadir>,确认目标数据库存在。 - 查看表列表 :
./fgogdu tables <datadir> <db>,确认目标表存在且列数正确。 - 诊断数据页 :
./fgogdu page <file> 0,查看首页结构与元组状态。 - 使用 verbose + max 模式恢复 :
./fgogdu recover ... --max -v,查看详细日志与跳过的坏块。 - 对比行数:统计恢复的 INSERT 行数,与源库(若可读)对比。
- 兜底恢复 :若以上均不理想,使用
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)内部工具,仅供内部数据恢复与应急演练使用。
作者:风哥