【1】dbcc checkdb發現錯誤信息
dbcc checkdb系統頁錯誤(GAM、SGAM、PFS)
、
事務日志備份也全部報錯
【2】查看錯誤頁類型信息
【2.1】查看 msdb..suspect_pages 獲取問題頁類型
SELECT DB_NAME(database_id) dbname,[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 event_type, error_count, last_update_date FROM msdb..suspect_pages
【2.2】查看錯誤頁是屬於哪種系統頁(PFS)
Declare @PageID int; -- Enter page number -- e.g., 8088 = PFS page Set @PageID = 32352; 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
【3】無法使用dbcc checkdb repair_allow_data_loss 修復,報同樣的錯誤
【4】解決思路
【4.-1】嘗試直接修復(DBCC CHECKALLOC(dbname,REPAIR_ALLOW_DATA_LOSS ))
DBCC CHECKALLOC [ ( database_name | database_id | 0 [ , NOINDEX | , { REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD } ] ) [ WITH { [ ALL_ERRORMSGS ] [ , NO_INFOMSGS ] [ , TABLOCK ] [ , ESTIMATEONLY ] } ] ]
【4.0】利用備份頁還原(推薦)
深入參考:https://www.cnblogs.com/gered/p/9435282.html
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 */
【4.1】庫小的時候
把庫遷移到本實例另外一個新建的庫
大概步驟:(也可以用Bcp)
(1)如果是2008級以上
停機=》利用右擊數據庫=》任務=》生成腳本 得到數據庫對象架構、數據腳本
(2)如果是2005
停機=》利用右擊數據庫=》任務=》生成腳本 得到數據庫對象架構腳本(不包含表數據)
然后利用 sys.tables來進行 insert into select ......遷移數據到另外一個庫
具體操作:
直接利用SSMS自帶的生成腳本,右擊數據庫=》任務=》生成腳本
然后選擇架構和數據,相關的觸發器、索引都可以。2008可以選擇架構和數據,2005只能選擇架構。
但2005,只能生成架構語句,也就是 create腳本,並不能生成對應的 insert value 。
所以2005的玩家,需要額外利用sys.tables把故障庫的數據,利用 insert into select 插入到新庫。
--要使用,@new_db內容用查找替換來全部替換掉,否則會有問題的 declare @old_db varchar(100),@new_db varchar(100),@sql varchar(max) select @old_db='[10.1.4.234].db_tank',@new_db='test2' -- 獲取有自增列插入語句 select 'use '+@new_db+';set identity_insert '+t1.name+' on;insert into '+@new_db+'.dbo.'+t1.name+'('+ (select stuff((select',['+name+']' from test2.sys.syscolumns where id=t1.object_id for xml path('')),1,1,''))+')'+ ' select '+(select stuff((select',['+name+']' from test2.sys.syscolumns where id=t1.object_id for xml path('')),1,1,'')) +' from '+@old_db+'.dbo.'+t1.name+';set identity_insert '+t1.name+' off;' from test2.sys.tables t1 where exists ( select 1 from test2.sys.columns t2 where t2.is_identity=1 and t1.object_id=t2.object_id ) and t1.type='u' -- 獲取無自增列插入語句 select 'use '+@new_db+';insert into '+@new_db+'.dbo.'+t1.name+' select * from '+@old_db+'.dbo.'+t1.name+';' from test2.sys.tables t1 where not exists ( select 1 from test2.sys.columns t2 where t2.is_identity=1 and t1.object_id=t2.object_id ) and t1.type='u' --------------核驗-------------------- -- 更新統計信息 use test2 EXEC sys.sp_updatestats use db_logs EXEC sys.sp_updatestats -- 根據聚集索引/堆對比行數 use master; if object_id('temp1') is not null drop table master.dbo.temp1 select t2.name tab_name,rows,indid into master..temp1 from [10.1.4.234].db_tank.sys.sysindexes t1 join [10.1.4.234].db_tank.sys.sysobjects t2 on t1.id=t2.id where t1.indid in(0,1) and t2.type!='S' use master; if object_id('temp2') is not null drop table master.dbo.temp2 select t2.name tab_name,rows,indid into master..temp2 from test2.sys.sysindexes t1 join test2.sys.sysobjects t2 on t1.id=t2.id where t1.indid in(0,1) and t2.type!='S' -- 根據聚集索引/堆對比行數,篩選行數不一致的 select t1.*,t2.*,t1.rows-t2.rows as flag from master..temp1 t1 join master..temp2 t2 on t1.tab_name=t2.tab_name where t1.rows-t2.rows>0 -- 對比表存在情況 select t1.*,t2.*,t1.rows-t2.rows as flag from master..temp1 t1 full join master..temp2 t2 on t1.tab_name=t2.tab_name where t1.tab_name is null or t2.tab_name is null
搞完之后記得還有賬戶映射,權限等問題
【4.2】庫大的時候,且短時間DML不多
(1)新建備份、快照等 構造現有時間點數據集,然后(如果是2008,使用apexsql 或 使用 cdc)(如果是2005,怕是只能使用apexsql、DML觸發器 等收集增量數據)
(2)把備份、快照等構造的時間點數據集插入到新庫
(3)然后應用增量數據
這里比較麻煩,就不演示了
【sql server】可能發生了架構損壞。請運行DBCC CHECKCATALOG.
參考文檔
https://www.cnblogs.com/gered/p/13207686.html
【sql server】可能發生了架構損壞。請運行DBCC CHECKCATALOG.
參考:DBCC IND https://www.cnblogs.com/gered/p/9444344.html#autoid-3-0-0