• (4.4)dbcc checkdb 数据页修复


    转自:http://blog.51cto.com/lzf328/955852 三篇

    一、创建错误数据库

    以前看Pual写过很多数据恢复的文章,他很多的测试都是自己创建的Corrupt数据库,其实我们自己也可以。

     DBCC CHECKDB MSDN:https://docs.microsoft.com/zh-cn/sql/t-sql/database-console-commands/dbcc-checkdb-transact-sql?view=sql-server-2017

    
    
    ALTER DATABASE Corrupt2008DemoFatalCorruption SET EMERGENCY        ---将数据库状态改为紧急模式
    ALTER DATABASE Corrupt2008DemoFatalCorruption SET SINGLE_USER        --将数据库改为单用户访问
    DBCC CHECKDB(Corrupt2008DemoFatalCorruption,repair_allow_data_loss)   ---运行repair_allow_data_loss修复
    DBCC CHECKDB withNO_INFOMSGS                          ---修复完成后运行DBCC CHECKDB确定没有问题
    ALTER DATABASE Corrupt2008DemoFatalCorruption SET MULTI_USER        --将数据库更改为多用户访问

    --通过备份文件还数据页
    命令:
    ---Corrupt.bak是在数据库损坏之前的备份 restore database corrupt page='1:78'fromdisk='d:mssqlcorrupt.bak'withnorecovery backup log corrupttodisk='d:mssqlcorrupt.trn' restore log corruptfromdisk='d:mssqlcorrupt.trn'withrecovery 页面还原用于修复隔离出来的损坏页。 还原和恢复少量页面的速度可能比还原一个文件更快,因此减少了还原操作中处于脱机状态的数据量。 还原页步骤: 1. 获取要还原的损坏页的页 ID。 2. 从包含页的完整数据库备份、文件备份或文件组备份开始进行页面还原。 在 RESTORE DATABASE 语句中,使用 PAGE 子句列出所有要还原的页的页 ID。 3. 应用最近的差异。 4. 应用后续日志备份。 5. 创建新的数据库日志备份,使其包含已还原页的最终 LSN,即最后还原的页脱机的时间点。 设置为顺序中首先还原的最终 LSN 是重做目标 LSN。包含该页的文件的联机前滚可以在重做目标 LSN 处停止。 6. 还原新的日志备份。 应用这个新的日志备份后,就完成了页面还原,可以开始使用页了。

    SQL Server页级别的数据恢复
    
    
    --1.最近的完整备份
    BACKUP DATABASE DBName TO DISK = N'C:Test.bak'
     
    --2.发现错误页(可以人为破坏)
    SELECT * FROM msdb.dbo.suspect_pages
     
    --3.立即备份日志1
    BACKUP LOG DBName TO
    DISK = 'C:Test_LOG1.bak'
    WITH INIT
     
    --3.用完整备份,还原数据损坏的页
    USE Master
    RESTORE DATABASE DBName
    PAGE = '1:832'
    FROM DISK = 'C:Test.bak'
    WITH NORECOVERY
     
    --4.备份日志2
    BACKUP LOG DBName TO
    DISK = 'C:Test_LOG2.bak'
    WITH INIT
     
    --5.还原日志1
    RESTORE LOG DBName FROM
    DISK = 'C:Test_LOG1.bak'
    WITH NORECOVERY
     
    --6.还原日志2
    RESTORE LOG DBName FROM
    DISK = 'C:Test_LOG2.bak'
    WITH NORECOVERY
     
    --7.还原数据库状态,大工告成
    RESTORE DATABASE DBName WITH RECOVERY
     
    /*
    人为破坏数据页
    1.查看表使用的数据页
    DBCC IND(DBName, TableName, -1)
    2.修改数据库访问模式
    ALTER DATABASE DBName SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    3.破坏数据页(1是PageFID,832是PagePID)
    DBCC WRITEPAGE(DBName, 1, 832, 0, 1, 0x41, 1)
    4.修改数据库访问模式
    ALTER DATABASE DBName SET MULTI_USER
    */
    
    

    1. 创建数据库数据表插入数据:

    use master

    go

    create databasecorrupt

    use corrupt

    go

    create tabletest(IDint, namevarchar(10))

    declare @int asint

    set @int = 1

    while @int <20

    begin

    insert intotestvalues(@int,'allentest')

    set @int += 1

    end

    2. 使用DBCC IND查看Test表所在的PageID

    dbcc ind(corrupt,test,1)

    3. 用DBCC PAGE查看TEST表的内容:

    dbcc traceon(3604,-1)

    go

    dbcc page(corrupt,1,55,1)

    这里我们只修改Slot 1数据,偏移地址为78,转化为10进制为120.

    所以当前Slot1的实际地址为:55*8192+120=450680

    4. 停掉SQL ServerXVI32打开数据文件然后输入地址找到对应的数据(可以看到数据与Step3中看到的数据一致)。

    5. 对数据进行修改保存关闭XVI32。

    6. 重启SQL Server然后用DBCC PAGEPage 55 Slot1内容(已经被更改)

    7. DBCCCHECKDB检查数据库发现下面的错误:

    dbcc checkdb withno_infomsgs

    Msg8928, Level 16, State 1, Line 1

    Object ID2105058535, index ID 0, partition ID 72057594038779904, alloc unit ID72057594039828480 (type In-row data): Page (1:55) could not be processed. See other errors for details.

    Msg8939, Level 16, State 98, Line 1

    Table error: ObjectID 2105058535, index ID 0, partition ID 72057594038779904, alloc unit ID72057594039828480 (type In-row data), page (1:55). Test (IS_OFF (BUF_IOERR,pBUF->bstat)) failed. Values are 12716041 and -4.

    这样我们就创建了一个Corrupt的数据库,稍后我会花时间测试恢复(page restore/ dbcc checkdbrepair_allow_data_loss/rebuildSQL Server log),然后把测试步骤发出来.

    如果你不想自己创建的话,也可以使用Paul提供的两个Corrupt数据库做测试。

    二、页面还原

    上文我们已经新建了Corrupt的数据库,今天我们就用页面还原修复损坏的页面。

    首先我们允许DBCC CHECKDB查看损坏的页面ID:

    DBCC CHECKDB withNO_INFOMSGS

    Msg 8928, Level 16,State 1, Line 1

    Object ID2105058535, index ID 0, partition ID 72057594038779904, alloc unit ID72057594039828480 (type In-row data): Page (1:78) could not be processed. See other errors for details.

    Msg 8939, Level 16,State 98, Line 1

    Table error: ObjectID 2105058535, index ID 0, partition ID 72057594038779904, alloc unit ID72057594039828480 (type In-row data), page (1:78). Test (IS_OFF (BUF_IOERR,pBUF->bstat)) failed. Values are 12716041 and -4.

    repair_allow_data_loss is the minimumrepair level for the errors found by DBCC CHECKDB (corrupt).

    建议的修复 是repair_allow_data_loss,但是如果用repair_allow_data_loss修复的话就会有数据损失,而且可能会造成数据一致性问题。SQL Server 2005之后提供了Page Restore,使用Page Restore我们可以直接修复这个损坏的页面。

    命令:---Corrupt.bak是在数据库损坏之前的备份

    restore database corrupt page='1:78'fromdisk='d:mssqlcorrupt.bak'withnorecovery

    backup log corrupttodisk='d:mssqlcorrupt.trn'

    restore log corruptfromdisk='d:mssqlcorrupt.trn'withrecovery

    页面还原用于修复隔离出来的损坏页。 还原和恢复少量页面的速度可能比还原一个文件更快,因此减少了还原操作中处于脱机状态的数据量。

    还原页步骤:

    1. 获取要还原的损坏页的页 ID。

    2. 从包含页的完整数据库备份、文件备份或文件组备份开始进行页面还原。 在 RESTORE DATABASE 语句中,使用 PAGE 子句列出所有要还原的页的页 ID。

    3. 应用最近的差异。

    4. 应用后续日志备份。

    5. 创建新的数据库日志备份,使其包含已还原页的最终 LSN,即最后还原的页脱机的时间点。 设置为顺序中首先还原的最终 LSN 是重做目标 LSN。包含该页的文件的联机前滚可以在重做目标 LSN 处停止。

    6. 还原新的日志备份。 应用这个新的日志备份后,就完成了页面还原,可以开始使用页了。

    更多页面还原信息请参考:http://msdn.microsoft.com/zh-cn/library/ms175168.aspx

    三、repair_allow_data_loss 页面修复

    运行DBCC CHECKDB withNO_INFOMSGS发现下面的错误:

    Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test ((m_type >= DATA_PAGE &&m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level== BASIC_HEADER)) failed. Values are 0 and 0.

    Msg 8939, Level 16,State 5, Line 4

    Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test (m_headerVersion == HEADER_7_0) failed.Values are 0 and 1.

    Msg 8939, Level 16,State 6, Line 4

    Table error: ObjectID 7, index ID 2, partition ID 562949953880064, alloc unit ID 562949953880064(type In-row data), page (1:54). Test ((m_type >= DATA_PAGE &&m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level== BASIC_HEADER)) failed. Values are 0 and 0.

    repair_allow_data_loss is the minimum repairlevel for the errors found by DBCC CHECKDB (Corrupt2008DemoFatalCorruption).

    最小的修复级别是repair_allow_data_loss

    如果我们没有数据库备份,无法使用页面还原,那么我们就需要用repair_allow_data_loss来修复(会有数据损失,而且不一定所有的都是可以恢复的 参考:http://blog.csdn.net/smithliu328/article/details/7827147

    下面我们就使用DBCC CHECKDH repair_allow_data_loss来修复损坏的数据库。

    ---将数据库状态改为紧急模式

    ALTER DATABASE Corrupt2008DemoFatalCorruption SETEMERGENCY

    GO

    --将数据库改为单用户访问

    ALTER DATABASE Corrupt2008DemoFatalCorruptionSETSINGLE_USER

    GO

    --运行repair_allow_data_loss修复

    DBCC CHECKDB(Corrupt2008DemoFatalCorruption,repair_allow_data_loss)

    Go

    ---修复完成后运行DBCC CHECKDB确定没有问题

    DBCC CHECKDB withNO_INFOMSGS

    Go

    --将数据库更改为多用户访问

    ALTER DATABASE Corrupt2008DemoFatalCorruptionSETMULTI_USER

    如果建议的修复级别为REPAIR_REBUILD,您可以放心执行,不会有数据损失这包括快速修复(如修复非聚集索引中缺少的行)以及更耗时的修复(如重新生成索引)。

    注意事项:

    仅将 REPAIR 选项作为最后手段使用。 若要修复错误,建议您通过备份进行还原。 修复操作不会考虑表本身或表之间可能存在的任何约束。如果指定的表与一个或多个约束有关,建议您在修复操作后运行 DBCC CHECKCONSTRAINTS。如果必须使用 REPAIR,则运行不带有修复选项的 DBCC CHECKDB 来查找要使用的修复级别。如果使用 REPAIR_ALLOW_DATA_LOSS 级别,则建议您在运行带有此选项的 DBCC CHECKDB 之前备份数据库。

  • 相关阅读:
    迷宫寻找路径数
    136. 只出现一次的数字
    48. 旋转图像
    283. 移动零
    面试题 01.06. 字符串压缩
    位运算符
    367. 有效的完全平方数
    868. 二进制间距
    SpringAOP表达式
    Mybatis常见错误及纠错
  • 原文地址:https://www.cnblogs.com/gered/p/9435282.html
Copyright © 2020-2023  润新知