MySQL vs Percona Server : stabilité de la réplication — pourquoi les équipes d’exploitation migrent

Cet article vous a aidé ?

Les pannes de réplication n’annoncent que rarement leur arrivée poliment. Elles se présentent à 03:17 via une alerte, un pic de latence, et une équipe produit qui demande pourquoi « la base de données est lente »
comme si c’était un seul bouton que vous avez oublié d’actionner.

L’écosystème MySQL vous offre des options : Oracle MySQL, Percona Server for MySQL, MariaDB, et une longue traîne d’outillage. Cet article porte sur une tranche étroite mais décisive :
la stabilité de la réplication en production — ce qui casse, comment le diagnostiquer vite, et pourquoi les équipes d’exploitation expérimentées finissent souvent par adopter Percona Server quand elles en ont assez des surprises.

Ce que les équipes d’exploitation entendent par « stabilité de la réplication »

La « stabilité de la réplication » n’est pas un chiffre de benchmark. C’est l’absence de drame. En termes de production, une réplication stable signifie :

  • Latence prévisible : vous pouvez la prévoir sous charge, et elle revient à la normale après des pics.
  • Comportement de basculement sûr : promouvoir une réplique ne doit pas perdre silencieusement des écritures reconnues ni créer un split-brain.
  • Clarté rapide de la cause racine : quand ça déraille, vous pouvez déterminer si le goulot est la source, le réseau, les relay logs, l’appliqueur, ou le stockage.
  • Marge opérationnelle : vous pouvez exécuter des changements de schéma, des sauvegardes et de la maintenance sans transformer la réplication en scène de crime.
  • Garanties de cohérence explicables : aux ingénieurs et aux auditeurs, sans danse interprétative.

La stabilité n’est pas seulement « la réplication tourne ». C’est « la réplication est banale ». La banalité est la fonctionnalité que vous voulez quand le business est éveillé.

MySQL vs Percona Server en pratique (pas le marketing)

Compatibilité : pourquoi Percona est même dans la conversation

Percona Server for MySQL est un remplaçant « drop-in » au sens pratique : même protocole, même couche SQL, même modèle de réplication, et généralement la même surface de configuration.
C’est important parce que « changer » en exploitation est habituellement un échange de paquets contrôlé, pas une réécriture.

La raison pour laquelle les équipes envisagent Percona est simple : il tend à être livré avec plus d’instrumentation opérationnelle et des paramètres/fonctionnalités orientés performance.
On change non pas par goût du changement, mais parce qu’on aime dormir.

La stabilité de la réplication est souvent un problème d’observabilité déguisé en problème de base de données

Un MySQL « vanilla » peut répliquer de façon fiable pendant des années. La raison la plus courante pour laquelle la réplication paraît « instable » est l’absence
des signaux qui vous auraient dit pourquoi elle prend du retard avant que cela ne devienne un incident visible par les clients.

Le différenciateur de Percona, opérationnellement, n’est souvent pas un algorithme de réplication magique. C’est :

  • Des compteurs internes et des diagnostics plus exposés dans un package prêt pour la production.
  • Des fonctionnalités et correctifs historiquement ciblés sur la performance sous concurrence (là où naît le lag de réplication).
  • Une première classe d’alignement avec un ensemble d’outils : Percona Toolkit (pt-heartbeat, pt-table-checksum) et Percona XtraBackup.

Où la stabilité se gagne réellement : les trois goulots

La réplication se décompose en trois lieux :

  1. Chemin de commit sur la source : binlog group commit, comportement fsync, paramètres de durabilité, rafales d’écritures.
  2. Transport & relay : gigue réseau, perte de paquets, I/O des relay logs, saturation disque sur les répliques.
  3. Chemin d’application sur la réplique : fil SQL (ou workers applier), I/O aléatoire, contention sur les verrous, suivi des dépendances, churn DDL.

Percona Server tend à vous donner plus de visibilité et des leviers de réglage autour de ces points d’étranglement. Il ne vous dispense pas de les comprendre.

Mon avis opérationnel et tranché

Si vous avez un primaire et une réplique et que vous traitez la réplication comme une pensée secondaire, MySQL fera l’affaire — jusqu’à ce qu’il ne le fasse plus. Si la réplication fait partie de votre plan de disponibilité,
de votre pipeline d’analytics, ou de votre santé mentale en astreinte, vous avez besoin de diagnostics plus solides et de pratiques plus sûres. C’est là que Percona Server gagne souvent sa place.

Ne migrez pas pour des impressions. Migrez parce que vous pouvez pointer une lacune de stabilité ou d’opérabilité que vous devez combler.

Faits intéressants et contexte historique (court et utile)

  • La réplication a commencé en mode statement-based, ce qui était rapide mais fragile ; la réplication row-based est devenue le choix « je veux la justesse » pour de nombreuses charges.
  • MySQL 5.6 a rendu les GTID grand public pour les utilisateurs MySQL, transformant le basculement de « calcul de position » en « identité de transaction », avec de nouvelles façons de se blesser.
  • La réplication multi-thread est arrivée pour traiter une douleur centrale : un seul fil SQL appliquant les changements ne peut pas suivre les débits d’écriture modernes.
  • La réplication semisynchrone a été introduite pour réduire la perte de données au basculement, mais son comportement en cas de latence peut surprendre les équipes qui la considèrent comme un quorum synchrone.
  • La sécurité face aux crashs s’est améliorée avec le temps ; les anciennes configurations pouvaient perdre l’état des relay logs et nécessiter des manipulations manuelles après un crash.
  • Percona Server a historiquement livré plus d’instrumentation (compteurs d’état, améliorations des requêtes lentes, fonctionnalités de performance) destinées aux opérateurs, pas seulement aux développeurs.
  • Percona Toolkit est devenu le « couteau suisse DBA » dans de nombreux environnements : détection de dérive par checksum, changement de schéma en ligne, mesure du lag par heartbeat.
  • XtraBackup a changé les opérations sur les répliques en rendant les sauvegardes physiques à chaud pratiques pour de grands jeux de données InnoDB, réduisant le temps de reconstruction et la dette de réplication.

Modes de défaillance de la réplication qui arrivent vraiment

1) « Latence » qui est en réalité un blocage de commit sur la source

Les équipes regardent les secondes-derrière-la-source de la réplique et supposent que la réplique est lente. Pendant ce temps, la source est bloquée sur fsync, binlog group commit,
ou des paramètres de durabilité qui se battent avec le stockage sous-jacent. La réplique n’est que le messager.

2) Saturation I/O des relay logs sur les répliques

Les répliques écrivent des relay logs, les flushent, puis appliquent. Si les écritures de relay logs entrent en compétition avec les flushs InnoDB ou les lectures de sauvegarde sur le même volume,
la réplique peut « prendre du retard » même si la capacité d’application est correcte. Vous verrez des rafales : rattrapage, retard, rattrapage.

3) Goulots des threads d’application : dépendances et lignes « chaudes »

La réplication multi-thread aide, mais seulement quand les transactions peuvent être parallélisées. Si votre charge martèle les mêmes lignes, les mêmes pages d’index,
ou une seule table, l’appliqueur est effectivement sérialisé. Cela ressemble souvent à « la réplication n’utilise pas le CPU », car elle attend des verrous ou de l’I/O.

4) DDL et verrous de métadonnées

Un innocent ALTER TABLE sur la source peut bloquer les écritures, bloquer la rotation des binlogs, ou faire en sorte que la réplique cesse d’appliquer jusqu’à ce qu’un verrou de métadonnées se libère.
Le « Online DDL » n’est pas une religion ; c’est un ensemble de compromis.

5) Non-déterminisme et pièges du statement-based

Utiliser la réplication statement-based avec des fonctions non déterministes, des triggers dangereux, ou une logique dépendante du temps est un générateur classique de dérive.
Ça peut tourner pendant des mois avant que le cas-limite ne scinde votre jeu de données.

6) GTID et transactions errantes

Les GTID simplifient le basculement, mais punissent le contrôle d’écriture négligent. Si une « réplique » accepte des écritures (même brièvement), vous pouvez créer des jeux GTID qui rendent la réintégration pénible.
Le système vous dit la vérité : la topologie n’est plus linéaire.

Blague #1 : La réplication, c’est comme une relation à distance — si vous cessez de communiquer, quelqu’un finit par inventer sa propre vérité.

Playbook de diagnostic rapide : premier / second / troisième

Quand la réplication est « instable », vous voulez identifier quel sous-système est le facteur limitant. Ne flânez pas. Faites un triage intentionnel.

Premier : la réplication est-elle arrêtée, dérivante ou simplement en retard ?

  • Vérifiez l’état des fils de réplique et les erreurs.
  • Confirmez le mode GTID et les jeux exécutés/purgés si vous utilisez GTID.
  • Mesurez le lag avec un heartbeat, pas seulement avec seconds-behind-source.

Second : la source produit-elle les binlogs de façon fluide ?

  • Recherchez les blocages de commit : fsync, pression sur redo log, paramètres de sync_binlog, latence disque.
  • Vérifiez si le binlog group commit est effectif ou s’il est compromis par des paramètres ou la charge.
  • Confirmez que la source n’est pas bloquée par du DDL, des verrous de métadonnées, ou de longues transactions.

Troisième : la réplique est-elle limitée par l’I/O, le verrouillage ou le parallélisme ?

  • Vérifiez l’I/O des relay logs et la saturation disque sur la réplique.
  • Vérifiez l’utilisation des workers de l’appliqueur et l’état du coordinateur.
  • Inspectez la longueur de la liste d’historique InnoDB et le retard de purge (la pression sur l’undo empire tout).
  • Identifiez les tables « chaudes » et les requêtes appliquées lentement.

Si vous effectuez ces trois passes, vous pouvez généralement nommer le goulot en moins de dix minutes. Le corriger peut prendre plus de temps. Le nommer est la première victoire.

Tâches pratiques : commandes, sorties et décisions (12+)

Les commandes ci-dessous supposent une installation Linux typique avec un serveur compatible MySQL local et une configuration de réplique. Ajustez les identifiants et sockets à votre environnement.
L’important n’est pas l’incantation exacte ; c’est le flux de travail : commande → interpréter la sortie → prendre une décision.

Task 1: Check replication thread health (the fastest “is it dead?” test)

cr0x@server:~$ mysql -uroot -p -e "SHOW REPLICA STATUS\G" | egrep -i "Replica_IO_Running|Replica_SQL_Running|Last_SQL_Error|Last_IO_Error|Seconds_Behind_Source|Retrieved_Gtid_Set|Executed_Gtid_Set"
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 7
Last_IO_Error:
Last_SQL_Error:
Retrieved_Gtid_Set: 3E11FA47-71CA-11EE-9A2D-525400123456:1-981233
Executed_Gtid_Set: 3E11FA47-71CA-11EE-9A2D-525400123456:1-981210

Ce que cela signifie : les deux fils tournent, le lag est faible, et la réplique a récupéré plus de GTID qu’elle n’en a exécuté (normal lorsqu’elle applique).

Décision : considérer comme « en retard », pas « cassée ». Passer à l’identification du goulot (I/O vs application vs blocage source).

Task 2: If replication is stopped, read the exact error (don’t guess)

cr0x@server:~$ mysql -uroot -p -e "SHOW REPLICA STATUS\G" | egrep -i "Replica_SQL_Running|Last_SQL_Errno|Last_SQL_Error|Last_Error_Timestamp"
Replica_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Could not execute Write_rows event on table app.users; Duplicate entry '84219' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.004221, end_log_pos 91827364
Last_Error_Timestamp: 251230 02:14:09

Ce que cela signifie : une clé dupliquée indique une dérive de données ou une écriture errante sur la réplique. Ce n’est pas un moment pour « réessayer plus tard ».

Décision : suspendre le basculement automatique ; lancer une analyse de dérive (checksum) et auditer le contrôle des écritures sur la réplique (read_only/super_read_only).

Task 3: Determine whether lag is in I/O thread or SQL/applier

cr0x@server:~$ mysql -uroot -p -e "SHOW REPLICA STATUS\G" | egrep -i "Seconds_Behind_Source|Replica_IO_State|Slave_SQL_Running_State|Relay_Log_Space|Source_Log_File|Read_Source_Log_Pos|Relay_Source_Log_File|Exec_Source_Log_Pos"
Replica_IO_State: Waiting for source to send event
Slave_SQL_Running_State: Waiting for dependent transaction to commit
Seconds_Behind_Source: 412
Relay_Log_Space: 6832162816
Source_Log_File: mysql-bin.004221
Read_Source_Log_Pos: 98222111
Relay_Source_Log_File: mysql-bin.004219
Exec_Source_Log_Pos: 44112233

Ce que cela signifie : le fil I/O suit (« Waiting for source to send event »), mais le fil SQL est en retard (le fichier d’exécution est plus ancien ; l’espace de relay est énorme).

Décision : se concentrer sur le chemin d’application : parallélisme des workers, lignes chaudes, I/O InnoDB, verrous et longues transactions.

Task 4: Confirm parallel replication configuration and whether it’s doing anything

cr0x@server:~$ mysql -uroot -p -e "SHOW VARIABLES LIKE 'replica_parallel%'; SHOW STATUS LIKE 'Replica_running%';"
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| replica_parallel_workers      | 8     |
| replica_parallel_type         | LOGICAL_CLOCK |
+-------------------------------+-------+
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| Replica_running           | ON    |
| Replica_running_state     | ON    |
+---------------------------+-------+

Ce que cela signifie : 8 workers configurés ; parallélisme par logique d’horloge activé (bon point de départ pour beaucoup de charges OLTP).

Décision : si le lag persiste, vérifier les stats des workers et si les transactions sont parallélisables ; augmenter les workers seulement si le CPU et le profil de verrous le permettent.

Task 5: Identify replication worker bottlenecks (applier is waiting on locks or commits)

cr0x@server:~$ mysql -uroot -p -e "SELECT THREAD_ID, SERVICE_STATE, LAST_ERROR_NUMBER, LAST_ERROR_MESSAGE FROM performance_schema.replication_applier_status_by_worker;"
+-----------+--------------+-------------------+--------------------+
| THREAD_ID | SERVICE_STATE| LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE |
+-----------+--------------+-------------------+--------------------+
|      1213 | ON           |                 0 |                    |
|      1214 | ON           |                 0 |                    |
|      1215 | ON           |                 0 |                    |
|      1216 | ON           |                 0 |                    |
|      1217 | ON           |                 0 |                    |
|      1218 | ON           |                 0 |                    |
|      1219 | ON           |                 0 |                    |
|      1220 | ON           |                 0 |                    |
+-----------+--------------+-------------------+--------------------+

Ce que cela signifie : les workers tournent et n’ont pas d’erreur. Cela ne prouve pas qu’ils sont efficaces ; ça prouve qu’ils ne sont pas morts.

Décision : corréler avec les métriques InnoDB et disque ; si les workers sont « ON » mais que le lag augmente, vous êtes probablement lié par l’I/O ou sérialisé par des dépendances de transaction.

Task 6: Check for long transactions on the replica blocking apply (metadata locks, row locks)

cr0x@server:~$ mysql -uroot -p -e "SELECT trx_id, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx ORDER BY trx_started LIMIT 5\G"
*************************** 1. row ***************************
trx_id: 924118311
trx_started: 2025-12-30 01:44:02
trx_mysql_thread_id: 23301
trx_query: ALTER TABLE orders ADD COLUMN promo_code VARCHAR(32)

Ce que cela signifie : un DDL de longue durée sur la réplique peut bloquer la progression de l’appliqueur ou causer des waits selon le comportement du moteur et le mode DDL.

Décision : arrêter la session conflictuelle, reprogrammer le DDL correctement (outillage de changement de schéma en ligne), et revérifier l’état de l’appliqueur.

Task 7: Measure lag with pt-heartbeat (seconds-behind can lie)

cr0x@server:~$ pt-heartbeat --user=root --ask-pass --monitor --database=percona --table=heartbeat --host=127.0.0.1 --interval=1
0.00s [  0.00s,  0.00s,  0.00s ]
0.98s [  0.22s,  0.80s,  0.98s ]
4.12s [  1.10s,  3.70s,  4.12s ]

Ce que cela signifie : le heartbeat montre le retard réel d’application ; les pics et la gigue indiquent un débit d’application incohérent, pas seulement un arriéré stable.

Décision : si les pics du heartbeat corrèlent avec la latence disque ou les fenêtres de sauvegarde, corriger la contention I/O ; s’ils corrèlent avec des rafales d’écritures, ajuster group commit / apply parallèle.

Task 8: Check disk latency on replica (I/O starvation is a lag factory)

cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (db-replica-01) 	12/30/2025 	_x86_64_	(16 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.44    0.00    4.21   28.77    0.00   54.58

Device            r/s     w/s   rkB/s   wkB/s  await  svctm  %util
nvme0n1         220.0   980.0  8800.0 74200.0  18.40   0.92 97.10

Ce que cela signifie : %util proche de 100 % et await ~18ms : le périphérique est saturé. L’application de la réplication sera erratique.

Décision : séparer relay logs / datadir, réduire les I/O concurrentes (sauvegardes, analytics), ou passer à un stockage plus rapide. Le tuning ne surmontera pas la physique.

Task 9: Check InnoDB flushing pressure (the silent replication killer)

cr0x@server:~$ mysql -uroot -p -e "SHOW ENGINE INNODB STATUS\G" | egrep -i "Log sequence number|Log flushed up to|checkpoint|pending|history list length|pages flushed"
Log sequence number 228771228911
Log flushed up to   228771110122
Last checkpoint at  228770000000
History list length 142381
pending writes: LRU 0, flush list 87, single page 0
pages flushed: 19872

Ce que cela signifie : la longueur de la history list est élevée et des écritures de flush sont en attente ; la purge/flush peut être à la traîne sous charge d’écriture, provoquant des bloquages et du lag.

Décision : enquêter sur les longues transactions, régler purge/flush, et réduire la nature en rafales ; envisager d’ajuster innodb_flush_log_at_trx_commit seulement avec une position de durabilité claire.

Task 10: Verify binlog and durability settings on the source (commit stall suspects)

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

Ce que cela signifie : c’est la posture « durable » : chaque transaction flush le redo et le binlog. Excellent pour la sécurité, coûteux en latence.

Décision : si vous observez des blocages de commit et que vous n’avez pas le stockage pour les soutenir, achetez du stockage meilleur ou acceptez une durabilité moindre. Il n’y a pas de troisième option.

Task 11: Check replication user and SSL status (flaky network and auth renegotiation are real)

cr0x@server:~$ mysql -uroot -p -e "SHOW REPLICA STATUS\G" | egrep -i "Master_SSL_Allowed|Master_SSL_Verify_Server_Cert|SSL|Connect_Retry|Last_IO_Error"
Master_SSL_Allowed: Yes
Master_SSL_Verify_Server_Cert: Yes
Connect_Retry: 60
Last_IO_Error:

Ce que cela signifie : SSL est activé et vérifié ; connect retry est raisonnable ; pas d’erreurs I/O actuelles.

Décision : si des erreurs I/O apparaissent de façon intermittente, corrélez avec des coupures réseau ; ajustez les timeouts seulement après avoir stabilisé le transport.

Task 12: Detect data drift safely with pt-table-checksum (don’t “trust” replication)

cr0x@server:~$ pt-table-checksum --user=root --ask-pass --host=db-primary-01 --databases=app --replicate=percona.checksums --nocheck-replication-filters
TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-30T02:22:01      0      1    128      16       0   0.423 app.users
12-30T02:22:02      0      0   8401      64       0   3.982 app.orders

Ce que cela signifie : DIFFS indique des checksums non concordants ; app.users présente une dérive. Cela correspond au symptôme de clé dupliquée cité plus haut.

Décision : ne plus considérer cette réplique comme promotable ; planifier une resynchronisation ou une réparation ciblée avec pt-table-sync après avoir compris la cause.

Task 13: Assess relay log growth and disk pressure (it’s often “just” space)

cr0x@server:~$ du -sh /var/lib/mysql/*relay* 2>/dev/null | sort -h | tail
42G	/var/lib/mysql/relay-bin.000812
42G	/var/lib/mysql/relay-bin.000813
43G	/var/lib/mysql/relay-bin.000814

Ce que cela signifie : les relay logs ont gonflé ; la pression disque peut causer de la latence ou une future panne.

Décision : corriger d’abord le débit d’application ; puis revoir les paramètres de purge des relay logs et s’assurer que la réplique peut suivre pendant les pics d’écriture.

Task 14: Confirm the replica is actually read-only (prevent errant writes)

cr0x@server:~$ mysql -uroot -p -e "SHOW VARIABLES WHERE Variable_name IN ('read_only','super_read_only');"
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| read_only       | ON    |
| super_read_only | ON    |
+-----------------+-------+

Ce que cela signifie : même les utilisateurs avec SUPER ne peuvent pas écrire (super_read_only). C’est un de ces paramètres qu’on oublie qu’une seule fois.

Décision : appliquer cela sur toutes les répliques via la gestion de configuration ; autoriser les écritures seulement pendant des procédures de promotion contrôlées.

Task 15: Inspect binary log throughput and rotation behavior (source-side sanity)

cr0x@server:~$ mysql -uroot -p -e "SHOW BINARY LOGS;"
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.004219 | 1073741824|
| mysql-bin.004220 | 1073741824|
| mysql-bin.004221 |  812331221|
+------------------+-----------+

Ce que cela signifie : les binlogs tournent à 1 GiB ; un fort churn peut augmenter l’I/O et le overhead métadonnées si vos disques sont lents ou vos sauvegardes naïves.

Décision : assurez-vous que la rétention des binlogs correspond au pire lag des répliques et à la stratégie de sauvegarde ; ne « optimisez » pas en réduisant la taille des fichiers à moins d’aimer les rotations supplémentaires.

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

Mini-histoire 1 : l’incident causé par une mauvaise hypothèse (GTID rend le basculement « automatique », non ?)

Une entreprise SaaS de taille moyenne utilisait MySQL avec GTID activé et une topologie primaire/réplique propre. Ils avaient un outil de basculement relié à la supervision.
L’équipe croyait que GTID rendait le basculement déterministe : promouvoir la réplique avec le plus de GTID exécutés, rediriger l’app, et passer à autre chose.

Lors d’un petit incident réseau, une réplique a brièvement perdu la connectivité avec le primaire. La supervision a vu « replication stopped » et a déclenché la promotion.
Le nouveau primaire est monté, mais une part du trafic est quand même allée vers l’ancien primaire parce qu’une hypothèse sur le TTL DNS ne correspondait pas à la réalité. Des écritures ont eu lieu sur les deux.
Personne ne l’a remarqué immédiatement parce que les deux étaient « sains » du point de vue de l’application.

L’heure suivante fut une leçon coûteuse sur les jeux GTID. Quand ils ont essayé de réintégrer l’ancien primaire comme réplique, il a refusé : des transactions errantes existaient des deux côtés.
Ils se sont retrouvés propriétaires de deux vérités divergentes. Les managers voulaient une fusion rapide. La base de données s’en fichait.

La réparation fut ennuyeuse : geler les écritures, choisir un vainqueur, reconstruire le perdant à partir d’une sauvegarde connue bonne, et appliquer super_read_only sur les répliques.
Ils ont aussi durci le basculement avec une exigence : avant promotion, prouver que l’ancien primaire est clôturé (pas d’écritures applicatives, pas de VIP, pas de route proxy).

Ils sont ensuite passés à Percona Server — pas parce que cela aurait empêché cette erreur, mais parce qu’ils voulaient une meilleure visibilité et une discipline d’outillage autour de l’état de la réplication.
Le vrai changement fut culturel : le basculement est une procédure, pas un réflexe.

Mini-histoire 2 : l’optimisation qui s’est retournée contre eux (commits rapides, tout le reste lent)

Une autre entreprise courait après les nombres de latence. Quelqu’un a proposé d’assouplir la durabilité : définir sync_binlog=0 et innodb_flush_log_at_trx_commit=2.
L’argument était convaincant : moins de fsyncs, meilleur débit, moins de lag sur les répliques parce que la source « tournerait plus lisse ».

Ça a effectivement tourné plus lisse. Jusqu’à ce qu’un reboot d’hôte pendant une mise à jour du noyau se passe mal. La source a redémarré, mais le binlog et le redo InnoDB ne s’alignaient pas parfaitement.
La réplication n’a pas arrêté ; elle a appliqué ce qu’elle pouvait. Le problème fut pire : le jeu de données présentait maintenant des incohérences subtiles et des transactions manquantes par rapport à ce que l’application avait reconnu.

L’incident n’a pas été catastrophique car ils disposaient d’un log d’événements externe pour les actions business critiques, donc ils ont pu réconcilier. Mais ce furent des semaines d’audits et de correctifs.
L’équipe ops, auparavant adepte du « gain de performance », est devenue allergique aux changements de durabilité non documentés.

Le compromis éventuel fut sensé : garder des paramètres durables pour les clusters critiques, utiliser du stockage plus rapide, et isoler les charges analytics sur des répliques pouvant tolérer des réglages moins stricts.
Ils ont aussi formalisé la « posture de durabilité » comme une décision produit, pas une bidouille nocturne d’un ingénieur.

Blague #2 : Désactiver le fsync pour « réparer » la réplication, c’est comme enlever votre détecteur de fumée pour arrêter le bip — paisible jusqu’à ce que ce soit mémorable.

Mini-histoire 3 : la pratique ennuyeuse mais correcte qui a sauvé la mise (drills de reconstruction et discipline des checksums)

Une fintech utilisait Percona Server avec une habitude stricte : chaque trimestre, ils reconstruisaient une réplique depuis zéro en utilisant Percona XtraBackup.
Pas par plaisir — parce que cela maintenait les runbooks honnêtes et prouvait que les sauvegardes étaient utilisables.

Un jour, une réplique a commencé à lancer des erreurs de clé dupliquée. L’instinct initial fut de « passer l’événement » pour relancer la réplication.
Mais leur politique interdisait de sauter sans comparaison de checksum et ticket d’incident. Des grognements, oui. La politique a tenu.

Ils ont lancé pt-table-checksum et trouvé une dérive limitée à un petit ensemble de tables liées à un job batch legacy.
Le job batch avait été accidentellement pointé sur une réplique pendant un week-end. read_only était ON, mais super_read_only ne l’était pas, et le job utilisait un compte privilégié.

Parce qu’ils s’entraînaient aux reconstructions, la réponse fut propre : reconstruire la réplique affectée, faire tourner les identifiants privilégiés, activer super_read_only, et ajouter un garde-fou dans le déploiement du job.
L’impact business fut minimal. L’astreinte a pu dîner encore chaud. Voilà à quoi ressemble la « banalité » quand elle fonctionne.

Erreurs courantes : symptôme → cause racine → correctif

1) Symptom: Seconds_Behind_Source jumps wildly, then recovers

Cause racine : saturation I/O de la réplique (relay logs + flush InnoDB + lectures de sauvegarde) ou commits source en rafales.

Correctif : isoler l’I/O (volumes séparés si possible), planifier les sauvegardes hors pics, vérifier la pression de flush, et mesurer le lag réel avec pt-heartbeat.

2) Symptom: Replica SQL thread stopped with duplicate key errors

Cause racine : dérive des données (écritures errantes, SBR non déterministe, corrections manuelles sur un nœud).

Correctif : ne pas sauter aveuglément ; exécuter des checksums, trouver le chemin d’écriture, appliquer super_read_only, puis resynchroniser par rebuild ou sync ciblé.

3) Symptom: Replication “running” but app reads are stale

Cause racine : vous lisez depuis une réplique en retard sans cohérence de session, ou seconds-behind est trompeur (décalage d’horloge, heartbeats absents).

Correctif : ajouter une mesure de heartbeat, implémenter un routage read-your-writes (GTID-aware, support proxy), ou restreindre les lectures sur répliques pour les chemins critiques.

4) Symptom: Failover worked, but old primary won’t rejoin

Cause racine : GTID errants dus à des écritures sur les deux nœuds ou à un fencing inapproprié.

Correctif : appliquer le fencing (VIP/proxy, règles firewall), rendre les répliques en lecture seule, et reconstruire les nœuds plutôt que de bricoler les jeux GTID en panique.

5) Symptom: Replication stops on DDL or waits forever

Cause racine : contention de verrous de métadonnées ou longue transaction empêchant le DDL de finir.

Correctif : identifier les sessions bloquantes, tuer ou reprogrammer, et utiliser des outils de changement de schéma en ligne adaptés à votre charge (et les tester d’abord sur une réplique).

6) Symptom: Replica can’t keep up even with many applier workers

Cause racine : les transactions ne sont pas parallélisables (lignes/tables chaudes) ou l’I/O est la vraie limite.

Correctif : réduire la contention (schéma et requêtes), sharder les tables chaudes, améliorer les index, ou scaler horizontalement. Ajouter des workers n’est pas une incantation.

7) Symptom: “IO thread reconnecting” and intermittent stalls

Cause racine : instabilité réseau, problèmes DNS, accrochages de renégociation TLS, ou timeouts trop agressifs.

Correctif : corriger le réseau d’abord ; ensuite ajuster les timeouts. Vérifier aussi les paramètres SSL et que les privilèges de l’utilisateur de réplication ne s’expirent pas de façon inattendue.

8) Symptom: Replicas fall behind during backups

Cause racine : les lectures de sauvegarde saturent le stockage, ou le processus de sauvegarde concurrence CPU et cache.

Correctif : brider les sauvegardes, utiliser du streaming off-host, isoler les disques, ou exécuter les sauvegardes sur des répliques dédiées. Si les sauvegardes nuisent à la réplication, vous n’êtes qu’à une restauration de la douleur.

Listes de contrôle / plan étape par étape

Checklist A: If your ops goal is “safe failover,” do these in order

  1. Appliquer la protection en écriture sur les répliques : définir read_only=ON et super_read_only=ON sur toutes les répliques via la gestion de configuration.
  2. Standardiser le mode GTID sur l’ensemble (si vous l’utilisez) : gtid_mode et enforce_gtid_consistency cohérents.
  3. Mettre en œuvre le fencing pour le basculement : prouver que l’ancien primaire est inaccessible pour les écritures (proxy/VIP/firewall), pas seulement « marqué unhealthy ».
  4. Rendre le lag observables : mesure par heartbeat, pas seulement seconds-behind-source.
  5. Répéter les procédures de rejoins : s’entraîner à reconstruire un nœud et le réintroduire proprement.
  6. Décider explicitement de la posture de durabilité : documenter si vous exécutez sync_binlog=1 et innodb_flush_log_at_trx_commit=1, et pourquoi.

Checklist B: If your ops goal is “less lag under load,” start here

  1. Mesurer le goulot : est-ce le commit source, le transport, l’I/O des relay, ou l’application ?
  2. Corriger la latence stockage d’abord : si votre réplique est à 95–100 % d’utilisation disque, ce n’est pas un problème de réglage de réplication ; c’est un problème de budget I/O.
  3. Utiliser le format binlog ROW sauf raison spécifique contraire.
  4. Activer un parallélisme de réplication sensé et vérifier son efficacité (stats des workers, pas seulement les paramètres).
  5. Réduire les points chauds : réécrire la requête qui met à jour la même ligne 10 000 fois par minute. Vous la connaissez.
  6. Contrôler les fenêtres de maintenance lourdes : sauvegardes, changements de schéma, requêtes analytics — ne pas les empiler sur les pics d’écriture.

Checklist C: Step-by-step plan for switching to Percona Server (minimize risk)

  1. Choisir un cluster pilote où les problèmes de réplication sont visibles mais le risque business est maîtrisable.
  2. Aligner les versions avec soin (majeure/mineure) et vérifier la compatibilité de réplication en staging avec un trafic proche de la production.
  3. Remplacer d’abord les répliques : échanger les paquets sur une réplique, la laisser répliquer, valider avec checksums et lectures applicatives.
  4. Promouvoir une réplique Percona lors d’un événement planifié (avec fencing complet) et en faire le primaire.
  5. Déployer sur les nœuds restants un par un ; conserver un plan de rollback propre (reconstruire plutôt que rétrograder in-place quand possible).
  6. Standardiser l’outillage : XtraBackup pour les rebuilds, pt-heartbeat pour le lag, pt-table-checksum pour la dérive, et un runbook d’incident clair.
  7. Verrouiller les contrôles banals : enforcement read-only, hygiène des comptes privilégiés, et drills de rebuild reproductibles.

Pourquoi Percona Server donne souvent l’impression d’être « plus stable » pour la réplication

Ce n’est pas de la magie ; c’est de l’effet de levier

La plupart des instabilités de réplication sont soit (a) un manque d’observabilité, (b) une inconsistance opérationnelle, ou (c) un I/O sous-dimensionné.
Percona Server tend à améliorer (a) et (b) dès l’installation, et il se marie bien avec des outils qui rendent (c) évident.

Les équipes ops basculent quand elles en ont assez de deviner

Dans beaucoup d’organisations, « on utilise MySQL » veut en réalité dire « on utilise MySQL plus du savoir tribal ». Ce savoir tribal est fragile. Il vit dans la tête d’un ingénieur senior,
et il part en vacances au pire moment possible.

L’écosystème Percona encourage une posture ops plus répétable : discipline des checksums, mesure par heartbeat, workflows de sauvegarde/rebuild standardisés.
Si votre stabilité de réplication dépend actuellement de débogages héroïques, la standardisation est une fonctionnalité.

Une citation de fiabilité à garder sur votre écran

L’espoir n’est pas une stratégie. — idée paraphrasée, souvent attribuée dans les cercles d’ingénierie aux responsables exploitation et praticiens de la fiabilité

Traitez cela comme un rappel : « la réplication fonctionne généralement » est de l’espoir. Une procédure de basculement et de rebuild testée est une stratégie.

FAQ

1) Est-ce que Percona Server réplique différemment de MySQL ?

Fondamentalement, non. Il utilise les mêmes concepts de réplication : binlogs, relay logs, fils d’application, GTID (quand activé), et le même protocole.
Les différences pratiques portent sur l’instrumentation, les fonctionnalités de performance, et le packaging orienté opérations.

2) Passer à Percona Server réduira-t-il automatiquement le lag de réplication ?

Pas automatiquement. Si le lag est causé par la latence disque, des lignes chaudes, ou des transactions non parallélisables, un simple changement de serveur ne corrigera pas la physique ni la conception de la charge.
Ce que cela améliore souvent, c’est votre capacité à voir rapidement la cause et appliquer la bonne correction avec moins d’hypothèses.

3) La réplication semisynchrone suffit-elle à empêcher la perte de données ?

Elle réduit la fenêtre, mais ce n’est pas la même chose qu’une réplication synchrone basée sur un quorum entre plusieurs nœuds.
En cas de latence ou de panne, elle peut se dégrader ou se comporter d’une manière qui surprend les équipes qui pensent « pas de perte de données jamais ».
Décidez ce que « sûr » signifie pour votre entreprise et testez les basculements dans des conditions dégradées.

4) Faut-il utiliser statement-based ou row-based pour la réplication ?

Préférez ROW pour la justesse dans la plupart des systèmes OLTP modernes. Le statement-based peut être plus compact et parfois plus rapide, mais il est plus facile de dériver avec du non-déterminisme.
Le mode mixte existe, mais la taxe de complexité est bien réelle.

5) Pourquoi Seconds_Behind_Source indique parfois 0 alors que je suis en retard ?

Il est calculé à partir des timestamps dans les events et peut être trompeur en cas de dérive d’horloge, périodes d’inactivité, ou certains états d’appliqueur.
Utilisez une table heartbeat (pt-heartbeat ou équivalent) pour une mesure opérationnelle fiable du lag.

6) Puis-je « sauter » une erreur de réplication pour relancer tout ?

Vous le pouvez. Vous pouvez aussi couper les freins pour alléger votre voiture. Sauter des erreurs n’est acceptable qu’avec une cause racine clairement comprise et un plan pour restaurer la cohérence
(checksum + sync ciblé ou rebuild). Sinon vous promouvez une narration corrompue.

7) Comment savoir s’il faut ajouter des replica parallel workers ?

N’ajoutez des workers qu’après avoir confirmé que l’appliqueur est lié au CPU et que les transactions sont parallélisables. Si vous êtes limité par l’I/O ou bloqué sur des lignes chaudes, plus de workers augmente la contention.
Vérifiez le statut des workers, les waits de verrou et la latence disque avant d’augmenter le parallélisme.

8) Quelle est la meilleure pratique « ennuyeuse » unique pour améliorer la sécurité de la réplication ?

Des drills de reconstruction trimestriels (ou mensuels) depuis des sauvegardes physiques, plus des validations de checksum régulières. Cela transforme un événement terrifiant en réflexe entraîné.
Aussi : appliquer super_read_only sur les répliques.

9) Si j’utilise déjà Orchestrator (ou similaire), dois-je quand même me soucier de ces détails ?

Oui. Orchestrator automatise une procédure ; il ne redéfinit pas la réalité. Si vos répliques acceptent des écritures, ou si vos métriques de lag sont fausses, l’orchestrateur échouera rapidement et avec assurance.
L’automatisation amplifie la correction et amplifie les erreurs — choisissez bien ce que vous lui donnez.

10) Quand ne dois-je pas passer à Percona Server ?

Si votre organisation ne peut pas maintenir l’hygiène des paquets, la discipline des versions, ou tester les upgrades, le changement ne vous sauvera pas.
De même, si vous êtes sur un service cloud managé qui n’autorise pas Percona, concentrez-vous sur les pratiques : instrumentation, heartbeats, checksums, drills de rebuild et dimensionnement I/O.

Prochaines étapes que vous pouvez réaliser cette semaine

  1. Instrumenter correctement le lag : déployer un heartbeat et le graphier. Arrêtez de vous fier à un seul champ d’état comme vérité.
  2. Auditer la protection en écriture des répliques : garantir super_read_only=ON partout et retirer les identifiants privilégiés des jobs batch.
  3. Exécuter un checksum sur un schéma critique : si vous trouvez de la dérive, traitez-la comme une défaillance de processus, pas comme un bug isolé.
  4. Faire un drill contrôlé de reconstruction de réplique : chronométrez-le, documentez-le, et corrigez ce qui vous a surpris.
  5. Choisir votre posture de durabilité : documenter les paramètres et la fenêtre de perte acceptable. Si le business veut « pas de perte », financez le matériel et la topologie.
  6. Si la migration vers Percona est envisagée : convertir d’abord une réplique, valider, puis promouvoir lors d’un événement planifié avec fencing et plan de rollback.

La stabilité de la réplication porte rarement sur un seul paramètre. Il s’agit de savoir si votre système vous dit la vérité rapidement, et si votre équipe s’est entraînée à réagir quand ce n’est pas le cas.
Si vous migrez de MySQL vers Percona Server, faites-le pour cela : moins de mystères, plus de répétabilité, et une topologie qui se comporte comme vous le pensez.

← Précédent
ZFS snapdir=visible : Auditer les instantanés sans énerver les utilisateurs
Suivant →
Ubuntu 24.04 : Secure Boot bloque les pilotes — réparez sans tout casser la configuration

Laisser un commentaire