DBRescue 使用说明
SQL Server MDF 表数据恢复
本文介绍使用 DBRescue 提取 SQL Server MDF 表数据的方法。准备好 MDF 文件、表结构和数据页参数,选择文件后即可执行。恢复结果另存,不修改原文件。
恢复原理
SQL Server 的表记录保存在数据页中。DBRescue 直接读取 MDF,通过指定的分配单元定位目标记录,再按 schema.tsv 中的列顺序和类型解析字段,整个过程无需启动原数据库。
当前支持单个 MDF 中的未压缩记录,可提取整数、字符、二进制、decimal、datetime2 等字段。数据导出为 TSV,保留对应页号、槽号和校验状态。decoded_rows.sql 为核对用的注释内容,不包含可直接执行的 INSERT。
文件在本地处理,结果写入独立目录,不修改源 MDF,不写回数据库。当前不支持 LDF 日志恢复及误删回滚。
恢复准备
执行前准备以下文件和参数。建议先复制 MDF,使用副本操作:
自己的文件,参数从哪里找
下面是只读查询,在数据库客户端执行,不是在 DBRescue 中执行。原库还能正常查询时,请 DBA 导出这些资料;原库已经故障,就使用匹配、可启动的副本,不要为了查参数强行启动故障原库。
先连接 MDF 对应的原数据库或匹配的可查询副本,把 dbo.sample 换成真实目标表。以下查询需要读取相应系统目录的权限。
1SET NOCOUNT ON;2SELECT @@VERSION AS version, DB_NAME() AS current_database;3SELECT name,page_verify_option_desc FROM sys.databases WHERE database_id=DB_ID();4SELECT c.column_id,c.name,t.name AS type_name,c.max_length,c.precision,c.scale FROM sys.columns c JOIN sys.types t ON c.user_type_id=t.user_type_id WHERE c.object_id=OBJECT_ID(N'dbo.sample') ORDER BY c.column_id;5SELECT p.index_id,p.partition_number,a.type_desc,a.allocation_unit_id FROM sys.partitions p JOIN sys.allocation_units a ON a.container_id=p.hobt_id WHERE p.object_id=OBJECT_ID(N'dbo.sample') AND a.type=1;page_verify_option_desc 是原库的页校验设置。列清单给出顺序、类型、长度、精度和小数位,不能只抄列名。 allocation_unit_id 清单用于让 DBA 核对目标索引和分区。它、OBJECT_ID()、普通 index_id 都不能直接填进工具的 Object / Index 字段;工具这里要求页分配组件值。本例 222 / 256 只对样本有效,自己的页组件仍须结合目标数据页确认。
下载参数核对 SQL没有结构或页组件资料时,先把 MDF 副本、版本、表设计、索引和分区资料交给 DBA 核对。不要把页校验改成 NONE 来绕过失败,也不要猜两个数字继续。
| 文件 / 参数 | 说明 |
|---|---|
| MDF 副本 | 不再被数据库写入的 MDF 文件副本,另建一个空目录存放恢复结果。 |
| schema.tsv | 对应表的结构文件,列顺序、类型须与实际记录布局一致。Excel 或重命名后的 SQL 文件不能代替。 |
| Object / Index | 目标数据页的分配单元组件,不是普通 OBJECT_ID 或索引编号。本文测试值仅用于随包 MDF。 |
| PAGE_VERIFY | 填写原库的 CHECKSUM、TORN_PAGE_DETECTION 或 NONE 设置。不清楚时先确认,不要随意选择 NONE。 |
只有 MDF、没有结构和页参数,当前无法执行这条恢复流程。压缩、加密、多文件及复杂类型需要另行确认,购买前请先联系。
测试环境与恢复结果
演示环境为 SQL Server 2022(16.0.4305.5)。测试库正常分离后,保留 MDF 和原库查询结果,在 Windows 桌面开发构建中使用测试授权执行恢复。表中共 4096 行、8 个字段。
恢复后将 TSV 与原库结果逐字段比对,4096 行一致,27 个目标数据页校验通过,源 MDF 的 SHA-256 未变。随后在独立 SQL Server 容器中按 8 列类型导入,再查询比对也通过。本次未模拟损坏,记录的事务状态仍需核对。
恢复实战
测试文件已打包,可以先下载跟着操作一遍,无需安装 SQL Server。点击下方标题展开,包含安装、选文件、填参数及恢复后检查。
SQL Server MDF 表数据恢复实战
SQL Server · 桌面工具操作实战
本文演示使用 DBRescue,从 SQL Server MDF 文件中提取表数据的过程。使用一份包含 4096 行数据的测试文件,恢复完成后,与原库查询结果逐字段比对。工具不修改源文件,恢复结果单独保存。
本次演练环境与适用范围
演示时间:2026 年 10 月 16 日。SQL Server 版本为 16.0.4305.5,数据库正常分离后采集 MDF。截图使用 Windows 桌面开发构建和测试授权,没有进行真实购买、生产授权签发及数据回灌。本次验证的是正常分离文件的记录提取,不是损坏文件恢复率。
下载工具和本文测试文件
本文测试文件已打包,包含 MDF、表结构、页参数和参考数据。下载解压后即可跟着操作,不需要安装 SQL Server。 正式提取需要 SQL Server 或全库授权,测试包不包含授权码。已有会员权益的用户先领取授权,无需重复购买。 使用自己的 MDF 时,表结构和参数都要重新准备,不能套用本文的 222 / 256。材料不齐先确认是否适用,再购买授权。
演示环境信息
- 操作环境
- Windows x64 · DBRescue 桌面开发构建(测试授权)
- 恢复文件
- 单个 MDF 副本 + 对应表的原生 schema.tsv
- 恢复方式
- 指定数据页分配单元,提取目标表记录
- 样本结果
- 4,096 行;任务状态 completed
1恢复准备
- 下载 practice.zip,右键选择“全部解压缩”。
- 打开解压目录,确认 input 下有 MDF、schema.tsv 和 baseline.json;根目录有 sample-settings.json 和三个 ps1 脚本。
- 在 input 同级目录下新建 output 文件夹,恢复结果放在这里。脚本与 input 保持原有位置,不要单独挪走。
baseline.json 是原库查询结果,供恢复后比对,不用选进工具。MDF 不需要附加到 SQL Server,直接选择文件即可。使用自己的文件时,要保留副本,并确认文件不再被数据库写入。
测试包需要完整解压。output 由你新建,三个脚本放在根目录:
1input/2 recovery-sample.mdf3 schema.tsv4 baseline.json5sample-settings.json6Check-Recovery.ps17Verify-Sample.ps18Inspect-Sample.ps19output/ (create this empty folder)2打开工具
- 下载当前电脑系统对应的 DBRescue 安装包,安装后打开。
- 在授权区域填入 SQL Server 或全库授权码,点击激活,确认授权有效。本文使用测试授权,不提供授权码。离线电脑使用工具中的离线请求、响应流程。
- 找到“新建恢复任务”,数据库类型选择 SQL Server,恢复模式选择“数据文件提取”。
界面版本不同时,入口文案可能略有区别。开始前确认引擎已就绪。购买前预览只能用于检查记录,不能代替完整导出。
3选择 MDF 文件
- 点击“源文件或目录”右侧的“文件”,选择 input 目录下的 recovery-sample.mdf。这里不选目录,也不选 LDF。
- 点击“输出目录”右侧的“选择”,选中刚建好的 output 文件夹。
- 需要检查文件读取情况,可以点击“检查源文件”。检查完成后,继续配置下面的参数。
源路径结尾应为 recovery-sample.mdf,输出路径应为 output。输出目录不能放在 input 里面,也不能放在程序或配置目录内。
4填写恢复参数
- 展开“用户、表与高级参数”。
- 点击“对应表的 schema.tsv(必选)”右侧的“文件”,选择 input/schema.tsv。
- “原数据库的 PAGE_VERIFY 设置”选择 CHECKSUM。
- “数据页分配单元 Object 组件”填写 222,“数据页分配单元 Index 组件”填写 256。
- 并发数保持 1,用户名和表名不用填写。参数填写完成后如下图:
这两个数字来自本次样本的页分配单元信息,不是普通 OBJECT_ID 或索引编号,只适用于本文 MDF。schema.tsv 中列名与类型以制表符分隔,练习时直接选择随包文件即可。
这几个参数从哪里来
本文的 222 / 256 和 CHECKSUM 来自测试文件的采集记录,已经写入解压目录下的 sample-settings.json。可以用记事本直接打开,也可以在 PowerShell 执行下面两行。输入解压目录的完整路径,不要输入 input 子目录。
1$practiceFolder = Read-Host 'Extracted practice folder'2Get-Content -LiteralPath (Join-Path $practiceFolder 'sample-settings.json') -Raw -Encoding UTF8找到 allocationUnitObjectComponent、allocationUnitIndexComponent、pageVerify,分别对应界面的 Object、Index 和 PAGE_VERIFY。这里只说明测试包的参数来源,不代表工具能自动识别其他 MDF 的表名和参数。
查看样本结构文件内容
1id int2name varchar(100)3small smallint4big bigint5active bit6tiny tinyint7code char(3)8payload varbinary(4)
5执行恢复
- 确认 MDF、schema.tsv、输出目录都已选好,校验方式为 CHECKSUM,Object / Index 为 222 / 256。
- 点击“开始恢复”,等待任务结束,运行中不要更换输入文件。
- 本次任务状态为 completed。日志显示 decoded_rows 为 4096、data_pages 为 27、skipped_slots 为 0,即读取 27 个目标数据页,提取 4096 行记录。
任务失败时先看日志,不要反复提交,也不要随意切换成 NONE。日志中的 TRANSACTION_STATE_UNKNOWN 表示事务状态未知,提取完成不等于记录都已提交。
6查看恢复数据
- 恢复完成后,点击“查看表数据”。
- 结果文件选择 decoded_rows.tsv,查看恢复出的字段和值。本次中文、表情、整数和空值均可在预览中看到,如下图:
- 点击“打开结果目录”,可以看到 decoded_rows.tsv、decoded_rows.sql、slot_locator.tsv 和 desktop-engine.log 等文件。
本次界面只预览前 50 行,完整数据在 TSV 文件中。decoded_rows.sql 是供核对的注释内容,不包含可直接执行的 INSERT,不能拿它直接回灌业务库。

7数据比对
- 点击“打开结果目录”,找到这次生成的 decoded_rows.tsv。检查脚本已经放进测试包,参考数据会自动从 input/baseline.json 读取,不需要手动选择。
随后又在独立 SQL Server 容器中执行了本例的类型导入,逐字段核对通过,具体操作见下方“导入测试库”。没有向原业务库回补。
- 打开解压后的测试包目录,确认能看到 Check-Recovery.ps1 和 input 文件夹。
- 点击资源管理器的地址栏,输入 powershell,按回车,在当前目录打开 PowerShell。
- 执行下面这一行。弹出文件选择窗口后,进入本次任务的结果目录,选择 decoded_rows.tsv,点击打开。
- 脚本先比对 4096 行、8 个字段,再统计重复 ID、页面校验和事务状态。关闭选择窗口即可取消,不修改任何文件。
1.\Check-Recovery.ps1下面是本次实际运行输出。第一行出现 PASS 才表示与本文样本基准一致;系统策略不允许执行时,不要关闭安全策略,请检查脚本并使用获准的环境。
1PASS: 4096 rows; 8 columns match the supplied baseline.2Rows: 40963Duplicate ID groups: 04Page checks:5VERIFIED_PAGE_CHECKSUM: 40966Transaction states:7TRANSACTION_STATE_UNKNOWN: 40964096 行都带有 VERIFIED_PAGE_CHECKSUM,重复 ID 为 0,但事务状态全部是 TRANSACTION_STATE_UNKNOWN。这表示页面校验通过,不能据此认定记录都已提交。该脚本按练习表的 id 检查重复,不能直接用于任意业务表。
先保留 MDF 副本、结构文件、任务日志和原始导出。下节继续验证样本在独立 SQL Server 中的导入;生产回补仍要确认事务、目标表结构、重复记录和业务关联。
导入测试库,再核对一次
SQL Server 也做了实际导入:在 ESXi 实验机的新容器中,按 8 列原类型建表并写入导出的 4096 行。按数字 ID 对齐后,全部字段与原库基准一致,包含中文、表情、二进制和 1584 个 NULL。容器没有外部网络,验收后已停止。
- 连接独立的 SQL Server 测试环境。下载下方 SQL,先确认它创建的是 guide_lab_107603c85c 测试库,不能把目标改成原业务库。
- 打开并执行完整脚本。脚本包含本例的建表和 4096 行虚构数据;目标库已存在时就停止,换一套空测试环境,不要直接 DROP。
- 待测试库状态为 ONLINE 后再查询,核对下方两个计数。还要按数值 ID 对齐,逐字段与练习包 baseline.json 比对,不能只比较两份查询的显示顺序。
1USE guide_lab_107603c85c;2SELECT COUNT(*) AS rows_total, COUNT(DISTINCT id) AS distinct_ids3FROM dbo.sample;在数据库客户端里,具体怎么执行
下面使用数据库自带的命令行客户端,不是在 DBRescue 任务窗口输入命令。先安装对应客户端,让管理员准备空的隔离测试环境和账号。把练习 SQL 放到 C:/recovery-practice;路径不同就替换下面的路径。
以下是连接模板:TEST_HOST 是测试服务器地址,TEST_PORT 是实际端口,TEST_USER 是测试账号,TEST_DATABASE 是管理员给出的空测试库,Oracle 的 TEST_SERVICE 是服务名。必须替换这些字样;密码在客户端提示时输入,不写进脚本。命令找不到时,进入客户端 bin 目录再执行。
1. 先确认连接位置
1sqlcmd -S tcp:TEST_HOST,TEST_PORT -U TEST_USER -d master -b -Q "SELECT @@SERVERNAME AS server_name, DB_NAME() AS current_database;"这条命令只打印服务器和当前库,不导入数据。确认服务器是隔离测试环境。证书或权限报错时先让管理员解决,不要跳过身份确认。
2. 再执行练习脚本
回到 PowerShell,使用同一套服务器和账号执行下面的 -i 命令。脚本会新建 guide_lab_107603c85c,不能把它改成业务库名。随后连接该库,等状态为 ONLINE 再核对数据。
1sqlcmd -S tcp:TEST_HOST,TEST_PORT -U TEST_USER -d master -b -f 65001 -i "C:\recovery-practice\import-sample.sql"执行中出现报错就停止,保留第一条错误和完整输出,不要反复重跑 INSERT。成功后在同一目标库执行上面的计数查询,再按 ID 对齐逐字段核对。只有两个计数都为 4096 还不能作为完整验收。
文件执行方式已在 ESXi 的原生客户端验证:MySQL SOURCE、psql 的 \i、sqlcmd -i、SQL*Plus 与 DIsql 的 @。连接地址、账号和 Windows 路径是需要替换的模板;本节没有把命令行记录当成图形客户端截图。
本例的总行数和去重后的 ID 数均为 4096。行数相同还不够,本次另外逐字段比对了全部记录;中文、NULL、数字和日期也要一起核对。
页校验通过不等于事务已提交。恢复结果仍保留 TRANSACTION_STATE_UNKNOWN,测试库可以读出数据也不代表可以覆盖原业务表。
换成自己的 MDF 时
表结构、页参数和校验设置都要重新确认,不能沿用测试包里的值。
- MDF 文件副本
- 对应表的 schema.tsv
- 目标页的 Object / Index 组件
- 原库 PAGE_VERIFY 设置
只有 MDF,其他信息没有怎么办?
本文的 schema.tsv 和 222 / 256 只适用于测试文件,不能用于其他 MDF。
schema.tsv 中的列顺序、类型要与目标表实际记录布局一致。可以使用建表 SQL 或表设计资料核对,但当前工具不能自动把任意建表 SQL 转成结构文件。
Object / Index 填写目标数据页的分配单元组件,不是普通 OBJECT_ID 或索引编号。PAGE_VERIFY 按原库设置填写。
只有 MDF、没有上述信息时,目前不能直接开始恢复。先准备数据库版本、故障经过、文件清单和表结构资料,找熟悉 SQL Server 页结构的 DBA 确认。
导出后,按自己的业务数据检查缺失、重复、事务状态和关联关系。本文没有进行数据回灌,测试比对通过也不代表业务库可以直接上线。
常见问题
开始恢复按钮不可用
检查运行环境/引擎是否就绪、授权是否有效、是否仍有任务运行。再核对源文件和输出目录是否已选。缺少结构文件、页组件或校验方式时,提交也会被拒绝。
提示结构文件无效或格式不支持
练习时重新选 input/schema.tsv,不要选 JSON、Excel 或重命名的 SQL。自己的表不能套练习结构;先核对真实列顺序、类型及工具支持范围。
任务失败或没有读出记录
先保留日志。练习时核对 MDF、schema.tsv 是否来自同一个解压包,参数是否为 CHECKSUM / 222 / 256。不要为绕过错误而改成 NONE。自己的文件出现校验或布局错误,应停止并核查文件完整性和支持范围。
比对脚本报行数、重复 ID 或字段不一致
Row count mismatch:检查是否选中了旧任务或只有部分记录的预览文件。Value mismatch:检查字段值、结构或文件是否被修改。Duplicate id:发现重复 ID,保留导出文件和日志。以上任一错误都不能按验证通过处理。
本次恢复结果
本次重新恢复后的检查结果如下:
1database: mssql2taskStatus: completed3rows: 40964columns: 85dataPagesChecksumVerified: 276sourceUnchanged: true7transactionVisibility: unknown8sqlExecution: comment-only4096 行、8 个字段逐值一致,27 个目标数据页校验通过,MDF 恢复前后的 SHA-256 一致。关闭工具重新打开,任务和结果预览仍可查看。以上均为测试授权下的提取验证。
解析细节和导出文件
读取 MDF 数据页
按数据页分配单元读取未压缩记录,使用提供的表结构解析列值。输出中保留页校验结果及事务状态,便于检查异常记录。
查看导出文件
TSV 保存字段值,slot_locator.tsv 保存记录位置,SQL 文件保存供核对的注释。任务结束后检查日志及导出文件,不自动写回数据库。
- decoded_rows.tsv
- 解码后的列值、页校验结果与事务状态
- decoded_rows.sql
- 供人工核对的 SQL 注释,不自动执行
- slot_locator.tsv
- 每条记录的页号、槽号与原始位置
- RECOVERY_COMMITTED
- 本次输出已完成写入的标记
查看命令行示例
1mssql-rescue mdf dump-table --file /recovery/database.mdf --schema /recovery/schema.tsv --object-id <allocation-object-component> --index-id <allocation-index-component> --page-verify checksum --out-dir /recovery/output --json