即使在BACKUP LOG TO DISK之后,日志文件上的DBCC SHRINKFILE也没有减小大小

时间:2011-08-25 15:54:02

标签: sql-server backup transaction-log dbcc

我有一个数据库,[我的数据库],它有以下信息:
SQL Server 2008
MDF尺寸:30 GB
LDF大小:67 GB

我想尽可能地缩小日志文件,所以我开始寻找如何做到这一点。警告:我不是一名DBA(甚至是接近DBA)并且一直在努力完成这一任务。

首先,我刚进入SSMS,数据库属性,文件,并将初始大小(MB)值编辑为10.这将日志文件减少到62 GB(不完全是我输入的10 MB)。所以,我附加了SQL Profiler,看到正在调用DBCC SHRINKFILE。然后我将该命令输入查询编辑器,这是结果。

DBCC SHRINKFILE (N'My DB_Log' , 10)

输出结果为:

Cannot shrink log file 2 (My DB_Log) because the logical log file located at the end of the file is in use.
DbId   FileId      CurrentSize MinimumSize UsedPages   EstimatedPages
------ ----------- ----------- ----------- ----------- --------------
8      2           8044104     12800       8044104     12800

(1 row(s) affected)

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
然后我对此做了一些研究并发现了这个:

http://support.microsoft.com/kb/907511

其中说我需要在收缩文件之前备份日志文件,以便释放虚拟日志文件并且收缩文件可以完成它的工作 - 我不知道这意味着什么......我只是在这里解释:)

所以,我想我会尝试备份日志文件,然后执行DBCC SHRINKFILE(我将新的日志文件大小更改为12800,因为这是在前一个DBCC SHRINKFILE命令的输出中标识的MinimumSize)< / p>

BACKUP LOG [My DB] TO DISK = 'D:\SQLBackup\20110824-MyDB-Log.bak'
GO
DBCC SHRINKFILE (N'My DB_Log' , 12800)
GO

结果与第一次结果相同。我只能将日志文件降低到62 GB。

我不确定我做错了什么,接下来应该尝试什么。

10 个答案:

答案 0 :(得分:112)

好的,这是一个减少事务文件物理大小的解决方案,但是没有将恢复模式更改为简单。

在数据库中,使用以下查询找到日志文件的file_id。

SELECT * FROM sys.database_files;

在我的实例中,日志文件是file_id 2.现在我们要查找正在使用的虚拟日志,并使用以下命令执行此操作。

DBCC LOGINFO;

在这里,您可以通过查看状态是2(正在使用中)还是0(免费)来查看是否正在使用任何虚拟日志。收缩文件时,从文件末尾开始物理删除空虚拟日志,直到它达到第一个使用状态。这就是为什么缩小事务日志文件有时会在某种程度上缩小它,但不会删除所有可用的虚拟日志。

如果您注意到0之后出现的状态2,则阻止了完全缩小文件的缩减。要解决此问题,请执行另一个事务日志备份,并立即运行这些命令,提供上面找到的file_id,以及希望将日志文件缩减到的大小。

-- DBCC SHRINKFILE (file_id, LogSize_MB)
DBCC SHRINKFILE (2, 100);
DBCC LOGINFO;

这将显示虚拟日志文件分配,希望您会注意到它已经有所减少。由于虚拟日志文件并不总是按顺序分配,您可能需要多次备份事务日志并再次运行此最后一个查询;但我通常可以在一两个备份中缩小它。

答案 1 :(得分:33)

除了已经执行的步骤之外,还需要将恢复模式设置为简单,然后才能缩小日志。

对于生产系统而言,这不是推荐的实践 ...您将失去从以前的备份/日志文件恢复到某个时间点的能力。

有关示例和解释,请参阅此DBCC SHRINKFILE (Transact-SQL) msdn页面上的示例B.

答案 2 :(得分:13)

我在sql server 2008 R2上使用此脚本。

USE [db_name]

ALTER DATABASE [db_name] SET RECOVERY SIMPLE WITH NO_WAIT

DBCC SHRINKFILE([log_file_name]/log_file_number, wanted_size)

ALTER DATABASE [db_name] SET RECOVERY FULL WITH NO_WAIT

答案 3 :(得分:7)

试试这个

ALTER DATABASE XXXX  SET RECOVERY SIMPLE

use XXXX

declare @log_File_Name varchar(200) 

select @log_File_Name  = name from sysfiles where filename like '%LDF'

declare @i int = FILE_IDEX ( @log_File_Name)

dbcc shrinkfile ( @i , 50) 

答案 4 :(得分:4)

答案 5 :(得分:4)

  

收缩日志文件

对于日志文件,数据库引擎使用target_size来计算整个日志的目标大小;因此,target_size是收缩操作后日志中的可用空间量。然后将整个日志的目标大小转换为每个日志文件的目标大小。 DBCC SHRINKFILE尝试立即将每个物理日志文件缩小到其目标大小。

但是,如果逻辑日志的一部分驻留在超出目标大小的虚拟日志中,则数据库引擎会释放尽可能多的空间,然后发出信息性消息。

该消息描述了将逻辑日志移出文件末尾的虚拟日志所需的操作。执行操作后,可以使用DBCC SHRINKFILE释放剩余空间。

由于日志文件只能缩小到虚拟日志文件边界,因此可能无法将日志文件缩小到小于虚拟日志文件大小的大小,即使它未被使用< / strong>即可。创建或扩展日志文件时,数据库引擎会动态选择虚拟日志文件的大小。

  
      
  • 疑难解答:文件不缩小
  •   

如果收缩操作没有错误地运行,但文件的大小似乎没有变化,请通过执行以下操作之一来验证文件是否有足够的可用空间来删除​​:

运行以下查询。

  

SELECT name,size / 128.0 - CAST(FILEPROPERTY(name,&#39; SpaceUsed&#39;)AS   int)/128.0 AS AvailableSpaceInMB FROM sys.database_files;

运行 DBCC SQLPERF 命令以返回事务日志中使用的空间。

  • 如果可用空间不足,则缩小操作不能再进一步减小文件大小。

  • 通常,日志文件似乎不会缩小。这通常是未截断的日志文件的结果。

  • 您可以截断日志,方法是将数据库恢复模式设置为SIMPLE ,或者备份日志然后运行再次 DBCC SHRINKFILE 操作。

示例:

将日志文件缩小到指定的目标大小

以下示例将AdventureWorks数据库中的日志文件缩小为1 MB。要允许DBCC SHRINKFILE命令收缩文件,首先通过将数据库恢复模型设置为SIMPLE来截断该文件。

  

Transact-SQL

USE AdventureWorks2012;
GO
- 通过将数据库恢复模型更改为SIMPLE来截断日志 ALTER DATABASE AdventureWorks2012
SET RECOVERY SIMPLE;
GO
- 将截断的日志文件缩小为1 MB DBCC SHRINKFILE(AdventureWorks2012_Log,1);
GO
- 重置数据库恢复模型 ALTER DATABASE AdventureWorks2012
SET RECOVERY FULL;
GO

当您使用DBCC SHRINKFILE(日志文件,大小)时,它只会从日志文件的末尾截断尽可能多的内容。当它到达仍在使用的最高虚拟日志时,它无法进一步缩小。这在SQL Server联机丛书中描述:

http://technet.microsoft.com/en-us/library/ms189493.aspx

因此,一旦日志的高端清晰,它的大小就会缩小。同样,这将取决于仍在使用多少日志。可以通过备份清除日志,但备份不会清除未完成的事务,因此即使重复备份,日志也可以保留在高端VLF中。

关于VLF的增加和减少,最初创建的日志文件有多大,日志文件增长的设置是什么?如果它只增长很少,它将产生比任何人想要的更多的VLF。

缩小日志文件的常见模式是CHECKPOINT,BACKUP,SHRINKFILE,CHECKPOINT,BACKUP,SHRINKFILE等,直到获得结果。日志可能不会缩小的原因有很多,包括非常大的回滚。

从简单切换为完整有问题:

这里有规则和例外。我们将在下面深入讨论长期交易。

但要注意完全恢复模式的一个注意事项是:如果您只是切换到完全恢复模式,但从未进行初始完全备份,则SQL Server将无法满足您处于完全恢复模式的请求。您的事务日志将继续在Simpleuntil中运行,您可以切换到完全恢复模型并进行第一次完全备份。

没有日志备份的完整恢复模型很糟糕:

那么,这是不受控制的日志增长的最常见原因?答:处于完全恢复模式而没有任何日志备份。

这种情况一直发生在人们身上。

为什么这是一个常见的错误?

为什么会一直发生?因为每个新数据库都通过查看模型数据库来获取其初始恢复模型设置。

模型的初始恢复模型设置始终是完全恢复模型 - 除非有人更改它。所以你可以说&#34;默认的恢复模型&#34;已满。许多人都没有意识到这一点,并且他们的数据库在完全恢复模型中运行而没有日志备份,因此事务日志文件比必要的大得多。这就是为什么在他们不为您的组织及其需求工作时更改默认值非常重要的原因。

答案 6 :(得分:2)

我尝试了很多方法,但这很有效。

示例代码可在DBCC SHRINKFILE

中使用
USE DBName;  
GO  
-- Truncate the log by changing the database recovery model to SIMPLE.  
ALTER DATABASE DBName  
SET RECOVERY SIMPLE;  
GO  
-- Shrink the truncated log file to 1 MB.  
DBCC SHRINKFILE (DBName_log, 1);  --File name SELECT * FROM sys.database_files; query to get the file name
GO  
-- Reset the database recovery model.  
ALTER DATABASE DBName  
SET RECOVERY FULL;  
GO

答案 7 :(得分:0)

我通过执行完整备份和事务备份解决了此问题。有时,备份过程没有完成,这就是.ldf文件没有缩小的原因之一。尝试这个。它对我有用。

答案 8 :(得分:0)

我们的一个交易量很大的数据库每天在日志表中增加几十万条记录。有多个日志文件每天增加数百 GB。

我们有一个计划作业,每半小时进行一次差异备份。我们还有另一项预定的内务工作,每天清晨运行。

将 RECOVERY 设置为 SIMPLE 后,我们会在整理期间执行 SHRINKFILE。我们会在过程开始和结束时进行完整备份,以克服无法从以前的备份/日志文件恢复到某个时间点的问题。我们在数据库中使用一些标志来确保在完成内务工作之前不会尝试进行差异备份。 简要概述如下—— 家政工作:

  1. 将状态设置为“整理中”
  2. 将数据库设置为单用户模式
  3. 对数据库进行完整备份
  4. 从各种旧表中删除记录
  5. 将数据库恢复模式设置为简单
  6. 遍历日志文件并缩小每个文件
  7. 将数据库恢复模式设置为FULL
  8. 对数据库进行完整备份
  9. 将数据库设置为多用户模式
  10. 将状态设置为“内务管理已完成”

差异备份作业:

  1. 仅在状态为“内务完成”时继续
  2. 进行差异备份

完成需要一段时间,但在早上正常业务开始之前,它会使我们的数据库变得整洁和新鲜。它对我们来说一直很好。

答案 9 :(得分:-1)

感谢@ user2630576和@ Ed.S。

以下是一种享受:

BACKUP LOG [database] TO DISK = 'D:\database.bak'
GO

ALTER DATABASE [database] SET RECOVERY SIMPLE

use [database]

declare @log_File_Name varchar(200)

select @log_File_Name = name from sysfiles where filename like '%LDF'

declare @i int = FILE_IDEX ( @log_File_Name)

dbcc shrinkfile ( @i , 50)

ALTER DATABASE [database] SET RECOVERY FULL