我经常被专业人士问道:在SQL SERVER 2008 中CHECKDB仍然被推荐使用吗?从SQL 2005开始SQL计算校验和来避免物理页损坏。然而,以我的经验(从SQL SERVER 7.0开始),我却从未能清楚地说明CHECKDB不是必要的。
其他人有好的建议吗?
_____________________________________________ From: Robert Dorr Sent:Friday, February 20, 2009 9:04 AM
这个问题曾经被提到很多次。的确,增加的数据库页审计校验和(DATABASE PAGE AUDIT CHECKSUM)减少了一些需要执行CHECKDB的次数。历史记录也表明,从SQL SERVER 7.0起数据库引擎的性能得到了显著提升,从而进一步减少了这种必要性。
但是,像检验和这样的功能只是保证写入磁盘的是什么,读取出来就是什么。它并不验证许多其它的数据完整性问题,而CHECKDB就是为此面设计。比如CHECKDB验证系统表的元数据,页链,索引排序等等。
这个问题的答案就是:从SQL SERVER 7.0起,这种必要性已经减少。一个严密的恢复计划应当包括数据库全备和CHECKDB,用以保证此计划的各个方面都是可用的。例如:你有一个干净的数据库,备份它,并用于恢复。因为在备份媒体迁移过程中发生了某些事情,它被损坏了。SQL2008中的校验和备份(Backup with CHECKSUM)能够有益于这种场景。有些供应商说:这个永远没有必要,数据库引擎能搞定所有事情。我觉得这种说法有点片面。
例如:
我曾经研究内存和ECC故障率。根据研究,内存传输中单独的位改变会导致数据损坏。这就是为什么SQL SERVER 2005对缓存池(Buffer Pool)增加了恒量页扫描(Constant Page Scanning)。当页在内存中时,恒量页扫描技术对校验和取样,用以确保只读页不会因为这样的错误而改变。这个技术用益于数据稳定,但是不能捕获所有的事情。所以还是可能发生ECC故障,缓存池中的页可能被改变并成功计算校验和写入磁盘。我曾经处理过一个案例就是这个问题:一个数据值中间的一个位被改变。这个列碰巧是一个被外键引用的主键。所以主键值是9,可能会被改变成19。因为这个重复的值19,导致了违反了主键约束,而外键引用的值9也不存在了。这个数据的改变不是受事务影响而发生的,只是页中任何一个值的改变都会导致。这个数据库配置了日志传送,而备机不会显示此错误,结果把“水搞得更混”。因为不是SQL SERVER直接导致主键值改变的,所以数据库日志也不会记录这个错误。所以即使做一个干净的还原,CHECKDB也不能发现问题。在做全备或者差备并成为历史存档备份前,在主库上执行DBCC CHECKDB是发现这种问题的唯一途径。
像ECC SQL SERVER bugs一样,更多的XPROC和COM对象bugs导致了同样的错误。如果XPROC中的代码错误地更新了内存,将出现同样模式的错误。
过去10年中我们在存储方面排名第一的问题是Stale Read(从硬件高速缓存中返回页的前一版本而不是最版本).因为这只是页的较旧版本,所以校验和测试通常不会失败。这样一个场景:我妻子存了$500到时我们的活期账户,几分钟后我取出$500.硬件高速缓存加载我妻子存款之前的账户结余。我妻子的存款被提交并写入了磁盘,但是硬件高速缓存没有被更新。当我取钱时更新未能找到这笔存款,便错误地使用初始的账户结余更新了我的账户。SQL SERVER 不会直接知道这些事情,所以这就变成了一个逻辑事务丢失。