Quando executamos isso em nossas instâncias do SQL Server 2008 R2, sempre causa um erro de gravidade 20. Ele não tem esse problema em nossas instâncias do SQL Server 2016.
Consulta:
DECLARE @v varchar(MAX) = REPLICATE(CONVERT(varchar(max),'a'),524289);
SELECT @v = @v FROM(SELECT 1 AS a) AS b;
Resultado:
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 (do servidor de não produção):
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
Isso é um bug nesta versão do SQL Server 2008 R2?
Atualizações:
- Isso produz um conjunto de arquivos relacionados ao despejo de memória. As seções legíveis para leigos basicamente repetem o resultado do erro acima.
- Reconhecemos que o SQL Server 2008 R2 é antigo e não tem suporte. Estaremos atualizando.
- Já resolvemos esse problema definindo a variável de texto grande fora de uma instrução SELECT.
- Estávamos curiosos se isso acontecia em outros ambientes e queríamos que isso fosse documentado publicamente caso acontecesse com outra pessoa.
O banco de dados envolvido é tempdb (ID do banco de dados 2). É aí que o valor das variáveis LOB é escrito. Você pode ver isso olhando no
sys.dm_db_task_space_usage
DMV (se sua consulta não estiver falhando com um erro, ou seja):Meu contexto de banco de dados de dados para essa consulta era "mestre", mas observe que database_id na consulta resulta em tempdb.
Assim, você pode verificar se há corrupção no tempdb. Esse banco de dados é recriado toda vez que o servidor é reiniciado, então eu ficaria surpreso se você tivesse corrupção persistente lá. A menos que você esteja tendo problemas de disco, nesse caso você deverá ver consistentemente erros no log de eventos "Sistema" do Windows que indicam corrupção.
Dito isso, também é muito possível que seja um bug no SQL Server 2008 R2 SP3. Há pelo menos um hotfix não relacionado à segurança para esse SP ( KB3033860 ). Os erros mencionados não parecem corresponder à sua situação, mas podem estar relacionados (são falhas de afirmação).
Infelizmente, como o SQL Server 2008 R2 está sem suporte, isso não será corrigido, mesmo que seja um bug. Sua melhor aposta é tentar contornar o problema ou atualizar.
Isso se reproduz para mim no Microsoft SQL Server 2008 R2 (SP2) build 10.50.4000. Parece ter sido corrigido algum tempo depois do SP3. O problema foi relatado no Connect (e posteriormente migrado para a voz do usuário, para que o link funcione).
Você precisa de mais de 512 KB de dados no LOB e uma atribuição de variável que leia da mesma variável, sem realizar nenhum cálculo.
Por exemplo:
A instrução quase executa sem erro. O SQL Server executa todos os cálculos corretamente e até atribui @v a @v sem problemas. A asserção ocorre quando o SQL Server está fechando a instrução, gravando o valor final de @v de volta na referência de variável fornecida @v. Ele faz isso como se @v fosse um parâmetro para a instrução de atribuição. Se isso soa complexo, é porque é. A atribuição de variável é um pouco hack, com alguns comportamentos legados estranhos. Não invejo aqueles que têm que manter esse código com todas as suas peculiaridades.
A asserção não ocorre com valores de 512 KB ou abaixo porque o SQL Server usa uma classe ILockBytes (ILB) na memória
CInMemIlb
para manipular a operação. Você deve ter notado ILB na mensagem de asserção (tmpilb.cpp). Mais de 512 KB, o SQL Server usaCMainIlb
em vez disso, que verifica outros leitores usando o identificador de blob ao gravar. Atribuir @v a si mesmo sem modificação significa que esta verificação falha.Entre as muitas soluções possíveis, duas que se enquadram naturalmente nas observações acima são:
Exemplos são mostrados abaixo. Nenhum dos dois produz a afirmação errônea:
Curiosamente, a mesma afirmação ressurgiu recentemente em uma correção do SQL Server 2019 para repositório de consultas e polybase.