A consulta de exclusão grande parece ter congelado

10

Executamos uma consulta de exclusão em um banco de dados com 1,8 bilhões de linhas. Essa exclusão excluiria 1,2 bilhão de linhas.

Em retrospectiva, teríamos dividido essa consulta em 100m por vez, mas estamos em uma posição em que ela está sendo executada por 24 horas e o arquivo de log está em 2Tb, que parece ser o tamanho máximo permitido para um arquivo de log.

O banco de dados está no modo de recuperação SIMPLES.

Existe alguma salvando esta consulta? Ou precisamos apenas reiniciar o SQL Server e ver o que acontece? O banco de dados será inutilizável? Existe algo que possamos fazer para acabar com isso da maneira mais limpa possível?

Graeme
fonte
Você o executou no SSMS? Apenas cancele. Vai demorar um pouco para cancelar. Tipo, desde que esteja em execução. Você precisa ser paciente.
Paparazzo
11
@Graeme De nossa experiência com bancos de dados de bilhões de registros (estamos executando alguns deles), às vezes é mais rápido salvar os registros restantes da tabela de vítimas, truncá-los, excluí-los, renomeá-los para o nome original e restaurar os índices, se houver .
Anton Krouglov 8/03/2017
11
Depois de limpar esse espaço, eu recomendo lotes muito menores que 100m, geralmente eu faço de 100 a 1m. Além disso, use sua chave primária como sua cláusula WHERE para selecionar os registros para exclusão, se possível.
BradC
Truncar é seu amigo ao excluir grandes quantidades de dados e tentar evitar problemas de log.
precisa saber é o seguinte

Respostas:

14

Primeiro, verifique o log de erros do SQL para ver se ele realmente atingiu o tamanho máximo do log. Caso isso aconteça, a consulta não tem nenhuma esperança de concluir, provavelmente já está em um estado de reversão.

Mesmo que seja, eu sempre prefiro matar o spid manualmente (use sp_who2ou sp_WhoIsActivepara encontrar o spid, faça um kill 59ou o que for). Você também não pode verificar o status de reversão, a menos que faça um KILL explícito, consulte este tópico relacionado .

Como se trata de uma exclusão e não de uma atualização ou inserção, você pode ter muita sorte e descobrir que ela reverte imediatamente. Caso contrário, pode demorar tanto (ou mais) para retroceder quanto para chegar a esse ponto.

Para ver o status da reversão, use

kill 59 with statusonly

Infelizmente, descobri que isso frequentemente não mostra nada de útil, apenas um "0% concluído". Nesse caso, você precisará usar sp_who2e assistir o IO e a CPU para ver se ainda está fazendo alguma coisa.

Em relação à reinicialização, esse é um risco grave. Se o spid estiver revertendo ativamente (CPU e IO estão mudando), a reinicialização do SQL deixará o banco de dados offline apenas até que a reversão esteja completamente concluída (horas e horas). Mas , se a CPU e o IO não estiverem se movendo, é possível limpá-lo imediatamente. De qualquer maneira, é um risco.

Uma opção final, se as coisas forem especialmente ruins: se você tiver um backup imediatamente antes do início da exclusão (e não houve outras atualizações no banco de dados) , a maneira mais rápida de recuperar pode ser simplesmente descartar o banco de dados, reiniciar SQL e restauração do backup.

Se você não conseguir eliminar o banco de dados (ou se você já reiniciou a instância e o sql errorlog está prevendo um tempo de recuperação de 24 horas), encerre os serviços SQL, exclua os arquivos MDF e LDF do disco, inicie o SQL, solte o banco de dados (fantasma) e restaure a partir do backup.

Obviamente, você só tentaria se esse fosse um banco de dados de processamento de back-end com o qual os usuários não interagissem.

BradC
fonte
3
Bons conselhos, sobre a opção de restauração. Assustador como o inferno, mas ainda é um bom conselho.
Max Vernon
2
Sim, tivemos um DBA para reiniciar uma instância nessa condição, o que nos forçou a decidir entre duas opções muito ruins: ficar inativo por 18 a 24 horas ou perder dados revertendo antes do início da consulta. A empresa optou por reverter.
BradC
11
Temos um backup completo a partir de 4 de março, que restauraremos como último recurso se a reinicialização não funcionar. Felizmente, é um banco de dados estático o suficiente que estávamos querendo reduzir. Obrigado pelo feedback, muito útil
Graeme
4
@Graeme - FYI - em vez de tentar excluir 1,2 bilhões de linhas, faça uma cópia da estrutura da tabela, copie as linhas que deseja manter na nova tabela e solte a tabela antiga. Se você adicionar uma nova pergunta perguntando como fazê-lo, posso mostrar uma maneira muito mais rápida e rápida do que excluir 1,2 bilhões de linhas.
Max Vernon
Minha resposta assume que o banco de dados está no modo de recuperação SIMPLES. Se estiver no modo COMPLETO, você também precisará gerenciar os enormes backups de log de logs.
BradC
8

NÃO REINICIE O SERVIDOR SQL. Isso prolongará sua agonia apenas uma vez que a recuperação ocorrerá, o que reverterá ou refará todas as transações não concluídas, incluindo sua exclusão.

A morte da sessão que está executando a exclusão resultará em uma reversão, o que também levará muito tempo para ser concluído.

Você deseja examinar a seguinte consulta para ver o estado da operação:

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;

A percent_completecoluna e aqueles que dependem dela, como estimated_completion_time, são preenchidos apenas para as seguintes operações:

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

Portanto, você só verá essa coluna significativa se você já cancelou a instrução de exclusão e está revertendo ou se você já reiniciou o SQL Server e está em recuperação.

Se a blocking_session_idcoluna contiver um número, isso indica que outra sessão está bloqueando a operação de exclusão. Se essa sessão estiver bloqueando a operação de exclusão desde o início, você poderá cancelar a operação sem que ocorra qualquer reversão.

Max Vernon
fonte
Boas consultas, mas parece bastante improvável que o log aumentasse muito se a exclusão estivesse sendo bloqueada.
BradC
4
sim. Estou apenas tentando explicar um pouco a saída. Os futuros leitores também podem ver isso. De fato, duvido que tenhamos notícias do OP daqui a pouco. Ele provavelmente está bastante ocupado.
Max Vernon