mysqld: Bruder, ich kann nicht aufstehen ...
Autor: Ben Shaohua, Ingenieur im ACOSEN R&D Center, verantwortlich für Projektanforderungen und Wartung. Andere Identitäten: Corgi-Schaufler.
Produziert von der Aikeson Open Source Community. Bitte kontaktieren Sie den Herausgeber und geben Sie die Quelle für den Nachdruck an.
Dieser Artikel ist etwa 2.100 Wörter lang und die Lektüre dauert voraussichtlich 7 Minuten.
Einführung
Wie der Titel schon sagt, kann MySQL in automatisierten Testszenarien nicht über systemd gestartet werden .
Beenden Sie kontinuierlich kill -9
den Instanzprozess und prüfen Sie , ob mysqld nach dem Beenden korrekt aufgerufen wird.
Spezifische Informationen lauten wie folgt:
- Hostinformationen: CentOS 8 (Docker-Container)
- Verwenden Sie systemd , um den mysqld- Prozess zu verwalten
- Der Betriebsmodus des systemd-Dienstes ist: forking
- Der Startbefehl lautet wie folgt:
# systemd 启动命令
sudo -S systemctl start mysqld_11690.service
# systemd service 内的 ExecStart 启动命令
/opt/mysql/base/8.0.34/bin/mysqld --defaults-file=/opt/mysql/etc/11690/my.cnf --daemonize --pid-file=/opt/mysql/data/11690/mysqld.pid --user=actiontech-mysql --socket=/opt/mysql/data/11690/mysqld.sock --port=11690
Symptom
Der Startbefehl bleibt weiterhin hängen, ohne Erfolg oder Rückgabe. Nach mehreren Versuchen kann das Szenario nicht manuell reproduziert werden.
Die folgende Abbildung zeigt ein Reproduktionsszenario. Wenn die Service- Portnummern inkonsistent sind, ignorieren Sie sie bitte.
Das MySQL-Fehlerprotokoll enthält keine Informationen. Überprüfen Sie den Status des Systemd-Dienstes und stellen Sie fest, dass die Ausführung des Startskripts MAIN PID
aufgrund fehlender Parameter fehlgeschlagen ist.
Die endgültige Informationsausgabe von systemd lautet:New main PID 31036 does not exist or is a zombie
Zusammenfassung der Gründe
Wenn systemd mysqld startet , wird es zunächst gemäß der Konfiguration in der Dienstvorlage ausgeführt:
- ExecStart ( mysqld starten )
- mysqld beginnt mit der Erstellung
pid
von Dateien - ExecStartPost (einige benutzerdefinierte Post-Skripte: Berechtigungen anpassen,
pid
in cgroup schreiben usw.)
Im Zwischenzustand von Schritt 2-3 , also pid
wenn die Datei gerade erstellt wird, empfängt der Host den vom automatisierten Test ausgegebenen Befehl: sudo -S kill -9 $(cat /opt/mysql/data/11690/mysqld.pid)
.
Da diese pid
Datei und dieser pid
Prozess vorhanden sind (wenn kill
der Befehl oder Befehl nicht vorhanden ist, cat
wird ein Fehler gemeldet), geht automatisiertes CASE davon aus, dass kill
der Vorgang erfolgreich beendet wurde. Da diese Datei jedoch mysqld.pid
von MySQL selbst verwaltet wird, müssen Sie aus Sicht von systemd noch auf den Abschluss von Schritt 3 warten, bevor der Start als erfolgreich angesehen wird.
Wenn systemd den Forking- Modus verwendet , bestimmt es PID
anhand des Werts des untergeordneten Prozesses, ob der Dienst erfolgreich gestartet wurde.
Wenn der untergeordnete Prozess erfolgreich gestartet wird und kein unerwarteter Abbruch erfolgt, betrachtet systemd den Dienst als gestartet und setzt den PID
Wert des untergeordneten Prozesses auf MAIN PID
.
Wenn der untergeordnete Prozess nicht gestartet werden kann oder unerwartet beendet wird, geht systemd davon aus, dass der Dienst nicht erfolgreich gestartet werden konnte.
abschließend
Da beim Ausführen von ExecStartPost die untergeordnete Prozess- ID 31036 gelöscht wurde kill
, fehlen der Nachverarbeitung shell
Startparameter, aber der ExecStart-Schritt wurde abgeschlossen, was dazu führt, dass MAIN PID 31036 zu einem Zombie-Prozess wird, der nur in systemd existiert .
Fehlerbehebungsprozess
Als ich auf dieses Problem stieß, war ich etwas verwirrt und überprüfte einfach die grundlegenden Informationen zum Speicher und zur Festplatte. Es hat die Erwartungen erfüllt und es gab keinen Mangel an Ressourcen.
Schauen wir uns zunächst das Fehlerprotokoll von MySQL an, um zu sehen, was wir finden. Sehen Sie sich die Ergebnisse wie folgt an:
...无关内容省略...
2024-02-05T05:08:42.538326+08:00 0 [Warning] [MY-010539] [Repl] Recovery from source pos 3943309 and file mysql-bin.000001 for channel ''. Previous relay log pos and relay log file had been set to 4, /opt/mysql/log/relaylog/11690/mysql-relay.000004 respectively.
2024-02-05T05:08:42.548513+08:00 0 [System] [MY-010931] [Server] /opt/mysql/base/8.0.34/bin/mysqld: ready for connections. Version: '8.0.34' socket: '/opt/mysql/data/11690/mysqld.sock' port: 11690 MySQL Community Server - GPL.
2024-02-05T05:08:42.548633+08:00 0 [System] [MY-013292] [Server] Admin interface ready for connections, address: '127.0.0.1' port: 6114
2024-02-05T05:08:42.548620+08:00 5 [Note] [MY-010051] [Server] Event Scheduler: scheduler thread started with id 5
Bei der Beobachtung des Fehlerprotokolls haben wir festgestellt, dass es keine nützlichen Informationen gibt, da nach der Startzeit keine Protokollinformationen ausgegeben werden.
Überprüfen Sie den Systemctl-Status , um den aktuellen Status des Dienstes zu bestätigen:
Das Bild unten zeigt die Statusinformationen unter normalen Umständen :
Nach dem Vergleich wurden zwei nützliche Informationen zusammengestellt:
- Die Nachausführung ist
shell
aufgrund fehlender-p
Parameter fehlgeschlagen (-p
die Parameter sindMAIN PID
, d. h. nachdem der untergeordnete Fork-Prozess gestartet wurdePID
). - systemd kann nicht abgerufen werden
PID 31036
, existiert nicht oder ist ein Zombie-Prozess.
Schauen wir uns zunächst den Prozess an ID
und mysqld.pid
sehen:
Bestätigungshinweise:
PID 31036
ist nicht vorhandenmysqld.pid
Die Datei existiert und der Dateiinhalt ist 31036top
Befehl zum Überprüfen, ob kein Zombie-Prozess vorhanden ist
Sie müssen noch weitere Hinweise zur Bestätigung der Ursache erhalten. Überprüfen Sie journalctl -u
den Inhalt, um zu sehen, ob er hilfreich ist:
sh-4.4# journalctl -u mysqld_11690.service
-- Logs begin at Mon 2024-02-05 04:00:35 CST, end at Mon 2024-02-05 17:08:01 CST. --
Feb 05 05:07:54 udp-11 systemd[1]: Starting MySQL Server...
Feb 05 05:07:56 udp-11 systemd[1]: Started MySQL Server.
Feb 05 05:08:31 udp-11 systemd[1]: mysqld_11690.service: Main process exited, code=killed, status=9/KILL
Feb 05 05:08:31 udp-11 systemd[1]: mysqld_11690.service: Failed with result 'signal'.
Feb 05 05:08:32 udp-11 systemd[1]: Starting MySQL Server...
Feb 05 05:08:36 udp-11 systemd[1]: Started MySQL Server.
Feb 05 05:08:37 udp-11 systemd[1]: mysqld_11690.service: Main process exited, code=killed, status=9/KILL
Feb 05 05:08:37 udp-11 systemd[1]: mysqld_11690.service: Failed with result 'signal'.
Feb 05 05:08:39 udp-11 systemd[1]: Starting MySQL Server...
Feb 05 05:08:42 udp-11 u_set_iops.sh[31507]: /etc/systemd/system/mysqld_11690.service.d/u_set_iops.sh: option requires an argument -- p
Feb 05 05:08:42 udp-11 systemd[1]: mysqld_11690.service: New main PID 31036 does not exist or is a zombie.
Der Inhalt hier journalctl -u
beschreibt nur das Phänomen und kann die spezifischen Gründe nicht analysieren. Er ähnelt dem Inhalt von systemctl status und ist nicht sehr hilfreich.
Sehen Sie sich /var/log/messages
den Inhalt des Systemprotokolls an:
Es wurde festgestellt, dass die Schleife einige Speicherfehlerinformationen gemeldet hat. Bei der Suche wurde festgestellt, dass es sich bei dem Fehler möglicherweise um ein Hardwareproblem handelt. Nachdem ich Kollegen im Bereich automatisiertes Testen befragt hatte, kam ich zu dem Schluss:
- Das Szenario ist ein gelegentliches Problem. Der Anwendungsfall wird viermal ausgeführt, zweimal erfolgreich und zweimal fehlgeschlagen.
- Jede Ausführung erfolgt auf demselben Host und demselben Container-Image.
- Wenn dies fehlschlägt, ist der Container, in dem sich der Hang befindet, derselbe.
Da es erfolgreiche Ausführungsergebnisse gibt, werden wir die Hardwareprobleme hier ignorieren.
Da nun Container erwähnt werden, gibt es ein Problem, wenn ich darüber nachdenke, ob cgroups dem Host zugeordnet werden? Im oben überprüften Systemctl-Status ist ersichtlich, dass das von cgroup zugeordnete Hostverzeichnis wie folgt lautet:CGroup: /docker/3a72b2cdc7bd9beb1c7b2abec24763046604602a38f0fcb7406d17f5d33353d2/system.slice/mysqld_11690.service
Überprüfen Sie die Lese- und Schreibberechtigungen des übergeordneten Ordners. system.slice
Es liegt keine Anomalie vor. Beseitigen Sie zunächst vorübergehend das Problem der cgroup- Zuordnung (da auf dem Host andere von systemd übernommene Dienste vorhanden sind , die ebenfalls dieselbe cgroup verwenden ).
Ich habe vor, zu versuchen , ob pstack speziell für systemctl start erkennen kann , wo systemd hängt :3048143
pid
sh-4.4# pstack 3048143
#0 0x00007fdfaef33ade in ppoll () from /lib64/libc.so.6
#1 0x00007fdfaf7768ee in bus_poll () from /usr/lib/systemd/libsystemd-shared-239.so
#2 0x00007fdfaf6a8f3d in bus_wait_for_jobs () from /usr/lib/systemd/libsystemd-shared-239.so
#3 0x000055b4c2d59b2e in start_unit ()
#4 0x00007fdfaf7457e3 in dispatch_verb () from /usr/lib/systemd/libsystemd-shared-239.so
#5 0x000055b4c2d4c2b4 in main ()
Die Beobachtung ergab, dass start_unit verdächtig ist. start_unit()
Die Funktion befindet sich in der ausführbaren Datei. Sie wird zum Starten von systemd-Einheiten verwendet , was nicht hilfreich ist.
Basierend auf vorhandenen Hinweisen können wir Folgendes spekulieren:
mysqld.pid
Wenn die Datei vorhanden ist, bedeutet dies, dass es tatsächlich einen mysqld-Prozess mit der Prozessnummer gab, der zuvor31036
gestartet wurde .- Nachdem der Prozess gestartet wurde, wird er durch den automatisierten Anwendungsfall
kill -9
beendet . - systemd hat eine bereits beendete Version erhalten
MAIN PID
, die Ausführung nach der Shell ist fehlgeschlagen und der Fork- Prozess ist fehlgeschlagen.
Indem wir die Schritte des systemd- Startvorgangs sortieren , können wir über die Möglichkeiten spekulieren. Die MySQL-Instanz generiert Dateien erst, nachdem mysqldmysqld.pid
erfolgreich gestartet wurde. Daher kann es sein, dass sie in nachfolgenden Schritten kill -9
versehentlich beendet wird .
Reproduktionsmethode
Da es keine weiteren Hinweise oder Hinweise gibt, habe ich vor, zu versuchen, es auf der Grundlage der abgeleiteten Schlussfolgerung zu reproduzieren.
4.1 Systemd-MySQL-Dienstvorlage anpassen
/etc/systemd/system/mysqld_11690.service
Bearbeiten Sie die Vorlagendatei Sekunden nach dem Start von mysqld , sleep10
sodass Sie das Szenario des Beendens des Instanzprozesses innerhalb dieses Zeitfensters simulieren können.
4.2 Neuladen der Konfiguration
Änderungen der Ausführungsaufträge systemctl daemon-reload
werden wirksam.
4.3 Szenenwiedergabe
- [SSH-Sitzung A] Bereiten Sie zunächst einen neuen Container vor, nehmen Sie die entsprechenden Konfigurationen vor und führen Sie ihn aus, um
sudo -S systemctl start mysqld_11690.service
einen MySQL- Prozess zu starten. Zu diesem Zeitpunktsleep
bleibt die Sitzung aus bestimmten Gründen hängen. - [SSH-Sitzung B] Überprüfen Sie in einem anderen Sitzungsfenster,
start
während der Befehl hängt,mysqld.pid
die Datei und führen Sie sie sofort aus, sobald die Datei erstellt wurdesudo -S kill -9 $(cat /opt/mysql/data/11690/mysqld.pid)
. - Beobachten Sie zu diesem Zeitpunkt den Systemctl-Status und die Leistung entspricht den Erwartungen.
Lösung
Entfernen Sie zunächst den kill
hängenden Befehl systemctl start und führen Sie ihn aus systemctl stop mysqld_11690.service
. Dadurch kann systemd den Zombie-Prozess aktiv beenden. Obwohl stop
der Befehl möglicherweise einen Fehler meldet, hat dies keine Auswirkungen.
Warten Sie, bis stop
die Ausführung abgeschlossen ist, und verwenden Sie dann start
den Befehl, um erneut zu starten und zum Normalzustand zurückzukehren.
Weitere technische Artikel finden Sie unter: https://opensource.actionsky.com/
Über SQLE
SQLE ist eine umfassende SQL-Qualitätsmanagementplattform, die die SQL-Prüfung und -Verwaltung von der Entwicklung bis zur Produktionsumgebung abdeckt. Es unterstützt gängige Open-Source-, kommerzielle und inländische Datenbanken, bietet Prozessautomatisierungsfunktionen für Entwicklung, Betrieb und Wartung, verbessert die Online-Effizienz und verbessert die Datenqualität.
SQLE erhalten
Typ | Adresse |
---|---|
Repository | https://github.com/actiontech/sqle |
dokumentieren | https://actiontech.github.io/sqle-docs/ |
Neuigkeiten veröffentlichen | https://github.com/actiontech/sqle/releases |
Entwicklungsdokumentation für das Datenaudit-Plug-in | https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse |