缩小镜像生产数据库上的事务日志文件的最简单方法

缩小镜像生产数据库上的事务日志文件的最简单方法

在镜像生产数据库上收缩事务日志文件的最简单的方法是什么?

我必须这么做,因为我的磁盘空间已经不够了。

我将在执行此操作之前进行完整的数据库备份,因此我不需要保留事务日志中的任何内容(对吗?我每天都进行完整的数据库备份,可能永远不需要时间点恢复,但如果可以的话我会保持该选项打开 - 这就是 .ldf 的真正用途,对吗?)。

解决了:
好的,完成后通过 SSMS 进行 2 次备份(非 TSQL)仅日志,创建一个全新的备份集,SSMS 中的“收缩文件日志”对话框终于真正起作用了,释放了一些磁盘空间。

不确定为什么需要 2 个备份,或者为什么 TSQL 不起作用,并且收缩对话框中报告的“可回收空间”没有任何变化(第一次备份后的所有收缩尝试都为 99%,但仍然没有释放任何空间),但问题现在解决了。谢谢大家。

答案1

进行事务日志备份,用你觉得最舒服的方法

这将导致已提交到数据库的事务日志从磁盘中删除。理想情况下,您应该创建一个数据库维护任务来定期为您执行此操作,原因正是如此 - 消除旧的事务日志,这样您就不会填满磁盘。

按照你问题的另一部分...不,不是真的。是的,它们执行该功能,但不仅仅是该功能。

数据库的备份(或写入)方式与其他文件不同,因为数据库文件本身不断使用和变化。因此,单一“时间点”备份要么需要将数据库脱机以“冻结”在一致状态,要么导致备份的不同部分包含与备份开始时不同的数据。

事务日志是数据库执行的每项“事务”的记录。每次更改、更新、添加、删除等记录时,这些操作不会写入数据库文件,而是写入单独的文件(事务日志),然后在 SQL 服务器确定这样做安全且不会停止任何活动时提交到数据库文件中。因此,事务日志实际上是数据库更改在实际成为数据库 [文件] 更改之前所存放的位置。

因此,如果您需要返回到给定的数据库状态或时间点,事务日志将被“重放”。本质上,不是复制文件数据,而是转到数据库的最新时间点状态,然后执行所有使数据库进入指定 [稍后] 状态的相同操作。但需要注意的是,在任何给定时间,您的事务日志都将包含尚未提交到数据库的事务。因此,它们不仅仅是执行时间点恢复的能力。它们包含 [一些] 正在或即将对数据库进行的更改。

这就是为什么你必须在清除事务日志之前进行备份——备份完成后,系统就会有一个数据库的时间点副本,供将来的任何恢复参考,能够确定哪些事务已提交到数据库,哪些尚未提交。有了这些信息,系统就知道哪些过时的事务日志应该删除,哪些不应该删除。

但是,这可能需要一些时间,具体取决于您的事务日志的大小。如果您以前从未做过,请做好准备,这将需要一段时间。

答案2

这是一个老问题,但有些事情没有得到很好的解释,希望本文能给你一些启发。如何缩小的问题大部分都得到了回答,但本文将解释你实际所做事情的“原因”部分。

备份(特别是日志备份)有多种功能。数据作为备份集写入磁盘,以便以后根据需要使用或丢弃。每个后续备份都会添加到该备份集中,位于完整日志数据库中。截断日志或启动新备份集会破坏链条,并会阻止(在许多情况下会否定)您恢复到链条破坏之前某个时间点的能力。

日志中的数据实际上并未被删除,备份期间日志文件也不会缩小。活动的 VLF 被标记为非活动,但那些无法完全提交的 VLF 除外 - 它们仍保持活动状态。非活动 VLF 能够被重写,从而使您的日志循环,效果就像一条蛇在吞食自己的尾巴。作为备份的一部分,会发出一个检查点,一旦当前 VLF 填满,它会告诉 DB 开始写入日志的开头。如果此时执行缩小,您将获得日志末尾的所有空间,直到活动 VLF 的位置。

第二次备份似乎“奏效”的原因在于,活动 VLF 通常会在这段时间内填满,并且日志会从头开始写入。当您进行第二次备份时,活动 VLF 会作为备份集的一部分写入磁盘(或不写入),并且 VLF 会标记为非活动状态。由于这是由于上一次收缩导致的日志尾部,因此执行收缩现在会释放日志开头的所有空间,直到当前活动的 VLF。

所有这些都假设了以下几点:1.) 您没有需要数小时或数天才能填满的大量 VLF;2.) 您的数据库相当不活跃,并且没有大量事务写入日志。如果这两种情况中的任何一种对您来说都是问题,那么缩小日志也会是一个问题。

所有这些对于非镜像和镜像数据库都是正确的。不同之处在于,在镜像方案中,您只需要在主数据库上执行维护,前提是您的镜像是完全相同的。

答案3

镜像功能使用日志来跟踪事物,直到它知道另一台服务器有这些更改。所以,ldf 不只是用于时间点恢复。(它对于某些复制方案也很重要,但您没有这样做。)即使 TRUNCATE_ONLY 也不会丢弃 SQL 可能需要的内容的记录更改。典型的例子是一些大型或长期运行的事务。如果您正在进行一个小时的事务的一半,并且 DBA 运行 TRUNCATE_ONLY,您的内容将不会从 LDF 中清除。LDF 可能会继续增长或遇到其他问题。如果 DBA 终止您的连接,等待回滚完成,然后运行 ​​TRUNCATE_ONLY,则日志应该会释放。

您是否尝试过使用:

select log_reuse_wait_desc from sys.databases where name = 'mydb' 

看看日志为什么这么大?微软文档说系统表这里

您还可以运行:

dbcc opentran() 

这有点老套,但它应该能显示该数据库中任何长时间运行的事务。微软文档中写道在此处命令

我要做的是确保按照计划进行日志备份。

我会确保给 TRUNCATE_ONLY 命令一点时间来工作,有时 SQL 需要一段时间才能开始向 LDF 文件前面的 VLF 写入。如果 LDF 文件中的最后一个 VLF 是正在写入的 VLF,则 SQL 无法缩短文件。如果做不到这一点,我会做一个完整的 BACKUP DATABASE(使用 COPY_ONLY,或者等到常规备份发生,如果那不是太远的话)。有时这似乎可以启动事情,但可能只是在等待当前 VLF 移动到 LDF 文件前面时备份分散了我的注意力。在当前 VLF 移动到 LDF 文件前面后,您应该能够使用 dbcc shrinkfile() 并获得预期结果。我建议先尝试删除小块,而不是尝试一次性完成所有操作。

此外,您还希望避免定期执行此操作,因为重复的“收缩-自动增长-收缩-自动增长”循环可能会损害性能。(这可能会导致文件碎片化,并且实际增长过程可能需要很长时间,在此期间无法提交任何事务。将文件增大到足够大,以使它们不会自动增长。自动增长应该是万无一失的,不应依赖。

相关内容