SQL SERVER Undelete 可能性探索(一)Clustered Table
admin
2023-05-29 00:21:22
0

SQLSERVER中,如果数据被误删了,依照官方的说法,SQLSERVER是没有undelete的。要想救回被删除的数据,最典型的方法就是透过将备份档还原成另一DB,将数据从另一DB找回来后,再新增回正式的DB。

不过,如果对于SQLSERVER的transaction log结构了解的人,只要交易纪录还在,就可以透过解析交易纪录来取得被删除的数据,再将数据Insert回DB。只是transaction log的解析有点复杂。这也是个值得探讨且有趣的主题。如果可以,或许可以找时间来谈谈这个。


其实还有一种方法….


SQLSERVER在执行delete的时候,它并不是真正立即将数据从page中抹除。它只是先将它「标记」为删除,这时候从逻辑上来看是已删除了(查不到了),但实际上数据还存在,这时我们称此笔纪录为 Ghost record。

注:

SQLSERVER的「标记」删除,在clustered table及heap table标记方法是不一样的。


真正的将数据清除(purge),是由GhostCleanuptask这支系统线程来做,它大约每5~10秒钟会被唤醒一次,去真正地清除Ghost record。不过,为避免造成系统忙碌,它每次只会检查或清除有限数量的页面(应该是10 pages)。


所以从delete commit,到数据真正被清除。中间是有一个缓冲期的。

有了这样的一个缓冲期,就给了我们一个可以Undelete的机会。


首先,最要紧的是,当发生误删的时候,必需尽速执行下列指令,停用Ghostcleanuptask。以免资料被真的清除。

dbcc traceon(661,-1)   --暂停Ghostcleanuptask


以下我们做一个简单的Undelete测试


Clustered Table undelete Testing

建立一个测试数据库,一并建立clustered index及non clustered index,并新增10笔数据

create database testghost

go

use testghost

go

create table testtbl(c1 int identity primary key,c2 int ,c3 varchar(10))

go


create index idx1 on testtbl(c2)

go

insert into testtbl values

(1,'aaaa'),(2,'aaaa'),(3,'aaaa'),(4,'aaaa'),(5,'aaaa'),

(6,'aaaa'),(7,'aaaa'),(8,'aaaa'),(9,'aaaa'),(10,'aaaa')


检查该table的page情况

exec master.dbo.[GetPagRowCount] 'testghost','testtbl',-1

注:GetPagRowCount是我自写的proc,只是方便查阅各page的数据,也可以用dbcc page去查.

SQL SERVER Undelete 可能性探索(一)Clustered Table


接着删除 c1=5 的数据

delete from testtbl where c1=5


执行select查询,已经查不到数据了

SQL SERVER Undelete 可能性探索(一)Clustered Table


假设C1=5为误删数据,我们开始做undelete...


暂停  Ghost cleanup task

dbcc traceon(661,-1)


使用procedure去检查testtbl的page信息。可以看到 clustered页面跟index页面有Ghost record产生了。由于这里只有一笔Ghsot record,所以我们几乎可以确定被误删的数据存放的位置为pageid 78,这也是要undelete的目标页面。(这样的定位方式,可能会有不准确的问题,最好的方法是透过fn_dblog()去取得误删的PageID,再用这个procedure,两者结果比对,就不会错了)

SQL SERVER Undelete 可能性探索(一)Clustered Table


PageID确定后,接下来要确定出该笔数据所在的SlotID,

我们透过dbcc page,看它的实体纪录,从record_type可以看出来。Slot 4是Ghost record

SQL SERVER Undelete 可能性探索(一)Clustered Table

至此我们可以确定 PageID 78,SlotID 4,是我们要Undelete的目标。


这是一个 Clustered table,它的标记删除的方法,是在那笔Row 的第一个byte中加入识别的bits,以标记是Ghost record(heap table则不一样)。

------------------------------------------------------------------------------------------------

Row的第一个Byte,由0开始从右边数来第1~3的位,换算成十进制,代表的意义如下:

0(data record)

1(Forwarded record)

2(a forwarding stub)

3(Index record)

4(blob fragment or row overflow data)

5(ghost index record)

6(ghost data record)

7(ghost version record)

-------------------------------------------------------------------------------------------------


最后利用二进制编辑器,去找到DB的PageID 78,SlotID 4,将第一个byte的Ghost record识别位(十进制6),改成正常的数据位(十进制0)。


改完之后,再次执行select 查询,资料已经可以查询的到了...

SQL SERVER Undelete 可能性探索(一)Clustered Table


我再检查page信息,发现它仍然被标示成Ghost record

SQL SERVER Undelete 可能性探索(一)Clustered Table


重建所有index...

alter index ALL on testtbl rebuild


再检查page信息,已经正常了

SQL SERVER Undelete 可能性探索(一)Clustered Table


不过,这样的改法会造成系统基底表的纪录跟data page的纪录不符,因此在执行dbcc checktable时会有错误。

整个Clustered Table Undelete的过程,最后必需执行

dbcc checktable(testtbl,repair_allow_data_loss)

修复数据表,虽然是用repair_allow_data_loss但它不会造成数据漏失。


最后别忘了将flag 661关闭

dbcc traceoff(661,-1)


SQL SERVER Undelete 测试成功~~


以上的测试,主要在探索Undelete的可能性,这个测试证明了Undelete是可能的。不过要真正运用在OLTP的作业环境上,还有一段路要走。(异动量大、快速定位目标pageid/slotid、Downtime的问题)。


相关内容

热门资讯

伊朗总统:最高领袖决策过程遭人... 新华社德黑兰8月6日电 据伊朗伊斯兰共和国广播电视台5日报道,伊朗总统佩泽希齐扬说,目前与伊朗最高领...
1300亿元人民币,阿根廷:同... 据凤凰卫视报道,阿根廷中央银行8月5日宣布,与中国人民银行延长货币互换协议,规模为1300亿元人民币...
北京化工大学实验室发生安全事故... 8月5日凌晨,北京化工大学发生一起实验室安全事故,一名硕士研究生在实验过程中左手严重受伤。
“婚外胚胎案”原配朱女士回应胚... 近日,“患癌妻子申请销毁丈夫婚外胚胎遭拒案”持续引发关注。就在昨天(8月5日)下午,“患癌妻子朱女士...
马克龙称欧盟及其伙伴将继续加大... 【环球网报道 记者 张江平】据俄罗斯《共青团真理报》报道,对于法国总统马克龙发表关于加大向俄罗斯施压...
韩国外长称将为重启韩朝对话创造... 据凤凰卫视报道,韩国外交部长官赵显8月5日总统工作报告后召开记者会。有关朝鲜问题,他表示,为奠定半岛...
比矿泉水还轻的12英寸平板:华... 【环球网科技报道 记者 张阳】平板电脑市场近年来的发展并不乐观,据国际数据公司(IDC)预测,202...
“一箭双星” 捷龙三号海上发射... 封面新闻记者 边雪 8月5日10时38分,捷龙三号运载火箭在山东海阳附近海域点火升空,随后以“一箭双...
这届AI办公,名字比产品还难用 头图及封面来源 | GPT ChatGPT Work、Claude Cowork、Microsoft...