SQL Server数据库损坏、检测以及简单的修复办法 数据库损坏( 二 )


与IO相关的三种错误
从上面的校验和原理可以看出 , SQL Server是可以检测页面损坏的 。这时 , 具体表现可能是以下三种错误之一:
823错误 , 即所谓的硬IO错误 , 可以理解为SQL Server想要读取页面 , 但是Windows告诉SQL Server无法读取页面 。
824错误 , 即所谓的软IO错误 , 可以理解为SQL Server已经读取了页面 , 但是通过计算校验和的等效值发现没有匹配 , 所以SQL Server认为页面已经损坏 。
85错误 , 即所谓的重试错误 。
其中 , 上面提到的823和824错误是严重错误 , 错误级别为24 , 所以会记录在Windows应用程序日志和SQL Server错误日志中 , 导致错误的页面会记录在msdb.dbo.suspect_pages中 , 错误页面的编号也会记录在SQL Server错误日志中 , 如图2所示 。
图2.824 SQL Server错误记录中的错误描述
因此 , 如果我们有一个完美的备份 , 我们可以通过备份恢复页面(再次强调 , 对于DBA来说 , 没有问题) 。清单1显示了一个简单的页面恢复代码 。
USE[master]RESTOREDATABASE[Corrupt_DB]PAGE='1:155'FROMDISK=N'C:\xxx.bak'WITHFILE=1,NORECOVERY,NOUNLOAD,STATS=5清单1 。一个简单的页面恢复代码 , 用于从备份中恢复文件ID1中的第155页 。
我记得我们之前说过 , 在读取页面以计算校验和时出现了错误 。这可能是写入永久存储器的页面本身的错误 , 或者是读取页面的过程中的错误 。此时 , SQL Server将再次尝试从IO子系统读取页面 , 最多尝试4次 。如果校验和在4次尝试中通过 , 则为825错误 , 否则为824错误 。请注意 , 与823和824错误不同 , 825错误是一条级别仅为10的消息 。
因此 , 因为有固定的错误号 , 所以可以在SQL Server代理中为823和824设置警报 。
备份校验和
只有在使用页面时 , 才会检查上述页面校验和的正确性 。备份数据库时 , 可以指定CheckSum选项 , 使备份读取的页面也计算校验和 , 从而确保备份的数据库不会损坏 。我们可以在图3的备份选项中注意到这两项:
图3 。校验和和出错后继续选项
如果启用了校验和 , 当在备份过程中发现页面校验和错误时 , 备份将终止;而如果启用了Continue_After_Error选项 , 当检测到校验和错误时 , 备份将继续并成功完成 。
如果为备份启用了校验和选项 , 则除了检查每页的校验和之外 , 在备份完成后 , 还会计算整个备份的校验和并将其存储在备份头中 。
此外 , 对于备份 , 我们可以通过Restore Verifyonly with CheckSum来验证备份 , 以确保备份的数据不会损坏 。
数据库名如前所述 , SQL Server查找错误有两种方式 , 即读取页面时和备份时(本质上是读取页面) 。但是如果我们想要更积极地检查数据一致性 , 那么我们应该定期使用CheckDB来检查数据一致性 , 这样就不会在生产时读取数据时发现错误 。
CheckDB命令将对整个数据库进行所有的一致性检查 。当检查对象是Master数据库时 , CheckDB也会检查ResourceDB 。
清单2显示了CheckDB最简单的用法 。在当前数据库上下文中直接执行CheckDB将检查当前数据库中的所有内容 。
DBCCCHECKDB清单2 。2的最简单用法 。数据库名
在企业版中 , CheckDB命令将通过多线程执行 , 并检查整个数据库的一致性 。在这个过程中使用了内置的数据库快照 , 所以不会造成拥塞 , 但是CheckDB会消耗大量的CPU、内存和IO 。因此 , 应该在维护窗口期间或系统空闲时执行CheckDB 。
默认情况下 , CheckDB命令会输出所有信息 , 但通常我们并不关心这些信息 , 而只关心错误信息 。因此 , 在实践中 , 通常给DBCC参数没有明确的信息 , 如清单3所示 。
DBCCCHECKDBWITHNO_INFOMSGS;清单3 。CheckDB通常带有No_InfoMsgs参数
实际上 , CheckDB是一组命令的总结 。CheckDB将依次检查以下内容:
第一次检查系统表
分配单元检查(DBCC检查分配)
检查完整的系统表 。
对所有表执行一致性逻辑检查(DBCC检查表)
元数据检查(DBCC检查目录)

推荐阅读