在SQL Server 2017(CU3)上,每当我在一个TDE数据库上启用备份压缩时,备份过程始终会损坏数据库中的特定页面。如果我运行备份时不进行压缩,则不会损坏它。这是我为验证和重现此问题而采取的步骤:
- 在数据库“ TDE_DB1”上运行DBCC CheckDB;一切都很好,没有错误;
- 成功备份数据库而无需压缩;RESTORE VERIFYONLY表示一切都很好;
- 成功将数据库还原为“ TDE_DB2”;一切都很好,DBCC CheckDB没有显示任何错误;
- 使用压缩成功备份“ TDE_DB1”数据库;RESTORE VERIFYONLY错误,提示“检测到备份集损坏”;
- 尝试将数据库还原为“ TDE_DB2”;错误,说“ RESTORE在数据库中的页面(1:92454)上检测到错误”
- 重复步骤1-3;一切都很好;
- DROP“ TDE_DB1”和“ TDE_DB2”; 从备份中还原“ TDE_DB1”;一切都很好;
- 重复步骤1-5;得到相同的结果
总结一下:数据库和常规备份看起来不错,在数据库上运行CHECKDB并在备份上运行VERIFYONLY不会报告任何错误。使用压缩备份数据库似乎会导致损坏。
下面是有错误的代码示例。(注意:将压缩与TDE数据库一起使用需要MAXTRANSFERSIZE)
-- Good, completes with no corruption;
BACKUP DATABASE [TDE_DB1] TO DISK = N'E:\MSSQL\Backup\TDE_DB1a.bak' WITH CHECKSUM;
RESTORE VERIFYONLY FROM DISK = N'E:\MSSQL\Backup\TDE_DB1a.bak' WITH CHECKSUM;
RESTORE DATABASE [TDE_DB2]
FROM DISK = 'E:\MSSQL\Backup\TDE_DB1a.bak'
WITH MOVE 'DataFileName' to 'E:\MSSQL\Data\TDE_DB2.mdf'
,MOVE 'LogFileName' to 'F:\MSSQL\Log\TDE_DB2_log.ldf';
-- Bad, I haz corruption;
BACKUP DATABASE [TDE_DB1] TO DISK = N'E:\MSSQL\Backup\TDE_DB1b.bak' WITH CHECKSUM, COMPRESSION, MAXTRANSFERSIZE = 131072;
RESTORE VERIFYONLY FROM DISK = N'E:\MSSQL\Backup\TDE_DB1b.bak' WITH CHECKSUM;
-- ERROR
--Msg 3189, Level 16, State 1, Line 1
--Damage to the backup set was detected.
--Msg 3013, Level 16, State 1, Line 1
--VERIFY DATABASE is terminating abnormally.
RESTORE DATABASE [TDE_DB2]
FROM DISK = 'E:\MSSQL\Backup\TDE_DB1b.bak'
WITH MOVE 'DataFileName' to 'E:\MSSQL\Data\TDE_DB2.mdf'
,MOVE 'LogFileName' to 'F:\MSSQL\Log\TDE_DB2_log.ldf';
-- ERROR
--Msg 3183, Level 16, State 1, Line 7
--RESTORE detected an error on page (1:92454) in database "TDE_DB2" as read from the backup set.
--Msg 3013, Level 16, State 1, Line 7
--RESTORE DATABASE is terminating abnormally.
然后,我尝试检查报告有错误的页面(它始终是同一页面。),但是DBCC PAGE报告该ObjectId为0。 根据Paul Randal的这篇文章,这意味着找不到元数据,并且原因之一可能是页面本身已损坏,并且使用了不正确的值来尝试查找元数据。他的建议是运行CHECKDB,我无法这样做,因为损坏的备份无法还原。
我尝试了该SO Post中的建议(将INIT和FORMAT添加到BACKUP命令中)以重置元数据,但似乎并没有改变任何内容,压缩备份上仍然损坏。
这仅在我的TDE数据库之一中发生。我在同一台服务器上还有其他4个TDE数据库,它们没有此问题。这告诉我该特定数据库可能存在潜在的问题。我意识到,简单的解决方案是不使用压缩,但是我觉得这实际上可能是即将出现的更大问题的预警。
有没有人看过这个,或者有任何想法为什么压缩会破坏该页面?在这一点上,我对下一步该做什么感到困惑。我考虑过从较早的备份中还原页面,但是我认为这并不重要,因为常规数据库中的页面看起来还不错。
更新1: 以下是DBCC PAGE的结果,带有选项0:
DBCC执行完成。如果DBCC打印了错误消息,请与系统管理员联系。
页面:(1:92454)
缓冲:
BUF @ 0x000002187AE55640
bpage = 0x000002184865E000 bhash = 0x0000000000000000
bpageno =(1:92454)bdbid = 8 breferences = 0 bcputicks = 563 bsampleCount = 1
bUse1 = 51429 bstat = 0x809 Blog = 0x15a
bnext = 0x0000000000000000 bDirtyContext = 0x0000000000000000 bstat2 = 0页面标题:
页面@ 0x000002184865E000
m_pageId =(1:92454)m_headerVersion = 111
m_type = 189 m_typeFlagBits = 0x2d m_level = 197
m_flagBits = 0x525e m_objId(AllocUnitId.idObj)= 788815194
m_indexId(AllocUnitId.idInd)= 515元数据:AllocUnit879 = 130 14 IndexId = -1元数据:ObjectId = 0 m_prevPage =(32842:1881351155)m_nextPage =(13086:-560562340)
pminlen = 36067 m_slotCnt = 8149 m_freeCnt = 51871 m_freeData = 7295 m_reservedCnt = 4810 m_lsn =(742012401:720884976:30 14755
m_xdesId =(12811:1559482793)m_ghostRecCnt = 12339
m_tornBits = -1381699202 DB Frag ID = 1分配状态
GAM(1:2)=分配的SGAM(1:3)=未
分配的PFS(1:88968)= 0x0 0_PCT_FULL DIFF(1:6)=未更改
ML(1:7)= NOT MIN_LOGGED
如果尝试使用其他选项运行DBCC PAGE,则会出现以下错误:
带有选项1的DBCC PAGE:消息0,级别11,状态0,行0在当前命令上发生严重错误。结果(如有)应丢弃。
带有选项3的DBCC PAGE:消息2514,级别16,状态5,第3行发生DBCC PAGE错误:无效的页面类型-无法进行转储样式3。
更新2: 以下是sys.dm_db_database_page_allocations DMO的一些结果:
的object_id = 75 index_id的= 1 rowset_id = 281474981625856 allocation_unit_id = 281474981625856
allocation_unit_type = 1 allocation_unit_type_desc = IN_ROW_DATA extent_file_id = 1 extent_page_id = 92448
allocated_page_iam_file_id = 1 allocated_page_iam_page_id = 104
allocated_page_file_id = 1 allocated_page_page_id = 92454
is_allocated = 0 is_iam_page = 0 is_mixed_page_allocation = 0