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 CHECKDB
autant 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 CHECKDB
ne 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_USER
option dans TempDB, je ne peux pas l'utiliser DBCC WRITEPAGE
pour corrompre une page, et donc je ne peux pas forcer la corruption dans TempDB.
Au lieu d'en utiliser DBCC WRITEPAGE
un, 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 TABLE
j'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 TABLE
ou 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.
-T 3609
conservera tempdb au démarrage (non documenté mais déjà connu )