【问题标题】:Current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction当前事务无法提交,并且无法支持写入日志文件的操作。回滚事务
【发布时间】:2015-08-28 12:31:46
【问题描述】:

我知道还有其他问题的标题与我发布的问题完全相同,但每个问题都非常特定于他们所引用的查询或程序。

我在这里为一所大学管理 Blackboard Learn 系统,并且可以直接访问数据库。简而言之,有一个存储过程会导致系统头痛。有时,当系统更改提交时,错误会被抛出到后端的日志中,识别称为bbgs_cc_setStmtStatus 的存储过程并以The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. 出错

这是 SP 的代码,但是,我没有编写它,因为它是 Blackboard 在填充并为应用程序创建表时安装的库存“设备”。

USE [BBLEARN]
GO
/****** Object:  StoredProcedure [dbo].[bbgs_cc_setStmtStatus]    Script Date: 09/27/2013 09:19:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE              [dbo].[bbgs_cc_setStmtStatus](
   @registryKey   nvarchar(255),
   @registryVal   nvarchar(255),
   @registryDesc  varchar(255),
   @overwrite     BIT
) 
AS
BEGIN
  DECLARE @message varchar(200);

  IF (0 < (SELECT count(*) FROM bbgs_cc_stmt_status WHERE registry_key = @registryKey) ) BEGIN
    IF( @overwrite=1 ) BEGIN
      UPDATE bbgs_cc_stmt_status SET
        registry_value = @registryVal,
        description    = @registryDesc,
        dtmodified     = getDate()
      WHERE registry_key = @registryKey;
    END
  END
  ELSE BEGIN
    INSERT INTO bbgs_cc_stmt_status
        (registry_key, registry_value, description) VALUES
        (@registryKey, @registryVal, @registryDesc);
  END

  SET @message = 'bbgs_cc_setStmtStatus: Saved registry key [' + @registryKey + '] as status [' + @registryVal + '].';
  EXEC dbo.bbgs_cc_log @message, 'INFORMATIONAL';

END

我不期待 Blackboard 特定的支持,但我想知道是否有任何我可以检查的关于 SQL Server 2008 的内容,看看是否有系统设置导致了这种情况。我确实有一张在 Blackboard 上打开的票,但还没有听到任何消息。

以下是我检查过的一些内容:

tempdb 系统数据库:

我使临时日志的初始大小为 100MB,并让它自动增长 100MB,不受限制地查看这是否是导致问题的原因。它似乎没有帮助。我们实际的 tempdb 从 4GB 开始,每次需要它时都会自动增长一个 gig。 tempdb 中可用空间为 tempdb 实际大小的 95-985 是否正常?例如,现在 tempdb 的大小为 12388.00 MB,可用空间为 12286.37MB。

此外,BBLEARN 主表的日志文件已停止增长,因为它已达到最大自动增长。我将其初始大小设置为 3GB 以增加其大小。

【问题讨论】:

  • 这个错误可能是由bbgs_cc_log存储过程产生的。可以显示 bbgs_cc_log 吗?

标签: sql sql-server sql-server-2008


【解决方案1】:

我看到了一些可能会阻止提交但不了解更多结构的潜在错误,这些只是猜测:

  1. 嵌套 if 中的 update 子句试图更新必须唯一的列(或列集)。因为检查只验证至少一项存在,但不限制检查以确保只有一项存在

    IF (0 < (SELECT ...) ) BEGIN
    

    对比

    IF (1 = (SELECT ...) ) BEGIN
    

    您可能会将非唯一值插入必须唯一的行中。检查以确保对运行更新的属性没有约束(特别是查找主键、标识和唯一约束)。出现此问题的可能性:低但非零。

  2. 应用程序未将值传递给所有参数,导致@message 字符串为空,从而导致日志记录方法在尝试添加空字符串时出错。请记住,在 SQL 中,anything + null = null 因此,虽然您可以插入并将值更新为 null,但您不能以您提供的代码的方式记录 null。相反,为了考虑空值,您应该将消息变量的设置器更改为以下内容:

    SET @message = 'bbgs_cc_setStmtStatus: Saved registry key [' + COALESCE(@registryKey, '') + '] as status [' + COALESCE(@registryVal,'') + '].';
    

    根据报告的错误,这更有可能是您的问题,但同样,如果没有应用程序代码(这可能会阻止传递空参数),则无法知道。

另外,我会注意到,而不是做一个

IF (0 < (SELECT count(*) ...) ) BEGIN

我会用

IF (EXISTS (SELECT 1 ...) ) BEGIN

因为它更有效。您不必返回子查询的每一行,因为执行计划将首先运行 FROM 语句并查看行是否存在,而不必实际评估选择,计算这些行,然后将其与 0 进行比较。

从这些建议开始,如果您能回来提供更多信息,我可以帮助您解决更多问题。

【讨论】:

    【解决方案2】:

    也许您可以使用 MERGE 语句: http://msdn.microsoft.com/fr-fr/library/bb510625%28v=sql.100%29.aspx

    我认为这样会更有效率。

    【讨论】:

      【解决方案3】:
      1. 启动 SSMS
      2. 导航到数据库名称
      3. 右键单击数据库名称并选择“属性”>“选项”
      4. 将“延迟的耐久性”更改为允许
      5. 点击确定

      【讨论】:

      • 这是一个糟糕的建议。如果有人想这样做,请联系我......我会尝试“说服你离开壁架”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多