web-dev-qa-db-fra.com

La grande requête de suppression semble avoir gelé

Nous avons exécuté une requête de suppression sur une base de données avec 1,8 milliard de lignes. Cette suppression supprimerait 1,2 milliard de lignes.

Avec le recul, nous aurions divisé cette requête en 100 m à la fois, mais nous sommes dans une position où elle fonctionne depuis 24 heures et le fichier journal est à 2 To, ce qui semble être la taille maximale autorisée pour un fichier journal.

La base de données est en mode de récupération SIMPLE.

Y a-t-il une sauvegarde de cette requête? Ou devons-nous simplement redémarrer SQL Server et voir ce qui se passe? La base de données sera-t-elle inutilisable? Y a-t-il quelque chose que nous puissions faire pour tuer cela aussi proprement que possible?

10
Graeme

Tout d'abord, vérifiez le journal des erreurs SQL pour voir s'il atteint réellement une taille maximale pour le journal. Si c'est le cas, la requête n'a aucun espoir de se terminer, elle est probablement déjà dans un état de restauration.

Même si c'est le cas, je préfère toujours tuer le spid manuellement (utilisez sp_who2 ou sp_WhoIsActive pour trouver le spid, puis faites un kill 59 ou peu importe). Vous ne pouvez pas non plus vérifier l'état de restauration, sauf si vous effectuez un KILL explicite, voir ce fil connexe .

Puisqu'il s'agit d'une suppression, et non d'une mise à jour ou d'un insert, vous pouvez être très chanceux et constater qu'il annule immédiatement. Sinon, il faudra peut-être autant de temps (ou plus) pour revenir en arrière que pour arriver à ce point.

Pour voir l'état de restauration, utilisez

kill 59 with statusonly

Malheureusement, j'ai constaté que cela ne montre souvent rien d'utile, juste un "0% terminé". Dans ce cas, vous devrez utiliser sp_who2 et regardez le IO et CPU pour voir s'il fait encore quelque chose.

Concernant le redémarrage, c'est un risque grave. Si le spid est activement rétrogradé (CPU et IO sont en train de changer), le redémarrage de SQL ne mettra la base de données hors ligne que jusqu'à ce que la restauration soit complètement terminée (heures et heures). Mais, si le CPU et IO sont pas en mouvement, alors il peut en fait l'effacer tout de suite. De toute façon, c'est un risque.

Une dernière option, si les choses sont particulièrement graves: Si vous avez une sauvegarde juste avant le début de la suppression (et qu'il n'y a pas eu d'autres mises à jour de la base de données) , alors le moyen le plus rapide de récupérer peut être de simplement supprimer la base de données, redémarrer SQL et restaurer à partir de la sauvegarde.

Si vous ne pouvez pas supprimer la base de données (ou si vous avez déjà redémarré l'instance et que le journal d'erreurs sql prévoit un temps de récupération de 24 heures), puis arrêtez les services SQL, supprimez le MDF et LDF fichiers depuis le disque, démarrez SQL, supprimez la base de données (fantôme) et restaurez à partir de la sauvegarde.

Évidemment, vous ne tenteriez que si c'était une base de données de traitement principale avec laquelle les utilisateurs n'interagissaient pas.

14
BradC

NE REDÉMARREZ PAS SERVEUR SQL. Cela ne fera que prolonger votre agonie puisque la récupération aura lieu, ce qui annulera ou recommencera toutes les transactions non terminées, y compris votre suppression.

La suppression de la session qui exécute la suppression entraînera une restauration, ce qui prendra également beaucoup de temps.

Vous souhaitez consulter la requête suivante pour voir l'état de l'opération:

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 colonne percent_complete Et celles qui en dépendent, telles que estimated_completion_time, Ne sont remplies que pour les opérations suivantes:

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

Vous ne verrez donc cette colonne que si vous avez déjà annulé l'instruction delete et qu'elle est annulée, ou si vous avez déjà redémarré SQL Server et qu'il est en cours de récupération.

Si la colonne blocking_session_id Contient un nombre, cela indique qu'une autre session bloque l'opération de suppression. Si cette session a bloqué l'opération de suppression depuis qu'elle a démarré, vous pouvez être en mesure d'annuler l'opération sans qu'aucune restauration ne soit nécessaire.

8
Max Vernon