Поиск Поврежденного Объекта По Номеру Поврежденной Страницы В Ms Sql Server 2005

На днях одна из баз MS SQL Server переключилась на Suspect, в журнале появилось сообщение об ошибке:

Сообщение 7105, уровень 22, состояние 9, строка 14 Идентификатор базы данных 6, страница (1:386499), слот 0 для узла типа данных LOB не существует. Обычно это вызвано транзакциями, которые могут читать незафиксированные данные на странице данных.

Запустите DBCC CHECKTABLE.

Базу перевели в Emergency и попытались выполнить DBCC CHECKDB, но выполнение тут же прервалось:
Сообщение 8921, уровень 16, состояние 1, строка 13 Проверка прекращена.

При сборе фактов был обнаружен сбой.

Возможно, в базе данных tempdb недостаточно места или системная таблица противоречива.

Проверьте предыдущие ошибки.

Сообщение 7105, уровень 22, состояние 9, строка 13 Идентификатор базы данных 6, страница (1:386499), слот 0 для узла типа данных LOB не существует. Обычно это вызвано транзакциями, которые могут читать незафиксированные данные на странице данных.

Запустите 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 и подозреваемых_страниц.

Проблема оказалась на странице с подозреваемого_страниц.

Первое, что нужно сделать, это выполнить (в контексте поврежденной базы данных) это СТРАНИЦА DBCC (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.

Если вам повезет (или вы играете на живой базе), в результате вы увидите поле Метаданные: ObjectId и собственно искомый object_id:

Поиск поврежденного объекта по номеру поврежденной страницы в MS SQL Server 2005

Однако, если вам не повезет, как нам, вы увидите это:
Метаданные: = Недоступно в автономной БД.

Если метаданные недоступны, не все потеряно, и в этом случае нам понадобится поле m_objId (AllocUnitId.idObj).

Если m_objId = 255 — это катастрофа, закройте статью и ищите что-нибудь другое (попробуйте заскриптовать все, что можно, и украсть данные, выполнить DBCC CHECKDB с параметрами «восстановления» вслепую и т. д.).

На скриншоте видно, что у меня m_objId=9931, т.е.

можно продолжать.

Теперь вам нужно выполнить несколько небольших вычислений, чтобы вычислить идентификатор единицы распределения (подробнее о единицах распределения можно прочитать здесь).

Здесь ):

Идентификатор единицы распределения = m_objid * 65536 + (2^56)
В нашем случае:
Идентификатор единицы распределения = 9931 * 65536 + (2^56) = 72057594688765952
Итак, зная ID единицы распределения, вы можете увидеть, что мы имеем в системном представлении.

sys.allocation_units :

SELECT * FROM sys.allocation_units WHERE allocation_unit_id = 72057594688765952



Поиск поврежденного объекта по номеру поврежденной страницы в MS SQL Server 2005

И там, в случае 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



Поиск поврежденного объекта по номеру поврежденной страницы в MS SQL Server 2005

И здесь уже есть правильные object_id и index_id. Теперь вы можете увидеть, что у нас есть в sys.objects и sys.indexes, и просто запустить:

SELECT OBJECT_NAME(object_id)

К счастью, и в реальной ситуации, и здесь некластеризованный индекс оказался поврежденным, после восстановления все пришло в норму (на самом деле нет, но это уже другая история).

Ссылки : Как использовать страницу DBCC Устранение неполадок и исправление повреждения уровня страницы SQL Server Что такое единицы распределения? Поиск имени таблицы по идентификатору страницы sys.allocation_units Теги: #Администрирование баз данных #Microsoft SQL Server #sql-сервер #коррупция #dbcc checkdb

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.