Восстановление несовместимых страниц в базе данных

8

У нас есть БД SQL 2000. Сбой сервера из-за сбоя массива Raid. Теперь, когда мы запускаем DBCC CHECKDB, мы получаем ошибку, что на 9 страницах есть 27 ошибок согласованности.

Когда мы запускаем DBCC PAGE на этих страницах, мы получаем это:

Msg 8939, Level 16, State 106, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (m_freeCnt == freeCnt) failed. Values are 2 and 19.
Msg 8939, Level 16, State 108, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (emptySlotCnt == 0) failed. Values are 1 and 0.

Поскольку указанный индекс не является кластеризованным и создается уникальным ограничением, включающим 2 столбца, мы попытались удалить и воссоздать индекс. Это привело к следующей ошибке:

CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 2. Most significant primary key is '3280'. 
The statement has been terminated. 

Однако работает

Select var_id,result_on
from tests
group by var_id,result_on
having count(*)>1

возвращает 0 строк

Вот что мы планируем сделать:

  • Восстановите аварийную копию БД перед сервером и запустите DBCC CHECKDB.
  • Если это возвращает чистый, то восстановите снова без восстановления
  • Применить все последующие резервные копии TLOG
  • Остановите производственное приложение, сделайте резервную копию хвостового журнала и примените это тоже
  • Бросьте prod DB и переименуйте только что восстановленную DB, чтобы сделать ее
  • Запустить приложение prod

Может ли кто-нибудь пробить дыры в этом подходе? Может быть, предложить другой подход? Нам нужно минимальное время простоя.

SQL 2000 DB Размер 94 ГБ Таблица с поврежденными страницами содержит 460 миллионов + строк данных

Спасибо за помощь.

Радж


источник
1
Мне нравится ваш подход. Имеет смысл для меня. Возможно, держите поврежденную базу данных рядом, как страховку ...
user24161
Кроме того, когда все
закончится, спланируйте
(то есть обновление 2005 или 2008 гг.)
user24161
+1 за наличие действующего и очень подходящего плана восстановления
Эндрю

Ответы:

2

Ваше решение для восстановления - это учебник. Если у вас есть соответствующие резервные копии и вы можете создать резервную копию журнала транзакций для поврежденной базы данных, тогда ваша стратегия - это учебник, который нужно реализовать.

Однако, прежде чем продолжить, рассматривали ли вы возможность воссоздания только затронутой таблицы?

Иногда вы можете создать точную копию затронутой таблицы, выполнив

select *
into NewTableFromOld
from DamagedTable

Затем просто удалите / замените поврежденную таблицу новой, не забывая добавить соответствующие ограничения и индексы.

Джон Сансом
источник
Спасибо за ответ. Ваш подход выглядит хорошо, но проблема в том, что, учитывая, что таблица содержит 461 миллион строк данных, как это повлияет на производство, когда я сделаю выбор *? Разве это не захватило бы замок и не поразило бы производительность?
Нет, если вы используете подсказку with (nolock) no. Однако вы можете проверить, что ничего не изменилось между исходной и целевой таблицами, пока вы взяли копию. В любом случае это, вероятно, потребуется при сборке таблицы, если вы не остановите приложение от внесения изменений. В такой операции будет зависеть производительность диска.
Джон Сансом
Лично я бы попробовал этот подход в первую очередь, вы можете сделать это с опцией nolock для тестирования, вы также можете проверить необходимое время. Если он работает так, как должен, я бы затем перевел базу данных в однопользовательский режим, делая это снова, чтобы убедиться, что никаких изменений не произойдет во время работы процесса. Время простоя будет намного меньше при таком подходе, если он работает.
лысый
Если вы собираетесь это сделать, я бы рекомендовал сначала создать таблицу (написав сценарий исходной таблицы). Затем используйте «INSERT INTO newTable SELECT» против «SELECT INTO». Вы можете столкнуться с проблемами производительности с «SELECT INTO».
SQL3D
0

Я попытался бы сначала объединить данные в файл, а затем вернуть их обратно в новую таблицу. SELECT INTO не подходит (IMO) для такого количества записей ...

m4rty
источник