Wyszło to z tego pokrewnego pytania , w którym chciałem wiedzieć, jak zmusić dwie transakcje do sekwencyjnego wykonywania w trywialnym przypadku (gdzie obie operują tylko w jednym rzędzie). Otrzymałem odpowiedź - użyj SELECT ... FOR UPDATEjako pierwszego wiersza obu transakcji - ale prowadzi to do problemu: jeśli pierwsza transakcja nigdy nie zostanie zatwierdzona lub wycofana, druga transakcja zostanie zablokowana na czas nieokreślony. innodb_lock_wait_timeoutZmienna określa liczbę sekund, po którym klient próbuje zrobić drugą transakcję zostanie powiedziane „Niestety, spróbuj ponownie” ... ale o ile mogę powiedzieć, że będą ponownie próbują aż do następnego uruchomienia serwera. Więc:
- Z pewnością musi istnieć sposób na wymuszenie,
ROLLBACKjeśli transakcja trwa wiecznie? Czy muszę uciekać się do używania demona do zabijania takich transakcji, a jeśli tak, to jak taki demon wyglądałby? - Jeśli połączenie zostanie przerwane w trakcie
wait_timeoutlub w trakcieinteractive_timeouttransakcji, czy transakcja zostanie wycofana? Czy istnieje sposób na przetestowanie tego z poziomu konsoli?
Wyjaśnienie : innodb_lock_wait_timeoutustawia liczbę sekund, przez które transakcja będzie czekać na zwolnienie blokady przed poddaniem się; chcę wymusić zwolnienie blokady.
Aktualizacja 1 : Oto prosty przykład, który pokazuje, dlaczego innodb_lock_wait_timeoutnie wystarczy, aby pierwsza transakcja nie została zablokowana przez pierwszą:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Przy ustawieniu domyślnym innodb_lock_wait_timeout = 50ta transakcja kończy się bez błędów po 55 sekundach. A jeśli dodasz znak UPDATEprzed SLEEPwierszem, a następnie zainicjujesz drugą transakcję od innego klienta, który próbuje przejść do SELECT ... FOR UPDATEtego samego wiersza, nastąpi przekroczenie limitu czasu drugiej transakcji, a nie tej, która zasnęła.
To, czego szukam, to sposób na wymuszenie końca spokojnego snu tej transakcji.
Aktualizacja 2 : W odpowiedzi na obawy hobodave dotyczące tego, jak realistyczny jest powyższy przykład, oto alternatywny scenariusz: DBA łączy się z serwerem na żywo i działa
START TRANSACTION
SELECT ... FOR UPDATE
gdzie druga linia blokuje wiersz, do którego aplikacja często zapisuje. Następnie DBA zostaje przerwane i odchodzi, zapominając o zakończeniu transakcji. Aplikacja zgrzyta, dopóki wiersz nie zostanie odblokowany. Chciałbym zminimalizować czas, w którym aplikacja utknęła w wyniku tego błędu.
ROLLBACKpierwszą transakcję, jeśli jej wykonanie zajmuje więcej niż nsekundy. Czy jest na to jakiś sposób?
MYSQLnie mam konfiguracji, która zapobiegałaby temu scenariuszowi. Ponieważ nie można zaakceptować zawieszenia serwera z powodu nieodpowiedzialności klientów. Nie miałem trudności ze zrozumieniem twojego pytania, jest ono również bardzo istotne.