我通常会避免像斑块这样的游标操作,但是,我遇到了第一个问题,即使用游标优于查询。所以我被迫使用它。
我创建了一个精心设计的报告存储过程,供许多用户使用。我使用游标迭代列表并将数据插入@TEMP_TABLE,最后选择临时表作为结果集。
游标的使用如下:
DECLARE HIGHLIGHTS_REPORT_CURSOR CURSOR LOCAL FOR
SELECT RowID, UserID,GradeID,ClassID,MenuSetID,CurrentSequence FROM @DATA
OPEN HIGHLIGHTS_REPORT_CURSOR
FETCH NEXT FROM HIGHLIGHTS_REPORT_CURSOR INTO @RowID,@UserID,@GradeID,@ClassID,@MenuSetID,@CurrentSequence
WHILE(@@FETCH_STATUS=0)BEGIN
...
FETCH NEXT FROM HIGHLIGHTS_REPORT_CURSOR INTO @RowID, @UserID,@GradeID,@ClassID,@MenuSetID,@CurrentSequence
END
CLOSE HIGHLIGHTS_REPORT_CURSOR
DEALLOCATE HIGHLIGHTS_REPORT_CURSOR
所以一切都很好,报告通过了 QA,没有问题,直到基于用户的增加现在我收到偶尔发送给我的异常日志,并出现以下错误:
Server Log Reference ID : b91a8f4a-b944-4355-bba3-2855fd126c2b
Message : A cursor with the name 'HIGHLIGHTS_REPORT_CURSOR' does not exist.
Source : HighlightsReport
Stack Trace : at System.Data.SqlClient.SqlConnection.OnError(SqlExceptionexception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
我可以 100% 肯定地说没有另一个同名游标。和之间没有错误的CLOSE\DEALLOCATE CURSOR
调用。BEGIN
END
我了解到 SQL ServerGLOBAL
在安装期间将“默认游标”数据库属性默认为。由于报告程序是唯一使用游标的 SP,我已将“默认游标”更改为LOCAL
.
那没有帮助:(也许“默认光标”是一个需要重新启动的设置。我没有重新启动,而是使用了声明的LOCAL
属性。CURSOR
这确保了我的光标在 SP 范围内,但仍然出现上述错误???
我开始认为这是多个连接同时访问 SP 的并发问题。这可以解释零星的行为以及为什么在 QA 期间没有发现这一点。
是否有可能两个连接几乎同时调用该过程,其中一个连接DEALLOCATE HIGHLIGHTS_REPORT_CURSOR
恰好在第二个连接命中FETCH NEXT FROM HIGHLIGHTS_REPORT_CURSOR INTO
块之前命中?
我假设使用 LOCAL 确保每个连接都有其副本,但事实并非如此?有任何想法吗?
更新。这很奇怪,我将三个异常消息堆叠为一个。我想知道快速连续调用同一个 sp 的客户端连接是否会导致类似的情况。
Server Log Reference ID : b91a8f4a-b944-4355-bba3-2855fd126c2b
Message : A cursor with the name 'HIGHLIGHTS_REPORT_CURSOR' does not exist.
A cursor with the name 'HIGHLIGHTS_REPORT_CURSOR' does not exist.
A cursor with the name 'HIGHLIGHTS_REPORT_CURSOR' does not exist.
Source : HighlightsReport
更新 2让我认为这是用户并发问题的部分是这些错误总是以两个为一组的事实。我同时收到来自两个不同用户的异常报告,其中包含上述错误。
所以这很奇怪,我还没有深入了解具体细节。简而言之,我不久前在 sql server 连接上启用了 MARS,以解决我在 IoC 容器连接方面遇到的问题。
这修复了类似于“您必须关闭当前命令 yaddayaddayadda”的异常。但是,在我的案例中,多个活动结果集似乎会导致并发问题。我实际上修复了应该修复的原始问题,而不是启用 MARS。解决方法是在每次调用时隐式创建一个新的数据上下文。