当前位置: 代码网 > it编程>数据库>MsSqlserver > SQL Server模拟checksum检测错误的完整步骤

SQL Server模拟checksum检测错误的完整步骤

2026年09月03日 MsSqlserver 我要评论
要模拟备份时 checksum 检测到错误并中断,最有效的方法是直接修改数据库数据页的底层二进制数据(即人为制造物理损坏/page corruption)。在 sql server 中,无法通过常规的

要模拟备份时 checksum 检测到错误并中断,最有效的方法是直接修改数据库数据页的底层二进制数据(即人为制造物理损坏/page corruption)。

在 sql server 中,无法通过常规的 update 语句破坏页面校验和,因为引擎会自动重新计算。我们需要使用未公开的危险命令 dbcc writepage 来直接篡改磁盘上的字节。

以下是完整的模拟步骤(请务必在独立的测试数据库中操作,绝对不能在生产环境运行!):

第一步:准备测试数据库和表

首先,创建一个名为 testverify 的干净数据库,并写入一条测试数据。

-- 1. 创建测试数据库
create database testverify;
go
use testverify;
go
-- 2. 设置页面校验和为 checksum(默认通常也是这个)
alter database testverify set page_verify checksum;
go
-- 3. 创建一张简单的表并插入数据
create table testtable (id int identity(1,1), name varchar(100));
insert into testtable (name) values ('row_to_be_corrupted');
go

第二步:找出数据所在的物理页面(page id)

我们需要知道数据存放在哪个数据页上,以便对其进行精准破坏。

-- 使用 dbcc ind 查看表的页面分配
-- 参数: ('数据库名', '表名', 1代表聚集索引或堆)
dbcc ind ('testverify', 'testtable', 1);
go

运行后在结果集中找到:

  • pagetype = 1 的那一行(1 代表数据页 data page)。
  • 记住这一行的 pagefid(文件 id,通常是 1)和 pagepid(页面 id,例如是 240)。

直接篡改数据行的内容(比如把字母 'r' 改掉)

-- 1. 开启跟踪标记,允许将 dbcc 的结果输出到 ssms 消息窗口
dbcc traceon (3604);
go
-- 2. 查看页面内容
-- 参数: ('数据库名', 文件id, 页面id, 输出格式)
-- 输出格式 0 代表只打印页面头部,1 代表打印每行的十六进制和文本对照(推荐)
dbcc page ('testverify', 1, 240, 1);
go

  • 原值分析:在数据行的内存镜像中,十六进制的 52 代表大写字母 r(即 row 的开头)。
  • 寻找绝对偏移量(offset)
    1. slot 0 的起始绝对偏移量是 0x60(十进制的 96)。
    2. 3000... 开始数,十六进制的 52 位于第 16 个字节的位置(从 0 开始算偏移是 15)。
    3. 因此,字母 'r' 在整个页面中的绝对偏移量是 96 + 15 = 111

你想改成 0x33 的话,命令应该这样写:

第三步:使用 dbcc writepage 故意破坏页面结构

现在,我们把数据库设为单用户模式,然后直接向这个页面写入错误的垃圾数据,从而破坏它的 checksum 校验。

注意:请将下面代码中的 312 替换为你上一步实际查到的 pagepid

-- 切换单用户模式
alter database testverify set single_user with rollback immediate;
go
dbcc traceon (3604, 2588);
go
-- 将偏移量设为 111,把字母 'r' (0x52) 强行篡改为 0x33(字符 '3')
dbcc writepage ('testverify', 1, 240, 111, 1, 0x33,1);
go
dbcc traceoff (3604, 2588);
go
-- 恢复多用户
alter database testverify set multi_user;
go
-- 1. 开启跟踪标记,允许将 dbcc 的结果输出到 ssms 消息窗口
dbcc traceon (3604);
go
-- 2. 查看页面内容
-- 参数: ('数据库名', 文件id, 页面id, 输出格式)
-- 输出格式 0 代表只打印页面头部,1 代表打印每行的十六进制和文本对照(推荐)
dbcc page ('testverify', 1, 240, 1);
go

第四步:测试备份,见证 checksum 报错

现在,我们运行带有 with checksum 的备份命令。由于磁盘上的页面已被破坏,备份会立刻中断并报出物理损坏的错误。

backup database [testverify] to  disk = n's:\tmp\testverify.bak' with noformat, init,  
name = n'testverify-full database backup', skip, norewind, nounload, compression,  stats = 10, checksum
go

expected output (预期错误信息):

你会看到类似下面的报错,提示遇到了 输入/输出(i/o)错误,并且明确指出了 checksum 不匹配

通过这个实验,你可以直观地看到 checksum 是如何在第一时间内拦截坏数据的。如果你想进一步了解当遇到这种备份报错时,应该通过什么步骤去尝试挽救或修复数据库,请告诉我!

以上就是sql server模拟checksum检测错误的完整步骤的详细内容,更多关于sql server模拟checksum检测错误的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com