Wyświetl otwarte transakcje w MySQL

98

Wykonałem kilka zapytań bez zatwierdzenia. Następnie aplikacja została zatrzymana.

Jak mogę wyświetlić te otwarte transakcje i zatwierdzić je lub anulować?

Alex
źródło
Myślę, że wszystkie Twoje transakcje są anulowane po rozłączeniu, ale nie jestem w 100% pewien.
Johan,
Jakiego rodzaju tabel używasz? MyISAM, InnoDB itp.?
cdeszaq
@cdeszaq, oczywiście nie MyISAM, nie ma transakcji, poza tym pytanie tak naprawdę nie ma nic wspólnego z tabelami.
Johan,
2
@Johan - podałem MyISAM tylko jako przykład typu tabeli. I to bardzo dużo robi znaczenia, bo nie wszystkie tabele że transakcje wsparcia zachowują się tak samo w odniesieniu do transakcji na utratę połączenia.
cdeszaq
@cdeszaq, Dokumentacja MySQL podaje coś zupełnie innego.
Johan,

Odpowiedzi:

61

Jak mogę wyświetlić te otwarte transakcje i zatwierdzić je lub anulować?

Nie ma otwartej transakcji, MySQL wycofa transakcję po rozłączeniu.
Nie możesz zatwierdzić transakcji (IFAIK).

Wyświetlasz wątki za pomocą

SHOW FULL PROCESSLIST  

Zobacz: http://dev.mysql.com/doc/refman/5.1/en/thread-information.html

To ci nie pomoże, ponieważ nie możesz wykonać transakcji z zerwanego połączenia.

Co się dzieje, gdy zrywa się połączenie
Z dokumentów MySQL: http://dev.mysql.com/doc/refman/5.0/en/mysql-tips.html

4.5.1.6.3. Wyłączanie MySQL Auto-Reconnect

Jeśli klient mysql utraci połączenie z serwerem podczas wysyłania oświadczenia, natychmiast i automatycznie spróbuje ponownie połączyć się z serwerem i ponownie wysłać oświadczenie. Jednak nawet jeśli mysql pomyślnie się połączy, pierwsze połączenie zostanie zakończone, a wszystkie poprzednie obiekty i ustawienia sesji zostaną utracone : tabele tymczasowe, tryb automatycznego zatwierdzania oraz zmienne zdefiniowane przez użytkownika i zmienne sesji. Ponadto wszelkie bieżące transakcje są wycofywane .

Takie zachowanie może być dla Ciebie niebezpieczne, jak w poniższym przykładzie, w którym serwer został wyłączony i uruchomiony ponownie między pierwszą a drugą instrukcją bez Twojej wiedzy:

Zobacz także: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html

Jak to zdiagnozować i naprawić
Aby sprawdzić automatyczne ponowne połączenie:

Jeśli nastąpi automatyczne ponowne połączenie (na przykład w wyniku wywołania mysql_ping ()), nie ma tego wyraźnego wskazania. Aby sprawdzić ponowne mysql_thread_id()połączenie, przed wywołaniem wywołaj, aby uzyskać oryginalny identyfikator połączenia mysql_ping(), a następnie zadzwoń mysql_thread_id()ponownie, aby sprawdzić, czy identyfikator się zmienił.

Upewnij się, że ostatnie zapytanie (transakcja) zostało zachowane w kliencie, aby w razie potrzeby móc je ponownie przesłać.
I wyłącz tryb automatycznego ponownego łączenia, ponieważ jest to niebezpieczne, zamiast tego zaimplementuj własne ponowne połączenie, aby wiedzieć, kiedy nastąpi spadek, i ponownie wysłać zapytanie.

Johan
źródło
To nie ma nic wspólnego z pytaniem. Ma to wpływ tylko na klienta mysql, a OP mówi o aplikacji ogólnej, co prawdopodobnie oznacza jego aplikację. Dodatkowo, skoro aplikacja wywołująca zatrzymała się, w jaki sposób mogłaby zachować transakcję w pamięci?
cdeszaq
@cdeszaq, to ​​wszystko ma związek z pytaniem. Aplikacja zwykle używa mysqld.dllAKA jako klienta. W pamięci przechowujesz instrukcję SQL, która zawiera pełną transakcję, dzięki czemu można ją odtworzyć, gdy połączenie zostanie przerwane. Lub przechowujesz go lokalnie na dysku, aby po ponownym uruchomieniu można go przesłać ponownie.
Johan,
W POKAŻ PEŁNĄ LISTĘ PROCESÓW jest wyświetlana tylko moja lista procesów. Więc myślę, że po prostu nie ma otwartych transakcji. Zabawne jest to, że wydaje się, że autoincrement_ids zostało utracone.
Alex
@alex oficjalna dokumentacja stwierdza, że ​​jest to udokumentowane zachowanie. Zobacz linki.
Johan,
Pięknie, Johan. Odpowiedział na pytanie i pokazał niektóre konsekwencje i rozwiązania tych konsekwencji, wszystko w kilku akapitach.
Gerard ONeill
55

Chociaż w przypadku nie będzie żadnej pozostałej transakcji, jak powiedział @Johan, możesz zobaczyć aktualną listę transakcji w InnoDB za pomocą poniższego zapytania, jeśli chcesz.

SELECT * FROM information_schema.innodb_trx\G

Z dokumentu :

Tabela INNODB_TRX zawiera informacje o każdej transakcji (z wyłączeniem transakcji tylko do odczytu) aktualnie wykonywanej wewnątrz InnoDB, w tym o tym, czy transakcja oczekuje na blokadę, kiedy rozpoczęła się transakcja oraz instrukcja SQL, którą transakcja jest wykonywana, jeśli taka istnieje.

Sanghyun Lee
źródło
Nie myśl, że istnieje sposób, aby stwierdzić, czy transakcje w tej tabeli należą do Twojego konkretnego żądania / sesji?
Captain Hypertext
1
Pamiętaj, że \Gmodyfikator na końcu jest przydatny tylko wtedy, gdy chcesz sformatować dane wyjściowe zapytania w narzędziu mysql CLI. Jeśli używasz narzędzia GUI, takiego jak Mysql Workbench, nie potrzebujesz go.
barell
30

Możesz użyć show innodb status(lubshow engine innodb status dla nowszych wersji mysql), aby uzyskać listę wszystkich działań aktualnie oczekujących w silniku InnoDB. W ścianie wyników będą ukryte transakcje i identyfikator wewnętrznego procesu, pod którym działają.

Nie będziesz w stanie wymusić zatwierdzenia lub wycofania tych transakcji, ale MOŻESZ zabić uruchamiający je proces MySQL, co w zasadzie sprowadza się do wycofania. Zabija połączenie procesów i powoduje, że MySQL usuwa bałagan po lewej stronie.

Oto, czego chciałbyś szukać:

------------
TRANSACTIONS
------------
Trx id counter 0 140151
Purge done for trx's n:o < 0 134992 undo n:o < 0 0
History list length 10
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 17004, OS thread id 140621902116624
MySQL thread id 10594, query id 10269885 localhost marc
show innodb status

W tym przypadku jest tylko jedno połączenie z silnikiem InnoDB w tej chwili (mój login, uruchamianie showzapytania). Gdyby ta linia była rzeczywistą transakcją połączenia / zablokowaną transakcją, którą chciałbyś zakończyć, zrobiłbyś następnie kill 10594.

Marc B.
źródło
Naprawdę nie ma potrzeby aktywnego przerywania połączenia po przekroczeniu limitu czasu, połączenie i tak zostanie zabite, a oczekująca transakcja z zerwanego połączenia nie może zostać zatwierdzona, więc można je przesłać ponownie bez obawy o powielenie.
Johan,
3
Lepiej jest zabijać zablokowane transakcje bez czekania na upłynięcie czasu na wyczyszczenie - w przeciwnym razie ryzykujesz zakleszczenie.
Marc B,
Ach tak, +1 za ten komentarz. Zapomniałem o tych impasach na minutę.
Johan,
@MarcB, dlaczego zmienili to na show engine innodb status?
Pacerier,
2

Używając tego zapytania, możesz zobaczyć wszystkie otwarte transakcje.

Lista wszystkich:

SHOW FULL PROCESSLIST  

jeśli chcesz zabić zawieszoną transakcję, skopiuj identyfikator transakcji i zakończ transakcję za pomocą tego polecenia:

KILL <id>    // e.g KILL 16543
M. Hamza Rajput
źródło