Ze skryptu wysłałem zapytanie takie jak to tysiące razy do mojej lokalnej bazy danych:
update some_table set some_column = some_value
Zapomniałem dodać część gdzie, więc ta sama kolumna została ustawiona na tę samą wartość dla wszystkich wierszy w tabeli i zostało to zrobione tysiące razy, a kolumna została zindeksowana, więc odpowiedni indeks był prawdopodobnie aktualizowany zbyt wiele razy .
Zauważyłem, że coś jest nie tak, ponieważ trwało to zbyt długo, więc zabiłem scenariusz. Od tamtej pory nawet zrestartowałem komputer, ale coś utknęło w tabeli, ponieważ proste zapytania trwają bardzo długo, a kiedy próbuję porzucić odpowiedni indeks, kończy się to z następującym komunikatem:
Lock wait timeout exceeded; try restarting transaction
To tabela innodb, więc zablokowana transakcja jest prawdopodobnie niejawna. Jak mogę naprawić tę tabelę i usunąć z niej zablokowaną transakcję?
źródło
SHOW FULL PROCESSLIST
?Odpowiedzi:
Miałem podobny problem i rozwiązałem go sprawdzając uruchomione wątki. Aby zobaczyć uruchomione wątki, użyj następującego polecenia w interfejsie wiersza poleceń mysql:
SHOW PROCESSLIST;
Może być również wysłany z phpMyAdmin, jeśli nie masz dostępu do interfejsu wiersza poleceń mysql.
Spowoduje to wyświetlenie listy wątków z odpowiednimi identyfikatorami i czasem wykonania, dzięki czemu możesz ZABIĆ wątki, których wykonanie zajmuje zbyt dużo czasu. W phpMyAdmin będziesz miał przycisk do zatrzymywania wątków za pomocą KILL, jeśli używasz interfejsu wiersza poleceń, po prostu użyj polecenia KILL, po którym następuje identyfikator wątku, jak w poniższym przykładzie:
KILL 115;
Spowoduje to zakończenie połączenia dla odpowiedniego wątku.
źródło
Możesz sprawdzić aktualnie realizowane transakcje za pomocą
SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`
Twoja transakcja powinna być jedną z pierwszych, ponieważ jest najstarszą na liście. Teraz po prostu weź wartość z
trx_mysql_thread_id
i wyślijKILL
polecenie:KILL 1234;
Jeśli nie masz pewności, która transakcja jest Twoja, powtarzaj bardzo często pierwsze zapytanie i zobacz, które transakcje trwają.
źródło
Sprawdź status InnoDB dla zamków
SHOW ENGINE InnoDB STATUS;
Sprawdź otwarte tabele MySQL
SHOW OPEN TABLES WHERE In_use > 0;
Sprawdź oczekujące transakcje InnoDB
SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`;
Sprawdź zależność zamka - co blokuje co
SELECT * FROM `information_schema`.`innodb_locks`;
Po zbadaniu powyższych wyników powinieneś być w stanie zobaczyć, co blokuje co.
Główna przyczyna problemu może również znajdować się w Twoim kodzie - sprawdź powiązane funkcje, szczególnie w przypadku adnotacji, jeśli używasz JPA, takiego jak Hibernate.
Na przykład, jak opisano tutaj , niewłaściwe użycie poniższej adnotacji może spowodować blokady w bazie danych:
źródło
SELECT * FROM information_schema.innodb_trx t JOIN information_schema.processlist p ON t.trx_mysql_thread_id = p.id
ujawniło winowajcę: Wątek blokujący pochodzi z mojego adresu IP ... Zapomniałem zamknąć konsolę debugowania, którą zostawiłem w trakcie transakcji ...Zaczęło się to przydarzać, gdy wzrosła wielkość mojej bazy danych i wykonywałem na niej wiele transakcji.
Prawda jest taka, że prawdopodobnie istnieje sposób na zoptymalizowanie zapytań lub bazy danych, ale wypróbuj te 2 zapytania, aby obejść problem.
Uruchomić to:
SET GLOBAL innodb_lock_wait_timeout = 5000;
A potem to:
SET innodb_lock_wait_timeout = 5000;
źródło
Kiedy ustanawiasz połączenie dla transakcji, uzyskujesz blokadę przed wykonaniem transakcji. Jeśli nie możesz zdobyć zamka, spróbuj przez jakiś czas. Jeśli nadal nie można uzyskać blokady, zgłaszany jest błąd przekroczenia czasu oczekiwania na blokadę. Dlaczego nie możesz uzyskać blokady, to fakt, że nie zamykasz połączenia. Tak więc, gdy próbujesz uzyskać blokadę po raz drugi, nie będziesz w stanie uzyskać blokady, ponieważ poprzednie połączenie jest nadal niezamknięte i utrzymuje blokadę.
Rozwiązanie: zamknij połączenie lub
setAutoCommit(true)
(zgodnie z projektem) zwolnij blokadę.źródło
Uruchom ponownie MySQL, działa dobrze.
ALE uważaj, jeśli takie zapytanie utknie, gdzieś jest problem:
LIKE %...%
itp.)Jak powiedział @syedrakib, działa, ale nie jest to długotrwałe rozwiązanie do produkcji.
Uwaga: ponowne uruchomienie może wpłynąć na dane o niespójnym stanie.
Możesz również sprawdzić, jak MySQL obsługuje twoje zapytanie za pomocą słowa kluczowego EXPLAIN i zobaczyć, czy jest tam coś, co przyspieszyło zapytanie (indeksy, złożone testy, ...).
źródło
Przejdź do procesów w mysql.
Więc widzę, że zadanie nadal działa.
Zabij określony proces lub poczekaj, aż proces się zakończy.
źródło
Napotkałem ten sam problem z komunikatem „aktualizacja”. Moim rozwiązaniem było po prostu wykonanie operacji dostępnych w phpMyAdmin dla tabeli. Zoptymalizowałem, opróżniłem i zdefragmentowałem tabelę (nie w tej kolejności). Nie ma potrzeby upuszczania tabeli i przywracania jej z kopii zapasowej. :)
źródło
Miałem ten sam problem. Myślę, że był to problem z zakleszczeniem w SQL. Możesz po prostu wymusić zamknięcie procesu SQL z Menedżera zadań. Jeśli to nie rozwiązało problemu, po prostu uruchom ponownie komputer. Nie musisz usuwać tabeli i ponownie ładować danych.
źródło
Miałem ten problem podczas próby usunięcia pewnej grupy rekordów (używając MS Access 2007 z połączeniem ODBC do MySQL na serwerze WWW). Zwykle usuwałbym pewne rekordy z MySQL, a następnie zastępowałem je zaktualizowanymi (kaskadowe usuwanie kilku powiązanych rekordów, co usprawnia usuwanie wszystkich powiązanych rekordów w celu usunięcia pojedynczego rekordu).
Próbowałem wykonać operacje dostępne w phpMyAdmin dla tabeli (optymalizacja, opróżnianie itp.), Ale otrzymywałem pozwolenie na błąd RELOAD, gdy próbowałem opróżnić. Ponieważ moja baza danych znajduje się na serwerze WWW, nie mogę ponownie uruchomić bazy danych. Przywracanie z kopii zapasowej nie wchodziło w grę.
Próbowałem uruchomić kwerendę usuwającą tę grupę rekordów na dostępie do mySQL cPanel w sieci. Otrzymałem ten sam komunikat o błędzie.
Moje rozwiązanie: Użyłem bezpłatnej przeglądarki MySQL Query Browser firmy Sun (Oracle) (którą wcześniej zainstalowałem na moim komputerze) i uruchomiłem tam zapytanie usuwające. Zadziałało od razu, problem rozwiązany. Następnie mogłem ponownie wykonać tę funkcję za pomocą skryptu Access przy użyciu połączenia ODBC Access to MySQL.
źródło
Problem w moim przypadku: wprowadzono pewne aktualizacje niektórych wierszy w ramach transakcji i przed zatwierdzeniem transakcji w innym miejscu te same wiersze były aktualizowane poza tą transakcją.
Ensuring that all the updates to the rows are made within the same transaction resolved my issue
.źródło
problem został rozwiązany w moim przypadku, zmieniając
delete
natruncate
problem- zapytanie:
delete from Survey1.sr_survey_generic_details mycursor.execute(query)
napraw- zapytanie:
truncate table Survey1.sr_survey_generic_details mycursor.execute(query)
źródło
Naprawione.
Upewnij się, że w zapytaniu nie ma niezgodnego typu danych. Wystąpił problem polegający na tym, że próbowałem „danych agenta przeglądarki użytkownika”
VARCHAR(255)
i miałem problem z tą blokadą, jednak gdy ją zmieniłemTEXT(255)
, naprawiłem go.Najprawdopodobniej jest to niezgodność typu danych.
źródło
Rozwiązałem problem, upuszczając stół i przywracając go z kopii zapasowej.
źródło