web-dev-qa-db-ja.com

TempDBのパーティションが破損していると、DBCC CHECKDBで問題が報告されないのはなぜですか。

SQL Serverの1つが最近次のエラーを報告しました:

_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.
_

15分以内にサーバーに接続して実行しました。

_SELECT name
FROM sys.databases
WHERE database_id = 2;
_

これは「tempdb」を返しました。次に実行しました:

_DBCC CHECKDB ('tempdb') WITH NO_INFOMSGS, TABLERESULTS;
_

結果は返されず、影響を受けるデータベースに問題がないことを示しています。

どのようにデータベースが破損すると、上記のエラーメッセージが表示されますが、_DBCC CHECKDB_は問題を報告しませんか?ページのチェックサム計算が失敗し、そのページを参照しているオブジェクトを削除できないと疑われるページがマークされた場合、私は推測しますが、私は間違っているはずです。

ページが「疑わしい」とマークされたら、どのようにして疑わしくない、修正、または再利用するか、または_DBCC CHECKDB_が問題のページに関する問題を報告しないようなものにマークできますか?


編集:2013-02-27 13:24

おもしろいことに、私は#tempテーブルが原因であると想定して、TempDBで破損を再現しようとしました。

ただし、TempDBで_SINGLE_USER_オプションを設定できないため、_DBCC WRITEPAGE_を使用してページを破損できず、TempDBで破損を強制できません。

_DBCC WRITEPAGE_を使用する代わりに、データベースをオフラインに設定し、16進エディターを使用してdbファイル内のランダムなバイトを変更できます。もちろん、データベースエンジンはTempDBをオフラインで実行できないため、TempDBでも機能しません。

インスタンスを停止すると、次回の起動時にTempDBが自動的に再作成されます。したがって、それもトリックを行いません。

誰かがこの腐敗を再現する方法を考えることができるなら、私はさらなる研究をしたいと思っています。

破損したページを_DROP TABLE_で修正できないという仮説をテストするために、テストデータベースを作成し、次のスクリプトを使用してページを破損させ、影響を受けるテーブルを削除しようとしました。その結果、テーブルを削除できませんでした。影響を受けたページを回復するために_RESTORE DATABASE Testdb PAGE = ''..._を実行する必要がありました。問題のページの他の部分に変更を加えたとしたら、ページは_DROP TABLE_または_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.
_

この時点でデータベースエンジンから切断されます。続行するには再接続してください。

_USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;
_

破損はここで報告されます。

_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.
_

破損はここで報告され、_DROP TABLE_は失敗します。

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

#2を編集して、要求された@@ VERSION情報を追加します。

_SELECT @@VERSION;
_

戻り値:

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

これは評価版であることを知っています。EnterpriseEditionのキーがあり、まもなくエディションのアップグレードが行われます。

9
Max Vernon

これは修正された既知の問題です。

FIX:SQL Server 2012を使用すると、「データベースのパーティションIDのカタログエントリが見つかりません」エラー

Microsoft SQL Server 2012でtempdb.sys.allocation_unitsテーブルをクエリするとします。クエリでNOLOCKヒントを使用するか、クエリがREAD UNCOMMITEDトランザクション分離レベルの下にある場合、次の断続的な608エラーメッセージが表示されます。

エラー:608重要度:16状態:1
データベースのパーティションにカタログエントリが見つかりませんでした。メタデータに一貫性がありません。 DBCC CHECKDBを実行してメタデータの破損をチェックします

注意:DBCC CHECKDBコマンドは、データベースの破損の兆候を示しません。

修正済み:

あなたのバージョン(11.0.3000.0)はSQL Server 2012 SP1 RTMです

3
Mitch Wheat

CHECKDBtempdbに対して実行することは、ユーザーデータベースに対して実行することと同じではありません。

から [〜#〜] msdn [〜#〜]

Tempdbに対してDBCC CHECKDBを実行しても、割り当てやカタログのチェックは実行されず、テーブルチェックを実行するには共有テーブルロックを取得する必要があります。これは、パフォーマンス上の理由から、データベーススナップショットがtempdbで使用できないためです。これは、必要なトランザクションの一貫性が得られないことを意味します。

7
Jon Seigel

はい。ただし、具体的には、TempDBではカタログエラーを確認できません。これを修正するには、可能であればSQL Serverをリサイクルする必要があります。 MSDNごと:

「tempdbに対してDBCC CHECKCATALOGを実行しても、チェックは行われません。これは、パフォーマンス上の理由から、データベーススナップショットがtempdbで利用できないためです。これは、必要なトランザクションの一貫性を取得できないことを意味します。サーバーをリサイクルして、tempdbメタデータの問題を解決してください。」

MSDBの記事はこちら: http://msdn.Microsoft.com/en-us/library/ms186720.aspx

6
Cate Donoghue