日志文件上的DBCC SHRINKFILE即使在BACKUP LOG TO DISK后也不会减小大小

我有一个数据库,[我的数据库],有以下信息:
SQL Server 2008
密度板尺寸:30 GB
LDF尺寸:67 GB

我想尽可能缩小日志文件,所以我开始研究如何做到这一点。 警告:我不是DBA(甚至不是DBA),而是通过这个任务感觉到进步。

首先,我进入SSMS,数据库属性,文件,并将初始大小(MB)值编辑为10.这将日志文件减less到62 GB(不完全是我input的10 MB)。 所以,我连接SQL Profiler,看到DBCC SHRINKFILE被调用。 然后我将这个命令input到查询编辑器中,结果如下。

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)

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

结果和第一次一样。 我只能将日志文件下载到62 GB。

我不知道我做错了什么,我应该尝试下一步。

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

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

请参阅此DBCC SHRINKFILE(Transact-SQL) msdn页上的示例B,以获取示例和解释。

好的,这里是一个解决scheme,以减less事务文件的物理大小,但不会将恢复模式更改为简单。

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

 SELECT * FROM sys.database_files; 

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

 DBCC LOGINFO; 

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

如果你注意到在0之后出现的状态2,这就阻止了缩小文件的收缩。 为了解决这个问题,可以进行另一个事务日志备份,并立即运行这些命令,提供上面find的file_id,以及希望减less日志文件的大小。

DBCC SHRINKFILE(file_id,LogSize_MB)

 DBCC SHRINKFILE (2, 100); DBCC LOGINFO; 

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

全文: http : //radderz.me.uk/2014/02/physically-shrinking-sql-transaction-log-files/

我在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 

尝试这个

 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) 

Paul Randal在他的博客上对这个问题进行了很好的讨论: http ://www.sqlskills.com/blogs/paul/post/backup-log-with-no_log-use-abuse-and- undocumented-trace-flags-to -stop-it.aspx

收缩日志文件

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

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

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

由于只能将日志文件收缩到虚拟日志文件边界,因此即使日志文件未被使用,也可能无法将日志文件缩小为小于虚拟日志文件的大小 。 当创build或扩展日志文件时,虚拟日志文件的大小由数据库引擎dynamicselect。

  • 疑难解答:文件不收缩

如果收缩操作运行时没有错误,但该文件的大小似乎没有更改,请通过执行以下操作之一来validation文件是否具有足够的可用空间来删除​​:

运行以下查询。

SELECT name,size / 128.0 – CAST(FILEPROPERTY(name,'SpaceUsed')AS int)/128.0 AS AvailableSpaceInMB FROM sys.database_files;

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

  • 如果可用空间不足,则收缩操作无法进一步缩小文件大小。

  • 通常情况下,它是不会缩小的日志文件。 这通常是未被截断的日志文件的结果。

  • 您可以通过将数据库恢复模型设置为SIMPLE ,或通过备份日志 ,然后再次运行DBCC SHRINKFILE操作来截断日志

例如:

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

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

的Transact-SQL

使用AdventureWorks2012;

– 通过将数据库恢复模型更改为SIMPLE来截断日志。
ALTER DATABASE AdventureWorks2012
设置恢复简单;

– 将截断的日志文件缩小到1 MB。
DBCC SHRINKFILE(AdventureWorks2012_Log,1);

– 重置数据库恢复模式。
ALTER DATABASE AdventureWorks2012
SET RECOVERY FULL;

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

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

所以,一旦日志的高端清晰,就可以缩小规模。 同样,这将取决于有多less日志仍在使用中。 日志可以通过备份来清除,但是备份不会清除未完成的事务,所以即使经过反复的备份,日志也可以保留在高端的VLF中。

关于VLF的增减,日志文件最初创build的数量有多大?日志文件增长的设置是多less? 如果它只增长一点点,它会创造出比任何愿望更多的VLF。

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

从简单切换到完全有一个问题:

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

但要记住完全恢复模式的一个注意事项是:如果您只是切换到完全恢复模式,但从不进行初始完全备份,SQL Server将不会满足您的请求处于完全恢复模式。 您的交易日志将继续像Simpleuntil一样运行,您可以切换到完全恢复模式并进行第一次完整备份。

完全恢复模式没有日志备份是不好的:

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

这一直发生在人们身上。

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

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

模型的初始恢复模型设置始终是完全恢复模式 – 直到有人改变它为止。 所以你可以说“默认恢复模式”是完整的。 很多人都没有意识到这一点,并使他们的数据库在完全恢复模式下运行,没有日志备份,因此事务日志文件比必要的大得多。 这就是为什么当它们不适合你的组织和它的需要时改变默认值是很重要的)

我尝试了很多方法,但是这个工作。

示例代码可以在DBCC SHRINKFILE中find

 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 

感谢@ 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