当我们在 SQL Server 2008 R2 实例上运行它时,每次都会导致严重性 20 错误。它在我们的 SQL Server 2016 实例上没有这个问题。
询问:
DECLARE @v varchar(MAX) = REPLICATE(CONVERT(varchar(max),'a'),524289);
SELECT @v = @v FROM(SELECT 1 AS a) AS b;
结果:
Location: tmpilb.cpp:3256
Expression: fNoReaderWriterConflict
SPID: 90
Process ID: 1576
Location: tmpilb.cpp:3306
Expression: fNoReaderWriterConflict
SPID: 90
Process ID: 1576
Msg 3624, Level 20, State 1, Line 4
A system assertion check has failed. Check the SQL Server error log for details. Typically, an assertion failure is caused by a software bug or data corruption. To check for database corruption, consider running DBCC CHECKDB. If you agreed to send dumps to Microsoft during setup, a mini dump will be sent to Microsoft. An update might be available from Microsoft in the latest Service Pack or in a QFE from Technical Support.
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
SELECT @@VERSION
:
Microsoft SQL Server 2008 R2 (SP3) - 10.50.6000.34 (X64)
Aug 19 2014 12:21:34
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
SQLDump0002.txt(来自非生产服务器):
Computer type is Intel(R) Xeon(R) CPU E5430 @ 2.66GHz.
Bios Version is DELL - 1
Phoenix ROM BIOS PLUS Version 1.10 2.5.0
8 X64 level 8664, 2 Mhz processor (s).
Windows NT 6.1 Build 7601 CSD Service Pack 1.
Memory
MemoryLoad = 87%
Total Physical = 32762 MB
Available Physical = 4058 MB
Total Page File = 65524 MB
Available Page File = 27332 MB
Total Virtual = 8388607 MB
Available Virtual = 8355194 MB
**Dump thread - spid = 0, EC = 0x00000003EF7E5F00
这是此版本 SQL Server 2008 R2 中的错误吗?
更新:
- 这确实会产生一组与故障转储相关的文件。它们的外行可读部分基本上重复了上面的错误结果。
- 我们认识到 SQL Server 2008 R2 已经过时并且不再受支持。我们将进行升级。
- 我们已经通过在 SELECT 语句之外设置大文本变量来解决这个问题。
- 我们很好奇这是否发生在任何其他环境中,我们希望将其公开记录以防发生在其他人身上。
涉及的数据库是 tempdb(数据库 ID 2)。这就是 LOB 变量的值被写入的地方。您可以通过查看
sys.dm_db_task_space_usage
DMV 来看到这一点(如果您的查询没有因错误而失败,即):该查询的数据数据库上下文是“master”,但请注意查询中的 database_id 会导致 tempdb。
因此,您可以检查 tempdb 是否损坏。每次重新启动服务器时都会重新创建该数据库,因此如果您在那里持续损坏,我会感到惊讶。除非您遇到磁盘问题,在这种情况下,您应该始终在 Windows“系统”事件日志中看到指示损坏的错误。
尽管如此,这也很可能是 SQL Server 2008 R2 SP3 中的一个错误。该 SP 至少有一个与安全无关的修补程序 ( KB3033860 )。那里提到的错误看起来与您的情况不匹配,但可能是相关的(它们是断言失败)。
不幸的是,由于 SQL Server 2008 R2 不支持,即使它是一个错误也不会修复。最好的办法是尝试解决问题或升级。
这在 Microsoft SQL Server 2008 R2 (SP2) build 10.50.4000 上为我重现。它似乎在 SP3 之后的一段时间内得到了修复。该问题已在 Connect 上报告(随后迁移到用户语音,以便该链接有效)。
LOB 中需要超过 512KB 的数据,以及从同一个变量中读取的变量赋值,而无需执行任何计算。
例如:
该语句几乎没有错误地执行。SQL Server 正确执行所有计算,甚至毫无问题地将@v 分配给@v。断言发生在 SQL Server 关闭语句时,将@v 的最终值写回到提供的变量引用@v。就像@v 是赋值语句的参数一样。如果这听起来很复杂,那是因为它是。变量赋值有点小技巧,有一些奇怪的遗留行为。我不羡慕那些必须维护该代码的所有怪癖。
CInMemIlb
由于 SQL Server 使用内存中的 ILockBytes (ILB) 类来处理操作,因此断言不会发生在 512KB 或以下的值上。您可能已经注意到断言消息 (tmpilb.cpp) 中的 ILB。超过 512KB,SQL ServerCMainIlb
改为使用,它在写入时使用 blob 句柄检查其他读取器。将@v 分配给自身而不进行修改意味着此检查失败。在许多可能的解决方法中,自然不属于上述观察的两个是:
示例如下所示。两者都不会产生错误的断言:
有趣的是,最近在 SQL Server 2019 对查询存储和 polybase 的修复中再次出现了相同的断言。