热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

当数据库出现页损坏或校验和出错时如何处理作者:nzperfect/perfectaction日期:2009.09.27Email:nzperfect@gmail.com最近一直在进一步学习数据库故障的处理方面的知识,做为一个数据库维护

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

  作者:nzperfect / perfectaction

  日期:2009.09.27

  Email:nzperfect@gmail.com

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

  前几天看到一个文章,是说一个网站管理员在招聘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方法为:

  dbcc traceon (3604, -1)

  go

  dbcc page('yourdb', 1, 94299, 3)

  go

  在输出的结果里(会报错,但可以看到页头信息),可以看到

  Metadata: IndexId = n

  如果n是0而表示是堆,1表示是聚集索引,>1是表示非聚集索引

  ps:其实从提示信息的Object ID 2088535921, index ID 0 ,也可以简单判断是堆.

  3.根据上面的第2步,我们知道这个页面是堆,这对我们来讲,不是好消息,因为如果是>1,我们可以删除该非聚集索引,再重建索引,不会丢失数据,而0或1则是元数据受损,这意味着有丢失元数据的可能性。

  那么如何仅仅修复这个数据页呢,这里我们假设该库是full模式,并且有良好的备份策略,有全备和日志备份。

  那么我们可以进行页面级还原操作,步骤如下:

  a.首先进行一次日志备份,如果你不放心,还可以再做一个全备;

  backup log yourdb to disk='D:DBBakyourdb_a.trn'

  b.通过完整备份来恢复该page. (yourdb.bak是一个全备。);

  restore database yourdb page= '1:94299' from disk='D:DBBakyourdb.bak' with norecovery

  c.恢复这个全备之后的差异(假设有差异yourdb.dif),如果没有差异备,直接到d步骤;

  restore database yourdb from disk='d:DBBakyourdb.dif' with norecovery

  d.恢复之后的log备份,可能有多个(假设为yourdb_1.trn,yourdb_2.trn);

  restore log yourdb from disk='d:DBBakyourdb_1.trn' with norecovery

  restore log yourdb from disk='d:DBBakyourdb_2.trn' with norecovery

  restore log yourdb from disk='d:DBBakyourdb_a.trn' with norecovery

  e.做一个最新的日志备;

  backup log yourdb to disk='D:DBBakyourdb_e.trn'

  f.还原最后的(e步骤)日志备份;

  restore log yourdb from disk='d:DBBakyourdb_e.trn' with recovery

  g.结束

  4.经过步骤三之后,我们再来检查一下该表是否还有错,从提示信息Object ID 2088535921里,我们查出表名tbname;

  tbname: select object_name(2088535921)

  然后 dbcc checktable('yourtable')检测,如果没有报错,则表示修复完成

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

  ps:需要注意的是,sql server 的page级恢复在企业版和开发版中,支持联机恢复page数据,在标准版只能脱机修复;

  在dbcc checkdb修复选项里,用repair_rebuild修复数据,联机文档称是不丢失数据,但在某些环境下可能也会丢失数据,不过,我没遇到过:)

  用repair_allow_data_loss 选项时,联机文档称可能会丢失数据,而对于堆或聚集索引的页损坏,sql server 会释放该页面,造成数据的丢失,但repair_allow_data_loss选项有两种情况是不会丢失数据,一种是非聚集索引上的页错误,另外是 lob页数据错误。

  总绍:

  一定要有良好的数据库备份策略,备份重于一切;

  要有异机备份,并且时时同步该备份文件;

  当数据库出现故障时,不要过于心急,冷静分析一下错误;

  如果不能确定如何做,可以借助google,如果你的错误信息里中文的,请翻译成英文后再google,这样搜到解决方案的可能性更大;

  做修复时,一定要再备一次数据库;

  dbcc checkdb的repair_allow_data_loss选项永远是最后的选择。

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

 


推荐阅读
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 《蝴蝶之吻》:Bob Carlisle的深情献礼
    美国抒情乡村歌手Bob Carlisle在他女儿Brooke十六岁生日前夕,目睹她即将展翅高飞,心中感慨万千。他以这首《Butterfly Kisses》表达了对女儿无尽的父爱与美好回忆。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
  • #print(34or4 ... [详细]
  • 本文将详细介绍多个流行的 Android 视频处理开源框架,包括 ijkplayer、FFmpeg、Vitamio、ExoPlayer 等。每个框架都有其独特的优势和应用场景,帮助开发者更高效地进行视频处理和播放。 ... [详细]
  • 本文探讨了为何相同的HTTP请求在两台不同操作系统(Windows与Ubuntu)的机器上会分别返回200 OK和429 Too Many Requests的状态码。我们将分析代码、环境差异及可能的影响因素。 ... [详细]
  • 本文将探讨2015年RCTF竞赛中的一道PWN题目——shaxian,重点分析其利用Fastbin和堆溢出的技巧。通过详细解析代码流程和漏洞利用过程,帮助读者理解此类题目的破解方法。 ... [详细]
  • 离线安装Grafana Cloudera Manager插件并监控CDH集群
    本文详细介绍如何离线安装Cloudera Manager (CM) 插件,并通过Grafana监控CDH集群的健康状况和资源使用情况。该插件利用CM提供的API接口进行数据获取和展示。 ... [详细]
  • CSS高级技巧:动态高亮当前页面导航
    本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ... [详细]
  • 本文介绍下,在php编程中,用正则表达式判断某一字符串是否为域名的方法,有需要的朋友参考下吧。通常匹配域名的格式要求:1、域 ... [详细]
  • 探讨在PHP开发中,如何选择使用Cookie或数据库来优化网站性能,特别是在处理用户保存的搜索结果时。 ... [详细]
  • 经常账户逆差对经济的影响:资产价格波动视角
    近年来,中国的经常账户余额无论是绝对规模还是占GDP的比率均显著下降。2018年第一季度,中国首次在十余年来出现经常账户逆差。本文探讨了这种变化对国内资产价格波动的具体影响,并结合全球主要经济体的经验数据进行了分析。 ... [详细]
  • 本文详细介绍了如何在Kendo UI for jQuery的数据管理组件中,将行标题字段呈现为锚点(即可点击链接),帮助开发人员更高效地实现这一功能。通过具体的代码示例和解释,即使是新手也能轻松掌握。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
author-avatar
用释怀来成全悲伤_490_905_560
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有