SQL SERVER系列(一):神秘的TornBits

一、DBCC PAGE命令


        在SQL Server 2000/2005中,有一个半公开的命令可以用来查看数据库系统内部数据页的具体内容,该命令允许你查看数据库中任意给定页的页头、数据行和行偏移表。 对于希望了解SQL Server内部存储的实现机制而言,这个命令是必不可少的工具,这个命令就是DBCC Page命令。

        DBCC PAGE( { dbid | dbname}, filenum,pagenum [,printopt])
   
       

其中:

dbid               :数据库ID

dbname        :数据库名称

filenum         :文件编号

pagenum     :文件内的页号

printopt         :输出选项

                        0             输出结果包含缓冲区头、页头 (默认值)

                        1             输出结果包含缓冲区头、页头、数据行、行偏移表

                        2            输出结果包含缓冲区头、页头、整个页、行偏移表

                        3            输出结果包含缓冲区头、页头、数据行(显示列值)、行偏移表


      
       以下就是一个使用DBCC PAGE命令的例子:
      

        在上图中,重点注意一下输出的页头信息,从中我们可以看出SQL Server在每个页的页头中存储了一些非常重要的信息,例如:上一页的页号(PrevPage)、下一页的页号(NextPage)、空闲字节数(FreeCnt)、日志序列号(LSN)等等,今天我们重点关注页头信息的最后一个域,即TornBits。    第一次看到这个词的时候也许会让人感到非常迷惑,其实它的作用是实现SQL Server中的一项非常重要的功能——残缺页检测(Torn Page Detection),如下图所示。
      


二、为什么要进行残缺页检测?

        我们知道,SQL Server的崩溃恢复算法是基于先写日志(WAL:Write-Ahead Log)的ARIES算法,该算法的最基本思想是在对任何一个数据页进行修改(更新)之时,都需要使用独立的日志记录所做的修改,以便日后能够根据此日志重做或者撤消此修改操作。所谓先写日志的意思是,任何一个被修改的数据页在被写入(刷新)到磁盘之前,该页所对应的修改日志必须被提前写入磁盘,这样就能避免在系统崩溃或者断电的情况下出现数据页已经被刷新到磁盘而日志尚未刷新到磁盘而引起无法撤消修改操作(回滚事务)的情况。
        一般来说,上述的崩溃恢复算法已经足够强大,在不出现硬件故障(例如硬盘损坏)的前提下,99.9%的情况下能够确保即使系统崩溃也不会对数据库中的数据造成任何破坏。但任何事情都有例外,的确存在0.1%的情况下,系统的突然断电会对数据库中的数据造成不可恢复(指在管理员不介入的情况下)的破坏。
        严格来说,产生这0.1%的例外情况并非是崩溃恢复算法本身的原因,而应该是SQL Server在实现该恢复算法时,没有完全满足该恢复算法的一个前提假设,这个前提假设就是:在将被修改的数据页写入到磁盘时,必须保证该写入操作是原子的,即要么整个数据页都写入成功,要么一个字节都没有写入到磁盘。如果这个前提假设没有得到保证,那么写入到磁盘中的数据页从理论上说就可能处于一种中间状态(既非修改前、也非修改后),此时该数据页就处于一种不可恢复的状态,这种页就成为残缺页(Torn Page)。
        众所周知,在SQL Server 2000中,每个数据页的大小为8KB(相当于16个512B的磁盘扇区),写入一个数据页就意味着需要写入16个磁盘扇区。我们知道,磁盘的最小IO单位是一个扇区(512B),而且磁盘驱动器可以保证每个扇区的IO操作是原子的,即要么512B内容完全写入成功,要么一个字节页不会写入。但是由于SQL Server的一个数据页对应16个扇区,因此单个扇区的原子IO操作并不能保证单个数据页的IO操作也是原子的(可以设想一下,假设磁盘驱动器在刚刚写入了前8个扇区之后,这时候系统突然掉电,后8个扇区的内容就无法写入了【注】)。
        正因为如此,SQL Server在第一次将数据页从磁盘读取到内存的时候,需要检测这种写入操作没有正确完成的页面,因为这种页面中的数据已经被破坏了。一旦SQL Server检测到这种页面的存在,将引发严重的 I/O 错误。

三、如何进行残缺页检测?

        前面已经讲到,SQL Server中的一个数据页相当于16个磁盘扇区,为了进行残缺页检测,SQL Server在页的每个512字节扇区末尾会放置一个2位签名,这个签名可能是01或者10,每写入一次磁盘,这些签名就会翻转一次。写入签名的操作是在数据页写入到磁盘之前进行的,而残缺页检测是在从磁盘读取数据页之后进行的,SQL Server通过验证上述写入的每个扇区末尾的签名是否正确,就可以检测到是否所有的16个扇区都正确写入。一旦某个扇区的签名不正确,则说明该数据页没有被正确写入,因此就是残缺页。
         那么页头中的TornBits又是什么呢?也许有些人已经猜到了,没错,TornBits就是保存了那些写入签名的位置的原始数据(在写入签名之前)。所以,根据TornBits本身并不能判断数据页是否正确写入,而是要根据TornBits所对应的那些签名位的状态来判断,至此TornBits的神秘面纱也终于被揭开了。

四、出现了残缺页之后如何恢复?

        检测到残缺页并非就意味着数据库不能再恢复到正确状态,如果之前做过数据库的完整备份,那么恢复数据库还是可能的。具体的做法是:首先使用之前的完整备份还原数据库,将数据库恢复到之前的某个一致状态,然后再应用自上次完整备份之后的事务日志,这样即可恢复数据库。当然了,这个操作只能由管理员手工启动,不能由SQL Server的事务恢复系统自动完成。

五、SQL Server 2005中的新机制

        在SQL Server 2005中,除了保留原有的“残缺页检测”机制之外,还引入了新的“校验和保护”机制,这种机制提供了更强大的数据完整性检查。此方法将对写入每一页中的数据进行校验和计算并将其值存储在页头中,每次从磁盘读取存储了校验和的页时,数据库引擎将重新计算页中数据的校验和。如果新的校验和不同于已存储的校验和,则引发错误824。校验和保护比残缺页保护能捕获到更多的错误,因为它受到页中每个字节的影响,但它对资源的消耗较多。启用校验和后,当缓冲区管理器从磁盘读取页时均可以检测到因电源故障以及硬件或固件故障导致的错误。




【注】有些磁盘驱动器带有备份电源,这样即使在数据页写入磁盘的过程中间发生断电的情况下,备份电源也可以确保磁盘高速缓存中的内容不会丢失,从而也就确保了针对数据页的IO操作也是原子的,这种情况下,也就没有必要使用残缺页检测机制。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值