一.概述 當資料庫發生損壞,資料庫的每個文件都能打開,只是其中的一些頁面壞了,這種情況可以藉助DBCC CHECKDB進行資料庫檢查修複。如果要保證資料庫不丟失,或修複不好,管理員只能做資料庫完整恢復,為了少數頁面恢復整個資料庫,代價是比較高的,sql server引入了頁面還原功能,可以指定還原若 ...
一.概述
當資料庫發生損壞,資料庫的每個文件都能打開,只是其中的一些頁面壞了,這種情況可以藉助DBCC CHECKDB進行資料庫檢查修複。如果要保證資料庫不丟失,或修複不好,管理員只能做資料庫完整恢復,為了少數頁面恢復整個資料庫,代價是比較高的,sql server引入了頁面還原功能,可以指定還原若幹頁面,從而能夠大大節省資料庫恢復時間。
頁面還原用於修複隔離的損壞頁面,還原恢復時間比文件更快,減少了還原過程中處於離線的數據量,當某個文件的大量頁面都出現損壞,可以直接還原該文件(需要有文件備份)。要進行還原的頁面是在訪問該頁面,遇到錯誤而標記為"可疑",可以試試去找msdb.dbo.suspect_pages表。在頁面還原後,也需要恢復所有的日誌文件備份。
1.1 還原的限制,不能還原的頁
(1)事務日誌不能還原。
(2)分配頁面:全局分配映射GAM頁面,共用全局分配映射SGAM頁面和可用空間PFS頁面,這些系統頁面損壞,頁面還原無法恢復。
(3)所有數據文件的頁面0 的(文件啟動頁面)。
(4)頁面1:9的(資料庫啟動頁面)。
1.2 還原條件
(1) 必需使用完整恢復模式。
(2) 只讀文件組中的頁面無法還原。
(3) 還原順序必須是從完整備份,文件備份中恢復頁面開始。
(4) 頁面還原需要截止到當前日誌文件的連續日誌備份。
(5) 資料庫備份和頁面還原不能同時進行。
二.還原步驟
(1) 獲取要還原的損壞頁面的頁ID,當sql server遇到校驗或殘缺寫錯誤時,會返回頁面編號。可以通過查詢msdb資料庫里的suspect_pages表,或者監視事件和errorlog文件里記錄的錯誤信息,查找到損壞的頁面ID。
(2) 從包含頁的完整資料庫備份,文件備份或文件組備份開始進行頁面還原。在restore database 語句中,使用page子句列出所有要還原的頁ID。
(3) 應用最近的差異備份。
(4) 應用後續的日誌備份。
(5) 創建新的資料庫尾日誌備份。
(6) 還原新的尾日誌備份,應用這個新的日誌備份後,就完成了頁面還原。
三. 備份
為了演示損壞的數據頁面,新建一個PageTest表,初始化三個PAGE頁,後面人為的破壞一個數據頁面。
use BackupPageTest -- 創建表 create table PageTest ( ID int, name varchar(8000) ) -- 產生 insert into PageTest select 1, REPLICATE('a',8000) insert into PageTest select 1, REPLICATE('b',8000) insert into PageTest select 1, REPLICATE('c',8000)
sys.system_internals_allocation_units 查看分配頁情況
/* 第1個參數:庫名 第2個參數:表名 第3個參數:-1: 顯示所有IAM、數據分頁、及指定對象上全部索引的索引分頁 PageFID: 文件ID PageType=1 指數據頁面 PageType=10 IAM頁面 */ -- 未公開的命令,語法如下: DBCC IND(dbname,tablename,-1)
use master -- 完整備份 backup database BackupPageTest to BackupTestDevice
四 模擬頁面損壞
使用PagePID為89的數據頁面進行演示,通過dbcc page查看該頁面,知道該頁數據是存儲的第三條數據。
dbcc traceon (3604) dbcc page('BackupPageTest',1,89,1)
使用 dbcc wirtepage來模擬該面損壞:
-- 未公開的命令語法為如下 dbcc writepage ({ dbid, 'dbname' }, fileid, pageid, offset, length, data)
-- 模擬頁面損壞 dbcc writepage(BackupPageTest,1,89,96,10,0x65656565656565656565)
-- 查詢該表時,第三條數據顯示NULL select * from PageTest
--更新第三條數據,結果報錯 update PageTest set id=2 where ID is null
-- 插入第4條是成功的 insert into PageTest select 4, REPLICATE('d',8000)
五. 獲取要修複的數據頁面
-- 使用checkdb檢查 DBCC CHECKDB(BackupPageTest)
通過校驗,提示無法處理面(1:89)如下圖
六. 還原
use master --從完整資料庫備份,開始還原,指定要還原的PAGE頁 restore database BackupPageTest page='1:89' from BackupTestDevice with file=39, norecovery --創建新的尾日誌備份 backup log BackupPageTest to BackupTestDevice
此時訪問數據表PageTest將會發錯,如下圖所示,表明在還原過程中數據是不可訪問的。
--最後還原新的尾日誌備份 restore log BackupPageTest from BackupTestDevice with file=40, recovery
數據修複過來了,如下圖:
再次CHECKDB 檢查表狀態