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


77

我有一个[My DB]数据库,其中包含以下信息:
SQL Server 2008
MDF大小:30 GB
LDF大小:67 GB

我想尽可能地缩小日志文件,因此我开始寻求解决方法。注意:我不是DBA(甚至不是DBA),并且在完成此任务时一直感觉良好。

首先,我只是进入SSMS,DB属性,文件,然后将“初始大小(MB)”值编辑为10。这将日志文件减小为62 GB(不完全是我输入的10 MB)。因此,我附加了SQL事件探查器,看到正在调用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)。

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

结果与第一次复查相同。我只能将日志文件减小到62 GB。

我不确定自己做错了什么,下一步该怎么做。


为了防止再次发生这种情况,您应该运行日志备份或将恢复模式设置为simple。
DForck42,2011年

3
我的问题是暂停的复制/镜像设置-看来sql如果认为需要复制它们,就不会收缩它们。这可能不是很多人的问题,但可能会有所帮助。
小资

Answers:


43

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

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

有关示例和说明,请参见此DBCC SHRINKFILE(Transact-SQL) msdn页面上的示例B。


出于好奇,是否有办法通过SSMS UI来查看恢复模式是什么?我浏览了数据库属性,但没有看到它。最接近的是显示Recovery / PageVerify值的“属性/选项”页面。
Ed Sinek

找到了-它不在“其他选项”列表中。它在页面顶部-三个下拉菜单之一。谢谢。
Ed Sinek

5
我会建议在运行此查询:select recovery_model_desc,从sys.databases中,其中name =“数据库名称”
jlnorsworthy

谢谢。改变恢复模式是关键:)
Alireza

133

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

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

SELECT * FROM sys.database_files;

在我的实例中,日志文件为file_id2。现在,我们要找到正在使用的虚拟日志,并使用以下命令进行操作。

DBCC LOGINFO;

在这里,您可以通过查看状态是2(正在使用)还是0(空闲)来查看是否正在使用任何虚拟日志。收缩文件时,将从文件末尾开始物理删除空的虚拟日志,直到达到第一个使用状态为止。这就是为什么缩小事务日志文件有时会使其部分缩小但不会删除所有可用的虚拟日志的原因。

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

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

然后将显示虚拟日志文件的分配,希望您会注意到它已有所减少。由于虚拟日志文件并非总是按顺序分配,因此您可能必须备份事务日志几次,然后再次运行该最后一个查询。但是我通常可以将其压缩到一两个备份之内。


6
像魅力一样工作。备份99%的免费日志只花了一秒钟,文件立即从22,000MB增长到200MB。这应该标记为正确答案。
Triynko 2015年

我感谢背景资料。不过,我仍然感到困惑,因为我认为您的解决方案可以归结为原始海报尝试过且无法正常工作的解决方案。您的解决方案是否可以多次运行“ BACKUP LOG ... GO DBCC SHRINKFILE ...”,直到可以正常工作?我尝试了几次都没有成功,似乎OP也尝试了失败。只是想弄清楚我是否在您的答案中遗漏了一些东西。
小资2015年

3
更新:我的问题是暂停的复制/镜像设置锁定了tlog。可能是一个小的边缘情况。
小资

4
@pettys是,如果您想将文件缩小到最小大小,则必须一次性完成备份,缩小,备份和缩小。原因(我认为是故意的)是,收缩只会将日志文件的大小减小到自上次备份以来的“已用页面”的大小;可能最大程度地减少了增长日志文件的需求,这对于定期进行加载和备份的生产环境很有用。上面试图演示和调试。如果您的日志文件中有“ 0”,则可以进一步缩小。如果不是这样,则释放备份日志的页面可能会出现问题。
Radderz 2015年

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

6
而且,如果您这样做了,那么您就破坏了事务日志备份链-这样,如果在重置为完全恢复后发生灾难……您将100%丢失数据,除非您在启动后进行了完全备份或DIFF备份重置为RECOVERY FULL。此外,WITH NO_WAIT表示您没有时间在进行中的交易。更好的选择是10秒后回滚(或类似的操作)。
迈克尔·坎贝尔

如何获取log_file_name或数字?
Kiquenet

10

尝试这个

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

保罗·兰达尔(Paul Randal)在他的博客上对此问题进行了详尽的讨论:http ://www.sqlskills.com/blogs/paul/post/backup-log-with-no_log-use-abuse-and-undocumented-trace-flags-to -stop-it.aspx


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

1
这是一个非常糟糕的主意,它在“当前接受的答案”中提供,并带有免责声明,说明其为何不好
詹姆斯·詹金斯

0

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


-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

这是一个非常糟糕的主意,它在“当前接受的答案”中提供,并带有免责声明,说明其为何不好
James Jenkins
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.