即使在将日志备份到磁盘后,日志文件上的 DBCC SHRINKFILE 也不会减小大小

发布于 2024-12-01 22:21:13 字数 1377 浏览 0 评论 0 原文

我有一个数据库 [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 命令的输出中标识的最小大小

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

)和第一圈一样。我只能将日志文件减小到 62 GB。

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

I've got a database, [My DB], that has the following info:
SQL Server 2008
MDF size: 30 GB
LDF size: 67 GB

I wanted to shrink the log file as much as possible and so I started my quest to figure out how to do this. Caveat: I am not a DBA (or even approaching a DBA) and have been progressing by feel through this quest.

First, I just went into SSMS, DB properties, Files, and edited the Initial Size (MB) value to 10. That reduced the log file to 62 GB (not exactly the 10 MB that I entered). So, I attached SQL Profiler, saw that DBCC SHRINKFILE was being called. I then entered that command into the query editor and here's the results.

DBCC SHRINKFILE (N'My DB_Log' , 10)

And the output was:

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.

I then did some research on that and found this:

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

Which says that I need to backup the log file before the shrinkfile so that the virtual log files will be released and the shrinkfile can do its job - I don't know what that means... I'm just paraphrasing here :)

So, I figured I'd try to backup the log file and then do a DBCC SHRINKFILE (and I changed the new log file size to 12800 since that was the MinimumSize identified in the output of the previous DBCC SHRINKFILE command)

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

The result was the same as the first go around. I can only get the log file down to 62 GB.

I'm not sure what I'm doing wrong and what I should try next.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

仙气飘飘 2024-12-08 22:21:13

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

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

SELECT * FROM sys.database_files;

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

DBCC LOGINFO;

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

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

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

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

Okay, here is a solution to reduce the physical size of the transaction file, but without changing the recovery mode to simple.

Within your database, locate the file_id of the log file using the following query.

SELECT * FROM sys.database_files;

In my instance, the log file is file_id 2. Now we want to locate the virtual logs in use, and do this with the following command.

DBCC LOGINFO;

Here you can see if any virtual logs are in use by seeing if the status is 2 (in use), or 0 (free). When shrinking files, empty virtual logs are physically removed starting at the end of the file until it hits the first used status. This is why shrinking a transaction log file sometimes shrinks it part way but does not remove all free virtual logs.

If you notice a status 2's that occur after 0's, this is blocking the shrink from fully shrinking the file. To get around this do another transaction log backup, and immediately run these commands, supplying the file_id found above, and the size you would like your log file to be reduced to.

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

This will then show the virtual log file allocation, and hopefully you'll notice that it's been reduced somewhat. Because virtual log files are not always allocated in order, you may have to backup the transaction log a couple of times and run this last query again; but I can normally shrink it down within a backup or two.

我最亲爱的 2024-12-08 22:21:13

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

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

请参阅此 DBCC SHRINKFILE (Transact-SQL) msdn 页面上的示例 B一个例子和解释。

In addition to the steps you have already taken, you will need to set the recovery mode to simple before you can shrink the log.

THIS IS NOT A RECOMMENDED PRACTICE for production systems... You will lose your ability to recover to a point in time from previous backups/log files.

See example B on this DBCC SHRINKFILE (Transact-SQL) msdn page for an example, and explanation.

沒落の蓅哖 2024-12-08 22:21:13

试试这个

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) 

Try this

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) 
薔薇婲 2024-12-08 22:21: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

I use this script on 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
醉南桥 2024-12-08 22:21:13

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

示例代码可在 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

I tried many ways but this works.

Sample code is availalbe in 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
扛起拖把扫天下 2024-12-08 22:21:13

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

I resolved this problem by taking the full and transactional backup. Sometimes, the backup process is not completed and that's one of the reason the .ldf file is not getting shrink. Try this. It worked for me.

友欢 2024-12-08 22:21:13

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

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

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

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

差异备份作业:

  1. 仅当状态为“内务管理已完成”
  2. 进行差异备份

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

One of our heavily transacted databases grows a few hundred thousand records in a log table every day. There are multiple log files that grow a few hundred GB every day.

We have a scheduled job that takes differential backup every half an hour. We have another scheduled job for housekeeping that runs early morning every day.

We do SHRINKFILE during the housekeeping after setting the RECOVERY to SIMPLE. We do take a full backup at the beginning and at the end of the process in order to overcome the issue of losing our ability to recover to a point in time from previous backups/log files. We use some flag in the database to make sure that the differential backup is not attempted until the housekeeping job is completed.
The brief outline is as below -
The House Keeping job:

  1. Set the status to 'Housekeeping in progress'
  2. Set the database to Single User mode
  3. Take a full backup of the database
  4. Delete records from various tables that are old
  5. Set the database RECOVERY mode to SIMPLE
  6. Iterate through the log files and shrink each of them
  7. Set the database RECOVERY mode to FULL
  8. Take a full backup of the database
  9. Set the database to Multi-User mode
  10. Set the status to 'Housekeeping completed'

The differential backup job:

  1. Proceed only if the status is 'Housekeeping completed'
  2. Take a differential backup

It takes a while to complete but it gets our database tidy and fresh before the regular business starts in the morning. It has been working fine for us.

心不设防 2024-12-08 22:21:13

遇到同样的问题,尝试使用 DBCC FREEPROCCACHE

它确实有帮助,我已经成功地缩小了 tempdb 的数据文件。

Had same issue, gave a try with DBCC FREEPROCCACHE.

It did help, I've managed to do shrink on tempdb's data files.

瀞厅☆埖开 2024-12-08 22:21:13

我在数据库中遇到了这个问题,最后找到了关于 CHECKPOINT 调用的注释。我的数据库已经设置为简单日志记录。关键是要运行几次,直到有结果。我能够将大约 7GB 的日志文件减少到大约 100 MB。拥有内存优化的文件组可能与需要这样做的原因有关。

CHECKPOINT
GO
DBCC SHRINKFILE (Your_Log_File_Name_Or_Id_Here, 100)
GO

I struggled with this on my database and finally found a comment about the CHECKPOINT call. My database was already set for SIMPLE logging. The key was to run this several times until there were results. I was able to get from about 7GB log file down to around 100 MB. Having a memory optimized file group may have something to do with why this was needed.

CHECKPOINT
GO
DBCC SHRINKFILE (Your_Log_File_Name_Or_Id_Here, 100)
GO
蒗幽 2024-12-08 22:21:13

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

Thanks to @user2630576 and @Ed.S.

the following worked a treat:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文