Jeśli użyję mysqldump --single-transakcja, zgodnie z dokumentami powinna ona robić flush tabele z blokadą odczytu, aby uzyskać spójny stan, a następnie rozpocząć transakcję i żaden pisarz nie powinien czekać.
Jednak ostatniej nocy złapałem następującą sytuację:
fragment z pełnej listy procesów:
setki tych ...
Command: Query
Time: 291
State: Waiting for table flush
Info: insert into db_external_notification.....
wtedy to:
Command: Query
Time: 1204
State: Sending data
Info: SELECT /*!40001 SQL_NO_CACHE */ * FROM `db_external_notification`
a reszta wątków jest w trybie uśpienia
czy ktoś ma pojęcie na co czekają te wkładki? Nie widzę żadnych tabel FLUSH, DDL ani niczego wspomnianego w instrukcji, które mogą powodować, że zapytania będą czekać.
pełne polecenie mysqldump
mysqldump --quick --add-drop-table --single-transaction --master-data=2 -uxx -pxx dbname
Myślę, że - szybkie tutaj jest zbędne, prawdopodobnie pozostałość po wcześniejszych czasach, ten skrypt jest bardzo stary, ale nie powinien nic zranić
mysqldump
? W szczególności używasz--flush-logs
lub--master-data
...? Istnieją potencjalne interakcje między opcjami.Odpowiedzi:
--Single-transakcja opcja mysqldump nie robi
FLUSH TABLES WITH READ LOCK;
. Powoduje to, że mysqldump konfiguruje powtarzalną transakcję odczytu dla wszystkich zrzutowanych tabel.W swoim pytaniu stwierdziłeś, że SELECT mysqldump dla
db_external_notification
tabeli wstrzymuje setki poleceń INSERT dla tej samej tabeli. Dlaczego to się dzieje ?Najprawdopodobniej blokada na indeksie gen_clust_index (lepiej znanym jako Indeks klastrowany). Ten paradygmat powoduje współistnienie danych i stron indeksu dla tabeli. Te strony indeksowe są oparte na KLUCZU PODSTAWOWYM lub na automatycznie wygenerowanym indeksie RowID (w przypadku braku KLUCZA PODSTAWOWEGO).
Powinieneś być w stanie to zauważyć, uruchamiając
SHOW ENGINE INNODB STATUS\G
i szukając dowolnej strony z gen_clust_index, która ma wyłączną blokadę. Wprowadzanie WSTAWEK do tabeli z indeksem klastrowanym wymaga wyłącznej blokady do obsługi BTREE KLUCZA PODSTAWOWEGO, a także serializacji przyrostu automatycznego.Omawiałem to zjawisko wcześniej
Aug 08, 2011
: Czy zakleszczenia InnoDB są dostępne wyłącznie dla INSERT / UPDATE / DELETE?Dec 22, 2011
: Zakleszczenie MySQL - nie można normalnie zrestartować?Dec 13, 2012
: MySQL InnoDB blokuje klucz podstawowy podczas usuwania nawet w CZYTANIU ZOBOWIĄZANYMAKTUALIZACJA 2014-07-21 15:03 EDT
Proszę spojrzeć na linie 614-617 twojego PastBin
Zauważ, że wiersz 617 mówi
Co mi to mówi? Masz jakiś KLUCZ PODSTAWOWY z włączonym auto_increment
id
.Twoje maksimum
id
dla tabelidb_external_notification
było mniejsze niż w1252538391
momencie uruchomienia mysqldump. Gdy odejmiemy1252538391
od1252538405
, oznacza to, że 14 lub więcej poleceń INSERT zostały prób. Wewnętrznie musiałoby to przesunąć auto_increment tej tabeli co najmniej 14 razy. Jednak nic nie można zatwierdzić ani nawet wepchnąć do bufora dziennika z powodu zarządzania tąid
luką.Teraz spójrz na listę procesów z Twojego PasteBin. O ile nie przeliczyłem, zobaczyłem 38 połączeń DB wykonujących WSTAW (19 Przed procesem mysqldump (identyfikator procesu
6155315
), 19 Po). Jestem pewien, że 14 lub więcej takich połączeń zostało zawieszonych z powodu zarządzania luką auto_increment.źródło
--single-transaction
Opcjamysqldump
nie zrobićFLUSH TABLES WITH READ LOCK
przed rozpoczęciem zadania kopii zapasowej , ale tylko pod pewnymi warunkami. Jednym z tych warunków jest podanie--master-data
opcji.W kodzie źródłowym z
mysql-5.6.19/client/mysqldump.c
wiersza 5797:Aby uzyskać solidną blokadę dokładnych współrzędnych binlog przed rozpoczęciem transakcji z powtarzalnym odczytem,
--master-data
opcja wyzwala tę blokadę, a następnie zostaje zwolniona po uzyskaniu współrzędnych binlog.W rzeczywistości
mysqldump
robiFLUSH TABLES
następnie przezFLUSH TABLES WITH READ LOCK
bo robi obie rzeczy umożliwia odczyt blokady należy uzyskać szybciej w przypadku, gdy początkowa równo zajmuje trochę czasu....jednak...
Jak tylko uzyska współrzędne binlog,
mysqldump
wydajeUNLOCK TABLES
polecenie, więc nic nie powinno blokować w wyniku rozpoczętego koloru. Żaden wątek nie powinien byćWaiting for table flush
również wynikiem wstrzymanej transakcjimysqldump
.Gdy zobaczysz wątek w
Waiting for table flush
stanie, powinno to oznaczać, żeFLUSH TABLES [WITH READ LOCK]
instrukcja została wydana i nadal działała w momencie rozpoczęcia zapytania - więc zapytanie musi poczekać na opróżnienie tabeli, zanim będzie mogło zostać wykonane. W przypadku opublikowanej listy procesówmysqldump
czyta się z tej samej tabeli, a zapytanie działa od jakiegoś czasu, ale zapytania blokujące nie blokowały się tak długo.To wszystko sugeruje, że wydarzyło się coś innego.
Istnieje wewnętrzny problem wyjaśniony w błędzie nr 44884 dotyczący sposobu
FLUSH TABLES
działania wewnętrznego.Nie zdziwiłbym się, gdyby problem nadal występował,byłbym zaskoczony, gdyby problem ten został kiedykolwiek „rozwiązany”, ponieważ jest to bardzo złożony problem do rozwiązania - praktycznie niemożliwy do naprawienia w środowisku o wysokiej współbieżności - i każda próba naprawienie go niesie ze sobą znaczne ryzyko złamania czegoś innego lub stworzenia nowego, innego i wciąż niepożądanego zachowania.Wydaje się prawdopodobne, że będzie to wyjaśnienie tego, co widzisz.
Konkretnie:
jeśli masz długo działające zapytanie działające na tabeli i problem
FLUSH TABLES
,FLUSH TABLES
blokuje się, dopóki długo nie zakończy się zapytanie.dodatkowo wszelkie zapytania rozpoczynające się po
FLUSH TABLES
wydaniu będą blokowane do momentuFLUSH TABLES
zakończenia.dodatkowo, jeśli zabijesz
FLUSH TABLES
zapytanie, blokowane zapytania będą nadal blokować oryginalne długo działające zapytanie, które blokowałoFLUSH TABLES
zapytanie, ponieważ mimo że zabiteFLUSH TABLES
zapytanie nie zakończyło się, ta tabela (ta lub więcej, zaangażowany w długo działające zapytanie) jest wciąż w trakcie opróżniania, a to oczekujące opróżnienie nastąpi zaraz po zakończeniu długo działającego zapytania - ale nie wcześniej.Prawdopodobnym wnioskiem tutaj jest to, że inny proces - być może inny mysqldump, niewłaściwe zapytanie lub źle napisany proces monitorowania próbował opróżnić tabelę.
To zapytanie zostało następnie zabite lub przekroczone przez nieznany mechanizm, ale jego następstwa utrzymywały się aż do
mysqldump
zakończenia odczytu z tabeli, o której mowa.Możesz zreplikować ten warunek, próbując wykonać
FLUSH TABLES
podczas długotrwałego zapytania. Następnie uruchom kolejne zapytanie, które zostanie zablokowane. Następnie zabijFLUSH TABLES
zapytanie, które nie odblokuje ostatniego zapytania. Następnie zabij pierwsze zapytanie lub pozwól mu zakończyć, a ostatnie zapytanie zostanie pomyślnie uruchomione.W związku z tym nie ma to związku:
Jest to normalne, ponieważ
mysqldump --single-transaction
problemy aSTART TRANSACTION WITH CONSISTENT SNAPSHOT
, które uniemożliwiają zrzut danych, które zostały zmienione podczas zrzutu. Bez tego współrzędne binlog uzyskane na początku byłyby bez znaczenia, ponieważ--single-transaction
nie byłyby tym, za co się podaje. Nie powinno to być w żaden sposób związane zWaiting for table flush
problemem, ponieważ transakcja ta oczywiście nie zawiera żadnych blokad.źródło
Przesłałem żądanie funkcji: https://support.oracle.com/epmos/faces/BugDisplay?id=27103902 .
Napisałem również poprawkę do 5.6.37, która używa tej samej metody co - pojedyncza transakcja - kombinacja danych master z - pojedyncza transakcja - slave danych, która jest dostarczana bez gwarancji. Używaj na własne ryzyko.
Przetestowałem to w następujący sposób z niewolnikami do bardzo zajętego mistrza, używając wielu tabel InnoDB z relacjami FK:
Proces przesyłania poprawek przez Oracle jest dość intensywny, dlatego wybrałem tę drogę. Mogę spróbować z Perconą i / lub MariaDB, aby ją zintegrować.
źródło