我知道还有其他问题的标题与我发布的问题完全相同,但每个问题都非常特定于它们所引用的查询或过程。
我在这里为一所大学管理 Blackboard Learn 系统,并且可以直接访问数据库。简而言之,有一个存储过程导致系统头痛。有时,当对系统的更改提交时,错误会被扔到后端的日志中,识别名为 bbgs_cc_setStmtStatus 的存储过程并错误提示 当前事务无法提交,并且无法支持以下操作写入日志文件。回滚事务。
这里是 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 开始,每次需要时都会自动增长 1GB。 tempdb中的可用空间为tempdb实际大小的95-985是否正常?例如,现在 tempdb 的大小为 12388.00 MB,可用空间为 12286.37MB。
此外,主 BBLEARN
表的日志文件已停止增长,因为它达到了最大自动增长。我将其初始大小设置为 3GB 以增加其大小。
最佳答案
我看到一些可能阻止提交的潜在错误,但在不了解有关结构的更多信息的情况下,这些只是猜测:
嵌套 if 中的 update 子句尝试更新必须唯一的列(或列集)。因为该检查仅验证至少一项存在,但并不将该检查限制为确保仅一项存在
IF (0 < (SELECT ...) ) BEGIN
对比
IF (1 = (SELECT ...) ) BEGIN
您可能会将非唯一值插入到必须唯一的行中。检查以确保运行更新的属性没有任何约束(特别是查找主键、标识和唯一约束)。这成为问题的可能性:低但非零。
应用程序未将值传递给所有参数,导致 @message 字符串为空,从而导致日志记录方法在尝试添加空字符串时出错。请记住,在 SQL 中,anything + null = null 因此,虽然您可以插入值并将值更新为 null,但您无法按照您提供的代码的方式记录 null。相反,为了解决空值,您应该将消息变量的 setter 更改为以下内容:
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 进行比较。
从这些建议开始,如果您能返回更多信息,我可以帮助您解决更多问题。
关于sql - 当前事务无法提交,并且无法支持写入日志文件的操作。回滚事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19053595/