我不是SQL专家,每当我需要做一些基本之外的事情时,我就会想起这个事实。我有一个测试数据库,它的大小不是很大,但是事务日志确实很大。如何清除事务日志?
当前回答
下面是收缩事务日志的脚本,但是我强烈建议在收缩之前备份事务日志。
如果你只是缩小文件,你将失去大量的数据,这些数据在灾难发生时可能会成为救星。事务日志包含大量有用的数据,可以使用第三方事务日志读取器读取(可以手动读取,但需要付出很大的努力)。
当涉及到时间点恢复时,事务日志也是必须的,所以不要把它扔掉,而是要确保事先备份它。
以下是人们使用存储在事务日志中的数据来完成恢复的几篇文章:
如何查看SQL Server 2008的事务日志 读取SQL Server 2008中的日志文件(*.LDF)
USE DATABASE_NAME;
GO
ALTER DATABASE DATABASE_NAME
SET RECOVERY SIMPLE;
GO
--First parameter is log file name and second is size in MB
DBCC SHRINKFILE (DATABASE_NAME_Log, 1);
ALTER DATABASE DATABASE_NAME
SET RECOVERY FULL;
GO
当执行上面的命令时,您可能会得到类似这样的错误
"不能收缩日志文件(日志文件名),因为逻辑 位于文件末尾的日志文件正在使用"
这意味着正在使用TLOG。在这种情况下,尝试在一行中多次执行该命令,或者找到减少数据库活动的方法。
其他回答
其他一些答案对我来说不适用:当db在线时不可能创建检查点,因为事务日志已满(多么讽刺)。但是,在将数据库设置为紧急模式后,我能够收缩日志文件:
alter database <database_name> set emergency;
use <database_name>;
checkpoint;
checkpoint;
alter database <database_name> set online;
dbcc shrinkfile(<database_name>_log, 200);
这是一种简单且不优雅且有潜在危险的方法。
备份数据库 分离数据库 重命名日志文件 附加数据库 将重新创建新的日志文件 删除重命名日志文件。
我猜您没有做日志备份。(截断日志)。我的建议是将恢复模式从完全恢复改为简单恢复。这将防止日志膨胀。
减小日志文件的大小应该用于遇到您不希望再次发生的意外增长的情况。如果日志文件将再次增长到相同的大小,那么通过临时缩小它并不能完成太多工作。现在,根据数据库的恢复目标,您应该采取以下操作。
首先,进行完全备份
如果没有确保在出现问题时可以恢复数据库,就不要对数据库进行任何更改。
如果你关心时间点的恢复
(所谓的时间点恢复,我的意思是您关心是否能够恢复到完全备份或差异备份之外的任何内容。)
假设您的数据库处于FULL恢复模式。如果不是,那么确保它是:
ALTER DATABASE testdb SET RECOVERY FULL;
Even if you are taking regular full backups, the log file will grow and grow until you perform a log backup - this is for your protection, not to needlessly eat away at your disk space. You should be performing these log backups quite frequently, according to your recovery objectives. For example, if you have a business rule that states you can afford to lose no more than 15 minutes of data in the event of a disaster, you should have a job that backs up the log every 15 minutes. Here is a script that will generate timestamped file names based on the current time (but you can also do this with maintenance plans etc., just don't choose any of the shrink options in maintenance plans, they're awful).
DECLARE @path NVARCHAR(255) = N'\\backup_share\log\testdb_'
+ CONVERT(CHAR(8), GETDATE(), 112) + '_'
+ REPLACE(CONVERT(CHAR(8), GETDATE(), 108),':','')
+ '.trn';
BACKUP LOG foo TO DISK = @path WITH INIT, COMPRESSION;
Note that \\backup_share\ should be on a different machine that represents a different underlying storage device. Backing these up to the same machine (or to a different machine that uses the same underlying disks, or a different VM that's on the same physical host) does not really help you, since if the machine blows up, you've lost your database and its backups. Depending on your network infrastructure it may make more sense to backup locally and then transfer them to a different location behind the scenes; in either case, you want to get them off the primary database machine as quickly as possible.
Now, once you have regular log backups running, it should be reasonable to shrink the log file to something more reasonable than whatever it's blown up to now. This does not mean running SHRINKFILE over and over again until the log file is 1 MB - even if you are backing up the log frequently, it still needs to accommodate the sum of any concurrent transactions that can occur. Log file autogrow events are expensive, since SQL Server has to zero out the files (unlike data files when instant file initialization is enabled), and user transactions have to wait while this happens. You want to do this grow-shrink-grow-shrink routine as little as possible, and you certainly don't want to make your users pay for it.
请注意,你可能需要备份两次日志才有可能去看心理医生(谢谢罗伯特)。
因此,您需要为您的日志文件提出一个实用的大小。如果不了解您的系统,这里没有人能告诉您这是什么,但是如果您经常缩小日志文件,并且它再次增长,那么一个好的水印可能比它的最大值高10-50%。让我们假设它达到200 MB,并且您希望任何后续的自动增长事件为50 MB,那么您可以这样调整日志文件的大小:
USE [master];
GO
ALTER DATABASE Test1
MODIFY FILE
(NAME = yourdb_log, SIZE = 200MB, FILEGROWTH = 50MB);
GO
注意,如果日志文件当前是> 200 MB,你可能需要先运行这个:
USE yourdb;
GO
DBCC SHRINKFILE(yourdb_log, 200);
GO
如果你不关心时间点的恢复
如果这是一个测试数据库,并且您不关心时间点恢复,那么您应该确保数据库处于SIMPLE恢复模式。
ALTER DATABASE testdb SET RECOVERY SIMPLE;
将数据库置于SIMPLE恢复模式将确保SQL Server重用日志文件的部分(基本上淘汰不活跃的事务),而不是不断增长以保留所有事务的记录(就像完全恢复一样,直到备份日志)。CHECKPOINT事件将帮助控制日志,并确保它不需要增长,除非您在检查点之间生成大量t-log活动。
接下来,您应该绝对确保日志增长确实是由于异常事件(例如,年度春季大扫除或重新构建最大的索引),而不是由于正常的日常使用。如果您将日志文件缩小到一个小得可笑的大小,而SQL Server必须再次增大它以适应您的正常活动,那么您将获得什么?您是否能够使用仅临时释放的磁盘空间?如果你需要立即修复,那么你可以运行以下命令:
USE yourdb;
GO
CHECKPOINT;
GO
CHECKPOINT; -- run twice to ensure file wrap-around
GO
DBCC SHRINKFILE(yourdb_log, 200); -- unit is set in MBs
GO
否则,设置适当的规模和增长速度。根据时间点恢复案例中的示例,您可以使用相同的代码和逻辑来确定合适的文件大小并设置合理的自动增长参数。
有些事你不想做
Back up the log with TRUNCATE_ONLY option and then SHRINKFILE. For one, this TRUNCATE_ONLY option has been deprecated and is no longer available in current versions of SQL Server. Second, if you are in FULL recovery model, this will destroy your log chain and require a new, full backup. Detach the database, delete the log file, and re-attach. I can't emphasize how dangerous this can be. Your database may not come back up, it may come up as suspect, you may have to revert to a backup (if you have one), etc. etc. Use the "shrink database" option. DBCC SHRINKDATABASE and the maintenance plan option to do the same are bad ideas, especially if you really only need to resolve a log problem issue. Target the file you want to adjust and adjust it independently, using DBCC SHRINKFILE or ALTER DATABASE ... MODIFY FILE (examples above). Shrink the log file to 1 MB. This looks tempting because, hey, SQL Server will let me do it in certain scenarios, and look at all the space it frees! Unless your database is read only (and it is, you should mark it as such using ALTER DATABASE), this will absolutely just lead to many unnecessary growth events, as the log has to accommodate current transactions regardless of the recovery model. What is the point of freeing up that space temporarily, just so SQL Server can take it back slowly and painfully? Create a second log file. This will provide temporarily relief for the drive that has filled your disk, but this is like trying to fix a punctured lung with a band-aid. You should deal with the problematic log file directly instead of just adding another potential problem. Other than redirecting some transaction log activity to a different drive, a second log file really does nothing for you (unlike a second data file), since only one of the files can ever be used at a time. Paul Randal also explains why multiple log files can bite you later.
要积极主动
一些少量而不是缩小你的日志文件,让它不断自动增长速度小,设置一些合理的大尺寸(最大可以容纳的总和你组并发事务),设定一个合理的自动增长设置回退,所以它不需要多次增长来满足单交易,所以,这将是相对罕见的曾经生长在正常业务操作。
The worst possible settings here are 1 MB growth or 10% growth. Funny enough, these are the defaults for SQL Server (which I've complained about and asked for changes to no avail) - 1 MB for data files, and 10% for log files. The former is much too small in this day and age, and the latter leads to longer and longer events every time (say, your log file is 500 MB, first growth is 50 MB, next growth is 55 MB, next growth is 60.5 MB, etc. etc. - and on slow I/O, believe me, you will really notice this curve).
进一步的阅读
请不要停在这里;虽然您所看到的许多关于缩减日志文件的建议本质上都是不好的,甚至可能是灾难性的,但有些人更关心数据完整性,而不是释放磁盘空间。
我在2009年写了一篇博文,当时我看到一些“这里是如何缩小日志文件”的帖子涌现出来。
Brent Ozar四年前写的一篇博客文章指出了多种资源,以回应一篇本不应该发表的SQL Server杂志文章。
Paul Randal的一篇博客文章解释了为什么t-log维护很重要,以及为什么不应该缩小数据文件。
Mike Walsh给出了一个很好的答案,涵盖了这些方面,包括为什么您可能无法立即缩小日志文件的原因。
如果不使用事务日志进行恢复(即只进行完全备份),可以将恢复模式设置为“简单”,那么事务日志很快就会缩小,再也不会被填满。
如果您使用SQL 7或2000,您可以在数据库选项选项卡中启用“截断检查点日志”。这有同样的效果。
显然,在生产环境中不建议这样做,因为您将无法恢复到某个时间点。
下面是收缩事务日志的脚本,但是我强烈建议在收缩之前备份事务日志。
如果你只是缩小文件,你将失去大量的数据,这些数据在灾难发生时可能会成为救星。事务日志包含大量有用的数据,可以使用第三方事务日志读取器读取(可以手动读取,但需要付出很大的努力)。
当涉及到时间点恢复时,事务日志也是必须的,所以不要把它扔掉,而是要确保事先备份它。
以下是人们使用存储在事务日志中的数据来完成恢复的几篇文章:
如何查看SQL Server 2008的事务日志 读取SQL Server 2008中的日志文件(*.LDF)
USE DATABASE_NAME;
GO
ALTER DATABASE DATABASE_NAME
SET RECOVERY SIMPLE;
GO
--First parameter is log file name and second is size in MB
DBCC SHRINKFILE (DATABASE_NAME_Log, 1);
ALTER DATABASE DATABASE_NAME
SET RECOVERY FULL;
GO
当执行上面的命令时,您可能会得到类似这样的错误
"不能收缩日志文件(日志文件名),因为逻辑 位于文件末尾的日志文件正在使用"
这意味着正在使用TLOG。在这种情况下,尝试在一行中多次执行该命令,或者找到减少数据库活动的方法。
推荐文章
- 我如何在T-SQL用逗号格式化一个数字?
- LEFT OUTER JOIN如何返回比左表中存在的记录更多的记录?
- 如何用SQL语句计算百分比
- SQL Server动态PIVOT查询?
- 如何等待2秒?
- SQL Server: CROSS JOIN和FULL OUTER JOIN的区别是什么?
- varchar和nvarchar SQL Server数据类型之间的主要性能差异是什么?
- 向现有表添加主键
- 我应该在SQL varchar(长度)中考虑电话的最长的全球电话号码是什么
- 表中标识列的显式值只能在使用列列表且IDENTITY_INSERT为ON SQL Server时指定
- 如何确定已安装的SQL Server实例及其版本?
- Scope_Identity()、Identity()、@@Identity和Ident_Current()之间的区别是什么?
- 如何在TSQL中刷新打印缓冲区?
- 如何用一个SQL查询从数据库中删除所有表?
- SQL查询返回两个表之间的差异