Пошук пошкодженого об’єкта за номером пошкодженої сторінки в MS SQL Server 2005

Днями одна з баз даних MS SQL Server перейшла в Suspect, в журналі було повідомлення про помилку:
Msg 7105, Level 22, State 9, Line 14
Database ID 6, page (1:386499), slot 0 for LOB data type node does not exist. This is usually caused by transactions that can read uncommitted data on a data page. Run DBCC CHECKTABLE.
Базу перевели в Emergency і спробували виконати DBCC CHECKDB, але виконання відразу ж переривалося:
Msg 8921, 16 Level, State 1, Line 13
Check terminated. A failure was detected while collecting facts. Possibly tempdb out of space or a system table is inconsistent. Check previous errors.
Msg 7105, Level 22, State 9, Line 13
Database ID 6, page (1:386499), slot 0 for LOB data type node does not exist. This is usually caused by transactions that can read uncommitted data on a data page. Run DBCC CHECKTABLE.
З аналогічною ж помилкою переривалося виконання команди DBCC CHECKALLOC. Ускладнювалося тим, що SQL Server був версії 9.0.1399, тобто RTM, без будь-яких оновлень.

Спроби використовувати хинт TABLOCK і явним чином підвищити рівень ізоляції транзакцій, ні до чого не привели (місця на дисках з tempdb було достатньо і DBCC CHECKALLOC з WITH ESTIMATEONLY завершувався з тією ж помилкою). Накочувати SP на сервер з пошкодженої БД вкрай не хотілося, а з яким конкретно об’єктом проблема, було абсолютно незрозуміло. Крім того, складалося враження, що повідомлення DBCC CHECKDB має мало спільного з реальністю, оскільки в msdb.dbo.suspect_pages була одна запис, але номер сторінки відрізнявся від того, який виводив DBCC CHECKDB.

Для того, що слідувати інструкціям DBCC CHECKDB і виконати DBCC CHECKTABLE, потрібно було дізнатися таблицю. І після довгих пошуків, одна інструкція знайшлася.
ПриміткаЯ прошу вибачення, що номери таблиць в повідомленнях про помилки в коді не збігаються. Помилки я взяв з журналів, а код вже після виконую в тестовому оточенні на інший, живий базі.

Ми використовували алгоритм нижче для визначення object_id обох сторінок — з DBCC CHECKDB і suspect_pages. Проблема виявилася в сторінці з suspect_pages

Перше, що потрібно зробити, це виконати (в контексті пошкодженої бази даних) — це DBCC PAGE (database_id, file_id, page_id, printopt):

DBCC TRACEON (3604);
DBCC PAGE(5, 1, 3242342, 0)
DBCC TRACEOFF (3604);

або:

DBCC PAGE(5, 1, 3242342, 0) WITH TABLERESULTS.

Якщо вам пощастило (або ви граєтеся на живий базі), в результаті ви побачите поле Metadata: ObjectId і, власне потрібний object_id:

Однак, якщо вам, як і нам, не пощастило, ви побачите наступне:
Metadata: = Unavailable in offline DB Якщо метадані недоступні, ще не все втрачено, в цьому випадку, нам потрібно полі m_objId (AllocUnitId.idObj). Якщо m_objId = 255, біда закривайте статтю шукайте щось інше (намагайтеся заскриптовать все що можна і потягти дані, виконувати DBCC CHECKDB з «відновними» параметрами наосліп і т. д.).
На скріншоті видно, що у мене m_objId = 9931, тобто можна продовжувати.

Тепер потрібно виконати невеликі обчислення, щоб обчислити Allocation Unit ID (докладніше про Allocation Units можна прочитати тут):
Allocation Unit ID = m_objid * 65536 + (2^56) У нашому випадку:
Allocation Unit ID = 9931 * 65536 + (2^56) = 72057594688765952
Отже, знаючи Allocation Unit ID, можна подивитися у нас в системному уявленні sys.allocation_units:

SELECT * FROM sys.allocation_units 
WHERE allocation_unit_id = 72057594688765952

І там, в разі, якщо type = 1 або 3 (IN_ROW_DATA, ROW_OVERFLOW_DATA), стовпець container_id = sys.partitions.hobt_id («Heap-Or-B-Tree ID»), тобто можна виконати запит:

SELECT * FROM sys.partitions WHERE hobt_id = 72057594661437440

І ось тут вже є коректний object_id і index_id. Тепер можна глянути, що там у нас в sys.objects і sys.indexes, так і просто виконати:

SELECT OBJECT_NAME(object_id)

На щастя, і в реальній ситуації, і тут повержденным виявився некластерный індекс, після перебудови якого все прийшло в норму (насправді немає, але це вже інша історія).

Посилання:
How to use DBCC PAGE
Troubleshooting and Fixing SQL Server Page Level Corruption
What Are Allocation Units?
Finding a table name from a page ID
sys.allocation_units

Читайте також  Вся правда про ОСРВ. Групи прапорів подій: введення і базові служби

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

You may also like...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *