У SQL Server 2017 (CU3) щоразу, коли я включаю компресію резервного копіювання на одній із моїх баз даних TDE, процес резервного копіювання завжди пошкоджує певну сторінку в базі даних. Якщо я запускаю резервну копію без стиснення, вона не пошкоджується. Ось кроки, які я вжив для перевірки та відтворення цієї проблеми:
- Запустити DBCC CheckDB в базі даних "TDE_DB1"; все добре, помилок немає;
- Успішно створити резервну копію бази даних без стиснення; ЗАВДАННЯ ВЕРІФОННО каже, що все добре;
- Успішно відновити базу даних як "TDE_DB2"; все добре, DBCC CheckDB не показує помилок;
- Успішно створити резервну копію бази даних "TDE_DB1" З компресією; ВІДКЛЮЧИТИ ВЕРИФІОННО помилки, кажучи: "Пошкодження набору резервних копій виявлено";
- Спроба відновити базу даних як "TDE_DB2"; помилки: "RESTORE виявив помилку на сторінці (1: 92454) у базі даних"
- Повторіть кроки 1-3; все добре;
- DROP "TDE_DB1" і "TDE_DB2"; Відновити "TDE_DB1" з резервної копії; все добре;
- Повторіть кроки 1-5; отримати однакові результати;
Підводячи підсумок: база даних та регулярні резервні копії здаються прекрасними, запуск CHECKDB в базі даних та VERIFYONLY на резервних копіях не повідомляють про помилки. Резервне копіювання бази даних при стисненні, здається, може спричинити корупцію.
Нижче наведено зразки коду з помилками. (Примітка. MAXTRANSFERSIZE потрібен для використання компресії з базою даних TDE )
-- 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. Відповідно до цієї статті Павла Рандала, це означає, що метаданих не було знайдено, і Однією з причин може бути те, що сама сторінка є пошкодженою, а неправильні значення використовувались для пошуку метаданих. Його порада - запустити CHECKDB, чого я не можу зробити, оскільки пошкоджена резервна копія не відновиться.
Я спробував пропозиції з цієї публікації SO (Додавання 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 бреферів = 0 bcputicks = 563 bsampleCount = 1
bUse1 = 51429 bstat = 0x809 blog = 0x15a
bnext = 0x00000000000000000000 bDirtyConteСТОРІНКА КОРИСТУВАЧА:
Сторінка @ 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 (AllocdanitId (51) AllocdanitIl (51) IndexId = -1 Метадані: ObjectId = 0 m_prevPage = (32842: 1881351155) m_nextPage = (13086: -560562340)
pminlen = 36067 m_slotCnt = 8149 m_freeCnt = 51871 m_freeData = 7295 m_reservedCls = 7105 m_reservedCls = 4810 m_reservedCls = 4810 m_reservedCls = 4810 m_reservedCls = 4810 m_reservedCls = 4810 m_reservedCnt = 4810 m_reservedCnt = 4810 m_freshData = 7295; 14755
m_xdesId = (12811: 1559482793) m_ghostRecCnt =
12339 m_tornBits = -1381699202 Ідентифікатор фрагмента БД = 1Статус розподілу
GAM (1: 2) = ALLOCATED SGAM (1: 3) = NOT ALLOCATED
PFS (1: 88968) = 0x0 0_PCT_FULL DIFF (1: 6) = NOT CHENGED
ML (1: 7) = NOT MIN_LOGGED
Якщо я спробую запустити DBCC PAGE з іншими параметрами, я отримую нижче помилки:
DBCC PAGE з опцією 1: Msg 0, рівень 11, стан 0, рядок 0 У поточній команді сталася сильна помилка. Результати, якщо такі є, слід відмовитися.
DBCC PAGE з опцією 3: Msg 2514, Рівень 16, Стан 5, Рядок 3 Виникла помилка PAGE DBCC: Невірний тип сторінки - стиль дамп 3 не можливий.
ОНОВЛЕННЯ 2: Ось деякі результати DMO sys.dm_db_database_page_allocations:
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