Как поврежденный раздел в TempDB может привести к тому, что DBCC CHECKDB не сообщит о проблеме?


9

Один из наших SQL-серверов недавно сообщил о следующей ошибке:

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

Просто для забавы я попытался воссоздать коррупцию в TempDB, предполагая, что виноват стол #temp.

Тем не менее, поскольку я не могу установить SINGLE_USERпараметр в TempDB, я не могу использовать, DBCC WRITEPAGEчтобы повредить страницу, и, следовательно, я не могу вызвать повреждение в TempDB.

Вместо этого DBCC WRITEPAGEможно было бы отключить базу данных и использовать шестнадцатеричный редактор для изменения случайных байтов в файле базы данных. Конечно, это не работает и на 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: )

Я знаю, что это Evaluation Edition, у нас есть ключи для Enterprise Edition, и мы скоро выполним обновление Edition.


2
К вашему сведению -T 3609, при запуске сохранится база данных tempdb (недокументированная, но уже известная )
Ремус Русану

Ответы:


3

Это известная проблема с исправлением:

ИСПРАВЛЕНИЕ: ошибка «Не найдена запись каталога для идентификатора раздела в базе данных» при использовании SQL Server 2012

Предположим, что вы запрашиваете таблицу tempdb.sys.allocation_units в Microsoft SQL Server 2012. Когда вы используете подсказку NOLOCK в запросе или запрос находится под уровнем изоляции транзакции READ UNCOMMITED, вы получаете следующее прерывистое сообщение об ошибке 608:

Ошибка: 608 Уровень серьезности: 16 Состояние: 1
Не найдена запись каталога для раздела в базе данных. Метаданные противоречивы. Запустите DBCC CHECKDB для проверки повреждения метаданных

Примечание. Команда DBCC CHECKDB не показывает никаких признаков повреждения базы данных.

Исправлено в:

Ваша версия (11.0.3000.0) - это SQL Server 2012 SP1 RTM


7

Запуск CHECKDBпротив tempdbне то же самое, что запуск против пользовательской базы данных.

Из MSDN :

Запуск DBCC CHECKDB для базы данных tempdb не выполняет каких-либо проверок распределения или каталога и должен получить общие блокировки таблиц для выполнения проверок таблиц. Это связано с тем, что по соображениям производительности снимки базы данных недоступны в базе данных tempdb. Это означает, что требуемая транзакционная согласованность не может быть получена.


6

Да, но, в частности, ошибка каталога не может быть проверена в TempDB. Вы должны перезапустить SQL Server, если это возможно, чтобы это исправить. По MSDN:

«Запуск DBCC CHECKCATALOG для базы данных tempdb не выполняет никаких проверок. Это связано с тем, что по соображениям производительности моментальные снимки базы данных недоступны на базе данных tempdb. Это означает, что не может быть получена требуемая согласованность транзакций. Перезапустите сервер, чтобы устранить любые проблемы с метаданными базы данных tempdb».

Статья MSDB находится здесь: http://msdn.microsoft.com/en-us/library/ms186720.aspx

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.