Comment une partition corrompue dans TempDB peut-elle empêcher DBCC CHECKDB de signaler aucun problème?

9

L'un de nos serveurs SQL a récemment signalé l'erreur suivante:

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.

Moins de 15 minutes plus tard, je me suis connecté au serveur et j'ai exécuté:

SELECT name
FROM sys.databases
WHERE database_id = 2;

Qui a renvoyé 'tempdb'. J'ai ensuite couru:

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

Qui n'a renvoyé aucun résultat, indiquant aucun problème avec la base de données affectée.

Comment la corruption dans la base de données peut-elle entraîner le message d'erreur ci-dessus sans pour DBCC CHECKDBautant signaler le problème? Je suppose que si un calcul de somme de contrôle de page échoue, la page est marquée comme suspecte que tout objet référençant cette page ne pourra pas être supprimé, mais je dois me tromper.

Une fois qu'une page est marquée «suspecte», comment peut-elle être marquée non suspecte, ou corrigée, ou réutilisée, ou quoi que ce soit qui DBCC CHECKDBne signale aucun problème avec la page en question?


Edit: 2013-02-27 13:24

Juste pour le plaisir, j'ai essayé de recréer la corruption dans TempDB en supposant qu'une table #temp était le coupable.

Cependant, comme je ne peux pas définir l' SINGLE_USERoption dans TempDB, je ne peux pas l'utiliser DBCC WRITEPAGEpour corrompre une page, et donc je ne peux pas forcer la corruption dans TempDB.

Au lieu d'en utiliser DBCC WRITEPAGEun, vous pouvez mettre la base de données hors ligne et utiliser un éditeur hexadécimal pour modifier des octets aléatoires dans le fichier db. Bien sûr, cela ne fonctionne pas non plus sur TempDB car le moteur de base de données ne peut pas fonctionner avec TempDB hors ligne.

Si vous arrêtez l'instance, TempDB est automatiquement recréé au prochain démarrage; donc cela ne fera pas l'affaire non plus.

Si quelqu'un peut penser à un moyen de recréer cette corruption, je serais prêt à faire d'autres recherches.

Afin de tester l'hypothèse qu'une page corrompue ne peut pas être corrigée par DROP TABLEj'ai créé une base de données de test et utilisé le script suivant pour corrompre une page, puis essayez de supprimer la table affectée. Le résultat ici est que le tableau n'a pas pu être supprimé; Je devais le faire RESTORE DATABASE Testdb PAGE = ''...pour récupérer la page affectée. Je suppose que si j'avais apporté une modification à une autre partie de la page en question, la page aurait peut-être pu être corrigée DROP TABLEou peut-être 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.

À ce stade, vous êtes déconnecté du moteur de base de données, alors reconnectez-vous pour continuer.

USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;

La corruption est signalée ici.

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 corruption est signalée ici, DROP TABLEéchoue.

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

Modifiez # 2, pour ajouter les informations @@ VERSION demandées.

SELECT @@VERSION;

Retour:

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

Je sais que c'est l'édition d'évaluation, nous avons des clés pour l'édition d'entreprise et nous ferons bientôt une mise à niveau de l'édition.

Max Vernon
la source
2
FYI -T 3609conservera tempdb au démarrage (non documenté mais déjà connu )
Remus Rusanu

Réponses:

3

Il s'agit d'un problème connu avec un correctif:

CORRECTIF: erreur «aucune entrée de catalogue trouvée pour l'ID de partition dans la base de données» lorsque vous utilisez SQL Server 2012

Supposons que vous interrogez la table tempdb.sys.allocation_units dans Microsoft SQL Server 2012. Lorsque vous utilisez l'indicateur NOLOCK dans la requête ou que la requête est sous le niveau d'isolement de transaction READ UNCOMMITED, vous recevez le message d'erreur 608 intermittent suivant:

Erreur: 608 Gravité: 16 État: 1
Aucune entrée de catalogue trouvée pour la partition dans la base de données. Les métadonnées sont incohérentes. Exécutez DBCC CHECKDB pour rechercher une corruption des métadonnées

Remarque La commande DBCC CHECKDB ne montre aucun signe de corruption de base de données.

Fixé dans:

Votre version (11.0.3000.0) est SQL Server 2012 SP1 RTM

Blé Mitch
la source
7

Courir CHECKDBcontre tempdbn'est pas la même que celle en cours d' exécution contre une base de données de l' utilisateur.

Depuis MSDN :

L'exécution de DBCC CHECKDB contre tempdb n'effectue aucune vérification d'allocation ou de catalogue et doit acquérir des verrous de table partagés pour effectuer des vérifications de table. En effet, pour des raisons de performances, les instantanés de base de données ne sont pas disponibles sur tempdb. Cela signifie que la cohérence transactionnelle requise ne peut pas être obtenue.

Jon Seigel
la source
6

Oui, mais en particulier, une erreur de catalogue ne peut pas être vérifiée dans TempDB. Vous devez recycler SQL Server si possible pour résoudre ce problème. Par MSDN:

"L'exécution de DBCC CHECKCATALOG contre tempdb n'effectue aucune vérification. En effet, pour des raisons de performances, les instantanés de base de données ne sont pas disponibles sur tempdb. Cela signifie que la cohérence transactionnelle requise ne peut pas être obtenue. Recyclez le serveur pour résoudre tout problème de métadonnées tempdb."

L'article MSDB est ici: http://msdn.microsoft.com/en-us/library/ms186720.aspx

Cate Donoghue
la source