Sql-Server-2008-R2

SQL Server 2008 R2 是否總是因某些大文本操作而出現嚴重級別 20 錯誤?

  • April 24, 2021

當我們在 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 語句之外設置大文本變數來解決這個問題。
  • 我們很好奇這是否發生在任何其他環境中,我們希望將其公開記錄以防發生在其他人身上。

這在 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);

該語句幾乎沒有錯誤地執行。SQL Server 正確執行所有計算,甚至毫無問題地將@v 分配給@v。斷言發生在 SQL Server 關閉語句時,將@v 的最終值寫回到提供的變數引用@v。就像@v 是賦值語句的參數一樣。如果這聽起來很複雜,那是因為它是。變數賦值有點小技巧,有一些奇怪的遺留行為。我不羨慕那些必須維護該程式碼的所有怪癖。

CInMemIlb由於 SQL Server 使用記憶體中的 ILockBytes (ILB) 類來處理操作,因此斷言不會發生在 512KB 或以下的值上。您可能已經註意到斷言消息 (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 + '');

有趣的是,最近在 SQL Server 2019 對查詢儲存和 polybase 的修復中再次出現了相同的斷言。

引用自:https://dba.stackexchange.com/questions/290316