79

我有一个数据库 [My DB],它包含以下信息:
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)

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

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

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

4

9 回答 9

139

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

在您的数据库中,使用以下查询找到日志文件的 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;

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

于 2014-02-17T03:38:02.710 回答
44

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

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

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

于 2011-08-25T16:09:29.337 回答
12

尝试这个

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) 
于 2013-07-29T14:25:35.913 回答
12

我在 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
于 2014-04-08T09:36:23.620 回答
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

于 2012-08-21T14:12:15.567 回答
3

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

示例代码在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
于 2017-07-19T06:30:52.473 回答
1

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

于 2020-11-13T08:40:21.160 回答
0

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

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

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

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

差异备份作业:

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

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

于 2021-06-20T07:07:05.300 回答
-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
于 2014-01-21T00:02:24.867 回答