Aller au contenu

Stockage RDS plein : récupération d'urgence et autoscaling du stockage

Une instance RDS en statut STORAGE_FULL n'accepte plus d'écritures. Voici la récupération d'urgence — agrandir le volume, récupérer de l'espace — et comment l'autoscaling du stockage prévient la récidive.

Quand une instance RDS affiche le statut STORAGE_FULL, le moteur ne peut plus écrire — les insertions échouent, et sur Postgres même les lectures peuvent bloquer parce que le moteur ne peut plus écrire le WAL ni les fichiers temporaires. La récupération la plus rapide : augmenter le stockage alloué depuis la console ou la CLI, ce qui fonctionne même pendant que l’instance est en STORAGE_FULL. Ensuite, trouvez ce qui a mangé le disque — journaux binaires, tables de journaux, fichiers temporaires ou slot de réplication bloqué — parce qu’agrandir le volume sans trouver le mangeur ne fait que planifier le prochain incident.

Ce qui se passe

Les instances RDS sur MySQL, Postgres, MariaDB et SQL Server reposent sur un volume EBS de taille allouée fixe (Aurora est différent — son stockage de cluster grandit automatiquement, donc cet article porte sur RDS hors Aurora). Quand FreeStorageSpace atteint zéro, RDS place l’instance en STORAGE_FULL et les opérations d’écriture échouent. Vous ne pouvez pas rétrécir le volume ensuite; le stockage ne fait que grandir.

L’espace disparaît rarement parce que les données de tables ont grandi en douceur. Les coupables habituels sont les canaux secondaires : des journaux binaires MySQL qui s’accumulent parce que binlog retention hours a été augmenté ou qu’un réplica de lecture a cessé de les consommer; le journal général ou le journal des requêtes lentes de MySQL écrit dans des tables (log_output = TABLE) et jamais pivoté; du WAL Postgres qui s’empile parce qu’un slot de réplication est bloqué — le slot épingle le WAL indéfiniment jusqu’à ce que le consommateur rattrape ou que le slot soit supprimé; d’énormes fichiers temporaires d’une requête en dérive qui trie sur disque; et le bon vieux gonflement de tables sur Postgres avec une charge lourde en mises à jour et un vacuum insuffisant.

Un piège opérationnel à connaître avant de toucher à quoi que ce soit : après toute modification de stockage, RDS bloque les modifications suivantes pendant six heures ou jusqu’à la fin de l’optimisation du stockage, selon le plus long des deux. Agrandissez généreusement du premier coup — vous n’aurez pas de deuxième essai avant des heures.

Quoi vérifier en premier

  • La pente de FreeStorageSpace dans RDS > Databases > votre-instance > Monitoring — un déclin lent indique la croissance des données; une falaise indique des journaux, des fichiers temporaires ou un slot bloqué.
  • Le statut de l’instance — STORAGE_FULL confirme le diagnostic; si le statut est available mais que les écritures échouent, vous avez un autre problème.
  • La rétention des journaux binaires sur MySQL : CALL mysql.rds_show_configuration; affiche binlog retention hours.
  • Les slots de réplication sur Postgres — un seul slot bloqué peut épingler des centaines de Go de WAL.
  • Les événements récents dans RDS > Events — RDS émet des événements de stockage faible avant de frapper le mur.

Comment vérifier

Vérifiez la métrique et l’allocation :

aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name FreeStorageSpace \
  --dimensions Name=DBInstanceIdentifier,Value=prod-db \
  --start-time 2026-07-02T00:00:00Z --end-time 2026-07-04T12:00:00Z \
  --period 3600 --statistics Minimum

aws rds describe-db-instances --db-instance-identifier prod-db \
  --query 'DBInstances[0].[AllocatedStorage,MaxAllocatedStorage,DBInstanceStatus]'

Si MaxAllocatedStorage est nul, l’autoscaling du stockage est désactivé. Dans le moteur, trouvez les mangeurs :

-- MySQL : espace disque des journaux binaires
SHOW BINARY LOGS;

-- MySQL : plus gros schémas
SELECT table_schema, ROUND(SUM(data_length+index_length)/1024/1024/1024,2) AS gb
FROM information_schema.tables GROUP BY table_schema ORDER BY gb DESC;

-- Postgres : slots de réplication bloqués qui épinglent le WAL
SELECT slot_name, active,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained
FROM pg_replication_slots;

-- Postgres : plus grosses relations
SELECT relname, pg_size_pretty(pg_total_relation_size(oid))
FROM pg_class ORDER BY pg_total_relation_size(oid) DESC LIMIT 10;

Le runbook

  1. Agrandir le volume maintenant. aws rds modify-db-instance --db-instance-identifier prod-db --allocated-storage 300 --apply-immediately. Ça fonctionne pendant STORAGE_FULL, sans redémarrage, et l’instance reste en ligne pendant que le volume grandit. AWS exige une augmentation d’au moins 10 % par rapport à l’actuel; vu le verrou de six heures, ajoutez 25-50 %, pas le minimum.
  2. Purger les journaux binaires MySQL s’ils sont le mangeur. Réduisez la rétention avec CALL mysql.rds_set_configuration('binlog retention hours', 24); — RDS purge automatiquement les journaux au-delà de la fenêtre, mais seulement si aucun réplica n’en a encore besoin. Confirmez d’abord la santé des réplicas.
  3. Supprimer le slot Postgres bloqué. Si pg_replication_slots montre un slot inactif retenant des dizaines de Go, et que son consommateur (une tâche DMS, un pipeline CDC, un réplica mort) est parti pour de bon, SELECT pg_drop_replication_slot('slot_name');. Le WAL retenu se libère en quelques minutes. Si le consommateur va revenir, réparez plutôt le consommateur — supprimer le slot force une resynchronisation complète.
  4. Pivoter les tables de journaux. Si log_output est à TABLE sur MySQL, exécutez CALL mysql.rds_rotate_slow_log; et CALL mysql.rds_rotate_general_log;, puis passez log_output à FILE dans le groupe de paramètres pour que la rotation par fichiers s’en occupe.
  5. Éliminer la source de fichiers temporaires. Tuez la requête qui fait un tri géant sur disque (visible dans pg_stat_activity / SHOW PROCESSLIST); son espace temporaire se libère à la terminaison.
  6. Activer l’autoscaling du stockage avant de fermer l’incident. Fixez --max-allocated-storage à un plafond que vous acceptez de payer. RDS agrandit alors le stockage automatiquement quand l’espace libre descend sous 10 % pendant cinq minutes — sujet au même délai de six heures entre les incréments, ce qui fait de l’autoscaling un filet de sécurité, pas un substitut à la planification de capacité.

Quand c’est la mauvaise approche

Si le stockage s’est rempli parce qu’un slot de réplication est bloqué ou que les journaux sont mal configurés, agrandir le volume d’abord reste correct — il faut que le moteur puisse écrire pour réparer quoi que ce soit — mais s’arrêter là est une erreur : le mangeur consommera le nouvel espace au même rythme. À l’inverse, si la croissance est constituée de vraies données d’affaires sur une pente raide, autoscaler vers un plafond toujours plus haut ne fait que reporter une conversation d’archivage ou de partitionnement. La facturation au Go sur gp3 est modeste, mais les IOPS et les coûts d’instantanés grandissent avec. Et si vous êtes sur Aurora, rien de tout ça ne s’applique — voyez Aurora vs RDS pour les différences entre les modèles de stockage.

Erreurs fréquentes

  • Agrandir le stockage du minimum de 10 %, frapper le mur à nouveau une heure plus tard, et être bloqué de toute modification pendant six heures.
  • Supprimer un slot de réplication Postgres dont dépendait un pipeline CDC en production, forçant une resynchronisation complète des tables pendant les heures d’affaires.
  • Supprimer des lignes pour libérer de l’espace et s’attendre à ce que FreeStorageSpace bouge — sur Postgres, les suppressions ne rendent pas l’espace à l’OS sans vacuum full ou réécriture de table; sur InnoDB, seuls les tablespaces file_per_table rétrécissent, et seulement à l’optimisation.
  • Confondre le stockage local de la classe d’instance avec le stockage EBS alloué — les charges lourdes en fichiers temporaires sur SQL Server et Postgres les épuisent différemment.

Prévention

  • Alarme sur FreeStorageSpace à 20 % et 10 % du stockage alloué — les alarmes en valeur absolue deviennent périmées quand le volume grandit.
  • Activez l’autoscaling du stockage avec un plafond MaxAllocatedStorage délibéré sur chaque instance de production.
  • Révisez la rétention des binlogs et les slots de réplication chaque mois; les deux échouent en silence.
  • Gardez log_output = FILE sur MySQL et laissez la rotation RDS gérer les journaux du moteur.
  • Surveillez la pente, pas le niveau : une tendance de FreeStorageSpace qui atteint zéro à l’intérieur de votre fenêtre de rétention d’instantanés mérite un billet maintenant. La stratégie d’instantanés compte ici aussi — voyez le runbook PITR et instantanés.

Un disque plein est la panne RDS la plus évitable qui soit : la métrique est publique, la pente est visible des semaines à l’avance, et le correctif est un appel CLI. Si personne dans votre équipe ne possède vraiment l’environnement AWS de bout en bout, c’est la racine de la plupart de ces problèmes — Stack Harbor opère des comptes AWS au quotidien sous Opérations AWS, et vous pouvez réserver une revue AWS.