Wie kann eine beschädigte Partition in TempDB dazu führen, dass DBCC CHECKDB kein Problem meldet?

9

Einer unserer SQL Server hat kürzlich den folgenden Fehler gemeldet:

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.

Weniger als 15 Minuten später stellte ich eine Verbindung zum Server her und lief:

SELECT name
FROM sys.databases
WHERE database_id = 2;

Welches gab 'tempdb' zurück. Ich rannte dann:

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

Was keine Ergebnisse ergab, was darauf hinweist, dass keine Probleme mit der betroffenen Datenbank vorliegen.

Wie kann eine Beschädigung der Datenbank zu der obigen Fehlermeldung führen, DBCC CHECKDBohne das Problem zu melden? Ich gehe davon aus, dass wenn eine Seitenprüfsummenberechnung fehlschlägt, die Seite als verdächtig markiert wird, dass ein Objekt, das auf diese Seite verweist, nicht gelöscht werden kann, aber ich muss mich irren.

Wenn eine Seite als "verdächtig" markiert ist, wie kann sie als nicht verdächtig markiert, repariert oder wiederverwendet werden oder was auch immer, DBCC CHECKDBdas kein Problem mit der betreffenden Seite meldet?


Bearbeiten: 2013-02-27 13:24

Nur zum Spaß habe ich versucht, die Beschädigung in TempDB wiederherzustellen, vorausgesetzt, eine # temp-Tabelle war der Schuldige.

Da ich die SINGLE_USEROption in TempDB nicht festlegen kann, kann ich DBCC WRITEPAGEeine Seite nicht beschädigen und daher keine Beschädigung in TempDB erzwingen.

Anstatt zu verwenden DBCC WRITEPAGE, könnte man die Datenbank offline setzen und einen Hex-Editor verwenden, um zufällige Bytes in der Datenbankdatei zu ändern. Dies funktioniert natürlich auch in TempDB nicht, da das Datenbankmodul nicht offline mit TempDB ausgeführt werden kann.

Wenn Sie die Instanz stoppen, wird TempDB beim nächsten Start automatisch neu erstellt. daher reicht das auch nicht aus.

Wenn sich jemand einen Weg ausdenken kann, um diese Korruption wiederherzustellen, wäre ich bereit, weitere Nachforschungen anzustellen.

Um die Hypothese zu testen, dass eine beschädigte Seite nicht behoben werden kann, habe DROP TABLEich eine Testdatenbank erstellt und das folgende Skript verwendet, um eine Seite zu beschädigen , und dann versucht, die betroffene Tabelle zu löschen. Ergebnis hier war, dass die Tabelle nicht gelöscht werden konnte; Ich musste, RESTORE DATABASE Testdb PAGE = ''...um die betroffene Seite wiederherzustellen. Ich gehe davon aus, dass die Seite, wenn ich eine Änderung an einem anderen Teil der fraglichen Seite vorgenommen hätte, möglicherweise mit DROP TABLEoder möglicherweise korrigiert worden wäre 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.

Zu diesem Zeitpunkt werden Sie vom Datenbankmodul getrennt. Stellen Sie daher die Verbindung wieder her, um fortzufahren.

USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;

Korruption wird hier gemeldet.

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.

Korruption wird hier gemeldet, DROP TABLEschlägt fehl.

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

Bearbeiten Sie # 2, um die angeforderten @@ VERSION-Informationen hinzuzufügen.

SELECT @@VERSION;

Kehrt zurück:

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

Ich weiß, dass dies die Evaluation Edition ist. Wir haben Schlüssel für die Enterprise Edition und werden in Kürze ein Edition-Upgrade durchführen.

Max Vernon
quelle
2
Zu -T 3609Ihrer Information, Tempdb wird zu Beginn beibehalten (undokumentiert, aber bereits bekannt )
Remus Rusanu

Antworten:

3

Dies ist ein bekanntes Problem mit einem Fix:

UPDATE: Fehler "Kein Katalogeintrag für Partitions-ID in Datenbank gefunden" bei Verwendung von SQL Server 2012

Angenommen, Sie fragen die Tabelle tempdb.sys.allocation_units in Microsoft SQL Server 2012 ab. Wenn Sie in der Abfrage einen NOLOCK-Hinweis verwenden oder sich die Abfrage unter der Transaktionsisolationsstufe READ UNCOMMITED befindet, wird die folgende zeitweise 608-Fehlermeldung angezeigt:

Fehler: 608 Schweregrad: 16 Status: 1
Für die Partition in der Datenbank wurde kein Katalogeintrag gefunden. Die Metadaten sind inkonsistent. Führen Sie DBCC CHECKDB aus, um nach einer Beschädigung der Metadaten zu suchen

Hinweis Der Befehl DBCC CHECKDB zeigt keine Anzeichen einer Datenbankbeschädigung an.

Behoben in:

Ihre Version (11.0.3000.0) ist SQL Server 2012 SP1 RTM

Mitch Wheat
quelle
7

Das Ausführen CHECKDBgegen tempdbist nicht dasselbe wie das Ausführen gegen eine Benutzerdatenbank.

Von MSDN :

Das Ausführen von DBCC CHECKDB für Tempdb führt keine Zuordnungs- oder Katalogprüfungen durch und muss gemeinsam genutzte Tabellensperren erwerben, um Tabellenprüfungen durchzuführen. Dies liegt daran, dass aus Leistungsgründen Datenbank-Snapshots in tempdb nicht verfügbar sind. Dies bedeutet, dass die erforderliche Transaktionskonsistenz nicht erhalten werden kann.

Jon Seigel
quelle
6

Ja, aber speziell kann ein Katalogfehler in TempDB nicht überprüft werden. Sie sollten SQL Server nach Möglichkeit recyceln, um dies zu beheben. Pro MSDN:

"Das Ausführen von DBCC CHECKCATALOG für Tempdb führt keine Überprüfungen durch. Dies liegt daran, dass aus Leistungsgründen keine Datenbank-Snapshots für Tempdb verfügbar sind. Dies bedeutet, dass die erforderliche Transaktionskonsistenz nicht erreicht werden kann. Recyceln Sie den Server, um Probleme mit Tempdb-Metadaten zu beheben."

Der MSDB-Artikel ist hier: http://msdn.microsoft.com/en-us/library/ms186720.aspx

Cate Donoghue
quelle