SQL 2017 TDE数据库中的备份压缩导致损坏


13

在SQL Server 2017(CU3)上,每当我在一个TDE数据库上启用备份压缩时,备份过程始终会损坏数据库中的特定页面。如果我运行备份时不进行压缩,则不会损坏它。这是我为验证和重现此问题而采取的步骤:

  1. 在数据库“ TDE_DB1”上运行DBCC CheckDB;一切都很好,没有错误;
  2. 成功备份数据库而无需压缩;RESTORE VERIFYONLY表示一切都很好;
  3. 成功将数据库还原为“ TDE_DB2”;一切都很好,DBCC CheckDB没有显示任何错误;
  4. 使用压缩成功备份“ TDE_DB1”数据库;RESTORE VERIFYONLY错误,提示“检测到备份集损坏”;
  5. 尝试将数据库还原为“ TDE_DB2”;错误,说“ RESTORE在数据库中的页面(1:92454)上检测到错误”
  6. 重复步骤1-3;一切都很好;
  7. DROP“ TDE_DB1”和“ TDE_DB2”; 从备份中还原“ TDE_DB1”;一切都很好;
  8. 重复步骤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_pa​​ge_iam_file_id = 1 allocated_pa​​ge_iam_page_id = 104
allocated_pa​​ge_file_id = 1 allocated_pa​​ge_page_id = 92454
is_allocated = 0 is_iam_page = 0 is_mixed_pa​​ge_allocation = 0

Answers:


8

似乎此问题与已在其上运行SHRINK操作的数据库有关。就我而言,我正在复制一个我们在SQL Server 2014上的生产数据库的副本(已使用TDE加密),在数据和日志文件上都运行DBCC SHRINKFILE,然后进行备份并将其还原到我的新SQL上2017服务器。(缩小的原因是为了减小大小,以便更快地传输备份。)

作为测试,我还原了未在其上运行DBCC SHRINKFILE的数据库的副本,并且在压缩备份时它没有损坏问题。

因此,总而言之,我的测试结果如下:

  • 在此“缩小的” TDE数据库上的正常备份/还原操作在SQL 2017中正常运行
  • 压缩“缩小的” TDE数据库的备份似乎会导致sys.sysmultiobjrefs表中的损坏
  • 压缩常规TDE数据库的备份(不运行DBCC SHRINKFILE)可以正常工作,并且不会报告损坏

我不知道这是否是SQL Server 2017中的已确认错误,但我已将发现发送给Microsoft,以供他们查看。

因此,这个故事的寓意是:不要收缩您的数据库!永远!:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.