(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:\mssql\corrupt.bak'withnorecovery backup log corrupttodisk='d:\mssql\corrupt.trn' restore log corruptfromdisk='d:\mssql\corrupt.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:\mssql\corrupt.bak'withnorecovery

 

backup log corrupttodisk='d:\mssql\corrupt.trn'

 

restore log corruptfromdisk='d:\mssql\corrupt.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 之前备份数据库。

posted @ 2018-08-07 09:57  郭大侠1  阅读(648)  评论(0编辑  收藏  举报