金仓KingBase数据库恢复工具FGKDU(FGEDU KingBase DUL)

金仓KingBase数据库恢复工具FGKDU(FGEDU KingBase DUL)

FGKDU(全称 FGEDU KingBase DUL,Data UnLoader)是一款专门面向人大金仓 KingBase 数据库的数据抽取与恢复工具,当数据库实例已经无法正常启动、传统逻辑备份与导出工具(如 pg_dumpkingbase_dumpsys_dump)全部失效时,仍然能够绕过数据库引擎,直接从底层物理数据文件中解析并抽取数据,把业务数据以可识别的格式导出,用于在新环境中重建数据库。


目录

  1. 程序介绍
  2. 程序功能与特性
  3. 支持环境
  4. 程序使用
  5. 程序各种案例场景与操作过程
  6. 常用问题与排查
  7. 作者信息

1. 程序介绍

1.1 项目概述

FGKDU(全称 FGEDU KingBase DUL,Data UnLoader)是一款专门面向人大金仓 KingBase 数据库的数据抽取与恢复工具,当数据库实例已经无法正常启动、传统逻辑备份与导出工具(如 pg_dumpkingbase_dumpsys_dump)全部失效时,仍然能够绕过数据库引擎,直接从底层物理数据文件中解析并抽取数据,把业务数据以可识别的格式导出,用于在新环境中重建数据库。

KingBase 是人大金仓基于 PostgreSQL 内核自主研发的关系型数据库。其数据页面格式、系统目录(pg_class、pg_attribute、pg_database 等)结构、TOAST 大字段存储机制、WAL(Write-Ahead Log)日志格式均与 PostgreSQL 保持兼容。版本对应关系如下:

KingBase 版本 底层 PostgreSQL 内核 说明
KingBase V6 PostgreSQL 8.x 早期版本
KingBase V7 PostgreSQL 9.x 广泛使用
KingBase V8 PostgreSQL 12 主流版本
KingBase V8R2/R3/R4/R6 PostgreSQL 12 衍生 企业级发行
KingBase V9 PostgreSQL 14 / 15 最新版本

FGKDU 正是基于上述兼容性,直接读取 KingBase 数据目录(PGDATA)下的物理数据文件,按照 PostgreSQL 页面格式(8KB 数据块)逐页解析,提取元组数据,最终输出为 SQL、DMP、CSV、TXT、BINARY 等多种格式。整个恢复过程完全脱离数据库实例,不依赖数据库在线状态,也不依赖任何 KingBase 客户端库。

1.2 适用场景

FGKDU 主要用于以下数据库灾难恢复场景:

  • 控制文件损坏或丢失:pg_control 文件物理损坏、校验和错误、魔数不匹配,导致数据库无法读取控制信息。
  • 数据文件物理损坏:磁盘坏道、RAID 阵列故障、存储设备异常导致部分数据文件读取失败。
  • 系统目录损坏:pg_class、pg_attribute、pg_database 等核心系统表损坏,无法定位用户表对象。
  • 参数文件丢失或错误:kingbase.conf 配置文件丢失或参数错误导致实例无法启动。
  • 误操作删除数据:DELETE 误删行、DROP TABLE 误删表、TRUNCATE 误清空表数据。
  • 数据库升级失败:版本升级过程中断、数据字典不兼容导致无法打开。
  • 文件系统故障:部分文件损坏、inode 错误、文件系统不一致。
  • VACUUM FULL 后数据丢失:维护操作异常导致数据意外丢失。
  • 主机意外断电:异常关机后数据库无法启动,需要紧急抽取业务数据。

1.3 工作原理

FGKDU 的工作流程可以概括为"直接读取物理文件 → 解析页面格式 → 提取元组数据 → 解码列值 → 写入输出文件"五个阶段,具体如下:

  1. 数据目录识别:读取 PG_VERSION 文件识别 KingBase 版本,读取 pg_control 检测数据块大小(自动识别 8KB/16KB/32KB)。
  2. 系统目录解析:解析 pg_database(数据库列表)、pg_class(表对象列表)、pg_attribute(列定义)等系统表,建立 OID 到表名、列类型的映射关系。
  3. 页面扫描:按照 8KB 页面格式逐块读取数据文件(路径为 PGDATA/base/{db_oid}/{relfilenode}),解析页面头(PageHeaderData:pd_lower/pd_upper/pd_special/pd_pagesize_version)。
  4. 元组提取:遍历页面中的项指针数组(ItemId),定位每个堆元组(HeapTuple),解析元组头(HeapTupleHeaderData:t_xmin/t_xmax/t_infomask),判断元组的可见性与删除状态。
  5. 列值解码:按照 pg_attribute 中的列类型定义,逐列解码数据值,支持整数、浮点、字符、日期时间、BYTEA(二进制大对象)、TEXT/CLOB、JSONB、NUMERIC 等全部常见类型。
  6. 输出写入:将解码后的行数据按照指定格式(SQL INSERT 语句、DMP 二进制、CSV、TXT)写入输出文件,同时生成恢复报告。

对于损坏页面,FGKDU 会启用增强恢复引擎:跳过无法解析的坏块,对坏块启用激进原始扫描(Aggressive Raw Scan)逐字节寻找有效的元组头特征码,最大程度从损坏文件中恢复数据。

1.4 与传统工具的对比

对比项 FGKDU pg_dump / kingbase_dump 物理备份恢复
是否需要数据库在线
是否需要完整控制文件
能否恢复已删除数据 是(DELETE/DROP/TRUNCATE)
能否处理损坏文件 是(自适应扫描)
输出格式 SQL/DMP/CSV/TXT/BINARY SQL/自定义 物理文件
部署方式 单文件零依赖 需安装客户端 需完整实例
恢复粒度 用户/Schema/表/文件级 库/表级 全库级

关于作者

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

如果您在使用过程中遇到问题、需要商业技术支持、或希望参与贡献,欢迎通过上方联系方式与作者取得联系。

2. 程序功能与特性

2.1 核心特性概览

FGKDU 围绕"灾难场景下的最大化数据恢复"这一核心目标设计,具备以下核心特性:

2.1.1 免依赖单文件可执行

采用完全静态链接编译,生成单个约 1.1MB 的可执行文件,零运行时依赖。无论是 Linux 还是 Windows 平台,编译产物拷贝到目标服务器即可直接运行,无需安装任何动态库、运行时环境或 KingBase 客户端。这极大简化了灾难恢复场景下的部署工作——运维人员只需通过 U 盘、scp 或网络传输单个文件,即可在任何目标机器上启动恢复。

  • Linux:完全静态链接(glibc-static),ldd 检查显示"not a dynamic executable"。
  • Windows:静态链接 libgcc,生成的 fgkdu.exe 不依赖任何 DLL,可在干净的 Windows 系统直接运行。

2.1.2 多平台原生支持

原生支持主流 Linux 发行版与 Windows 操作系统,一套源码跨平台编译:

  • Linux:RHEL 5/6/7/8/9/10、Oracle Enterprise Linux(OEL)、CentOS、麒麟(Kylin/NeoKylin)、欧拉(EulerOS/openEuler)、统信 UOS、Ubuntu 12.04-24.04、SUSE/openSUSE、Debian,以及任何内核 2.6.32+ 的 Linux x86_64 系统。
  • Windows:Windows 7/8/10/11、Windows Server 2008 R2 - 2022,内置完整的 POSIX 兼容层(kb_wincompat.h),提供目录操作、文件 I/O、信号处理、时间函数、getopt_long 等跨平台支持。

2.1.3 多版本兼容

支持 KingBase V6 到 V9 全系列版本,底层覆盖 PostgreSQL 8.x 到 15.x 内核:

  • 自动从 PG_VERSION 文件识别 KingBase 大版本。
  • 自动从 pg_control 文件识别 PostgreSQL 页面版本(pd_pagesize_version 字段)。
  • 兼容 PG 9.2 - 15 的页面格式差异(页头结构、pd_prune_xid 字段等)。
  • 兼容多版本系统目录结构变化。

2.1.4 自动块大小检测

从 pg_control 控制文件自动检测数据块大小,支持 8KB(默认)、16KB、32KB 等配置。当 pg_control 不可用时,自动回退到 KingBase 默认的 8192 字节(8KB),并输出警告提示。无需用户手动指定块大小参数。

2.1.5 多种恢复模式

针对不同灾难场景,提供五种恢复命令:

  • scan 全量扫描导出:通过系统目录正常解析,导出所有有效数据行,适用于数据目录健康或轻微损坏场景。
  • recover delete:扫描元组的 t_xmax 事务标记,恢复被 DELETE 误删的行,适用于未执行 VACUUM 的误删除恢复。
  • recover drop:扫描孤立的 relfilenode 文件,恢复被 DROP TABLE 删除的表数据,适用于误删表场景。
  • recover truncate:检测 relfilenode 变更,恢复被 TRUNCATE 截断的旧文件数据。
  • recover max:忽略系统目录,直接扫描所有数据文件进行最大化恢复,是系统目录严重损坏时的终极手段。

2.1.6 强大恢复引擎(v1.0 新增)

v1.0 引入了多层级的增强恢复引擎,在所有恢复场景中最大化数据恢复量:

  • 激进原始扫描(Aggressive Raw Scan):不依赖页头和项指针,逐字节扫描整个数据文件,寻找有效的元组头模式。适用于页头严重损坏、项指针区域损坏、数据文件被部分覆盖的场景。
  • 空闲空间扫描(Free Space Scan):扫描每个页面的空闲空间区域(pd_lower 和 pd_upper 之间),寻找尚未被 VACUUM 清理的已删除元组数据。适用于 DELETE 后未执行 VACUUM 的恢复。
  • WAL 日志恢复(WAL Recovery):扫描 pg_wal/ 目录下的 WAL 日志文件,从日志记录中提取已被 VACUUM 清理的历史数据。适用于主数据文件已无痕迹但 WAL 日志完好的恢复。
  • 多级回退恢复(Fallback Recovery):按照恢复策略优先级自动级联执行:第一级正常扫描 → 第二级激进原始扫描(损坏率超 30%)→ 第三级空闲空间扫描 → 第四级激进原始扫描 → 第五级 WAL 日志恢复,最大化数据恢复量。
  • LOB/TOAST 恢复:大字段指针解码,保留原始大小、关联 TOAST 表 OID 等元信息。

2.1.7 LOB 大字段默认导出

默认支持所有大字段类型的导出,无需额外参数:

  • 内联 LOB(小于 2KB):直接完整输出。BYTEA 输出为 \x... 十六进制格式,TEXT/CLOB 输出实际文本,JSONB 输出 JSON 文本,均可直接导入新库无语法错误。
  • TOAST 外部化 LOB(大于 2KB):输出有效占位值加 SQL 注释元数据,包括 relid(关联 TOAST 表 OID)、valueid(chunk ID)、rawsize(原始大小)、compressed(是否压缩)。注释格式示例:NULL /* LOB BYTEA TOAST rel=28912 val=415 size=24576000 compressed=Y - manual recovery */,可直接导入不报语法错误,后续可基于元信息人工恢复完整大字段。

2.1.8 损坏容错机制

内置自适应损坏恢复扫描器,确保面对严重损坏的数据文件也不会崩溃:

  • 页面安全验证:读取每个页面前验证 pd_lower >= 24(页头最小大小)、pd_upper <= page_size、pd_lower < pd_upper、检测全零页(完全损坏)、验证项指针指向有效区域。
  • 坏块跳过:自动跳过损坏的页面头,从正常页面继续恢复。
  • 边界检查:所有内存访问前进行边界检查。
  • 信号保护:捕获 SIGSEGV/SIGBUS/SIGABRT/SIGFPE 信号(Windows 额外支持 SIGBREAK),防止程序崩溃,确保恢复过程不中断。
  • 继续执行:使用 --continue-on-error 选项,遇到错误时继续恢复而非退出。

2.1.9 多输出格式

支持五种输出格式,满足不同恢复与迁移需求:

格式 说明 适用场景
SQL(默认) 生成可执行的 INSERT 语句,含 CREATE TABLE 与注释 直接导入新库
DMP 二进制归档文件,每个表一个文件 跨库迁移、归档
CSV 逗号分隔文本 Excel 查看、数据分析
TXT 纯文本 简单查看
BINARY 原始二进制 底层归档

2.1.10 精细粒度恢复

支持三级粒度精确定位恢复对象:

  • 按用户/数据库-u):仅恢复指定用户或数据库的所有数据。
  • 按 Schema-s):仅恢复指定模式下的所有表。
  • 按单表-t):仅恢复指定表,支持 schema.table 格式。
  • 三者可组合使用,如 -u mydb -s public -t orders 精确到单库单模式单表。

2.1.11 稳定性加固

全面的稳定性保障措施:

  • 全面的边界检查与错误处理。
  • 页面安全验证防止崩溃。
  • 信号保护机制。
  • 多段文件(relfilenode.1、relfilenode.2)自动处理。
  • 实时进度显示与详细日志输出。

2.2 功能特性详细说明

数据类型支持

FGKDU 支持全部 KingBase/PostgreSQL 常见数据类型的解码:

类型分类 支持类型
整数类型 int2(smallint)、int4(integer)、int8(bigint)、serial、bigserial
浮点类型 float4(real)、float8(double precision)
精确数值 numeric/decimal(含高精度)
字符类型 char、varchar、text、bpchar
二进制 bytea(含内联与 TOAST)
日期时间 date、time、timestamp、timestamptz、interval
布尔 boolean
UUID uuid
JSON json、jsonb
网络地址 inet、cidr、macaddr
位串 bit、varbit
大对象 TEXT/CLOB、BYTEA(含 TOAST)

输出目录结构

scan 与 unload 命令会自动按数据库/模式组织输出目录,便于按库恢复:

output/
├── testdb/                          # testdb 数据库
│   ├── public/                      # public 模式
│   │   ├── customers.sql            # 各表数据
│   │   └── orders.sql
│   └── hr/                          # hr 模式
│       └── employees.sql
├── business_db/                     # business_db 数据库
│   └── public/
│       └── ...
├── fgkdu_recovery_report.txt        # 恢复报告
└── import_all.sh                    # 一键导入脚本

恢复报告

每次恢复操作完成后,FGKDU 会自动生成恢复报告,包含:

  • 数据库/模式/表的处理数量。
  • 总行数提取统计。
  • 坏块数量与占比。
  • raw scan 恢复的元组数。
  • 各恢复策略(正常扫描/空闲空间/WAL)的贡献统计。
  • 数据完整性统计。
  • 输出目录与日志路径。

实时进度显示

在 unload 等长耗时操作中,FGKDU 提供详细的实时进度显示:

  • 当前处理的数据库 OID 与名称。
  • 当前处理的表名与 OID。
  • 每表导出行数与总计行数。
  • 已扫描文件数与总文件数。
  • 实时扫描进度百分比。
  • 吞吐量统计(行/秒)。

3. 支持环境

3.1 支持的操作系统

Linux 平台

操作系统 支持版本
Red Hat Enterprise Linux(RHEL) 5 / 6 / 7 / 8 / 9 / 10
Oracle Enterprise Linux(OEL) 5 / 6 / 7 / 8 / 9 / 10
CentOS 5 / 6 / 7 / 8 / 9
麒麟(Kylin / NeoKylin) 全系列
欧拉(EulerOS / openEuler) 全系列
统信 UOS 全系列
Ubuntu 12.04 - 24.04
SUSE / openSUSE 全系列
Debian 全系列
通用 Linux x86_64 内核 2.6.32 及以上

Windows 平台

操作系统 支持版本
Windows 桌面 7 / 8 / 10 / 11(64 位)
Windows Server 2008 R2 / 2012 / 2016 / 2019 / 2022

3.2 支持的 KingBase 版本

KingBase 版本 底层 PostgreSQL 内核 支持状态
KingBase V6 PostgreSQL 8.x 支持
KingBase V7 PostgreSQL 9.x 支持
KingBase V8 PostgreSQL 12 支持
KingBase V8R2 PostgreSQL 12 衍生 支持
KingBase V8R3 PostgreSQL 12 衍生 支持
KingBase V8R4 PostgreSQL 12 衍生 支持
KingBase V8R6 PostgreSQL 12 衍生 支持
KingBase V9 PostgreSQL 14 / 15 支持

底层覆盖 PostgreSQL 8.x - 15.x 全系列内核。

3.3 编译要求

Linux 编译环境

  • 编译器:GCC 4.8 及以上(推荐 GCC 7+)。
  • 静态链接依赖:glibc-static(完全静态构建需要)、libstdc++-static。
  • 构建工具:make。
  • 操作系统:Linux x86_64,内核 2.6.32 及以上。

各发行版依赖安装命令:

# RHEL / OEL / CentOS 系列
yum install -y gcc glibc-static libstdc++-static make

# Ubuntu / Debian 系列
apt-get update
apt-get install -y gcc libc6-dev make

# SUSE / openSUSE 系列
zypper install -y gcc glibc-devel-static make

# 欧拉 / openEuler
dnf install -y gcc glibc-static make

Windows 编译环境

  • 方式一(推荐):MinGW-w64,生成原生无依赖 exe。
  • 方式二:Microsoft Visual Studio 2019/2022(通过 CMake)。
  • 跨平台构建:CMake 3.5 及以上。

3.4 运行环境要求

  • 目标服务器操作系统:见上文支持列表。
  • 磁盘空间:输出目录空间至少为数据目录大小的 1.5 倍(SQL 格式约为原始数据的 1.5 倍)。
  • 内存:无特殊要求,默认配置即可(大库恢复建议 1GB 以上可用内存)。
  • 权限:对 KingBase 数据目录具备读权限(建议以 kingbase 用户或 root 运行)。
  • 依赖:零运行时依赖(完全静态二进制)。

4. 程序使用

4.1 编译与部署

4.1.1 Linux 平台编译

# 进入项目源码目录
cd /path/to/FGKDU

# 查看所有构建目标
make help

# 推荐:完全静态单文件构建(零依赖,可拷贝到任何 Linux 系统运行)
make standalone

# 如果完全静态构建失败(缺少 glibc-static),使用便携版构建
make portable

编译成功后生成 build/standalone/fgkdu 可执行文件(约 1.1MB)。

4.1.2 Windows 平台编译

方式一:MinGW-w64(推荐)

:: 使用构建脚本(最简单)
build_win.bat

:: 或手动执行编译命令
gcc -std=gnu99 -O2 -Wall -Iinclude -D_WIN32 -D_CRT_SECURE_NO_WARNINGS ^
    src\main.c src\cli\kb_cli.c src\io\kb_io.c src\page\kb_page.c ^
    src\tuple\kb_tuple.c src\dbdict\kb_dbdict.c src\scan\kb_scan.c ^
    src\output\kb_output.c src\utils\kb_utils.c src\utils\kb_getopt.c ^
    src\version\kb_version.c ^
    -o fgkdu.exe -static -static-libgcc -lm -s

方式二:CMake + MSVC

mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release

方式三:CMake + MinGW

mkdir build
cd build
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release

编译完成后生成 fgkdu.exe,拷贝到任何 Windows 系统即可运行,无需安装任何运行时库。

4.1.3 部署到目标服务器

# 拷贝到目标服务器(Linux)
scp build/standalone/fgkdu kingbase@target-host:/tmp/

# 设置执行权限
ssh kingbase@target-host "chmod +x /tmp/fgkdu"

# 建议部署到 /usr/local/bin 以便全局调用
sudo cp build/standalone/fgkdu /usr/local/bin/
sudo chmod 755 /usr/local/bin/fgkdu

Windows 部署:将 fgkdu.exe 拷贝到任意目录(如 D:\tools\),可选加入系统 PATH。

4.1.4 安装验证

# 1. 验证版本号
fgkdu -V
# 预期输出:
# FGKDU - FGEDU KingBase DUL v1.0.0
# Version: 1.0.0 (Major: 1, Minor: 0, Patch: 0)
# Build mode: standalone static
# Author: 风哥 (QQ:113257174, WX:itpux-com)

# 2. 验证帮助信息
fgkdu -h

# 3. 验证零动态依赖(Linux)
ldd /usr/local/bin/fgkdu
# 预期输出: not a dynamic executable(不是动态可执行文件)

4.2 命令一览

命令 说明
diagnose 诊断数据目录,检查完整性与损坏程度
list databases 列出所有数据库
list schemas 列出所有模式
list tables 列出所有表
scan 扫描导出所有表数据(全量导出)
recover delete 恢复 DELETE 删除的数据行
recover drop 恢复 DROP 删除的表数据
recover truncate 恢复 TRUNCATE 截断的表数据
recover max 最大恢复(忽略系统目录,扫描所有数据文件)
unload 全库按用户名/数据库名导出(按库分目录)
scan-file <path> 直接扫描单个数据文件(底层恢复)

4.3 选项说明

选项 说明
-d, --data-dir PATH KingBase 数据目录路径
-o, --output-dir PATH 输出目录路径
-f, --format FORMAT 输出格式:sql、csv、txt、dmp、binary
-u, --user NAME 用户名/数据库名(按库过滤)
-D, --database NAME 数据库名(-u 的别名)
-s, --schema SCHEMA 模式名(按模式过滤)
-t, --table TABLE 表名(支持 schema.table 格式)
--include-deleted 包含已删除行
--include-updated 包含已更新行
-v, --verbose 详细输出日志
--progress 显示进度
--continue-on-error 出错继续执行
-V, --version 显示版本信息
-h, --help 显示帮助信息

4.4 命令详解

4.4.1 diagnose 诊断命令

对 KingBase 数据目录进行全面健康检查,是所有恢复操作的第一步。诊断结果会指出数据目录的完好程度、可用恢复策略,为后续操作提供决策依据。

诊断检查项:

  1. 数据目录存在性与权限检查。
  2. PG_VERSION 文件读取与版本识别。
  3. pg_control 控制文件状态(魔数、版本、校验和、块大小)。
  4. 关键子目录结构(base/、global/、pg_wal/、pg_tblspc/)。
  5. 系统目录可读性(pg_database、pg_class、pg_attribute)。
  6. 数据块大小自动检测。
  7. 典型数据文件完整性抽样检查。
  8. 文件权限检查。
# 基本诊断
fgkdu diagnose -d /opt/kingbase/data

# 详细诊断(含每个文件的可读性统计)
fgkdu diagnose -d /opt/kingbase/data -v

4.4.2 list 列出对象命令

# 列出所有数据库
fgkdu list databases -d /opt/kingbase/data

# 列出所有模式
fgkdu list schemas -d /opt/kingbase/data

# 列出所有表
fgkdu list tables -d /opt/kingbase/data

# 列出指定数据库的表
fgkdu list tables -d /opt/kingbase/data -u testdb

# 列出指定模式的表
fgkdu list tables -d /opt/kingbase/data -s public

4.4.3 scan 全量扫描导出

通过系统目录正常解析,扫描并导出所有(或指定)表的有效数据行。适用于数据目录健康或轻微损坏场景。

# 导出所有表为 SQL(默认格式)
fgkdu scan -d /opt/kingbase/data -o ./output

# 导出为 DMP 格式(每表一个文件)
fgkdu scan -d /opt/kingbase/data -o ./output -f dmp

# 导出为 CSV 格式
fgkdu scan -d /opt/kingbase/data -o ./output -f csv

# 按数据库过滤导出
fgkdu scan -d /opt/kingbase/data -u testdb -o ./output

# 按模式过滤导出
fgkdu scan -d /opt/kingbase/data -s public -o ./output

# 按单表导出
fgkdu scan -d /opt/kingbase/data -t public.orders -o ./output

# 遇到错误继续
fgkdu scan -d /opt/kingbase/data -o ./output --continue-on-error -v

4.4.4 recover delete 恢复已删除行

恢复被 DELETE 语句误删除的数据行。利用 KingBase/PostgreSQL 的 MVCC 机制:DELETE 操作不会物理删除元组,仅设置 t_xmax 事务号标记删除,在 VACUUM 之前被删除的行仍然完整存在于数据页面中。

# 恢复所有已删除数据
fgkdu recover delete -d /opt/kingbase/data -o ./recovered

# 恢复指定表的已删除数据
fgkdu recover delete -d /opt/kingbase/data -t public.orders -o ./recovered

# 恢复指定用户/schema 的已删除数据
fgkdu recover delete -d /opt/kingbase/data -u system -s public -o ./recovered

恢复原理:扫描每个数据页面的所有元组 → 检查元组头的 t_xmax 字段(非 0 表示被标记删除)→ 检查 t_infomask 标志位区分删除/更新 → 解码被删除元组的数据列输出 INSERT 语句 → 同时启用空闲空间扫描与 WAL 日志恢复。

4.4.5 recover drop 恢复已删除表

恢复被 DROP TABLE 语句删除的表数据。DROP TABLE 会从 pg_class/pg_attribute 中删除表定义,但数据文件(relfilenode)可能仍存在于磁盘上成为孤立文件。

# 恢复所有 DROP 的表数据
fgkdu recover drop -d /opt/kingbase/data -o ./recovered

恢复原理:扫描 base/{db_oid}/ 目录下所有数字命名文件 → 与 pg_class 已知表 OID 匹配 → 找出孤立 relfilenode 文件 → 对每个孤立文件尝试多种策略解析 → 列名恢复为 col1..colN,类型做最佳猜测。

4.4.6 recover truncate 恢复已截断表

恢复被 TRUNCATE TABLE 语句清空的数据。TRUNCATE 创建新的空 relfilenode 文件替换旧文件,旧文件不会立即被物理删除。

# 恢复 TRUNCATE 的表数据
fgkdu recover truncate -d /opt/kingbase/data -o ./recovered

4.4.7 recover max 最大恢复

当系统目录严重损坏时,FGKDU 直接扫描 base/ 目录下的所有数据文件,不依赖任何目录信息,实现最大程度的数据恢复。这是最后的恢复手段,自动启用多级回退恢复策略。

# 最大恢复(忽略系统目录,扫描所有数据文件)
fgkdu recover max -d /opt/kingbase/data -o ./recovered

# 遇到错误继续,详细日志
fgkdu recover max -d /opt/kingbase/data -o ./recovered --continue-on-error -v

4.4.8 unload 全库按用户名导出

当数据库无法启动时,全库抽取所有数据,并按用户名/数据库名自动生成子目录,导出所有能导出的表。与 recover max 不同,unload 会按数据库分目录组织输出,结构更清晰,便于按库恢复。

# 全库 unload:按数据库名自动分目录导出所有表
fgkdu unload -d /opt/kingbase/data -o /tmp/unload_output

# 按用户名/数据库名 unload:仅导出指定数据库的所有表
fgkdu unload -d /opt/kingbase/data -u fgedu -o /tmp/unload_output

# 指定输出格式(默认 sql,支持 csv/txt/dmp/binary)
fgkdu unload -d /opt/kingbase/data -o /tmp/unload_output -f dmp

# 遇到错误继续(推荐,损坏场景必备)
fgkdu unload -d /opt/kingbase/data -o /tmp/unload_output --continue-on-error -v

输出目录结构:

/tmp/unload_output/
├── fgedudb/                          # fgedudb 数据库
│   ├── 16468_recovered.sql           # 各表数据(按 relfilenode 命名)
│   └── 16481_recovered.sql
├── postgres/                         # postgres 数据库
│   └── *_recovered.sql
├── template1/                        # template1 数据库
│   └── *_recovered.sql
└── _global/                          # 全局共享系统表(pg_database 等)
    └── *_recovered.sql

工作原理:

  1. 扫描 base/ 目录下的每个数据库 OID 子目录。
  2. 尝试从系统目录 pg_database 解析数据库名(best effort)。
  3. 系统目录可读时:子目录名为数据库名(如 fgedudb)。
  4. 系统目录损坏时:子目录名回退为 oid_<OID>(如 oid_16384),仍可正常导出。
  5. 对每个数据库目录下的数据文件逐个扫描,导出可恢复的行。
  6. 同时扫描 global/ 目录的共享系统表,输出到 _global/ 子目录。
  7. 若指定 -u,仅处理匹配的数据库。

4.4.9 scan-file 直接扫描文件

直接扫描指定的单个数据文件,是最底层的恢复方式。当知道具体哪个文件包含需要的数据时使用。

# 直接扫描单个数据文件
fgkdu scan-file /opt/kingbase/data/base/16384/16521 -o ./recovered

# 指定输出格式
fgkdu scan-file /opt/kingbase/data/base/16384/16521 -o ./recovered -f dmp

scan-file 命令会自动在正常扫描失败后启用激进原始扫描,从损坏文件中尽力恢复数据。

4.5 输出格式说明

4.5.1 SQL 格式(默认)

生成可直接执行的 SQL 文件,包含 CREATE TABLE 语句(如果目录可用)、INSERT 语句、恢复报告与恢复指南。是最推荐的恢复格式,可直接导入新库。

4.5.2 DMP 格式(二进制)

生成二进制 DMP 文件,每个表一个文件。包含文件头(魔数、版本、表信息)、行数据(二进制格式)、文件尾。适合跨库迁移与归档。

4.5.3 CSV 格式

生成 CSV 文件,适合用 Excel 等表格工具查看,也便于数据分析与处理。

4.5.4 TXT 格式

生成纯文本格式,便于简单查看。

4.5.5 BINARY 格式

生成原始二进制格式,适合底层归档。

4.6 高级用法

4.6.1 块大小自动检测

FGKDU 自动从 pg_control 文件中检测块大小。如果 pg_control 不可用,会使用默认的 8192 字节(KingBase 默认块大小),并输出警告。

4.6.2 多段文件支持

KingBase 大表会分段存储(relfilenode.1、relfilenode.2 等),FGKDU 自动处理多段文件,无需用户干预。

4.6.3 配置文件使用

FGKDU 支持简单的配置文件:

# fgkdu.conf
data_dir=/opt/kingbase/data
output_dir=./output
format=sql
fgkdu scan --config fgkdu.conf

4.6.4 详细日志与进度

# 启用详细输出
fgkdu scan -d /opt/kingbase/data -o ./output -v

# 显示进度
fgkdu scan -d /opt/kingbase/data -o ./output --progress

# 日志会显示每个文件的处理状态、坏块信息、恢复统计等

5. 程序各种案例场景与操作过程

5.1 案例一:金仓KingBase数据库无法启动(控制文件损坏)完整恢复

场景描述:服务器意外断电后 KingBase 无法启动,日志提示 "pg_control corrupted"、"invalid page header"。控制文件损坏导致数据库无法读取控制信息,但用户数据文件大概率完好。

恢复思路:先诊断,后尝试常规扫描,若系统目录损坏则启用最大恢复。

操作步骤

# 步骤 0:紧急备份整个数据目录(先做备份再任何操作)
cp -a /opt/kingbase/data /data/backup/data_backup_20260808/

# 步骤 1:诊断数据目录,确认损坏范围
fgkdu diagnose -d /opt/kingbase/data -v
# 预期输出:
#   [WARN] WARNING: pg_control corrupted: invalid checksum
#   [OK  ] base/ directory: OK (2 databases found)
#   [ERR ] pg_class: partial - 89/100 blocks readable
#   === Diagnostics Complete: 11% corrupted ===

# 步骤 2:先尝试常规 scan(带 continue-on-error)
fgkdu scan -d /opt/kingbase/data -o ./output --continue-on-error -v
# 如果输出目录中有大量 .sql 文件并且行数正常,则完成
# 如果 scan 退出码非 0 或输出文件极少,进入步骤 3

# 步骤 3:常规扫描失败,用最大恢复 recover max
fgkdu recover max -d /opt/kingbase/data -o ./output_max --continue-on-error -v
# 预期输出:
#   Files scanned:     124
#   Rows recovered:    508,231
#   Bad blocks:        10
#   === MAX Recovery Complete ===

# 步骤 4:验证恢复结果
ls -lh ./output_max/        # 检查输出文件数
wc -l ./output_max/*.sql    # 统计行数
head -50 ./output_max/schema_table.sql  # 查看恢复结果

Windows 等价命令

fgkdu.exe diagnose -d D:\kingbase\data
fgkdu.exe scan -d D:\kingbase\data -o .\output --continue-on-error
fgkdu.exe recover max -d D:\kingbase\data -o .\output_max

验证方法

ls -lh ./output_max/        # 检查输出文件数
wc -l ./output_max/*.sql    # 统计行数
head -50 ./output_max/*.sql # 查看恢复结果

5.2 案例二:金仓KingBase误 DELETE 恢复误删除行

场景描述:开发人员误执行 DELETE FROM public.orders WHERE status='CANCELLED' 删除了 2280 行订单数据,尚未执行 VACUUM,需要立即恢复。

恢复思路:利用 t_xmax 事务标记恢复未 VACUUM 的已删除行。

操作步骤

# 步骤 1:立即停止数据库写入(防止 VACUUM 清理已删除行)
# 在数据库层面停止相关业务写入

# 步骤 2:执行误删除行恢复(针对指定表)
fgkdu recover delete -d /opt/kingbase/data \
    -u testdb -s public -t orders \
    -o ./recovered_orders -v

# 预期输出:
# [INFO] Recover DELETE rows starting...
# [INFO] Strategy: t_xmax scan + free space scan + WAL fallback
# [INFO] Scanning public.orders (16450)...
#   [SCAN] Normal scan: found 1,580 deleted rows via t_xmax
#   [FREE SPACE] Free space area scan: found 642 additional rows
#   [WAL] WAL recovery: 58 rows recovered
#   [TOTAL] public.orders: 2280 rows recovered
# === RECOVER DELETE COMPLETE ===
# Total deleted rows recovered: 2,280

# 步骤 3:验证恢复结果
grep -c '^INSERT INTO' ./recovered_orders/orders_deleted.sql
# 预期:2280

head -20 ./recovered_orders/orders_deleted.sql
# 查看恢复的 INSERT 语句

# 步骤 4:导入新库验证
ksql -U system -d newdb -f ./recovered_orders/orders_deleted.sql
SELECT count(*) FROM public.orders;  -- 验证行数

5.3 案例三:金仓KingBase误 DROP TABLE 恢复被删表

场景描述:运维误执行 DROP TABLE public.old_transactions 删除了一张重要历史表,需要恢复。

恢复思路:DROP TABLE 删除了系统目录定义,但数据文件(孤立 relfilenode)仍存在于磁盘,扫描孤立文件恢复。

操作步骤

# 步骤 1:尽快停止数据库写入,防止磁盘块被重用

# 步骤 2:执行 DROP TABLE 恢复
fgkdu recover drop -d /opt/kingbase/data -o ./recovered_drop -v
# 预期输出:
# [INFO] Detected 16 orphan candidate files
# [ORPHAN] File base/16384/16800 (256 MB): valid page headers found
#   [ANALYZE] 42 columns detected
#   [RECOVER] orphan_16800: 52,340 rows extracted
# === RECOVER DROP COMPLETE ===
# Total rows recovered from dropped tables: 2,012,987

# 步骤 3:查看恢复的文件
ls -lhS ./recovered_drop/
# 预期:按大小排序的 SQL 文件

# 步骤 4:查看恢复报告,了解每个孤立文件的推断信息
cat ./recovered_drop/fgkdu_drop_recovery_report.txt

# 步骤 5:抽样查看恢复的数据
head -30 ./recovered_drop/dropped_table_16800.sql
# 注意:列名恢复为 col1..colN,需人工根据业务知识重命名

注意:恢复的表列名为 col1..colN,需要人工根据业务知识重命名列。

5.4 案例四:金仓KingBase误 TRUNCATE 恢复被截断数据

场景描述:运维误执行 TRUNCATE TABLE public.audit_log 清空了审计日志表,需要恢复。

恢复思路:TRUNCATE 创建新的空 relfilenode 替换旧文件,旧文件可能仍存在,扫描旧文件恢复。

操作步骤

# 步骤 1:执行 TRUNCATE 恢复
fgkdu recover truncate -d /opt/kingbase/data -o ./recovered_truncate -v

# 步骤 2:查看恢复结果
ls -lh ./recovered_truncate/
cat ./recovered_truncate/*.sql | head -50

# 步骤 3:导入新库验证
ksql -U system -d newdb -f ./recovered_truncate/*.sql

5.5 案例五:金仓KingBase按指定用户(数据库)导出全部数据

场景描述:需要把 system 用户(数据库名 sales)中的所有数据迁移到新服务器。

操作步骤

# 步骤 1:列出所有数据库,确认目标数据库 OID
fgkdu list databases -d /opt/kingbase/data
# 输出:
#   OID      NAME
#   1        template1
#   16384    sales        <-- 目标库

# 步骤 2:按数据库(-u)导出全部数据为 SQL
fgkdu scan -d /opt/kingbase/data -u sales -o ./sales_export -f sql

# 步骤 3:同时导出为 DMP(每表一个二进制文件)
fgkdu scan -d /opt/kingbase/data -u sales -o ./sales_export_dmp -f dmp

# 步骤 4:查看被恢复的表
ls -1 ./sales_export/ | head -20
# public_orders.sql
# public_customers.sql
# public_products.sql

# 步骤 5:在新库中导入
ksql -U system -d sales_new -f ./sales_export/*.sql

注意-u 参数同时接受 KingBase 用户名与数据库名(因为 KingBase 常以同名数据库+用户工作)。

5.6 案例六:金仓KingBase按指定 Schema 导出所有表

场景描述:只需要 public schema 或 hr schema 的数据。

操作步骤

# 步骤 1:列出所有 schema
fgkdu list schemas -d /opt/kingbase/data
#   OID     NAMESPACE
#   11      pg_catalog
#   2200    public
#   16482   hr
#   16500   report

# 步骤 2:按 schema 导出(public 全量)
fgkdu scan -d /opt/kingbase/data -s public -o ./schema_public_export

# 步骤 3:按多个 schema 逐个导出
for s in public hr report; do
    fgkdu scan -d /opt/kingbase/data -s "$s" -o "./schema_${s}_export" -f dmp
done

5.7 案例七:金仓KingBase按指定单表导出(含 LOB 字段)

场景描述:只需要 public.orders 表(有 BYTEA 发票字段),同时要恢复被误 DELETE 的行。

操作步骤

# 方式一:-t public.orders(推荐,schema 明确)
fgkdu scan -d /opt/kingbase/data -t public.orders -o ./table_export -f sql

# 方式二:-s public -t orders(拆分为两个参数)
fgkdu recover delete -d /opt/kingbase/data -s public -t orders -o ./orders_deleted

# 方式三:-t orders(当前 schema,public 默认)
fgkdu scan -d /opt/kingbase/data -t orders -o ./table_export -f dmp

# 验证 LOB 导出格式(BYTEA 输出为 '\x...' 十六进制格式,可直接导入)
grep "orders_blob_col" ./table_export/public_orders.sql | head -5
# INSERT INTO "public"."orders" VALUES (1, 1001, '\x255044462D312E340A25...', '2026-01-15');

# 检查 TOAST 大字段(被外部化的 LOB)
grep "LOB BYTEA TOAST" ./table_export/public_orders.sql
# INSERT INTO "public"."orders" VALUES (123, 2024, NULL /* LOB BYTEA TOAST rel=28912 val=415 size=24576000 compressed=Y */);

# 新库导入
ksql -U system -d newdb -f ./table_export/public_orders.sql
SELECT count(*) FROM public.orders;
SELECT length(orders_blob_col) FROM public.orders WHERE id=1;

5.8 案例八:金仓KingBase直接按数据文件批量导出(绕过目录)

场景描述:系统目录完全损坏,无法通过 OID 对应表名,但数据文件仍完好。

操作步骤

# 步骤 1:列出数据目录中的所有数据文件
ls /opt/kingbase/data/base/
#   1/  16384/

ls -1 /opt/kingbase/data/base/16384/ | head -10
#   1259      <- pg_class
#   16385     <- 用户表1
#   16385.1   <- 用户表1的第二段(大表)
#   16386
#   16387     <- 用户表4(含LOB)

# 步骤 2:直接 scan-file 单个文件
fgkdu scan-file /opt/kingbase/data/base/16384/16387 -o ./direct_export -f sql

# 步骤 3:批量 scan-file 扫描整个数据库目录(所有文件)
mkdir -p ./all_files_export
for f in /opt/kingbase/data/base/16384/*; do
    echo "Processing $f..."
    fgkdu scan-file "$f" -o ./all_files_export -f sql --continue-on-error
done

# Windows 批量(cmd 批处理)
# mkdir all_files_export
# for %f in (D:\kingbase\data\base\16384\*) do (
#     echo Processing %f
#     fgkdu.exe scan-file "%f" -o .\all_files_export -f sql --continue-on-error
# )

# 步骤 4:检查批量恢复结果
ls -1 ./all_files_export/ | wc -l
#  87  <- 成功从87个数据文件中恢复了SQL
wc -l ./all_files_export/*.sql | tail -1
#  512034 total  <- 共恢复51万行

# 步骤 5:从恢复的 SQL 中验证数据质量
head -100 ./all_files_export/*_16387.sql

5.9 案例九:金仓KingBase数据文件严重损坏 recover max 终极恢复

场景描述:磁盘出现大量坏道,系统目录严重损坏,需要最大化恢复数据。

操作步骤

# 步骤 1:先诊断损坏程度
fgkdu diagnose -d /opt/kingbase/data -v

# 步骤 2:执行最大恢复(后台运行,大库耗时较长)
nohup fgkdu recover max -d /opt/kingbase/data \
    -o ./max_recovery \
    --continue-on-error \
    -v > max_recovery.log 2>&1 &

# 步骤 3:监控进度
tail -f max_recovery.log
# 或统计已处理文件数
ls -1 ./max_recovery/*.sql 2>/dev/null | wc -l

# 步骤 4:完成后检查结果
tail -100 max_recovery.log
# 预期统计:
# Total rows extracted: 128,456,789
# Files scanned: 487
# Level 2 raw scan activated: 63 files
# Bad blocks: 1,208 (0.01%)

# 步骤 5:统计输出的 SQL 文件数与总行数
ls -1 ./max_recovery/*.sql | wc -l
grep -hc '^INSERT INTO' ./max_recovery/*.sql | awk '{s+=$1} END {print "Total INSERT lines:", s}'

5.10 案例十:金仓KingBase含 LOB(BYTEA/TEXT/JSONB)表的完整导出与恢复验证

场景描述:数据库中存储了大量 PDF/图片(BYTEA)、日志数据(TEXT 1MB+)、JSONB 配置对象。

操作步骤

# 步骤 1:导出所有表(默认已经支持 LOB,无需额外参数)
fgkdu scan -d /opt/kingbase/data -o ./lob_full_export -f sql -v

# LOB 处理说明:
# - 内联 LOB(< 2KB): 直接完整输出 BYTEA 的 '\x...' 十六进制 / TEXT 的实际文本
# - TOAST 外部化 LOB(> 2KB): 输出有效占位值 + SQL 注释
#   BYTEA: NULL /* LOB BYTEA TOAST rel=28912 val=415 size=24576000 compressed=Y */
#   TEXT : ''   /* LOB TEXT TOAST  rel=28912 val=416 size=1048576 compressed=N */
#   JSONB: '{}' /* LOB JSONB TOAST rel=28912 val=417 size=524288  compressed=N */

# 步骤 2:检查 SQL 文件中的 LOB 输出
grep -n "BYTEA\|\\\\x\|LOB" ./lob_full_export/*documents*.sql | head -20
# 正常的 BYTEA:
# INSERT INTO ... VALUES (..., '\x255044462D312E340A25E2E3CFD3...');  -- 内联,直接导入
# TOAST 的 BYTEA:
# INSERT INTO ... VALUES (..., NULL /* LOB BYTEA TOAST rel=28912 val=415 size=24576000 compressed=Y */);

# 步骤 3:导入 KingBase 新库
ksql -U system -d newdb << 'EOFSQL'
-- 先关闭 fsync 加速导入
SET fsync = off;
SET work_mem = '256MB';
SET maintenance_work_mem = '1GB';

-- 执行导出的 SQL 文件
\i ./lob_full_export/public_documents.sql

-- 验证内联 LOB(< 2KB)
SELECT count(*), count(content) FROM public.documents;
-- count | count
-- -------+-------
--  50000 | 38421   <- 38421条内联LOB成功,11579条为TOAST占位

-- 验证 BYTEA 数据正确(PDF 文件头 25 50 44 46 = %PDF)
SELECT encode(content::bytea, 'hex') FROM public.documents WHERE id=1 LIMIT 1;
--                encode
-- ----------------------------------------
-- 255044462d312e340a25e2e3cfd30a...(正确)
EOFSQL

5.11 案例十一:金仓KingBase数据库无法启动 unload 按用户名全库导出

场景描述:数据库因控制文件损坏无法启动,pg_dump、kingbase_dump 等工具都依赖数据库在线无法使用,需要全库抽取并按数据库名分目录导出。

unload 与其他命令的选择

命令 数据库在线 输出结构 适用场景
pg_dump 需要 单文件 数据库可正常启动
scan 不需要 单一目录 系统目录健康
recover max 不需要 单一目录 系统目录损坏
unload 不需要 按数据库名分目录 全库导出,最佳选择

操作步骤

# 步骤 1:诊断数据目录
fgkdu diagnose -d /opt/kingbase/data -v

# 步骤 2:全库 unload(按数据库名自动分目录,后台运行)
nohup fgkdu unload -d /opt/kingbase/data \
    -o /tmp/unload_recovery \
    --continue-on-error \
    -v > /tmp/unload_full.log 2>&1 &

# 监控进度
tail -f /tmp/unload_full.log

# 步骤 3:按用户名/数据库名 unload(仅导出指定数据库)
fgkdu unload -d /opt/kingbase/data \
    -u fgedudb \
    -o /tmp/unload_fgedudb \
    --continue-on-error -v

# 步骤 4:查看输出目录结构
find /tmp/unload_recovery -type d
# /tmp/unload_recovery/
# /tmp/unload_recovery/fgedudb
# /tmp/unload_recovery/postgres
# /tmp/unload_recovery/template1
# /tmp/unload_recovery/_global

# 步骤 5:统计各库恢复的文件数与行数
for db_dir in /tmp/unload_recovery/*/; do
    echo "=== $db_dir ==="
    ls -1 "$db_dir" | wc -l
    grep -hc '^INSERT INTO' "$db_dir"/*.sql 2>/dev/null | awk '{s+=$1} END {print "INSERT lines:", s}'
done

# 预期输出样例:
# === Unload Complete ===
# Databases unloaded: 4
# Files scanned:      35
# Rows extracted:     156
# Bad blocks:         0

5.12 案例十二:金仓KingBase恢复到新建库完整流程

场景描述:数据抽取完成后,需要在新环境中重建数据库并导入数据。

操作步骤

# 步骤 1:在新服务器上创建 KingBase 实例
# 使用 kingbase_initdb 初始化新数据目录

# 步骤 2:启动新实例
sys_ctl start -D /opt/kingbase/new_data -l /tmp/kb.log

# 步骤 3:创建目标数据库
ksql -U system -d security << 'EOF'
CREATE DATABASE newdb WITH ENCODING 'UTF8';
\q
EOF

# 步骤 4:导入 SQL 格式文件(推荐)
ksql -U system -d newdb << 'EOF'
SET fsync = off;
SET work_mem = '256MB';
SET maintenance_work_mem = '1GB';
\i /data/recovery/output/testdb/public/customers.sql
\i /data/recovery/output/testdb/public/orders.sql
\i /data/recovery/output/testdb/public/order_items.sql
EOF

# 步骤 5:数据验证
ksql -U system -d newdb -c "SELECT count(*) FROM public.customers;"
ksql -U system -d newdb -c "SELECT count(*) FROM public.orders;"
ksql -U system -d newdb -c "SELECT * FROM public.orders LIMIT 10;"

# 步骤 6:重建索引与约束(如导出文件不含)
ksql -U system -d newdb -f schema_indexes.sql
ksql -U system -d newdb -f schema_constraints.sql

# 步骤 7:ANALYZE 更新统计信息
ksql -U system -d newdb -c "ANALYZE;"

6. 常用问题与排查

6.1 编译失败:完全静态构建失败

问题:执行 make standalone 报错 "Fully static build failed" 或找不到静态库。

原因:缺少 glibc-static 静态链接库。

解决:安装静态库依赖。

# RHEL / OEL / CentOS 系列
yum install -y glibc-static libstdc++-static

# Ubuntu / Debian 系列
apt-get install -y libc6-dev

# SUSE / openSUSE 系列
zypper install -y glibc-devel-static

# 如果仍无法完全静态构建,使用半静态构建作为替代
make portable

6.2 无法识别数据目录

问题:报错 "Not a valid KingBase data directory"。

原因:数据目录缺少 PG_VERSION 文件,或路径不正确。

解决:确认数据目录包含 PG_VERSION 文件。

# 检查 PG_VERSION 文件是否存在
ls /opt/kingbase/data/PG_VERSION
# 预期:/opt/kingbase/data/PG_VERSION

# 检查内容
cat /opt/kingbase/data/PG_VERSION
# 预期:12(或 14、15 等 KingBase 对应的 PG 内核版本号)

# 确认数据目录结构完整
ls -la /opt/kingbase/data/
# 预期包含:PG_VERSION、base/、global/、pg_wal/ 等关键目录

6.3 恢复的数据为空或行数为 0

可能原因与解决方案

  1. 系统目录损坏:pg_class 无法读取,无法定位用户表。

    • 解决:使用 recover max 命令绕过系统目录直接扫描所有数据文件。
    fgkdu recover max -d /opt/kingbase/data -o ./recovered
    
  2. 数据文件名为非数字格式:KingBase 数据文件以 OID 数字命名,若文件名异常无法识别。

    • 解决:使用 scan-file 直接扫描指定文件。
    fgkdu scan-file /opt/kingbase/data/base/16384/16521 -o ./recovered
    
  3. 表已被 VACUUM 清理:已删除行被 VACUUM 物理清理后无法从主文件恢复。

    • 解决:尝试 WAL 日志恢复(recover max 会自动启用 WAL 恢复策略)。
    fgkdu recover max -d /opt/kingbase/data -o ./recovered -v
    # 查看日志中 [WAL] 开头的恢复记录
    
  4. 数据目录路径错误:-d 指向了非数据目录路径。

    • 解决:先用 diagnose 确认目录有效性。

6.4 权限问题

问题:报错 "Permission denied" 无法读取数据文件。

原因:当前用户对 KingBase 数据目录无读权限。

解决

# 方式一:以 kingbase 用户运行
su - kingbase -c "fgkdu scan -d /opt/kingbase/data -o ./output"

# 方式二:赋予读权限
sudo chmod -R +r /opt/kingbase/data

# 方式三:以 root 运行(需要确保安全)
sudo fgkdu scan -d /opt/kingbase/data -o ./output

6.5 恢复的数据不完整

问题:恢复的行数少于预期,部分表数据缺失。

原因与解决:FGKDU 会在输出文件中生成恢复报告,包含恢复的行数、坏块数量、raw scan 恢复的元组数、数据完整性统计。查看报告了解恢复情况。

# 查看恢复报告
cat ./output/fgkdu_recovery_report.txt

# 报告包含:
# - 恢复的行数
# - 坏块数量
# - raw scan 恢复的元组数
# - 数据完整性统计
# - 各恢复策略的贡献

对于 raw scan 恢复的数据需要人工验证,因为列类型可能是猜测的。建议:

  1. 对比原表的行数与恢复行数。
  2. 抽样检查恢复的数据内容。
  3. 对于列名是 col1..colN 的恢复表,根据业务知识重命名列。

6.6 程序崩溃或信号异常

问题:程序运行中收到 SIGSEGV/SIGBUS 信号退出。

原因:遇到严重损坏的数据文件,触发了内存访问异常。

解决:FGKDU 内置信号保护机制,正常情况下会捕获信号继续运行。如果仍崩溃:

# 1. 使用 --continue-on-error 遇到错误继续
fgkdu scan -d /opt/kingbase/data -o ./output --continue-on-error -v

# 2. 改用 recover max(更强的容错)
fgkdu recover max -d /opt/kingbase/data -o ./output --continue-on-error -v

# 3. 改用 scan-file 逐个文件扫描(定位问题文件)
for f in /opt/kingbase/data/base/16384/*; do
    fgkdu scan-file "$f" -o ./output --continue-on-error
done

6.7 磁盘空间不足

问题:恢复过程中输出目录磁盘空间不足。

解决

# 恢复前检查磁盘空间(SQL 格式约为原始数据的 1.5 倍)
df -h /data/recovery

# 切换到空间充足的磁盘
fgkdu scan -d /opt/kingbase/data -o /data/large_disk/output

# 使用 DMP 格式(比 SQL 格式更节省空间)
fgkdu scan -d /opt/kingbase/data -o ./output -f dmp

6.8 Windows 平台路径问题

问题:Windows 下路径分隔符导致命令失败。

解决:FGKDU 已内置路径分隔符自动转换,\/ 均可。如果仍有问题,统一使用反斜杠:

:: 推荐使用反斜杠
fgkdu.exe scan -d D:\kingbase\data -o D:\recovery\output

:: 正斜杠也可
fgkdu.exe scan -d D:/kingbase/data -o D:/recovery/output

6.9 恢复的 TOAST 大字段为占位值

问题:导出的 SQL 中 TOAST 大字段(大于 2KB 的 BYTEA/TEXT/JSONB)显示为 NULL 或占位值加注释,而非完整数据。

原因:TOAST 大字段存储在独立的 TOAST 表中,主表中仅保存指针。FGKDU 默认输出占位值加元信息注释,保证导入不报语法错误。

解决:基于注释中的元信息(relid/valueid/rawsize/compressed)人工恢复:

-- 元信息示例:
-- NULL /* LOB BYTEA TOAST rel=28912 val=415 size=24576000 compressed=Y */

-- 1. 从原库对应的 TOAST 表(OID 28912)中按 chunk_id=415 恢复 chunk 数据
-- 2. 按 chunk_seq 顺序拼接
-- 3. 若 compressed=Y,需解压(PG 默认 pglz 压缩)
-- 4. 拼接后即为完整的大字段原始数据

6.10 LOB 数据验证失败

问题:导入新库后,BYTEA 字段长度与原库不一致。

解决

-- 验证内联 LOB(< 2KB)应完整
SELECT id, length(content::bytea) FROM documents WHERE id <= 1000;

-- 验证 PDF 文件头(正确应为 25504446 = %PDF)
SELECT id, encode(substring(content::bytea, 1, 4), 'hex') FROM documents WHERE id=1;
-- 预期:25504446

-- 统计内联与 TOAST 占位的数量
SELECT
    count(*) AS total,
    count(content) AS inline_lob,
    count(*) - count(content) AS toast_placeholder
FROM documents;

6.11 恢复速度慢

问题:大库恢复耗时过长。

解决

# 1. 使用 -v 查看进度,确认是否在处理大文件
fgkdu scan -d /opt/kingbase/data -o ./output -v

# 2. 指定单表恢复(比全库快)
fgkdu scan -d /opt/kingbase/data -t public.large_table -o ./output

# 3. 按数据库分批恢复
for db in db1 db2 db3; do
    fgkdu scan -d /opt/kingbase/data -u $db -o ./output_$db
done

# 4. 后台运行避免终端阻塞
nohup fgkdu scan -d /opt/kingbase/data -o ./output -v > scan.log 2>&1 &
tail -f scan.log

6.12 恢复报告查看

问题:需要了解恢复的详细情况。

解决:查看恢复报告与日志。

# 查看恢复报告
cat ./output/fgkdu_recovery_report.txt

# 查看详细日志(需 -v)
cat scan.log | grep -E "TABLE|COMPLETE|ERROR|WARN"

# 统计各表恢复行数
grep "rows extracted" scan.log

# 统计总行数
grep -hc '^INSERT INTO' ./output/*/*.sql | awk '{s+=$1} END {print "Total:", s}'

# 查看坏块信息
grep "bad block" scan.log

关于作者

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

FGKDU 是一款面向人大金仓 KingBase 数据库的数据抽取与恢复工具。当 KingBase 数据库无法启动时,FGKDU 可以直接从底层数据文件中抽取数据,导出为 SQL/DMP/CSV/TXT/BINARY 等格式,用于新建库的数据恢复。完全静态链接编译,单文件零依赖,支持 Linux 与 Windows 双平台,覆盖 KingBase V6 - V9 全系列版本。

如需技术支持或有功能建议,可通过上述联系方式与作者沟通。使用前请务必备份原数据目录,恢复操作应在数据目录副本上进行,避免对原始数据造成二次损坏。

posted @ 2026-08-29 10:08  风哥数据库教程  阅读(7)  评论(0)    收藏  举报