Большой запрос на удаление, кажется, заморожен

10

Мы запустили запрос на удаление базы данных с 1,8 млрд строк. Это удаление приведет к удалению 1,2 млрд строк.

Оглядываясь назад, мы бы разбили этот запрос на 100 м за один раз, но мы находимся в положении, когда он выполнялся в течение 24 часов, а размер файла журнала составляет 2 ТБ, что, по-видимому, является максимально допустимым размером для файла журнала.

База данных находится в режиме ПРОСТОГО восстановления.

Есть ли сохранение этого запроса? Или нам нужно просто перезапустить SQL Server и посмотреть, что произойдет? Будет ли база данных непригодной для использования? Есть ли что-нибудь, что мы можем сделать, чтобы убить это как можно более чисто?

Graeme
источник
Вы запускали его из SSMS? Просто отмени это. Отмена займет некоторое время. Примерно так долго, как он был запущен. Вы должны быть терпеливыми.
Папараццо
1
@Graeme Исходя из нашего опыта работы с базами данных на миллиард записей (у нас их несколько), иногда быстрее сохранить оставшиеся записи из таблицы жертвы, обрезать их, удалить, переименовать сохраненные записи в исходное имя и затем восстановить индексы, если таковые имеются ,
Антон Кроуглов
1
Как только вы очистите этот спид, я бы порекомендовал намного меньшие партии, чем 100 м, я обычно делаю 100 к 1 м. Кроме того, используйте свой первичный ключ в качестве предложения WHERE, чтобы выбрать записи для удаления, если это вообще возможно.
BradC
Truncate - ваш друг, удаляя большие объемы данных и пытаясь избежать проблем с журналами.
Jeff.Clark

Ответы:

14

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

Даже если это так, я всегда предпочитаю убить спид вручную (используйте sp_who2или, sp_WhoIsActiveчтобы найти спид, затем выполните a kill 59или что-либо еще). Вы также не можете проверить состояние отката, если не выполните явное KILL, см. Эту связанную ветку .

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

Чтобы увидеть статус отката, используйте

kill 59 with statusonly

К сожалению, я обнаружил, что это часто не показывает ничего полезного, просто «0% завершено». В этом случае вам придется использовать sp_who2и наблюдать за IO и процессором, чтобы убедиться, что он все еще что-то делает.

Что касается перезагрузки, это серьезный риск. Если spid активно откатывается (ЦП и IO меняются), то перезапуск SQL только переведет базу данных в автономный режим полностью, пока откат не будет полностью завершен (часы и часы). Но если процессор и ввод-вывод не движутся, то он может на самом деле очистить его сразу. В любом случае, это риск.

Один последний вариант, если все особенно страшно: если у вас есть резервная копия непосредственно перед началом удаления (и других обновлений базы данных не было) , то самый быстрый способ восстановления может состоять в простом удалении БД, перезапуске SQL и восстановление из резервной копии.

Если вы не можете удалить БД (или вы уже перезапустили экземпляр, а журнал ошибок sql предсказывает 24-часовое время восстановления), затем закройте службы SQL, удалите файлы MDF и LDF с диска, запустите SQL, удалите (призрачная) база данных и восстановление из резервной копии.

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

BradC
источник
3
Хороший совет, по поводу варианта восстановления. Страшно до чертиков, но все же хороший совет.
Макс Вернон,
2
Да, у нас был DBA, перезапускающий экземпляр в этом состоянии, что заставило нас выбирать между двумя очень плохими вариантами: отключиться на 18-24 часа или потерять данные, откатившись до начала запроса. Бизнес решил откатиться.
BradC
1
У нас есть полная резервная копия с 4 марта, которую мы восстановим в крайнем случае, если перезагрузка не сработает. К счастью, это достаточно статичная БД, которую мы просто хотели урезать. Спасибо за отзыв, очень помог
Грэм
4
@Graeme - FYI - вместо того, чтобы пытаться удалить 1,2 миллиарда строк, сделайте копию структуры таблицы, скопируйте строки, которые вы хотите сохранить, в новую таблицу, а затем удалите старую таблицу. Если вы добавите новый вопрос, спрашивающий, как это сделать, я покажу вам очень удобный способ, который намного быстрее, чем удаление 1,2 миллиарда строк.
Макс Вернон,
Мой ответ предполагает, что БД находится в режиме ПРОСТОГО восстановления. Если он находится в режиме FULL, вам также придется управлять огромными резервными копиями журнала.
BradC
8

НЕ ПЕРЕЗАПУСКАЙТЕ СЕРВЕР SQL. Это только продлит вашу агонию, так как произойдет восстановление, что приведет к откату или восстановлению всех незавершенных транзакций, включая ваше удаление.

Завершение сеанса, в котором выполняется удаление, приведет к откату, который также займет много времени.

Вы хотите посмотреть на следующий запрос, чтобы увидеть состояние операции:

SELECT des.session_id 
    , des.host_name
    , des.login_name
    , der.command
    , der.estimated_completion_time
    , der.blocking_session_id
    , der.last_wait_type
    , der.percent_complete
    , der.start_time
    , der.status
    , der.wait_resource
    , der.wait_type
    , der.wait_time
FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_exec_requests der ON des.session_id = der.session_id
WHERE des.session_id <> @@SPID
    AND des.is_user_process = 1
ORDER BY des.session_id;

percent_completeКолонка, и те , которые полагаются на него, например estimated_completion_time, заполняются только для следующих операций:

ALTER INDEX REORGANIZE
AUTO_SHRINK option with ALTER DATABASE
BACKUP DATABASE
DBCC CHECKDB
DBCC CHECKFILEGROUP
DBCC CHECKTABLE
DBCC INDEXDEFRAG
DBCC SHRINKDATABASE
DBCC SHRINKFILE
RECOVERY
RESTORE DATABASE
ROLLBACK
TDE ENCRYPTION

Таким образом, вы увидите, что этот столбец будет иметь смысл только в том случае, если вы уже отменили оператор delete, и он откатывается, или если вы уже перезапустили SQL Server и он находится в процессе восстановления.

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

Макс Вернон
источник
Хорошие запросы, но кажется маловероятным, что журнал увеличился бы, если бы удаление было заблокировано.
BradC
4
да. Я просто пытаюсь объяснить результат немного. Будущие читатели также могут увидеть это. На самом деле, я сомневаюсь, что мы услышим от ФП в ближайшее время. Он, вероятно, довольно занят.
Макс Вернон,