SQL Server 2008 R2 是否总是因某些大文本操作的严重性级别为 20 的错误而失败?

Ril*_*jor 4 sql-server-2008-r2 errors

当我们在 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;
Run Code Online (Sandbox Code Playgroud)

结果:

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.
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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                                                       

 
Run Code Online (Sandbox Code Playgroud)

这是此版本的 SQL Server 2008 R2 中的错误吗?

更新:

  • 这确实会产生一组与故障转储相关的文件。它们的外行可读部分基本上重复了上面的错误结果。
  • 我们认识到 SQL Server 2008 R2 已经过时且不再受支持。我们将进行升级。
  • 我们已经通过在 SELECT 语句之外设置大文本变量来解决这个问题。
  • 我们很好奇这是否发生在任何其他环境中,我们希望公开记录,以防发生在其他人身上。

Jos*_*ell 6

确实没有涉及数据库。你可以看到它没有击中任何桌子。但是,是的,我们已经“在”几个数据库中运行了这个,并针对它们运行了 CHECKDB 只是为了确定。

涉及的数据库是 tempdb(数据库 ID 2)。这就是 LOB 变量的值被写入的地方。您可以通过查看sys.dm_db_task_space_usageDMV看到这一点(如果您的查询没有因错误而失败,那就是):

显示此查询的 208 个 tempdb 分配的 SSMS 结果的屏幕截图

该查询的我的数据数据库上下文是“master”,但请注意查询中的 database_id 导致 tempdb。

所以你可以检查 tempdb 是否损坏。每次重新启动服务器时都会重新创建此数据库,因此如果您在那里持续损坏,我会感到惊讶。除非您遇到磁盘问题,否则您应该始终在 Windows“系统”事件日志中看到指示损坏的错误。


尽管如此,这也很可能是 SQL Server 2008 R2 SP3 中的一个错误。该 SP 至少有一个与安全无关的修补程序 ( KB3033860 )。那里提到的错误看起来与您的情况不符,但可能相关(它们是断言失败)。

不幸的是,由于 SQL Server 2008 R2 不受支持,即使它是一个错误,也不会修复。最好的办法是尝试解决问题或升级。


Pau*_*ite 6

这在 Microsoft SQL Server 2008 R2 (SP2) build 10.50.4000 上为我重现。它似乎在 SP3 之后修复了一段时间。该问题已在 Connect 上报告(随后迁移到用户语音,因此该链接有效)。

您需要 LOB 中超过 512KB 的数据,以及从同一变量读取的变量赋值,而不执行任何计算。

例如:

-- No error at 512KB
DECLARE @v varchar(max) = REPLICATE(CONVERT(varchar(max), 'a'), 512 * 1024);
SET @v = (SELECT @v);

-- Assertion failure at 512KB + 1
DECLARE @v varchar(max) = REPLICATE(CONVERT(varchar(max), 'a'), 512 * 1024 + 1);
SET @v = (SELECT @v);
Run Code Online (Sandbox Code Playgroud)

该语句几乎没有错误地执行。SQL Server 正确执行所有计算,甚至毫无问题地将 @v 分配给 @v。断言发生在 SQL Server 关闭语句时,将 @v 的最终值写回提供的变量引用 @v。它就像@v 是赋值语句的参数一样。如果这听起来很复杂,那是因为它确实如此。变量赋值有点麻烦,有一些奇怪的遗留行为。我不羡慕那些必须维护该代码及其所有怪癖的人。

断言不会发生在 512KB 或以下的值,因为 SQL Server 使用内存中的 ILockBytes (ILB) 类CInMemIlb来处理操作。您可能已经注意到断言消息 (tmpilb.cpp) 中的 ILB。超过 512KB,SQL ServerCMainIlb改为使用,它在写入时使用 blob 句柄检查其他读取器。不加修改地将@v 分配给自身意味着此检查失败。

在许多可能的解决方法中,自然不属于上述观察结果的两个是:

  1. 分配给不同的变量
  2. 进行计算

示例如下所示。两者都不会产生错误的断言:

-- Assign to a different variable
DECLARE @v varchar(max) = REPLICATE(CONVERT(varchar(max), 'a'), 512 * 1024 + 1);
DECLARE @v2 varchar(max);
SET @v2 = (SELECT @v);

-- Perform a calculation
DECLARE @v varchar(max) = REPLICATE(CONVERT(varchar(max), 'a'), 512 * 1024 + 1);
SET @v = (SELECT @v + '');
Run Code Online (Sandbox Code Playgroud)

有趣的是,最近在 SQL Server 2019 的查询存储和 polybase 修复中再次出现了相同的断言。