La consulta de eliminación grande parece haberse congelado

10

Ejecutamos una consulta de eliminación en una base de datos con 1.800 millones de filas. Esta eliminación eliminaría 1.200 millones de filas.

En retrospectiva, habríamos dividido esta consulta en 100 m a la vez, pero estamos en una posición en la que se ha estado ejecutando durante 24 horas y el archivo de registro está en 2Tb, que parece ser el tamaño máximo permitido para un archivo de registro.

La base de datos está en modo de recuperación SIMPLE.

¿Hay alguna que guarde esta consulta? ¿O necesitamos simplemente reiniciar el SQL Server y ver qué sucede? ¿La base de datos será inutilizable? ¿Hay algo que podamos hacer para acabar con esto de la manera más limpia posible?

Graeme
fuente
¿Lo ejecutaste desde SSMS? Solo cancelalo. Tardará un tiempo en cancelar. Me gusta por mucho tiempo que ha estado funcionando. Necesitas ser paciente.
paparazzo
1
@Graeme Según nuestra experiencia con bases de datos de miles de millones de registros (estamos ejecutando un par de ellas), a veces es más rápido guardar los registros restantes de la tabla de víctimas, truncarlos, eliminarlos, cambiar el nombre de los registros guardados de nuevo al nombre original y luego restaurar los índices, si corresponde. .
Anton Krouglov
1
Una vez que haya limpiado este spid, recomendaría lotes mucho más pequeños que 100 m, generalmente hago de 100k a 1m. Además, use su clave principal como su cláusula WHERE para seleccionar los registros para su eliminación, si es posible.
BradC
Truncar es su amigo cuando elimina grandes cantidades de datos e intenta evitar problemas de registro.
Jeff.Clark

Respuestas:

14

En primer lugar, verifique el registro de errores de SQL para ver si realmente alcanzó un tamaño máximo para el registro. Si lo hizo, entonces la consulta no tiene esperanzas de completarse, probablemente ya esté en un estado de reversión.

Incluso si es así, siempre prefiero matar el spid manualmente (usar sp_who2o sp_WhoIsActivepara encontrar el spid, luego hacer un kill 59o lo que sea). Tampoco puede verificar el estado de reversión a menos que haga un KILL explícito, vea este hilo relacionado .

Como se trata de una eliminación, y no una actualización o inserción, puede ser muy afortunado y descubrir que retrocede de inmediato. De lo contrario, puede llevar tanto tiempo (o más) retroceder como lo hizo para llegar a este punto.

Para ver el estado de reversión, use

kill 59 with statusonly

Desafortunadamente, he encontrado que esto con frecuencia no muestra nada útil, solo un "0% completado". En ese caso, tendrá que usar sp_who2y observar el IO y la CPU para ver si todavía está haciendo algo.

En cuanto al reinicio, este es un grave riesgo. Si el spid está retrocediendo activamente (la CPU y la E / S están cambiando), reiniciar SQL solo desconectará la base de datos por completo hasta que la reversión haya finalizado por completo (horas y horas). Pero , si la CPU y la E / S no se mueven, de hecho puede eliminarlo de inmediato. De cualquier manera, es un riesgo.

Una última opción, si las cosas son especialmente graves: si tiene una copia de seguridad justo antes de que comenzara la eliminación (y no ha habido otras actualizaciones de la base de datos) , entonces la forma más rápida de recuperación puede ser simplemente soltar la base de datos, reiniciar SQL y restauración desde copia de seguridad.

Si no puede soltar la base de datos (o si ya reinició la instancia y el registro de errores de sql predice un tiempo de recuperación de 24 horas), cierre los servicios SQL, elimine los archivos MDF y LDF del disco, inicie SQL, suelte la base de datos (fantasma) y restaurar desde la copia de seguridad.

Obviamente, solo lo intentaría si fuera una base de datos de procesamiento de fondo con la que los usuarios no interactuaran.

BradC
fuente
3
Un buen consejo, sobre la opción de restauración. Miedo como el infierno, pero sigue siendo un buen consejo.
Max Vernon
2
Sí, tuvimos un DBA que reinició una instancia en esta condición, lo que nos obligó a decidir entre dos opciones muy malas: estar inactivo durante 18-24 horas, o perder datos volviendo a antes de que comenzara la consulta. El negocio decidió retroceder.
BradC
1
Tenemos una copia de seguridad completa del 4 de marzo que restauraremos como último recurso si el reinicio no funciona. Afortunadamente, es un DB suficientemente estático que solo queríamos recortar. Gracias por los comentarios, muy útil
Graeme
44
@Graeme - FYI - en lugar de tratar de eliminar 1.200 millones de filas, haga una copia de la estructura de la tabla, copie las filas que desea mantener en la nueva tabla y luego suelte la tabla anterior. Si agrega una nueva pregunta preguntando cómo hacerlo, puedo mostrarle una forma muy hábil que es mucho más rápida que eliminar 1.200 millones de filas.
Max Vernon
Mi respuesta asume que el db está en modo de recuperación SIMPLE. Si está en modo COMPLETO, también deberá administrar las enormes copias de seguridad de los registros de tránsito.
BradC
8

NO REINICIE EL SERVIDOR SQL. Esto solo prolongará su agonía, ya que se realizará la recuperación, lo que revertirá o rehacerá cualquier transacción no completada, incluida su eliminación.

Eliminar la sesión que está ejecutando la eliminación dará como resultado una reversión, que también tardará mucho tiempo en completarse.

Desea ver la siguiente consulta para ver el estado de la operación:

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;

La percent_completecolumna y las que dependen de ella, como estimated_completion_time, solo se rellenan para las siguientes operaciones:

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

Por lo tanto, solo verá que esa columna tiene sentido si ya ha cancelado la declaración de eliminación, y está retrocediendo, o si ya ha reiniciado SQL Server y está en recuperación.

Si la blocking_session_idcolumna contiene un número, eso indica que otra sesión está bloqueando la operación de eliminación. Si esa sesión ha estado bloqueando la operación de eliminación desde que comenzó, es posible que pueda cancelar la operación sin tener que realizar ninguna reversión.

Max Vernon
fuente
Buenas consultas, pero parece bastante improbable que el registro hubiera crecido enormemente si se hubiera bloqueado la eliminación.
BradC
44
si. Solo intento explicar un poco la salida. Los futuros lectores también pueden ver esto. De hecho, dudo que tengamos noticias del OP en el próximo tiempo. Es probable que esté bastante ocupado.
Max Vernon