MYSQL METADATA LOCK (MDL LOCK) Theorie und Sperrtyptest

MYSQL METADATA LOCK (MDL LOCK) Theorie und Sperrtyptest

MYSQL METADATA LOCK (MDL LOCK) Lerntheorie und Sperrtyptest

Vorwort:

Quellcode-Version: 5.7.14
Beachten Sie den Unterschied in der MDL- und DML-Terminologie

1. Vorläufiges Verständnis

MDL-Sperren in MySQL haben schon immer Kopfschmerzen bereitet. Wenn wir über Sperren sprechen, sprechen wir normalerweise über Lückensperren, nächste Schlüsselsperren, Zeilensperren usw. auf der unteren Ebene von INNODB.
Weil es leicht zu verstehen und zu beobachten ist, ist über MDL LOCK wenig bekannt, weil es wirklich schwer zu beobachten ist. Nur wenn ein Problem auftritt, können Sie das einfache sogenannte Warten auf den Sperrstatus der Tabellenmetadaten kaum sehen, indem Sie die Prozessliste anzeigen überprüfen. Tatsächlich ist MDL LOCK ein sehr komplexes Subsystem der oberen Schicht von MySQL, das über einen eigenen Mechanismus zur Erkennung von Deadlocks verfügt.
(Ungerichteter Graph?) Und was die Leute normalerweise sagen, ist, ob die Tabelle gesperrt ist oder nicht, was sich tatsächlich darauf bezieht. Man kann sehen, dass es kritisch und ernst ist. Der Autor hat auch einiges (die Spitze des Eisbergs) entsprechend seinen eigenen Bedürfnissen gelernt.
Obwohl ich nicht alle Codes lesen kann, habe ich eine TICKET-Druckfunktion hinzugefügt, um den MDL LOCK-Sperrvorgang der Anweisung zum leichteren Studium auszudrucken. Im Folgenden werden zunächst einige Grundlagen erläutert, die Ihnen zeigen, was geändert wurde. Abschließend wird jeder MDL-TYP getestet und analysiert. Wenn Sie sich nicht für die grundlegenden Konzepte und das Hinzufügen von Druckfunktionen interessieren, können Sie direkt auf den fünften Teil des Sperrtests verweisen. Dies kann jedoch etwas schwierig erscheinen, wenn Sie die Grundlagen nicht verstehen.
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 Ebene: 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: 'Opening tables'

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.

MDL LOCK的死鎖拋錯和INNODB死鎖一模一樣不同的只是SHOW ENGINE INNODB 沒有死鎖信息.
----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 finden Sie die Klassifizierung von NAMESPACE

- 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 LOCK , z. B. ist flush table with read lock namespace space:GLOBAL type:S
Objektsperre: Wie der Name schon sagt, MDL LOCK auf Objektebene, wie z. 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?

Siehe Quellcode-Kommentare:

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

7. MDL_key-Klasse

Es handelt sich um den tatsächlichen NAMESPACE+DB+OBJECT_NAME , der in ein char eingefügt wird. Er erscheint in MDL_LOCK und MDL_REQUEST
private :

  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

Diese Klasse enthält hauptsächlich den aktuellen Ticketerwerbsstatus 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, den Prozess des Sperrens, Aktualisierens und Herabstufens von MDL zu verstehen. Da der Quellcode zu groß ist, ist es unmöglich, alles abzudecken. Obwohl 5.7 die folgende Methode zur Ansicht hinzufügt

  • 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

Es ist jedoch immer noch schwierig zu überprüfen, welche MDL-LOCKs eine Anweisung erhalten hat. 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.
friend int 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 Thread id aus show processlist , 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 zur Beobachtung die Druckfunktion an der entsprechenden Stelle hinzufügen. Die Druckstelle ist unten markiert und der größte Teil des Quellcodes wurde gelöscht. Bitte beziehen Sie sich selbst darauf.

Quellcode anzeigen:

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 neuer_typ)

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, Enumeration_MDL_Typ neuer Typ, ulong Wartezeit_für_Sperre)

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 tritt bei vielen Vorgängen auf und wird beispielsweise durch jeden DML/DDL-Vorgang ausgelöst.
DML-Operationen wie DELTE/UPDATE/INSERT/FOR UPDATE fügen eine IX-Sperre auf dem GLOBAL und dann auf dem Objekt hinzu. DDL-Anweisungen fügen mindestens eine IX-Sperre auf dem GLOBAL, eine IX-Sperre auf dem SCHEMA, zu dem das Objekt gehört, und dann auf dem Objekt hinzu.

Unten sehen Sie die GLOABLIX MDL LOCK, die durch DELETE ausgelöst wurde

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

所以這個MDL LOCK 無所不在,而只有是否兼容問題,如果不兼容則堵塞。SCOPED 的IX類型一般都是兼容的除非遇到
S類型

2. MDL_SHARED(S)

這把鎖一般用在flush tables with read lock中

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
MDL IX von SCOPED ist nicht kompatibel mit MDL S. flush tables with read lock; 就會堵塞所有DELTE/UPDATE/INSERT/FOR UPDATE等DML和DDL操作(因為這些操作都需要GLOBAL MDL IX鎖)

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 bei nicht aktuellen Lese-Auswahlen verwendet.

Kompatibilität:

       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

這里還是要提及一下平時我們偶爾會出現select也堵住的情況(比如DDL的某個階段需要對象MDL X鎖)。我們不得不抱怨
MYSQL居然會堵塞select其實這里也就是object mdl lock X 和SR 不兼容的問題(參考前面的兼容矩陣)。

5. MDL_SHARED_WRITE (SW)

這把鎖一般用于DELTE/UPDATE/INSERT/FOR UPDATE等操作對table的加鎖(當前讀), 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

Used by DML statements modifying
tables and using the LOW_PRIORITY clause

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, sodass diese SU-Sperre die Lese- und Schreibvorgänge von DML/SELECT nicht blockiert.
Die INNODB-Engine-Schicht ist die Grundlage von ONLINE DDL. Wenn sie nicht kompatibel ist, können Sie die INNODB-Engine-Schicht nicht betreten, geschweige denn ONLINE
DDL, beachten Sie, dass ich ALGORITHM=INPLACE gesagt und LOCK nicht gesetzt habe

(Für DDL-Operationen mit LOCK=DEFAULT oder ohne LOCK-Klausel verwendet MySQL die niedrigste Ebene
der Sperren, die für diese Art von Operation verfügbar sind, und die gleichzeitige Abfragen, DML oder beides ermöglichen, wo immer
möglich. Diese Einstellung sollten Sie verwenden, wenn Sie vorgeplante und getestete Änderungen vornehmen, von denen Sie wissen, dass sie nicht
kann Verfügbarkeitsprobleme aufgrund der Arbeitslast für diese Tabelle verursachen
Wenn eine Operation auf dem Primärschlüssel ALGORITHM=INPLACE verwendet, werden die Daten zwar trotzdem kopiert, aber
ist effizienter als die Verwendung von ALGORITHM=COPY, weil:
? Für ALGORITHM=INPLACE ist kein Undo-Logging oder zugehöriges Redo-Logging erforderlich. Diese Operationen fügen
Overhead für DDL-Anweisungen, die ALGORITHM=COPY verwenden.
? Die Sekundärindexeinträge sind vorsortiert und können so der Reihe nach geladen werden.
? Der Änderungspuffer wird nicht verwendet, da keine wahlfreien Einfügungen in die sekundären Indizes erfolgen.
)

Wie die folgende Aussage

mysql> Tabelle ändern, testsort12, Spalte hinzufügen, int nicht null;
Abfrage OK, 0 Zeilen betroffen (6,27 Sek.)
Datensätze: 0 Duplikate: 0 Warnungen: 0

Eine einfache Analyse:

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 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: mdl_transaction
2017-08-03T19: 46: 54.856214Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer
2017-08-03T19: 47: 00.260166Z 3 [Anmerkung] (upgrade_shared_lock) Diese MDL-Sperre wird ein Upgrade durchführen
2017-08-03T19: 47: 00.304057Z 3 [Anmerkung] (upgrade_shared_lock) Dieses MDL-Sperren-Upgrade auf
2017-08-03T19: 47: 00.304090Z 3 [Anmerkung] (> MDL-Druck) 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 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: TestSort12
2017-08-03T19: 47: 00.304132Z 3 [Hinweis] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T19: 47: 00.304181Z 3 [Anmerkung] (------> MDL-Druck) MDL-Typ ist: MDL_EXCLUSIVE (x)
2017-08-03T19: 47: 00.304196Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: mdl_transaction
2017-08-03T19: 47: 00.304211z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer
2017-08-03T19: 47: 01.032329Z 3 [Hinweis] (Accire_lock) Dieses MDL-Schloss erwerben OK!

Holen Sie sich zunächst die Tabelle Testsort12

2017-08-03T19: 46: 54.781487 Got mdl_shared_upgradable (SU)
2017-08-03T19: 46: 54.804293 Upgrade MDL_EXCLUSIVE (x)
2017-08-03T19: 46: 54.855563 Downgrade MDL_SHARDE_UPGRADABLE (SU) Downgrade Downgrade Downgrade Downgrade Downgrade
2017-08-03T19: 47: 00.304057 Upgrade MDL_EXCLUSIVE (x)

Denn unabhängig davon, dass dieser Alterbetrieb noch zeitaufwändig ist實際在MDL SU模式下所以不會堵塞DML/SELECT操作。
這里再給大家提個醒所謂的ONLINE DDL只是在COPY階段不堵塞DML/SELECT操作,還是盡量在數據庫壓力小的時候,
比如如果有DML沒有提交或者SELECT沒有做完這個時候SW SR必然堵塞X,而X能夠堵塞一切且為高優先級。這樣導致的現象就是由于DML未提交堵塞DDL操作而DDL操作堵塞一切操作,基本對于這個TABLE的表全部堵塞。

Für Algorithmus = Kopie ist der Rest des Codes ähnlich,但是在COPY階段用的是SNW鎖,接下來我就先來看看SNW鎖

8. Mdl_Shared_no_write (SNW)

SU kann auf SNW aktualisiert werden und SNW kann auf X aktualisiert werden, wie bereits erwähnt, um in Algorithmus = Kopie zu verwenden, um die Datenkonsistenz zu schützen.

Kompatibilität:

       Anfrage |.                   
        Typ |.
      ----------+------------------------------------------+
      SNW |.


Sie können sehen, dass SR aber SW nicht.
MySQL> ALTER TABLE TESTSORT12 Fügen Sie die Spalte hinzu.

2017-08-03T20: 07: 58.413215Z 3 [Anmerkung] (upgrade_shared_lock) Dieses MDL-Sperren-Upgrade auf
2017-08-03T20: 07: 58.413241z 3 [Anmerkung] (> MDL-Druck) Thread-ID ist 3:
2017-08-03T20: 07: 58.413257Z 3 [Hinweis] (-> MDL-Druck) DB_NAME IST: Test
2017-08-03T20: 07: 58.413273Z 3 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: testSort12
2017-08-03T20: 07: 58.413292Z 3 [Anmerkung] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T20: 07: 58.413308z 3 [Hinweis] (------> MDL-Druck) MDL-Typ ist: MDL_SHARD_NO_WRITE (SNW)
2017-08-03T20: 07: 58.413325Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: mdl_transaction
2017-08-03T20: 07: 58.413341Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer
2017-08-03T20: 08: 25.392006Z 3 [Hinweis] (upgrade_shared_lock) Dieses MDL-Sperren-Upgrade auf
2017-08-03T20: 08: 25.392024Z 3 [Anmerkung] (> MDL-Druck) 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 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: TestSort12
2017-08-03T20: 08: 25.392199z 3 [Anmerkung] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T20: 08: 25.392214Z 3 [Anmerkung] (------> MDL-Druck) MDL-Typ ist: MDL_EXCLUSIVE (x)
2017-08-03T20: 08: 25.392228Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: MDL_TRANSACTIONALE
2017-08-03T20: 08: 25.392242Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer

2017-08-03T20: 07: 58.413308 Got mdl_shared_no_write (SNW)
2017-08-03T20: 08: 25.392006 auf MDL_EXCLUSIVE (x) aktualisiert

這2017-08-03T20:07:58.413308到2017-08-03T20:08:25.392006就是實際COPY的時間,可見整個COPY期間只能DML
而不能SELECT,也是ALGORITHM=COPY和ALGORITHM=INPLACE一個關鍵區別。

9. Mdl_Shared_read_only (SRO)

用于LOCK TABLES READ 語句

Die Kompatibilität ist wie folgt

      Anfrage |.
        Typ |.
      ----------+------------------------------------------+
      Sro |.


Blöcke DML (SW), aber ausgewählt (SR) ist noch möglich.

MySQL> Sperrtabelle Testsort12 lesen;
Abfrage OK, 0 Zeilen betroffen (0,01 Sek.)
2017-08-03T21: 08: 27.267947Z 3 [Anmerkung] (Accire_lock) Diese MDL Lock Acquire OK!
2017-08-03T21: 08: 27.267979z 3 [Anmerkung] (> MDL-Druck) 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 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: TestSort12
2017-08-03T21: 08: 27.268070Z 3 [Hinweis] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T21: 08: 27.268113z 3 [Hinweis] (------> MDL-Druck) MDL-Typ ist: MDL_SHARD_READ_ONLY (SRO)
2017-08-03T21: 08: 27.268145Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: mdl_transaction
2017-08-03T21: 08: 27.268175Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer

10. mdl_shared_no_read_write (SNRW)

用于LOCK TABLES WRITE語句

Kompatibilität:

       Anfrage |.
        Typ |.
      ----------+------------------------------------------+
      Snrw |.


Es ist ersichtlich, dass DML (SW) und Select (SR) blockiert sind, nur SH verfügbar ist und Desc (SH) ebenfalls erhältlich ist.

MySQL> Sperrtabelle Testsort12 schreiben;
Abfrage OK, 0 Zeilen betroffen (0,00 Sek.)
2017-08-03T21: 13: 07.113347Z 3 [Anmerkung] (Accire_lock) Diese MDL-Schloss erwerben OK!
2017-08-03T21: 13: 07.113407Z 3 [Anmerkung] (> MDL-Druck) Thread-ID ist 3:
2017-08-03T21: 13: 07.113435Z 3 [Anmerkung] (---> MDL Print) Namespace ist: global
2017-08-03T21: 13: 07.113458z 3 [Anmerkung] (----> MDL-Druck) Schneller Pfad lautet: (y)
2017-08-03T21: 13: 07.113482z 3 [Anmerkung] (------> MDL-Druck) MDL-Typ ist: MDL_intention_Exclusive (IX)
2017-08-03T21: 13: 07.113505Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: MDL_Statement
2017-08-03T21: 13: 07.113604Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer
2017-08-03T21: 13: 07.113637Z 3 [Anmerkung] (Accire_lock) Diese MDL-Schloss erwerben OK!
2017-08-03T21: 13: 07.113660Z 3 [Anmerkung] (> MDL-Druck) 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 [Anmerkung] (-> MDL Print) OBJ_NAME IS:
2017-08-03T21: 13: 07.113725Z 3 [Anmerkung] (---> MDL Print) Namespace ist: Schema
2017-08-03T21: 13: 07.113746z 3 [Anmerkung] (----> MDL-Druck) Schneller Pfad lautet: (y)
2017-08-03T21: 13: 07.113768z 3 [Anmerkung] (------> MDL-Druck) MDL-Typ ist: mdl_intention_exclusive (ix)
2017-08-03T21: 13: 07.113791z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: mdl_transaction
2017-08-03T21: 13: 07.113813z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer
2017-08-03T21: 13: 07.113842Z 3 [Anmerkung] (Accire_lock) Dieser MDL-Schloss erwerben OK!
2017-08-03T21: 13: 07.113865Z 3 [Anmerkung] (> MDL-Druck) 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 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: TestSort12
2017-08-03T21: 13: 07.113945Z 3 [Anmerkung] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T21: 13: 07.113975Z 3 [Hinweis] (------> MDL-Druck) MDL-Typ ist: MDL_SHARD_NO_READ_WRITE (SNRW)
2017-08-03T21: 13: 07.113998z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: MDL_TRANSACTIONALE
2017-08-03T21: 13: 07.114021z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer

除此之外lock table 還需要GLOBAL和SCHEMA上的IX鎖,換句話說flush tables with read lock; 會堵塞lock table testsort12 write;但是lock table testsort12 read 卻不會堵塞。

11. MDL_EXCLUSIVE (x)

Wird für verschiedene DDL -Operationen verwendet, kommentiert als Create/Drop/ -umbenennen Tabellenoperationen.
Fügen Sie den Spaltenbetrieb hinzu, die Dauer ist jedoch im Allgemeinen kurz.

Kompatibilität:

       Anfrage |.
        Typ |.
      ----------+------------------------------------------+
      X |.


Es gibt keine zufällige Blockierung von allem oben, aber es wird auch durch alles blockiert, wie z. B. die Säulenoperation hinzufügen.

2017-08-03T19: 46: 54.804240Z 3 [Anmerkung] (> MDL-Druck) Thread-ID ist 3:
2017-08-03T19: 46: 54.804254Z 3 [Anmerkung] (-> MDL-Druck) DB_NAME IST: Test
2017-08-03T19: 46: 54.804267Z 3 [Anmerkung] (-> MDL-Druck) OBJ_NAME IS: TestSort12
2017-08-03T19: 46: 54.804280Z 3 [Anmerkung] (---> MDL Print) Namespace ist: Tabelle
2017-08-03T19: 46: 54.804293Z 3 [Anmerkung] (------> MDL-Druck) MDL-Typ ist: MDL_EXCLUSIVE (x)
2017-08-03T19: 46: 54.804306Z 3 [Anmerkung] (------> MDL-Druck) MDL-Dauer ist: MDL_TRANSACTIONALE
2017-08-03T19: 46: 54.804319Z 3 [Anmerkung] (-------> MDL-Druck) MDL-Status ist: leer

6. Quellcodekommentare

enum enum_mdl_type {
  /*
    Eine ausschließliche Absicht, die nur für Scoped -Schlösser verwendet wird.
    Der Eigentümer dieser Art von Schloss kann aktualisierbare exklusive Schlösser erwerben
    Einzelne Objekte.
    Kompatibel mit anderen IX -Schlössern, ist aber unvereinbar mit Scoped S und
    X Locken.
  */
  Mdl_intentention_exclusive = 0,,
  /*
    Ein gemeinsames Metadatenschloss.
    In Fällen zu verwenden, wenn wir nur an Objektmetadaten interessiert sind
    und es besteht keine Absicht, auf Objektdaten zuzugreifen (z. B. für gespeicherte
    Routinen oder während der Vorbereitung vorbereitete Aussagen).
    Wir verwenden diese Art von Schloss auch für offene Handler, seit Sperre
    Von dieser Aussage erworbene Erklärung muss mit dem erworbenen Lock kompatibel sein
    nach Sperrtabellen ... Schreibanweisung, dh SNRW (wir können nicht vorbeikommen
    Erwerben von S -Schloss bei Handler ... OPENTIONEN und aktualisiert es auf SR
    Sperren Sie für Handler ... Lesen Sie, da es kein Problem mit den Bedürfnissen löst
    DML
    Öffnen Sie den Handler in derselben Verbindung).
    Um eine Deadlock zu vermeiden, die auftreten kann, wenn SNRW Lock auf aktualisiert wird
    X Sperre für Tisch, auf der es ein aktives S -Schloss gibt, das im Besitz von Tisch gibt
    Faden, der sich in der Reihe auf Tischebene im Besitz des Threads wartet
    Durchführung von Upgrade Wir müssen Thr_abort_locks_for_thread () verwenden.)
    Einrichtungen in einer solchen Situation.
    Dieses Problem entsteht nicht für Sperren auf gespeicherten Routinen, wie wir es nicht tun
    Verwenden Sie SNRW -Schlösser für sie.
    Während der Vorbereitung von Anrufen als Schlösser auf Tischebene werden hier nicht erworben
    Fall.
  */
  Mdl_shared,
  /*
    Eine hochprioritäts gemeinsame Metadatenschloss.
    Wird für Fälle verwendet, in denen keine Absicht besteht, auf Objektdaten zuzugreifen (dh
    Daten in der Tabelle).
    "Hohe Priorität" bedeutet, dass es im Gegensatz zu anderen gemeinsamen Schlössern gewährt wird
    Ignorieren Sie anhängige Anfragen für exklusive Schlösser.
    Fälle, in denen wir nur auf Metadaten und nicht auf Daten zugreifen müssen, z
    Füllen Sie eine Tabelle Information_Schema.
    Da SH -Lock mit SNRW Lock kompatibel ist, ist die Verbindung, die
    Hält Sh Lock Lock nicht, um irgendeine Art von Tischebene zu erwerben
    oder ROW-Ebene, da dies zu einem Deadlock führen kann
    Wenn Sie SH -Sperren erwerben, sollte die Verbindung nicht auf andere warten
    Ressource, da dies für X -Schlösser und ein Potenzial verhungern kann
    Deadlock während des Upgrades von SNW oder SNRW auf X Lock (zB wenn die
    Die Upgrade -Verbindung hält die Ressource, auf die gewartet wird).
  */
  Mdl_shared_high_prio,
  /*
    Eine gemeinsame Metadatenschloss für Fälle, in denen die Absicht besteht, Daten zu lesen
    vom Tisch.
    Eine Verbindung, die diese Art von Schloss hält, kann Tabellenmetadaten lesen und lesen
    Tabellendaten (nach Erfassen geeigneter Tabellen- und Zeilenebene-Sperren).
    Dies bedeutet, dass man nur tl_read, tl_read_no_insert und erwerben kann und
    Ähnliche Schlösser auf Tabellenebene auf der Tabelle, wenn man die SR-MDL-Sperre enthält.
    Für Tabellen in Auswahl, Unterabfragen und Sperrtabelle verwendet werden ... lesen Sie
    Aussagen.
  */
  Mdl_shared_read,
  /*
    Eine gemeinsame Metadatenschloss für Fälle, in denen die Änderung der Absicht besteht
    (und nicht nur lesen) Daten in der Tabelle.
    Eine Verbindung, die SW -Sperre hält, kann Tabellenmetadaten lesen und ändern oder lesen
    Tabellendaten (nach Erfassen geeigneter Tabellen- und Zeilenebene-Sperren).
    Für die Änderung von Tabellen durch Einfügen, Aktualisieren, Löschen verwendet werden
    Aussagen, aber keine Sperrentabelle ... Schreiben oder DDL)
    Wählen Sie ... für das Update.
  */
  Mdl_shared_write,
  /*
    Eine Version der MDL_SHARDEL -Write -Sperre, die eine geringere Priorität hat als
    MDL_SHARD_READ_ONLY LOCKS.
    Tabellen und Verwendung der Low_Priority -Klausel.
  */
  Mdl_shared_write_low_prio,
  /*
    Ein aufrüstbares freigegebenes Metadatenschloss, das gleichzeitige Updates ermöglicht und
    Reads von Tabellendaten.
    Eine Verbindung, die diese Art von Schloss hält, kann Tabellenmetadaten lesen und lesen
    Tabellendaten.
    SRO -Schlösser.
    Kann auf SNW, SNRW und X -Schlösser verbessert werden.
    oder SNRW -Sperrdatenänderungen können frei erfolgen.
    Für die erste Phase der Alter Tabelle verwendet werden.
  */
  Mdl_shared_upgradable,
  /*
    Eine gemeinsam genutzte Metadatenschloss für Fälle, in denen wir Daten aus der Tabelle lesen müssen
    und blockieren Sie alle gleichzeitigen Modifikationen (für Daten und Metadaten).
    Verwendet von Lock Tables Read Anweisung.
  */
  Mdl_shared_read_only,
  /*
    Ein aufrüstbares freigegebenes Metadatenschloss, das alle Versuche zum Aktualisieren blockiert
    Tabellendaten, die Lesevorgänge ermöglichen.
    Eine Verbindung, die diese Art von Schloss hält, kann Tabellenmetadaten lesen und lesen
    Tabellendaten.
    Kann auf X Metadata Lock verbessert werden.
    Beachten Sie, dass, da diese Art von Schloss nicht mit SNRW oder SW kompatibel ist
    Sperrtypen und erwerben geeignete Schlösser auf Motorebene zum Lesen
    (TL_READ* Für MyISAM sollte freigegebene Zeilensperrungen in InnoDB sein) sein
    korrigierenfrei.
    Für die erste Phase der Alterentabelle verwendet werden, wenn Daten zwischen Daten kopieren
    Tabellen, um eine gleichzeitige Auswahl aus der Tabelle zuzulassen, jedoch nicht Aktualisierungen.
  */
  Mdl_shared_no_write,
  /*
    Ein aufrüstbares gemeinsames Metadatenschloss, das andere Verbindungen ermöglicht
    Zugriff auf Tabellenmetadaten, aber keine Daten.
    Es blockiert alle Versuche, Tabellendaten zu lesen oder zu aktualisieren, während es zulässig ist
    Information_schema und Anfragen anzeigen.
    Eine Verbindung, die diese Art von Schloss hält, kann Tabellenmetadaten modifizieren und
    Tabellendaten lesen.
    Kann auf X Metadata Lock verbessert werden.
    Für Sperrtabellen Schreibanweisung verwendet werden.
    Nicht kompatibel mit einem anderen Sperrtyp außer S und SH.
  */
  Mdl_shared_no_read_write,
  /*
    Ein exklusives Metadatenschloss.
    Eine Verbindung, die diese Sperre hält, kann die Metadaten und die Daten beider Tabellen ändern.
    Während dieses Schlosses kann keine andere Art von Metadatenschloss gewährt werden.
    Zum Erstellen/Drop-/Umbenennen von Tabellenanweisungen und zur Ausführung von verwendet werden
    Bestimmte Phasen anderer DDL -Anweisungen.
  */
  Mdl_exclusive,
  / * Dies sollte der letzte sein !!! */
  Mdl_type_end};


/** Dauer der Metadatenschloss.

enum enum_mdl_duration {
  /**
    Sperren mit Anweisungsdauer werden am Ende automatisch veröffentlicht
    der Anweisung oder Transaktion.
  */
  Mdl_statement = 0,,
  /**
    Schlösser mit Transaktionsdauer werden am Ende automatisch freigegeben
    der Transaktion.
  */
  Mdl_transaction,
  /**
    Schlösser mit explizitem Dauer überleben das Ende der Aussage und der Transaktion.
    Sie müssen explizit veröffentlicht werden, indem sie mdl_context :: Release_lock () aufrufen.
  */
  Mdl_explicit,
  / * Dies sollte der letzte sein!
  Mdl_duration_end};

/**
    Objekt -Namespaces.
    SIC: Wenn Sie dieses Enum ein neues Mitglied hinzufügen
    Aktualisieren Sie M_NameSpace_TO_WAIT_STATE_NAME -Array in MDL.

    In verschiedenen Namespaces gibt es verschiedene Arten von Objekten
     - Global wird für das Global Read Lock verwendet.
     - Tablespace ist für Tablespaces.
     - Schema ist für Schemas (auch bekannt als Datenbanken).
     - Die Tabelle ist für Tabellen und Ansichten.
     - Funktion ist für gespeicherte Funktionen.
     - Verfahren ist für gespeicherte Verfahren.
     - Trigger ist für Auslöser.
     - Ereignis ist für Veranstaltungen für Veranstaltungen geeignet.
     - Commit ist für die Ermöglichung des globalen Leseschloss, Commits zu blockieren.
     - User_level_lock ist für Sperren von Benutzerebene.
     - Locking_Service ist für den Namen Plugin RW-Lock-Service
    Beachten
    Es ist notwendig, einen separaten Namespace für sie zu haben
    MDL_Key wird auch außerhalb des MDL -Subsystems verwendet.
    Beachten Sie auch, dass das Warten auf Spezialverschlüsse auf Benutzerebene ist, um Spezial zu erhalten
    Der Behandlungserweiter wird abgebrochen, wenn die Verbindung zum Klienten verloren geht.
  */
  enum enum_mdl_namespace {global = 0,,
                            Tablespace,
                            SCHEMA,
                            TISCH,
                            FUNKTION,
                            VERFAHREN,
                            AUSLÖSEN,
                            EREIGNIS,
                            BEGEHEN,
                            User_level_lock,
                            Locking_service,
                            Backup,
                            Binlog,
                            / * Dies sollte der letzte sein!
                            Namespace_end};

Die oben genannten Details der MySQL -Metadata -Sperre (MDL Lock) -Theorie und des Sperrenentyps.

Das könnte Sie auch interessieren:
  • Gründe und Methoden für das Warten auf Tischmetadaten in MySQL
  • Detaillierte Erläuterung des Metadatenschlosses, das Sie wissen müssen, wenn Sie die MySQL -Tabellenstruktur ändern
  • MySQL Metadata Lock (MDL Lock) MDL Lock -Problemanalyse
  • MySQL Slave verzögert Fremdschlüsselprüfung und automatische Inkrementschloss für eine Spalte
  • Eine kurze Diskussion über den Schlossbereich von MySQL Next-Taste-Schloss
  • MySQL-Methode zur Sperrensteuerung für Parallelität
  • Lösung für das Problem der gesperrten Transaktionsverarbeitung mit hoher Parallelität in PHP+MySQL

<<:  Richtige Methode zum Schreiben leerer Links, um Seitensprünge nach dem Klicken auf ein href #-Problem zu verhindern

>>:  Erfahren Sie, wie Sie mit dem Docker-Maven-Plugin die Bereitstellung automatisieren

Artikel empfehlen

Detaillierte Erklärung des JavaScript-Statuscontainers Redux

Inhaltsverzeichnis 1. Warum Redux 2. Redux-Datenf...

Einige Details zu Semikolons in JavaScript

Vorwort Semikolons sind in JavaScript optional un...

Detaillierte Beispiele für Docker-Compose-Netzwerke

Ich habe heute mit den Netzwerkeinstellungen unte...

MySQL-Onlineprobleme mit langsamem Log und Optimierungslösungen

Das MySQL-Slow-Log ist ein Informationstyp, auf d...

Docker-Compose-Tutorial: Installation und Schnellstart

Inhaltsverzeichnis 1. Einführung in Compose 2. Co...

HTML-Tutorial: DOCTYPE-Abkürzung

Beim Schreiben von HTML-Code sollte die erste Zei...

CentOS 6 Kompilieren und installieren Sie ZLMediaKit-Analyse

Installieren Sie ZLMediaKit auf centos6 Der Autor...

Eine Codezeile zeigt Ihnen, wie Sie Linux-Prozesse verbergen

Freunde fragen mich immer, wie man Linux-Prozesse...

Detaillierte Erklärung der MySQL EXPLAIN-Ausgabespalten

1. Einleitung Die EXPLAIN-Anweisung liefert Infor...

Detaillierte Analyse der MySQL-Sperrblockierung

Bei der täglichen Wartung werden Threads häufig b...

Mac+IDEA+Tomcat-Konfigurationsschritte

Inhaltsverzeichnis 1. Herunterladen 2. Installati...

MySQL5.7.27-winx64 Version Win10 Download- und Installations-Tutorial-Diagramm

MySQL 5.7-Installation Wir lernen in der Schule M...