Technischer Deep Dive: Warum deine MySQL-Datenbank meistens an der Last der Abfragen und nicht an Hardware-Power scheitert.
Wie solide ist deine Datenbank?
Ein Website-Relaunch, der läuft. Ein Social-Media-Beitrag, der viral geteilt wird. Eine erfolgreiche Marketing-Aktion, die deinen Onlineshop bewirbt. Im Leben eines Unternehmens gibt es immer wieder mal Tage, an dem sinnbildlich die Zahlen springen. Dann kommt die Zeit, in der deine Datenbank beweisen muss, wie gut sie gebaut ist.
Was dabei zuerst nachgibt, ist in vielen Fällen eine Abfrage. Die Hardware meldet sich zuletzt. Ja, sie meldet sich seltener, als die meisten Gründer erwarten. Das ist die gute Nachricht an einem ansonsten unangenehmen Tag. Denn eine Abfrage reparierst du mit Arbeitszeit.
Der Ablauf ist dabei erstaunlich gleichförmig. Er hat nur vier Stationen. Welche das sind? Das erfährst du in diesem Fachbeitrag für Datenbank- und MySQL-Experten.
Vier Engpässe melden sich in fester Reihenfolge
Am Anfang stehen Abfragen ohne passenden Index. Fehlt er, liest die Datenbank die ganze Tabelle, um ein paar Zeilen zu finden. Bei zweitausend Datensätzen fällt das niemandem auf, bei zwei Millionen wird aus derselben Abfrage die langsamste Stelle deiner Anwendung. Das Tückische daran: Ausgelöst hat den Einbruch allein die gewachsene Datenmenge, der Code ist derselbe geblieben.
Kurz darauf kommt das N+1-Muster dazu. Das bringt dein ORM mit. Es holt eine Liste mit einer einzigen Abfrage und schickt anschließend für jede zurückgegebene Zeile eine weitere hinterher. Aus einer Übersicht mit fünfzig Bestellungen werden so einundfünfzig Abfragen statt zwei. Mit zehn Testdatensätzen bleibt das unsichtbar, im Betrieb mit echten Listen multipliziert sich alles mit jedem Aufruf.
Als Drittes läuft der Verbindungspool voll. Und als Viertes ist die Maschine selbst am Ende: CPU, Arbeitsspeicher und Festplatten-I/O sind ausgereizt. Die Fehlerquote steigt, die Antwortzeiten steigen mit. Diese vierte Station ist die einzige, die wirklich Geld kostet. Viele Teams landen dort, weil sie die ersten drei übersprungen haben.
...............
Anzeige:
...............
Sobald der Verbindungspool voll ist, wartet deine Anwendung
Der Pool ist die Station, die am häufigsten falsch gelesen wird. Deine Anwendung hält eine begrenzte Zahl offener Verbindungen zur Datenbank bereit. Die Datenbank selbst erlaubt ebenfalls nur eine bestimmte Zahl gleichzeitiger Verbindungen. Bei MySQL sind das standardmäßig 151 (Systemvariable max_connections). Beide Grenzen existieren, beide sind konfiguriert. Leider kennt oft niemand im Team die aktuellen Werte auswendig.
Interessant ist, was beim Anschlag passiert. Nämlich: Neue Anfragen stellen sich an und warten, bis eine Verbindung frei wird. Für deine Nutzer sieht das aus wie eine langsame Webseite. In deiner Überwachung sieht es aus wie hohe Latenz. Und in der Datenbank selbst bleibt die Auslastung dabei entspannt. Genau deshalb wird an dieser Stelle so oft die falsche Rechnung aufgemacht und ein größerer Server bestellt – obwohl nur eine Zahl in einer Konfigurationsdatei die Ursache war.
Langsame Webseiten kosten messbar Umsatz. In der Studie „Milliseconds Make Millions“ von Deloitte und Google stiegen die Conversion Rates bei Onlinehändlern um 8,4 Prozent, wenn die mobile Ladezeit um nur 0,1 Sekunden sank.
👉 Was lernen wir daraus? Beobachte nicht den Durchschnitt, sondern die p95- und p99-Latenz. Also die Antwortzeit, unter der 95 beziehungsweise 99 Prozent der Anfragen bleiben. Wartezeiten am Pool treffen zuerst die langsamsten Anfragen und gehen im Mittelwert fast vollständig unter.
Eine Stunde reicht, um die teuerste Abfrage zu finden
Blockiere dir mal eine Stunde in deinem Terminkalender. Teile die Stunde in drei gleiche Blöcke von jeweils 20 Minuten auf. Arbeite dann die folgenden Tasks schrittweise ab.
Schritt 1: Slow Query Log
Die ersten zwanzig Minuten gehören dem Slow Query Log. Hier lohnt ein genauer Blick. Warum? Die Standardeinstellungen taugen für diesen Zweck wenig: Das Protokoll ist ab Werk abgeschaltet, und der Schwellenwert long_query_time steht auf zehn Sekunden. Wer es einschaltet und danach in eine leere Datei schaut, hat deshalb selten ein schnelles System. Sondern häufig eine Abfrage, die acht Sekunden braucht und unter dieser Schwelle bleibt.
Schalte das Protokoll also ein, setz den Schwellenwert auf einen Wert, der zu deiner Anwendung passt. Lass das Protokoll über eine typische Stunde mitlaufen. Interessant sind am Ende die Abfragen mit der höchsten Gesamtlast, also Laufzeit mal Häufigkeit.
Diese Verdichtung musst du nicht von Hand erledigen! Der pt-query-digest aus dem Percona Toolkit fasst das Slow Query Log nach normalisierten Abfragen zusammen. Unter MySQL 8.x liefert die View sys.statement_analysis dieselbe Sicht aus dem Performance-Schema, das ab Werk aktiv ist. Absteigend nach Gesamtlatenz sortiert und ganz ohne eingeschaltetes Slow Query Log.
Schritt 2: Genaue Analysen
Die zweiten zwanzig Minuten gehören den fünf teuersten Kandidaten aus dieser Liste. Stell jeder von ihnen EXPLAIN voran und lies die Ausgabe an vier Stellen:
➡ Spalte „key“: Steht hier ein NULL, hat MySQL einen brauchbaren Index gesucht und keinen gefunden.
➡ Spalte „type“: Steht hier ein ALL, wird die Tabelle vollständig gelesen, was das Handbuch außerhalb der ersten Tabelle einer Verknüpfung ausdrücklich als sehr schlecht bezeichnet.
➡ Spalte „rows“: Zeigt, wie viele Zeilen MySQL für die Ausführung zu prüfen glaubt, bei InnoDB als Schätzung.
➡ Spalte“ Extra“: Using filesort und Using temporary sind die beiden Einträge, nach denen du laut Handbuch gezielt Ausschau halten solltest, wenn Abfragen schnell werden sollen.
Schritt 3: Connections
Die letzten zwanzig Minuten gehören den Verbindungen. Stell die Zahl der aktiven Verbindungen der konfigurierten Obergrenze gegenüber und sieh dir den Verlauf der letzten Wochen an. Sind im Alltag beispielsweise siebzig von hundert Verbindungen belegt, liegt die Auslastung bei 70 Prozent. Du weißt also, wie viel Luft nach oben bleibt.
Erreicht der Wert regelmäßig das Limit, kommen zwei Ursachen infrage: Entweder gibt deine Anwendung Verbindungen später zurück, als sie müsste. Oder die Nachfrage ist dauerhaft gestiegen. Nur der zweite Fall ist ein Kapazitätsproblem.
Vor der Hardware-Bestellung: Arbeite diese Eingriffe ab
✅ Der Index auf den Spalten
Setze ihn auf die Spalten, nach denen deine teuersten Abfragen filtern und sortieren. Er ist meist eine Zeile Migration und wirkt sofort. Seine Grenze: Jeder Index kostet Speicherplatz und macht Schreibvorgänge etwas langsamer, weshalb zwanzig Indizes auf einer Tabelle ein eigenes Problem sind.
✅ Das Zwischenspeichern
Caching der immer gleichen Lesezugriffe (Startseite, Kategorienliste, Konfiguration) nimmt oft den größten Teil der Leselast weg. Seine Grenze ist die Aktualität: Alles, was im Cache liegt, ist für die Dauer seiner Gültigkeit veraltet. Bei Preisen oder Beständen wählst du diese Dauer besser sehr bewusst.
✅ Der ehrliche Blick auf die Poolgrößen
Realistische Obergrenzen auf beiden Seiten und kurze Haltezeiten lösen erstaunlich viele Zwischenfälle. Die Grenze dieses Eingriffs ist unangenehm: Bei einer Anwendung, die Verbindungen offen liegen lässt, verschiebt ein größerer Pool den Anschlag lediglich nach hinten.
✅ Extraprüfung 1
Zwei Prüfungen gehören noch dazu, bevor du der Hardware die Schuld gibst. Ein Connection Pooler wie ProxySQL zwischen Anwendung und MySQL bündelt viele kurze Verbindungen, sodass die Datenbank selbst deutlich weniger davon offen halten muss.
✅ Extraprüfung 2
Die zweite Prüfung ist die Trefferquote des InnoDB Buffer Pools, das Verhältnis von Innodb_buffer_pool_reads zu Innodb_buffer_pool_read_requests. Auf dedizierten Servern erhält der Buffer Pool laut MySQL-Handbuch oft bis zu 80 Prozent des Arbeitsspeichers. Müssen unter Last spürbar mehr Seiten von der Platte gelesen werden, fehlt eher Speicher als Rechenleistung.
...............
Anzeige:
...............
Wo der Index endet, beginnt der zweite Knoten
Irgendwann sind diese drei Eingriffe erledigt. Aber die Last ist trotzdem noch da? Dann geht es um Architektur. Die typischen Fragen lauten dann :
❓ Was passiert, wenn diese eine Maschine ausfällt?
❓ Wie weit zurück reichen deine Sicherungen?
❓ Wer entlastet die Datenbank bei Lesezugriffen?
Technisch ist das die Wahl zwischen vertikaler und horizontaler Skalierung. Vertikal bedeutet einen größeren Knoten bei gleichem Aufbau. Horizontal bedeutet, Lesezugriffe auf Replikate zu verteilen. Sharding, also das Aufteilen der Daten auf mehrere Datenbanken, bleibt der letzte Schritt.
Doch Lesereplikate bringen eine eigene Bedingung mit: Sie laufen dem Primärknoten mit einer Replikationsverzögerung hinterher. Deine Anwendung muss also vertragen, dass ein gerade geschriebener Datensatz dort für einen Moment noch fehlt.
Was ist die Lösung?
Die Lösung unterscheidet sich je nach Tarif stärker, als es so manche Preisliste vermuten lässt. In der Übersicht von ovhcloud mysql stehen beispielsweise diese drei Pläne nebeneinander:
| Plan | Knoten | Failover | Backup-Aufbewahrung | SLA |
| Discovery | 1 | keines | 48 Stunden | kein SLA |
| Production | 2, Multi-AZ | 1, ohne Ausfallzeit | 14 Tage | 99,95 % |
| Advanced | 3, Multi-AZ, inkl. Lesereplikate | 2, ohne Ausfallzeit | 30 Tage | 99,99 % |
Die SLA von bis zu 99,99 % gilt laut Anbieter für Bereitstellungen in einer 3-AZ-Region. Verbindungspooling, Point-in-Time-Recovery und ein Monitoring mit Prometheus-Metriken sind über alle Pläne hinweg enthalten. Der Wechsel zwischen ihnen ist als Ein-Klick-Vorgang angelegt.
Zwei Dinge daran sind für dich wichtiger als die Preise. Die Zusage zur Verfügbarkeit beginnt beim zweiten Knoten und die Lesereplikate beim dritten, also oberhalb dessen, was ein sparsames Team für den Anfang wählt. Und mitgeliefertes Verbindungspooling arbeitet einer Anwendung zu, die ihre Verbindungen sauber zurückgibt – es ersetzt diese Sauberkeit aber nicht.
👉 Eine verwaltete MySQL Datenbank verlagert damit den Betrieb zum Anbieter. Die Verantwortung für den Umgang mit ihr bleibt bei dir.
Miss deinen Spielraum in Nutzern, nicht in Gigahertz
Für die Planung reicht eine einzige Zahl. Tabellen mit vCPU-Empfehlungen helfen dabei wenig, weil der Bedarf vollständig davon abhängt, was deine Anwendung tut. Die eine Zahl rechnest du dir aus dem dritten Block deiner Analysestunde selbst aus.
Hier ein simples Beispiel: Bei 2.000 aktiven Nutzern sind im Schnitt siebzig von hundert Verbindungen belegt. Das sind 0,035 Verbindungen pro Nutzer. Die hundertste Verbindung wäre demnach bei knapp 2.900 Nutzern erreicht, sofern das Nutzungsverhalten gleich bleibt. Dein Spielraum liegt also bei rund 45 Prozent. In Nutzern ausgedrückt weißt du damit, ob du von einer Verdopplung deiner Zahlen sechs Monate oder sechs Wochen entfernt bist.
Die Rechnung bleibt eine Faustformel. Sie hat trotzdem die entscheidende Eigenschaft: Sie ist in derselben Einheit formuliert wie dein Wachstumsziel. Dieselbe Rechnung funktioniert mit Abfragen pro Sekunde, mit belegtem Speicherplatz und mit der Zeit, die dein langsamster Seitenaufruf braucht.
Fazit
Der Ansturm auf deine Datenbank kündigt sich selten an – aber du kannst ihn erwarten. Denn meist scheitert nicht die Hardware, sondern eine Abfrage. Und die reparierst du mit Arbeitszeit, nicht mit Geld.
Plane deshalb die Analysestunde fest in deine Abläufe ein. So triffst du die Entscheidung über neue Hardware mit Daten statt mit Bauchgefühl.
Willst du die StartUpWissen-Tipps zugesendet bekommen? Abonniere den kostenlosen Newsletter!
✅ Erlesene Inhalte ✅ Top-Ratgeber für Unternehmer ✅ Gratis-Tipps
_____________________
Bilder: Freepik/Magnific

