EinfĂŒhrung
Hallo. Ich bin ningenMe, Webentwickler.
Wie im Titel erwĂ€hnt, ist meine Geschichte eine Geschichte ĂŒber das physische Löschen von 300 Millionen DatensĂ€tzen in MySQL.
Ich habe mich dafĂŒr interessiert, also entschied ich mich, ein Memo (eine Anleitung) zu erstellen.
Der Anfang â Alert
Im Batch Server, den ich verwende und betreue, gibt es einen regelmĂ€Ăigen Prozess, der einmal tĂ€glich Daten des letzten Monats aus MySQL sammelt.
In der Regel dauert dieser Prozess etwa 1 Stunde, aber diesmal benötigte er 7 oder 8 Stunden, und die Warnungen hörten nicht auf ...
Die Ursache suchen
Ich habe versucht, den Prozess neu zu starten, die Logs anzusehen, aber ich sah nichts Schlimmes.
Die Abfrage wurde korrekt indiziert. Aber als ich nachdachte, was schiefgehen könnte, merkte ich, dass das Datenbankvolumen ziemlich groà ist.
hoge_table | 350'000'000 |350 Millionen DatensÀtze. Es scheint, dass die Indizierung korrekt funktionierte, nur sehr langsam.
Die erforderliche Datensammlung fĂŒr den Monat betrug etwa 12.000.000 DatensĂ€tze. Es scheint, dass das Select-Team viel Zeit benötigte, und die Transaktion lange Zeit nicht abgeschlossen wurde.
DB
Im Grunde genommen ist es eine Tabelle, die tÀglich um etwa 400.000 DatensÀtze wÀchst. Die Datenbank sollte nur die Daten des letzten Monats sammeln, daher war die Erwartung, dass sie dieses Datenvolumen bewÀltigen kann, aber leider war die Operation rotate nicht aktiviert.
Diese Datenbank wurde nicht von mir entwickelt. Ich habe sie von einem anderen Entwickler ĂŒbernommen, daher bleibt das GefĂŒhl, dass es sich um technische Schulden handelt.
Der Moment kam, als das Volumen der tĂ€glich eingefĂŒgten Daten groĂ wurde und schlieĂlich an die Grenzen stieĂ. Es wird erwartet, dass man bei so einem groĂen Datenvolumen sie aufteilt, aber das wurde leider nicht gemacht.
Und dann kam ich ins Spiel.
Behebung
Es war sinnvoller, die Datenbank selbst zu verkleinern und die Verarbeitungszeit zu reduzieren, als die Logik selbst zu Àndern.
Die Situation sollte sich erheblich Ă€ndern, wenn 300 Millionen DatensĂ€tze gelöscht werden, also beschloss ich, dies zu tun ... Ach, ich dachte, das wĂŒrde sicher funktionieren.
Aktion 1
Nachdem ich ein zuverlÀssiges Backup erstellt hatte, begann ich endlich, Abfragen zu senden.
âAbfrage sendenâ
DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';ăâŠă
ăâŠă
âHmm⊠Keine Antwort. Vielleicht dauert der Prozess zu lange?â â dachte ich, aber ich schaute vorsichtshalber in Grafana und sah, dass die Festplattenauslastung sehr schnell anstieg.
âGefĂ€hrlichâ â dachte ich wieder und stoppte sofort die Abfrage.
Aktion 2
Nachdem ich alles analysiert hatte, wurde mir klar, dass das Datenvolumen zu groà war, um alles auf einmal zu löschen.
Ich beschloss, ein Skript zu schreiben, das etwa 1.000.000 DatensÀtze löschen kann, und startete es.
âIch werde das Skript umsetzenâ
âJetzt wird es bestimmt funktionierenâ, dachte ich.
Aktion 3
Die zweite Methode funktionierte, war jedoch sehr arbeitsintensiv.
Um alles ordentlich und ohne unnötige Nerven zu machen, hÀtte ich ungefÀhr zwei Wochen gebraucht. Dennoch entsprach dieses Szenario nicht den Dienstanforderungen, also musste ich davon absehen.
Deshalb habe ich Folgendes beschlossen:
Tabelle kopieren und umbenennen
Aus dem vorherigen Schritt verstand ich, dass das Löschen eines so groĂen Datenvolumens ebenso groĂe Last verursacht. Daher entschloss ich mich, eine neue Tabelle von Grund auf mit INSERT zu erstellen und die Daten, die ich löschen wollte, dorthin zu verschieben.
| hoge_table | 350'000'000|
| tmp_hoge_table | 50'000'000|Wenn ich eine neue Tabelle in der gleichen GröĂe wie oben beschrieben erstelle, sollte die Datenverarbeitungsgeschwindigkeit auch um 1/7 schneller werden.
Nachdem ich die Tabelle erstellt und umbenannt hatte, begann ich, sie als Haupttabelle zu verwenden. Nun, wenn ich die Tabelle mit 300 Millionen DatensÀtzen lösche, sollte alles in Ordnung sein.
Ich fand heraus, dass TRUNCATE oder DROP eine geringere Last erzeugen als DELETE, und beschloss, diese Methode zu verwenden.
AusfĂŒhrung
âAbfrage sendenâ
INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS'; ăâŠă
ăâŠă
âĂhmâŠ?â
Aktion 4
Ich dachte, die vorherige Idee wĂŒrde funktionieren, aber nach dem Senden der INSERT-Anfrage trat ein mehrfacher Fehler auf. MySQL ist unerbittlich.
Ich war bereits so mĂŒde, dass ich zu denken begann, dass ich nicht mehr weitermachen wollte.
Ich setzte mich hin und ĂŒberlegte und erkannte, dass vielleicht die Anzahl der INSERT-Anfragen fĂŒr einmal zu hoch warâŠ
Ich versuchte, eine INSERT-Anfrage fĂŒr das Datenvolumen zu senden, mit dem die Datenbank an einem Tag umgehen sollte. Es hat funktioniert!
Und danach senden wir weiterhin Anfragen fĂŒr das gleiche Datenvolumen. Da wir ein monatliches Datenvolumen entfernen mĂŒssen, wiederholen wir diese Operation etwa 35 Mal.
Tabelle umbenennen
Hier hatte ich GlĂŒck: Alles lief reibungslos.
Die Warnungen sind verschwunden.
Die Geschwindigkeit der Batch-Verarbeitung hat zugenommen.
FrĂŒher dauerte dieser Prozess etwa eine Stunde, jetzt etwa 2 Minuten.
Nachdem ich mich vergewissert hatte, dass alle Probleme gelöst waren, habe ich 300 Millionen DatensĂ€tze gelöscht. Ich habe die Tabelle entfernt und fĂŒhlte mich wie neu geboren.
Zusammenfassung
Ich habe verstanden, dass beim Batch-Processing das Rotate-Processing ĂŒbersehen wurde, und das war das Hauptproblem. Ein solcher Fehler in der Architektur fĂŒhrt zu einer sinnlosen Zeitverschwendung.
Denken Sie an die Last bei der Replikation von Daten, wenn Sie DatensĂ€tze aus der Datenbank entfernen? Lassen Sie uns MySQL nicht ĂŒberlasten.
Diejenigen, die sich gut mit Datenbanken auskennen, werden mit einem solchen Problem sicherlich nicht konfrontiert werden. Ich hoffe, dieser Artikel war fĂŒr die anderen nĂŒtzlich.
Danke fĂŒrs Lesen!
Wir wĂŒrden uns sehr freuen, wenn Sie uns mitteilen, ob Ihnen dieser Artikel gefallen hat, ob die Ăbersetzung verstĂ€ndlich war und ob sie Ihnen nĂŒtzlich war?
Quelle: habr.com
