科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道当数据库出现页损坏或校验和出错时如何处理

当数据库出现页损坏或校验和出错时如何处理

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

当数据库出现页损坏或校验和出错时如何处理

作者:csdn 来源:csdn 2009年12月18日

关键字: 问答 MS-SQL Server

  • 评论
  • 分享微博
  • 分享邮件

当数据库出现页损坏或校验和出错时如何处理

当数据库出现页损坏或校验和出错时如何处理

作者:perfectaction
日期:2009.09.27
最近一直在进一步学习数据库故障的处理方面的知识,做为一个数据库维护人员,我即期望遇到所有的数据库出错的案例,以增加自己的经验,但同时又担心遇到这样或那样无法处理的数据库故障而导致数据丢失。

前几天看到一个文章,是说一个网站管理员在招聘DBA时,提出一个问题:“如果在sql server 日志里发现一个页损坏或是校验和错误应该如何处理?”网站管理员描述,大概有90%的应聘者都会采用一个方案,用DBCC CHECKDB加上其中的一个修复选项,但其中也基本没有人能具体解释DBCC CHECKDB修复的过程或是工作原理及能修复到什么程度。

借助联机文档以及个人的一些理解和经历,解释一下如何面对这个问题:"当数据库出现页损坏或校验和出错时如何处理?"

首先,需要先了解DBCC CHECKDB,联机文档url:
http://technet.microsoft.com/zh-cn/library/ms176064.aspx

通过联机文档,可以得知有REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD三个修复选项,而提供实际功能的只有REPAIR_ALLOW_DATA_LOSS和REPAIR_REBUILD两个,其中REPAIR_ALLOW_DATA_LOSS 尝试修复报告的所有错误,这些修复可能会导致一些数据丢失;而且REPAIR_REBUILD执行不会丢失数据的修复,包括快速修复(如修复非聚集索引中缺少的行)以及更耗时的修复(如重新生成索引);可见REPAIR_REBUILD是我们期望的。

当你从sql server log里或是在程序查询数据库或是定期通过DBCC CHECKDB为数据库做体检的时候,出现了页损坏或校验和出错信息时,如:
---------------------------------------------------------------------------------------------------------------------------------
M8928sg , Level 16, State 1, Line 1
Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data): Page (1:94299) could not be processed.  See other errors for details.
Msg 8939, Level 16, State 98, Line 1
Table error: Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data), page (1:94299). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed.
CHECKDB found 0 allocation errors and 2 consistency errors in table 'yourtable' (object ID 2088535921).
CHECKDB found 0 allocation errors and 2 consistency errors in database 'yourdb'.
repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (yourdb).
---------------------------------------------------------------------------------------------------------------------------------
现在我们应该如何做?下面分析一下

1.通过上面的提示,告诉我们:对象 2088535921出错,它是一个表,页面为1:94299
2.接下来,我们判断损坏的页在堆上还是聚集索引还是非聚集索引,sql server方法为:
SQL code    dbcc traceon (3604, -1)
    go
    dbcc page('yourdb', 1, 94299, 3)
    go

  在输出的结果里(会报错,但可以看到页头信息),可以看到
SQL codeMetadata: IndexId = n
 
  如果n是0而表示是堆,1表示是聚集索引,>1是表示非聚集索引
  ps:其实从提示信息的Object ID 2088535921, index ID 0 ,也可以简单判断是堆.
3.根据上面的第2步,我们知道这个页面是堆,这对我们来讲,不是好消息,因为如果是>1,我们可以删除该非聚集索引,再重建索引,不会丢失数据,而0或1则是元数据受损,这意味着有丢失元数据的可能性,如果这时用
SQL code    dbcc checkdb('yourdb',repair_allow_data_loss)

则可能出现元数据的丢失;
  那么如何仅仅修复这个数据页呢,这里我们假设该库是full模式,并且有良好的备份策略,有全备和日志备份。
  那么我们可以进行页面级还原操作,具体步骤如下:

  a.首先进行一次日志备份,如果你不放心,还可以再做一个全备;
SQL code    backup log yourdb to disk='D:\DBBak\yourdb_a.trn'

  b.通过完整备份来恢复该page. (yourdb.bak是一个全备。);
SQL code    restore database yourdb page= '1:94299' from disk='D:\DBBak\yourdb.bak' with norecovery

  c.恢复这个全备之后的差异(假设有差异yourdb.dif),如果没有差异备,直接到d步骤;
SQL code    restore database yourdb from disk='d:\DBBak\yourdb.dif'  with norecovery

  d.恢复之后的log备份,可能有多个(假设为yourdb_1.trn,yourdb_2.trn);
SQL code    restore log yourdb from disk='d:\DBBak\yourdb_1.trn' with norecovery
    restore log yourdb from disk='d:\DBBak\yourdb_2.trn' with norecovery
    restore log yourdb from disk='d:\DBBak\yourdb_a.trn' with norecovery

  e.做一个最新的日志备;
SQL code    backup log yourdb to disk='D:\DBBak\yourdb_e.trn'

  f.还原最后的(e步骤)日志备份;
SQL code    restore log yourdb from disk='d:\DBBak\yourdb_e.trn' with recovery

  g.结束
4.经过步骤三之后,我们再来检查一下该表是否还有错,从提示信息Object ID 2088535921里,我们查出表名tbname;
SQL code    select object_name(2088535921)
    然后 dbcc checktable('tbname')检测,如果没有报错,则表示修复完成

5.最后,对整个库再做一次dbcc checkdb检查;


在sql server 2005/2008企业版进行上述操作,数据库是联机的,仅当访问该page(1:94299)时不能访问,其它page均可正常访问,在还原后续日志的过程,sql server仅针对有关该页面的事务日志进行恢复操作;而在在标准版只能脱机修复;
在dbcc checkdb修复选项里,用repair_rebuild修复数据,联机文档称是不丢失数据,但在某些环境下可能也会丢失数据,不过,我没遇到过:)
用repair_allow_data_loss选项时,联机文档称可能会丢失数据,而对于堆或聚集索引的页损坏,sql server 会释放该页面,造成数据的丢失,但repair_allow_data_loss选项有两种情况是不会丢失数据,一种是非聚集索引上的页错误,另外是lob页数据错误。

总结:
    一定要有良好的数据库备份策略,备份重于一切;
    要有异机备份,并且时时同步该备份文件;
    当数据库出现故障时,不要过于心急,冷静分析一下错误;
    如果不能确定如何做,可以借助google,如果你的错误信息里中文的,请翻译成英文后再google,这样搜到解决方案的可能性更大;
    做修复时,一定要再备一次数据库;
    dbcc checkdb的repair_allow_data_loss选项永远是最后的选择。

结束,如有错误,请指正。


 

 

 

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章