好贷网好贷款

SQL Server 简单模式下,误删除堆表记录进行数据恢复(技术贴) 100zc10151]

发布时间:2016-12-3 14:51:06 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"SQL Server 简单模式下,误删除堆表记录进行数据恢复(技术贴) 100zc10151]",主要涉及到SQL Server 简单模式下,误删除堆表记录进行数据恢复(技术贴) 100zc10151]方面的内容,对于SQL Server 简单模式下,误删除堆表记录进行数据恢复(技术贴) 100zc10151]感兴趣的同学可以参考一下。

本帖最后由 zc10151 于 2013-01-17 19:20:12 编辑   很多朋友认为数据库在简单模式下,堆表误删除一条记录,是无法找回的,因为没有日志记录。其实不然,某种意义上是可以找回的,因为堆表在删除记录时,只更改了行偏移,实际数据没有被物理删除,所以利用这点,测试了下恢复数据,果然成功了,但是还有点问题没有研究出结果:除了更改偏移量,删除数据时还需要更改页眉,这点还没时间去琢磨,所以恢复数据时还要能推断出页眉的16进制对应关系,有兴趣的朋友可以分享下经验给我。 废话不多说,测试的demo如下: 测试环境:   SQL Server 2008 R2   数据库:repl_test 简单模式   测试表:test_del   测试步骤 1.创建测试表test_del,并插入测试数据。 create table test_del( a int identity,b char(10)) go insert into test_del select 'row 1'; insert into test_del select 'row 2'; insert into test_del select 'row 3'; insert into test_del select 'row 4'; insert into test_del select 'row 5'; go 2.查看测试数据,显示正常。 3.DBCC IND命令来找到数据页id,找到数据页id:219,这个数据页存放了test_del的数据 使用dbcc page查看数据页的内容以及行偏移量 dbcc page(repl_test,1,219,1) go 输出结果为: DATA: Slot 0, Offset 0x60, Length 21, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 21 Memory Dump @0x00000000120CC060 0000000000000000: 10001200 01000000 726f7720 31202020 †........row 1  0000000000000010: 20200200 00†††††††††††††††††††††††††† ... Slot 1, Offset 0x75, Length 21, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 21 Memory Dump @0x00000000120CC075 0000000000000000: 10001200 02000000 726f7720 32202020 †........row 2  0000000000000010: 20200200 00†††††††††††††††††††††††††† ... Slot 2, Offset 0x8a, Length 21, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 21 Memory Dump @0x00000000120CC08A 0000000000000000: 10001200 03000000 726f7720 33202020 †........row 3  0000000000000010: 20200200 00†††††††††††††††††††††††††† ... Slot 3, Offset 0x9f, Length 21, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 21 Memory Dump @0x00000000120CC09F 0000000000000000: 10001200 04000000 726f7720 34202020 †........row 4  0000000000000010: 20200200 00†††††††††††††††††††††††††† ... Slot 4, Offset 0xb4, Length 21, DumpStyle BYTE Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP Record Size = 21 Memory Dump @0x00000000120CC0B4 0000000000000000: 10001200 05000000 726f7720 35202020 †........row 5  0000000000000010: 20200200 00†††††††††††††††††††††††††† ... OFFSET TABLE: Row - Offset  4 (0x4) - 180 (0xb4)  3 (0x3) - 159 (0x9f)  2 (0x2) - 138 (0x8a)  1 (0x1) - 117 (0x75)  0 (0x0) - 96 (0x60) 其中行偏移量第一行为96 (0x60),实际记录为row 1,row 2: (0x75),row 3: (0x8a),row 4:(0x9f),row 5: (0xb4)   4. 删除第三行数据 a = 3,b = row 3的记录 delete test_del where a = 3 go 说明a=3 b=row3的记录已经被删除。 5.再次查看数据页的行偏移  dbcc page(repl_test,1,219,1) go Row - Offset  4 (0x4) - 180 (0xb4)  3 (0x3) - 159 (0x9f)  2 (0x2) - 0 (0x0)  1 (0x1) - 117 (0x75)  0 (0x0) - 96 (0x60) 发现第3行的行偏移量被更改成了0,继续执行 dbcc page(repl_test,1,219,2) go DATA: .. 00000000120CC060: 10001200 01000000 726f7720 31202020 †........row 1  00000000120CC070: 20200200 00100012 00020000 00726f77 † ...........row  00000000120CC080: 20322020 20202002 00001000 12000300 † 2 .........  00000000120CC090: 0000726f 77203320 20202020 02000010 †..row 3 ....  00000000120CC0A0: 00120004 00000072 6f772034 20202020 †.......row 4  00000000120CC0B0: 20020000 10001200 05000000 726f7720 † ...........row  00000000120CC0C0: 35202020 20200200 00000021 21212121 发现row3的记录还存在数据页中! 那么猜想,是否将第三行的行偏移量0x0修改回原来的0x8a就可以恢复记录了? 利用winHex工具,打开mdf文件,因为是219页面,8*220 = 1802240字节,所以219的行偏移量应该在1802239处,剩下的工作就很简单了     6.关闭数据库的数据页I/O保护机制,即设置page_verify数据库选项为none,并将repl_test 数据库设置为脱机,利用winhex找到repl_test.mdf文件的1802240结尾处16进制码   alter database repl_test set page_verify none go use master  alter database repl_test set offline go   把repl_test数据库设置为脱机,用winhex工具找到219页面的结尾处(220页面的其实位置):   果然第3行的行偏移量为00 00,那么我将其改回8A 00后保存,(删除记录前,我对该页的页眉16进制代码进行了截图,还原记录时人工对应截图修改回了页眉16进制码)并将数据库设置为online   记录被成功恢复。 可惜小弟不才,还没研究页眉结构对应的物理16进制关系。只靠修改前的页眉截图,修改后按照截图还原页眉,这里无法向大家说明白修改的地方。希望有经验或者有兴趣的朋友可以和我分享下,谢谢~ 文笔不好,如果哪里看的模糊请留言。

高,学习了,感谢分享。

个人感觉这种方式只适合研究数据库的原理,而不适合实际应用 因为在实际情况下,误删数据时不可能提供这么多信息供你做恢复参考的

引用 2 楼 x_wy46 的回复:个人感觉这种方式只适合研究数据库的原理,而不适合实际应用 因为在实际情况下,误删数据时不可能提供这么多信息供你做恢复参考的 很多数据是可以自己计算出来的,目前我了解的,除了页眉格式外,其他的都已经能确保推出需要的数据了。 其实可以利用这个原理继续深入,

引用 3 楼 zc10151 的回复:引用 2 楼 x_wy46 的回复:个人感觉这种方式只适合研究数据库的原理,而不适合实际应用 因为在实际情况下,误删数据时不可能提供这么多信息供你做恢复参考的 很多数据是可以自己计算出来的,目前我了解的,除了页眉格式外,其他的都已经能确保推出需要的数据了。 其实可以利用这个原理继续深入, 楼主的探索精神值得学习,真的!!! 现实的情况是,做的内部系统,很多表主键没有,约束没有,索引没有,到处select * 各种不规范 人们对数据的认识停留在很浅的层次 你写出了一个页面,人家点两下,不报错,再加上整个样式啥的,看起来“还不错” 老板眼里你比那弄数据库的强多了, 弄数据的,老板看不见,摸不着,除了问题还怪你恢复的不及时,没有问题更觉着你没“价值” 哎,数据库不玩到一定的水平,一个数据库管理员的作用看起来微乎其微

引用 4 楼 x_wy46 的回复:引用 3 楼 zc10151 的回复:引用 2 楼 x_wy46 的回复:个人感觉这种方式只适合研究数据库的原理,而不适合实际应用 因为在实际情况下,误删数据时不可能提供这么多信息供你做恢复参考的 很多数据是可以自己计算出来的,目前我了解的,除了页眉格式外,其他的都已经能确保推出需要的数据了。 其实可以利用这个原理继续深入, 楼主的探索精神值得学习,真的!…… 加油兄弟~ 我也做了管理员几年了,不规范的慢慢规范就好了~这个只是分享下,实际怎么应用还得看怎么去理解了~

期待后续。另外我听说过能通过mdf找回比较高百分比的数据,估计他们的原理和你的差不多。

引用 6 楼 DBA_Huangzj 的回复:期待后续。另外我听说过能通过mdf找回比较高百分比的数据,估计他们的原理和你的差不多。斑竹支持,一定努力到底~

我是个菜鸟,靠时间累一下分数而已

引用 8 楼 DBA_Huangzj 的回复:我是个菜鸟,靠时间累一下分数而已 分数有用?

引用 9 楼 yangsh0722 的回复:引用 8 楼 DBA_Huangzj 的回复:我是个菜鸟,靠时间累一下分数而已 分数有用?你一边玩泥沙去,没你说话的地方

膜拜一下~~那么只是适合堆表吗?还有如果批量删除数据的话。。这个方法可以批量找回吗?

首先要知道删除的数据所在的文件号页面号,而且delete之后再多insert几下可能Slot 2就被使用了,所以实际应用上没太大的可操作性。 而且实际的表有N个页面,在Heap的IAM_Chain里面要查出被删除数据页面号,难度可向而知。 知道页面号的情况下,用DBCC WRITEPAGE在线情况下就可以改回来。

引用 10 楼 DBA_Huangzj 的回复:引用 9 楼 yangsh0722 的回复:引用 8 楼 DBA_Huangzj 的回复:我是个菜鸟,靠时间累一下分数而已 分数有用?你一边玩泥沙去,没你说话的地方

引用 12 楼 Vidor 的回复:首先要知道删除的数据所在的文件号页面号,而且delete之后再多insert几下可能Slot 2就被使用了,所以实际应用上没太大的可操作性。 而且实际的表有N个页面,在Heap的IAM_Chain里面要查出被删除数据页面号,难度可向而知。 知道页面号的情况下,用DBCC WRITEPAGE在线情况下就可以改回来。这个我也想过,特别是刚删了又陆陆续续在写入。所以比较好的实践还是对正式环境使用完整模式并创建库后马上做一次完整备份。不过这不是这个文章的主题思想,唠叨几句而已

引用 11 楼 szm341 的回复:膜拜一下~~那么只是适合堆表吗?还有如果批量删除数据的话。。这个方法可以批量找回吗?聚集索引还没试过,待研究中

引用 12 楼 Vidor 的回复:首先要知道删除的数据所在的文件号页面号,而且delete之后再多insert几下可能Slot 2就被使用了,所以实际应用上没太大的可操作性。 而且实际的表有N个页面,在Heap的IAM_Chain里面要查出被删除数据页面号,难度可向而知。 知道页面号的情况下,用DBCC WRITEPAGE在线情况下就可以改回来。 槽2可能不是马上就能被使用的,印象中堆表空间释放是在某种情况下才可以,这个文章其实只是个入门级,哈哈~我想继续深究,会找到一个修复数据的可行性方案的~可惜不才啊..

引用 15 楼 zc10151 的回复:引用 11 楼 szm341 的回复:膜拜一下~~那么只是适合堆表吗?还有如果批量删除数据的话。。这个方法可以批量找回吗?聚集索引还没试过,待研究中 支持lz继续研究~早日发布成果给大家分享呵呵

引用 16 楼 zc10151 的回复:引用 12 楼 Vidor 的回复:首先要知道删除的数据所在的文件号页面号,而且delete之后再多insert几下可能Slot 2就被使用了,所以实际应用上没太大的可操作性。 而且实际的表有N个页面,在Heap的IAM_Chain里面要查出被删除数据页面号,难度可向而知。 知道页面号的情况下,用DBCC WRITEPAGE在线情况下就可以改回来。 槽2可能…… 不锁表或不删除表的前提下,堆表的delete是不会release page的。详见 http://support.microsoft.com/kb/913399/en-us

引用 18 楼 mayuanf 的回复:不锁表或不删除表的前提下,堆表的delete是不会release page的。详见 http://support.microsoft.com/kb/913399/en-us  不是同一个议题好吧,delete堆表确实不会释放页面为其它对象所用,但不等于自己都不能用。 这里只删除了Slot 2尚不涉及release page,但Slot 2对于该表就是可用空间,随时可以用新纪录填充的,象楼主测试的单页情况下,下一条合适数据就会填充Slot 2。

删除记录 ,有时 在空间不够的情况 或者有转移记录 的 幻想记录 等这种方法可能不行

貌似可行,但重要的一点是如何知道“第三行的行偏移量0x0修改回原来的0x8a”,也就是说删除之后我们如何知道它的来的Offset为0x8a。

上一篇:有没有指代一个数据库的同义词? 100sz_haitao]
下一篇:[推荐] 升两颗星,发现有好多东西还是不知道,月末了准备不在逛论坛了,散个分顺便在此分享一个生成流水号(订单号)的思路 300筱筱澄]

相关文章

相关评论