Wenn ich mysqldump --single-transaction verwende, sollte es laut den Dokumenten Tabellen mit Lesesperre leeren, um einen konsistenten Status zu erhalten, und dann eine Transaktion starten, und es sollten keine Writer warten.
Ich habe jedoch letzte Nacht die folgende Situation festgestellt:
Auszug aus der vollständigen Prozessliste anzeigen:
Hunderte von denen ...
Command: Query
Time: 291
State: Waiting for table flush
Info: insert into db_external_notification.....
dann das:
Command: Query
Time: 1204
State: Sending data
Info: SELECT /*!40001 SQL_NO_CACHE */ * FROM `db_external_notification`
und der Rest der Threads ist im Schlaf
Hat jemand eine Idee, worauf diese Beilagen warten? Ich sehe keine FLUSH-Tabellen oder DDL oder irgendetwas im Handbuch Erwähntes, das dazu führen kann, dass die Abfragen warten.
vollständiger Befehl mysqldump
mysqldump --quick --add-drop-table --single-transaction --master-data=2 -uxx -pxx dbname
Ich denke - schnell ist hier überflüssig, wahrscheinlich ein Überbleibsel aus früheren Zeiten. Dieses Skript ist sehr alt, sollte aber nichts schaden
mysqldump
? Verwenden Sie insbesondere--flush-logs
oder--master-data
...? Es gibt mögliche Wechselwirkungen zwischen den Optionen.Antworten:
Die Option --single-transaction von mysqldump funktioniert nicht
FLUSH TABLES WITH READ LOCK;
. Dadurch richtet mysqldump eine wiederholbare Lesetransaktion für alle Tabellen aus, die gesichert werden.In Ihrer Frage haben Sie angegeben, dass SELECT für die
db_external_notification
Tabelle von mysqldump Hunderte von INSERT-Befehlen für dieselbe Tabelle enthält. Warum passiert das ?Am wahrscheinlichsten ist eine Sperre für den gen_clust_index (besser bekannt als Clustered Index). Dieses Paradigma bewirkt, dass Daten- und Indexseiten für eine Tabelle nebeneinander existieren. Diese Indexseiten basieren entweder auf dem PRIMARY KEY oder einem automatisch generierten RowID-Index (falls es keinen PRIMARY KEY gibt).
Sie sollten dies erkennen können, indem Sie
SHOW ENGINE INNODB STATUS\G
eine Seite aus dem gen_clust_index mit einer exklusiven Sperre ausführen und suchen . Um INSERTs in eine Tabelle mit einem Clustered-Index einzufügen, ist eine exklusive Sperre für die Behandlung des BTREE des PRIMARY KEY sowie für die Serialisierung des auto_increment erforderlich.Ich habe dieses Phänomen bereits diskutiert
Aug 08, 2011
: Sind InnoDB Deadlocks exklusiv für INSERT / UPDATE / DELETE?Dec 22, 2011
: MySQL Deadlock - kann nicht normal neu gestartet werden?Dec 13, 2012
: MySQL InnoDB sperrt den Primärschlüssel beim Löschen auch in READ COMMITTEDUPDATE 2014-07-21 15:03 EDT
Bitte beachten Sie die Zeilen 614-617 Ihres PastBin
Beachten Sie, dass in Zeile 617 steht
Was sagt mir das? Sie haben einen PRIMARY KEY mit einem auto_increment aktiviert
id
.Ihr Maximum
id
für die Tabelledb_external_notification
war geringer als1252538391
beim Start von mysqldump. Wenn Sie subtrahieren1252538391
aus1252538405
, bedeutet dies , dass 14 oder mehr INSERT Befehle versucht. Intern müsste das auto_increment dieser Tabelle mindestens 14 Mal verschoben werden. Aufgrund der Verwaltung dieserid
Lücke kann jedoch nichts festgeschrieben oder sogar in den Protokollpuffer verschoben werden .Schauen Sie sich jetzt die Prozessliste in Ihrem PasteBin an. Sofern ich nicht falsch gezählt habe, habe ich 38 DB-Verbindungen gesehen, die ein INSERT ausgeführt haben (19 vor dem mysqldump-Prozess (Prozess-ID
6155315
), 19 danach). Ich bin sicher, dass 14 oder mehr dieser Verbindungen aufgrund der Verwaltung der Lücke auto_increment eingefroren sind.quelle
Die
--single-transaction
Optionmysqldump
führt eineFLUSH TABLES WITH READ LOCK
Aktion vor dem Starten des Sicherungsjobs durch, jedoch nur unter bestimmten Bedingungen. Eine dieser Bedingungen ist, wenn Sie auch die--master-data
Option angeben .Im Quellcode aus
mysql-5.6.19/client/mysqldump.c
Zeile 5797:Um eine solide Sperre für die genauen Binlog-Koordinaten zu erhalten, bevor die Transaktion mit wiederholbarem Lesen gestartet wird,
--master-data
löst die Option aus, dass diese Sperre abgerufen und dann freigegeben wird, sobald die Binlog-Koordinaten erhalten wurden.Tatsächlich
mysqldump
wird aFLUSH TABLES
gefolgt von a ausgeführt,FLUSH TABLES WITH READ LOCK
da in beiden Fällen die Lesesperre in Fällen, in denen das anfängliche Spülen einige Zeit dauert, schneller erreicht werden kann....jedoch...
Sobald es die binlog-Koordinaten erhalten hat,
mysqldump
gibt es eineUNLOCK TABLES
Anweisung aus, sodass aufgrund des von Ihnen gestarteten Flushs nichts blockiert werden sollte. Threads sollten auch nicht dasWaiting for table flush
Ergebnis der Transaktion sein, die gehaltenmysqldump
wird.Wenn Sie einen Thread im
Waiting for table flush
Status sehen, sollte dies bedeuten, dass dieFLUSH TABLES [WITH READ LOCK]
Anweisung ausgegeben wurde und zum Zeitpunkt des Starts der Abfrage noch ausgeführt wurde. Daher muss die Abfrage auf das Löschen der Tabelle warten, bevor sie ausgeführt werden kann. Bei der von Ihnen veröffentlichten Prozesslistemysqldump
wird aus derselben Tabelle gelesen, und die Abfrage wurde eine Weile ausgeführt, die blockierenden Abfragen wurden jedoch nicht so lange blockiert.Dies alles deutet darauf hin, dass etwas anderes passiert ist.
In Bug # 44884 wird ein langjähriges Problem mit der
FLUSH TABLES
internen Funktionsweise erläutert .Ich wäre nicht überrascht, wenn das Problem weiterhin besteht.Ich wäre überrascht, wenn dieses Problem jemals "behoben" würde, da es sich um ein sehr komplexes Problem handelt, das in einer Umgebung mit hoher Parallelität praktisch unmöglich zu beheben ist Das Reparieren birgt ein erhebliches Risiko, etwas anderes zu beschädigen oder neues, anderes und immer noch unerwünschtes Verhalten zu erzeugen.Es ist wahrscheinlich, dass dies die Erklärung für das ist, was Sie sehen.
Speziell:
Wenn eine Abfrage mit langer Laufzeit für eine Tabelle ausgeführt wird und ein Problem auftritt
FLUSH TABLES
,FLUSH TABLES
wird die Abfrage blockiert, bis die Abfrage mit langer Laufzeit abgeschlossen ist.Darüber hinaus werden alle Abfragen, die nach der
FLUSH TABLES
Ausgabe beginnen, blockiert, bis dieFLUSH TABLES
abgeschlossen ist.Wenn Sie die
FLUSH TABLES
Abfrage beenden, werden die blockierenden Abfragen weiterhin für die ursprüngliche Abfrage mit langer Laufzeit blockiert, die dieFLUSH TABLES
Abfrage blockiert hat , daFLUSH TABLES
diese Tabelle (die eine oder Darüber hinaus wird die lange laufende Abfrage noch geleert, und diese anstehende Leerung wird stattfinden, sobald die lang laufende Abfrage abgeschlossen ist - jedoch nicht vorher.Die wahrscheinliche Schlussfolgerung hier ist, dass ein anderer Prozess - vielleicht ein anderer mysqldump oder eine schlecht beratene Abfrage oder ein schlecht geschriebener Überwachungsprozess - versucht hat, eine Tabelle zu leeren.
Diese Abfrage wurde später durch einen unbekannten Mechanismus beendet oder abgelaufen, aber ihre Nachwirkungen blieben bestehen, bis
mysqldump
das Lesen aus der fraglichen Tabelle abgeschlossen war.Sie können diese Bedingung replizieren, indem Sie versuchen,
FLUSH TABLES
während eine lang laufende Abfrage ausgeführt wird. Starten Sie dann eine weitere Abfrage, die blockiert wird. Beenden Sie dann dieFLUSH TABLES
Abfrage, wodurch die letzte Abfrage nicht entsperrt wird. Beenden Sie dann die erste Abfrage oder lassen Sie sie beenden, und die letzte Abfrage wird erfolgreich ausgeführt.Nachträglich hat dies nichts zu tun:
Das ist normal, da
mysqldump --single-transaction
Probleme a auftretenSTART TRANSACTION WITH CONSISTENT SNAPSHOT
, die verhindern, dass Daten ausgegeben werden, die während des Speicherauszugs geändert wurden. Ohne das wären die zu Beginn erhaltenen Binlog-Koordinaten bedeutungslos, da das--single-transaction
nicht das wäre, was es behauptet zu sein. Dies sollte in keiner Weise mit demWaiting for table flush
Problem zusammenhängen, da diese Transaktion offensichtlich keine Sperren enthält.quelle
Ich habe eine Funktionsanfrage gesendet: https://support.oracle.com/epmos/faces/BugDisplay?id=27103902 .
Ich habe auch einen Patch gegen 5.6.37 geschrieben, der die gleiche Methode wie die Kombination von --single-transaction --master-data mit --single-transaction --slave-data verwendet und ohne Gewähr bereitgestellt wird. Benutzung auf eigene Gefahr.
Ich habe es mit dem folgenden Prozess mit Slaves für einen sehr beschäftigten Master unter Verwendung vieler InnoDB-Tabellen mit FK-Beziehungen getestet:
Der Patch-Einreichungsprozess von Oracle ist ziemlich intensiv, weshalb ich diesen Weg gegangen bin. Ich kann mit Percona und / oder MariaDB versuchen, es zu integrieren.
quelle