MariaDB vs Percona Server Réplication : quand les cas limites font mal

Cet article vous a aidé ?

Sur les schémas, la réplication ressemble à une ligne droite : le primaire écrit, les réplicas suivent, tout le monde rentre chez soi.
En production, c’est une scène de crime : un réplica « en cours » mais erroné, une bascule qui « a fonctionné » mais a perdu des données,
ou un graphe de latence qui se bloque juste quand le PDG fait une démo.

MariaDB et Percona Server parlent tous deux un « MySQL-ish », mais leurs cas limites de réplication ne coïncident pas proprement.
Les pires défaillances viennent de l’hypothèse qu’ils le font. Ce guide de terrain couvre les coins dangereux : GTID, binlogs,
sécurité au crash, filtrage, semi-sync, et les habitudes opérationnelles qui vous évitent l’enfer des postmortems.

Ce que vous choisissez réellement (indice : sémantique opérationnelle)

« MariaDB vs Percona Server » sonne comme une liste de fonctionnalités. Avec la réplication, c’est un choix de comportement.
En temps normal, les deux vont streamer des événements de binlog vers les réplicas et les appliquer. Sous contrainte — partitions réseau,
blocages disque, bascules, récupération après crash — les différences apparaissent : ce qui est écrit dans le binlog, ce qui est
accusé de réception, ce qui est considéré comme sûr, et ce que vos outils supposent.

Percona Server est une variante de MySQL qui suit généralement le comportement d’Oracle MySQL tout en ajoutant instrumentation,
réglages et correctifs opérationnels (souvent orientés performance ou observabilité). MariaDB est un fork autonome avec
des fonctionnalités de réplication parfois en avance, parfois simplement différentes, et occasionnellement incompatibles de manière subtile —
surtout autour de la sémantique GTID.

Voici le cadre d’opinion qui tient pendant les incidents :

  • Si vous avez besoin d’« interopérabilité avec l’écosystème MySQL en priorité », Percona Server est généralement le pari le plus sûr. Beaucoup d’outils supposent les détails GTID et binlog à la manière d’Oracle.
  • Si vous voulez des fonctionnalités spécifiques à MariaDB (et acceptez la sémantique MariaDB), engagez-vous complètement : utilisez GTID MariaDB de bout en bout, des outils compatibles MariaDB, et testez les chemins de bascule comme vous testez les sauvegardes — régulièrement.
  • Si vous prévoyez de mélanger MariaDB et Percona dans la même topologie de réplication, faites-le uniquement avec une matrice de compatibilité écrite et un laboratoire qui rejoue vos binlogs réels. « Ça a marché une fois » n’est pas une matrice.

Faits historiques qui expliquent les bizarreries d’aujourd’hui

Ce sont des bribes d’histoire courtes et concrètes qui comptent parce que la « bizarrerie » en réplication est souvent
« des décisions héritées prises en public ». Gardez-les à l’esprit quand vous déboguez.

  1. La réplication MySQL a commencé comme réplication basée sur les instructions (SBR), fragile face au SQL non déterministe ; la réplication basée sur les lignes (RBR) est arrivée ensuite et a changé les attentes opérationnelles.
  2. MariaDB a bifurqué de MySQL en 2009 et a fait évoluer ses fonctionnalités de réplication indépendamment, y compris sa propre implémentation GTID et métadonnées.
  3. GTID d’Oracle MySQL (5.6+) et GTID de MariaDB ne sont pas le même protocole ; ils résolvent des problèmes similaires avec des identifiants et règles de bascule différents.
  4. Percona Server a historiquement livré des patchs « orientés opérateur » comme une meilleure instrumentation et des options de configuration ; cela a influencé la manière dont les équipes surveillent la réplication (et leurs attentes).
  5. MySQL 5.7/8.0 a fait de la réplication basée sur les lignes la valeur par défaut dans de nombreuses entreprises car elle réduit la « dérive des réplicas », mais elle augmente le volume de binlog et la sensibilité IO.
  6. La réplication multi-thread est arrivée par étapes : d’abord un parallélisme grossier, puis des approches plus fines basées sur « horloge logique »/GTID ; MariaDB a sa propre approche de réplication parallèle et ses propres réglages.
  7. Le semi-synchrone a été ajouté comme concept de plugin et a évolué ; il réduit mais n’élimine pas les risques de perte de données sous certaines séquences de bascule.
  8. La sécurité au crash de la réplication s’est améliorée au fil des ans via des dépôts de métadonnées et la récupération des relay logs, mais des choix de configuration peuvent vous ramener en 2012.
  9. Les checksums et métadonnées des événements de binlog ont évolué ; la réplication inter-version et inter-flavors peut casser sur des détails aussi triviaux que « le binlog indique CRC32 et le réplica n’est pas d’accord ».

Modèles de réplication et divergences entre MariaDB et Percona

Réplication asynchrone : le défaut qui ment poliment

La réplication asynchrone classique signifie que le primaire commit et répond au client « OK » sans attendre les réplicas.
C’est rapide. C’est aussi honnête sur un point : si le primaire meurt, vous pouvez perdre les dernières transactions.
Les cas limites apparaissent quand on oublie que l’ACK client n’est pas une garantie de durabilité au-delà des paramètres de stockage du primaire.

La différence MariaDB vs Percona ici n’est pas philosophique. Elle tient aux détails :
comment l’état GTID est suivi, comment la récupération après crash repositionne les relay logs, quels sont les paramètres par défaut, et ce que vos
outils d’orchestration supposent.

Ligne vs instruction vs mixte : le format de réplication n’est pas une préférence

Si vous utilisez encore la réplication basée sur les instructions sur des systèmes critiques, vous misez essentiellement votre
emploi sur le fait que chaque requête soit déterministe sous tous les plans d’exécution, fuseaux horaires, modes SQL et fonctions.
C’est un choix de vie audacieux.

La RBR est plus sûre pour la cohérence mais plus lourde en disque, IO, et parfois réseau. Le mode mixte tente d’être malin et vous surprend souvent à 3 h du matin.
Le cas limite important : une seule instruction non déterministe peut causer une dérive du réplica, et alors chaque bascule « réussie » n’est que le fait de remplacer plus rapidement une base de données erronée.

Percona Server vs MariaDB : ce que ressentent les opérateurs

Les opérateurs ne se soucient pas des slogans ; ils veulent que les outils de bascule fassent les bons choix.
Dans Percona Server (aligné sur la sémantique Oracle MySQL), GTID et les internals de réplication tendent à se comporter comme l’écosystème MySQL plus large l’attend.
Les fonctionnalités de réplication de MariaDB peuvent être excellentes, mais elles ne sont pas toujours plug-and-play.

Traduction : vous pouvez exploiter l’un ou l’autre correctement, mais vous ne pouvez pas improviser. La réplication punit l’improvisation.

GTID : le plus gros piège commercialisé

Les GTID sont censés rendre la bascule ennuyeuse : chaque transaction a un ID global, les réplicas savent ce qu’ils ont exécuté,
et vous pouvez promouvoir un réplica sans compter manuellement les positions binlog.

Les cas limites proviennent de deux faits :

  • Le GTID de MariaDB et le GTID MySQL/Oracle sont des systèmes différents avec des formats et une gestion d’état différents.
  • La correction des GTID dépend de la manière dont vous configurez la journalisation, la sécurité au crash et des hypothèses de votre outil de bascule.

GTID MariaDB vs GTID MySQL/Percona : « même acronyme, contrat différent »

Dans le style MySQL/Percona, l’UUID du serveur (ou l’ensemble d’identifiants serveur) est inclus dans les ensembles GTID et les variables d’état
comme gtid_executed. MariaDB utilise un GTID basé sur domaine avec des variables et conventions différentes.
Les deux peuvent supporter le comportement « auto-positioning », mais le niveau wire et les métadonnées ne sont pas interchangeables.

Mélanger les flavors à travers des frontières GTID est là où les équipes saignent. Si vous répliquez de MariaDB vers Percona ou vice versa,
vous devez valider :

  • Si le GTID est supporté dans cette direction et combinaison de versions.
  • Si votre canal de réplication comprend le format GTID émis par le primaire.
  • Si votre outil de bascule lit les bonnes variables d’état et les interprète correctement.

GTID et bascule : ce que « sûr » signifie réellement

Une bascule GTID « sûre » requiert deux conditions :

  1. Le réplica candidat a reçu toutes les transactions qui ont été accusées aux clients (ou votre appli accepte d’en perdre certaines).
  2. Le réplica candidat a appliqué ces transactions et ne les réappliquera ni ne les sautera après promotion.

Le GTID aide pour la condition n°2 (ne pas réappliquer les transactions) si configuré correctement. Il ne garantit pas la n°1.
C’est là que le semi-sync, les paramètres de durabilité (sync_binlog, innodb_flush_log_at_trx_commit) et le timing réseau comptent.

Blague #1

Le GTID, c’est comme étiqueter vos restes : vous devez quand même les mettre au frigo si vous ne voulez pas le regretter plus tard.

Compatibilité des binlogs : checksums, formats et incompatibilités silencieuses

La réplication est finalement un contrat : « J’écrirai des événements comme ceci ; vous comprendrez et appliquerez ces événements. »
Les contrats se rompent de trois façons : le primaire change ce qu’il écrit, le réplica change ce qu’il comprend,
ou un intermédiaire édite silencieusement le trafic (rare, mais j’ai vu des proxies « utiles » faire des choses stupides).

Checksums du binlog : petit réglage, grosse panne

Les checksums de binlog protègent contre la corruption, mais la compatibilité dépend que les deux côtés soient d’accord.
Un mode de défaillance classique est de mettre à jour un côté ou de changer un défaut, puis de voir la réplication s’arrêter avec une erreur de parsing.

Conseil pratique : standardisez les settings de checksum de binlog à l’échelle du parc et intégrez-les dans vos audits de base.
Ne laissez pas un serveur être « spécial ».

Format du binlog : la RBR est plus sûre, mais attention à la latence due au volume

Quand vous passez à la RBR, vous corrigez souvent des problèmes de cohérence tout en créant de nouveaux goulets d’étranglement de performance :
les réplicas deviennent limités par l’IO en appliquant de grosses images de lignes, et les relay logs gonflent.

Percona Server et MariaDB gèrent tous deux la RBR, mais leurs mécanismes d’application parallèle et leurs réglages diffèrent.
Le cas limite n’est pas « est-ce que ça réplique » mais « est-ce que ça peut suivre pendant des rafales d’écriture et des changements de schéma. »

Types d’événements et décalage de version

La réplication inter-version (même au sein d’un même flavor) est là où apparaissent des types d’événements étranges.
Un primaire plus récent peut émettre des événements qu’un réplica légèrement plus ancien ne peut pas parser. Parfois vous obtenez une erreur claire.
Parfois ça ressemble à de la latence, puis un arrêt, puis un opérateur confus relance START SLAVE comme stratégie d’adaptation.

Semi-sync et scénarios « perte de données quand même »

La réplication semi-synchrone réduit la fenêtre de perte en attendant qu’au moins un réplica accuse réception de la transaction avant que le primaire ne réponde OK. Réception, pas application. Si le réplica accusant réception a l’événement dans un relay log mais ne l’a pas committé, une bascule peut encore le perdre — ou pire, bifurquer l’historique selon votre procédure.

C’est là que beaucoup de dirigeants entendent « semi-sync » et pensent « pas de perte de données ». Cette croyance a causé plus d’une réunion gênante avec les finances.

Ce que le semi-sync vous apporte réellement

  • Moins de transactions reconnues existent uniquement sur le primaire.
  • Meilleures chances qu’un réplica promu contienne les dernières écritures committées.
  • Plus de latence et plus de sensibilité aux jitter réseau/répliques.

Séquence d’échec qui perd encore des données

Le primaire commit, envoie au réplica, le réplica ACK la réception, le primaire ACK le client. Puis le réplica plante avant l’application,
ou le relay log est corrompu, ou la bascule promeut un autre réplica qui ne l’a jamais reçu. Félicitations : semi-sync, résultats asynchrones.

Position de l’opérateur

Utilisez le semi-sync si votre budget de latence le permet et si vous comprenez ses garanties. Associez-le à des règles de promotion :
ne promouvez que des réplicas confirmés à jour et suffisamment durables pour votre RPO.
Sinon, vous payez juste un loyer de latence pour l’ambiance.

Réplication parallèle : plus rapide… jusqu’à ce que ça ne le soit plus

La réplication parallèle est une fonctionnalité de performance qui devient un débat de cohérence dès que vous avez des transactions cross-schema,
des lignes chaudes, ou une charge « essentiellement parallèle sauf pour les morceaux qui comptent ».

Le cas limite : vous « optimisez la latence » en augmentant les threads workers, mais le réplica devient CPU-limité, ou limité par des mutex,
ou commence à thrash le buffer pool, et l’application ralentit. Ou il suit — jusque l’arrivée d’un DDL où tout s’accumule derrière comme des voitures derrière un défilé.

Percona Server (aligné avec MySQL) utilise typiquement des mécanismes d’application parallèle de style MySQL et une instrumentation que beaucoup d’outils attendent.
MariaDB a son propre système de réplication parallèle et ses variables, et les schémas de tuning ne sont pas toujours transférables.
Vous devez mesurer, pas deviner.

Filtres et changements de schéma : désastres lents

Les filtres de réplication (replicate-do-db, replicate-ignore-db, jokers, filtres de table)
semblent un moyen propre de « garder seulement ce dont vous avez besoin ». En réalité, ils sont une dette à long terme à moins d’être traités
comme du code : revus, testés et revalidés après chaque changement de schéma.

Filtres + format binlog mixte + requêtes inter-base peuvent amener des réplicas à manquer des changements silencieusement.
« Silencieux » est le pire mot en réplication.

Réplication de DDL : où « ça marchait en staging » meurt

Le DDL est brutal pour les réplicas. Il est souvent mono-thread, bloque, et peut créer d’énormes événements de changement de lignes.
Les outils de changement de schéma en ligne réduisent l’impact mais introduisent leurs propres cas limites : triggers, tables fantômes et pics de latence.

Si vous devez choisir une philosophie : priorisez la cohérence et la récupération prévisible plutôt que le débit de pointe.
Vous pouvez acheter du matériel pour le débit. Vous ne pouvez pas racheter des données cohérentes après une mauvaise bascule.

Tâches pratiques : commandes, sorties et décisions

Ci-dessous des tâches opérationnelles réelles. Chaque section inclut une commande, une sortie d’exemple, ce que cela signifie, et la décision à prendre.
Utilisez-les comme réflexes pendant les incidents et lors des audits du mardi ennuyeux. Le mardi ennuyeux, c’est là que vous gagnez.

Tâche 1 : Identifier la distribution et la version du serveur (arrêtez de deviner)

cr0x@server:~$ mysql -e "SELECT @@version, @@version_comment\G"
*************************** 1. row ***************************
@@version: 10.11.6-MariaDB-1:10.11.6+maria~ubu2204
@@version_comment: MariaDB Server

Ce que cela signifie : Vous êtes sur MariaDB 10.11.x. Si votre runbook suppose les variables GTID MySQL/Percona, il est déjà faux.

Décision : Utilisez la syntaxe/variables de réplication MariaDB et assurez-vous que vos outils de bascule supportent les GTID MariaDB (si activés).

Tâche 2 : Vérifier le binlog du primaire et la posture de durabilité

cr0x@server:~$ mysql -e "SHOW VARIABLES WHERE Variable_name IN ('log_bin','binlog_format','sync_binlog','innodb_flush_log_at_trx_commit')"
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| binlog_format                  | ROW   |
| innodb_flush_log_at_trx_commit | 1     |
| log_bin                        | ON    |
| sync_binlog                    | 1     |
+--------------------------------+-------+

Ce que cela signifie : Les binlogs sont activés, la réplication est en mode ROW, et la durabilité est stricte (coût IO plus élevé, meilleure sécurité au crash).

Décision : Si la latence est acceptable, conservez cela. Si vous êtes tenté de l’assouplir, ne le faites qu’avec un accord explicite sur le RPO/RTO et un plan de récupération testé.

Tâche 3 : Confirmer le statut du réplica (la base ennuyeuse)

cr0x@server:~$ mysql -e "SHOW SLAVE STATUS\G" | egrep "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_SQL_Error|Last_IO_Error"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
Last_IO_Error:
Last_SQL_Error:

Ce que cela signifie : Les threads tournent et le réplica n’indique pas de latence. C’est nécessaire, pas suffisant, pour la cohérence.

Décision : Si vous diagnostiquez des « résultats incorrects », vous devez aller au-delà et vérifier les GTID/positions/checksums exécutés.

Tâche 4 : Mesurer correctement la latence de réplication (ne vénérez pas Seconds_Behind_Master)

cr0x@server:~$ pt-heartbeat --check --database=percona --table=heartbeat --host=127.0.0.1 --user=monitor --password='***'
0.183

Ce que cela signifie : La latence observée réelle est d’environ 183ms. C’est souvent plus fiable que Seconds_Behind_Master sous charge ou en apply parallèle.

Décision : Utilisez la latence basée sur heartbeat pour l’alerte et le gating des bascules. Traitez Seconds_Behind_Master comme un indice, pas une oraclisation.

Tâche 5 : Valider la compatibilité des checksums de binlog

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'binlog_checksum';"
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| binlog_checksum | CRC32 |
+-----------------+-------+

Ce que cela signifie : Le primaire émet des checksums CRC32. Un réplica qui attend NONE (ou qui n’a pas le support) peut échouer à lire les événements.

Décision : Assurez-vous que les réplicas sont configurés pour comprendre le même mode de checksum ; standardisez-le sur tout le parc avant les montées de version.

Tâche 6 : Repérer la pression des relay logs et le risque disque

cr0x@server:~$ du -sh /var/lib/mysql/*relay* 2>/dev/null | tail -n 3
18G	/var/lib/mysql/relay-bin.000112
18G	/var/lib/mysql/relay-bin.000113
36G	/var/lib/mysql/relay-log.info

Ce que cela signifie : Les relay logs sont énormes. Cela corrèle souvent avec de la latence ou un SQL thread lent à appliquer.

Décision : Avant de redémarrer quoi que ce soit, trouvez le goulet d’application (IO, verrous, DDL). Si le disque est presque plein, priorisez l’arrêt de l’hémorragie : limitez les écritures, ajoutez de l’espace ou provisionnez un nouveau réplica.

Tâche 7 : Trouver les coordonnées de réplication actuelles (la position binlog compte toujours)

cr0x@server:~$ mysql -e "SHOW MASTER STATUS\G"
*************************** 1. row ***************************
File: mysql-bin.001874
Position: 918273645
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:

Ce que cela signifie : Vous avez un fichier/position de binlog. Même avec GTID, c’est utile pour des comparaisons point-in-time et le debugging.

Décision : Enregistrez ceci avant les opérations risquées (bascule, redémarrage, changement de config). C’est votre fil d’Ariane quand vous êtes fatigué.

Tâche 8 : Vérifier si le réplica applique en parallèle (et si ça aide)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'slave_parallel_workers';"
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| slave_parallel_workers | 16    |
+------------------------+-------+

Ce que cela signifie : Le réplica est configuré pour 16 workers parallèles (nom de variable MySQL/Percona ; MariaDB utilise d’autres réglages selon la version).

Décision : Si la latence empire après avoir augmenté les workers, revenez en arrière et profilez : saturation CPU, attentes sur mutex, stalls IO et sérialisation DDL sont des coupables courants.

Tâche 9 : Inspecter l’état des workers de réplication pour identifier le blocage

cr0x@server:~$ mysql -e "SELECT THREAD_ID,PROCESSLIST_STATE,PROCESSLIST_INFO FROM performance_schema.threads t JOIN performance_schema.processlist p ON t.PROCESSLIST_ID=p.ID WHERE p.COMMAND IN ('Connect','Binlog Dump GTID','Binlog Dump','Query') LIMIT 5\G"
*************************** 1. row ***************************
THREAD_ID: 82
PROCESSLIST_STATE: Waiting for master to send event
PROCESSLIST_INFO: NULL
*************************** 2. row ***************************
THREAD_ID: 109
PROCESSLIST_STATE: Waiting for handler commit
PROCESSLIST_INFO: INSERT INTO orders ...

Ce que cela signifie : Le thread IO est inactif (bon signe), mais un worker est bloqué en attente de commit — souvent IO, fsync ou contention.

Décision : Examinez la latence disque et la pression de flush InnoDB. Ne multipliez pas la contention en augmentant simplement le nombre de workers.

Tâche 10 : Vérifier la latence disque (la latence de réplication est souvent liée au stockage)

cr0x@server:~$ iostat -x 1 3
Device            r/s     w/s   r_await   w_await  aqu-sz  %util
nvme0n1         120.0   980.0     1.10    18.70    7.42   92.0

Ce que cela signifie : Les écritures attendent ~19ms en moyenne et le device est ~92% utilisé. Le SQL thread du réplica est probablement limité par l’IO.

Décision : Réduisez l’amplification d’écriture (tuning buffer pool, taille des logs), déplacez les réplicas vers un stockage plus rapide, ou réduisez temporairement le taux d’écriture entrant. Le tuning CPU ne réparera pas un disque saturé.

Tâche 11 : Confirmer les réglages de récupération crash-safe des relay logs

cr0x@server:~$ mysql -e "SHOW VARIABLES WHERE Variable_name IN ('relay_log_recovery','master_info_repository','relay_log_info_repository');"
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| master_info_repository  | TABLE |
| relay_log_info_repository | TABLE |
| relay_log_recovery      | ON    |
+-------------------------+-------+

Ce que cela signifie : Les métadonnées sont stockées en TABLE et la récupération des relay logs est activée — bon pour la sécurité au crash.

Décision : Si ces valeurs sont FILE/OFF dans votre parc, planifiez un changement contrôlé. Le lendemain d’un reboot non propre n’est pas le moment de découvrir que vous ne pouvez pas récupérer proprement les relay logs.

Tâche 12 : Détecter une rupture de réplication due à une clé dupliquée (classique après une mauvaise promotion)

cr0x@server:~$ mysql -e "SHOW SLAVE STATUS\G" | egrep "Last_SQL_Errno|Last_SQL_Error|Slave_SQL_Running"
Slave_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Error 'Duplicate entry '1842' for key 'PRIMARY'' on query. Default database: 'app'. Query: 'INSERT INTO users(id,...) VALUES(...)'

Ce que cela signifie : Le réplica a appliqué quelque chose hors ordre ou a divergé. Souvent causé par écrire sur un réplica, ou par une bascule qui a promu un réplica manquant des transactions.

Décision : Stoppez. Ne sautez pas les erreurs à l’aveugle. Identifiez l’étendue de la divergence : comparez les ensembles GTID/positions, lancez des vérifications de consistance, et envisagez de reconstruire le réplica à partir d’un snapshot connu bon.

Tâche 13 : Vérifier qu’on n’écrit personne sur les réplicas (ça arrive)

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'read_only'; SHOW VARIABLES LIKE 'super_read_only';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | OFF   |
+---------------+-------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| super_read_only | OFF   |
+-----------------+-------+

Ce que cela signifie : Le réplica est modifiable. C’est acceptable seulement si vous l’utilisez intentionnellement (rare) et comprenez les conséquences.

Décision : Activez read_only et super_read_only pour les réplicas par politique. Si une appli a besoin d’écrire, elle nécessite une architecture différente, pas une exception furtive.

Tâche 14 : Vérifier l’existence de filtres de réplication qui suppriment silencieusement des données

cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'replicate%';" | egrep -v "replicate_(same_server_id|rewrite_db)"
replicate_do_db	app
replicate_ignore_db	mysql
replicate_wild_ignore_table	app.tmp_%

Ce que cela signifie : Vous filtrez la réplication. Cela peut être valide, mais c’est dangereux avec des requêtes inter-base et du DDL.

Décision : Auditez chaque filtre par rapport aux schémas de charge réels. Si vous ne pouvez pas prouver que c’est sûr, retirez-le et isolez les données autrement (instances séparées, clusters séparés).

Plaquette de diagnostic rapide

Quand la réplication est « lente » ou « cassée », votre travail n’est pas de fixer les yeux sur une métrique. Votre travail est de trouver rapidement la ressource limitante
et le mode d’échec, puis de choisir l’intervention la moins risquée.

Premier point : la réplication est-elle arrêtée ou menteuse ?

  • Vérifiez SHOW SLAVE STATUS\G (ou équivalent) pour IO/SQL running et erreurs.
  • Si les deux threads tournent, n’assumez pas la cohérence. Validez la latence via heartbeat et des contrôles d’échantillons de données.

Deuxième point : quel est le goulot réseau, disque ou verrous ?

  • Réseau/thread IO : thread IO non running, en « connecting » ou « reconnecting ».
  • Disque/commit : thread SQL en attente de commit, await iostat élevé, %util saturé.
  • Verrous/DDL : thread SQL bloqué sur des verrous de métadonnées ; un DDL long bloque l’application.

Troisième point : est-ce un décalage de format/compatibilité ?

  • Vérifiez le format de binlog et les variables checksum sur les deux côtés.
  • Vérifiez le décalage de version, les différences de plugins et la compatibilité du mode GTID.

Quatrième point : décider le niveau d’intervention

  • Faible risque : limiter les écritures, ajouter de l’espace disque, réparer le réseau, améliorer l’IO.
  • Risque moyen : ajuster les workers parallèles ou appliquer des réglages en mesurant.
  • Risque élevé : sauter des erreurs, réinitialiser le slave, reconstruire des réplicas, promouvoir un autre nœud. Le risque élevé requiert un plan écrit et un rollback.

Erreurs courantes : symptômes → cause racine → correctif

1) « Seconds_Behind_Master est 0, mais les données sont erronées »

Symptôme : Les lectures applicatives sur les réplicas montrent des lignes manquantes ou des agrégats obsolètes ; le statut de réplication semble « correct ».

Cause racine : Dérive due à la réplication par instruction, fonctions non déterministes, ou filtres qui suppriment des événements ; parfois des écritures ont fui vers les réplicas.

Correctif : Passez à la réplication basée sur les lignes quand c’est possible ; retirez les filtres risqués ; appliquez super_read_only ; lancez des vérifications de consistance et reconstruisez les réplicas divergents.

2) « La réplication a cassé après une mise à jour mineure »

Symptôme : Le thread IO s’arrête avec des erreurs de parsing d’événements ; ou le thread SQL a des erreurs sur des types d’événements inconnus.

Cause racine : Décalage de version émettant des fonctionnalités de binlog que le réplica ne peut pas parser ; mismatch de checksum ; incompatibilité de mode GTID entre flavors.

Correctif : Alignez les versions dans des plages supportées ; standardisez binlog_checksum ; validez la compatibilité GTID dans un labo et sur un réplica canari avant le déploiement.

3) « La latence croît pendant les rafales d’écriture, sans récupération »

Symptôme : Les relay logs gonflent ; le thread SQL montre « Waiting for handler commit » ; l’IO chauffe.

Cause racine : Le disque du réplica est le goulot (pression de fsync, stockage saturé), pas le CPU. La RBR augmente l’amplification d’écriture.

Correctif : Déplacez les réplicas vers un stockage plus rapide ; tunez la configuration des logs InnoDB ; assurez-vous que le buffer pool est dimensionné ; envisagez de retarder les requêtes analytiques lourdes sur les réplicas.

4) « Nous avons fait une bascule avec GTID et avons tout de même perdu des transactions »

Symptôme : Des utilisateurs signalent des écritures récentes manquantes ; le primaire est tombé ; un nouveau primaire a été promu proprement.

Cause racine : Fenêtre de réplication asynchrone, ack semi-sync portant sur la réception seulement, ou réplica promu pas entièrement rattrapé/appliqué.

Correctif : Gatez la promotion sur un état vérifié à jour ; si vous utilisez semi-sync, assurez-vous que votre bascule promeut le réplica qui a accusé réception quand c’est possible ; resserrez les paramètres de durabilité si nécessaire.

5) « La réplication parallèle a empiré les choses »

Symptôme : Augmenter les workers augmente la latence et le CPU ; le débit de réplication diminue.

Cause racine : Contention, lignes chaudes, sérialisation des commits, churn du buffer pool, ou DDL bloquant l’application.

Correctif : Réduisez les workers ; profilez les attentes ; traitez le DDL comme un événement planifié ; shardez les hotspots d’écriture si nécessaire ; validez les réglages sous charge réaliste.

6) « Le réplica plante et revient cassé »

Symptôme : Après un reboot, le réplica ne peut pas reprendre ; les relay logs sont incohérents ; requiert un repositionnement manuel.

Cause racine : Dépôts de métadonnées non crash-safe ; récupération des relay logs désactivée ; problèmes de filesystem/disque.

Correctif : Activez des dépôts crash-safe (TABLE) et la récupération des relay logs ; validez la santé du filesystem ; reconstruisez le réplica si l’état est suspect.

Trois mini-récits d’entreprise depuis les tranchées de la réplication

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise SaaS de taille moyenne exploitait un parc mixte : MariaDB pour une ligne de produits legacy, Percona Server pour des services plus récents.
Une nouvelle équipe hérita d’une topologie de réplication cross-datacenter et standardisa le runbook de bascule autour de « GTID auto-positioning ».
Ils supposèrent que GTID = GTID. Même acronyme, même sécurité, même résultat.

Lors d’une panne primaire, ils promurent un réplica en suivant les étapes qui fonctionnaient parfaitement sur Percona.
La réplication reprit, l’appli se rétablit, les dashboards passèrent au vert. Tout le monde souffla.
Puis les escalades du support commencèrent : des changements d’abonnement récents manquaient, mais seulement pour certains clients.

Le postmortem fut instructif. L’état GTID de MariaDB n’était pas interprété comme l’attendait l’outil de bascule.
L’outil choisit un candidat de promotion qui semblait à jour selon une métrique mais n’était pas le nœud « le plus avancé » selon la sémantique de domaine GTID de MariaDB.

Ils auraient pu le détecter avec un pré-flight : valider les ensembles de transactions exécutées en utilisant les variables serveur correctes,
et tester la bascule cross-flavor dans un labo avec de vrais binlogs. Au lieu de cela, ils ont appris en production, la salle de classe la plus chère.

La correction n’était pas héroïque. Ils séparèrent les playbooks opérationnels par flavor, imposèrent une surveillance spécifique par flavor, et cessèrent de prétendre
qu’un script d’automatisation universel pourrait piloter les deux sans logique de compatibilité explicite.

Mini-récit 2 : L’optimisation qui a échoué

Une société e-commerce connaissait un problème courant : les réplicas prenaient du retard pendant les promotions.
Quelqu’un proposa une simple astuce : assouplir la durabilité pour accélérer les commits et laisser les réplicas rattraper leur retard.
Ils baissèrent sync_binlog et modifièrent les réglages de flush de logs sur les réplicas aussi, parce que « les réplicas n’ont pas besoin d’être aussi durables ».

La latence s’améliora pendant un temps. L’équipe célébra avec la satisfaction discrète d’avoir rogné des millisecondes sur un graphe.
Puis un hôte réplica redémarra pendant une mise à jour du kernel, et le réplica revint avec des relay logs non fiables.
La récupération nécessita une intervention manuelle, puis une reconstruction.

Pendant la fenêtre de reconstruction, les réplicas restants prirent plus de trafic en lecture et plus de charge de réplication.
La latence revint, maintenant avec moins de filets de sécurité. Ils avaient optimisé l’état stable tout en augmentant le rayon d’impact lors d’événements routiniers.

La leçon n’était pas « ne jamais tuner ». C’était « tunez avec un modèle d’échec ». Si vous baissez la durabilité, vous devez modéliser ce qui arrive sur crash,
coupure de courant et bascule. Si votre modèle est « probablement OK », félicitations : vous avez adopté l’ingénierie populaire.

Ils revinrent sur les réglages risqués, déplacèrent les réplicas vers des disques plus rapides, et cessèrent d’utiliser des réglages de durabilité comme pansement de performance.
Le stockage était le goulot depuis le début — comme c’est souvent le cas.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une plateforme de paiements exploitait Percona Server avec une discipline opérationnelle stricte.
Ils avaient un rituel hebdomadaire : valider le rattrapage des réplicas, exécuter une passe de checksum de consistance sur un sous-ensemble de tables en rotation,
répéter une promotion contrôlée en staging qui reflétait la configuration de production, et enregistrer les commandes exactes.
Personne n’en parlait. Ce n’était pas de « l’innovation ». C’était de l’entretien.

Un après-midi, un nœud primaire commença à émettre des stalls fsync intermittents. La latence de réplication monta.
L’astreinte sortit la plaquette de diagnostic rapide et confirma que le problème venait de la latence de stockage, pas des verrous SQL.
Ils freinaient un batch writer, drainaient le trafic, et se préparèrent à basculer.

Le facteur décisif fut la porte de promotion : ils ne promurent que le réplica vérifié à jour via heartbeat et état de transaction,
et ils disposaient d’une checklist pré-approuvée pour s’assurer que les flags read-only et les réglages binlog étaient corrects sur le nouveau primaire.

La bascule fut peu spectaculaire. Elle fut aussi propre. Aucune transaction manquante, aucune dérive, aucune chasse aux différences de table.
Leur plus grand stress fut d’attendre les TTL DNS, ce qui est le bon type de stress.

La fiabilité est surtout un tas d’habitudes ennuyeuses. L’ennui est sous-estimé.

Une citation à garder au mur

Idée paraphrasée (attribuée à Richard Cook) : « Le succès vient de la capacité à s’adapter aux surprises ; l’échec provient du même système qui fonctionne sous contrainte. »

Listes de contrôle / plan pas à pas

Checklist A : Concevoir la réplication pour réduire l’impact des cas limites

  1. Choisissez une stratégie de flavor : GTID uniquement MariaDB, GTID uniquement MySQL/Percona, ou pas de GTID avec positions explicites. Évitez le « on verra plus tard ».
  2. Standardisez le format de binlog (préférez ROW) et le checksum de binlog sur tout le parc.
  3. Décidez de votre posture de durabilité et documentez le RPO. Alignez sync_binlog et innodb_flush_log_at_trx_commit avec cette décision.
  4. Activez les métadonnées de réplication crash-safe (master_info_repository=TABLE, relay_log_info_repository=TABLE, relay_log_recovery=ON) là où c’est supporté et testé.
  5. Imposez le read-only sur les réplicas (read_only et super_read_only).
  6. Choisissez une méthode de mesure de latence qui reflète la réalité (basée sur heartbeat).
  7. Décidez de la manière de déployer les DDL (fenêtres planifiées, outils de changement de schéma en ligne, ou migrations au niveau applicatif).

Checklist B : Procédure de promotion / bascule (version sûre pour les humains)

  1. Gelez les écritures si possible (mode maintenance applicatif ou throttling des writers). Si vous ne pouvez pas, au moins connaissez votre fenêtre de perte attendue.
  2. Choisissez le candidat de promotion sur la base d’un rattrapage vérifié : latence heartbeat proche de zéro, threads de réplication sains, pas d’erreurs SQL.
  3. Vérifiez l’état des transactions en utilisant les variables GTID/position correctes pour le flavor. Ne « traduisez pas ça dans votre tête ».
  4. Confirmez que le candidat n’est pas modifiable avant la promotion sauf si nécessaire. Ensuite, passez-le en écriture intentionnellement.
  5. Promouvez : arrêtez proprement la réplication, réinitialisez la config de réplication si besoin, assurez-vous que le binlog est activé sur le nouveau primaire.
  6. Pointez les autres réplicas vers le nouveau primaire en utilisant la méthode d’auto-position correcte pour votre flavor.
  7. Validez la cohérence avec des vérifications ponctuelles et une petite sonde de consistance. Puis dégelezz les écritures.

Checklist C : Quand vous devez reconstruire un réplica (et vous le ferez)

  1. Arrêtez la réplication et enregistrez la sortie de statut courante pour la timeline de l’incident.
  2. Choisissez une source de snapshot propre (préférez un réplica vérifié correct, pas « le moins cassé »).
  3. Restaurez les données, puis définissez soigneusement les coordonnées/état GTID de réplication.
  4. Démarrez la réplication et surveillez les erreurs SQL précoces (duplications, tables manquantes, problèmes de checksum).
  5. Exécutez une vérification de consistance ciblée sur les tables à haute valeur avant de le remettre en service.

Blague #2

Les filtres de réplication sont comme la politique de bureau : ils semblent utiles jusqu’à ce que vous réalisiez qu’ils ont silencieusement supprimé des informations importantes.

FAQ

1) MariaDB peut-elle répliquer depuis Percona Server (ou vice versa) en toute sécurité ?

Parfois, dans certaines combinaisons de versions et configurations, mais « en toute sécurité » requiert de tester votre format de binlog exact,
le mode checksum et la stratégie GTID. Le GTID cross-flavor est l’endroit où les équipes se font mal. Si vous devez mélanger, faites-le avec un labo qui rejoue de vrais binlogs.

2) Dois-je utiliser GTID partout ?

Oui si vos outils et procédures d’équipe sont GTID-natifs pour le flavor choisi. Non si vous mélangez les flavors sans plan de compatibilité.
Le GTID améliore l’ergonomie de la bascule, mais n’élimine pas les fenêtres de perte de données ni les mauvaises décisions de promotion.

3) La réplication semi-sync est-elle « sans perte de données » ?

Non. Elle réduit la fenêtre en garantissant qu’au moins un réplica a reçu l’événement avant l’ACK client, mais la réception n’est pas l’application.
Vous pouvez toujours perdre des transactions selon le timing du crash et le choix de bascule.

4) Pourquoi la latence de réplication pique-t-elle pendant un DDL même avec réplication parallèle ?

Le DDL sérialise souvent l’exécution et peut prendre des verrous de métadonnées qui bloquent l’application. Les workers parallèles ne peuvent pas dépasser un événement bloquant.
Traitez les gros changements de schéma comme des événements planifiés et testez-les sous charge similaire à la production.

5) Quelle est la métrique de latence la plus fiable pour les décisions de bascule ?

Les mesures basées sur heartbeat (par ex., un timestamp écrit sur le primaire et lu sur les réplicas) sont généralement plus véridiques que
Seconds_Behind_Master, surtout en apply parallèle ou quand le thread SQL est bloqué de manière intermittente.

6) Si la réplication est cassée, dois-je sauter la transaction fautive ?

Seulement en dernier recours, et seulement quand vous comprenez pleinement ce que vous sautez et comment réparer la cohérence.
Sauter est un instrument de dette opérationnelle avec intérêts composés.

7) Pourquoi les réplicas divergent même quand la réplication dit qu’elle tourne ?

Causes courantes : réplication par instruction avec non-déterminisme, écritures ayant fuité vers les réplicas, filtres de réplication, et
comportement applicatif dépendant de paramètres de session non répliqués comme attendu. La divergence est généralement un échec de politique, pas un mystère.

8) Quelle est la façon la plus rapide de dire si le goulot est le stockage ?

Si l’état des threads SQL montre des attentes de commit et que iostat affiche un await élevé/%util, c’est le stockage.
Réparez le stockage ou réduisez la pression d’écriture. N’« optimisez » pas les threads de réplication contre un mur disque.

9) Les fonctionnalités spécifiques à Percona changent-elles le comportement de réplication ?

Percona Server est typiquement proche de la sémantique de réplication d’Oracle MySQL, mais l’instrumentation et les knobs supplémentaires peuvent changer le comportement de performance.
Traitez-le comme un flavor à part entière : maintenez des configurations cohérentes et testez les montées de version, surtout autour de la réplication parallèle et de la durabilité.

10) Quel est le format de binlog le plus sûr aujourd’hui ?

La réplication basée sur les lignes est le choix usuel pour la cohérence. Le coût est un volume de binlog plus élevé et plus d’IO sur les réplicas.
Si vous choisissez la réplication par instruction, vous avez besoin de contrôles stricts sur les patterns SQL et d’une tolérance élevée à la « dérive surprise ».

Prochaines étapes à réaliser cette semaine

Si vous voulez moins d’incidents de réplication, ne commencez pas par débattre des marques. Commencez par lever l’ambiguïté.

  1. Inventoriez les flavors et versions dans votre topologie. Notez-les. Arrêtez de supposer « c’est tout MySQL ».
  2. Standardisez le format de binlog et le checksum et vérifiez via les commandes sur chaque nœud.
  3. Décidez et documentez votre RPO, puis alignez les réglages de durabilité avec celui-ci. Si le business ne décide pas, choisissez des réglages conservateurs et faites-lui signer la facture latence.
  4. Implémentez une mesure de latence basée sur heartbeat et utilisez-la dans les alertes et les gates de bascule.
  5. Exécutez un exercice de bascule contrôlée en staging avec des settings proches de la production. Chronométrez-le. Corrigez les étapes qui requièrent du savoir tribal.
  6. Choisissez une pratique de « correction ennuyeuse » (imposition du read-only, métadonnées de réplication crash-safe, checks hebdomadaires de consistance) et faites-en une politique.

Les cas limites de réplication ne se soucient pas de la distribution que vous avez installée. Ils se soucient de ce que vous avez supposé, de ce que vous avez testé,
et de ce que vous êtes prêt à garder cohérent quand personne ne regarde.

← Précédent
Ubuntu 24.04 : Docker + UFW = ports ouverts à la surprise — colmatez la brèche sans casser les conteneurs
Suivant →
ZFS logbias : latence vs débit — choisissez ce dont vous avez vraiment besoin

Laisser un commentaire