На днях одна из баз MS SQL Server переключилась на Suspect, в журнале появилось сообщение об ошибке:
Сообщение 7105, уровень 22, состояние 9, строка 14 Идентификатор базы данных 6, страница (1:386499), слот 0 для узла типа данных LOB не существует. Обычно это вызвано транзакциями, которые могут читать незафиксированные данные на странице данных.Базу перевели в Emergency и попытались выполнить DBCC CHECKDB, но выполнение тут же прервалось:Запустите DBCC CHECKTABLE.
Сообщение 8921, уровень 16, состояние 1, строка 13 Проверка прекращена.Команда DBCC CHECKALLOC была прервана из-за аналогичной ошибки.При сборе фактов был обнаружен сбой.
Возможно, в базе данных tempdb недостаточно места или системная таблица противоречива.
Проверьте предыдущие ошибки.
Сообщение 7105, уровень 22, состояние 9, строка 13 Идентификатор базы данных 6, страница (1:386499), слот 0 для узла типа данных LOB не существует. Обычно это вызвано транзакциями, которые могут читать незафиксированные данные на странице данных.
Запустите DBCC CHECKTABLE.
Все осложнялось тем, что 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:
Однако, если вам не повезет, как нам, вы увидите это:
Метаданные: = Недоступно в автономной БД.Если метаданные недоступны, не все потеряно, и в этом случае нам понадобится поле 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
И там, в случае 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)
К счастью, и в реальной ситуации, и здесь некластеризованный индекс оказался поврежденным, после восстановления все пришло в норму (на самом деле нет, но это уже другая история).
Ссылки : Как использовать страницу DBCC Устранение неполадок и исправление повреждения уровня страницы SQL Server Что такое единицы распределения? Поиск имени таблицы по идентификатору страницы sys.allocation_units Теги: #Администрирование баз данных #Microsoft SQL Server #sql-сервер #коррупция #dbcc checkdb
-
Как Начинался Проект Pvs-Studio 10 Лет Назад
19 Oct, 24 -
Мой Питомец:
19 Oct, 24 -
Правда Ли, Что Go Быстрее Ruby?
19 Oct, 24 -
Новый Подход К Продаже Рекламы На Сайтах.
19 Oct, 24