ProblembeschreibungDer Benutzer hat einen Änderungsvorgang an der primären Datenbank durchgeführt, der etwa eine Stunde dauerte. Nachdem der Vorgang abgeschlossen ist, stellt die Slave-Datenbank fest, dass eine Synchronisierungsverzögerung vorliegt, aber der Indikator „Seconds_Behind_Master“ im Überwachungsdiagramm zeigt 0 an und die Verzögerungsdistanz des Binärprotokolls nimmt ständig zu. PrinzipanalyseDa wir die Verzögerungszeit analysieren, beginnen wir natürlich mit der Berechnung der Verzögerung. Der Einfachheit halber wird hier der Quellcode der offiziellen Version 5.7.31 zum Lesen zitiert. Hier finden Sie den Code zur Berechnung der Verzögerungszeit: ./sql/rpl_slave.cc bool show_slave_status_send_data(THD *thd, Master_info *mi, char* io_gtid_set_buffer, char* sql_gtid_set_buffer) ...... wenn ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) && (!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name()))) { wenn (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) Protokoll->Speichern(0LL); anders Protokoll->store_null(); } anders { langer Zeitunterschied = ((lang)(Zeit(0) - mi->rli->letzter_Masterzeitstempel) - mi->Uhrdifferenz mit Master); Protokoll->Speichern((langlang)(mi->rli->letzter_Master_Zeitstempel? max(0L, Zeitdifferenz) : 0)); } ...... Aus der Berechnungsmethode von time_diff können wir feststellen, dass diese Verzögerung grundsätzlich eine Zeitdifferenz ist, und dann wird die Zeitdifferenz zwischen dem Master und dem Slave berechnet. Da es jedoch viele if-Anweisungen gibt, verwende ich die Kommentare in der Quellcodedatei: /* Der Pseudocode zur Berechnung von Seconds_Behind_Master: wenn (SQL-Thread läuft) { if (SQL-Thread hat alle verfügbaren Relay-Protokolle verarbeitet) { wenn (IO-Thread läuft) drucke 0; anders drucke NULL; } anders Berechnen Sie Seconds_Behind_Master. } anders drucke NULL; */ Es ist ersichtlich, dass die Berechnung von Seconds_Behind_Master in zwei Teile unterteilt ist:
Achten Sie dann bei der Berechnung der Verzögerungszeit am Ende auf die Bedeutung dieser Variablen:
Es ist ersichtlich, dass bei der Berechnung der Verzögerung der Wert tatsächlich dadurch erhalten wird, dass die Zeit, zu der das wiedergegebene Ereignis auf dem Master ausgeführt wird, von der Ortszeit des Slaves abgezogen und dann die Zeitdifferenz zwischen beiden ausgeglichen wird. Logischerweise gibt es kein Problem. Da time(0) und clock_diff_with_master normalerweise nicht falsch sein können, sollte das Problem dieses Mal bei last_master_timestamp liegen. PS: Obwohl es meistens kein Problem gibt, nimmt time(0) die Ortszeit an. Wenn also ein Problem mit der Ortszeit des Slaves vorliegt, ist der Endwert auch falsch, aber das liegt nicht im Rahmen dieses Falls. Finden Sie dann die Logik zur Berechnung des last_master_timestamp bei der Ausführung des Ereignisses. In Kombination mit den Kommentaren können wir feststellen, dass normale Replikation und parallele Replikation unterschiedliche Berechnungsmethoden verwenden. Die erste ist die normale Replikation und der Berechnungszeitpunkt liegt vor der Ausführung des Ereignisses: ./sql/rpl_slave.cc ...... wenn (ev) { Aufzählung enum_slave_apply_event_and_update_pos_retval exec_res; ptr_ev= &ev; /* Auch wenn wir dieses Ereignis nicht ausführen, behalten wir den Master-Zeitstempel, damit die Sekunden hinter dem Master das richtige Delta zeigen (es gibt Ereignisse die nicht wiederholt werden, sodass wir immer wieder in Rückstand geraten). Handelt es sich um ein künstliches Ereignis oder um ein Relay-Log-Ereignis (vom IO-Thread generiert event) oder ev->when auf 0 gesetzt ist, oder ein FD vom Master, oder ein Heartbeat Ereignis mit Server-ID „0“, dann aktualisieren wir den letzten Master-Zeitstempel nicht. Bei paralleler Ausführung wird last_master_timestamp nur aktualisiert, wenn ein Job wird aus GAQ genommen. Wenn also last_master_timestamp 0 ist (was zeigt an, dass GAQ leer ist, alle Slave-Worker warten auf Ereignisse von der Koordinator), müssen wir es mit einem Zeitstempel vom ersten initialisieren Ereignis, das parallel ausgeführt werden soll. */ wenn ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) && !(ev->is_artificial_event() || ev->is_relay_log_event() || (ev->common_header->when.tv_sec == 0) || ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT || ev->server_id == 0)) { rli->last_master_timestamp = ev->common_header->when.tv_sec + (Zeit_t) ev->Ausführungszeit; DBUG_ASSERT(rli->last_master_timestamp >= 0); } ...... Der Wert von last_master_timestamp ist die Startzeit des Ereignisses plus die Ausführungszeit. In 5.7 hatten viele Ereignisse keinen Ausführungszeitwert. 8.0 fügt diesen Wert vielen Ereignissen hinzu, sodass dies als Vorteil des Upgrades auf 8.0 angesehen werden kann. Die Berechnungsmethode der parallelen Replikation lautet wie folgt: ./sql/rpl\_slave.cc ...... /* Wir müssen sicherstellen, dass dies an dieser Stelle nie aufgerufen wird, wenn cnt ist Null. Dieser Wert bedeutet, dass die Checkpoint-Informationen wird komplett zurückgesetzt. */ /* Aktualisieren Sie den rli->last_master_timestamp, um den korrekten Seconds_behind_master zu melden. Wenn GAQ leer ist, setzen Sie es auf Null. Andernfalls aktualisieren Sie es mit dem Zeitstempel des ersten Jobs der Slave_job_queue die in der Funktion Log_event::get_slave_worker() zugewiesen wurde. */ ts = rli->gaq->leer() ? 0 : neu interpretieren_cast<Slave_job_group*>(rli->gaq->head_queue())->ts; rli->reset_notified_checkpoint(cnt, ts, brauche_Datensperre, true); /* Ende von "Koordinator::"commit_positions" */ ...... Wenn in der Commit_Positions-Logik des Koordinators die Gaq-Warteschlange leer ist, wird der Last_Master_Timestamp direkt auf 0 gesetzt, andernfalls wird der Zeitstempel des ersten Jobs in der Gaq-Warteschlange ausgewählt. Es sollte hinzugefügt werden, dass diese Berechnung nicht in Echtzeit, sondern intermittierend erfolgt. Vor der Berechnungslogik steht die folgende Logik: /* Derzeit wird die Checkpoint-Routine vom SQL-Thread aufgerufen. Aus diesem Grund heißt diese Funktion Aufruf von entsprechenden Punkten im Ausführungspfad des SQL-Threads und die verstrichene Zeit wird berechnet Überprüfen Sie hier, ob es Zeit ist, es auszuführen. */ set_timespec_nsec(&aktuelle_Uhr, 0); ulonglong diff = diff_timespec(&aktuelle_Uhr, &rli->letzte_Uhr); wenn (!force && diff < Punkt) { /* Wir müssen den Checkpoint jetzt nicht ausführen, weil die verstrichene Zeit reicht nicht aus. */ DBUG_RETURN(FALSE); } Das heißt, innerhalb des Zeitintervalls dieses Zeitraums wird es direkt zurückgegeben und der last_master_timestamp wird nicht aktualisiert. Daher werden Sie manchmal feststellen, dass sich der Wert von Seconds_Behind_Master bei der parallelen Replikation von Zeit zu Zeit von 0 auf 1 ändert. Der Vorgang der gaq-Warteschlange ähnelt wahrscheinlich den Push- und Pop-Vorgängen des Stapels, sodass die in gaq verbleibenden Transaktionen immer nicht abgeschlossene Transaktionen sind. Daher ist die Zeitberechnung aus der Perspektive allgemeiner Szenarien in Ordnung. ProblemanalyseDie Prinzipanalyse erläutert kurz die Logik der gesamten Berechnung. Kommen wir nun zur eigentlichen Frage zurück. Bei Tencent Cloud Database MySQL ist die parallele Replikation standardmäßig aktiviert, sodass eine gaq-Warteschlange vorhanden ist und der Änderungsvorgang sehr lange dauert. Unabhängig davon, ob der Änderungsvorgang in einer Gruppe paralleler Transaktionen ausgeführt wird (höchstwahrscheinlich ist DDL immer eine separate Transaktionsgruppe), ist die gaq-Warteschlange schließlich leer und last_master_timestamp wird auf 0 gesetzt. In Bezug auf die Berechnungslogik von Seconds_Behind_Master wird der endgültige time_diff ebenfalls auf 0 gesetzt, sodass die Verzögerungszeit vor dem Ende des Änderungsvorgangs immer 0 beträgt. Nachdem der Änderungsvorgang ausgeführt wurde, wird die Gaq-Warteschlange mit neuen Ereignissen und Transaktionen gefüllt, sodass die Verzögerung vorher möglicherweise 0 beträgt, aber plötzlich auf einen sehr hohen Wert springt. ExpandierenWenn wir die Unterschiede in den Berechnungsmethoden zwischen normaler Replikation und paralleler Replikation vergleichen, können wir die folgenden Merkmale erkennen:
Um zusammenzufassenFür eine strenge Beurteilung der Verzögerung ist es besser, sich auf die GTID-Lücke und die Binlog-Positionslücke zu verlassen. Gemessen an den Änderungen der Ereignisausführungszeit in 8.0 arbeiten zumindest die Verantwortlichen von Oracle noch hart daran. Ich hoffe, diese kleineren Probleme können so schnell wie möglich behoben werden. Oben finden Sie ausführliche Informationen dazu, warum Seconds_Behind_Master bei einer MySQL-Synchronisierungsverzögerung immer noch 0 ist. Weitere Informationen zur MySQL-Synchronisierungsverzögerung Seconds_Behind_Master ist 0 finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Beispielcode zur Implementierung des Dunkelmodus mit CSS-Variablen
>>: Detaillierte Erklärung der JS-Array-Methoden
Um zu verstehen, was das bedeutet, müssen wir zunä...
Beim Konfigurieren des Domänennamens der Schnitts...
In den vorherigen drei Artikeln wurden gängige Si...
MySQL 8.0.19 unterstützt die Sperrung des Kontos ...
Inhaltsverzeichnis Über FastDFS 1. Suche nach Bil...
In diesem Artikel wird der spezifische Code für j...
Häufig gestellte Fragen zu benutzerdefinierten Bi...
Inhaltsverzeichnis Hintergrund Problembeschreibun...
Das Boxmodell gibt die Breite und Höhe sowie die ...
Auf immer mehr Websites wird HTML4 durch XHTML ers...
1. Voraussetzungen 1. Das Projekt wurde bereitges...
Es zeigt hauptsächlich, wie X-Frame-Options, X-XS...
Wenn die Datenbank gleichzeitig denselben Datenst...
1. Hintergrund Verwenden Sie LDAP, um betriebs- u...
eins. Warum einen privaten Nexus-Server erstellen...