TempDB 中的损坏分区如何导致 DBCC CHECKDB 报告没有问题?

Han*_*non 9 sql-server sql-server-2012 tempdb dbcc-checkdb

我们的其中一台 SQL Server 最近报告了以下错误:

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.
Run Code Online (Sandbox Code Playgroud)

不到 15 分钟后,我连接到服务器并运行:

SELECT name
FROM sys.databases
WHERE database_id = 2;
Run Code Online (Sandbox Code Playgroud)

返回'tempdb'。然后我跑了:

DBCC CHECKDB ('tempdb') WITH NO_INFOMSGS, TABLERESULTS;
Run Code Online (Sandbox Code Playgroud)

没有返回任何结果,表明受影响的数据库没有问题。

数据库中的损坏如何导致上述错误消息DBCC CHECKDB但未报告问题?我假设如果页面校验和计算失败,导致页面被标记为怀疑引用该页面的任何对象将无法删除,但我一定是错的。

一旦页面被标记为“可疑”,如何将其标记为“不可疑”、“已修复”或“重用”,或者DBCC CHECKDB不报告相关页面有任何问题的任何内容?


编辑:2013-02-27 13:24

只是为了好玩,我试图在 TempDB 中重新创建损坏,假设 #temp 表是罪魁祸首。

但是,由于我无法SINGLE_USER在 TempDB 中设置该选项,因此无法用于DBCC WRITEPAGE损坏页面,因此我无法在 TempDB 中强制损坏。

而不是使用DBCC WRITEPAGE一个可以将数据库设置为离线并使用十六进制编辑器来修改 db 文件中的随机字节。当然,这在 TempDB 上也不起作用,因为数据库引擎无法在 TempDB 离线时运行。

如果你停止实例,TempDB 会在下次启动时自动重新创建;因此这也不起作用。

如果有人能想出一种方法来重现这种腐败,我愿意做进一步的研究。

为了测试无法修复损坏的页面的假设,DROP TABLE我创建了一个测试数据库并使用以下脚本来损坏页面,然后尝试删除受影响的表。这里的结果是无法删除表;RESTORE DATABASE Testdb PAGE = ''...为了恢复受影响的页面,我不得不这样做。我假设如果我对相关页面的其他部分进行了更改,也许该页面可以使用DROP TABLETRUNCATE 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.
Run Code Online (Sandbox Code Playgroud)

此时您与数据库引擎断开连接,因此重新连接以继续。

USE Test;
DBCC CHECKDB WITH NO_INFOMSGS, TABLERESULTS;
Run Code Online (Sandbox Code Playgroud)

腐败报告在这里。

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.
Run Code Online (Sandbox Code Playgroud)

腐败报告here,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';
Run Code Online (Sandbox Code Playgroud)

编辑#2,添加请求的@@VERSION 信息。

SELECT @@VERSION;
Run Code Online (Sandbox Code Playgroud)

返回:

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: )
Run Code Online (Sandbox Code Playgroud)

我知道这是评估版,我们有企业版的密钥,很快就会进行版本升级。

Jon*_*gel 7

运行CHECKDB反对tempdb是不一样的运行它针对的用户数据库。

MSDN

针对 tempdb 运行 DBCC CHECKDB 不会执行任何分配或目录检查,并且必须获取共享表锁才能执行表检查。这是因为出于性能原因,数据库快照在 tempdb 上不可用。这意味着无法获得所需的事务一致性。


Cat*_*hue 6

是的,但具体而言,无法在 TempDB 中检查目录错误。如果可能,您应该回收 SQL Server 来解决这个问题。每 MSDN:

“针对 tempdb 运行 DBCC CHECKCATALOG 不会执行任何检查。这是因为出于性能原因,数据库快照在 tempdb 上不可用。这意味着无法获得所需的事务一致性。回收服务器以解决任何 tempdb 元数据问题。”

MSDB 文章在这里:http : //msdn.microsoft.com/en-us/library/ms186720.aspx


Mit*_*eat 3

这是一个已修复的已知问题:

修复:使用 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