今天開發找我,說數據庫insert不進數據,叫我看一下html
他發了一個截圖給我數據庫
而後我登陸上服務器,發現了可疑的地方,並且這個數據庫以前有一段經歷服務器
在月初的時候這個數據庫曾經置疑過,啓動不起來ide
Could not redo log record (163041:116859:5), for transaction ID (0:-1175226963), on page (17:20633999), database 'xxrchives' (database ID 7). Page: LSN = (162930:20671:38), type = 2. Log: OpCode = 2, context 3, PrevPageLSN: (163041:116230:18). Restore from a backup of the database, or repair the database. During redoing of a logged operation in database 'xxxrchives', an error occurred at log record ID (163041:116859:5). Typically, the specific failure is previously logged as an error in the Windows Event Log service. Restore the database from a full backup, or repair the database. An error occurred during recovery, preventing the database 'xxxrchives' (database ID 7) from restarting. Diagnose the recovery errors and fix them, or restore from a known good backup. If errors are not corrected or expected, contact Technical Support. Setting database option EMERGENCY to ON for database xxxchives. The database 'xxxxchives' is marked EMERGENCY_MODE and is in a state that does not allow recovery to be run.
因爲一些特殊的緣由沒有作備份,數據庫大小差很少3TB,這裏3TB是已經除去可用空間的了,裏面只有幾張表,其中只有一張大表spa
修復語句以下3d
USE MASTER GO ALTER DATABASE [xxxrchives] SET EMERGENCY GO ALTER DATABASE [xxxxchives] SET SINGLE_USER WITH ROLLBACK IMMEDIATE GO DBCC CHECKDB('xxxxchives','REPAIR_ALLOW_DATA_LOSS') with tablock GO ALTER DATABASE [xxxxchives] SET ONLINE GO ALTER DATABASE [xxxxchives] SET MULTI_USER GO
數據相對來講不是很是重要,容許丟失一些數據rest
結果運行了差很少7天,業務也一度中斷了日誌
其實有數據庫完整備份的話可使用頁面還原的方法還原有問題的頁面,加上日誌備份,而不用這麼大工程的。。。code
有經驗的SQLSERVER管理員應該知道最後我使用的方法如何拋棄有824錯誤的頁面,只保留正常的數據頁面,這個大表是作了表分區的,因爲篇幅關係這裏不具體說了htm
消息 824,級別 24,狀態 2,第 3 行 SQL Server 檢測到基於一致性的邏輯 I/O 錯誤 pageid 不正確(應爲 6:33780000,但實際爲 0:0)。在文件 'E:\DataBase\FG_xxxxive\FG_xxxxhive_Id_04_data.ndf' 中、偏移量爲 0x0000406e240000 的位置對數據庫 ID 7 中的頁 (6:33780000) 執行 讀取 期間,發生了該錯誤。SQL Server 錯誤日誌或系統事件日誌中的其餘消息可能提供了更詳細信息。這是一個威脅數據庫完整性的嚴重錯誤條件,必須當即糾正。請執行完整的數據庫一致性檢查(DBCC CHECKDB)。此錯誤能夠由許多因素致使;有關詳細信息,請參閱 SQL Server 聯機叢書。
問題所在
這個數據庫運行在SQL2008上面,一直都是簡單模式,那麼問題來了,因爲當時checkdb的時間很長,積累了大量事務日誌
可是,按道理處於簡單模式會自動截斷日誌的,可是當時本人也沒有看,內心只想着數據庫立刻online
步驟一:今天開發找我插不進去數據也是由於這個,我運行了下面語句,這個語句是我找問題的時候通常都先用這個語句,由於在徐海蔚老師的書裏面也建議先使用這個語句
SELECT * FROM sys.[sysprocesses]
結果發現
至關多的log等待
步驟二:我再運行下面腳本
-- ============================================= -- Author: <樺仔> -- Blog: <http://www.cnblogs.com/lyhabc/> -- Create date: <2014/4/18> -- Description: <統計各個數據庫的總大小V2 不包含數據文件> -- ============================================= SET NOCOUNT ON USE master GO DECLARE @DBNAME NVARCHAR(MAX) DECLARE @SQL NVARCHAR(MAX) --臨時表保存數據 CREATE TABLE #DataBaseServerData ( ID INT IDENTITY(1, 1) , DBNAME NVARCHAR(MAX) , Log_Total_MB DECIMAL(18, 1) NOT NULL , Log_FREE_SPACE_MB DECIMAL(18, 1) NOT NULL ) --遊標 DECLARE @itemCur CURSOR SET @itemCur = CURSOR FOR SELECT name from SYS.[sysdatabases] WHERE [name] NOT IN ('MASTER','MODEL','TEMPDB','MSDB','ReportServer','ReportServerTempDB') OPEN @itemCur FETCH NEXT FROM @itemCur INTO @DBNAME WHILE @@FETCH_STATUS = 0 BEGIN SET @SQL=N'USE ['+@DBNAME+'];'+CHAR(10) + 'INSERT [#DataBaseServerData] ( [DBNAME] , [Log_Total_MB] , [Log_FREE_SPACE_MB ] ) SELECT '''+@DBNAME+''', str(sum(convert(dec(17,2),sysfiles.size)) / 128,10,2) AS Total_MB, SUM(( database_files.size - FILEPROPERTY(database_files.name, ''SpaceUsed'') )) / 128.0 AS free_space_mb FROM dbo.sysfiles as sysfiles INNER JOIN sys.database_files as database_files ON sysfiles.[fileid]=database_files.[file_id] WHERE sysfiles.[groupid] =0 AND database_files.[type] = 1;' EXEC (@SQL) FETCH NEXT FROM @itemCur INTO @DBNAME END CLOSE @itemCur DEALLOCATE @itemCur SELECT * FROM [#DataBaseServerData] DROP TABLE [#DataBaseServerData]
結果發現
上百G的日誌文件
步驟三:我使用數據分析腳本也發現表裏面的數據沒有增長,按F5刷新了不少次
--數據分析 CREATE TABLE #tablespaceinfo ( nameinfo VARCHAR(50) , rowsinfo BIGINT , reserved VARCHAR(20) , datainfo VARCHAR(20) , index_size VARCHAR(20) , unused VARCHAR(20) ) DECLARE @tablename VARCHAR(255); DECLARE Info_cursor CURSOR FOR SELECT '[' + [name] + ']' FROM sys.tables WHERE type = 'U'; OPEN Info_cursor FETCH NEXT FROM Info_cursor INTO @tablename WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO #tablespaceinfo EXEC sp_spaceused @tablename FETCH NEXT FROM Info_cursor INTO @tablename END CLOSE Info_cursor DEALLOCATE Info_cursor --建立臨時表 CREATE TABLE [#tmptb] ( TableName VARCHAR(50) , DataInfo BIGINT , RowsInfo BIGINT , Spaceperrow AS ( CASE RowsInfo WHEN 0 THEN 0 ELSE CAST(DataInfo AS decimal(18,2))/CAST(RowsInfo AS decimal(18,2)) END ) PERSISTED ) --插入數據到臨時表 INSERT INTO [#tmptb] ( [TableName] , [DataInfo] , [RowsInfo] ) SELECT [nameinfo] , CAST(REPLACE([datainfo], 'KB', '') AS BIGINT) AS 'datainfo' , [rowsinfo] FROM #tablespaceinfo ORDER BY CAST(REPLACE(reserved, 'KB', '') AS BIGINT) DESC --彙總記錄 SELECT [tbspinfo].* , [tmptb].[Spaceperrow] AS '每行記錄大概佔用空間(KB)' FROM [#tablespaceinfo] AS tbspinfo , [#tmptb] AS tmptb WHERE [tbspinfo].[nameinfo] = [tmptb].[TableName] ORDER BY CAST(REPLACE([tbspinfo].[reserved], 'KB', '') AS BIGINT) DESC DROP TABLE [#tablespaceinfo] DROP TABLE [#tmptb]
步驟四:下面檢查 VLF
DBCC LOGINFO
有400多個VLF
步驟五:檢查一下log爲何不能重用的緣由
SELECT DB_NAME([database_id]) AS dbname , [log_reuse_wait] , [log_reuse_wait_desc] FROM sys.[databases]
結果發現 數據庫作了複製,我接手的時候這個數據庫是不須要複製的,多是之前的同事弄的
步驟六:我使用博客園裏面i6first的文章把複製幹掉《你還能夠再詭異點嗎——SQL日誌文件不斷增加》
EXEC sp_removedbreplication [xxxchives]
步驟七:而後再來收縮日誌
USE [xxxxchives] GO DBCC SHRINKFILE (N'xxxxxchives_log' , 5000) GO
弄完以後,數據庫正常了,沒有log等待,數據也在不斷增長
總結
簡單幾個步驟:從發現問題到解決問題,有些人可能半天才能解決,有些人幾分鐘就能夠解決,這就是積累經驗的重要性
我本身的作法是多看書,多看博客園,在QQ羣裏看一下你們的問題,這就是經驗了,快速解決問題的經驗
本人也喜歡將工做中遇到的問題寫在博客裏面,以供你們參考,你們一塊兒進步o(∩_∩)o
若有不對的地方,歡迎你們拍磚o(∩_∩)o