Wydaje się, że duże zapytanie do usunięcia zostało zawieszone

10

Uruchomiliśmy zapytanie usuwania w bazie danych z wierszami o wartości 1,8 miliarda. To usunięcie spowoduje usunięcie 1,2 mld wierszy.

Z perspektywy czasu podzielilibyśmy to zapytanie na 100 m jednocześnie, ale jesteśmy w pozycji, w której działa ono przez 24 godziny, a plik dziennika ma 2 TB, co wydaje się być maksymalnym dozwolonym rozmiarem pliku dziennika.

Baza danych jest w trybie odzyskiwania SIMPLE.

Czy jest jakieś zapisywanie tego zapytania? Czy też musimy po prostu zrestartować SQL Server i zobaczyć, co się stanie? Czy baza danych będzie bezużyteczna? Czy jest coś, co możemy zrobić, aby zabić to tak czysto, jak to możliwe?

Graeme
źródło
Czy uruchomiłeś go z SSMS? Po prostu anuluj. Anulowanie potrwa chwilę. Niby o ile długo działa. Musisz być cierpliwy.
paparazzo
1
@Graeme Z naszego doświadczenia z bazami danych zawierającymi miliardy rekordów (prowadzimy kilka z nich) czasami czasem jest szybciej zapisywać pozostałe rekordy z tabeli ofiar, obcinać je, usuwać, zmieniać nazwy zapisanych rekordów z powrotem na pierwotną nazwę, a następnie przywracać indeksy, jeśli takie istnieją .
Anton Krouglov,
1
Gdy wyczyścisz ten pająk, polecam dużo mniejsze partie niż 100 m, zwykle robię od 100 do 1 m. Użyj również klucza podstawowego jako klauzuli WHERE, aby wybrać rekordy do usunięcia, jeśli to w ogóle możliwe.
BradC,
Truncate jest Twoim przyjacielem podczas usuwania dużych ilości danych i próbowania uniknięcia problemów z logowaniem.
Jeff.Clark

Odpowiedzi:

14

Przede wszystkim sprawdź dziennik błędów SQL, aby sprawdzić, czy rzeczywiście osiągnął maksymalny rozmiar dziennika. Jeśli tak, zapytanie nie ma szans na zakończenie, prawdopodobnie jest już w stanie wycofania.

Nawet jeśli tak jest, zawsze wolę zabić spid ręcznie (użyj sp_who2lub, sp_WhoIsActiveaby znaleźć spid, a następnie zrób coś kill 59innego). Nie możesz również sprawdzić stanu wycofania, chyba że zrobisz jawny ZABÓJ, zobacz ten powiązany wątek .

Ponieważ jest to usunięcie, a nie aktualizacja lub wstawka, możesz mieć szczęście i stwierdzić, że natychmiast się wycofuje. Jeśli nie, cofnięcie może zająć tak długo (lub dłużej), jak w przypadku tego miejsca.

Aby zobaczyć stan wycofania, użyj

kill 59 with statusonly

Niestety często stwierdziłem, że nie pokazuje nic użytecznego, a jedynie „0% ukończenia”. W takim przypadku będziesz musiał użyć sp_who2IO i procesora, aby zobaczyć, czy nadal coś robi.

Jeśli chodzi o ponowne uruchomienie, jest to poważne ryzyko. Jeśli spid aktywnie się wycofuje (procesor i operacje wejścia / wyjścia zmieniają się), wówczas ponowne uruchomienie SQL spowoduje całkowite wyłączenie bazy danych do czasu całkowitego wycofania (godziny i godziny). Ale jeśli procesor i we / wy się nie poruszają, może to od razu wyczyścić. Tak czy inaczej, jest to ryzyko.

Jedna ostatnia opcja, jeśli sprawy są szczególnie tragiczne: jeśli masz kopię zapasową tuż przed rozpoczęciem usuwania (a nie było innych aktualizacji bazy danych ) , najszybszym sposobem na odzyskanie może być po prostu usunięcie bazy danych, ponowne uruchomienie SQL i przywracanie z kopii zapasowej.

Jeśli nie możesz upuścić bazy danych (lub jeśli zrestartowałeś już instancję, a dziennik błędów sql przewiduje 24-godzinny czas odzyskiwania), zamknij usługi SQL, usuń pliki MDF i LDF z dysku, uruchom SQL, upuść (ghost) baza danych i przywróć z kopii zapasowej.

Oczywiście spróbowałbyś tego, gdyby była to baza danych przetwarzania zaplecza, z którą użytkownicy nie wchodziliby w interakcję.

BradC
źródło
3
Dobra rada na temat opcji przywracania. Przerażające jak diabli, ale wciąż dobra rada.
Max Vernon,
2
Tak, mieliśmy DBA ponownie uruchomiło instancję w tym stanie, co zmusiło nas do wyboru między dwiema bardzo złymi opcjami: być wyłączonym przez 18-24 godzin lub stracić dane, cofając się przed rozpoczęciem zapytania. Firma zdecydowała się wycofać.
BradC,
1
Mamy pełną kopię zapasową od 4 marca, którą przywrócimy w ostateczności, jeśli ponowne uruchomienie nie zadziała. Na szczęście jest to wystarczająco statyczny DB, który chcieliśmy tylko przyciąć. Dziękuję za opinię, bardzo pomocna
Graeme
4
@Graeme - FYI - zamiast próbować usunąć 1,2 miliarda wierszy, wykonaj kopię struktury tabeli, skopiuj wiersze, które chcesz zachować, do nowej tabeli, a następnie upuść starą tabelę. Jeśli dodasz nowe pytanie z pytaniem, jak to zrobić, mogę pokazać ci bardzo zręczny sposób, który jest znacznie szybszy niż usuwanie 1,2 miliarda wierszy.
Max Vernon,
Moja odpowiedź zakłada, że ​​db jest w trybie odzyskiwania SIMPLE. Jeśli jest w trybie PEŁNYM, będziesz musiał także zarządzać ogromnymi kopiami zapasowymi dziennika tran.
BradC,
8

NIE PONOWNIE URUCHAMIAJ SERWERA SQL. To tylko przedłuży twoją agonię, ponieważ nastąpi odzyskiwanie, które przywróci lub powtórzy wszelkie niezakończone transakcje, w tym twoje usunięcie.

Zabicie sesji, w której działa usuwanie, spowoduje wycofanie, które również zajmie dużo czasu.

Chcesz spojrzeć na następujące zapytanie, aby zobaczyć stan operacji:

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;

percent_completeKolumna, a te, które polegają na tym, jak estimated_completion_timesą wypełniane tylko dla następujących operacji:

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

Tak więc zobaczysz, że ta kolumna będzie miała znaczenie tylko wtedy, gdy anulowałeś już instrukcję usuwania i jest ona wycofywana lub jeśli ponownie uruchomiłeś SQL Server i jest on w trakcie odzyskiwania.

Jeśli blocking_session_idkolumna zawiera liczbę, oznacza to, że inna sesja blokuje operację usuwania. Jeśli ta sesja blokuje operację usuwania od momentu jej rozpoczęcia, możesz być w stanie anulować operację bez konieczności cofania.

Max Vernon
źródło
Dobre zapytania, ale wydaje się mało prawdopodobne, że dziennik urósłby, gdyby usunięcie zostało zablokowane.
BradC,
4
tak. Próbuję tylko trochę wyjaśnić wynik. Przyszli czytelnicy również mogą to zobaczyć. Wątpię, czy w najbliższym czasie usłyszymy od OP. Prawdopodobnie jest bardzo zajęty.
Max Vernon