記錄SQL Server2008日志文件損壞的恢復過程:
環境:
系 統:Windows Server2003
數據庫:SQL Server2008
故障原因:
通過mstsc鏈接同一服務器時,用戶界面不一致。決定重啟服務器,未正確關閉應用程序的情況下(程序在訪問數據庫),導致數據庫日志文件損壞,自然也就無法訪問mdf文件!(都是微軟自家的產品,重啟服務器為什么不能檢查數據庫的狀態,將數據庫設置在安全狀態后在重啟呢??(有一種解釋是:SQL Server為了加快關機的速度,允許使用NOWAIT選項。此選項將跳過檢查點操作,導致部分數據未回寫到MDF文件(僅記錄在LDF中)。在這種情況下,如果丟失了LDF文件,盡管可以修復數據庫,卻會有數據丟失)所以,要養成良好的習慣。關閉現有數據庫鏈接,再重啟服務器)
故障表現:無法訪問數據文件,就像下面JD_2數據庫一樣。
解決方案:
1:將數據庫JD_2刪除、或者分離(這里可能會提示無法刪除或分離數據庫,可以重啟對應的數據庫實例后再次嘗試) 2:新建數據庫,日志文件和數據文件名稱和要恢復對應文件一樣命名。 3:將新建的數據庫設置為脫機模式,找到新建數據庫的物理路徑,將要恢復的mdf文件拷貝覆蓋現有的mdf文件。 4:設置數據庫為聯機模式,刷新數據庫,可以看到並沒有什么卵用。 5:執行alter database JD_2 set emergency 將數據庫設置為緊急模式。 執行:
1 use master 2 3 declare @databasename varchar(255) 4 5 set @databasename='JD_2' 6 7 ALTER DATABASE JD_2 SET SINGLE_USER //將目標數據庫置為單用戶狀態 8 9 dbcc checkdb(@databasename,REPAIR_ALLOW_DATA_LOSS) 10 11 dbcc checkdb(@databasename,REPAIR_REBUILD) 12 13 ALTER DATABASE JD_2 SET MULTI_USER //將目標數據庫置為多用戶狀態
6:刷新后數據庫處於緊急模式,數據基本恢復。當前數據局處於緊急模式,無法對數據庫備份,無法增刪改查,只能讀取。所以我們要恢復緊急模式為正常模式
7:執行 select * from sys.master_files 查看數據庫基本信息和狀態信息 8:執行 select * from sysdatabases 查看所有數據庫的信息如下: Status狀態碼含義:http://blog.csdn.net/nemo2011/article/details/9233777
執行:
方案1:
1 sp_configure 'allow updates',1 2 reconfigure with override 3 update sysdatabases set status=0 where name='JD_New'
更改數據庫狀態碼,提示不允許更改=>sql server2008不支持對系統表的修改 方案2: 對於正常未損壞的數據庫可以使用
1 ALTER DATABASE dbname SET EMERGENCY 2 3 ALTER DATABASE dbname SET ONLINE
在緊急模式和普通模式間切換。但是對於損壞過的數據,經驗證此方法行不通。 參考了一些網上的辦法,都沒能解決問題!請朋友不吝賜教~~ 如果只是關心數據庫表中的基礎數據,可以新建數據庫,將待恢復的數據批量導入到新的數據庫中執行以下語句(修改DatabaseFrom為損壞數據庫名稱、DatabaseTo為新數據庫名稱即可;2、10、11行)=>
1 USE [DatabaseFrom] 2 3 DECLARE @fromdb VARCHAR(100) 4 DECLARE @todb VARCHAR(100) 5 DECLARE @tablename VARCHAR(100) 6 DECLARE @columnnames NVARCHAR(max) 7 DECLARE @isidentity NVARCHAR(30) 8 DECLARE @temsql NVARCHAR(max) 9 DECLARE @sql NVARCHAR(max) 10 SET @fromdb = 'DatabaseFrom' 11 SET @todb = 'DatabaseTo' 12 13 IF (OBJECT_ID('#MyTempTable') IS NOT NULL) 14 drop table #MyTempTable 15 16 17 CREATE TABLE #MyTempTable (names varchar(500)) 18 insert into #MyTempTable 19 SELECT name from sys.tables WHERE type='U' AND name not in (select OBJECT_NAME(parent_object_id) 'name' from sys.objects where type='F') 20 21 insert into #MyTempTable 22 select OBJECT_NAME(parent_object_id) 'name' from sys.objects where type='F' order by object_id 23 24 25 --游標 26 DECLARE @itemCur CURSOR 27 SET @itemCur = CURSOR FOR 28 SELECT names from #MyTempTable 29 30 OPEN @itemCur 31 FETCH NEXT FROM @itemCur INTO @tablename 32 WHILE @@FETCH_STATUS=0 33 34 BEGIN 35 36 SET @sql = '' 37 38 --獲取表字段 39 SET @temsql = N' 40 BEGIN 41 SET @columnnamesOUT ='''' 42 SELECT @columnnamesOUT = @columnnamesOUT + '','' + ''['' + name + '']'' 43 From sys.columns where object_id=OBJECT_ID(''['+@fromdb+'].dbo.'+@tablename+''') 44 order by column_id 45 SELECT @columnnamesOUT=substring(@columnnamesOUT,2,len(@columnnamesOUT)) 46 END 47 ' 48 EXEC sp_executesql @temsql,N'@columnnamesOUT NVARCHAR(max) OUTPUT',@columnnamesOUT=@columnnames OUTPUT 49 50 PRINT ('--'+@tablename) 51 PRINT ('--表名 '''+@tablename+'''') 52 53 54 55 56 --INSERT 57 SET @sql = @sql+'SELECT * INTO ['+@todb+'].[dbo].['+@tablename+'] FROM ['+@fromdb+'].[dbo].['+@tablename+']' 58 59 60 61 --返回SQL 62 PRINT(@sql)PRINT('GO')+CHAR(13) 63 64 FETCH NEXT FROM @itemCur INTO @tablename 65 END 66 67 CLOSE @itemCur 68 DEALLOCATE @itemCur 69 70 71 drop table #MyTempTable
然后拷貝消息欄的語句執行即可:
1 (749 行受影響) 2 3 (0 行受影響) 4 --sm_idx_River_2 5 --表名 'sm_idx_River_2' 6 SELECT * INTO [JD_2_Back].[dbo].[sm_idx_River_2] FROM [JD_2].[dbo].[sm_idx_River_2] 7 GO 8 9 --TyphoonGustForm_1 10 --表名 'TyphoonGustForm_1' 11 SELECT * INTO [JD_2_Back].[dbo].[TyphoonGustForm_1] FROM [JD_2].[dbo].[TyphoonGustForm_1] 12 GO 13 14 --Interpolation_3Tier3 15 --表名 'Interpolation_3Tier3' 16 SELECT * INTO [JD_2_Back].[dbo].[Interpolation_3Tier3] FROM [JD_2].[dbo].[Interpolation_3Tier3] 17 GO 18 19 --YGZZPonding3_CJ 20 --表名 'YGZZPonding3_CJ' 21 SELECT * INTO [JD_2_Back].[dbo].[YGZZPonding3_CJ] FROM [JD_2].[dbo].[YGZZPonding3_CJ] 22 GO 23 24 --ForestDistribut_2 25 --表名 'ForestDistribut_2' 26 SELECT * INTO [JD_2_Back].[dbo].[ForestDistribut_2] FROM [JD_2].[dbo].[ForestDistribut_2] 27 GO
可能會有錯誤,如下所示:我們就找出了 出錯的數據表了!然后在手動修改特定的錯誤表吧......
最后就是刪除損壞的數據庫,更改新數據庫名字即可。
無奈損壞的數據庫為超圖映射過來的數據庫(推測,超圖對數據庫設置了一些除表外其他的一些附加信息),通過新建數據庫,然后簡單的導出數據,還是無法解決(通過超圖桌面版和object.net版本 無法修改數據集 )。最后只能,找出去年備份的數據庫,然后看下哪些數據集更新,從損壞的數據庫中慢慢更新了。。。。。。