1. Einleitung MDL-Sperren in MySQL haben schon immer Kopfschmerzen bereitet. Wenn wir über Sperren sprechen, bevorzugen wir normalerweise Lückensperren, nächste Schlüsselsperren, Zeilensperren usw. auf der unteren Ebene von INNODB, da sie leicht zu verstehen und zu beobachten sind. Wir wissen jedoch sehr wenig über MDL-Sperren, da sie wirklich schwer zu beobachten sind. Wir können sie nur sehen, indem wir bei einem Problem die Prozessliste anzeigen überprüfen. Das sogenannte Warten auf die Sperre der Tabellenmetadaten und andere Zustände sind einfach. Tatsächlich ist MDL LOCK ein sehr komplexes Subsystem in der oberen Schicht von MySQL und verfügt über einen eigenen Mechanismus zur Erkennung von Deadlocks. (Ungerichteter Graph?) Und was die Leute normalerweise sagen, ist, ob die Tabelle gesperrt ist, was tatsächlich darauf hinweist, was ihre Kritikalität und Ernsthaftigkeit zeigt. Der Autor hat auch einiges (die Spitze des Eisbergs) entsprechend seinen eigenen Bedürfnissen gelernt und er kann nicht den gesamten Code lesen, aber der Autor hat eine TICKET-Druckfunktion hinzugefügt, um den MDL LOCK-Sperrvorgang der Anweisung auszudrucken, damit er leichter studiert und recherchiert werden kann. Beginnen wir mit einigen Grundlagen und erzählen Ihnen dann, was geändert wurde. Schließlich wird jeder MDL-TYP getestet und analysiert. Wenn Sie nicht an den grundlegenden Konzepten und dem Hinzufügen von Druckfunktionen interessiert sind, können Sie direkt auf den fünften Teil des Sperrtests verweisen, aber wenn Sie die Grundlagen nicht verstehen, kann dies etwas schwierig erscheinen. Ich bin kürzlich auf einen Deadlock in MDL LOCK gestoßen. Im nächsten Artikel werde ich einen Fall beschreiben. Hier werde ich nur die Theorie betrachten. ----Auf der MySQL SERVER-Ebene wird MDL LOCK tatsächlich bereits in der Funktion open_table erworben. Man kann sagen, dass es sich um die früheste erworbene LOCK-Struktur handelt ----Früheste Erfassungsphase: THD::enter_stage: 'Tabellen öffnen' Aufrufstapelrahmen #0 open_table_get_mdl_lock (thd=0x7fffd0000df0, ot_ctx=0x7fffec06fb00, Tabellenliste=0x7fffd00067d8, Flags=0, mdl_ticket=0x7fffec06f950) unter /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:2789 #1 0x0000000001516e17 in open_table (thd=0x7fffd0000df0, Tabellenliste = 0x7fffd00067d8, ot_ctx = 0x7fffec06fb00) unter /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:3237 ----Fehlercode bei der Deadlock-Erkennung: { "ER_LOCK_DEADLOCK", 1213, "Beim Versuch, eine Sperre zu erhalten, wurde ein Deadlock festgestellt. Versuchen Sie, die Transaktion neu zu starten." }, FEHLER 1213 (40001): Beim Versuch, eine Sperre zu erhalten, wurde ein Deadlock festgestellt. Versuchen Sie, die Transaktion neu zu starten. Der Deadlock-Fehler von MDL LOCK ist genau derselbe wie der eines INNODB-Deadlocks, außer dass SHOW ENGINE INNODB keine Deadlock-Informationen hat. ----Beteiligter Code: mdl.h mdl.cc 2. Grundlegende wichtige Datenstrukturen (Klassen) und Konzepte 1. MDL-TYP MDL_INTENTION_EXCLUSIVE(IX) MDL_SHARED(S) MDL_SHARED_HIGH_PRIO(SH) MDL_SHARED_READ(SR) MDL_SHARED_WRITE(SW) MDL_SHARED_WRITE_LOW_PRIO(SWL) MDL_SHARED_UPGRADABLE (SU) MDL_SHARED_READ_ONLY (SRO) MDL_SHARED_NO_WRITE(SNW) MDL_SHARED_NO_READ_WRITE(SNRW) MDL_EXCLUSIVE(X) Jeder TYP wird später ausführlich getestet und die Erklärung im Quellcode wird am Ende gegeben. 2. MDL-NAMENSRAUM In MDL wird MDL_KEY durch NAMESPACE+DB+OBJECT_NAME dargestellt. Der sogenannte Namespace ist nicht wichtig. Nachfolgend sind die Kategorien von NAMESPACE aufgeführt - GLOBAL wird für die globale Lesesperre verwendet. - TABLESPACE ist für Tablespaces. - SCHEMA ist für Schemata (auch bekannt als Datenbanken). - TABLE ist für Tabellen und Ansichten. - FUNCTION ist für gespeicherte Funktionen. - PROCEDURE ist für gespeicherte Prozeduren. - TRIGGER steht für Auslöser. - EVENT ist für Event-Scheduler-Ereignisse. - COMMIT dient zum Aktivieren der globalen Lesesperre, um Commits zu blockieren. - USER_LEVEL_LOCK ist für Sperren auf Benutzerebene. - LOCKING_SERVICE steht für das Namensplugin RW-Lock Service 3. Klassifizierung implementieren Bereichssperre: entspricht im Allgemeinen der globalen MDL-Sperre, z. B. ist das Leeren einer Tabelle mit Lesesperre der Namespace-Bereich: GLOBAL Typ: S Objektsperre: Wie der Name schon sagt, MDL LOCK auf Objektebene, wie z. B. TABLE Hier sind die Kommentare im Quellcode: /** Hilfsstruktur, die definiert, wie verschiedene Arten von Sperren behandelt werden für einen bestimmten MDL_lock. In der Praxis verwenden wir nur zwei Strategien: „scoped“ Sperrstrategie für Sperren in den Namespaces GLOBAL, COMMIT, TABLESPACE und SCHEMA und „Objekt“-Sperrstrategie für alle anderen Namespaces. */ 4. MDL-Kompatibilitätsmatrix Zielfernrohrverriegelung: | Art der aktiven | Anfrage | Bereichssperre | Typ | IS(*) IX SX | ---------+------------------+ IST | + + + + | + + - - | + - + - | X | + - - - | Objektsperre: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ S | SCH | + + + + + + + + + - | SR | + + + + + + + + - - | SW | + + + + + + - - - - | + + + + + + - - - - | SO | + + + + + - + - - - | SRO | + + + - - - + - - - | + + - - - - - - - - | X | - - - - - - - - - - - | 5. Dauer der MDL und wann dauert die MDL? Dies bedarf keiner weiteren Erklärung, schauen Sie sich einfach die Kommentare zum Quellcode an MDL_STATEMENT: Sperren mit Anweisungsdauer werden am Ende automatisch freigegeben der Abrechnung oder Transaktion. MDL_TRANSACTION: Sperren mit Transaktionsdauer werden am Ende automatisch freigegeben der Transaktion MDL_EXPLICIT: Sperren mit expliziter Dauer überdauern das Ende der Anweisung und Transaktion. Sie müssen explizit durch den Aufruf von MDL_context::release_lock() freigegeben werden. 6. MDL LOCK FAST PATH (unaufdringlich) ODER SLOW PATH (aufdringlich) Der Zweck der Verwendung zweier unterschiedlicher Methoden besteht darin, die Implementierung der MDL-Sperre zu optimieren. Nachfolgend finden Sie die Kommentare im Quellcode. A) „unauffällige“ Schlossarten 1) Jeder Typ aus diesem Set sollte mit allen anderen kompatibel sein Typen aus dem Set (einschließlich sich selbst). 2) Diese Typen sollten für DML-Operationen üblich sein Unser Ziel ist die Optimierung der Beschaffung und Freigabe von Sperren dieser Typ durch Vermeidung komplexer Prüfungen und Manipulationen an m_waiting/ m_granted Bitmaps/Listen. Wir ersetzen sie durch eine Prüfung von und Inkrementieren/Dekrementieren von Ganzzahlzählern. Wir nennen die letztere Art der Erfassung/Freigabe „Fast Path“. Die Verwendung des „Fast Path“ reduziert die Größe des kritischen Abschnitts mit MDL_lock::m_rwlock Sperre im Normalfall und erhöht somit Skalierbarkeit. Der Betrag, um den der Erwerb/die Freigabe einer bestimmten Art "unauffällige" Sperre erhöht/verringert gepackten Zähler in MDL_lock::m_fast_path_state wird von dieser Funktion zurückgegeben. B) „aufdringliche“ Schlossarten 1) Gewährte oder ausstehende Sperren dieser Art sind inkompatibel mit einigen anderen Schlosstypen oder mit sich selbst. 2) Nicht üblich für DML-Operationen Diese Schlösser müssen immer mit Manipulationen an m_waiting/m_granted Bitmaps/Listen, d. h. wir müssen den „langsamen Pfad“ verwenden für sie. Darüber hinaus bei Vorhandensein von aktiven/ausstehenden Sperren von "aufdringliche" Menge, die wir mit "langsamen Pfaden" erwerben müssen, sogar Sperren von "unaufdringlicher" Typ. 7. MDL_request-Klasse Das heißt, die MDL LOCK-Anforderung muss nach der Anweisungsanalyse abgerufen werden. Anschließend wird die MDL LOCK-Anwendung im MDL-Subsystem über dieses Klassenobjekt ausgeführt, das wahrscheinlich die folgenden Eigenschaften enthält /** Typ der Metadatensperre. */ enum enum_mdl_type Typ; //Erforderlicher Typ/** Dauer der angeforderten Sperre. */ enum enum_mdl_duration Dauer; //Dauer/** Zeiger zur Teilnahme an der Liste der Sperranforderungen für diesen Kontext. */ MDL_request *next_in_list; //Implementierung einer doppelt verketteten Liste MDL_request **prev_in_list; /** Zeiger auf das Sperrticketobjekt für diese Sperranforderung. Nur gültig, wenn dieser Sperranforderung entsprochen wird. */ MDL_ticket *ticket; //Beachten Sie, dass bei erfolgreicher Anwendung (keine Wartezeit) auf ein tatsächliches TICKET verwiesen wird, andernfalls ist es NULL /** Eine Sperre wird basierend auf einem vollqualifizierten Namen und Typ angefordert. */ MDL_key key; //Beachten Sie, dass dies ein MDL_KEY-Typ ist. Das Wichtigste ist der oben erwähnte NAMESPACE+DB+OBJECT_NAME Die MDL_key-Klasse ist der eigentliche NAMESPACE+DB+OBJECT_NAME, der in ein Zeichenarray eingefügt wird. Er erscheint in MDL_LOCK und MDL_REQUEST. Privat: uint16 m_Länge; uint16 m_db_name_länge; char m_ptr[MAX_MDLKEY_LENGTH]; //Hier einfügen 8. MDL_ticket Wenn Sie MDL LOCK erwerben, müssen Sie wie bei einem Ticket ein Ticket an MDL_request zurückgeben. Wenn Sie warten, erhalten Sie kein MDL_context::acquire_lock Es kann beobachtet werden. Natürlich ist dies auch die Kategorie, die ich hauptsächlich beobachte. /** Zeiger zur Teilnahme an der Liste der Sperranforderungen für diesen Kontext. Kontext privat. Wie hier erklärt wird, ist die Bildung der verknüpften Liste im Kontext, der Thread privat ist*/ MDL_Ticket *nächstes_im_Kontext; MDL_ticket **vorheriger_im_Kontext; /** Hinweise zur Aufnahme in die Liste der erfüllten/ausstehenden Anfragen für das Schloss. Extern zugänglich. Wie hier erklärt ist die Bildung der verknüpften Liste in MDL_LOCK, die global ist */ MDL_Ticket *nächstes_in_Sperre; MDL_ticket **vorheriges_in_Sperre; /** Kontext des Besitzers des Metadaten-Sperrtickets. Extern zugänglich. Dies verweist offensichtlich auf den Besitzer des Tickets, nämlich MDL_context, ein Thread-Attribut*/ MDL_Kontext *m_ctx; /** Zeiger auf das Sperrobjekt für dieses Sperrticket. Extern zugänglich. Offensichtlich ist dies ein Zeiger auf MDL_LOCK*/ MDL_lock *m_lock; /** Zeigt an, dass das Ticket einer Sperre entspricht, die über den „Fast Path“ erworben wurde Algorithmus. Dies bedeutet insbesondere, dass er nicht in MDL_lock::m_granted bitmap/list und wird stattdessen berücksichtigt durch MDL_lock::m_fast_path_locks_granted_counter Dies gibt an, ob es sich um FAST PATH handelt. Aus den Kommentaren geht hervor, dass die Fast-Path-Methode die gewährte Bitmap und die verknüpfte Liste in MDL LOCK nicht belegt. Stattdessen wird ein Zähler m_fast_path_locks_granted_counter verwendet. So sind die Kosten auf jeden Fall geringer*/ bool m_ist_fast_path; /** Zeigt an, dass das Ticket einer Sperranforderung entspricht, die Speicher-Engine-Benachrichtigung während der Übernahme und erfordert Speicher-Engine-Benachrichtigung nach ihrer Veröffentlichung. */ bool m_hton_notified; 9. MDL_Sperre Jeder MDL_key entspricht einem MDL_lock, der die sogenannte GRANTED-Verknüpfungsliste und die WAIT-Verknüpfungsliste enthält. Angesichts der Komplexität können Sie direkt auf die Quellcodekommentare verweisen, die ebenfalls sehr detailliert sind. Hier sind die verschiedenen Eigenschaften, die ich beschrieben habe. /** Der Schlüssel des zu schützenden Objekts (Daten). */ MDL_key-Schlüssel; /** Liste der gewährten Tickets für dieses Schloss. */ Ticketliste m_zuerkannt; /** Tickets für Kontexte, die auf die Erlangung einer Sperre warten. */ Ticketliste m_waiting; 10. MDL_Kontext Dies ist eine sogenannte Kontextstruktur für die Interaktion des gesamten MySQL-Threads mit dem MDL-Sperrsubsystem. Sie enthält viele Methoden und Eigenschaften. Die Eigenschaften, die mich mehr interessieren, sind die folgenden: /** Wenn unsere Anfrage für eine Sperre geplant ist oder durch den Deadlock abgebrochen wird Detektor, das Ergebnis wird in dieser Klasse aufgezeichnet. */ MDL_warten m_warten; /** Listen aller über diese Verbindung erworbenen MDL-Tickets. Dies ist ein verknüpftes Listenarray mit unterschiedlichen MDL-Sperrdauern. Tatsächlich handelt es sich um eine verknüpfte Liste von MDL_STATEMENT, eine verknüpfte Liste von MDL_TRANSACTION und eine verknüpfte Liste von MDL_EXPLICIT*/ Ticketliste m_tickets[MDL_DURATION_END]; //Dies ist ein Zeiger der übergeordneten Klasse, der auf ein Objekt der untergeordneten Klasse zeigt, ein typisches Beispiel für das Überschreiben virtueller Funktionen. Tatsächlich zeigt er auf einen Thread/* Klasse THD: öffentlicher MDL_context_owner, öffentliche Query_arena, öffentlicher Open_tables_state */ MDL_Kontextbesitzer *m_owner; 11. MDL_wait In diesem Kurs geht es vor allem um den aktuellen Stand des Ticketerwerbs enum_wait_status m_wait_status; Enthalten EMPTY-Initialisierung GEWÄHRT Erfolg haben Opfer-Deadlock TIME-OUT GETÖTET GETÖTET 12. Warten auf das Ziel PSI_stage_info MDL_Schlüssel::m_Namespace_to_wait_state_name[NAMESPACE_END]= { {0, "Warten auf globale Lesesperre", 0}, {0, "Warten auf Sperre der Tablespace-Metadaten", 0}, {0, "Warten auf Schema-Metadatensperre", 0}, {0, "Warten auf Sperre der Tabellenmetadaten", 0}, {0, "Warten auf Sperre der gespeicherten Funktionsmetadaten", 0}, {0, "Warten auf Sperre der Metadaten der gespeicherten Prozedur", 0}, {0, "Warten auf Trigger-Metadatensperre", 0}, {0, "Warten auf Sperre der Ereignismetadaten", 0}, {0, "Warten auf Commit-Sperre", 0}, {0, "Benutzersperre", 0}, /* Mit altem Status kompatibel sein. */ {0, "Warten auf Sperren des Service-Locks", 0}, {0, "Warten auf Backup-Sperre", 0}, {0, "Warten auf Binlog-Sperre", 0} }; 3. MDL LOCK-Druckfunktion hinzufügen Der beste Weg, MDL LOCK zu studieren, besteht darin, sich den MDL-Sperr-, Upgrade- und Downgrade-Prozess anzueignen. Da der Quellcode zu groß ist, ist es unmöglich, alles abzudecken. UPDATE performance_schema.setup_consumers SET ENABLED = „JA“, wobei NAME = „global_instrumentation“ ist; UPDATE performance_schema.setup_instruments SET ENABLED = „JA“, wobei NAME = „Warten/Sperren/Metadaten/SQL/MDL“ ist; Wählen Sie * aus performance_schema.metadata_locks Wenn Sie jedoch sehen möchten, welche MDL-LOCKs eine Anweisung erhalten hat, scheint sie immer noch hilflos. Daher habe ich mdl.cc einen Funktionsprototyp wie folgt hinzugefügt /*p_ticket im Parameter*/ int mein_Druckticket(const MDL_ticket* p_ticket) Und in der Klasse mdl_ticket wird dieser Funktionsprototyp als Friend-Funktion hinzugefügt, da sonst die privaten Mitglieder nicht abgerufen werden können und die angegebene öffentliche Methode komplizierter ist. Freund in my_print_ticket(const MDL_ticket* p_ticket); Die folgenden Informationen zu MDL LOCK werden hauptsächlich abgerufen und im MySQL-Fehlerprotokoll gedruckt: Die Thread-ID wird über p_ticket->m_ctx->get_thd() abgerufen. Der Name der MDL-Sperrdatenbank wird über p_ticket->m_lock->key.db_name() abgerufen. Der Name des MDL-Sperrobjekts kann über p_ticket->m_lock->key.name() abgerufen werden. Der MDL-Sperrnamespace wird über p_ticket->m_lock->key.mdl_namespace() abgerufen. Der schnelle Pfad für die MDL-Sperre wird über p_ticket->m_is_fast_path abgerufen. Wenn ja, wird es ausgegeben, andernfalls nicht. Der MDL-Sperrtyp wird über p_ticket->m_type ermittelt. Die Dauer der MDL-Sperre wird über p_ticket->m_duration ermittelt. Die Ausgabeinformationen lauten wie folgt: 2017-08-03T07:34:21.720583Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T07:34:21.720601Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T07:34:21.720619Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:test 2017-08-03T07:34:21.720637Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T07:34:21.720655Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T07:34:21.720673Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_WRITE(SW) 2017-08-03T07:34:21.720692Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION Tatsächlich sind die Informationen denen in metadata_locks ähnlich. Dies ist hier die Thread-ID, die die ID aus show processlist ist, aber ich kann die Informationen zum Sperrenerwerbsverlauf abrufen. Ich habe hier kein LOCK_STATUS: GRANTED, aber ich kann es anhand der MDL_context::acquire_lock-Logik beurteilen. mysql> wähle * aus performance_schema.metadata_locks\G *************************** 1. Reihe *************************** OBJECT_TYPE: TABELLE OBJECT_SCHEMA: Test OBJEKTNAME: Test OBJECT_INSTANCE_BEGIN: 140734412907760 SPERRTYP: SHARED_WRITE LOCK_DURATION: TRANSAKTION LOCK_STATUS: GEWÄHRT QUELLE: sql_parse.cc:6314 Eigentümer-Thread-ID: 39 Eigentümer_Veranstaltungs-ID: 241 4. Fügen Sie an der entsprechenden Stelle eine Druckfunktion zur Beobachtung hinzu Da wir das Sperren, Upgraden und Downgraden von MDL LOCK untersuchen möchten, müssen wir deren Funktionseintrag finden und dann die Druckfunktion zur Beobachtung an der entsprechenden Position hinzufügen. Die Druckposition ist unten markiert und der größte Teil des Quellcodes wurde gelöscht. Bitte überprüfen Sie den Quellcode als Referenz. 1. Sperre: MDL_context::acquire_lock bool MDL_context::acquire_lock(MDL_request *mdl_request, ulong Sperrwartezeitüberschreitung) { if (mdl_request->ticket) //Ticket erfolgreich erhalten { /* Es ist uns gelungen, die Sperre ohne Wartezeit zu erlangen. MDL_lock, MDL_context und MDL_request wurden aktualisiert Dementsprechend können wir den Erfolg einfach zurückgeben. */ //REQUESET erhält TICKET erfolgreich, print returniert hier FALSE; } /* Unser Versuch, die Sperre zu erhalten, ohne zu warten, ist fehlgeschlagen. Als Ergebnis dieses Versuchs erhielten wir MDL_ticket mit m_lock Mitglied, das auf das entsprechende MDL_lock-Objekt zeigt, das hat MDL_lock::m_rwlock schreibgesperrt. */ //Nicht erfolgreicher Erwerb, trete der MDL_lock-Warteschlange bei lock= ticket->m_lock; Sperre->m_waiting.add_ticket(Ticket); will_wait_for(ticket); //Deadlock-Erkennung/* Für das Objekt liegt eine gemeinsame oder exklusive Sperre vor. */ DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait"); deadlock_finden(); //Ticket hier ausdrucken und in den Wartevorgang einsteigen, wenn (Sperre->Notification(Ticket) || Sperre->Verbindungsprüfung()) { } done_waiting_for(); //Warten Sie, bis der Wartegraph zur Deadlock-Erkennung angepasst ist und entfernen Sie die Wartekante (ungerichteter Graph) //Natürlich ist es hier nach einer Weile gelungen und der Status lautet GEWÄHRT DBUG_ASSERT(Wartestatus == MDL_wait::GRANTED); m_tickets[mdl_request->Dauer].push_front(Ticket); mdl_request->ticket = Ticket; mysql_mdl_set_status(Ticket->m_psi, MDL_Ticket::GEWÄHRT); //Hier wird das TICKET gedruckt, das durch das Warten auf die ANFRAGE erhalten wurde gibt FALSE zurück; } 2. Herabstufung: void MDL_ticket::downgrade_lock(enum_mdl_type new_type) void MDL_ticket::downgrade_lock(enum_mdl_type neuer_typ) { /* Erlaube nur Downgrades von EXCLUSIVE und SHARED_NO_WRITE. */ DBUG_ASSERT(m_type == MDL_EXCLUSIVE || m_type == MDL_SHARED_NO_WRITE); //Drucken Sie das TICKET vor dem Downgrade hier aus wenn (m_hton_notified) { mysql_mdl_set_status(m_psi, MDL_ticket::POST_RELEASE_NOTIFY); m_ctx->get_owner()->notify_hton_post_release_exclusive(&m_lock->key); m_hton_notified = falsch; mysql_mdl_set_status(m_psi, MDL_ticket::GEWÄHRT); } //Das Ende der Funktion verspricht die Ausgabe des herabgestuften TICKET } 3. Upgrade: MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,enum_mdl_type neuer_Typ, ulong lock_wait_timeout) bool MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket, enum_mdl_type neuer_Typ, ulong Sperre_Wartezeitüberschreitung) { MDL_REQUEST_INIT_BY_KEY(&mdl_neue_Sperranforderung, &mdl_ticket->m_lock->key, neuer_Typ, MDL_TRANSACTION); //Eine Anfrage erstellen //Der hier ausgedruckte TICKET-Typ, wenn (acquire_lock(&mdl_new_lock_request, lock_wait_timeout)) //Versuchen Sie, mit dem neuen LOCK_TYPE zu sperren DBUG_RETURN(TRUE); ist_neues_Ticket = ! hat_Sperre(mdl_svp, mdl_new_lock_request.ticket); Sperre = mdl_ticket->m_lock; //Es folgt eine Reihe von Wartungsarbeiten an MDL_LOCK und der sogenannten Zusammenführungsoperation./* Der folgende Code geht davon aus, dass wir auf den Sperrtyp „aufdringlich“ aktualisiert haben. */ DBUG_ASSERT(Sperre->ist_aufdringliche_Sperre(neuer_Typ)); /* Die erworbene und die ursprüngliche Sperre zusammenführen. @todo: Zu einer Methode wechseln. */ mysql_prlock_wrlock(&lock->m_rwlock); if (ist_neues_Ticket) { m_tickets[MDL_TRANSACTION].entfernen(mdl_new_lock_request.ticket); MDL_ticket::zerstören(mdl_new_lock_request.ticket); } //Der aktualisierte TICKET-Typ wird hier gedruckt DBUG_RETURN(FALSE); } Natürlich drucke ich jetzt nur an diesen Stellen. Bei Bedarf kann ich in Zukunft auch an anderen Stellen Funktionen hinzufügen. 5. Verschiedene MDL LOCK TYPE Sperrtests 1. MDL_INTENTION_EXCLUSIVE (IX) Diese Sperre wird bei vielen Vorgängen auftreten. Sie wird beispielsweise beim Ausführen eines beliebigen DML/DDL-Vorgangs ausgelöst. Tatsächlich fügen DML-Vorgänge wie DELETE/UPDATE/INSERT/FOR UPDATE eine IX-Sperre auf GLOBAL hinzu und sperren dann das Objekt. DDL-Anweisungen fügen mindestens eine IX-Sperre auf GLOBAL und eine IX-Sperre auf dem SCHEMA hinzu, zu dem das Objekt gehört. Die Sperre für dieses Objekt ist die durch DELETE ausgelöste GLOABL IX MDL LOCK. 2017-08-03T18:22:38.092100Z 3 [Hinweis] Test2:open_tables_for_query() 2017-08-03T18:22:38.092205Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T18:22:38.092242Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T18:22:38.092276Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:GLOBAL 2017-08-03T18:22:38.092310Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T18:22:38.092344Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:22:38.092380Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_STATEMENT 2017-08-03T18:22:38.092551Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Nachfolgend sehen Sie die GLOABLIX MDL LOCK und die SCHEMA-level MDL LOCK, die durch die ALETER-Anweisung ausgelöst werden. 2017-08-03T18:46:05.894871Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T18:46:05.894915Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T18:46:05.894948Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:GLOBAL 2017-08-03T18:46:05.894980Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T18:46:05.895012Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:46:05.895044Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_STATEMENT 2017-08-03T18:46:05.895076Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T18:46:05.895116Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T18:46:05.895147Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T18:46:05.895206Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T18:46:05.895243Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist: 2017-08-03T18:46:05.895276Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:SCHEMA 2017-08-03T18:46:05.895325Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T18:46:05.895357Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T18:46:05.895390Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T18:46:05.895421Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Dieses MDL LOCK gibt es also überall. Die einzige Frage ist, ob es kompatibel ist. Wenn es nicht kompatibel ist, wird es blockiert. Der IX-Typ von SCOPED ist grundsätzlich kompatibel, es sei denn, er trifft auf 2. MDL_SHARED(S) Diese Sperre wird im Allgemeinen in Flush-Tabellen mit Lesesperre verwendet. mysql> Tabellen mit Lesesperre leeren; Abfrage OK, 0 Zeilen betroffen (0,01 Sek.) 2017-08-03T18:19:11.603911Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T18:19:11.603947Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T18:19:11.603971Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:GLOBAL 2017-08-03T18:19:11.603994Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED(S) 2017-08-03T18:19:11.604045Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_EXPLICIT 2017-08-03T18:19:11.604073Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T18:19:11.604133Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T18:19:11.604156Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T18:19:11.604194Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:COMMIT 2017-08-03T18:19:11.604217Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED(S) 2017-08-03T18:19:11.604240Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_EXPLICIT 2017-08-03T18:19:11.604310Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Wir stellen fest, dass ihr Namensraum GLOBAL ist und COMMIT offensichtlich SCOPED LOCK ist und ihr TYPE S ist. Daher ist es offensichtlich, dass gemäß dem Kompatibilitätsprinzip 3. MDL_SHARED_HIGH_PRIO (SH) Dieses Schloss wird grundsätzlich von jedem häufig verwendet, aber Sie spüren es nicht. Beispielsweise verwenden wir normalerweise die desc-Operation Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ SCH | + + + + + + + + + - | mysql> Beschreibung test.testsort10; 2017-08-03T19:06:05.843277Z 4 [Hinweis] (acquire_lock) DIESES MDL-LOCK konnte erfolgreich erworben werden! 2017-08-03T19:06:05.843324Z 4 [Hinweis] (>MDL PRINT) Die Thread-ID ist 4: 2017-08-03T19:06:05.843359Z 4 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:06:05.843392Z 4 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort10 2017-08-03T19:06:05.843425Z 4 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:06:05.843456Z 4 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T19:06:05.843506Z 4 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_HIGH_PRIO(SH) 2017-08-03T19:06:05.843538Z 4 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:06:05.843570Z 4 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Dieser Typ hat eine höhere Priorität, ist aber mit X inkompatibel. Es ist auch leicht zu verstehen, dass beispielsweise der Desc-Vorgang während der Umbenennungsphase nicht ausgeführt werden kann. 4. MDL_SHARED_READ(SR) Diese Sperre wird im Allgemeinen aus Kompatibilitätsgründen bei nicht aktuellen Lese-Selects verwendet: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ SR | + + + + + + + + - - | mysql> wähle * aus test.testsort10, Limit 1; 2017-08-03T19:13:52.338764Z 4 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T19:13:52.338813Z 4 [Hinweis] (>MDL PRINT) Thread-ID ist 4: 2017-08-03T19:13:52.338847Z 4 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:13:52.338883Z 4 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort10 2017-08-03T19:13:52.338917Z 4 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:13:52.338950Z 4 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T19:13:52.339025Z 4 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_READ(SR) 2017-08-03T19:13:52.339062Z 4 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:13:52.339097Z 4 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Hier müssen wir noch erwähnen, dass wir gelegentlich auf Situationen stoßen, in denen die Auswahl blockiert ist (beispielsweise ist in einer bestimmten Phase von DDL eine Objekt-MDL-X-Sperre erforderlich). Wir müssen uns beschweren 5. MDL_SHARED_WRITE (SW) Diese Sperre wird im Allgemeinen verwendet, um die Tabelle (aktuell gelesen) für DELETE/UPDATE/INSERT/FOR UPDATE-Operationen zu sperren, mit Ausnahme von DDL-Operationen. Beachten Sie jedoch, dass DML-Operationen tatsächlich eine GLOBAL IX-Sperre haben. Wie bereits erwähnt, gilt diese Sperre nur für das Objekt. Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ SW | + + + + + + - - - - | mysql> wähle * aus test.testsort10, Limit 1 für Update; 2017-08-03T19:25:41.218428Z 4 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T19:25:41.218461Z 4 [Hinweis] (>MDL PRINT) Thread-ID ist 4: 2017-08-03T19:25:41.218493Z 4 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:25:41.218525Z 4 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort10 2017-08-03T19:25:41.218557Z 4 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:25:41.218588Z 4 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T19:25:41.218620Z 4 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_WRITE(SW) 2017-08-03T19:25:41.218677Z 4 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:25:41.218874Z 4 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 6. MDL_SHARED_WRITE_LOW_PRIO (SWL) Diese Sperre wird selten verwendet. Nur Quellcodekommentare Wird von DML-Anweisungen verwendet, die Tabellen und Verwendung der LOW_PRIORITY-Klausel Wird verwenden Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ + + + + + + - - - - | mysql> aktualisiere LOW_PRIORITY test.testsort10, setze id1=1000, wobei id1= 96282; 2017-08-03T19:32:47.433507Z 4 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T19:32:47.433521Z 4 [Hinweis] (>MDL PRINT) Thread-ID ist 4: 2017-08-03T19:32:47.433533Z 4 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:32:47.433547Z 4 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort10 2017-08-03T19:32:47.433560Z 4 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:32:47.433572Z 4 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T19:32:47.433594Z 4 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_WRITE_LOW_PRIO(SWL) 2017-08-03T19:32:47.433607Z 4 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:32:47.433620Z 4 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 7. MDL_SHARED_UPGRADABLE (SU) Diese Sperre wird normalerweise in der Anweisung ALTER TABLE verwendet. Sie kann auf SNW, SNRW, X hochgestuft werden, und zumindest die X-Sperre kann auf SU herabgestuft werden. Tatsächlich ist INNODB ONLINE DDL sehr abhängig davon, DML (SW) und SELECT (SR) werden nicht blockiert Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ SO | + + + + + - + - - - | Wir müssen die Kompatibilität untersuchen. Wir können sehen, dass (SELECT)SR (DML)SW alle in OBJECT LOCK zulässig sind. In SCOPED LOCK sind DML DDL zwar in GLOBAL gesperrt, aber ihre Typen sind alle IX. Daher blockiert diese SU-Sperre nicht die Lese- und Schreibvorgänge von DML/SELECT, die in die INNODB-Engine-Schicht gelangen. Sie ist die Grundlage von ONLINE DDL. Wenn sie nicht kompatibel ist, können Sie nicht in die INNODB-Engine-Schicht gelangen, geschweige denn in ONLINE DDL. Beachten Sie, dass ich ALGORITHM=INPLACE gesagt habe und LOCK nicht festlegen soll. (Für DDL-Operationen mit LOCK=DEFAULT oder ohne LOCK-Klausel verwendet MySQL die niedrigste Ebene Wie die folgende Aussage mysql> Tabelle ändern, testsort12, Spalte hinzufügen, int nicht null; Lassen Sie mich es kurz analysieren: 2017-08-03T19:46:54.781453Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK konnte erfolgreich erworben werden! 2017-08-03T19:46:54.781487Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T19:46:54.781948Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:46:54.781990Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T19:46:54.782026Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:46:54.782060Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_UPGRADABLE(SU) 2017-08-03T19:46:54.782096Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:46:54.782175Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T19:46:54.803898Z 3 [Hinweis] (upgrade_shared_lock)DIESE MDL-SCHLOSS wird aktualisiert 2017-08-03T19:46:54.804201Z 3 [Hinweis] (upgrade_shared_lock)DIESES MDL LOCK-Upgrade AUF 2017-08-03T19:46:54.804240Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T19:46:54.804254Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:46:54.804267Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T19:46:54.804280Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:46:54.804293Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ: MDL_EXCLUSIVE(X) 2017-08-03T19:46:54.804306Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:46:54.804319Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T19:46:54.855563Z 3 [Hinweis] (downgrade_lock)DIESE MDL-SPERRE führt zu einem Downgrade 2017-08-03T19:46:54.855693Z 3 [Hinweis] (downgrade_lock) zu dieser MDL-Sperre 2017-08-03T19:46:54.855706Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T19:46:54.855717Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:46:54.856053Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T19:46:54.856069Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:46:54.856082Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_UPGRADABLE(SU) 2017-08-03T19:46:54.856094Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:46:54.856214Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T19:47:00.260166Z 3 [Hinweis] (upgrade_shared_lock)DIESE MDL-SCHLOSS wird aktualisiert 2017-08-03T19:47:00.304057Z 3 [Hinweis] (upgrade_shared_lock)DIESES MDL LOCK Upgrade AUF 2017-08-03T19:47:00.304090Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T19:47:00.304105Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:47:00.304119Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T19:47:00.304132Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:47:00.304181Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_EXCLUSIVE(X) 2017-08-03T19:47:00.304196Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:47:00.304211Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T19:47:01.032329Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! Holen Sie sich zuerst die Tabelle testsort12 2017-08-03T19:46:54.781487 MDL_SHARED_UPGRADABLE erhalten (SU) 2017-08-03T19:46:54.804293 Upgrade MDL_EXCLUSIVE(X) 2017-08-03T19:46:54.855563 Downgrade MDL_SHARED_UPGRADABLE (SU) 2017-08-03T19:47:00.304057 Upgrade MDL_EXCLUSIVE(X) Denn egal was passiert, dieser Änderungsvorgang ist immer noch zeitaufwändig. Aus der Zeit können wir erkennen, dass die Zeit vom 03.08.2017, 19:46:54 Uhr, als das Downgrade abgeschlossen war, bis zum 03.08.2017, 19:47:00 Uhr tatsächlich die zeitaufwändigste ist. Tatsächlich ist dies der eigentliche Kopiervorgang, aber dieser Prozess befindet sich tatsächlich im MDL-SU-Modus, sodass DML/SELECT-Vorgänge nicht blockiert werden. 8. MDL_SHARED_NO_WRITE (SNW) SU kann auf SNW aktualisiert werden und SNW kann auf X aktualisiert werden, wie bereits zuvor zur Verwendung in ALGORITHM=COPY erwähnt, um die Datenkonsistenz zu schützen. Anfrage | Bewilligte Anfragen für Sperre Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ + + + - - - + - - - | Sie können sehen, dass SR funktioniert, SW jedoch nicht. Natürlich ist DML (SW) blockiert, während SELECT (SR) nicht blockiert ist. Im Folgenden gebe ich nur die wichtigsten Teile an. mysql> Tabelle ändern, testsort12, Spalte hinzufügen, ik int nicht null, ALGORITHMUS=KOPIEREN; 2017-08-03T20:07:58.413215Z 3 [Hinweis] (upgrade_shared_lock)DIESES MDL LOCK Upgrade AUF 2017-08-03T20:07:58.413241Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T20:07:58.413257Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T20:07:58.413273Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T20:07:58.413292Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T20:07:58.413308Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_NO_WRITE(SNW) 2017-08-03T20:07:58.413325Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T20:07:58.413341Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T20:08:25.392006Z 3 [Hinweis] (upgrade_shared_lock)DIESES MDL LOCK Upgrade AUF 2017-08-03T20:08:25.392024Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T20:08:25.392086Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T20:08:25.392159Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T20:08:25.392199Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T20:08:25.392214Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_EXCLUSIVE(X) 2017-08-03T20:08:25.392228Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T20:08:25.392242Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T20:07:58.413308 Habe MDL_SHARED_NO_WRITE erhalten (SNW) 2017-08-03T20:08:25.392006 Upgrade auf MDL_EXCLUSIVE(X) Die Zeit von 2017-08-03T20:07:58.413308 bis 2017-08-03T20:08:25.392006 ist die tatsächliche Kopierzeit. Es ist ersichtlich, dass während des gesamten Kopierzeitraums nur DML ausgeführt werden kann. 9. MDL_SHARED_READ_ONLY (SRO) Für die Anweisung LOCK TABLES READ Die Kompatibilität ist wie folgt Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ SRO | Blockiert DML (SW), aber SELECT (SR) ist weiterhin möglich. mysql> Sperrtabelle testsort12 lesen; Abfrage OK, 0 Zeilen betroffen (0,01 Sek.) 2017-08-03T21:08:27.267947Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T21:08:27.267979Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T21:08:27.268009Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T21:08:27.268040Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T21:08:27.268070Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T21:08:27.268113Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_READ_ONLY (SRO) 2017-08-03T21:08:27.268145Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T21:08:27.268175Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 10. MDL_SHARED_NO_READ_WRITE (SNRW) Für die Anweisung LOCK TABLES WRITE Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ + + - - - - - - - - | Es ist ersichtlich, dass DML (SW) und SELECT (SR) blockiert sind, nur SH noch verfügbar ist und DESC (SH) ebenfalls verfügbar ist. mysql> Tabelle sperren, Testsort12 schreiben; Abfrage OK, 0 Zeilen betroffen (0,00 Sek.) 2017-08-03T21:13:07.113347Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T21:13:07.113407Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T21:13:07.113435Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:GLOBAL 2017-08-03T21:13:07.113458Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T21:13:07.113482Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T21:13:07.113505Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_STATEMENT 2017-08-03T21:13:07.113604Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T21:13:07.113637Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T21:13:07.113660Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T21:13:07.113681Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T21:13:07.113703Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist: 2017-08-03T21:13:07.113725Z 3 [Hinweis] (--->MDL PRINT) Namespace ist:SCHEMA 2017-08-03T21:13:07.113746Z 3 [Hinweis] (---->MDL PRINT) Der Schnellpfad lautet: (Y) 2017-08-03T21:13:07.113768Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_INTENTION_EXCLUSIVE(IX) 2017-08-03T21:13:07.113791Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T21:13:07.113813Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 2017-08-03T21:13:07.113842Z 3 [Hinweis] (acquire_lock) DIESES MDL-LOCK wurde erfolgreich erworben! 2017-08-03T21:13:07.113865Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T21:13:07.113887Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T21:13:07.113922Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T21:13:07.113945Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T21:13:07.113975Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_SHARED_NO_READ_WRITE(SNRW) 2017-08-03T21:13:07.113998Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T21:13:07.114021Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER Darüber hinaus erfordert die Sperrtabelle auch IX-Sperren für GLOBAL und SCHEMA. Mit anderen Worten: Tabellen mit Lesesperre leeren; blockiert 11. MDL_EXCLUSIVE(X) Wird für verschiedene DDL-Operationen verwendet und als CREATE/DROP/RENAME TABLE-Operationen bezeichnet. Tatsächlich beinhalten fast alle DDL-Operationen diese Sperre, wie oben analysiert. Kompatibilität: Anfrage | Gewährte Anfragen für Sperre | Typ | S SH SR SW SWLP SU SRO SNW SNRW X | ----------+---------------------------------------------+ X | - - - - - - - - - - - | Es ist kein Zufall, dass alles blockiert wird, aber es wird auch durch alles blockiert. Zum Beispiel die Operation „Spalte hinzufügen“ gerade 2017-08-03T19:46:54.804240Z 3 [Hinweis] (>MDL PRINT) Thread-ID ist 3: 2017-08-03T19:46:54.804254Z 3 [Hinweis] (->MDL PRINT) DB_name ist:test 2017-08-03T19:46:54.804267Z 3 [Hinweis] (-->MDL PRINT) OBJ_name ist:testsort12 2017-08-03T19:46:54.804280Z 3 [Hinweis] (--->MDL PRINT) Namespace ist: TABLE 2017-08-03T19:46:54.804293Z 3 [Hinweis] (----->MDL PRINT) Mdl-Typ ist: MDL_EXCLUSIVE(X) 2017-08-03T19:46:54.804306Z 3 [Hinweis] (------>MDL PRINT) Mdl-Dauer ist: MDL_TRANSACTION 2017-08-03T19:46:54.804319Z 3 [Hinweis] (---------->MDL PRINT) Mdl-Status ist: LEER 6. Quellcode-Kommentare Aufzählung enum_mdl_type { /* Eine exklusive Metadatensperre. Wird nur für Sperren mit begrenztem Gültigkeitsbereich verwendet. Besitzer dieses Schlosstyps können aufrüstbare exklusive Schlösser erwerben auf einzelne Objekte. Kompatibel mit anderen IX-Sperren, jedoch inkompatibel mit S- und X-Sperren. */ MDL_INTENTION_EXCLUSIVE = 0, /* Eine gemeinsame Metadatensperre. Zu verwenden in Fällen, in denen wir nur an Objektmetadaten interessiert sind und es besteht keine Absicht, auf Objektdaten zuzugreifen (z. B. bei gespeicherten Routinen oder während der Vorbereitung vorbereiteter Anweisungen). Wir missbrauchen diese Art von Sperre auch für offene HANDLER, da Sperren durch diese Anweisung erworben muss mit der erworbenen Sperre kompatibel sein durch LOCK TABLES ... WRITE-Anweisung, also SNRW (Wir kommen nicht durch Erwerben der S-Sperre zum Zeitpunkt HANDLER ... OPEN und Upgrade auf SR Sperre für HANDLER ... LESEN, da es das Problem nicht löst um DML-Anweisungen abzubrechen, die auf eine Sperre auf Tabellenebene warten, während öffnen Sie HANDLER in derselben Verbindung). Um Deadlocks zu vermeiden, die auftreten können, wenn die SNRW-Sperre auf X-Sperre für Tabelle, auf der eine aktive S-Sperre vorhanden ist, deren Eigentümer ist Thread, der wiederum auf eine Sperre auf Tabellenebene wartet, die dem Thread gehört Beim Upgrade müssen wir thr_abort_locks_for_thread() verwenden. Einrichtungen in einer solchen Situation. Dieses Problem tritt nicht bei Sperren gespeicherter Routinen auf, da wir nicht verwenden Sie dafür SNRW-Sperren. Es tritt auch nicht auf, wenn S-Sperren verwendet werden während PREPARE-Aufrufen, da in diesem Fall keine Sperren auf Tabellenebene erworben werden Fall. */ MDL_SHARED, /* Eine gemeinsam genutzte Metadatensperre mit hoher Priorität. Wird in Fällen verwendet, in denen kein Zugriff auf Objektdaten beabsichtigt ist (d. h. Daten in der Tabelle). "Hohe Priorität" bedeutet, dass im Gegensatz zu anderen gemeinsam genutzten Schlössern Ignorieren ausstehender Anfragen für exklusive Sperren. Vorgesehen für den Einsatz in Fälle, in denen wir nur auf Metadaten und nicht auf Daten zugreifen müssen, z. B. wenn Füllen einer INFORMATION_SCHEMA-Tabelle. Da das SH-Schloss mit dem SNRW-Schloss kompatibel ist, ist die Verbindung, die hält SH lock lock sollte nicht versuchen, jede Art von Tabelle-Ebene zu erwerben oder Zeilensperre, da dies zu einem Deadlock führen kann. Außerdem nach Wenn die SH-Sperre erworben wird, sollte die Verbindung nicht auf andere warten Ressource, da dies zu einem Mangel an X-Sperren und einem potenziellen Deadlock beim Upgrade von SNW oder SNRW auf X Lock (z.B. wenn die die zu aktualisierende Verbindung hält die Ressource, auf die gewartet wird). */ MDL_SHARED_HIGH_PRIO, /* Eine gemeinsame Metadatensperre für Fälle, in denen Daten gelesen werden sollen aus der Tabelle. Eine Verbindung mit dieser Sperre kann Tabellenmetadaten lesen und Tabellendaten (nach dem Erwerb der entsprechenden Sperren auf Tabellen- und Zeilenebene). Das bedeutet, dass man nur TL_READ, TL_READ_NO_INSERT und Ähnliche Sperren auf Tabellenebene für die Tabelle, wenn eine SR-MDL-Sperre darauf gehalten wird. Zu verwenden für Tabellen in SELECTs, Unterabfragen und LOCK TABLE ... READ Aussagen. */ MDL_SHARED_READ, /* Eine gemeinsame Metadatensperre für Fälle, in denen Änderungen beabsichtigt sind (und nicht nur die) Daten in der Tabelle lesen. Eine Verbindung mit SW-Sperre kann Tabellenmetadaten lesen und ändern oder lesen Tabellendaten (nach dem Erwerb der entsprechenden Sperren auf Tabellen- und Zeilenebene). Zu verwenden für Tabellen, die durch INSERT, UPDATE, DELETE geändert werden sollen Anweisungen, aber nicht LOCK TABLE ... WRITE oder DDL). Auch von AUSWÄHLEN ... ZUM UPDATE. */ MDL_SHARED_WRITE, /* Eine Version der MDL_SHARED_WRITE-Sperre, die eine niedrigere Priorität hat als MDL_SHARED_READ_ONLY Sperren. Wird von DML-Anweisungen verwendet, die Tabellen und Verwendung der LOW_PRIORITY-Klausel. */ MDL_SHARED_WRITE_LOW_PRIO, /* Eine aktualisierbare gemeinsame Metadatensperre, die gleichzeitige Aktualisierungen ermöglicht und liest Tabellendaten. Eine Verbindung mit dieser Sperre kann Tabellenmetadaten lesen und Tabellendaten. Es sollten keine Daten geändert werden, da diese Sperre kompatibel ist mit SRO-Schlösser. Kann auf SNW-, SNRW- und X-Schlösser aufgerüstet werden. Sobald das SU-Schloss auf X aufgerüstet ist oder die Änderung der SNRW-Sperrdaten kann frei erfolgen. Soll für die erste Phase von ALTER TABLE verwendet werden. */ MDL_SHARED_UPGRADABLE, /* Eine gemeinsame Metadatensperre für Fälle, in denen wir Daten aus einer Tabelle lesen müssen und blockieren Sie alle gleichzeitigen Änderungen daran (sowohl für Daten als auch für Metadaten). Wird von der LOCK TABLES READ-Anweisung verwendet. */ MDL_SHARED_READ_ONLY, /* Eine aktualisierbare gemeinsame Metadatensperre, die alle Aktualisierungsversuche blockiert Tabellendaten, die Lesevorgänge ermöglichen. Eine Verbindung mit dieser Sperre kann Tabellenmetadaten lesen und Tabellendaten. Kann auf X-Metadatensperre aktualisiert werden. Beachten Sie, dass dieser Schlosstyp nicht mit SNRW oder SW kompatibel ist Sperrtypen, Erwerb geeigneter Sperren auf Engine-Ebene zum Lesen (TL_READ* für MyISAM, gemeinsame Zeilensperren in InnoDB) sollte streitfrei. Wird für die erste Phase von ALTER TABLE verwendet, wenn Daten zwischen Tabellen, um gleichzeitige SELECT-Vorgänge aus der Tabelle zuzulassen, jedoch keine UPDATE-Vorgänge. */ MDL_SHARED_NO_WRITE, /* Eine erweiterbare gemeinsame Metadatensperre, die andere Verbindungen ermöglicht um auf Tabellenmetadaten, aber nicht auf Daten zuzugreifen. Es blockiert alle Versuche, Tabellendaten zu lesen oder zu aktualisieren und ermöglicht gleichzeitig INFORMATION_SCHEMA- und SHOW-Abfragen. Eine Verbindung mit dieser Art von Sperre kann Tabellenmetadaten lesen, ändern und Tabellendaten lesen. Kann auf X-Metadatensperre aktualisiert werden. Zu verwenden für die LOCK TABLES WRITE-Anweisung. Nicht kompatibel mit anderen Schlosstypen außer S und SH. */ MDL_SHARED_NO_READ_WRITE, /* Eine exklusive Metadatensperre. Eine Verbindung, die diese Sperre aufrechterhält, kann sowohl die Metadaten als auch die Daten der Tabelle ändern. Solange diese Sperre besteht, kann keine andere Art von Metadatensperre gewährt werden. Zu verwenden für CREATE/DROP/RENAME TABLE-Anweisungen und zur Ausführung von bestimmte Phasen anderer DDL-Anweisungen. */ MDL_EXCLUSIVE, /* Dies sollte das letzte sein!!! */ MDL_TYPE_END}; /** Dauer der Metadatensperre. */ Aufzählung enum_mdl_duration { /** Sperren mit Anweisungsdauer werden automatisch am Ende freigegeben der Abrechnung oder Transaktion. */ MDL_STATEMENT = 0, /** Sperren mit Transaktionsdauer werden am Ende automatisch freigegeben der Transaktion. */ MDL_TRANSACTION, /** Sperren mit expliziter Dauer überdauern das Ende der Anweisung und Transaktion. Sie müssen explizit durch den Aufruf von MDL_context::release_lock() freigegeben werden. */ MDL_EXPLICIT, /* Dies sollte das letzte sein! */ MDL_DURATION_END }; /** Objektnamespaces. Sic: Wenn Sie dieser Aufzählung ein neues Mitglied hinzufügen, achten Sie darauf, Aktualisieren Sie das Array m_namespace_to_wait_state_name in MDL. Verschiedene Objekttypen existieren in verschiedenen Namespaces - GLOBAL wird für die globale Lesesperre verwendet. - TABLESPACE ist für Tablespaces. - SCHEMA ist für Schemata (auch bekannt als Datenbanken). - TABLE ist für Tabellen und Ansichten. - FUNCTION ist für gespeicherte Funktionen. - PROCEDURE ist für gespeicherte Prozeduren. - TRIGGER steht für Auslöser. - EVENT ist für Event-Scheduler-Ereignisse. - COMMIT dient zum Aktivieren der globalen Lesesperre, um Commits zu blockieren. - USER_LEVEL_LOCK ist für Sperren auf Benutzerebene. - LOCKING_SERVICE steht für das Namensplugin RW-Lock Service Beachten Sie, dass es zwar keine Metadatensperre für Trigger gibt, Es ist notwendig, einen separaten Namespace für sie zu haben, da MDL_key wird auch außerhalb des MDL-Subsystems verwendet. Beachten Sie auch, dass Anfragen, die auf Sperren auf Benutzerebene warten, spezielle Das Warten auf die Behandlung wird abgebrochen, wenn die Verbindung zum Client verloren geht. */ enum enum_mdl_namespace { GLOBAL=0, TABELLENBEREICH, SCHEMA, TISCH, FUNKTION, VERFAHREN, AUSLÖSEN, EREIGNIS, BEGEHEN, USER_LEVEL_LOCK, SPERRSERVICE, SICHERUNG, BINLOG, /* Dies sollte das letzte sein! */ NAMESPACE_END }; Das könnte Sie auch interessieren:
|
<<: So konfigurieren Sie eine JDK-Umgebung unter Linux
Lassen Sie uns zunächst die Daten simulieren, die...
1. Installationsumgebung Computermodell: Lenovo Y...
Vorwort Wenn Sie das Attribut „overflow: scroll“ ...
1. Verwendung des Iframe-Tags <br />Wenn es ...
Während des Crawler-Entwicklungsprozesses sind Si...
Inhaltsverzeichnis Vorwort Was ist Datenbindung? ...
Vorwort Nach einem Failover sind Synchronisierung...
1. Verwenden Sie Docker-Images, um alle Image-Dat...
Vorwort: Partitionierung ist ein Tabellenentwurfs...
Inhaltsverzeichnis Vorwort Installation und Verwe...
eins. Vorwort <br />Sie werden diese Art von...
Beim Importieren von Daten mit falscher MySQL-Zei...
Vuex ist ein speziell für Vue.js-Anwendungen entw...
1. Erzwingen Sie keinen Zeilenumbruch und beenden ...
Da ich derzeit zum Erlernen von Deep Learning die...