In che modo una partizione danneggiata in TempDB potrebbe non causare problemi a DBCC CHECKDB?


9

Uno dei nostri server SQL ha segnalato di recente il seguente errore:

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.

Meno di 15 minuti dopo mi sono connesso al server ed ho eseguito:

SELECT name
FROM sys.databases
WHERE database_id = 2;

Che ha restituito "tempdb". Ho quindi eseguito:

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

Che non ha restituito risultati, indicando problemi con il database interessato.

In che modo la corruzione nel database potrebbe causare il messaggio di errore sopra riportato ma DBCC CHECKDBnon segnalare il problema? Presumo che un calcolo del checksum della pagina fallisca, facendo sì che la pagina venga contrassegnata come sospetta che qualsiasi oggetto che fa riferimento a quella pagina non possa essere eliminato, ma devo sbagliarmi.

Una volta che una pagina è contrassegnata come "sospetta", come può essere contrassegnata come non sospetta, o riparata, o riutilizzata, o qualsiasi altra cosa che DBCC CHECKDBnon segnala alcun problema con la pagina in questione?


Modifica: 27/02/2013 13:24

Solo per divertimento, ho provato a ricreare la corruzione in TempDB ipotizzando che il colpevole fosse una tabella #temp.

Tuttavia, poiché non posso impostare l' SINGLE_USERopzione in TempDB, non posso usare DBCC WRITEPAGEper corrompere una pagina e quindi non posso forzare la corruzione in TempDB.

Invece di DBCC WRITEPAGEusarne uno, è possibile impostare il database offline e utilizzare un editor esadecimale per modificare byte casuali nel file db. Naturalmente, ciò non funziona neanche su TempDB poiché il motore di database non può essere eseguito con TempDB offline.

Se si interrompe l'istanza, TempDB viene ricreato automaticamente al successivo avvio; quindi anche questo non farà il trucco.

Se qualcuno potesse pensare a un modo per ricreare questa corruzione, sarei disposto a fare ulteriori ricerche.

Per verificare l'ipotesi che una pagina danneggiata non possa essere riparata da DROP TABLEme, ho creato un database di prova e ho usato il seguente script per corrompere una pagina, quindi ho cercato di eliminare la tabella interessata. Il risultato qui era che la tabella non poteva essere cancellata; Ho dovuto per RESTORE DATABASE Testdb PAGE = ''...recuperare la pagina interessata. Suppongo che se avessi apportato una modifica a qualche altra parte della pagina in questione, forse la pagina avrebbe potuto essere corretta DROP TABLEo forse 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.

A questo punto ti disconnetti dal motore di database, quindi riconnettiti per continuare.

USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;

La corruzione è riportata qui.

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.

La corruzione è riportata qui, DROP TABLEnon riesce.

/* 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';

Modifica # 2, per aggiungere le informazioni sulla VERSIONE @@ richieste.

SELECT @@VERSION;

Ritorna:

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: )

So che questa è la versione di valutazione, abbiamo le chiavi per la versione Enterprise e presto eseguiremo un aggiornamento della versione.


2
FYI -T 3609manterrà tempdb all'inizio (non documentato ma già noto )
Remus Rusanu,

Risposte:


3

Questo è un problema noto con una correzione:

FIX: errore "Nessuna voce di catalogo trovata per ID partizione nel database" quando si utilizza SQL Server 2012

Si supponga di eseguire una query nella tabella tempdb.sys.allocation_units in Microsoft SQL Server 2012. Quando si utilizza l'hint NOLOCK nella query o la query si trova nel livello di isolamento della transazione READ UNCOMMITED, viene visualizzato il seguente messaggio di errore 608 intermittente:

Errore: 608 Gravità: 16 Stato: 1
Nessuna voce di catalogo trovata per la partizione nel database. I metadati sono incoerenti. Eseguire DBCC CHECKDB per verificare la corruzione dei metadati

Nota Il comando DBCC CHECKDB non mostra alcun segno di danneggiamento del database.

Risolto in:

La tua versione (11.0.3000.0) è SQL Server 2012 SP1 RTM


7

L'esecuzione CHECKDBcontro tempdbnon è la stessa dell'esecuzione su un database utente.

Da MSDN :

L'esecuzione di DBCC CHECKDB su tempdb non esegue alcun controllo di allocazione o catalogo e deve acquisire blocchi di tabella condivisi per eseguire controlli di tabella. Questo perché, per motivi di prestazioni, gli snapshot del database non sono disponibili su tempdb. Ciò significa che non è possibile ottenere la coerenza transazionale richiesta.


6

Sì, ma in particolare, un errore di catalogo non può essere verificato in TempDB. Se possibile, è necessario riciclare SQL Server per risolvere il problema. Per MSDN:

"L'esecuzione di DBCC CHECKCATALOG su tempdb non esegue alcun controllo. Questo perché, per motivi di prestazioni, gli snapshot del database non sono disponibili su tempdb. Ciò significa che non è possibile ottenere la coerenza transazionale richiesta. Riciclare il server per risolvere eventuali problemi relativi ai metadati tempdb."

L'articolo di MSDB è qui: http://msdn.microsoft.com/en-us/library/ms186720.aspx

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.