【问题标题】:The transaction log for the database is full数据库的事务日志已满
【发布时间】:2013-07-14 12:59:30
【问题描述】:

我有一个长时间运行的进程,该进程在整个持续时间内保持打开事务。

我无法控制它的执行方式。

由于事务在整个持续时间内保持打开状态,当事务日志填满时,SQL Server 无法增加日志文件的大小。

因此进程失败并出现错误"The transaction log for database 'xxx' is full"。

我试图通过增加数据库属性中事务日志文件的大小来防止这种情况发生,但我得到了同样的错误。

不知道接下来我应该尝试什么。该过程会运行几个小时,因此试错并不容易。

有什么想法吗?

如果有人有兴趣,该过程是Microsoft Dynamics CRM 4.0.中的组织导入

有足够的磁盘空间,我们有简单日志模式的日志,并在启动进程之前备份了日志。

-=-=-=-=- 更新 -=-=-=-=-

到目前为止,感谢所有 cmets。以下是让我相信日志不会因为打开的事务而增长的原因:

我收到以下错误...

Import Organization (Name=xxx, Id=560d04e7-98ed-e211-9759-0050569d6d39) failed with Exception:
System.Data.SqlClient.SqlException: The transaction log for database 'xxx' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases

所以按照这个建议,我去了“log_reuse_wait_desc column in sys.databases”,它的值是“ACTIVE_TRANSACTION”。

根据微软: http://msdn.microsoft.com/en-us/library/ms345414(v=sql.105).aspx

意思如下:

事务处于活动状态(所有恢复模式)。 • 日志备份开始时可能存在长时间运行的事务。在这种情况下,释放空间可能需要另一个日志备份。有关详细信息,请参阅本主题后面的“长时间运行的活动事务”。

• 事务被延迟(仅限 SQL Server 2005 企业版和更高版本)。延迟事务实际上是一个活动事务,其回滚由于某些不可用资源而被阻止。有关延迟事务的原因以及如何将它们移出延迟状态的信息,请参阅延迟事务。

我是不是误会了什么?

-=-=-=- 更新 2 -=-=-=-

刚刚启动进程,初始日志文件大小设置为 30GB。这需要几个小时才能完成。

-=-=-=- 最终更新 -=-=-=-

这个问题实际上是由日志文件消耗了所有可用磁盘空间引起的。在最后一次尝试中,我释放了 120GB,但它仍然使用了所有空间,最终失败了。

我之前没有意识到这会发生,因为当进程在一夜之间运行时,它会在失败时回滚。这次我能够在回滚之前检查日志文件的大小。

感谢大家的意见。

【问题讨论】:

  • re "...并且已经备份了日志"....如果数据库处于简单模式,您将无法备份日志,日志备份不适用于简单模式。它是批量记录的吗?
  • 我备份了整个数据库并将其缩小,导致日志缩小到 1MB。然后,我最初将日志文件的大小增加到 20GB,现在增加到 30GB。

标签: sql sql-server sql-server-2008 dynamics-crm


【解决方案1】:

要解决此问题,请将 Recovery Model 更改为 Simple 然后 Shrink Files Log

1。 数据库属性 > 选项 > 恢复模型 > 简单

2。 数据库任务 > 收缩 > 文件 > 日志

完成。

然后检查您的数据库日志文件大小 数据库属性 > 文件 > 数据库文件 > 路径

查看完整的 sql server 日志:打开 Log File Viewer at SSMS > 数据库 > 管理 > SQL Server 日志 > 当前

【讨论】:

  • 不,这不能解决问题。问题是日志文件在长时间运行过程中不断增长,直到磁盘空间不足。通过暂时将日志文件移动到另一个具有 1TB 可用空间的驱动器,该问题得到了纠正。当长时间运行的进程(即保持打开事务)正在进行时,您无法缩小日志文件。该过程是文件增长的唯一原因。
  • 正如@Jimbo 已经说过的,这并不能解决 OP 的问题。它可能会释放一些当前未使用的空间,但是一旦再次运行长事务,空间将再次被占用(并且可能更早失败)
  • 这并没有解决问题。我的日志只有 500 个字节。我认为这个问题是在我昨天完成备份后开始的。
  • 如果您在整个驱动器上还有几兆字节可用,这绝对是解决办法。
  • 它可能会解决一个问题。它不能解决 OP 中报告的问题。
【解决方案2】:

我曾经遇到过这个错误,它最终是服务器的硬盘驱动器磁盘空间不足。

【讨论】:

  • 阅读 OP 的更新。原来是这个问题。
  • 我也是这样。我发现一个完全不相关的程序创建了一个非常大的日志文件(超过 400 GB,天哪!)并填满了所有剩余的硬盘空间!一旦我清除了它,问题就消失了。
【解决方案3】:

这是一次性脚本,还是定期发生的工作?

过去,对于临时需要大量日志文件空间的特殊项目,我创建了第二个日志文件并使其变得很大。项目完成后,我们删除了额外的日志文件。

【讨论】:

  • 我不会说这是一次性的工作,但我们很少需要这样做。我没有创建第二个日志文件,但我确实将当前日志文件的初始大小增加到了 30GB。在我上次运行期间,它设置为 20GB,但仍然失败。
  • 考虑到我只有一个驱动器可以使用,拥有第二个日志文件会比拥有一个大文件更好吗?
  • 我现在记得,附加文件主要使我们能够访问另一个更大的驱动器。
  • 导入的数据有多大?如果您要导入 30 GB 的数据,您的日志文件可能需要至少一样大。
  • 日志大小是关键。当前任务再次失败,当我看到失败时日志文件的大小时,我简直不敢相信自己的眼睛。它只处理了一半的帐户,并且已经达到 53GB。看来我必须清理另外 60-70GB 附近的某个地方才能完成此过程。
【解决方案4】:

您是否为日志文件启用了启用自动增长和无限制的文件增长?您可以在“数据库属性 > 文件”中通过 SSMS 进行编辑

【讨论】:

  • 是的。它设置为自动增长 10%,不受限制。问题是当有一个打开的事务时自动增长将不起作用。
  • 您知道这笔交易有多大吗?尝试将事务日志大小设置为大于该估计值,无论如何,如果磁盘分配不是问题,请在开始时为数据和日志分配足够的空间。它提高了性能。不要我们自动增长 10%,只需要几 GB,这样性能就足够了。
  • SQL Server 如果需要更多空间来完成该事务,则在事务期间自动增长日志。
  • 嗨,Ross,我已经提供了我的逻辑,认为未结交易会阻止问题更新的增长。我的推理不正确吗?
  • @Jimbo SQL Server 不要求您保留它。如果您有自动增长,SQL Server 会在事务期间执行自动增长。足够大可以节省大量时间,但不应该影响过程。
【解决方案5】:

这是一种老派的方法,但如果您在 SQL 中执行迭代更新或插入操作,这些操作会运行很长时间,那么定期(以编程方式)调用“检查点”是个好主意。调用“检查点”会导致 SQL 将所有这些仅用于内存的更改(称为脏页)和存储在事务日志中的项目写入磁盘。这具有定期清理事务日志的效果,从而防止出现上述问题。

【讨论】:

  • 不幸的是,我无法控制该过程的执行方式。 Dynamics CRM 是 Microsoft 应用程序,组织导入流程是该应用程序的一部分。
【解决方案6】:

以下将截断日志。

USE [yourdbname] 
GO

-- TRUNCATE TRANSACTION LOG --
DBCC SHRINKFILE(yourdbname_log, 1)
BACKUP LOG yourdbname WITH TRUNCATE_ONLY
DBCC SHRINKFILE(yourdbname_log, 1)
GO

-- CHECK DATABASE HEALTH --
ALTER FUNCTION [dbo].[checker]() RETURNS int AS BEGIN  RETURN 0 END
GO

【讨论】:

  • 嘿 Pinal,此功能已从 SQL Server 2008 及更高版本中完全删除:brentozar.com/archive/2009/08/…
  • 使用更高版本,尝试 BACKUP LOG TO DISK=N'NUL:'
【解决方案7】:

如果您的数据库恢复模式已满且您没有日志备份维护计划,您将收到此错误,因为事务日志因LOG_BACKUP 而变满。

这将阻止对此数据库执行任何操作(例如收缩),并且 SQL Server 数据库引擎将引发 9002 错误。

为了克服这种行为,我建议您查看此The transaction log for database ‘SharePoint_Config’ is full due to LOG_BACKUP,其中显示了解决问题的详细步骤。

【讨论】:

    【解决方案8】:

    我遇到错误:“数据库 '...' 的事务日志已满,因为 'ACTIVE_TRANSACTION' 从我的数据库表中删除旧行以释放磁盘空间。我意识到如果数字在我的情况下,要删除的行数大于 1000000。因此,我没有使用 1 个 DELETE 语句,而是使用 DELETE TOP (1000000)....语句来划分删除任务。

    例如:

    而不是使用这个语句:

    DELETE FROM Vt30 WHERE Rt < DATEADD(YEAR, -1, GETDATE())
    

    重复使用以下语句:

    DELETE TOP(1000000) FROM Vt30 WHERE Rt < DATEADD(YEAR, -1, GETDATE())
    

    【讨论】:

      【解决方案9】:

      试试这个:

      USE YourDB;  
      GO  
      -- Truncate the log by changing the database recovery model to SIMPLE.  
      ALTER DATABASE YourDB
      SET RECOVERY SIMPLE;  
      GO  
      -- Shrink the truncated log file to 50 MB.  
      DBCC SHRINKFILE (YourDB_log, 50);  
      GO  
      -- Reset the database recovery model.  
      ALTER DATABASE YourDB
      SET RECOVERY FULL;  
      GO 
      

      希望对你有帮助。

      【讨论】:

      • 这是最早尝试的事情之一,甚至在问题文本中也提到过。这并不能解决单个打开事务填满日志并使用所有可用磁盘空间的问题。整个过程以简单模式进行。但是,您是提供此确切答案但没有阅读问题的众多人之一......
      【解决方案10】:

      除了上面的答案,我还想提一下,如果可能的话,你也可以释放服务器来解决这个问题。如果由于数据库溢出而导致服务器已满,您可以从构建您的数据库的服务器中删除一些不必要的文件。至少这可以暂时解决问题并让您查询数据库

      【讨论】:

      • 是的。在我的情况下,服务器没有足够的资源,所以我们不得不插入一个外部驱动器,这成功了。大多数情况下,这是一个难以调查的问题,因为我们惊讶地发现日志需要这么多空间,有问题的进程是黑盒的,整个事情在我们有机会检查之前就回滚了。
      【解决方案11】:

      多次执行有限删除解决了我的问题

      之前

      DELETE FROM TableName WHERE Condition
      

      之后

      DELETE TOP(1000) FROM TableName WHERECondition
      

      【讨论】:

        【解决方案12】:

        问题的答案不是从表中删除行,而是由于活动事务而占用的 tempDB 空间。这主要发生在我们尝试插入更新和删除事务的合并(upsert)运行时。唯一的选择是确保将数据库设置为简单恢复模式,并将文件增加到最大空间(添加其他文件组)。尽管这有其自身的优点和缺点,但这些是唯一的选择。

        您拥有的另一个选项是将合并(更新插入)拆分为两个操作。一个执行插入,另一个执行更新和删除。

        【讨论】:

        • 如果您阅读了这个问题,您就会知道数据库在发生这种情况时已经处于简单恢复模式。当您有一个长时间运行的未处理事务时,这无济于事。该文件继续增长,直到事务被提交或回滚。阅读问题的第一行“我有一个长时间运行的进程,它在整个持续时间内保持打开事务。”
        【解决方案13】:

        这是我的英雄代码。我遇到过这个问题。并使用此代码来解决此问题。

         USE master;
        
            SELECT 
                name, log_reuse_wait, log_reuse_wait_desc, is_cdc_enabled 
            FROM 
                sys.databases 
            WHERE 
                name = 'XX_System';
        
            SELECT DATABASEPROPERTYEX('XX_System', 'IsPublished');
        
        
            USE XX_System;
            EXEC sp_repldone null, null, 0,0,1;
            EXEC sp_removedbreplication XX_System;
        
        
            DBCC OPENTRAN;
            DBCC SQLPERF(LOGSPACE);
            EXEC sp_replcounters;
        
        
        
            DBCC SQLPERF(LOGSPACE);
        

        【讨论】:

        • 请始终将您的答案放在上下文中,而不仅仅是粘贴代码。有关详细信息,请参阅here。
        【解决方案14】:

        试试这个:

        如果可能,重新启动服务 MSSQLSERVER 和 SQLSERVERAGENT。

        【讨论】:

          猜你喜欢
          • 2017-11-20
          • 1970-01-01
          • 2013-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          相关资源
          最近更新 更多