Niedawno wykonałem zapytanie o aktualizację względem 100 000 rekordów. Zdałem sobie sprawę, że popełniłem błąd podczas działania zapytania i szybko odłączyłem kabel sieciowy.
Czy zapytanie o aktualizację?
- zatrzymać przetwarzanie i całkowicie wycofać?
- kontynuować przetwarzanie do zakończenia i zatwierdzić?
- zatrzymać przetwarzanie i zostawić zaktualizowaną tylko część wierszy docelowych?
sql-server
network
robocop
źródło
źródło
Odpowiedzi:
Jak wspomniano Nick i Martin, ostateczny stan twojego zapytania zależy od tego, czy SQL Server wie o wyciągnięciu kabla sieciowego przed zakończeniem zapytania. Z Books Online (choć uważam za interesujące, że istnieją równoważne tematy w 2000 , 2005 , 2008 i 2008 R2 , ale nie 2012 lub 2014):
(Nawiasem mówiąc, to słowo połączenia w drugim ostatnim zdaniu prawdopodobnie miało być transakcją . Nie wiem, jak się wycofuje połączenie).
W podobny sposób SQL Server może cofać lub ponawiać transakcje podczas odzyskiwania po nieoczekiwanym zamknięciu serwera, co będzie zależeć od stanu transakcji w momencie zamknięcia. Widziałem, jak ludzie używają tej taktyki, aby osiągnąć to, co próbowaliście zrobić (anulować transakcję), a kiedy serwer uruchomił się ponownie, znaczna część pracy została po prostu przerobiona (więc efekt netto ich gwałtownej reakcji był znacznie bliższy do zera niż się spodziewali).
Zamiast więc poddawać się temu, zamiast robić drastyczne rzeczy w panice, jak szarpanie kabla sieciowego lub wyłączanie maszyny, sugeruję w przyszłości lepszą dyscyplinę w uruchamianiu zapytań ad hoc względem ważnych systemów. Na przykład zamiast:
Masz to:
Następnie, jeśli aktualizacja rzeczywiście była poprawna, możesz podświetlić tę
COMMIT
część i uruchomić ją. Jeśli nie, możesz spokojnie zaznaczyć tęROLLBACK
część i uruchomić ją. Możesz nawet użyć dodatków, takich jak SSMS Tools Pack, aby edytowaćNew Query
szablon, aby uwzględnić ten szablon.Teraz nadal może sprawiać kłopoty w przypadku uruchomienia zapytania, a następnie nie zatwierdzenia ani wycofania, ponieważ teraz transakcja blokuje innych użytkowników. Jest to jednak lepsze niż nieodwracalne modyfikowanie danych.
I oczywiście, jak zawsze, masz kopię zapasową, na której możesz polegać.
źródło
@Aaron ma rację. Najlepszym rozwiązaniem jest utworzenie transakcji przed poleceniami. Jeśli nie pamiętasz, aby to zrobić, jedną z opcji jest przejście do
Tools-Options
ustawień i włączenieSET IMPLICIT_TRANSACTIONS
. Spowoduje to automatyczne rozpoczęcie transakcji, gdy tylko niektóre polecenia zostaną uruchomione. Obejmuje toUPDATE
,DELETE
itd. To wydaje się być dość pełna lista dowolnego polecenia, które"change"
coś.SELECT
jest również uwzględniony na liście iwill
rozpoczyna transakcję. Można zobaczyć pełną listę poleceń, które zaczynają transakcji będzie to ustawienie tutaj . Nie utworzy transakcji, jeśli została już uruchomiona. Wadą tego jest to, że będziesz musiał pamiętaćCOMMIT
po każdej dokonanej zmianie.UWAGA: W oparciu o sugestię @ Aarona zamierzam to podkreślić.
Zasadniczo
BEGIN
rezygnujesz z zapominania o transakcji i zepsucia czegoś, za zapominanieCOMMIT
o transakcji i zawieszenie jej, jeśli zostawisz ją otwartą, a następnie wyjdziesz na cały dzień. Testowałem właśnie zamykając okno zapytania, sądząc, że wycofuje ono moją transakcję, ale poprosiło mnie, jeśli chcę zatwierdzić lub wycofać transakcję.źródło
SELECT
będzie uruchomić transakcji (która jest również udokumentowane w linku pisał)myślę, że to naprawdę zależy:
jeśli polecenie dotrze już do serwera przed odłączeniem kabla sieciowego, polecenie nadal będzie działać normalnie.
jeśli masz TransactionScope (używany w .Net, nie jestem pewien, że w innych językach) do enkapsulacji wszystkich poleceń aktualizacji, prawdopodobnie możesz zatrzymać transakcję, która zostanie zatwierdzona, tylko jeśli transakcja nie została wykonana, ale nie ma gwarancji. .
źródło