Этот вопрос возникал уже несколько раз, совсем недавно — сегодня утром в письме: последующие запуски DBCC CHECKDB показывают разное количество повреждений, а иногда и вовсе их не находят — что происходит? Ещё более странно: задание обслуживания запускает DBCC CHECKDB, который показывает ошибки, но затем утром — никаких ошибок согласованности. Как?
Я отвечал на это ещё в колонке SQL Q&A в TechNet Magazine, но хочу опубликовать это и здесь, в блоге, более подробно. Ответ связан с тем, как проверяется согласованность базы данных и как обнаруживаются повреждения.
Начиная с версии 2005, вы, вероятно, используете контрольные суммы страниц для помощи в обнаружении повреждений. Если вы создали базу данных в версии 2005 или новее, контрольные суммы страниц включены по умолчанию, и каждая распределённая страница будет иметь такую сумму. Если вы обновили базу данных с версии 2000 или более ранней, то вам необходимо вручную включить контрольные суммы страниц с помощью ALTER DATABASE. И... ничего не происходит. До тех пор, пока страница не будет считана, изменена и затем записана обратно. Таким образом, ваша обновлённая база данных будет содержать смесь из отсутствия контрольных сумм/контрольных сумм страниц или защиты от «оборванных» страниц/контрольных сумм страниц. Примечание: защищённые от «обрыва» страницы остаются таковыми даже при включённых контрольных суммах страниц до следующего их изменения. Затем они получат контрольную сумму страницы. Объяснение и примеры смотрите в статье Отключается ли "torn page detection" при включении "page checksums"?.
Итак, вы включили контрольные суммы страниц. Как теперь можно определить, есть ли в базе данных повреждения? Существует несколько способов, которыми повреждения могут проявиться:
- Вы выполняете операцию, которая обращается к повреждённой странице, и проверка контрольной суммы страницы завершается неудачей.
- Вы запускаете BACKUP … WITH CHECKSUM, и он находит страницу с неверной контрольной суммой.
- Вы запускаете DBCC CHECKDB, и он находит страницу с неверной контрольной суммой.
Всё это хорошо, но что, если на странице нет контрольной суммы страницы (потому что она не изменялась с момента включения контрольных сумм)? Ни один из пунктов с #1 по #3 не завершится неудачей из-за неверной контрольной суммы страницы, так как проверять просто нечего. #1 может завершиться неудачей в зависимости от степени повреждения страницы, и, вероятно, выдаст неясное сообщение, которое не сразу кричит о «повреждении». #2 не завершится неудачей, так как единственный случай, когда BACKUP проверяет то, что резервирует, — это когда включён WITH CHECKSUM и на странице есть контрольная сумма. #3 может обнаружить повреждение в зависимости от его характера. Например, если повреждение находится в середине большого поля varchar, то, вероятно, нет. Ваш лучший вариант — включить контрольные суммы страниц и регулярно запускать DBCC CHECKDB.
Вот как обнаруживаются повреждения. А что насчёт исчезающих повреждений? Здесь мы касаемся того, как работают проверки согласованности. Проверки согласованности выполняются только для страниц в базе данных, которые являются распределёнными. Если страница ни к чему не распределена, то её 8192 байта бессмысленны и не могут быть интерпретированы. Не путайте понятия «зарезервирована» и «распределена» — я объяснял это в первой статье о заблуждениях здесь. Пока страница распределена, она будет проверена на согласованность DBCC CHECKDB, включая проверку контрольной суммы страницы, если она существует. Повреждение может казаться «исчезнувшим», если повреждённая страница была распределена во время выполнения DBCC CHECKDB, но затем освобождена (деаллоцирована) к моменту следующего запуска DBCC CHECKDB. В первый раз она будет сообщена как повреждённая, но во второй раз она не распределена, поэтому её согласованность не проверяется, и она не будет сообщена как повреждённая. Повреждение выглядит так, как будто оно таинственным образом испарилось. Но это не так — просто повреждённая страница больше не является распределённой. Ничто не мешает SQL Server освободить повреждённую страницу — фактически, именно это и делают многие исправления DBCC CHECKDB — освобождают то, что сломано, и исправляют все связи.
Феномен с заданием обслуживания может возникать из-за порядка операций в этом задании. Если сначала выполняется DBCC CHECKDB, а затем происходит перестроение индекса, и это перестроение затрагивает именно тот индекс, в котором DBCC CHECKDB обнаружил повреждение, то новый индекс будет иметь совершенно другой набор страниц базы данных и не будет содержать повреждённую страницу. Бинго — повреждение исчезло. Последующий запуск DBCC CHECKDB может не найти никаких повреждений, потому что ранее повреждённые страницы больше не являются распределёнными.
Суть — всякий раз, когда вы получаете сообщения об ошибках повреждения, в 99,99% случаев проблема в вашей подсистеме ввода-вывода, даже если повреждения «исчезают».

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