Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
2016年9月13日 PASS
Database Corruption Challenge - Steve Stedman
Presented by Steve Stedman
https://www.youtube.com/watch?v=5oBA5nL0uRc&feature=youtu.be&a
1.備份資料庫,還原至測試機來進行修復工作(確保還原程序遭遇問題時,可以重頭再來修復一次)
2.如果決定用allow data loss,嘗試先找出可能遺失的資料並事先嘗試SELECT INTO保留下來
3.執行之前尋求是否有其他人的意見
定期執行
osql -E -Q"DBCC CHECKDB (AdventureWorks) WITH ALL_ERRORMSGS, NO_INFOMSGS" -oC:\outputfile.txt
sqlcmd -E -Q"DBCC CHECKDB (AdventureWorks) WITH ALL_ERRORMSGS, NO_INFOMSGS" -o C:\outputfile.txt
PS.WITH NO_INFOMSGS只顯示錯誤訊息,一般的information不顯示
基本流程
1.將有損毀的資料庫備份檔還原到測試機,切換成single_user mode。
ATLER DATABASE AdventureWorks SET SINGLE_USER WITH ROLLBACK_IMMEDIATELY;
2.取得錯誤訊
USE [master];
GO
DBCC CHECKDB (AdventureWorks) WITH NO_INFOMSGS;
GO
DBCC CHECKTABLE ('HumanResources.Employee') WITH NO_INFOMSGS;
GO
2.取回損毀的資料
(1)如果原資料表還能查詢的狀況
A.透過DBCC CHECKTABLE找出哪一筆或哪幾筆資料損毀
page(1, 280) ->page 280
DBCC TRACEON(3604)
DBCC PAGE(dbname, 1, 280,2) with no_infomsgs;
從結果找出m_type
m_type=1 ->data page
slotcount =27 -> number of rows in this page
所以如果執行allow data loss則會出現27然後修復完成(損毀的地方)
B.透過select with non-clustered Index取回一些資料。
select col1, col2 from table with (index=clusted_index1);
利用彙總函數,比對clustered index與non-clustered index資料是否有不同
PS.數值與日期欄位可用SUM(column),文字欄位可用 SUM(LEN(column))
若查出來值不同(例如col4不同),表示其中一個欄位有損毀
使用OUTER ALL JOIN 同一個TABLE 找出哪一筆的col4是NULL
因無法直接update or delete那一筆損毀的資料,若執行會出現錯誤
所以從non-cluster index SELECT資料到table_save暫存資料表
D.嘗試修復
DBCC CHECKTABLE(tableName, REPAIR_REBUILD)
通常無法修復
DBCC CHECKTABLE(tableName, REPAIR_ALLOW_DATA_LOSS)
出現找到錯誤,並已經修復
但執行select * from table發現只剩一半的資料,其他消失
E.將資料從table_save補回原資料表
接下就INSERT table select * from table_save
where table.id not in (select id from table)
(2)如果原資料表不能查詢的狀況
A.先透過select with non-clustered Index取回一些資料。(如果後面的步驟無法取得完整資料,最少還有這些)
B.嘗試透過DBCC IND, DBCC PAGE來取回損毀資料表(clustered index)的完整資料
C.再用TRUNCATE TABLE來移除損毀
D.INSERT SELECT from救回資料的資料表
3.修復資料庫並回存資料
truncate table Table_1
insert into Table_1 select * from Table_copy