数据库文件损坏修复实战笔记

 今天终于碰到数据库文件头pfs损坏的案例。

环境:win server 2008+sql 2008 R2 SP2

问题描述:db某些page损坏

问题定位

 1、执行DBCC CHECKDB(DB, 'REPAIR_ALLOW_DATA_LOSS') With No_InfoMsgs, All_ErrorMsgs, TableResults;

 Note: 需要关注的是RefFile和RefPage这两个列,而不是File和Pge列。Level,stauts

 2 、备份永远是DBA第一条天规

Note: backup也报”SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确(应为 1:1256,但实际为 0:0)“ ,44码的手瞬间小抖了下,压力指数暴增。

 3、

复制代码
SELECT DB_NAME(database_id),[file_id],page_id,
CASE event_type
WHEN 1 THEN '823 or 824 or Torn Page'
WHEN 2 THEN 'Bad Checksum'
WHEN 3 THEN 'Torn Page'
WHEN 4 THEN 'Restored'
WHEN 5 THEN 'Repaired (DBCC)'
WHEN 7 THEN 'Deallocated (DBCC)'
END,
error_count,
last_update_date
FROM msdb..suspect_pages
复制代码

 

  Note: 执行结果10+条记录

PS: SQL 2008 Enterprise及更高版本支持 Mirroring和AlwaysOn 页面自动修复功能.但是仅限于Event ID in (823,824,829)错误。AlwaysOn动态管理视图sys.dm_hadr_auto_page_repair中会记录该自动修复操作

  4.  DBCC PAGE(dbid,filenum, pagenum,3) WITH TABLERESULTS

Note: 瞬间报一致性错误。观察执行结果:  PFS (1:1) 参数对应的value值为 ”NOT ALLOCATED“,可以断定PFS文件头损坏。正常情况下,dbcc page 可以显示详细 KeyHashValue,进而根据sys.partitions定位具体的object

 

解决方案

使用REPAIR_ALLOW_DATA_LOSS级别都不能修复data

1、  有全备bak,用restore page 方式:

      1) backup log db  to disk =''                    ---- 备份尾部日志

      2)  RESTORE DATABASE <database> PAGE='1:57, 1:202, 1:916, 1:1016' FROM disk WITH NORECOVERY;         --全备还原损坏的页

      3) RESTORE DATABASE <database>  from disk='第一步的log备份'                     ---还原到当前时间点

2.  没有全备,将数据导入到一个新建的空数据库里:

  · 通过vs 2010的schema compare, data compare

  · SSMS 右键--导入导出数据

  ·  BCP 个人推荐

3.  有全备,但是bak文件也受损

     RESTORE DATABASE dbname FROM DISK='‘   WITH CONTINUE_AFTER_ERROR

补充:

      DBCC CHECK在REPAIR_ALLOW_DATA_LOSS过程中发现页内数据有问题,是把整个页面的数据删除,以维护数据的一致性,所以会丢数据。

      DBCC CHECK需要多长时间跟DB的大小,io错误量有关。进度查询可以查看sys.dm_exec_requests中percent_complete字段信息

 2014-4-30补充:

什么是管理区分配页
管理区分配页是数据文件中特殊的页,用来跟踪和管理区分配,本篇将关注三种:

全局分配映射表 (GAM):记录已分配的区,对于一个数据文件,每4GB会有一个GAM页,它的ID总是为2,之后每511,232页出现一次。
        Page ID = 2 or Page ID % 511232

共享全局分配映射表 (SGAM) :记录当前用作混合区且至少有一个未使用的页的区,每4GB会有一个SGAM页,它的ID总是为3,之后每511,232页出现一次。
       Page ID = 3 or (Page ID – 1) % 511232

页可用空间 (PFS):记录每页的分配状态,是否已分配单个页以及每页的可用空间量,每64MB会有一个PFS页,它的ID总是为1,之后每8,088页出现一次。
       Page ID = 1 or Page ID % 8088

如果PAGE id是1/2/3,那么很明显会知道他们是什么管理区分配页,如果PAGE ID很大,那么我们有两个办法来区分它们:

一个办法是采用SQL脚本计算:

复制代码
Declare @PageID int;

-- Enter page number
-- e.g., 8088 = PFS page
Set @PageID = 8088;

Select Case
    When @PageID = 1 Or @PageID % 8088 = 0 Then 'Is PFS Page'
    When @PageID = 2 Or @PageID % 511232 = 0 Then 'Is GAM Page'
    When @PageID = 3 Or (@PageID - 1) % 511232 = 0 Then 'Is SGAM Page'
    Else 'Is Not PFS, GAM, or SGAM page'
    End
复制代码

另一个办法是采用DBCC PAGE来看它的m_type值:

 

posted @ 2014-04-25 12:01  莫问前程  阅读(1276)  评论(6编辑  收藏  举报