如何解决 BACKUP WITH CHECKSUM 而不是 DBCC CHECKDB 检测到的损坏?

Her*_*rot 5 sql-server-2008-r2 dbcc-checkdb checksum

最近,我被要求从生产环境刷新测试服务器上的几个数据库。一直想遵循最佳实践,我使用WITH CHECKSUM选项执行备份,最终得到以下错误:

Msg 3043, Level 16, State 1, Line 32
BACKUP 'DBName' detected an error on page (1:428321) in file 'F:\path\DBName.mdf'.
Msg 3013, Level 16, State 1, Line 32
BACKUP DATABASE is terminating abnormally.
Run Code Online (Sandbox Code Playgroud)

对错误感到惊讶,我运行DBCC CHECKDB以查看发生了什么,但不幸的是(或者幸运的是),它恢复正常。

到目前为止,我发现的所有信息都鼓励使用 DBCC CHECKDB 的发现作为下一步的指南,所以我不确定如何解决这个问题?

一些快速信息:

  1. SQL Server 是 2008 R2。

  2. 我在msdb.dbo.suspect_pages表中发现了错误的确认。它包含事件类型 1 和 3。

  3. 我使用的 DBCC 命令是 DBCC CHECKDB (DBName) WITH NO_INFOMSGS, ALL_ERRORMSGS;

  4. 我不是正式的 DBA,但由于我有一些经验,所以我被允许执行备份和恢复。

  5. 我确实读过类似的帖子DBCC CheckDB 会错过哪些类型的损坏?. 然而,虽然我相信我明白为什么(那篇文章的重点),但我不知道如何解决它。

  6. 通过省略WITH CHECKSUM选项,我能够成功执行备份。

在此先感谢您的指导!

更新

下面“usr”提供的评论让我走上了正确的道路。页面 (1:428321) 到底包含什么内容?我做了更多的研究,发现了DBCC PAGE命令。然而,我注意到了一些奇怪的事情。当我执行以下...

DBCC TRACEON (3604);
DBCC PAGE ('DBName', 1, 428321, 3);
Run Code Online (Sandbox Code Playgroud)

我得到了以下回复(注意第一行的页码)...

PAGE: (1:2021305)

BUFFER:

BUF @0x0000000CFEFCC580

bpage = 0x0000000CFE764000           bhash = 0x0000000000000000           bpageno = (1:428321)
bdbid = 18                           breferences = 0                      bcputicks = 0
bsampleCount = 0                     bUse1 = 20204                        bstat = 0xc00809
blog = 0xbcca2159                    bnext = 0x0000000000000000           

PAGE HEADER:

Page @0x0000000CFE764000

m_pageId = (1:2021305)               m_headerVersion = 1                  m_type = 1
m_typeFlagBits = 0x0                 m_level = 0                          m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 5313   m_indexId (AllocUnitId.idInd) = 256  
Metadata: AllocUnitId = 72057594386120704                                 Metadata: PartitionId = 0
Metadata: IndexId = -1               Metadata: ObjectId = 0               m_prevPage = (1:2021304)
m_nextPage = (1:2021306)             pminlen = 194                        m_slotCnt = 10
m_freeCnt = 228                      m_freeData = 7944                    m_reservedCnt = 0
m_lsn = (121329:238172:13)           m_xactReserved = 0                   m_xdesId = (0:0)
m_ghostRecCnt = 0                    m_tornBits = 297819981               

Allocation Status

GAM (1:2) = ALLOCATED                SGAM (1:3) = NOT ALLOCATED           
PFS (1:420576) = 0x40 ALLOCATED   0_PCT_FULL                              DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED            

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Run Code Online (Sandbox Code Playgroud)

2021305 ??? 我不是输入了428321吗?如果我只是在它之前的页面 (428320) 上运行命令,我就会得到那个页面。所以我想我越来越近了,但仍然不知道该页面包含什么。

usr*_*usr 2

我不知道如何解决这个问题

在评论中,我们进行了调查,但从未最终确定该页面是否已分配。

如果它被分配了,这绝对是一个错过的腐败CHECKDB。中的一个错误CHECKDB。请向 Microsoft 报告该情况。

如果未分配,我将如何修复它:用虚拟数据填充文件,例如CONVERT(binary(8000), 0x). 现在该页面应该已被虚拟数据消耗并被干净的内容覆盖。

实际上,你可以用这个想法来测试SQL Server是否认为该页已分配。如果这有效,那么肯定没有分配。

或者,您可以使用写入页面功能对页面进行零填充,但这会在数据库启动页面中留下审核跟踪。我猜,当微软支持人员将来为你提供帮助时,他们不会喜欢发现这个。他们可能认为您的页面写入造成了损坏。此外,它通过在没有解决方案的情况下终止调查来窃取调查的所有乐趣:)