金仓KingBase数据库恢复工具FGKDU(FGEDU KingBase DUL)
金仓KingBase数据库恢复工具FGKDU(FGEDU KingBase DUL)
FGKDU(全称 FGEDU KingBase DUL,Data UnLoader)是一款专门面向人大金仓 KingBase 数据库的数据抽取与恢复工具,当数据库实例已经无法正常启动、传统逻辑备份与导出工具(如
pg_dump、kingbase_dump、sys_dump)全部失效时,仍然能够绕过数据库引擎,直接从底层物理数据文件中解析并抽取数据,把业务数据以可识别的格式导出,用于在新环境中重建数据库。
目录
1. 程序介绍
1.1 项目概述
FGKDU(全称 FGEDU KingBase DUL,Data UnLoader)是一款专门面向人大金仓 KingBase 数据库的数据抽取与恢复工具,当数据库实例已经无法正常启动、传统逻辑备份与导出工具(如 pg_dump、kingbase_dump、sys_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 的工作流程可以概括为"直接读取物理文件 → 解析页面格式 → 提取元组数据 → 解码列值 → 写入输出文件"五个阶段,具体如下:
- 数据目录识别:读取 PG_VERSION 文件识别 KingBase 版本,读取 pg_control 检测数据块大小(自动识别 8KB/16KB/32KB)。
- 系统目录解析:解析 pg_database(数据库列表)、pg_class(表对象列表)、pg_attribute(列定义)等系统表,建立 OID 到表名、列类型的映射关系。
- 页面扫描:按照 8KB 页面格式逐块读取数据文件(路径为
PGDATA/base/{db_oid}/{relfilenode}),解析页面头(PageHeaderData:pd_lower/pd_upper/pd_special/pd_pagesize_version)。 - 元组提取:遍历页面中的项指针数组(ItemId),定位每个堆元组(HeapTuple),解析元组头(HeapTupleHeaderData:t_xmin/t_xmax/t_infomask),判断元组的可见性与删除状态。
- 列值解码:按照 pg_attribute 中的列类型定义,逐列解码数据值,支持整数、浮点、字符、日期时间、BYTEA(二进制大对象)、TEXT/CLOB、JSONB、NUMERIC 等全部常见类型。
- 输出写入:将解码后的行数据按照指定格式(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 数据目录进行全面健康检查,是所有恢复操作的第一步。诊断结果会指出数据目录的完好程度、可用恢复策略,为后续操作提供决策依据。
诊断检查项:
- 数据目录存在性与权限检查。
- PG_VERSION 文件读取与版本识别。
- pg_control 控制文件状态(魔数、版本、校验和、块大小)。
- 关键子目录结构(base/、global/、pg_wal/、pg_tblspc/)。
- 系统目录可读性(pg_database、pg_class、pg_attribute)。
- 数据块大小自动检测。
- 典型数据文件完整性抽样检查。
- 文件权限检查。
# 基本诊断
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
工作原理:
- 扫描
base/目录下的每个数据库 OID 子目录。 - 尝试从系统目录
pg_database解析数据库名(best effort)。 - 系统目录可读时:子目录名为数据库名(如
fgedudb)。 - 系统目录损坏时:子目录名回退为
oid_<OID>(如oid_16384),仍可正常导出。 - 对每个数据库目录下的数据文件逐个扫描,导出可恢复的行。
- 同时扫描
global/目录的共享系统表,输出到_global/子目录。 - 若指定
-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
可能原因与解决方案:
-
系统目录损坏:pg_class 无法读取,无法定位用户表。
- 解决:使用
recover max命令绕过系统目录直接扫描所有数据文件。
fgkdu recover max -d /opt/kingbase/data -o ./recovered - 解决:使用
-
数据文件名为非数字格式:KingBase 数据文件以 OID 数字命名,若文件名异常无法识别。
- 解决:使用
scan-file直接扫描指定文件。
fgkdu scan-file /opt/kingbase/data/base/16384/16521 -o ./recovered - 解决:使用
-
表已被 VACUUM 清理:已删除行被 VACUUM 物理清理后无法从主文件恢复。
- 解决:尝试 WAL 日志恢复(recover max 会自动启用 WAL 恢复策略)。
fgkdu recover max -d /opt/kingbase/data -o ./recovered -v # 查看日志中 [WAL] 开头的恢复记录 -
数据目录路径错误:-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 恢复的数据需要人工验证,因为列类型可能是猜测的。建议:
- 对比原表的行数与恢复行数。
- 抽样检查恢复的数据内容。
- 对于列名是 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 全系列版本。
如需技术支持或有功能建议,可通过上述联系方式与作者沟通。使用前请务必备份原数据目录,恢复操作应在数据目录副本上进行,避免对原始数据造成二次损坏。

浙公网安备 33010602011771号