Problemphänomen Ich habe kürzlich Sysbench verwendet, um MySQL zu testen. Da der Test lange dauerte, habe ich ein Skript geschrieben, das im Hintergrund in der Reihenfolge Vorbereiten->Ausführen->Bereinigen ausgeführt wurde. Nach dem Lauf habe ich das Protokoll überprüft und ein Problem festgestellt. Im Fehlerprotokoll des MySQL-Dienstes waren mehrere Fehler ähnlich den folgenden enthalten:
Es sieht nach einem E/A-Fehler aus, aber der MySQL-Prozess ist nicht abgestürzt und der Sysbench-Client hat keinen Fehler gemeldet. Problemerkennungsprozess Anhand der Zeitaufzeichnung des Fehlers und des Vergleichs der Zeitpunkte der einzelnen Phasen der Skriptausgabe wurde ermittelt, dass der zu diesem Zeitpunkt vom Skript ausgeführte Befehl folgender war:
Ich habe den Testfall erneut manuell ausgeführt, aber die gleiche Situation ist nicht erneut aufgetreten. Allerdings tritt diese Fehlermeldung bei der Ausführung des Skripts immer noch auf. Der erste Verdacht liegt darin, dass dieses Problem durch die kurze Zeitspanne zwischen Ausführung und Bereinigung ausgelöst wird. Da die Ausführung von 100 G Daten lange dauert und die Wiederholungskosten hoch sind, versuchen Sie zunächst, die Menge der Anwendungsfalldaten zu reduzieren. Ändern Sie --table-size=4000000 in 2000000. Bei der Ausführung des Skripts wird dieses Problem nicht mehr ausgelöst. Ändern Sie abschließend --table-size=3000000, um den Auslöser zu stabilisieren und die Reproduktionszeit zu verkürzen. Um zu bestätigen, dass das Problem aufgrund des langen Intervalls nicht reproduziert werden konnte, wurde das Skript so geändert, dass es zwischen der Ausführungs- und der Bereinigungsphase 10 Sekunden lang pausiert. Tatsächlich wurde diese Fehlermeldung nicht ausgelöst. Wenn Sie es auf einen Ruhezustand von 5 Sekunden ändern, kann es immer noch ausgelöst werden, aber die Anzahl der gemeldeten Fehler wurde reduziert. Problemuntersuchung Beim Betrachten des Codes der entsprechenden Version von mysql5.7.22 stellte ich fest, dass dieser Fehler nur an einer Stelle auftritt: in der Funktion fil_io() in Zeile 5578 der Datei fil0fil.cc. Verwenden Sie das GDB-Debugging direkt, fügen Sie an dieser Stelle einen Haltepunkt hinzu und führen Sie ein reproduzierbares Skript aus, um den folgenden Stapel zu erhalten: (gdb) bt #0 fil_io (Typ=..., Sync=Sync@Eintrag=false, Seiten-ID=..., Seitengröße=..., Byte-Offset=Byte-Offset@Eintrag=0, Länge=16384, Puffer=0x7f9ead544000, Nachricht=Nachricht@Eintrag=0x7f9ea8ce9c78) bei mysql-5.7.22/storage/innobase/fil/fil0fil.cc:5580 #1 0x00000000010f99fa in buf_read_page_low (Fehler=0x7f9ddaffc72c, Sync=<optimiert raus>, Typ=0, Modus=<optimiert raus>, Seiten-ID=..., Seitengröße=..., unzip=true) bei mysql-5.7.22/storage/innobase/buf/buf0rea.cc:195 #2 0x00000000010fc5fa in buf_read_ibuf_merge_pages (sync=sync@entry=false, space_ids=space_ids@entry=0x7f9ddaffc7e0, page_nos=page_nos@entry=0x7f9ddaffc7a0, n_stored=2) bei mysql-5.7.22/storage/innobase/buf/buf0rea.cc:834 #3 0x0000000000f3a86c in ibuf_merge_pages (n_pages=n_pages@entry=0x7f9ddaffce30, sync=sync@entry=false) bei mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2552 #4 0x0000000000f3a94a in ibuf_merge (sync=false, sync=false, n_pages=0x7f9ddaffce30) bei mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2656 #5 ibuf_merge_in_background (voll=voll@eintrag=false) bei mysql-5.7.22/storage/innobase/ibuf/ibuf0ibuf.cc:2721 #6 0x000000000102bcf4 in srv_master_do_active_tasks () bei mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2132 #7 srv_master_thread (arg=<optimized out>) bei mysql-5.7.22/storage/innobase/srv/srv0srv.cc:2383 #8 0x00007fa003eeddc5 in start_thread () von /lib64/libpthread.so.0 #9 0x00007fa002aab74d in Klon () von /lib64/libc.so.6 Offensichtlich ist dies der Hintergrund-Thread, der den Einfügepuffer-Zusammenführungsvorgang durchführt. Zu diesem Zeitpunkt wird festgestellt, dass space->stop_new_ops wahr ist, was bedeutet, dass der Bereich, zu dem die zu verarbeitende Seite gehört, gelöscht wird. Warum sollten Sie einen Speicherplatz bearbeiten, der gelöscht wird? Hierzu ist eine Untersuchung der Einfügepufferfunktion, des Einfügepufferzusammenführungsprozesses und des Tabellenlöschprozesses erforderlich. Hintergrundwissen zum Einfügepuffer Der Einfügepuffer ist eine spezielle Datenstruktur (B+-Baum), die Änderungen zwischenspeichert, wenn sich die Hilfsindexseite nicht im Pufferpool befindet, und sie später zusammenführt, wenn die Seite durch andere Lesevorgänge in den Pufferpool geladen wird. Als MySQL diese Funktion erstmals einführte, konnte es nur Einfügevorgänge zwischenspeichern, daher hieß es Einfügepuffer. Jetzt können diese Vorgänge INSERT, UPDATE oder DELETE (DML) sein, daher heißt es Änderungspuffer (in diesem Artikel wird es immer noch als Einfügepuffer beschrieben), aber ibuf wird immer noch als Bezeichner im Quellcode verwendet. Diese Funktion speichert mehrere Aktualisierungen derselben Seite im Cache und führt sie zu einem einmaligen Aktualisierungsvorgang zusammen. Dadurch wird der IO-Aufwand reduziert und zufälliger IO-Aufwand in sequentieller IO-Aufwand umgewandelt. Dadurch können Leistungsverluste durch zufälligen IO-Aufwand vermieden und die Schreibleistung der Datenbank verbessert werden. Zugehörige Einfügepuffer-Zusammenführungslogik Wenn die Pufferseite in den Pufferpool gelesen wird, wird eine Einfügepufferung durchgeführt. Der Zusammenführungsprozess findet in mehreren Hauptszenarien statt:
Unser Problem dieses Mal gehört eindeutig zum zweiten Fall. Der InnoDB-Hauptthread (svr_master_thread) führt jede Sekunde aktiv einen Zusammenführungsvorgang im Einfügepuffer aus. Stellen Sie zunächst fest, ob in der letzten Sekunde eine Aktivität auf dem Server stattgefunden hat (z. B. Einfügen von Tupeln in Seiten, Zeilenoperationen in Undo-Tabellen usw.). Wenn dies der Fall ist, beträgt die maximale Anzahl der zusammenzuführenden Seiten 5 % der innodb_io_capacity-Einstellung. Wenn nicht, ist die maximale Anzahl der zusammenzuführenden Seiten der durch innodb_io_capacity festgelegte Wert. Der Hauptprozess zum Zusammenführen des InnoDB-Hauptthreads (svr_master_thread) ist wie folgt:
Logik zum Löschen verknüpfter Tabellen
Abschluss Die Situation ist sehr klar. Es gibt keine Sperre, die den gegenseitigen Ausschluss zwischen dem Prozess des Hauptthreads zum Abrufen von Ibufs (Speicherplatz, Seite) und dem Prozess zum Ausführen des Löschvorgangs gewährleistet. Nur der Zusammenführungsvorgang und der Löschvorgang nach Abschluss der asynchronen E/A schließen sich gegenseitig aus. Wenn der Hintergrund-Thread ibuf merge startet und Schritt 2 der Erkennung ausgeführt hat, aber Schritt 3 der Erkennung noch nicht ausgeführt hat, und der Benutzer-Thread mit dem Löschen der Tabelle beginnt und das Flag stop_new_ops setzt, aber Schritt 5 zum Löschen des Tablespace-Cache noch nicht ausgeführt hat, wird diese Fehlermeldung angezeigt. Die Interaktion zwischen den beiden Threads wird in der folgenden Abbildung dargestellt: Wenn nichts Unerwartetes passiert, muss es einen Thread geben, der den Löschvorgang der entsprechenden Tabelle ausführt, wenn der Haltepunkt erreicht wird. Tatsächlich können wir den folgenden Stapel finden: Thread 118 (Thread 0x7f9de0111700 (LWP 5234)): #0 0x00007fa003ef1e8e in pthread_cond_broadcast@@GLIBC_2.3.2 () von /lib64/libpthread.so.0 #1 0x0000000000f82f41 im Broadcast (dies=0xd452ef8) bei mysql-5.7.22/storage/innobase/os/os0event.cc:184 #2 gesetzt (dies=0xd452ef8) bei mysql-5.7.22/storage/innobase/os/os0event.cc:75 #3 os_event_set (Ereignis=0xd452ef8) bei mysql-5.7.22/storage/innobase/os/os0event.cc:483 #4 0x00000000010ec8a4 im Signal (dieses = <optimized out>) bei mysql-5.7.22/storage/innobase/include/ut0mutex.ic:105 #5 beenden (dies = <optimized out>) bei mysql-5.7.22/storage/innobase/include/ib0mutex.h:690 #6 beenden (dies = <optimized out>) bei mysql-5.7.22/storage/innobase/include/ib0mutex.h:961 #7 buf_flush_yield (bpage=<optimiert aus>, buf_pool=<optimiert aus>) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:405 #8 buf_flush_try_yield (verarbeitet=<optimiert>, bpage=<optimiert>, buf_pool=<optimiert>) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:449 #9 buf_flush_or_remove_pages (trx=<optimiert aus>, flush=<optimiert aus>, observer=<optimiert aus>, id=<optimiert aus>, buf_pool=<optimiert aus>) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:632 #10 buf_flush_dirty_pages (buf_pool=<optimiert aus>, id=<optimiert aus>, observer=<optimiert aus>, flush=<optimiert aus>, trx=<optimiert aus>) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:693 #11 0x00000000010f6de7 in buf_LRU_remove_pages (trx=0x0, buf_remove=BUF_REMOVE_FLUSH_NO_WRITE, id=55, buf_pool=0x31e55e8) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:893 #12 buf_LRU_flush_or_remove_pages (id=id@entry=55, buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE, trx=trx@entry=0x0) bei mysql-5.7.22/storage/innobase/buf/buf0lru.cc:951 #13 0x000000000114e488 in fil_delete_tablespace (id=id@entry=55, buf_remove=buf_remove@entry=BUF_REMOVE_FLUSH_NO_WRITE) bei mysql-5.7.22/storage/innobase/fil/fil0fil.cc:2800 #14 0x0000000000fe77bd in row_drop_single_table_tablespace (trx=0x0, is_encrypted=false, is_temp=false, Dateipfad=0x7f9d7c209f38 "./sbtest/sbtest25.ibd", Tabellenname=0x7f9d7c209dc8 "sbtest/sbtest25", Space-ID=55) bei mysql-5.7.22/storage/innobase/row/row0mysql.cc:4189 #15 row_drop_table_for_mysql (name=name@entry=0x7f9de010e020 "sbtest/sbtest25", trx=trx@entry=0x7f9ff9515750, drop_db=<optimiert>, nonatomic=<optimiert>, nonatomic@entry=true, handler=handler@entry=0x0) bei mysql-5.7.22/storage/innobase/row/row0mysql.cc:4741 #16 0x0000000000f092f3 in ha_innobase::delete_table (dies=<optimized out>, Name=0x7f9de010f5e0 "./sbtest/sbtest25") bei mysql-5.7.22/storage/innobase/handler/ha_innodb.cc:12539 #17 0x0000000000801a30 in ha_delete_table (thd=thd@entry=0x7f9d7c1f6910, table_type=table_type@entry=0x2ebd100, path=path@entry=0x7f9de010f5e0 "./sbtest/sbtest25", db=db@entry=0x7f9d7c00e560 "sbtest", alias=0x7f9d7c00df98 "sbtest25", generate_warning=generate_warning@entry=true) bei mysql-5.7.22/sql/handler.cc:2586 #18 0x0000000000d0a6af in mysql_rm_table_no_locks (thd=thd@entry=0x7f9d7c1f6910, tables=tables@entry=0x7f9d7c00dfe0, if_exists=true, drop_temporary=false, drop_view=drop_view@entry=false, dont_log_query=dont_log_query@entry=false) bei mysql-5.7.22/sql/sql_table.cc:2546 #19 0x0000000000d0ba58 in mysql_rm_table (thd=thd@entry=0x7f9d7c1f6910, tables=tables@entry=0x7f9d7c00dfe0, if_exists=<optimized out>, drop_temporary=<optimized out>) bei mysql-5.7.22/sql/sql_table.cc:2196 #20 0x0000000000c9d90b in mysql_execute_command (thd=thd@entry=0x7f9d7c1f6910, first_level=first_level@entry=true) bei mysql-5.7.22/sql/sql_parse.cc:3589 #21 0x0000000000ca1edd in mysql_parse (thd=thd@entry=0x7f9d7c1f6910, parser_state=parser_state@entry=0x7f9de01107a0) bei mysql-5.7.22/sql/sql_parse.cc:5582 #22 0x0000000000ca2a20 im dispatch_command (thd=thd@entry=0x7f9d7c1f6910, com_data=com_data@entry=0x7f9de0110e00, Befehl=COM_QUERY) bei mysql-5.7.22/sql/sql_parse.cc:1458 #23 0x0000000000ca4377 in do_command (thd=thd@entry=0x7f9d7c1f6910) bei mysql-5.7.22/sql/sql_parse.cc:999 #24 0x0000000000d5ed00 in handle_connection (arg=arg@entry=0x10b8e910) bei mysql-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:300 #25 0x0000000001223d74 in pfs_spawn_thread (Argument = 0x10c48f40) bei mysql-5.7.22/storage/perfschema/pfs.cc:2190 #26 0x00007fa003eeddc5 in start_thread () von /lib64/libpthread.so.0 #27 0x00007fa002aab74d in Klon () von /lib64/libc.so.6 Lösung Fügen Sie einen neuen Parameter ignore_missing_space für buf_read_ibuf_merge_pages, buf_read_page_low und fil_io hinzu. Gibt an, dass der zu löschende Speicherplatz ignoriert wird. Der Standardwert ist „false“ und wird auf „true“ gesetzt, wenn ibuf_merge_pages aufgerufen wird. Im Fehlermeldebereich von fil_io wird zusätzlich ermittelt, ob der Parameter true ist. Wenn dies der Fall ist, wird kein Fehler gemeldet und andere Prozesse werden fortgesetzt. Oder übergeben Sie direkt den Parameter IORequest::IGNORE_MISSING, wenn buf_read_ibuf_merge_pages buf_read_page_low aufruft. Den spezifischen Code finden Sie im MariaDB-Commit: 8edbb1117a9e1fd81fbd08b8f1d06c72efe38f44 Betroffene Versionen Überprüfen Sie die relevanten Informationen. Dieses Problem trat beim Löschen der Tablespace-Version beim Ändern von Bug#19710564 auf.
Optimierungsvorschläge Die Leistung kann wie folgt optimiert werden: Notieren Sie die fehlerhafte Speicher-ID in buf_read_ibuf_merge_pages, bestimmen Sie während der Schleife die Speicher-ID der nächsten Seite und löschen Sie, wenn die Speicher-ID dieselbe ist, direkt den entsprechenden ibuf-Datensatz (die aktuell zugewiesene maximale Speicher-ID wird im Systemtabellenbereich aufgezeichnet, die Speicher-ID belegt 4 Bytes, was niedriger als 0xFFFFFFF0UL ist. Lesen Sie beim Zuweisen den im Systemtabellenbereich gespeicherten Wert und fügen Sie dann eins hinzu, um ihn eindeutig zu machen). Zusammenfassen Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Wenn Sie Fragen haben, können Sie eine Nachricht hinterlassen. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Das könnte Sie auch interessieren:
|
<<: Analyse der Implementierung der Nginx Rush-Kaufstrombegrenzungskonfiguration
>>: So verstehen Sie den einfachen Speichermodus der Statusverwaltung von Vue
In diesem Artikelbeispiel wird der spezifische Co...
Früher hatte fast jede Website eine Sitemap-Seite...
Mysql mehrere unabhängige Tabellen Abfragedaten u...
MySQL-Escape Escape bedeutet die ursprüngliche Se...
Diese Datenbankabfrageanweisung ist eine von 50 D...
<br /> Im ersten und zweiten Teil haben wir ...
Vorwort Führen Sie den Befehl show create table &...
Inhaltsverzeichnis 1. Ereignisablauf 1. Konzept 2...
Was ist ein Deckungsindex? Das Erstellen eines In...
In diesem Artikel wird der spezifische Code der o...
Wenn die Datenbank gleichzeitig denselben Datenst...
In Tomcat ist JSP nicht verstümmelt, aber HTML-Ch...
Inhaltsverzeichnis 1. Wie verwende ich Mixin? 2. ...
In diesem Artikel wird der spezifische Code von R...
In diesem Artikel wird der spezifische Code für J...