Co się stanie, jeśli nie zatwierdzisz transakcji w bazie danych (powiedzmy, SQL Server)?

108

Załóżmy, że mam zapytanie:

begin tran
-- some other sql code

A potem zapominam o zatwierdzeniu lub wycofaniu.

Co się stanie, jeśli inny klient spróbuje wykonać zapytanie?

Charbela
źródło

Odpowiedzi:

148

Dopóki nie ZATWIERDZISZ ani nie ROLLBACK transakcji, jest ona nadal „uruchomiona” i potencjalnie zawiera blokady.

Jeśli klient (aplikacja lub użytkownik) zamknie połączenie z bazą danych przed zatwierdzeniem, wszelkie nadal działające transakcje zostaną wycofane i zakończone.

marc_s
źródło
1
mmm, ok, rozumiem, że to tworzy jakiś rodzaj blokady. Nie byłem pewien, czy zamknięcie połączenia rzeczywiście wyprowadzi mnie z tego stanu. problem polegał na tym, że otrzymywałem błąd, kiedy próbowałem popełnić błąd. teraz zamknąłem połączenie i wszystko działało.
Charbel
12
Uwaga dodatkowa: Jeśli używasz Management Studio, zamknięcie okna zapytania spowoduje zamknięcie połączenia
Joe Phillips,
3
@BradleyDotNET: tak, zdecydowanie
marc_s
2
Należy pamiętać, że SQL Server Management Studio domyślnie zatwierdza automatycznie po zamknięciu okna zapytania / połączenia.
Nuno
1
Należy pamiętać, że gdy klient zamyka połączenie, gdy transakcja jest aktywna, nie zawsze jest ona wycofywana - zależy to od klienta i bazy danych. Np. Gdy aplikacja Java zamyka połączenie z bazą danych Oracle, wszelkie otwarte połączenia są automatycznie zatwierdzane.
AviD,
38

Możesz tego spróbować samemu, co powinno pomóc ci poczuć, jak to działa.

Otwórz dwa okna (zakładki) w Management Studio, każde z nich będzie miało własne połączenie z sql.

Teraz możesz rozpocząć transakcję w jednym oknie, zrobić coś takiego jak wstawianie / aktualizowanie / usuwanie, ale jeszcze nie zatwierdzać. następnie w drugim oknie możesz zobaczyć, jak wygląda baza danych spoza transakcji. W zależności od poziomu izolacji tabela może być zablokowana do momentu zatwierdzenia pierwszego okna lub możesz (nie) zobaczyć, co zrobiła do tej pory inna transakcja itp.

Baw się różnymi poziomami izolacji i nie wyświetlaj podpowiedzi, aby zobaczyć, jak wpływają one na wyniki.

Zobacz także, co się stanie, gdy wyrzucisz błąd w transakcji.

Bardzo ważne jest, aby zrozumieć, jak to wszystko działa, w przeciwnym razie niejednokrotnie będziesz zaskoczony tym, co robi sql.

Baw się dobrze! GJ.

gjvdkamp
źródło
ok, ale czy transakcja zostanie zapisana w celu zalogowania przynajmniej przed wydaniem zatwierdzenia? Na przykład, powiedzmy, że chcę rozpocząć transakcję, uruchom polecenie wstawiania i „zrób coś innego” przed wykonaniem zatwierdzenia. czy moje polecenie wstawiania zostanie zapisane w celu logowania? w ten sposób, jeśli serwer ulegnie awarii przed wykonaniem zatwierdzenia… może wrócić do miejsca, w którym był i mogę po prostu wydać zatwierdzenie później (za każdym razem, gdy skończę robić „coś innego”).
user1870400
16

Transakcje mają przebiegać całkowicie lub wcale. Jedynym sposobem zakończenia transakcji jest zatwierdzenie, każdy inny sposób spowoduje wycofanie.

Dlatego jeśli rozpoczniesz, a następnie nie zatwierdzisz, zostanie wycofana po zamknięciu połączenia (ponieważ transakcja została zerwana bez oznaczenia jako zakończona).

Piskvor opuścił budynek
źródło
Tak powinno być, ale nie zawsze tak jest.
FalcoGer
... takie jak MySQL MyISAM, który nie obsługuje transakcji, jasne.
Piskvor opuścił budynek
3

zależy od poziomu izolacji transakcji przychodzącej.

Wyjaśnienie izolacji transakcji SQL

Xhalent
źródło
6
Zachowanie transakcji nie zależy od poziomu izolacji. Liczba blokad, które mogą powodować, tak.
marc_s
Jestem prawie pewien, jakie dane można odczytać przez połączenie, jest zdecydowanie zależne od poziomu izolacji. Jeśli masz izolację ustawioną na READ UNCOMMITTED, możesz odczytać dane, które nie zostały jeszcze zatwierdzone i mogą w rzeczywistości zostać wycofane w pewnym momencie ścieżki, ale zapewnia to brak blokady. Jeśli jako poziom izolacji ustawiłeś READ COMMITTED, nie możesz odczytać niezatwierdzonych wierszy - drugi klient zawiesi się, chyba że użyjesz SNAPSHOT.
Xhalent
2

Kiedy otwierasz transakcję, nic samo się nie blokuje. Ale jeśli wykonasz jakieś zapytania wewnątrz tej transakcji, w zależności od poziomu izolacji, niektóre wiersze, tabele lub strony zostaną zablokowane, więc wpłynie to na inne zapytania, które próbują uzyskać do nich dostęp z innych transakcji.

czerwona koniczyna
źródło
1

Przykład transakcji

rozpocznij tran t

Twoje instrukcje sql

jeśli wystąpił błąd rollback tran tt else commit tran tt

Dopóki nie wykonałeś commita trans tt, dane nie zostaną zmienione

user3386471
źródło
1
Zwróć uwagę, że nazewnictwo transakcji jest nie tylko zbędne w MS SQL, ale może dawać fałszywe poczucie kontroli. BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Yna przykład nie działa. Zobacz stackoverflow.com/questions/1273376/…
0

Oprócz potencjalnych problemów z blokowaniem, które możesz spowodować, zauważysz również, że dzienniki transakcji zaczynają rosnąć, ponieważ nie można ich obciąć poza minimalną wartość LSN dla aktywnej transakcji, a jeśli używasz izolacji migawki, Twój magazyn wersji w tempdb będzie się powiększał podobne powody.

Możesz użyć, dbcc opentranaby zobaczyć szczegóły najstarszej otwartej transakcji.

Martin Smith
źródło
0

Każda niezakończona transakcja pozostawi serwer zablokowany, a inne zapytania nie będą wykonywane na serwerze. Musisz albo wycofać transakcję, albo ją zatwierdzić. Zamknięcie SSMS spowoduje również zakończenie transakcji, co pozwoli na wykonanie innych zapytań.

Josh Moorish
źródło
-4

Zachowanie nie jest zdefiniowane, więc musisz jawnie ustawić zatwierdzenie lub wycofanie:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

„Jeśli tryb automatycznego zatwierdzania jest wyłączony i połączenie zostanie zamknięte bez jawnego zatwierdzania lub cofania ostatnich zmian, wykonywana jest niejawna operacja COMMIT”.

Hsqldb dokonuje wycofania

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

wynik jest

2011-11-14 14: 20: 22,519 główne INFO [SqlAutoCommitExample: 55] [AutoCommit włączone = false] 2011-11-14 14: 20: 22,546 główne INFO [SqlAutoCommitExample: 65] [Znaleziono 0 # użytkowników w bazie danych]

Bernd Schatz
źródło
2
Może tak być w przypadku Oracle (nie mam pojęcia), ale pytający pyta o MS-SQL
PaulG
Pierwszy cytat dotyczy sterownika JDBC, a nie serwera.
djechlin