最近在系統運行中發現了一個錯誤,錯誤信息如下:
錯誤信息:查詢A201412C20568單證信息錯誤 ---> System.Data.OleDb.OleDbException: 由於數據移動,未能繼續以 NOLOCK 方式掃描。
一開始我認為企業的數據庫是SQL SERVER 2005以上的版本,使用了以下方式:
USE MASTER GO
ALTER DATABASE work_yf SET SINGLE_USER GO --允許丟失數據修復 DBCC CHECKDB (work_yf, REPAIR_ALLOW_DATA_LOSS) GO
ALTER DATABASE work_yf SET MULTI_USER
在執行了命令之后,發現無法成功。后研究了一下企業使用的數據庫,發現是SQL SERVER 2000的。所以只能使用以下方式進行修復。
第一步:通過以下代碼查詢,是哪些表中出錯了
DECLARE @table_name sysname DECLARE ROY_table CURSOR FOR
SELECT name FROM sysobjects where xtype in ('u','s') OPEN ROY_table FETCH NEXT FROM ROY_table INTO @table_name
WHILE @@FETCH_STATUS = 0
BEGIN
DBCC CheckTable (@table_name) PRINT '--------------數據表'+@table_name + '的檢查整理完成------------------'
FETCH NEXT FROM ROY_table INTO @table_name
END
CLOSE ROY_table DEALLOCATE ROY_table
執行上述命名之后,會在“消息”窗口中顯示如下信息:(以下信息中只有出錯信息,其他正常信息已經去除)
服務器: 消息 8929,級別 16,狀態 1,行 10 對象 ID 2: 在文本 ID 177078272 中發現錯誤,該文本的所有者是由 RID = (1:135:19) id = 661577395 and indid = 3 標識的數據記錄。 服務器: 消息 8961,級別 16,狀態 1,行 10 表錯誤: 對象 ID 2。text、ntext 或 image 節點(位於頁 (1:66),槽 2,文本 ID 177078272)與該節點位於頁 (1:284),
槽 6 處的引用不匹配。 'sysindexes' 的 DBCC 結果。 對象 'sysindexes' 有 304 行,這些行位於 14 頁中。 CHECKTABLE 發現了 0 個分配錯誤和 2 個一致性錯誤(在表 'sysindexes' 中,該表的對象 ID 為 2)。 通過上面的提示信息,找到出錯的索引或統計信息
--------------數據表sysindexes的檢查整理完成------------------
服務器: 消息 8936,級別 16,狀態 1,行 10
表錯誤: 對象 ID 709577566,索引 ID 1。B 樹鏈的鏈接不匹配。(1:2203)->next = (1:176),但 (1:176)->Prev = (1:2045)。
服務器: 消息 8977,級別 16,狀態 1,行 10
表錯誤: 對象 ID 709577566,索引 ID 1。未遇到頁 (1:2203) 的父節點。
'PDE_LIST_ORG' 的 DBCC 結果。
對象 'PDE_LIST_ORG' 有 216 行,這些行位於 11 頁中。
CHECKTABLE 發現了 0 個分配錯誤和 2 個一致性錯誤(在表 'PDE_LIST_ORG' 中,該表的對象 ID 為 709577566)。
repair_rebuild 是最低的修復級別(對於由 DBCC CHECKTABLE (work_yf.dbo.PDE_LIST_ORG ) 發現的錯誤而言)。
--------------數據表PDE_LIST_ORG的檢查整理完成------------------
服務器: 消息 8978,級別 16,狀態 1,行 10
表錯誤: 對象 ID 725577623,索引 ID 1。頁 (1:3891) 缺少上一頁 (1:3892) 對它的引用。可能是因為鏈的鏈接有問題。
服務器: 消息 8976,級別 16,狀態 1,行 10
表錯誤: 對象 ID 725577623,索引 ID 1。在掃描操作中未發現頁 (1:3892),而其父代 (1:2198) 和上一頁 (1:3889) 指向了該頁。
請檢查先前的錯誤。
'PDE_LIST_ORG_HISTROY' 的 DBCC 結果。
對象 'PDE_LIST_ORG_HISTROY' 有 16755 行,這些行位於 489 頁中。
CHECKTABLE 發現了 0 個分配錯誤和 2 個一致性錯誤(在表 'PDE_LIST_ORG_HISTROY' 中,該表的對象 ID 為 725577623)。
repair_rebuild 是最低的修復級別(對於由 DBCC CHECKTABLE (work_yf.dbo.PDE_LIST_ORG_HISTROY ) 發現的錯誤而言)。
--------------數據表PDE_LIST_ORG_HISTROY的檢查整理完成------------------
第二步,進行分析,除了上面的斜體字部分,需要注意,其他都很清楚,就是兩張業務表發生了錯誤。
而斜體字部分是指一張系統表sysindexes,需要進一步查詢是哪些索引出錯了。
1) 使用以下語句檢查是哪些索引出現了問題,原來是_WA_Sys_STATUS_276EDEB3出錯是問題。
SELECT * FROM SYSINDEXES WHERE id = 661577395 and indid = 3 select * from sysobjects where id = 661577395
第三步,進行修得操作。具體操作方法如下:
--方法如下:
--1. 先停掉數據庫服務器,把出問題的數據庫(例如:work_yf)的.mdf與.ldf文件備份到備份目錄中。
--2.我們使用默認方式建立一個供恢復使用的數據庫(如work_yf)。可以在SQL Server Enterprise Manager里面建立。
--3.停掉數據庫服務器。
--4.將剛才生成的數據庫的日志文件work_yf_log.ldf刪除,用要修復的數據庫mdf文件覆蓋剛才生成的數據庫數據文件work_yf_data.mdf。
--5.啟動數據庫服務器。此時會看到數據庫work_yf的狀態為“置疑”。這時候不能對此數據庫進行任何操作。
--6.設置數據庫允許直接操作系統表。此操作可以在SQL Server Enterprise Manager里面選擇數據庫服務器,按右鍵,選擇“屬性”,
在“服務器設置”頁面中將“允許對系統目錄直接修改”一項選中。也可以使用如下語句來實現。
use master go exec sp_configure 'allow updates',1 go reconfigure with override go
--7.設置work_yf為緊急修復模式
update sysdatabases set status=-32768 where dbid=DB_ID('work_yf')
--此時可以在SQL Server Enterprise Manager里面看到該數據庫處於“只讀\置疑\脫機\緊急模式”可以看到數據庫里面的表,
但是僅僅有系統表
--8.下面執行真正的恢復操作,重建數據庫日志文件
go dbcc rebuild_log('work_yf','D:\Program Files\Microsoft SQL Server\MSSQL\Data\work_yf_log.ldf') go
--執行過程中,如果遇到下列提示信息:
--服務器: 消息 5030,級別 16,狀態 1,行 1
--未能排它地鎖定數據庫以執行該操作。
--DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
--說明您的其他程序正在使用該數據庫,如果剛才您在F步驟中使用SQL Server Enterprise Manager打開了work_yf庫的系統表,
那么退出SQL Server Enterprise Manager就可以了。
--正確執行完成的提示應該類似於:
--警告: 數據庫 'work_yf' 的日志已重建。已失去事務的一致性。應運行 DBCC CHECKDB 以驗證物理一致性。
將必須重置數據庫選項,並且可能需要刪除多余的日志文件。
--DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
--此時打開在SQL Server Enterprise Manager里面會看到數據庫的狀態為“只供DBO使用”。此時可以訪問數據庫里面的用戶表了。
--9 設置為單用戶狀態
go exec sp_dboption 'work_yf','dbo use only','false' GO exec sp_dboption 'work_yf', 'single user', 'true' go reconfigure with override
--10 修復表,具體要修復哪些表,請在執行DBCC CheckTable (表名) ,自行檢查。我在這里使用了"重建索引並修復(REPAIR_REBUILD)"的選項。
一共有三個選項:
--1) 快速修復 REPAIR_FAST
--2) 重建索引並修復 REPAIR_REBUILD
--3) 允許丟失數據修復 REPAIR_ALLOW_DATA_LOSS
use work_yf GO DBCC CheckTable (PDE_LIST_ORG_HISTROY,REPAIR_REBUILD) GO DBCC CheckTable (PDE_LIST_ORG,REPAIR_REBUILD) GO DBCC CheckTable (PDE_HEAD,REPAIR_REBUILD)
--剛才我在檢查的時候,發現一個_WA_Sys_STATUS_276EDEB3也出錯了,這是SQL SERVER自動建立的統計信息,
所以需要進行刪除,然后在進行修復
GO DROP STATISTICS PDE_HEAD._WA_Sys_STATUS_276EDEB3 GO DBCC CheckTable (SYSINDEXES,REPAIR_REBUILD) GO
--11.驗證數據庫一致性(可省略)
use master go DBCC CheckDB (work_yf)
go
--一般執行結果如下:
--CHECKDB 發現了 0 個分配錯誤和 0 個一致性錯誤(在數據庫 'work_yf' 中)。
--DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
--12.設置數據庫為正常狀態
exec sp_dboption 'work_yf', 'single user', 'false' go exec sp_dboption 'work_yf','dbo use only','false' go
--如果沒有出錯,那么恭喜,現在就可以正常的使用恢復后的數據庫啦。
--13.最后一步,我們要將步驟E中設置的“允許對系統目錄直接修改”一項恢復。因為平時直接操作系統表是一件比較危險的事情。
當然,我們可以在SQL Server Enterprise Manager里面恢復,也可以使用如下語句完成
exec sp_configure 'allow updates',0 go reconfigure with override go