Große Löschabfrage scheint eingefroren zu sein

10

Wir haben eine Löschabfrage für eine Datenbank mit 1,8 Mrd. Zeilen ausgeführt. Dieses Löschen würde 1,2 Milliarden Zeilen löschen.

Im Nachhinein hätten wir diese Abfrage in jeweils 100 m aufgeteilt, aber wir befinden uns in einer Position, in der sie 24 Stunden lang ausgeführt wurde und die Protokolldatei 2 TB groß ist. Dies scheint die maximal zulässige Größe für eine Protokolldatei zu sein.

Die Datenbank befindet sich im EINFACHEN Wiederherstellungsmodus.

Gibt es eine Speicherung dieser Abfrage? Oder müssen wir nur den SQL Server neu starten und sehen, was passiert? Wird die Datenbank unbrauchbar? Können wir irgendetwas tun, um dies so sauber wie möglich abzutöten?

Graeme
quelle
Haben Sie es von SSMS ausgeführt? Einfach abbrechen. Das Abbrechen dauert eine Weile. Wie ungefähr so ​​lange es gelaufen ist. Du musst geduldig sein.
Paparazzo
1
@Graeme Aufgrund unserer Erfahrung mit Datenbanken mit Milliarden Datensätzen (wir führen einige davon aus) ist es manchmal schneller, verbleibende Datensätze aus der Opfertabelle zu speichern , abzuschneiden, zu löschen, gespeicherte Datensätze wieder in den ursprünglichen Namen umzubenennen und gegebenenfalls Indizes wiederherzustellen .
Anton Krouglov
1
Sobald Sie diese Spid gelöscht haben, würde ich viel kleinere Chargen als 100 m empfehlen. Normalerweise mache ich 100.000 bis 1 m. Verwenden Sie außerdem Ihren Primärschlüssel als WHERE-Klausel, um die zu löschenden Datensätze auszuwählen, sofern dies möglich ist.
BradC
Truncate ist Ihr Freund, wenn Sie große Datenmengen löschen und versuchen, Protokollprobleme zu vermeiden.
Jeff.Clark

Antworten:

13

Überprüfen Sie zunächst das SQL-Fehlerprotokoll, um festzustellen, ob es tatsächlich eine maximale Größe für das Protokoll erreicht hat. Wenn dies der Fall ist, hat die Abfrage keine Hoffnung auf Abschluss. Sie befindet sich wahrscheinlich bereits in einem Rollback-Status.

Selbst wenn es so ist, ziehe ich es immer vor, die Spid manuell zu töten (benutze sp_who2oder sp_WhoIsActivefinde die Spid, dann mache eine kill 59oder was auch immer). Sie können den Rollback-Status auch nur überprüfen, wenn Sie einen expliziten KILL ausführen. Weitere Informationen finden Sie in diesem verwandten Thread .

Da dies ein Löschen und kein Aktualisieren oder Einfügen ist, haben Sie möglicherweise großes Glück und stellen fest, dass es sofort zurückgesetzt wird. Wenn nicht, kann das Zurücksetzen genauso lange (oder länger) dauern wie bis zu diesem Punkt.

Verwenden Sie, um den Rollback-Status anzuzeigen

kill 59 with statusonly

Leider habe ich festgestellt, dass dies häufig nichts Nützliches anzeigt, nur eine "0% vollständig". In diesem Fall müssen Sie sp_who2die E / A und die CPU verwenden und beobachten, um festzustellen, ob sie noch etwas tun.

In Bezug auf den Neustart ist dies ein ernstes Risiko. Wenn das Spid aktiv zurückgesetzt wird (CPU und E / A ändern sich), wird beim Neustart von SQL die Datenbank nur vollständig offline geschaltet, bis das Rollback vollständig abgeschlossen ist (Stunden und Stunden). Aber , wenn die CPU und IO sind nicht bewegt, dann kann es in der Tat ist es sofort klar. In jedem Fall ist es ein Risiko.

Eine letzte Option, wenn die Dinge besonders schlimm sind: Wenn Sie ein Backup von kurz vor dem Start des Löschvorgangs haben (und es keine anderen Updates für die Datenbank gab) , besteht der schnellste Weg zur Wiederherstellung möglicherweise darin, die Datenbank einfach zu löschen und neu zu starten SQL und Wiederherstellung aus dem Backup.

Wenn Sie die Datenbank nicht löschen können (oder wenn Sie die Instanz bereits neu gestartet haben und das SQL-Fehlerprotokoll eine Wiederherstellungszeit von 24 Stunden vorhersagt), fahren Sie die SQL-Dienste herunter, löschen Sie die MDF- und LDF-Dateien von der Festplatte, starten Sie SQL und löschen Sie sie die (Geister-) Datenbank und Wiederherstellung aus dem Backup.

Natürlich würden Sie dies nur versuchen, wenn dies eine Back-End-Verarbeitungsdatenbank wäre, mit der Benutzer nicht interagiert haben.

BradC
quelle
3
Guter Rat zur Wiederherstellungsoption. Gruselig wie die Hölle, aber immer noch gute Ratschläge.
Max Vernon
2
Ja, wir hatten einen DBA, der eine Instanz in diesem Zustand neu startete, was uns dazu zwang, uns zwischen zwei sehr schlechten Optionen zu entscheiden: 18 bis 24 Stunden ausfallen oder Daten verlieren, indem wir vor dem Start der Abfrage einen Rollback durchführen. Das Unternehmen entschied sich für einen Rollback.
BradC
1
Wir haben ab dem 4. März ein vollständiges Backup, das wir als letzten Ausweg wiederherstellen werden, wenn der Neustart nicht funktioniert. Zum Glück ist es eine ausreichend statische Datenbank, die wir nur reduzieren wollten. Vielen Dank für das Feedback, sehr hilfreich
Graeme
4
@Graeme - FYI - Anstatt zu versuchen, 1,2 Milliarden Zeilen zu löschen, erstellen Sie eine Kopie der Tabellenstruktur, kopieren Sie die Zeilen, die Sie behalten möchten, in die neue Tabelle und löschen Sie die alte Tabelle. Wenn Sie eine neue Frage hinzufügen, in der Sie gefragt werden, wie es geht, kann ich Ihnen einen sehr raffinierten Weg zeigen, der viel schneller ist als das Löschen von 1,2 Milliarden Zeilen.
Max Vernon
Meine Antwort geht davon aus, dass sich die Datenbank im EINFACHEN Wiederherstellungsmodus befindet. Wenn es sich im FULL-Modus befindet, müssen Sie auch die riesigen Trans-Log-Backups verwalten.
BradC
8

Starten Sie den SQL Server nicht neu. Dies verlängert nur Ihre Qual, da eine Wiederherstellung stattfindet, die alle nicht abgeschlossenen Transaktionen, einschließlich Ihres Löschvorgangs, rückgängig macht oder wiederholt.

Wenn Sie die Sitzung beenden, in der der Löschvorgang ausgeführt wird, tritt ein Rollback auf, dessen Abschluss ebenfalls lange dauert.

Sie möchten sich die folgende Abfrage ansehen, um den Status der Operation anzuzeigen:

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;

Die percent_completeSpalte und diejenigen, die darauf angewiesen sind, z. B. estimated_completion_time, werden nur für die folgenden Vorgänge ausgefüllt:

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

Daher wird diese Spalte nur dann von Bedeutung sein, wenn Sie die Löschanweisung bereits abgebrochen haben und sie zurückgesetzt wird oder wenn Sie den SQL Server bereits neu gestartet haben und sich in der Wiederherstellung befinden.

Wenn die blocking_session_idSpalte eine Nummer enthält, bedeutet dies, dass eine andere Sitzung den Löschvorgang blockiert. Wenn diese Sitzung den Löschvorgang seit dem Start blockiert hat, können Sie den Vorgang möglicherweise abbrechen, ohne dass ein Rollback erforderlich ist.

Max Vernon
quelle
Gute Abfragen, aber es ist ziemlich unwahrscheinlich, dass das Protokoll sehr groß geworden wäre, wenn das Löschen blockiert worden wäre.
BradC
4
Ja. Ich versuche nur, die Ausgabe leicht zu erklären. Zukünftige Leser können dies auch sehen. Tatsächlich bezweifle ich, dass wir in der nächsten Zeit vom OP hören werden. Er ist wahrscheinlich ziemlich beschäftigt.
Max Vernon