La història de la supressió física de 300 milions de registres a MySQL

Introducció

Hola. Sóc ningenMe, desenvolupador web.

Com diu el títol, la meva història és la història de la supressió física de 300 milions de registres a MySQL.

Em vaig interessar en això, així que vaig decidir fer un recordatori (instruccions).

Inici - Alerta

El servidor per lots que faig servir i mantinc té un procés regular que recull les dades de l'últim mes de MySQL una vegada al dia.

En general, aquest procés es completa en aproximadament 1 hora, però aquesta vegada no es va completar durant 7 o 8 hores, i l'alerta no va deixar d'aparèixer...

Buscant un motiu

Vaig intentar reiniciar el procés i mirar els registres, però no vaig veure res dolent.
La consulta s'ha indexat correctament. Però quan vaig pensar en què anava malament, em vaig adonar que la mida de la base de dades és bastant gran.

hoge_table | 350'000'000 |

350 milions de registres. La indexació semblava funcionar correctament, només molt lenta.

La recollida de dades requerida per mes va ser d'aproximadament 12 de registres. Sembla que l'ordre de selecció va trigar molt de temps i la transacció no es va executar durant molt de temps.

DB

Es tracta bàsicament d'una taula que creix unes 400 entrades cada dia. La base de dades havia de recollir dades només durant l'últim mes, per tant, s'esperava que aguanti exactament aquesta quantitat de dades, però, malauradament, l'operació de rotació no es va incloure.

Aquesta base de dades no la vaig desenvolupar jo. El vaig agafar a un altre desenvolupador, així que encara em semblava un deute tècnic.

Va arribar un moment en què el volum de dades inserides diàriament es va fer gran i finalment va arribar al seu límit. Se suposa que quan es treballa amb una quantitat tan gran de dades, caldria separar-les, però això, malauradament, no es va fer.

I després vaig entrar en acció.

Correcció

Era més racional reduir la mida de la pròpia base de dades i reduir el temps de processament que no pas canviar la pròpia lògica.

La situació hauria de canviar significativament si esborreu 300 milions de registres, així que vaig decidir fer-ho... Eh, vaig pensar que això funcionaria definitivament.

Acció 1

Després d'haver preparat una còpia de seguretat fiable, finalment vaig començar a enviar sol·licituds.

「Enviant una sol·licitud」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"…"

"…"

“Hmm... Sense resposta. Potser el procés triga molt de temps?" — Vaig pensar, però per si de cas, vaig mirar grafana i vaig veure que la càrrega del disc creixia molt ràpidament.
"Perillós", vaig pensar de nou i immediatament vaig aturar la petició.

Acció 2

Després d'analitzar-ho tot, em vaig adonar que el volum de dades era massa gran per esborrar-ho tot alhora.

Vaig decidir escriure un script que pogués eliminar uns 1 de registres i el vaig llançar.

「Implemento el guió」

"Ara això definitivament funcionarà", vaig pensar.

Acció 3

El segon mètode va funcionar, però va resultar ser molt intensiu de mà d'obra.
Fer-ho tot amb cura, sense nervis innecessaris, trigaria unes dues setmanes. Però tot i així, aquest escenari no complia els requisits del servei, per la qual cosa ens vam haver d'allunyar.

Així que això és el que vaig decidir fer:

Copieu la taula i canvieu-li el nom

Des del pas anterior, em vaig adonar que l'eliminació d'una quantitat tan gran de dades crea una càrrega igual de gran. Així que vaig decidir crear una taula nova des de zero mitjançant la inserció i moure-hi les dades que anava a suprimir.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

Si feu que la nova taula tingui la mateixa mida que l'anterior, la velocitat de processament de dades també hauria de ser 1/7 més ràpida.

Després de crear la taula i canviar-li el nom, vaig començar a utilitzar-la com a taula mestra. Ara si deixo caure la taula amb 300 milions de registres, tot hauria d'anar bé.
Vaig descobrir que truncar o deixar anar crea menys sobrecàrrega que suprimir i vaig decidir utilitzar aquest mètode.

Execució

「Enviant una sol·licitud」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"…"
"…"
"Em...?"

Acció 4

Vaig pensar que la idea anterior funcionaria, però després d'enviar la sol·licitud d'inserció, van aparèixer diversos errors. MySQL no perdona.

Ja estava tan cansat que vaig començar a pensar que ja no volia fer això.

Em vaig asseure i vaig pensar i em vaig adonar que potser hi havia massa consultes d'inserció per una vegada...
Vaig provar d'enviar una sol·licitud d'inserció per a la quantitat de dades que hauria de processar la base de dades en 1 dia. Succeït!

Bé, després continuem enviant sol·licituds per a la mateixa quantitat de dades. Com que hem d'eliminar dades d'un mes, repetim aquesta operació unes 35 vegades.

Canviar el nom d'una taula

Aquí la sort va estar de la meva part: tot va anar bé.

Alerta desapareguda

La velocitat de processament per lots ha augmentat.

Abans aquest procés durava aproximadament una hora, ara triga uns 2 minuts.

Després d'estar segur que tots els problemes estaven resolts, vaig deixar caure 300 milions de registres. Vaig esborrar la taula i em vaig sentir renéixer.

Resum

Em vaig adonar que faltava el processament de rotació en el processament per lots, i aquest era el principal problema. Aquest tipus d'error arquitectònic comporta una pèrdua de temps.

Penseu en la càrrega durant la replicació de dades quan suprimiu registres de la base de dades? No sobrecarreguem MySQL.

Aquells que coneixen bé les bases de dades definitivament no trobaran aquest problema. Per a la resta de vosaltres, espero que aquest article sigui útil.

Gràcies per llegir!

Estarem molt contents si ens digueu si us ha agradat aquest article, si la traducció és clara, si us ha estat útil?

Font: www.habr.com

Afegeix comentari