В Twitter состоялось краткое обсуждение того, почему страницы PFS (повреждённый заголовок, а не отдельные байты PFS) нельзя восстановить (поводом стал вопрос #sqlhelp о том, почему для них невозможно восстановление отдельной страницы, в отличие от других карт распределения базы данных). Для справки: их также нельзя исправить с помощью автоматического восстановления страниц с зеркала или в группе доступности (AG).
Страницы PFS встречаются каждые 8088 страниц в каждом файле данных и хранят байт информации о себе и о следующих 8087 страницах. Самая важная информация, которую они хранят, — это то, выделена ли страница (используется) или нет. Подробнее о страницах PFS и других картах распределения базы данных можно прочитать в этой записи блога.
Итак, почему их не может восстановить DBCC CHECKDB, когда все остальные карты распределения базы данных могут?
Ответ заключается в том, что информация о распределении страниц больше нигде в базе данных не дублируется, и её поэтому невозможно восстановить.
Можно предположить, что DBCC CHECKDB мог бы определить, какие страницы распределены, выводя это состояние из того, что страница как-то связана с другой страницей, которая точно распределена. И он мог бы это сделать, за исключением случая с кучей без некластерных индексов.
Если у кучи нет некластерных индексов, в базе данных не существует другой структуры, которая ссылалась бы на какие-либо страницы данных в этой куче. Следовательно, без информации на странице PFS невозможно определить, какие из страниц, содержащихся в экстентах, распределённых под кучу, на самом деле распределены, а какие нет. Это связано с тем, что SQL Server не затрагивает страницу при её освобождении, поэтому на странице нет ничего, что указывало бы, распределена ли она в данный момент или была освобождена.
Что, если DBCC CHECKDB сможет определить, что в базе данных нет таких случаев?
Ответ: алгоритм восстановления страницы PFS с учётом ссылок с других страниц на страницы, охватываемые этим диапазоном PFS, крайне сложен и потребовал бы поиска по всей базе данных, чтения и обработки всех страниц во второй раз после их восстановления, чтобы найти связи со страницами в повреждённом диапазоне. Хотя технически это звучит возможно, когда я проектировал написание такого алгоритма ещё в 2001–2002 годах, я быстро столкнулся с проблемами времени выполнения и сложности, которые сделали эту работу совершенно неосуществимой.
Также невозможно просто пометить все страницы как распределённые — потому что тогда просмотры в порядке распределения наткнулись бы на потенциально неотформатированные страницы и завершились бы с ошибкой. Это также нарушило бы резервное копирование с использованием WITH CHECKSUM. Такой алгоритм можно было бы заставить работать (при отсутствии куч без некластерных индексов), но у него те же проблемы, что и у алгоритма выше.
Таким образом, страницы PFS нельзя восстановить, и, если структура базы данных не изменится так, чтобы каким-либо образом дублировать эту информацию о распределении, я не вижу, чтобы это изменилось в будущем.

Комментариев нет:
Отправить комментарий