技术开发 频道

管理SQL Server事务日志的大小

  【IT168 技术文档】这些用于该脚本的查询和临时对象基于我在2008年底发表的一篇名为“确定分配给Microsoft SQL Server数据库的空闲空间、消耗空间和总空间”的文章。在这篇文章中,我讲解了你如何通过创建自己的存储过程来立即返回日志大小,文件大小和空间消耗大小的信息从而解决存在于Microsoft SQL Server中的大量多余方法论的问题。

  LogWatch所作的不是接近相同的元数据,而是更加接近它来避免这种情况的发生:你的事务日志似乎由于数据文件的大小而失去控制。我们之前都看过这种情况,它可能由于多种原因而发生。你可能遇到这样的情况:一个数据库寄生在你的某个实例中,该日志文件是10GB,而数据文件仅仅5GB。(我不是说自己遇到过这种情况,但假设我有个朋友遇到过。)无论如何,你有一个事务日志看起来严重超大。为什么发生这种情况呢?其中一些原因是:

  备份行为不足。 也许数据库高度进行事务处理,以全备份模式来运行,但是日志没有以正确的频率来备份,从而不能匹配活动的进行。
 
  一个数据库备份可能由于某些原因被遗漏或者失败了,如磁盘空间,在运行备份中SQL Agent job开始的某个步骤的失败,或者其它问题影响了备份过程的顺利进行。

  设计不良的数据库不能充分提交T-SQL代码中的事务,因此导致在大量多于活动在写到数据文件之前就记录下来了。

  不恰当的数据库恢复模式

  usp_LogWatch存储过程利用深受我喜爱的一个未正式纪录的存储程序sp_Msforeachdb来查询该实例中的每一个数据库,记录每个数据库文件结构的大小信息。随后,它返回这样的结果: 每个数据库日志文件的累积大小超过该数据库日志文件总大小的50%。这种情况很容易通过WHERE子句来调整,它把结果返回给用户,并且只与我的环境有关。

  任何超过这些限制的东西都是小问题,我确实不需要花时间来检查。请注意在我的环境中我使用了一个专门的数据库用于这个性质的脚本。我也有一个独立的模式,它依赖于该数据库的函数。我使用了一个叫做MetaBOT的模式和类似的脚本。我也使用了模式StatsBOT, IndexBOT,BackupBOT。我确定你能够明白这是为什么。如果你不能利用模式,你可以通过用dbo替代MetaBOT的参照简单修改脚本中的代码来使用dbo模式。让我们来看看下面的代码。

CREATE PROCEDURE [MetaBOT].[usp_LogWatch] AS
  
DECLARE @SQL VARCHAR(5000)
  
--Clean up temp objects if not properly done so previously
  IF EXISTS (SELECT NAME FROM tempdb..sysobjects WHERE NAME = '#usp_LogWatch_Results')
  
BEGIN
  
DROP TABLE #usp_LogWatch_Results
  
END
  
--Create temporary table to store results
  CREATE TABLE #usp_LogWatch_Results ([Database Name] sysname, [File Type] VARCHAR(4), [Total Size in Mb] INT)
  
--Create SQL script to run against all databases on the instance
  SELECT @SQL =
  
'USE [?]
  INSERT INTO #usp_LogWatch_Results([Database Name], [File Type], [Total Size in Mb])
  SELECT DB_NAME(), [File Type] =
   CASE type
  WHEN 0 THEN
''Data'''
  
+
  
'WHEN 1 THEN ''Log'''
  
+
  
'END,
  [Total Size in Mb] =
  CASE ceiling([size]/128)
  WHEN 0 THEN 1
  ELSE ceiling([size]/128)
  END
  FROM sys.database_file
  --Run the command against each database
  EXEC sp_MSforeachdb @SQL
  SELECT D.[Database Name], D.[Total Data File Size In Mb], L.[Total Log File Size In Mb],
  CAST(CAST(L.[Total Log File Size In Mb] AS decimal(8,1))/CAST(D.[Total Data File Size In Mb]
  AS decimal(8,1)) AS decimal(4,2)) AS [Log::Data Ratio]
  FROM
  (
  SELECT [Database Name], [File Type], SUM([Total Size in Mb]) AS [Total Data File Size In Mb]
  FROM #usp_LogWatch_Results
  WHERE [File Type] =
'Data'
  GROUP BY [Database Name], [File Type]
  ) AS D INNER JOIN
  (
  SELECT [Database Name], [File Type], SUM([Total Size in Mb]) AS [Total Log File Size In Mb]
  FROM #usp_LogWatch_Results
  WHERE [File Type] =
'Log'
  GROUP BY [Database Name], [File Type]
  ) AS L ON D.[Database Name] = L.[Database Name]
  WHERE L.[Total Log File Size In Mb] > 500 AND
  CAST(CAST(L.[Total Log File Size In Mb] AS decimal(8,1))/CAST(D.[Total Data File Size In Mb]
  AS decimal(8,1)) AS decimal(4,2)) > 0.5
  ORDER BY CAST(CAST(L.[Total Log File Size In Mb] AS decimal(8,1))/CAST(D.[Total Data File Size In Mb]
  AS decimal(8,1)) AS decimal(4,2)) DESC,
  L.[Total Log File Size In Mb] DESC
  --Clean up your temporary objects
  DROP TABLE #usp_LogWatch_Results

  结果通过数据库,所有相关数据文件的总大小,累计日志文件大小,通过数据文件和日志文件相除计算得到的比率来返回。

  因此,观察第一个记录,你会看到也许有些东西失去平衡。这肯定需要调查。反过来,观察最后一条记录,根据数据库行为,大小可能是可以接受的。这就是为什么明白你所支持的总环境这么重要,即使你没有资源提供对整个SQL Server域的共同支持。并非所有的结果都有必要理解成有些东西出现问题了。重要的是即使我没有像需要的那样有足够的时间和用80%的注意力来处理20%的部分那样,但是我需要处理在我的SQL Server环境中到底发生了什么事,并且明白什么时候结果是对的还是错的。

0
相关文章