MySQL mit daemontools betreiben

Dieser Artikel ist der vierte und letzte Teil einer kleinen Gruppe von Artikeln über MySQL-Backups.

Hier ist der erste Artikel: MySQL-Backups, aber wie?

Hier ist der zweite Artikel: MySQL Replikation

Hier ist der dritte Artikel: Hinter der MySQL-Replikation aufräumen

Wer häufiger liest, was wir so über unsere Arbeit schreiben, wird schon mitbekommen haben, daß wir sehr gerne die daemontools von Daniel J. Bernstein einsetzen, um init-Skripte, xinetd, rc-Skripte und sogar cron (mit der daemontools-Erweiterung runwhen) zu ersetzen.

Das funktioniert mit dem meisten Diensten ganz gut, mit einigen weniger, wobei die letztere Gruppe seit Jahren schrumpft und durch die zunehmende Verbreitung von Upstart (das ganz ähnlich wie daemontools arbeitet und den gleichen Zweck erfüllt) dürfte sich dieser Prozess noch beschleunigen.

Bei MySQL erscheint die Einrichtung unter daemontools oft etwas kompliziert. Der Grund hierfür ist eigentlich ironisch: Die Entwickler von MySQL waren auch auf Probleme mit init gestoßen und haben keine allgemein verbreitete Lösung dafür finden können (es gab halt keine, möglicherweise wird Upstart jetzt die allgemeine Lösung werden, aber für MySQL kam das viele Jahre zu spät, gerade die Schwäche von init, Dienste nicht zuverlässig neuzustarten ist halt für einen Dienst wie MySQL kein Pappenstiel). Also haben sie das Problem kurzerhand selbst gelöst und einen Wrapper um den MySQL Daemon geschrieben, der diese Aufgabe übernimmt, egal ob init gerade korrekt arbeitet oder nicht, mysqld_safe war geboren.

Wenn man nun MySQL unter daemontools laufen lassen möchte, unterläuft einem sehr schnell ein verbreiteter Fehler, den ich anfangs auch gemacht habe. Ich hab nämlich ganz naiv ins init-Skript geschaut wie MySQL denn von dort gestartet wird und das einfach auf das run-Skript für daemontools übertragen:


#!/bin/sh
exec /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf

Und das funktioniert auch — auf den ersten Blick. Der MySQL-Dienst wird gestartet und läuft und läuft und läuft. Aber leider läuft er auch nach einem svc -d /service/mysql (dem Äquivalent zu service mysql stop) weiter. Um MySQL mit diesem run-Skript sauber zu beenden, muß man dem Dienst manuell ein SIGTERM schicken. Er beendet dann zwar sauber, aber irgendwie entspricht das nicht dem Sinn von daemontools.

Die Ursache liegt eben genau in mysqld_safe, der darauf vorbereitet ist von init oder mysqladmin den Befehl zum Beenden zu erhalten, aber eben nicht auf daemontools vorbereitet ist. Ich hab dem irgendwann als es mich mal wieder nervte nachrecherchiert und dabei herausgefunden, daß mysqld_safe letztlich genau das gleiche macht was daemontools tun und daß man MySQL auch wunderbar ohne ihn direkt unter daemontools laufen lassen kann.

Mit ein paar weiteren Tweaks sieht das run-Skript dann so aus:


#!/bin/sh -u
# remap STDERR to STDOUT, so all errors will show up in the logs
exec 2>&1
exec \
setuidgid mysql \
mysqld \
--defaults-file=/etc/my.cnf

Hier wird noch die Ausgabe von stderr nach stdout umgeleitet, damit man vom MySQL-Dienst auch ein nützliches Log erhält. Außerdem lasse ich den Dienst als User mysql laufen, um seine Rechte einzuschränken, wie mysqld_safe es in den meisten Konfigurationen auch tun würde.

Ein weiterer Vorteil von daemontools ist auch, daß man mysqld nahezu alle Konfigurationsoptionen beim Aufruf über die Kommandozeile übergeben kann — also auch über das run-Skript. Wer möchte, kann sich die /etc/my.cnf dadurch sehr kurz halten. Bestimmte Einstellungen kann man aus der /etc/my.cnf jetzt ohnehin entfernen, z.B. braucht man keine PID-Datei mehr (hier sollte man aber aufpassen, da sich der Name und Speicherort der Binary Log Dateien anscheined nach der PID-Datei richtet, wenn man sie nicht mit --log-bin[=base_name] explizit konfiguriert hat, wie ich im vorigen Artikel beschrieben habe).

Noch ein Hinweis für einen besonderen Anwendungsfall: Im zweiten Artikel dieser Serie beschrieb ich, daß man zum Einrichten einer Replikation auf dem MySQL-Master den Befehl FLUSH TABLES WITH READ LOCK; absetzen soll und den Master dann mit mysqladmin anhalten soll, ohne daß die Sperre aufgehoben wird. Dieses Herunterfahren läßt sich mit daemontools durch den Befehl svc -t erreichen, allerdings nur, wenn daemontools nicht darauf konfiguriert sind, den Dienst sofort wieder neuzustarten.