L'histoire de la suppression physique de 300 millions d'enregistrements dans MySQL

introduction

Bonjour. Je m'appelle NingenMe, développeur web.

Comme le titre l'indique, mon histoire est celle de la suppression physique de 300 millions d'enregistrements dans MySQL.

Cela m'a intéressé, j'ai donc décidé de faire un rappel (instructions).

Accueil - Alerte

Le serveur batch que j'utilise et gère dispose d'un processus régulier qui collecte les données du mois dernier auprès de MySQL une fois par jour.

Habituellement, ce processus est terminé en 1 heure environ, mais cette fois, il ne s'est pas terminé avant 7 ou 8 heures, et l'alerte n'a pas cessé d'apparaître...

Chercher une raison

J'ai essayé de redémarrer le processus et de consulter les journaux, mais je n'ai rien vu d'anormal.
La requête a été indexée correctement. Mais quand j’ai réfléchi à ce qui n’allait pas, j’ai réalisé que la taille de la base de données était assez grande.

hoge_table | 350'000'000 |

350 millions de disques. L'indexation semblait fonctionner correctement, mais très lentement.

La collecte de données requise par mois était d'environ 12 000 000 d'enregistrements. Il semble que la commande select ait pris beaucoup de temps et que la transaction n'ait pas été exécutée depuis longtemps.

DB

Il s'agit essentiellement d'un tableau qui s'agrandit d'environ 400 000 entrées chaque jour. La base de données était censée collecter des données uniquement pour le mois dernier. On s'attendait donc à ce qu'elle supporte exactement cette quantité de données, mais, malheureusement, l'opération de rotation n'a pas été incluse.

Cette base de données n'a pas été développée par moi. Je l'ai repris à un autre développeur, donc cela ressemblait toujours à une dette technique.

Il est arrivé un moment où le volume de données insérées quotidiennement est devenu important et a finalement atteint sa limite. On suppose que lorsqu’on travaille avec une si grande quantité de données, il serait nécessaire de les séparer, mais cela n’a malheureusement pas été fait.

Et puis je suis entré en action.

Correction

Il était plus rationnel de réduire la taille de la base de données elle-même et de réduire le temps de traitement que de modifier la logique elle-même.

La situation devrait changer considérablement si vous effacez 300 millions d'enregistrements, alors j'ai décidé de le faire... Eh, je pensais que cela fonctionnerait certainement.

Action 1

Après avoir préparé une sauvegarde fiable, j'ai finalement commencé à envoyer des demandes.

« Envoi d'une demande »

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

"..."

"..."

« Hmm… Pas de réponse. Peut-être que le processus prend beaucoup de temps ? — J'ai pensé, mais juste au cas où, j'ai regardé grafana et j'ai vu que la charge du disque augmentait très rapidement.
"Dangereux", ai-je réfléchi à nouveau et j'ai immédiatement arrêté la demande.

Action 2

Après avoir tout analysé, je me suis rendu compte que le volume de données était trop important pour tout supprimer d’un coup.

J'ai décidé d'écrire un script capable de supprimer environ 1 000 000 d'enregistrements et je l'ai lancé.

"J'implémente le script"

"Maintenant, ça va certainement marcher", ai-je pensé.

Action 3

La deuxième méthode a fonctionné, mais s’est avérée très exigeante en main-d’œuvre.
Tout faire avec soin, sans nerfs inutiles, prendrait environ deux semaines. Mais ce scénario ne répondait toujours pas aux exigences de service, nous avons donc dû nous en éloigner.

Voici donc ce que j'ai décidé de faire :

Copiez le tableau et renommez-le

À l’étape précédente, j’ai réalisé que la suppression d’une si grande quantité de données créait une charge tout aussi importante. J'ai donc décidé de créer une nouvelle table à partir de zéro en utilisant l'insertion et d'y déplacer les données que j'allais supprimer.

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

Si vous donnez au nouveau tableau la même taille que ci-dessus, la vitesse de traitement des données devrait également devenir 1/7 plus rapide.

Après avoir créé la table et l'avoir renommée, j'ai commencé à l'utiliser comme table principale. Maintenant, si je laisse tomber la table avec 300 millions d'enregistrements, tout devrait bien se passer.
J'ai découvert que tronquer ou supprimer créait moins de surcharge que supprimer et j'ai décidé d'utiliser cette méthode.

Exécution

« Envoi d'une demande »

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

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

Action 4

Je pensais que l'idée précédente fonctionnerait, mais après l'envoi de la demande d'insertion, plusieurs erreurs sont apparues. MySQL ne pardonne pas.

J’étais déjà tellement fatigué que j’ai commencé à penser que je ne voulais plus faire ça.

Je me suis assis et j'ai réfléchi et j'ai réalisé qu'il y avait peut-être trop de requêtes d'insertion pour une seule fois...
J'ai essayé d'envoyer une demande d'insertion pour la quantité de données que la base de données devrait traiter en 1 jour. Arrivé!

Eh bien, après cela, nous continuons à envoyer des demandes pour la même quantité de données. Puisque nous devons supprimer un mois de données, nous répétons cette opération environ 35 fois.

Renommer une table

Ici, la chance était de mon côté : tout s’est bien passé.

Alerte disparue

La vitesse de traitement par lots a augmenté.

Auparavant, ce processus prenait environ une heure, maintenant il prend environ 2 minutes.

Après avoir été sûr que tous les problèmes étaient résolus, j'ai supprimé 300 millions de disques. J'ai supprimé le tableau et je me suis senti renaître.

Résumé

J'ai réalisé que le traitement de rotation manquait dans le traitement par lots, et c'était le principal problème. Ce genre d'erreur architecturale entraîne une perte de temps.

Pensez-vous à la charge lors de la réplication des données lors de la suppression d'enregistrements de la base de données ? Ne surchargeons pas MySQL.

Ceux qui connaissent bien les bases de données ne rencontreront certainement pas un tel problème. Pour le reste d’entre vous, j’espère que cet article vous a été utile.

Merci d'avoir lu!

Nous serons très heureux si vous nous dites si vous avez aimé cet article, si la traduction est claire, si elle vous a été utile ?

Source: habr.com

Ajouter un commentaire