今天开发找我,说数据库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