La query di eliminazione di grandi dimensioni sembra essere stata bloccata


10

Abbiamo eseguito una query di eliminazione su un database con 1,8 miliardi di righe. Questa eliminazione eliminerebbe 1,2 miliardi di righe.

Con il senno di poi, avremmo suddiviso questa query in 100m alla volta, ma siamo in una posizione in cui è stata in esecuzione per 24 ore e il file di registro è a 2 TB che sembra essere la dimensione massima consentita per un file di registro.

Il database è in modalità di recupero SEMPLICE.

C'è qualche salvataggio di questa query? Oppure dobbiamo semplicemente riavviare SQL Server e vedere cosa succede? Il database sarà inutilizzabile? C'è qualcosa che possiamo fare per eliminarlo nel modo più pulito possibile?


L'hai eseguito da SSMS? Basta annullarlo. Ci vorrà un po 'per annullare. Mi piace finché è in esecuzione. Devi essere paziente.
paparazzo,

1
@Graeme Dalla nostra esperienza con database di miliardi di record (ne stiamo eseguendo un paio) è talvolta più veloce salvare i record rimanenti dalla tabella delle vittime, troncarli, eliminarli, rinominare i record salvati con il nome originale e quindi ripristinare gli indici se presenti .
Anton Krouglov

1
Dopo aver eliminato questo spid, consiglierei lotti molto più piccoli di 100m, di solito faccio da 100k a 1m. Inoltre, utilizzare la chiave primaria come clausola WHERE per selezionare i record da eliminare, se possibile.
BradC

Troncare è il tuo amico quando si eliminano grandi quantità di dati e si cerca di evitare problemi di registro.
Jeff Clark

Risposte:


14

Prima di tutto, controlla il log degli errori SQL per vedere se ha effettivamente raggiunto una dimensione massima per il registro. In tal caso, la query non ha alcuna speranza di essere completata, probabilmente è già in uno stato di rollback.

Anche se lo è, preferisco sempre uccidere lo spid manualmente (usa sp_who2o sp_WhoIsActiveper trovare lo spid, quindi fai uno kill 59o qualunque cosa). Inoltre, non puoi controllare lo stato del rollback a meno che tu non faccia un KILL esplicito, vedi questo thread correlato .

Poiché si tratta di un'eliminazione e non di un aggiornamento o inserimento, potresti essere molto fortunato e scoprire che esegue immediatamente il rollback. In caso contrario, potrebbe essere necessario il tempo (o più lungo) per il rollback come ha fatto per arrivare a questo punto.

Per visualizzare lo stato del rollback, utilizzare

kill 59 with statusonly

Purtroppo, ho scoperto che questo spesso non mostra nulla di utile, solo uno "0% completo". In tal caso, dovrai utilizzare sp_who2e guardare l'IO e la CPU per vedere se sta ancora facendo qualcosa.

Per quanto riguarda il riavvio, questo è un grave rischio. Se lo spid sta eseguendo il rollback attivo (CPU e IO stanno cambiando), il riavvio di SQL metterà il database in modalità offline solo fino al termine del rollback (ore e ore). Ma se la CPU e l'IO non si muovono, potrebbe in effetti cancellarlo immediatamente. Ad ogni modo, è un rischio.

Un'ultima opzione, se le cose sono particolarmente terribili: se hai un backup appena prima dell'inizio dell'eliminazione (e non ci sono stati altri aggiornamenti al db) , il modo più veloce per recuperare potrebbe essere semplicemente quello di eliminare il DB, riavviare SQL e ripristino dal backup.

Se non riesci a eliminare il DB (o se hai già riavviato l'istanza e il log degli errori sql prevede un tempo di recupero di 24 ore), quindi chiudere i servizi SQL, eliminare i file MDF e LDF dal disco, avviare SQL, rilasciare il database (fantasma) e ripristina dal backup.

Ovviamente tenteresti solo che se si trattasse di un database di elaborazione back-end con cui gli utenti non interagiscono.


3
Un buon consiglio sull'opzione di ripristino. Spaventoso da morire, ma comunque un buon consiglio.
Max Vernon,

2
Sì, abbiamo avuto un DBA che riavviava un'istanza in questa condizione, il che ci ha costretto a decidere tra due opzioni pessime: essere inattivi per 18-24 ore o perdere i dati tornando indietro prima dell'inizio della query. L'azienda decise di ritirarsi.
BradC

1
Abbiamo un backup completo dal 4 marzo che ripristineremo come ultima risorsa se il riavvio non funziona. Fortunatamente è un DB abbastanza statico che volevamo solo tagliare. Grazie per il feedback, molto utile
Graeme

4
@Graeme - FYI - invece di provare a eliminare 1,2 miliardi di righe, crea una copia della struttura della tabella, copia le righe che desideri conservare nella nuova tabella, quindi rilascia la vecchia tabella. Se aggiungi una nuova domanda che ti chiede come farlo, posso mostrarti un modo molto fluido che è molto più veloce dell'eliminazione di 1,2 miliardi di righe.
Max Vernon

La mia risposta presuppone che il db sia in modalità di recupero SEMPLICE. Se è in modalità COMPLETA, dovrai gestire anche gli enormi backup del log tran.
BradC

8

NON RIAVVIARE SERVER SQL. Ciò prolungherà solo la tua agonia poiché avrà luogo il recupero, che eseguirà il rollback o ripeterà tutte le transazioni non completate, inclusa la tua eliminazione.

L'uccisione della sessione che esegue l'eliminazione comporterà un rollback, che richiederà anche molto tempo per il completamento.

Si desidera guardare la seguente query per vedere lo stato dell'operazione:

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_completecolonna e quelle che si basano su di essa, ad esempio estimated_completion_time, vengono popolate solo per le seguenti operazioni:

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

Quindi vedrai che la colonna è significativa solo se hai già annullato l'istruzione delete e sta tornando indietro o se hai già riavviato SQL Server ed è in fase di ripristino.

Se la blocking_session_idcolonna contiene un numero, ciò indica che l'altra sessione sta bloccando l'operazione di eliminazione. Se quella sessione ha bloccato l'operazione di eliminazione da quando è stata avviata, potresti essere in grado di annullare l'operazione senza che sia necessario eseguire il rollback.


Buone query, ma sembra abbastanza improbabile che il registro sarebbe diventato enorme se l'eliminazione fosse bloccata.
BradC

4
sì. Sto solo cercando di spiegare leggermente l'output. Anche i futuri lettori potrebbero vederlo. In effetti, dubito che tra poco avremo notizie dall'OP. Probabilmente è piuttosto impegnato.
Max Vernon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.