Le pager sonne, Slack s’enflamme, et quelqu’un prononce la phrase qui transforme votre café en mécanisme de survie :
« J’ai lancé le delete en prod. »
C’est là que la mythologie du « on a la réplication » s’effondre. La réplication est excellente pour rester en ligne quand le matériel lâche.
Elle est catastrophique pour vous sauver des humains, parce qu’elle réplique les humains avec une fidélité impressionnante. Ce qui vous sauve,
c’est la capacité à rembobiner le temps : la récupération point-in-time (PITR), plus la discipline opérationnelle pour la rendre réelle.
Réplication vs PITR : deux promesses différentes
Promesse de la réplication : rester opérationnel quand quelque chose casse
La réplication concerne la disponibilité et le scaling en lecture. Elle répond à « que se passe-t-il si un nœud meurt ? » et parfois « que se passe-t-il si une zone tombe ? ».
Elle ne répond pas à « que se passe-t-il si nous écrivons des données incorrectes ? » Si vous répliquez des écritures, vous répliquez les erreurs, les suppressions de schéma et les mauvais déploiements.
La phrase douloureuse est « latence de réplication ». Les gens la traitent comme une métrique de performance ; pendant un incident, elle devient un outil de récupération.
La latence peut vous donner une fenêtre pour stopper le rayon d’impact. Mais c’est une ceinture de sécurité peu fiable : parfois elle existe, parfois non,
et elle n’a pas été conçue pour le crash auquel vous êtes confronté.
Promesse de la PITR : revenir à un instant connu
La PITR est une stratégie de sauvegarde, pas de réplication. Le concept est simple : prendre une sauvegarde de base (snapshot complet) puis
conserver les journaux d’écriture préalable (WAL dans PostgreSQL ; binlogs dans MariaDB). Pour récupérer, vous restaurez la sauvegarde de base et rejouez les journaux
jusqu’à juste avant l’erreur.
La PITR est ce que vous voulez quand le problème est « nous avons modifié les données » plutôt que « nous avons perdu un serveur ». C’est aussi ce que vous voulez quand
un job soi-disant « en lecture seule » a décidé d’être créatif et a lancé un UPDATE sans clause WHERE.
Une idée paraphrasée de John Allspaw (opérations et résilience) : « La fiabilité vient de la conception en prévision des pannes, pas de faire semblant qu’elles n’arriveront pas. » (idée paraphrasée)
La réplication garde le service en ligne. La PITR garde votre carrière en ligne.
Modes d’erreur humaine : ce qui se passe réellement
La taxonomie ennuyeuse des catastrophes (qui se répète)
- Suppression/mise à jour accidentelle : clause WHERE manquante, mauvais ID de locataire, ou « correctif rapide » dans une console.
- Changements de schéma ratés : suppression d’une colonne/table, ordre de migration incorrect, ajout d’un NOT NULL avant le backfill.
- Erreurs d’import de données : CSV mal mappé, job ETL utilisant le mauvais environnement, clés dupliquées.
- Erreurs de privilèges : octroi excessif, révocation d’accès, ou maintenance exécutée en superutilisateur.
- Bugs applicatifs : « ça marche en staging » puis le nouveau code supprime les mauvaises lignes à grande échelle.
Pourquoi la réplication vous laisse tomber ici
La plupart des systèmes de réplication dans MariaDB et PostgreSQL sont conçus pour répliquer les changements commités. Ils sont assez déterministes
pour garder les copies cohérentes. C’est excellent jusqu’au moment où le changement que vous avez commit est exactement celui que vous souhaitez annuler.
Le premier piège est psychologique : les équipes voient plusieurs nœuds et supposent « on peut toujours basculer ». Le basculement n’annule pas les écritures.
Il vous déplace simplement vers une autre copie de la même erreur.
Blague #1 : La réplication, c’est comme un chat de groupe — tout le monde reçoit le message, y compris le message embarrassant que vous aimeriez pouvoir retirer.
Ce que la PITR ne peut pas non plus faire (pour ne pas la romantiser)
La PITR ne peut pas reconstruire un historique que vous n’avez pas conservé. Si vous n’archivez pas les WAL/binlogs de manière fiable, ou si vous les faites tourner trop agressivement,
votre bouton de rembobinage est cosmétique. La PITR ne réparera pas non plus une corruption au niveau application si vous ne pouvez pas identifier un point sûr dans le temps.
Vous avez toujours besoin de forensique : quand l’écriture erronée a-t-elle commencé et quand a-t-elle cessé ?
Mécanismes de récupération MariaDB : binlogs, GTID, réplicas
Notions de réplication : ce que vous avez réellement en production
MariaDB (et la lignée MySQL) utilise couramment les journaux binaires du primaire, appliqués par les réplicas. Vous rencontrerez
la réplication fichier/position et la réplication basée sur GTID. Le GTID est généralement plus facile à opérationnaliser, mais il ne résout pas magiquement
l’erreur humaine ; il rend juste le basculement et les changements de topologie moins sujets aux erreurs.
Si vous exécutez la semi-synchronisation, vous réduisez la chance de perdre les dernières transactions lors d’un basculement. C’est un réglage de disponibilité/perte-de-données,
pas un réglage spécifique aux erreurs humaines.
PITR dans MariaDB : sauvegarde de base + replay de binlogs
La PITR MariaDB consiste typiquement à : prendre une sauvegarde complète (logique avec mariadb-dump ou physique avec des outils comme mariabackup),
puis conserver les binlogs et les rejouer jusqu’à juste avant l’instruction fautive. L’avantage opérationnel est que le replay de binlogs peut être
filtré et ciblé si vous utilisez la journalisation en mode row et que vous avez de bons timestamps/GTID.
Les binlogs basés sur les instructions peuvent être une source d’accidents en récupération car le replay peut ne pas être déterministe selon les fonctions, le temps,
ou les instructions non déterministes. La journalisation basée sur les lignes est plus lourde mais plus prévisible pour la récupération.
Le pattern du « replica en retard » (utile, mais pas un plan)
Certaines équipes maintiennent un replica retardé (latence intentionnelle) afin que les suppressions accidentelles sur le primaire ne s’appliquent pas immédiatement.
Cela peut vous sauver si l’erreur est remarquée rapidement et que la fenêtre de retard la couvre.
Ce n’est toujours pas un plan de récupération complet. Les replicas retardés échouent en conditions réelles : quelqu’un le redémarre et il se rattrape,
ou le thread SQL s’arrête et vous ne le remarquez pas avant qu’il ne soit inutile, ou la latence est trop courte pour des incidents à progression lente.
Mécanismes de récupération PostgreSQL : WAL, timelines, standbys
Notions de réplication : streaming replication et sa forme
La réplication streaming de PostgreSQL envoie les WAL du primaire vers les standbys. Les standbys peuvent être synchrones ou asynchrones.
Comme MariaDB, la réplication vise à garder une copie prête à prendre la relève.
La nuance opérationnelle : PostgreSQL a des timelines. Lorsque vous promouvez un standby, vous créez une nouvelle timeline. C’est normal,
mais cela a de l’importance pour la PITR car votre archive WAL doit inclure l’historique des timelines, et vous devez comprendre ce que vous restaurez.
PITR dans PostgreSQL : sauvegarde de base + archivage WAL
La PITR est un concept de première classe dans PostgreSQL : une sauvegarde de base plus un archivage continu des segments WAL. La récupération se configure
en restaurant la sauvegarde de base, puis en utilisant un signal de récupération plus une cible de temps/LSN, et en rejouant les WAL depuis votre archive.
Le grand avantage : PostgreSQL dispose d’outils robustes autour du replay WAL et d’une séparation propre entre la réplication streaming et l’archivage WAL.
Mais vous devez quand même construire la chaîne : fiabilité de archive_command, rétention, validation et tests de restauration.
Blague #2 : Le WAL est l’enregistreur de vol de votre base de données — sauf qu’il n’aide que si vous ne l’avez pas stocké dans le même avion.
La réplication logique n’est pas votre parachute
La réplication logique de PostgreSQL (et les systèmes de capture de changement similaires) peut aider à répliquer sélectivement des tables et éviter certaines
catégories de douleur liées aux changements de schéma. Ce n’est pas un substitut à la PITR. La réplication logique diffuse aussi des changements, y compris des erreurs,
et manque souvent de la capacité de rembobiner sans une stratégie de snapshot séparée.
Ce qui vous sauve après une erreur humaine : matrice de décision
Premiers principes : définissez la question avant de choisir un outil
Après une erreur humaine, vous avez besoin de réponses à trois questions :
- Rayon d’impact : quelles données ont changé et dans quelle mesure ?
- Bornes temporelles : quand la mauvaise modification a-t-elle commencé, et quand a-t-elle été détectée ?
- Objectif de récupération : devez-vous restaurer tout le cluster, ou seulement un schéma/table/locataire ?
La réplication aide quand :
- Un nœud est mort et vous devez basculer avec un minimum d’indisponibilité.
- Vous avez besoin d’une copie en lecture seule pour décharger des requêtes.
- Vous voulez une capacité de remplacement rapide pendant que vous reconstruisez l’hôte défaillant.
La PITR aide quand :
- Les données ont été modifiées incorrectement et vous devez revenir « dans le temps ».
- Des changements de schéma ont été appliqués et vous devez récupérer juste avant leur application.
- Un rançongiciel/compromission a chiffré ou altéré des données sur toutes les réplicas.
Vérité dure : vous avez typiquement besoin des deux
Les systèmes matures utilisent la réplication pour la disponibilité et la PITR pour la récupération. Si le budget force un choix, choisissez la PITR d’abord pour
les systèmes où la correction des données importe plus que le temps de disponibilité. C’est la plupart des systèmes métier, même ceux dont les propriétaires insistent
« on peut recréer ça ». Ils ne le peuvent pas. Ils ne veulent juste pas payer le stockage.
Tâches pratiques (commandes, sorties, décisions)
Ce sont le type de tâches que vous exécutez pendant un exercice ou un incident : rapides, concrètes et liées à des décisions. Les sorties
montrées sont représentatives. Votre environnement diffèrera, mais le sens restera.
Tâche 1 — MariaDB : confirmer que le binlog est activé et quel format est utilisé
cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'binlog_format';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | ROW |
+---------------+-----------+
Ce que cela signifie : les binlogs existent et sont basés sur les lignes (bon pour un replay déterministe).
Décision : si log_bin est OFF, arrêtez de prétendre que vous avez la PITR ; vous n’avez que des sauvegardes.
Si binlog_format est STATEMENT, envisagez de passer à ROW pour la récupérabilité (après avoir vérifié l’impact sur la charge).
Tâche 2 — MariaDB : trouver le fichier/position binlog courant (base pour la timeline de l’incident)
cr0x@server:~$ mariadb -e "SHOW MASTER STATUS\G"
*************************** 1. row ***************************
File: mariadb-bin.001842
Position: 987654321
Binlog_Do_DB:
Binlog_Ignore_DB:
Ce que cela signifie : cela identifie où se trouve le primaire « maintenant ».
Décision : enregistrez-le dans le document d’incident ; vous utiliserez le fichier/position ou des plages GTID pour borner la récupération.
Tâche 3 — MariaDB : vérifier la santé des réplicas et la latence
cr0x@server:~$ mariadb -e "SHOW SLAVE STATUS\G" | egrep "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Using_Gtid"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 2
Using_Gtid: Current_Pos
Ce que cela signifie : la réplication est saine et presque rattrapée.
Décision : si l’erreur humaine vient d’avoir lieu et que la latence est faible, vous ne pouvez probablement pas utiliser la latence comme fenêtre de sécurité.
Si Slave_SQL_Running est No, traitez cela comme un incident — votre « réplica de sécurité » pourrait être mort silencieusement.
Tâche 4 — MariaDB : arrêter immédiatement un replica pour préserver une copie « pré-erreur » (si vous l’avez pris à temps)
cr0x@server:~$ mariadb -e "STOP SLAVE SQL_THREAD; SHOW SLAVE STATUS\G" | egrep "Slave_SQL_Running|Seconds_Behind_Master"
Slave_SQL_Running: No
Seconds_Behind_Master: 57
Ce que cela signifie : le thread SQL est arrêté ; le thread IO peut encore récupérer les binlogs, mais ne pas les appliquer.
Décision : figez ce replica. Ne redémarrez pas le thread SQL avant d’avoir extrait les lignes nécessaires ou élaboré un plan de récupération.
C’est une mesure tactique, pas votre restauration finale.
Tâche 5 — MariaDB : localiser un événement suspect dans les binlogs par heure
cr0x@server:~$ mysqlbinlog --start-datetime="2025-12-30 09:55:00" --stop-datetime="2025-12-30 10:05:00" /var/lib/mysql/mariadb-bin.001842 | head -n 30
# at 456700001
#251230 9:58:12 server id 101 end_log_pos 456700321 CRC32 0x2a1b3c4d GTID 0-101-998877
BEGIN
# at 456700321
#251230 9:58:12 server id 101 end_log_pos 456701234 CRC32 0x1c2d3e4f Query thread_id=8899 exec_time=0 error_code=0
use appdb/*!*/;
SET TIMESTAMP=1767088692/*!*/;
DELETE FROM orders WHERE tenant_id=42;
/*!*/;
Ce que cela signifie : vous avez trouvé l’instruction fautive et son heure/GTID.
Décision : fixez votre point d’arrêt PITR juste avant ce GTID/heure ; ou planifiez une réinsertion au niveau table si faisable.
Si le binlog est basé sur les lignes, la sortie montrera des événements de lignes plutôt que le SQL, ce qui peut toujours être utilisé pour rejouer/ignorer précisément.
Tâche 6 — MariaDB : rejouer les binlogs dans une copie restaurée jusqu’à un point sûr
cr0x@server:~$ mysqlbinlog --stop-datetime="2025-12-30 09:58:11" /archives/mariadb-bin.* | mariadb appdb
Query OK, 0 rows affected (0.001 sec)
Query OK, 0 rows affected (0.000 sec)
Ce que cela signifie : vous avez appliqué les changements jusqu’à juste avant l’instruction fautive.
Décision : validez les comptes de lignes / checks métier sur cette copie restaurée ; puis décidez de basculer, d’extraire des lignes, ou d’exécuter une fusion contrôlée.
Tâche 7 — PostgreSQL : confirmer que l’archivage WAL est configuré
cr0x@server:~$ psql -X -c "SHOW wal_level; SHOW archive_mode; SHOW archive_command;"
wal_level
----------
replica
(1 row)
archive_mode
--------------
on
(1 row)
archive_command
------------------------------------------------
test ! -f /wal-archive/%f && cp %p /wal-archive/%f
(1 row)
Ce que cela signifie : l’archivage WAL est activé, et archive_command est une copie simple vers un répertoire d’archive local.
Décision : si archive_mode est off, vous n’avez pas de PITR. Si archive_command est fragile (pas de retries, pas d’alerting),
considérez-le comme un bug de fiabilité et corrigez-le avant d’en avoir besoin.
Tâche 8 — PostgreSQL : vérifier que les WAL sont réellement archivés (pas seulement « configurés »)
cr0x@server:~$ psql -X -c "SELECT now(), last_archived_wal, last_archived_time, failed_count FROM pg_stat_archiver;"
now | last_archived_wal | last_archived_time | failed_count
-------------------------------+---------------------------+-----------------------------+--------------
2025-12-30 10:06:40.12345+00 | 000000010000003A0000009F | 2025-12-30 10:06:12+00 | 0
(1 row)
Ce que cela signifie : l’archivage fonctionne récemment ; les échecs sont nuls.
Décision : si failed_count augmente, arrêtez. Vous construisez une fausse sensation de sécurité.
Corrigez d’abord les échecs de l’archivage, sinon votre restauration s’arrêtera sur un segment manquant.
Tâche 9 — PostgreSQL : vérifier la latence de réplication pendant un incident
cr0x@server:~$ psql -X -c "SELECT application_name, state, write_lag, flush_lag, replay_lag FROM pg_stat_replication;"
application_name | state | write_lag | flush_lag | replay_lag
------------------+-----------+-----------+-----------+------------
standby-a | streaming | 00:00:00 | 00:00:00 | 00:00:02
(1 row)
Ce que cela signifie : le standby a 2 secondes de retard en replay.
Décision : cette latence n’est pas un plan de récupération. Si l’écriture fautive a déjà été commitée, elle touchera probablement aussi le standby.
Si vous avez besoin d’un « point gel », vous devez agir vite (ou compter sur la PITR).
Tâche 10 — PostgreSQL : trouver l’heure approximative des mauvais changements via logs/LSN
cr0x@server:~$ psql -X -c "SELECT now(), pg_current_wal_lsn();"
now | pg_current_wal_lsn
-------------------------------+--------------------
2025-12-30 10:07:10.551+00 | 3A/9F123ABC
(1 row)
Ce que cela signifie : vous avez un marqueur LSN courant.
Décision : pendant la réponse à l’incident, enregistrez les LSN avec les timestamps. Ils aident à reconstituer ce qui s’est passé si les horloges dérivent ou si les logs sont confus.
Tâche 11 — PostgreSQL : restaurer une sauvegarde de base et configurer la cible PITR
cr0x@server:~$ sudo -u postgres bash -lc 'cat > /var/lib/postgresql/16/main/postgresql.auto.conf <
Ce que cela signifie : la récupération tirera les WAL depuis l’archive et s’arrêtera à l’heure cible.
Décision : choisissez une heure cible juste avant la transaction destructive. Si incertain, choisissez plus tôt puis ré-appliquez les changements connus bons avec prudence.
Tâche 12 — PostgreSQL : confirmer que la récupération s’est arrêtée là où vous l’avez demandé
cr0x@server:~$ psql -X -c "SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn();"
pg_is_in_recovery | pg_last_wal_replay_lsn
-------------------+------------------------
f | 3A/9EFFFF00
(1 row)
Ce que cela signifie : la récupération est terminée (f) et vous avez le dernier LSN rejoué.
Décision : exécutez des requêtes de validation maintenant. Si les données semblent correctes, vous pouvez planifier le cutover. Sinon, relancez la récupération avec une cible différente.
Tâche 13 — Vérification de sanity du stockage : vérifier que le volume d’archive a de l’espace et n’est pas plein silencieusement
cr0x@server:~$ df -h /wal-archive
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 500G 412G 63G 87% /wal-archive
Ce que cela signifie : l’archive WAL approche de sa capacité.
Décision : si cela atteint 100%, l’archivage WAL échoue et la PITR casse. Mettez en place rétention et alertes ; ne vous fiez pas au « on ajoute juste de l’espace » comme stratégie.
Tâche 14 — MariaDB : vérifier que la rétention des binlogs ne grignote pas votre fenêtre de récupération
cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'expire_logs_days'; SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';"
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| expire_logs_days| 1 |
+-----------------+-------+
+---------------------------+--------+
| Variable_name | Value |
+---------------------------+--------+
| binlog_expire_logs_seconds| 0 |
+---------------------------+--------+
Ce que cela signifie : les binlogs expirent après 1 jour via expire_logs_days.
Décision : si votre temps de détection pour les erreurs est plus long qu’un jour (ce qui est fréquent), augmentez la rétention ou expédiez les binlogs vers un stockage durable.
Sinon la PITR échouera avec des logs manquants exactement quand vous en aurez besoin.
Playbook de diagnostic rapide
Quand quelqu’un hurle « les données ont disparu », vous devez identifier s’il s’agit (a) d’un problème de réplication, (b) d’un problème de sauvegarde/PITR,
ou (c) d’un bug applicatif qui continue de dégrader les données. C’est du triage, pas de la philosophie.
Première étape : arrêter l’hémorragie
- Geler les écritures : désactivez le job, mettez un feature flag, ou déployez un rollback. Si impossible, bloquez temporairement l’utilisateur applicatif au niveau BD.
- Préserver les preuves : snapshottez le volume affecté si possible ; arrêtez le thread d’application d’un replica si vous l’avez intercepté à temps.
- Enregistrer des marqueurs : heure courante, fichier/position binlog ou WAL LSN courant, et qui a exécuté quoi.
Deuxième étape : décider quel chemin de récupération est viable
- Y a-t-il un réplica sûr ? Seulement s’il est définitivement pré-erreur (retard intentionnel, arrêté à temps, ou topologie séparée).
- La PITR est-elle viable ? Confirmez que l’archivage des logs est continu, que la rétention couvre la fenêtre temporelle, et que vous avez une sauvegarde de base.
- Pouvez-vous faire une réparation ciblée ? Parfois vous pouvez réinsérer des lignes depuis un snapshot/réplica sans restauration complète.
Troisième étape : trouver le goulot d’étranglement (tueur de RTO)
- Débit de restauration : téléchargement + décompression de la sauvegarde de base + performances du système de fichiers.
- Vitesse de replay : taux d’application WAL/binlog ; vérifiez si vous êtes limité en I/O ou CPU.
- Validation & cutover : pouvez-vous vérifier la correction rapidement et rediriger le trafic en sécurité ?
Erreurs courantes : symptômes → cause racine → correctif
« Nous avons basculé, mais la mauvaise suppression est toujours là. »
Symptôme : vous promouvez un replica et les lignes manquantes restent manquantes.
Cause racine : la réplication a propagé la suppression ; le basculement a seulement changé la copie que vous regardez.
Correctif : utilisez la PITR ou un replica/snapshot pré-erreur préservé ; implémentez la PITR avec des restaurations testées ; considérez le replica retardé comme un complément.
« La PITR a échoué à mi-chemin avec des fichiers WAL/binlog manquants. »
Symptôme : la récupération s’arrête avec « requested WAL segment has already been removed » (PostgreSQL) ou fichier binlog introuvable (MariaDB).
Cause racine : rétention trop courte, pipeline d’archivage en échec, ou archive stockée sur le même disque qui est tombé.
Correctif : augmentez la rétention, alertez sur les échecs de l’archiver, stockez les archives sur un stockage durable séparé, et exécutez des drills de restauration périodiques qui prouvent la continuité.
« Nous avons restauré, mais les données sont incohérentes / les contraintes échouent. »
Symptôme : la base restaurée ne démarre pas proprement, ou l’application explose d’erreurs à cause de relations/contraintes manquantes.
Cause racine : mélange incorrect de dumps logiques et de replay de logs physiques ; ou restauration de schéma d’un moment et des données d’un autre.
Correctif : gardez la PITR cohérente : la sauvegarde de base doit correspondre au flux de logs. Pour les restaurations partielles, exportez/importez de manière cohérente (schéma + données) et validez.
« Le réplica devait être retardé, mais il ne l’était pas. »
Symptôme : le replica retardé contient l’erreur.
Cause racine : retard mal configuré, replica redémarré et rattrapé, ou monitoring n’a pas alerté sur l’absence de retard.
Correctif : surveillez le retard effectif, pas seulement la configuration. Testez le workflow : pouvez-vous réellement arrêter l’application et extraire des données pendant un exercice ?
« Le disque d’archive s’est rempli silencieusement ; maintenant nous n’avons plus de PITR. »
Symptôme : échecs d’archivage commencent ; plus tard vous découvrez des trous.
Cause racine : pas de rétention, pas d’alerting, ou archive stockée localement sans planification de capacité.
Correctif : définissez des politiques de rétention, surveillez l’espace libre et les stats de l’archiver, et traitez l’archive WAL/binlog comme un stockage critique de production avec des SLO.
« La restauration est trop lente ; le RTO est de la fantaisie. »
Symptôme : la restauration de base prend des heures ; le replay WAL prend encore plus de temps ; l’entreprise panique.
Cause racine : sauvegardes sur des médias lents, chemin de restauration non testé, goulots d’étranglement d’encryption/compression, ou IOPS insuffisantes.
Correctif : mesurez le débit de restauration trimestriellement, gardez des sauvegardes de base « warm » en standby, optimisez le stockage, et considérez des stratégies de sauvegarde incrémentale ou différée.
Checklists / plan étape par étape
Construire une posture de récupération qui survit aux humains (plan 90 jours)
- Définir RPO/RTO par base : ce que vous pouvez perdre, et combien de temps vous pouvez être hors service.
- Implémenter la réplication pour la disponibilité : au moins un standby/réplica dans un domaine de panne séparé.
- Implémenter la PITR :
- MariaDB : sauvegarde de base physique + shipping des binlogs et rétention.
- PostgreSQL : sauvegarde de base + archivage WAL avec
pg_stat_archiversurveillé.
- Stockage séparé : archivez les logs hors des disques du primaire et idéalement hors du même rayon d’impact.
- Rétention basée sur le temps de détection : conservez les logs assez longtemps pour pouvoir remarquer les erreurs. Beaucoup d’équipes ont besoin de semaines, pas de jours.
- Réaliser des drills de restauration mensuellement : une restauration PITR complète sur un cluster scratch, avec requêtes de validation et un journal écrit.
- Documenter le cutover : DNS/chaînes de connexion, mode lecture seule, coordination applicative, et rollback du rollback.
- Ajouter des garde-fous : limiter l’accès à la console prod, exiger des migrations révisées, protéger les tables dangereuses (permissions), et utiliser des outils plus sûrs.
Étapes de réponse à incident : suppression/drop accidentel
- Arrêter les écrivains : geler le job/le déploiement ; empêcher d’autres changements.
- Marquer la timeline : heure exacte de détection ; identifier l’heure de début approximative via logs applicatifs/logs d’audit.
- Choisir la stratégie de récupération :
- Petit rayon d’impact : extraire les lignes manquantes depuis une restauration PITR ou un replica arrêté et réinsérer.
- Grand rayon d’impact : restauration PITR complète et cutover contrôlé.
- Exécuter la récupération en parallèle : une personne monte l’environnement de restauration ; une autre valide l’étendue ; une autre gère les communications.
- Valider sérieusement : comptes de lignes, invariants métier, tests smoke applicatifs.
- Cutover : basculer le trafic, surveiller les taux d’erreur, garder l’ancien primaire isolé tant que vous n’êtes pas sûr.
Trois mini-récits d’entreprise issus du terrain
Mini-récit 1 : l’incident causé par une fausse hypothèse
Une plateforme B2B de taille moyenne exploitait MariaDB avec un primaire et deux réplicas. Le deck ops disait « HA : oui » et tout le monde s’est détendu.
Un développeur a lancé un script de nettoyage censé supprimer des locataires de test. Il a supprimé des locataires réels. Rapidement.
L’on-call a fait ce que le runbook suggérait : promouvoir un replica. Cela a pris des minutes, et le site est revenu. Tout le monde a applaudi,
jusqu’à ce que le support client signale les mêmes locataires manquants. Bien sûr. La suppression avait été répliquée. Ils venaient de basculer vers
une autre copie du même lieu du crime.
Ils avaient des dumps logiques nocturnes, mais pas de rétention de binlog au-delà de quelques heures et pas de chemin de restauration testé pour un « restore à 10:03 ».
L’équipe a essayé de reconstituer à partir d’événements applicatifs et d’exports partiels. Ça a fonctionné pour certains locataires, mais pas tous, et ça a pris des jours.
Le correctif durable n’a pas été « former mieux les devs ». Ce fut d’activer l’envoi correct des binlogs hors-hôte, d’augmenter la rétention,
et d’exécuter un drill PITR mensuel où quelqu’un supprime intentionnellement un locataire dans un bac à sable et le récupère.
Mini-récit 2 : l’optimisation qui s’est retournée contre eux
Une autre entreprise exploitait PostgreSQL avec archivage WAL. Quelqu’un a remarqué que le volume d’archive WAL grossissait vite et a « optimisé »
la rétention en ne gardant que quelques jours. Ils ont aussi compressé fortement les archives et les ont poussées vers un stockage plus lent.
C’était joli sur le tableau de bord des coûts.
Trois semaines plus tard, un bug applicatif de longue durée commençait à corrompre un sous-ensemble de lignes. Ce n’était pas dramatique — assez subtil
pour passer une inspection distraite. Lorsqu’on l’a finalement découvert, l’équipe avait besoin de restaurer à un point avant le déploiement du bug.
C’était bien en dehors de la fenêtre de rétention WAL.
Ils ont tenté d’assembler une restauration avec des sauvegardes de base hebdomadaires plus des exports logiques partiels, mais les données restaurées
ne s’alignaient pas proprement avec les migrations de schéma actuelles. Ils ont passé la nuit à débattre de quelle « vérité » faire confiance : la base de données
ou les caches dérivés de l’application. Ce n’est pas un débat agréable à 3h du matin.
Le correctif était ennuyeux : conserver les archives WAL plus longtemps (basé sur le temps de détection, pas sur l’anxiété disque), stocker sur un stockage
qui peut soutenir le débit de restauration, et surveiller l’objectif RTO réel comme métrique. Le coût comptait toujours, mais ils ont optimisé avec des données,
pas avec des impressions.
Mini-récit 3 : la pratique ennuyeuse mais correcte qui a sauvé la mise
Une équipe de services financiers (la pression réglementaire fait des merveilles pour les bonnes habitudes) exploitait PostgreSQL avec réplication streaming,
plus archivage WAL vers un stockage séparé. Chaque mois, un job programmé restaurait la sauvegarde de base de la semaine précédente dans un
environnement isolé et exécutait un ensemble d’« invariants » : les soldes s’additionnent correctement, les clés étrangères correspondent, et un échantillon
de parcours client peut être rejoué.
Un après-midi, un ingénieur a appliqué une migration qui supprimait un index puis a lancé une mise à jour qui a accidentellement touché bien plus de lignes que prévu.
Le site est resté up — la réplication était fine — mais les données visibles par les clients étaient erronées. Ils ont immédiatement gelé les écritures.
Parce qu’ils avaient fait des drills de restauration, ils connaissaient déjà le temps de restauration, les commandes, et quel chemin de stockage était le plus rapide.
Ils ont restauré à cinq minutes avant la migration, validé les invariants, puis utilisé un replay contrôlé des événements applicatifs pour une fenêtre étroite.
Le cutover fut tendu mais propre.
Personne n’a reçu d’ovation debout. C’est le but. La récompense pour la correction, c’est un canal d’incident calme et tout le monde qui va se coucher.
Faits & contexte historique utiles
- Le WAL de PostgreSQL a une longue histoire : l’idée centrale du write-ahead logging est antérieure à beaucoup de produits de sauvegarde « modernes ».
- MariaDB a forké MySQL en 2009 après l’acquisition de Sun par Oracle ; cette histoire a façonné la confiance en entreprise et les choix d’outillage.
- Les formats de binlog MySQL/MariaDB ont évolué : la journalisation statement-based est arrivée en premier ; la row-based est devenue le choix le plus sûr pour une récupération déterministe.
- Les timelines PostgreSQL ont de l’importance : chaque promotion crée une nouvelle timeline ; oublier les fichiers d’historique de timeline peut casser les restaurations de manière déroutante.
- La réplication n’a jamais été conçue pour annuler : les deux systèmes priorisent la cohérence des copies, pas la réversibilité des transactions.
- « Réplication synchrone » ne veut pas dire « à l’abri des humains » : elle réduit la perte de données lors d’un crash/basculement, pas la corruption logique.
- La réplication logique est sélective mais pas voyage dans le temps : elle est excellente pour les migrations et la réplication partielle, pas pour rembobiner des erreurs.
- Beaucoup d’incidents sont des échecs de détection : l’erreur humaine arrive souvent des minutes ou heures avant d’être remarquée ; la rétention doit coller à la réalité.
FAQ
1) Si j’ai la réplication, ai-je encore besoin de la PITR ?
Oui. La réplication gère le matériel et certains scénarios de basculement. La PITR gère les écritures erronées, les erreurs de schéma, et les compromissions qui se propagent.
Si vous ne pouvez choisir qu’une seule solution pour une base critique, choisissez la PITR et acceptez un certain temps d’arrêt.
2) Un replica retardé peut-il remplacer la PITR ?
Non. C’est un complément utile : une manière rapide de récupérer des lignes manquantes ou de préserver une copie pré-erreur. Mais il peut échouer silencieusement,
et ne couvrira pas la corruption à progression lente au-delà de sa fenêtre de retard.
3) Quelle est la plus grande différence opérationnelle entre MariaDB et PostgreSQL en matière de récupération ?
PostgreSQL dispose d’un workflow PITR très explicite centré sur les sauvegardes de base et l’archivage WAL avec une introspection forte (comme pg_stat_archiver).
La PITR de MariaDB est puissante mais plus « assemblez votre propre aventure » : sauvegardes physiques plus gestion des binlogs et replay soigné.
4) Dois-je utiliser des dumps logiques pour la PITR ?
Les dumps logiques sont excellents pour la portabilité et les restaurations au niveau table, mais ils ne constituent pas à eux seuls une PITR. La PITR nécessite une base cohérente + flux de logs.
Utilisez les dumps logiques en complément, pas comme colonne vertébrale, sauf si la taille des données et le RTO le permettent.
5) Combien de temps dois-je conserver les WAL/binlogs ?
Basez-vous sur le temps de détection, pas sur le confort. Si votre organisation découvre habituellement les problèmes des jours plus tard, conservez au moins des semaines de logs.
Assurez-vous aussi que vous pouvez supporter le temps de restauration pour cette fenêtre.
6) Quelle est la meilleure façon de savoir que mon RTO est réel ?
Effectuez des restaurations selon un calendrier et mesurez : temps pour récupérer la sauvegarde, temps pour restaurer, temps pour rejouer les logs, temps pour valider,
temps pour cutover. Si vous ne mesurez pas, votre RTO n’est qu’un vœu.
7) Puis-je faire une PITR « juste avant une transaction » de façon fiable ?
Généralement oui, mais la précision varie. PostgreSQL peut cibler des timestamps et peut aussi travailler avec des cibles LSN. MariaDB peut rejouer jusqu’à une datetime
et souvent jusqu’à des frontières GTID selon les outils et le format de logging. Plus vous logguez et vous entraînez, plus vous gagnez en précision.
8) Qu’en est-il de restaurer une seule table ou un seul locataire ?
Le schéma courant est : restauration PITR dans un environnement isolé, extraction des lignes nécessaires (ou schéma/table), puis fusion dans la prod avec prudence.
C’est plus lent qu’un cutover complet mais évite un rollback global pour une erreur localisée.
9) Le chiffrement/la compression des archives affecte-t-il la récupération ?
Oui. Cela peut écraser le débit de restauration et transformer « nous avons des sauvegardes » en « nous avons des sauvegardes lentes ». Si vous compressez, testez la vitesse de restauration sous charge.
N’optimisez pas les coûts de stockage en rendant la récupération impossible.
Conclusion : prochaines étapes réalisables cette semaine
Si vous retenez une leçon opérationnelle du débat MariaDB vs PostgreSQL, faites-en celle-ci : la réplication n’est pas un bouton de rembobinage.
Les deux bases peuvent très bien récupérer après une erreur humaine — mais seulement si vous traitez la PITR comme une fonctionnalité de production, pas comme une case à cocher.
- Choisissez une fenêtre de récupération réaliste (RPO/RTO) et alignez la rétention des logs sur votre temps de détection.
- Prouvez que la PITR fonctionne : réalisez un drill complet de restauration de bout en bout et chronométrez-le.
- Instrumentez la chaîne d’archivage : alertez sur les échecs d’archivage WAL/binlog et sur la capacité du stockage d’archive.
- Rédigez le runbook « arrêter l’hémorragie » : geler les écritures fait souvent la différence entre une réparation de 10 minutes et une reconstruction d’une semaine.
- Conservez la réplication pour l’uptime, mais cessez de la vendre en interne comme protection contre les erreurs. Ce n’est pas le cas.
Le jour où vous en aurez besoin, vous n’aurez pas le temps de devenir la personne qui sait comment faire. Renforcez ce muscle maintenant, tant que personne ne regarde.