Como uma partição corrompida no TempDB pode resultar no DBCC CHECKDB sem relatar nenhum problema?

9

Um de nossos servidores SQL relatou o seguinte erro recentemente:

DATE/TIME:  2/25/2013 9:15:14 PM

DESCRIPTION:    No catalog entry found for partition ID 9079262474267394048
     in database 2. The metadata is inconsistent. Run DBCC CHECKDB to check for
     a metadata corruption.

Menos de 15 minutos depois, conectei-me ao servidor e executei:

SELECT name
FROM sys.databases
WHERE database_id = 2;

O que retornou 'tempdb'. Eu então corri:

DBCC CHECKDB ('tempdb') WITH NO_INFOMSGS, TABLERESULTS;

O que não retornou resultados, indicando que não há problemas com o banco de dados afetado.

Como a corrupção no banco de dados resultou na mensagem de erro acima e ainda DBCC CHECKDBnão relatou o problema? Presumo que um cálculo de soma de verificação de página falhe, resultando na página sendo marcada como suspeita de que qualquer objeto que faça referência a essa página não possa ser descartado, mas devo estar errado.

Depois que uma página é marcada como 'suspeita', como pode ser marcada como não suspeita, ou corrigida ou reutilizada, ou qualquer outra coisa que DBCC CHECKDBnão relate nenhum problema com a página em questão?


Edit: 2013-02-27 13:24

Apenas por diversão, tentei recriar a corrupção no TempDB, assumindo que uma tabela #temp era a culpada.

No entanto, como não consigo definir a SINGLE_USERopção no TempDB, não posso usar DBCC WRITEPAGEpara corromper uma página e, portanto, não posso forçar a corrupção no TempDB.

Em vez de usar, DBCC WRITEPAGEpode-se definir o banco de dados offline e usar um editor hexadecimal para modificar bytes aleatórios no arquivo db. Obviamente, isso também não funciona no TempDB, pois o mecanismo do banco de dados não pode ser executado com o TempDB offline.

Se você parar a instância, o TempDB será recriado automaticamente na próxima inicialização; portanto, isso também não funcionará.

Se alguém puder pensar em uma maneira de recriar essa corrupção, eu estaria disposto a fazer pesquisas adicionais.

Para testar a hipótese de que uma página corrompida não pode ser corrigida, DROP TABLEcriei um banco de dados de teste e usei o script a seguir para corromper uma página e, em seguida, tente descartar a tabela afetada. O resultado aqui foi que a tabela não pôde ser excluída; Eu precisei para RESTORE DATABASE Testdb PAGE = ''...recuperar a página afetada. Presumo que, se eu tivesse feito uma alteração em alguma outra parte da página em questão, talvez a página pudesse ter sido corrigida DROP TABLEou talvez TRUNCATE table.

/* ********************************************* */
/* ********************************************* */
/* DO NOT USE THIS CODE ON A PRODUCTION SYSTEM!! */
/* ********************************************* */
/* ********************************************* */
USE Master;
GO
ALTER DATABASE test SET RECOVERY FULL;
BACKUP DATABASE Test 
    TO DISK = 'Test_db.bak'
    WITH FORMAT
        , INIT
        , NAME = 'Test Database backup'
        , SKIP
        , NOREWIND
        , NOUNLOAD
        , COMPRESSION
        , STATS = 1;
BACKUP LOG Test
    TO DISK = 'Test_log.bak'
    WITH FORMAT
        , INIT
        , NAME = 'Test Log backup'
        , SKIP
        , NOREWIND
        , NOUNLOAD
        , COMPRESSION
        , STATS = 1;
GO
ALTER DATABASE test SET SINGLE_USER;
GO
USE Test;
GO
IF EXISTS (SELECT name FROM sys.key_constraints WHERE name = 'PK_temp') 
    ALTER TABLE temp DROP CONSTRAINT PK_temp;
IF EXISTS (SELECT name FROM sys.default_constraints 
    WHERE name = 'DF_temp_testdata') 
    ALTER TABLE temp DROP CONSTRAINT DF_temp_testdata;
IF EXISTS (SELECT name FROM sys.tables WHERE name = 'temp') 
DROP TABLE temp;
GO
CREATE TABLE temp
(
    tempID INT NOT NULL CONSTRAINT PK_temp PRIMARY KEY CLUSTERED IDENTITY(1,1)
    , testdata uniqueidentifier CONSTRAINT DF_temp_testdata DEFAULT (NEWID())
);
GO

/* insert 10 rows into #temp */
INSERT INTO temp default values;
GO 10 

/* get some necessary parameters */
DECLARE @partitionID bigint;
DECLARE @dbid smallint;
DECLARE @tblid int;
DECLARE @indexid int;
DECLARE @pageid bigint;
DECLARE @offset INT;
DECLARE @fileid INT;

SELECT @dbid = db_id('Test')
    , @tblid = t.object_id
    , @partitionID = p.partition_id
    , @indexid = i.index_id
FROM sys.tables t
    INNER JOIN sys.partitions p ON t.object_id = p.object_id
    INNER JOIN sys.indexes i on t.object_id = i.object_id
WHERE t.name = 'temp';

SELECT TOP(1) @fileid = file_id 
FROM sys.database_files;

SELECT TOP(1) @pageid = allocated_page_page_id 
FROM sys.dm_db_database_page_allocations(@dbid, @tblid, null, @partitionID, 'LIMITED')
WHERE allocation_unit_type = 1;

/* get a random offset into the 8KB page */
SET @offset = FLOOR(rand() * 8192);
SELECT @offset;

/* 0x75 below is the letter 't' */
DBCC WRITEPAGE (@dbid, @fileid, @pageid, @offset, 1, 0x74, 1);


SELECT * FROM temp;

Msg 824, Level 24, State 2, Line 36
SQL Server detected a logical consistency-based I/O error: incorrect checksum
 (expected: 0x298b2ce9; actual: 0x2ecb2ce9). It occurred during a read of page 
 (1:1054) in database ID 7 at offset 0x0000000083c000 in file 'C:\SQLServer
 \MSSQL11.MSSQLSERVER\MSSQL\DATA\Test.mdf'.  Additional messages in the SQL 
 Server error log or system event log may provide more detail. This is a
 severe error condition that threatens database integrity and must be
 corrected immediately. Complete a full database consistency check
 (DBCC CHECKDB). This error can be caused by many factors; for more
 information, see SQL Server Books Online.

Nesse ponto, você é desconectado do mecanismo de banco de dados, reconecte-se para continuar.

USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;

A corrupção é relatada aqui.

DROP TABLE temp;

Msg 824, Level 24, State 2, Line 36
SQL Server detected a logical consistency-based I/O error: incorrect checksum
 (expected: 0x298b2ce9; actual: 0x2ecb2ce9). It occurred during a read of page 
 (1:1054) in database ID 7 at offset 0x0000000083c000 in file 'C:\SQLServer
 \MSSQL11.MSSQLSERVER\MSSQL\DATA\Test.mdf'.  Additional messages in the SQL 
 Server error log or system event log may provide more detail. This is a
 severe error condition that threatens database integrity and must be
 corrected immediately. Complete a full database consistency check
 (DBCC CHECKDB). This error can be caused by many factors; for more
 information, see SQL Server Books Online.

A corrupção é relatada aqui, DROP TABLEfalha.

/* assuming ENTERPRISE or DEVELOPER edition of SQL Server,
    I can use PAGE='' to restore a single page from backup */
USE Master;
RESTORE DATABASE Test PAGE = '1:1054' FROM DISK = 'Test_db.bak'; 
BACKUP LOG Test TO DISK = 'Test_log_1.bak';

RESTORE LOG Test FROM DISK = 'Test_log.bak';
RESTORE LOG Test FROM DISK = 'Test_log_1.bak';

Edite # 2, para adicionar as informações solicitadas pela @@ VERSION.

SELECT @@VERSION;

Devoluções:

Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64) 
    Oct 19 2012 13:38:57 
    Copyright (c) Microsoft Corporation
    Enterprise Evaluation Edition (64-bit) on Windows NT 6.2 <X64> 
        (Build 9200: )

Sei que esta é a Edição de Avaliação, temos chaves para a Edição Empresarial e faremos uma Atualização da Edição em breve.

Max Vernon
fonte
2
FYI -T 3609irá preservar tempdb no início (em situação irregular, mas já conhecida )
Remus Rusanu

Respostas:

3

Este é um problema conhecido com uma correção:

CORRECÇÃO: Erro "Nenhuma entrada de catálogo encontrada para a ID da partição no banco de dados" quando você usa o SQL Server 2012

Suponha que você consulte a tabela tempdb.sys.allocation_units no Microsoft SQL Server 2012. Quando você usa a dica NOLOCK na consulta ou a consulta está no nível de isolamento de transação READ UNCOMMITED, você recebe a seguinte mensagem de erro 608 intermitente:

Erro: 608 Gravidade: 16 Estado: 1
Nenhuma entrada de catálogo encontrada para partição no banco de dados. Os metadados são inconsistentes. Execute DBCC CHECKDB para verificar se há uma corrupção de metadados

Nota O comando DBCC CHECKDB não mostra nenhum sinal de corrupção do banco de dados.

Corrigido em:

Sua versão (11.0.3000.0) é o SQL Server 2012 SP1 RTM

Mitch Wheat
fonte
7

Executar CHECKDBcontra tempdbnão é o mesmo que executá-lo em um banco de dados do usuário.

Do MSDN :

A execução do DBCC CHECKDB no tempdb não executa nenhuma verificação de alocação ou catálogo e deve adquirir bloqueios de tabela compartilhados para executar verificações de tabela. Isso ocorre porque, por motivos de desempenho, os instantâneos do banco de dados não estão disponíveis no tempdb. Isso significa que a consistência transacional necessária não pode ser obtida.

Jon Seigel
fonte
6

Sim, mas especificamente, um erro de catálogo não pode ser verificado no TempDB. Você deve reciclar o SQL Server, se possível, para corrigir isso. Por MSDN:

"A execução do DBCC CHECKCATALOG no tempdb não executa nenhuma verificação. Isso ocorre porque, por motivos de desempenho, as capturas instantâneas do banco de dados não estão disponíveis no tempdb. Isso significa que a consistência transacional necessária não pode ser obtida. Recicle o servidor para resolver quaisquer problemas de metadados do tempdb."

O artigo do MSDB está aqui: http://msdn.microsoft.com/en-us/library/ms186720.aspx

Cate Donoghue
fonte