Eine kurze Erläuterung der Manifestation und Wertauswahlmethode von innodb_autoinc_lock_mode

Eine kurze Erläuterung der Manifestation und Wertauswahlmethode von innodb_autoinc_lock_mode

Voraussetzung: Percona 5.6 Version, Transaktionsisolationsebene ist RR

mysql> zeigen erstellen Tabelle test_autoinc_lock\G
*************************** 1. Reihe ***************************
    Tabelle: test_autoinc_lock
Tabelle erstellen: CREATE TABLE `test_autoinc_lock` (
 `id` int(11) NICHT NULL AUTO_INCREMENT,
 `a` int(11) DEFAULT NULL,
 Primärschlüssel (`id`),
 SCHLÜSSEL `idx_a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8

1 Zeile im Satz (0,00 Sek.)
mysql> wähle * aus test_autoinc_lock;
+----+------+
| Ich würde | ein |
+----+------+
| 1 | 1 |
| 12 | 2 |
| 2 | 3 |
| 3 | 5 |
| 4 | 7 |
| 5 | 7 |
| 6 | 9 |
| 7 | 10 |
+----+------+
8 Zeilen im Satz (0,00 Sek.)

Bedingung 1 innodb_autoinc_lock_mode ist auf 0 gesetzt

Sitzung1
 begin;delete from test_autoinc_lock where a>7;//session2 wird zu diesem Zeitpunkt nicht übermittelt
mysql> insert into test_autoinc_lock(a) values(100); //Gap-Sperre vorhanden, und die Sperre wartet auf Sitzung 3
mysql> insert into test_autoinc_lock(a) values(2); //Dies ist auch im Wartezustand. Theoretisch ist dies nicht der Sperrbereich der Lückensperre, also worauf wartet es? session4
mysql> wähle * aus information_schema.innodb_trx\G
*************************** 1. Reihe ***************************
          trx_id: 2317
         trx_state: SPERRE WARTEN
        trx_started: 31.10.2016 19:28:05
   trx_requested_lock_id: 2317:20
     trx_wait_started: 31.10.2016 19:28:05
        trx_gewicht: 1
    trx_mysql_thread_id: 9
         trx_query: in test_autoinc_lock(a) Werte(2) einfügen
    trx_operation_state: Auto-Inc-Sperre festlegen
     trx_tables_in_use: 1
     trx_tables_locked: 1
     trx_lock_structs: 1
   trx_lock_memory_bytes: 360
      trx_rows_locked: 0
     trx_rows_modified: 0
  trx_concurrency_tickets: 0
    trx_isolation_level: WIEDERHOLBARES LESEN
     trx_unique_checks: 1
  trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 10000
     trx_ist_schreibgeschützt: 0
trx_autocommit_non_locking: 0

Überprüfen Sie zu diesem Zeitpunkt, dass Sitzung 3 auf die Auto-Inkrement-Sperre wartet und sich im Status der Einstellung der Auto-Inkrement-Sperre befunden hat.

Sitzung2

FEHLER 1205 (HY000): Wartezeit für Sperre überschritten; versuchen Sie, die Transaktion neu zu starten.

Zu diesem Zeitpunkt wird Sitzung 3 gesperrt und wartet auf das Timeout, um beendet zu werden.

Sitzung3

Schauen Sie sich nun Sitzung 3 an und Sie können sehen, dass die Einfügung abgeschlossen ist.

mysql> wähle * aus test_autoinc_lock;
+----+------+
| Ich würde | ein |
+----+------+
| 1 | 1 |
| 12 | 2 |
| 13 | 2 |
| 2 | 3 |
| 3 | 5 |
| 4 | 7 |
| 5 | 7 |
| 6 | 9 |
| 7 | 10 |
+----+------+
9 Zeilen im Set (0,00 Sek.) //Beachten Sie, dass der maximale Autoinkrementwert zu diesem Zeitpunkt 13 beträgt, was dem vorherigen maximalen Autoinkrementwert + 1 entspricht. Mit anderen Worten, Sitzung2 hat später die erwartete Autoinkrement-ID freigegeben und 13 Sitzung3 überlassen. Die Anwendung von Autoinkrement-ID-Werten ist vollständig seriell.

Fazit: Wenn innodb_autoinc_lock_mode 0 ist, wird es offiziell als traditionell bezeichnet

Ebene: Die Autoinkrementsperre befindet sich auf der Ebene der Tabellensperre und muss warten, bis das aktuelle SQL ausgeführt oder zurückgesetzt wird, bevor sie freigegeben wird. Auf diese Weise ist es denkbar, dass bei hoher Parallelität der Wettbewerb um die Autoinkrementsperre relativ groß ist.

Bedingung 2: innodb_autoinc_lock_mode ist auf 1 gesetzt

Sitzung1
mysql> beginnen;
Abfrage OK, 0 Zeilen betroffen (0,00 Sek.)


mysql> löschen aus test_autoinc_lock, wobei a>7;
Abfrage OK, 2 Zeilen betroffen (0,00 Sek.)
mysql> wähle * aus test_autoinc_lock;
+----+------+
| Ich würde | ein |
+----+------+
| 1 | 1 |
| 12 | 2 |
| 13 | 2 |
| 2 | 3 |
| 3 | 5 |
| 4 | 7 |
| 5 | 7 |
| 6 | 9 |
| 7 | 10 |
+----+------+
9 Zeilen im Satz (0,00 Sek.) //Beachten Sie, dass die maximale automatische Inkrementierung zu diesem Zeitpunkt 13 beträgt


Sitzung2
mysql> insert into test_autoinc_lock(a) values(100); //Die gleiche Lückensperre existiert und die Sperre wartet auf Sitzung 3
mysql> in test_autoinc_lock(a) Werte(5) einfügen;
Abfrage OK, 1 Zeile betroffen (0,00 Sek.)


mysql> wähle * aus test_autoinc_lock;
+----+------+
| Ich würde | ein |
+----+------+
| 1 | 1 |
| 12 | 2 |
| 13 | 2 |
| 2 | 3 |
| 3 | 5 |
| 15 | 5 |
| 4 | 7 |
| 5 | 7 |
| 6 | 9 |
| 7 | 10 |
+----+------+
10 Zeilen im Set (0,00 Sek.) //session3 wird direkt abgeschlossen. Beachten Sie, dass der eingefügte Auto-Increment-ID-Wert 15 ist, was bedeutet, dass die 14, die Session2 zugewiesen werden sollte, übersprungen wird. Sie können sehen, dass der Auto-Increment-ID-Wert sofort Session3 zugewiesen wird, ohne dass Sie warten müssen, bis Session2 die Ausführung abgeschlossen hat.

Fazit: Wenn innodb_autoinc_lock_mode 1 ist, wird es offiziell als aufeinanderfolgend bezeichnet

Auf dieser Ebene kann, wenn es sich um ein einzelnes Insert-SQL handelt, die Sperre sofort erworben und freigegeben werden, ohne auf die Ausführung des aktuellen SQL warten zu müssen (es sei denn, eine Sitzung hat die Auto-Increment-Sperre bereits in anderen Transaktionen erworben). Darüber hinaus handelt es sich auch dann noch um eine Sperre auf Tabellenebene, wenn es sich bei dem SQL um eine Art Batch-Insert-SQL handelt, wie etwa „insert into ...select ...“, „load data“, „replace ..select ...“. Dies kann so verstanden werden, dass man auf die Ausführung des aktuellen SQL warten muss, bevor man es freigeben kann.

Man kann davon ausgehen, dass es sich bei einem Wert von 1 um eine relativ leichte Sperre handelt und die Replikation nicht beeinträchtigt wird. Der einzige Nachteil besteht darin, dass der generierte Autoinkrementwert möglicherweise nicht vollständig kontinuierlich ist (aber ich persönlich denke, dass dies oft nicht sehr wichtig ist und es nicht erforderlich ist, die Anzahl der Zeilen basierend auf dem Autoinkrement-ID-Wert zu zählen).

Bedingung 3: innodb_autoinc_lock_mode ist auf 2 gesetzt

Lassen Sie mich zunächst die Schlussfolgerung ziehen: Wenn innodb_autoinc_lock_mode auf 2 gesetzt ist, können alle SQL-Anweisungen vom Typ „Insert“ sofort Sperren erwerben und freigeben, was am effizientesten ist. Es wird jedoch ein neues Problem eingeführt: Wenn binlog_format eine Anweisung ist, kann die Sicherheit der Replikation nicht garantiert werden, da Batch-Einfügungen, wie z. B. Einfügen ..select...-Anweisungen, in diesem Fall auch sofort eine große Anzahl von automatisch inkrementierten ID-Werten erhalten können, ohne die gesamte Tabelle zu sperren. Der Slave wird beim Wiedergeben dieses SQL zwangsläufig verwirrt. Führen wir einen Test durch, um zu überprüfen, ob die Replikation nicht sicher ist.

Master-Sitzung1
mysql> Variablen wie „%binlog_for%“ anzeigen;
+---------------+-----------+
| Variablenname | Wert |
+---------------+-----------+
| binlog_format | ANWEISUNG |
+---------------+-----------+
1 Zeile im Satz (0,00 Sek.)
mysql> einfügen in test_autoinc_lock(a) select * from test_auto;
Abfrage OK, 8388608 Zeilen betroffen, 1 Warnung (29,85 Sek.)
Datensätze: 8388608 Duplikate: 0 Warnungen: 1


Master-Sitzung2 (beachten Sie, dass Sitzung2 ausgeführt wird, bevor Sitzung1 abgeschlossen ist)
mysql> in test_autoinc_lock(a) Werte(2) einfügen;
Abfrage OK, 1 Zeile betroffen (0,01 Sek.)
mysql> wähle * aus test_autoinc_lock, wobei a=2;
+---------+------+
| Ich würde | ein |
+---------+------+
| 1376236 | 2 |
+---------+------+
1 Zeile im Satz (0,00 Sek.)


Slave-Sitzung1 (zu diesem Zeitpunkt sind 1376236 Primärschlüsselkonflikte zu sehen)
mysql> Slave-Status anzeigen\G
*************************** 1. Reihe ***************************
        Slave_IO_State: Wartet darauf, dass der Master ein Ereignis sendet
         Master_Host: 10.9.73.139
         Master_Benutzer: ucloudbackup
         Master_Port: 3306
        Verbindungswiederholung: 60
       Master_Log_File: mysql-bin.000006
     Read_Master_Log_Pos: 75823243
        Relay-Logdatei:mysql-relay.000002
        Relay_Log_Pos: 541
    Relay_Master_Log_File: mysql-bin.000006
       Slave_IO_Running: Ja
      Slave_SQL_Running: Nein
       Replicate_Do_DB: 
     Replikat_Ignorieren_DB: 
      Tabelle_replizieren: 
    Tabelle_Ignorieren_replizieren: 
   Wild_Do_Tabelle replizieren: 
 Tabelle_Wild_Ignore_replizieren: 
          Letzte_Fehlernummer: 1062
          Last_Error: Fehler „Doppelter Eintrag „1376236“ für Schlüssel „PRIMARY“ bei Abfrage. Standarddatenbank: „test“. Abfrage: „insert into test_autoinc_lock(a) select * from test_auto“
         Skip_Counter: 0
     Exec_Master_Log_Pos: 75822971

Wir können die Ursache des Problems leicht finden, indem wir das Binärprotokoll der Master-Datenbank analysieren. Als der erste Batch-Eintrag nicht abgeschlossen wurde, erhielt der zweite einfache Eintrag eine Sperre mit einem Auto-Increment-ID-Wert von 1376236. Beim Schreiben in die Master-Datenbank gibt es zu diesem Zeitpunkt kein Problem, aber wenn es in der Slave-Datenbank widergespiegelt wird, tritt zwangsläufig ein Primärschlüsselkonflikt auf, da es sich um eine anweisungsbasierte Replikation handelt.

SETZEN SIE INSERT_ID=1376236/*!*/;
#161031 21:44:31 Server-ID 168380811 End-Log-Pos 75822940 CRC32 0x65797f1c Abfrage Thread-ID = 20 Exec-Zeit = 0 Fehlercode = 0
verwende „test“/*!*/;
ZEITSTEMPEL FESTLEGEN=1477921471/*!*/;
in test_autoinc_lock(a) Werte einfügen(2)
/*!*/;
# bei 75822940
#161031 21:44:31 Server-ID 168380811 end_log_pos 75822971 CRC32 0xbb91449d Xid = 274
BEGEHEN /*!*/;
# bei 75822971
#161031 21:44:26 Server-ID 168380811 End-Log-Pos 75823050 CRC32 0xa297b57b Abfrage Thread-ID = 57 Exec-Zeit = 30 Fehlercode = 0
ZEITSTEMPEL EINSTELLEN=1477921466/*!*/;
BEGINNEN
/*!*/;
# bei 75823050
# bei 75823082
#161031 21:44:26 Server-ID 168380811 end_log_pos 75823082 CRC32 0xa5aa31a1 Intvar
SETZEN SIE INSERT_ID=1/*!*/;
#161031 21:44:26 Server-ID 168380811 End-Log-Pos 75823212 CRC32 0x470282ba Abfrage Thread-ID = 57 Exec-Zeit = 30 Fehlercode = 0
ZEITSTEMPEL EINSTELLEN=1477921466/*!*/;
in test_autoinc_lock(a) einfügen, * aus test_auto auswählen

Zusammenfassen:

1 Beim Kopieren von InnoDB-Zeilen können Sie innodb_autoinc_lock_mode auf 2 setzen, wodurch die Parallelität der Tabelle in allen Einfügesituationen maximiert wird.

2 Beim Replizieren von InnoDB-Anweisungen können Sie innodb_autoinc_lock_mode auf 1 setzen, um die Replikationssicherheit zu gewährleisten und gleichzeitig maximale Parallelität für einfache Einfügeanweisungen zu erreichen.

3 Im Fall der MyISAM-Engine ist das Festlegen des Parameters innodb_autoinc_lock_mode ungültig (Test ausgelassen), unabhängig davon, welche Art von automatisch inkrementeller ID-Sperre eine Sperre auf Tabellenebene ist.

4 Tatsächlich erwähnte der Fragesteller, dass bei Verwendung des Auto-Increment-ID-Werts als Primärschlüssel unter der InnoDB-Engine die Einfügegeschwindigkeit im Vergleich zu UUID oder einem benutzerdefinierten Primärschlüssel verbessert werden kann, da InnoDB ein Primärschlüssel-Clusterindex ist und auf den tatsächlichen Primärschlüsselwert in der Reihenfolge des Primärschlüssels zugegriffen werden muss. Dann erfolgt die Auto-Increment-ID selbst in aufsteigender Reihenfolge, sodass beim Einfügen von Daten die darunterliegende Ebene keine zusätzlichen Sortiervorgänge durchführen muss und die Anzahl der Indexseitenaufteilungen reduziert wird, wodurch die Einfügegeschwindigkeit erheblich erhöht wird (es sei denn, andere Lösungen können auch sicherstellen, dass der Primärschlüssel vollständig automatisch inkrementiert wird).

Die obige kurze Diskussion über die Manifestation und die Referenzmethode zur Wertauswahl von innodb_autoinc_lock_mode ist der gesamte Inhalt, den der Editor mit Ihnen teilt. Ich hoffe, er kann Ihnen als Referenz dienen. Ich hoffe auch, dass Sie 123WORDPRESS.COM unterstützen.

<<:  Detaillierte Erläuterung mehrerer Möglichkeiten zum Schreiben privater Variablen der ES6-Implementierungsklasse

>>:  Anfangseinstellungen nach der Installation von Ubuntu 16 in der Entwicklungsumgebung

Artikel empfehlen

Wie gestaltet man eine Webseite? Wie erstelle ich eine Webseite?

Wenn es um das Verständnis von Webdesign geht, sc...

HTML-, CSS- und JS-Kompatibilitätsbaum (IE, Firefox, Chrome)

Was ist ein Baum im Webdesign? Einfach ausgedrückt...

10 Tipps zur Website-Benutzerfreundlichkeit, die jeder kennen sollte

Lassen Sie uns keine weitere Zeit verschwenden un...

Interviewer stellen häufig Fragen zum Lebenszyklus von React

React-Lebenszyklus Zwei Bilder zum besseren Verst...

HTML-Formular_PowerNode Java Academy

1. Formular 1. Die Rolle des Formulars HTML-Formu...

Was ist ein MIME-TYP? MIME-Typen-Typensammlung

Was ist ein MIME-TYP? 1. Zunächst müssen wir verst...

Was bei der Migration von MySQL auf 8.0 zu beachten ist (Zusammenfassung)

Passwortmodus PDO::__construct(): Der Server hat ...

Grundlegender JSON-Betriebsleitfaden in MySQL 5.7

Vorwort Aufgrund der Projektanforderungen werden ...

Detailliertes Beispiel der MySQL curdate()-Funktion

Einführung in die MySQL CURDATE-Funktion Bei Verw...

Native JS-Implementierung der Lupenkomponente

In diesem Artikelbeispiel wird der spezifische Co...

Saubere XHTML-Syntax

Das Schreiben von XHTML erfordert eine saubere HTM...