Vous avez acheté « trois petits serveurs » parce que le budget aime les groupes de trois. Ensuite vous avez déployé une base SQL distribuée parce que le marketing aime le mot « résilient ».
Maintenant le p95 de la latence sur votre tableau de bord ressemble à un itinéraire panoramique, et chaque revue d’incident inclut la phrase « mais en local ça fonctionnait ».
Voici la taxe de latence que personne ne met sur la diapositive : la correction distribuée a un coût réel par requête, et ce coût devient bruyant sur des petits serveurs.
Pas catastrophique. Juste suffisamment bruyant pour vous enlever le sommeil.
La taxe de latence : ce que vous payez pour le consensus
Si vous ne retenez qu’une chose, que ce soit celle-ci : le chemin OLTP par défaut de MySQL est « effectuer l’écriture localement, puis répliquer plus tard ».
Le chemin OLTP par défaut de CockroachDB est « coordonner l’écriture avec un quorum, puis valider ».
Sur un réseau correct et des disques sains, les écritures par quorum vont bien. Sur des petits serveurs avec du stockage grand public et du réseau 1Gbps (ou pire : virtualisé en « best effort »),
les écritures par quorum deviennent un amplificateur de latence. Pas toujours sur la latence médiane. Sur la latence queue. Celle que les utilisateurs remarquent et que les SRE héritent.
La différence opérationnelle n’est pas subtile :
- MySQL : Un unique primaire peut être extrêmement rapide. C’est aussi un point unique où la physique est clémente et la correction est locale. Les réplicas servent à l’échelle de lecture et au basculement. La cohérence est un choix de politique.
- CockroachDB : Chaque écriture participe au consensus pour la plage qu’elle touche. La cohérence est la valeur par défaut, pas un ajout. La latence est la taxe.
Un cadrage pratique : si votre application est sensible à la latence p99 et que vous faites tourner des nœuds petits, le SQL distribué peut ressembler à l’embauche d’un comité pour approuver chaque e-mail que vous envoyez.
Une citation qui survit à beaucoup de revues d’incidents : Tout échoue, tout le temps.
— Werner Vogels.
Il ne parlait pas spécifiquement de votre cluster trois nœuds, mais il aurait tout aussi bien pu.
Où la taxe apparaît (et pourquoi ça surprend)
La surprise n’est pas qu’un système distribué ait un overhead. La surprise est où il se manifeste.
Vous regarderez le CPU et verrez beaucoup de marge. Vous regarderez le temps moyen des requêtes et vous vous sentirez bien. Puis vous ouvrirez l’histogramme et verrez p95/p99 s’envoler.
Endroits courants où la taxe apparaît :
- Écritures par quorum : une validation nécessite des accuses de réception de la majorité des réplicas pour la plage. C’est au moins un aller-retour, parfois plus.
- Cohérence des lectures : les lectures fortement cohérentes peuvent nécessiter une coordination (la place du leaseholder compte). Les lectures périmées peuvent être plus rapides, mais il faut y souscrire et comprendre les conséquences.
- Scissions et rééquilibrages de plages : le travail en arrière-plan n’est pas « gratuit ». Sur de petites machines, il concurrence directement la latence au premier plan.
- Compactions : les moteurs basés sur LSM échangent amplification d’écriture contre efficacité de lecture. Cette amplification devient une taxe disque et CPU à des moments inopportuns.
Deux chiffres qui devraient hanter votre feuille de calcul de dimensionnement
Vous ne pouvez pas « optimiser » la physique, seulement la contourner.
- RTT réseau entre nœuds : chaque milliseconde compte quand votre chemin de validation inclut une coordination inter-nœuds. 1–2ms RTT semble correct jusqu’à ce que vous ayez besoin de plusieurs sauts sous charge.
- Latence fsync du stockage : si votre couche de stockage transforme occasionnellement fsync en une aventure de 20–100ms, le consensus distribué incorporera fidèlement cette aventure dans la latence visible par l’utilisateur.
Blague #1 : Un cluster trois nœuds sur de petites VM, c’est comme une course de relais à trois où chacun insiste pour se lacer les chaussures entre les remises.
Faits et histoire utiles pour vos arguments
Ce ne sont pas des anecdotes pour un quiz au bar. Ils expliquent pourquoi les systèmes se comportent ainsi.
- MySQL a été livré au milieu des années 1990 et est devenu le choix par défaut pour l’OLTP web parce qu’il était facile à déployer, facile à répliquer et rapide sur une seule machine.
- InnoDB est devenu le moteur de stockage par défaut de MySQL (après des années de domination de MyISAM), apportant récupération après crash, verrouillage au niveau des lignes et transactions réelles aux déploiements grand public.
- La plupart des modèles HA MySQL historiques favorisaient la réplication asynchrone car elle est simple et garde la latence du primaire basse ; le compromis est la perte potentielle de données en cas de basculement.
- Les algorithmes de consensus comme Raft ont été conçus pour rendre le consensus distribué plus facile à comprendre et implémenter que Paxos, pas pour être gratuits en latence.
- CockroachDB a été construit avec Raft dès le départ, visant des sémantiques SQL de type PostgreSQL avec une conception shared-nothing et géo-distribuée.
- Google Spanner a popularisé le « SQL distribué à forte cohérence » en utilisant TrueTime ; CockroachDB vise des objectifs similaires sans matériel d’horloge spécialisé, ce qui affecte la manière dont l’incertitude et les réessais transactionnels apparaissent.
- Les moteurs de stockage LSM sont devenus courants dans les bases distribuées car ils gèrent bien un fort débit d’écriture, mais ils nécessitent des compactions — c’est-à-dire des E/S en arrière-plan qui peuvent mordre la latence queue.
- L’ère du théorème CAP a fait de la « cohérence vs disponibilité » une conversation de comité ; les systèmes SQL distribués choisissent typiquement cohérence et tolérance aux partitions, forçant des compromis sur la disponibilité pendant les partitions.
- La latence p99 est devenue une obsession SRE parce que l’expérience utilisateur est dominée par le comportement en queue, pas par les moyennes ; la coordination distribuée est un générateur classique de latence queue.
Pourquoi les petits serveurs font paraître le SQL distribué pire
« Petits serveurs » signifie généralement une combinaison de : moins de cœurs, moins de RAM, NVMe plus lent (ou pire : attaché au réseau), voisins moins prévisibles, et un réseau dimensionné pour un trafic « normal ».
Le SQL distribué n’a rien contre les petits serveurs. Il refuse simplement de faire semblant qu’ils sont des grosses machines.
Les nœuds petits ne réduisent pas seulement la capacité ; ils réduisent la marge
La marge est la marge invisible qui maintient la latence queue stable.
Sur une grosse machine, les compactions, les flushs ou un léger jitter réseau peuvent être absorbés.
Sur un petit nœud, le même travail en arrière-plan concurrence le trafic au premier plan et gagne plus souvent que vous ne le souhaitez.
Les clusters trois nœuds sont séduisants opérationnellement (et mécaniquement sévères)
Trois nœuds est la forme minimale qui ressemble à « un cluster ». C’est aussi la forme minimale où toute perturbation peut devenir visible par les utilisateurs.
Perdre un nœud et vous êtes en mode « plus d’échecs, s’il vous plaît ».
- MySQL sur trois nœuds signifie typiquement 1 primaire + 2 réplicas. Le primaire reste chaud ; les réplicas sont surtout des passagers jusqu’au basculement.
- CockroachDB sur trois nœuds signifie que les trois sont dans le chemin d’écriture (quorum). La santé de chaque nœud compte à chaque minute.
Le tueur silencieux : l’hétérogénéité
Les petites flottes sont rarement homogènes. Un nœud est sur un hyperviseur légèrement plus bruyant.
Un disque est légèrement plus lent.
Une NIC partage des interruptions avec quelque chose de grossier.
Les systèmes distribués tendent à fonctionner au rythme de leur participant le plus mauvais — surtout sur le p99.
MySQL : la référence basse latence avec des arêtes vives
Le super-pouvoir de MySQL est ennuyeux : une machine, un journal de commit, une hiérarchie de cache.
Si votre charge tient sur un primaire, MySQL peut offrir une très faible latence avec un comportement prévisible.
Vous pouvez absolument mal faire tourner MySQL, mais il faut y mettre du cœur.
Ce pour quoi MySQL est excellent (sur petits serveurs)
- Écritures de ligne unique à faible latence quand votre schéma et vos index sont sains.
- p95/p99 stable quand le stockage est correct et que vous évitez les points chauds de contention.
- Simplicité opérationnelle pour les équipes qui peuvent tolérer un primaire unique et ont un plan clair de basculement.
Les modes de panne de MySQL ne sont pas subtils
- Saturation du primaire : vous n’obtenez pas une dégradation graduelle ; vous obtenez une file d’attente.
- Décalage de réplication : l’échelle de lecture et la sécurité du basculement dépendent d’un flux asynchrone en retard à moins que vous ne payiez le coût sync.
- Correction du basculement : le split brain est évitable, mais pas automatique ; vous avez besoin d’outils et de discipline.
Vérification de réalité pour MySQL
Si vous avez besoin d’une forte cohérence entre plusieurs écrivains dans plusieurs emplacements, MySQL ne deviendra pas magiquement une base distribuée.
Vous pouvez construire cela avec semi-sync replication, group replication, ou une coordination externe — mais vous gagnerez chaque pageur.
CockroachDB : la correction à l’échelle, même quand vous n’aviez pas besoin d’échelle
Le pitch de CockroachDB est simple : garder SQL, perdre la fragilité du primaire unique.
Les écritures sont répliquées. Les lectures peuvent être servies depuis le « bon » endroit. Les basculements sont automatisés et rapides.
C’est de l’ingénierie réelle, pas de la poudre aux yeux.
Ce pour quoi CockroachDB est excellent (même sur petits serveurs)
- Survivre aux défaillances de nœuds sans rituels manuels de basculement.
- Scalabilité des lectures et écritures en ajoutant des nœuds (dans la limite du raisonnable et avec attention à la localité).
- Sémantiques cohérentes qui simplifient la logique applicative par rapport à une réplication bricolée à la main.
Ce que CockroachDB exige de vous
- Respect de la latence : vous coordonnez, donc mesurez le réseau et le disque sérieusement.
- Compréhension de la contention : les points chauds ne disparaissent pas dans un cluster ; ils deviennent des points chauds distribués avec réessais.
- Décisions de localité soignées : leaseholders et réplicas doivent être placés intentionnellement si vous tenez à la latence.
Réessais de transaction : la « fonctionnalité » qui ressemble à un bug
CockroachDB réessaiera des transactions sous contention ou incertitude. Cela fait partie de la préservation de la correction.
Le symptôme est des erreurs au niveau applicatif (ou des réessais par le driver) et des pics de latence qui paraissent aléatoires tant que vous ne les corrélez pas avec des métriques de contention.
Blague #2 : Le SQL distribué est le seul produit pouvant vous vendre « pas de point de défaillance unique » et quand même échouer votre requête parce que deux horloges n’étaient pas d’accord poliment.
Par charge de travail : qui gagne et pourquoi
OLTP simple (lectures/écritures d’une ligne, SLO p99 strict)
Sur petits serveurs, MySQL gagne généralement sur la latence brute. La validation est locale. Le cache est local. Le chemin de code est mature et court.
CockroachDB peut répondre à des SLO raisonnables ici, mais vous sentirez davantage le coût du quorum et du moteur de stockage, surtout si vos nœuds sont sous-dimensionnés ou votre réseau est instable.
Si votre produit vit ou meurt sur 5–20ms p99 pour de petites transactions, ne remplacez pas avec légèreté une base à consensus en espérant qu’elle « s’ajuste ».
Haute disponibilité avec basculement automatique
CockroachDB gagne sur le comportement opérationnel. Si vous n’avez pas le personnel pour exécuter proprement des exercices de basculement MySQL, vous finirez par mal basculer.
CockroachDB rend la perte de nœud « ennuyeuse ».
MySQL peut être hautement disponible, mais vous devez l’implémenter et vous y entraîner. La technologie existe. La cohérence organisationnelle souvent non.
Mise à l’échelle des écritures (plusieurs écrivains, croissance horizontale)
L’échelle horizontale des écritures n’est pas le terrain natif de MySQL.
Vous pouvez faire du sharding, mais alors votre application devient une couche de routage. C’est une architecture légitime, mais c’est un engagement.
CockroachDB est conçu pour faire évoluer les écritures en scindant des ranges et en les distribuant. Sur de petits nœuds, vous serez toujours limités par le disque et le CPU par nœud,
mais au moins l’objectif de conception correspond à l’exigence.
Mise à l’échelle des lectures
Les réplicas de lecture MySQL sont bruts mais efficaces. Ils sont aussi opérationnellement indulgents : si un réplica accuse du retard, vous contournez.
CockroachDB peut aussi distribuer les lectures, mais il faut comprendre les leaseholders et la localité ; autrement les lectures rebondissent dans le cluster et paient des sauts supplémentaires.
Multi-région et latence
Si vous êtes vraiment multi-région, la vitesse de la lumière devient votre chef de produit. La forte cohérence à travers des océans est coûteuse.
CockroachDB vous donne des outils pour placer les données et contrôler la localité lecture/écriture, mais si vous demandez des millisecondes à un chiffre au niveau mondial, votre demande est irréaliste.
MySQL en multi-région devient souvent un primaire dans une région comme vérité avec des réplicas asynchrones ailleurs. C’est rapide localement et « éventuellement correct » à distance.
Parfois c’est exactement ce que vous voulez.
Évolution du schéma et friction opérationnelle
Les deux ont des pièges pour les changements de schéma. MySQL a des décennies de savoir-faire opérationnel pour les modifications en ligne.
CockroachDB prend en charge les changements de schéma en ligne mais peut encore vous surprendre avec des backfills et leur impact sur les petits clusters.
Tâches pratiques : commandes, sorties et la décision qu’elles entraînent
Vous ne réglez pas la latence distribuée avec des bonnes intentions. Vous la réglez avec des mesures qui pointent la partie la plus lente du chemin de validation :
réseau, disque, contention ou topologie.
Ci-dessous des tâches concrètes. Chacune inclut (1) une commande, (2) une sortie représentative, (3) ce que ça signifie, et (4) la décision à prendre.
Exécutez-les sur vos nœuds réels. De préférence pendant un test de charge qui ressemble à la production, pas un mardi après-midi calme.
Task 1: Confirm network RTT between database nodes
cr0x@server:~$ ping -c 5 db-node-2
PING db-node-2 (10.0.0.12) 56(84) bytes of data.
64 bytes from 10.0.0.12: icmp_seq=1 ttl=64 time=0.78 ms
64 bytes from 10.0.0.12: icmp_seq=2 ttl=64 time=0.91 ms
64 bytes from 10.0.0.12: icmp_seq=3 ttl=64 time=1.02 ms
64 bytes from 10.0.0.12: icmp_seq=4 ttl=64 time=0.85 ms
64 bytes from 10.0.0.12: icmp_seq=5 ttl=64 time=0.80 ms
--- db-node-2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4092ms
rtt min/avg/max/mdev = 0.78/0.87/1.02/0.09 ms
Signification : Un RTT sous la milliseconde à ~1ms est convenable pour un petit cluster. Si vous voyez 3–10ms à l’intérieur d’un même « datacenter », attendez-vous à des douleurs p99 sous écritures par quorum.
Décision : Si le RTT est élevé ou instable, corrigez le placement réseau (même rack/zone), les réglages NIC offload, et les voisins bruyants avant d’accuser la base de données.
Task 2: Measure TCP latency and retransmits under load
cr0x@server:~$ ss -ti dst 10.0.0.12:26257 | head -n 12
ESTAB 0 0 10.0.0.11:52144 10.0.0.12:26257
cubic wscale:7,7 rto:204 rtt:1.3/0.4 ato:40 mss:1448 pmtu:1500 rcvmss:1448 advmss:1448 cwnd:10 bytes_acked:812345 segs_out:12034 segs_in:11877 send 89.2Mbps lastsnd:12 lastrcv:12 lastack:12 pacing_rate 178Mbps retrans:3/12034
Signification : rtt montre le RTT observé et sa variance. retrans indique perte de paquets ou congestion.
Décision : Si les retransmissions augmentent pendant les pics, votre latence queue n’est pas une « optimisation de base de données ». C’est de la congestion. Corrigez QoS, bande passante, MTU, ou le trafic est-ouest bruyant.
Task 3: Check disk latency distribution (the real villain)
cr0x@server:~$ iostat -x 1 5
Linux 6.5.0 (db-node-1) 12/30/2025 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
18.20 0.00 6.40 3.60 0.00 71.80
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz aqu-sz %util
nvme0n1 210.0 8120.0 0.0 0.0 1.20 38.7 480.0 24576.0 0.0 0.0 14.80 51.2 7.40 92.0
Signification : w_await à ~15ms avec %util ~92% signifie que les écritures font la queue. C’est là que p99 va mourir.
Décision : Si l’utilisation disque est constamment élevée ou si les await montent en pics, passez à un stockage plus rapide, séparez les périphériques WAL, réduisez l’amplification d’écriture, ou diminuez la pression de compaction avant de toucher aux réglages SQL.
Task 4: Validate filesystem and mount options
cr0x@server:~$ findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS /var/lib
/var/lib /dev/nvme0n1p2 ext4 rw,relatime,discard,data=ordered
Signification : Des options comme discard peuvent ajouter de la latence sur certains setups ; les valeurs par défaut ext4 sont généralement correctes, mais les détails comptent.
Décision : Si vous voyez des systèmes de fichiers réseau, du thin-provisioning étrange, ou des options non sûres, corrigez le stockage d’abord. Le consensus distribué n’excuse pas des disques instables.
Task 5: Check CPU steal time (virtualization tax)
cr0x@server:~$ mpstat 1 5 | tail -n 7
12:22:11 PM all 15.40 0.00 6.90 2.10 0.00 4.80 0.00 70.80
12:22:12 PM all 17.20 0.00 8.10 2.40 0.00 6.20 0.00 66.10
12:22:13 PM all 14.80 0.00 6.30 1.90 0.00 7.60 0.00 69.40
Signification : Si vous voyez %steal non trivial (pas montré ici ; c’est 0.00), l’hyperviseur emprunte votre temps CPU. Cela gonfle la latence de coordination.
Décision : Steal élevé → passez à des instances dédiées, fixez des pCPUs, ou acceptez que votre p99 soit une ressource partagée avec les jobs batch de vos voisins.
Task 6: Measure fsync behavior quickly with fio
cr0x@server:~$ fio --name=fsync-test --directory=/var/lib/dbtest --size=1G --bs=4k --rw=write --ioengine=sync --fdatasync=1 --runtime=30 --time_based --direct=1
fsync-test: (g=0): rw=write, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=sync, iodepth=1
fio-3.33
Starting 1 process
fsync-test: (groupid=0, jobs=1): err= 0: pid=22811: Tue Dec 30 12:23:40 2025
write: IOPS=4200, BW=16.4MiB/s (17.2MB/s)(492MiB/30001msec); 0 zone resets
clat (usec): min=70, max=24500, avg=220, stdev=410
clat percentiles (usec):
| 95.00th=[ 310], 99.00th=[ 950], 99.90th=[ 8500]
Signification : Le 99.90th à 8.5ms est assez correct ; si vous voyez 50–200ms au 99.9th, votre base de données « gèlera » périodiquement au p99.
Décision : Queue fsync mauvaise → changez la classe de stockage, désactivez les mensonges du cache d’écriture, assurez la protection contre panne de courant, ou déplacez WAL/pebble/redo vers un média meilleur.
Task 7: MySQL—check InnoDB log flush policy
cr0x@server:~$ mysql -e "SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';"
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
Signification : 1 est le plus sûr : flush à chaque commit. 2 ou 0 peut réduire la latence mais risque de perdre des commits récents en cas de crash.
Décision : Si vous comparez MySQL à CockroachDB, gardez ceci à 1 pour l’honnêteté. Si vous le changez, inscrivez le risque dans votre runbook d’incident.
Task 8: MySQL—verify semi-sync is actually on (or not)
cr0x@server:~$ mysql -e "SHOW STATUS LIKE 'Rpl_semi_sync_master_status';"
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | OFF |
+-----------------------------+-------+
Signification : Si semi-sync est OFF, les commits du primaire n’attendent pas d’accusé de réception des réplicas. C’est pourquoi MySQL est rapide, et aussi pourquoi le basculement peut perdre des données.
Décision : Si l’entreprise exige « pas de perte de données », soit vous activez semi-sync (en payant la latence), soit vous cessez de prétendre que la réplication asynchrone remplit cette exigence.
Task 9: MySQL—spot replication lag and decide what “fresh” means
cr0x@server:~$ mysql -e "SHOW REPLICA STATUS\G" | egrep "Seconds_Behind_Source|Replica_IO_Running|Replica_SQL_Running"
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 42
Signification : 42 secondes de retard n’est pas « un peu ». C’est une base de données différente.
Décision : Orientez les lectures qui exigent de la fraîcheur vers le primaire, optimisez la réplication (apply parallèle, corrections de schéma/index), ou acceptez explicitement la cohérence éventuelle au niveau applicatif.
Task 10: CockroachDB—check node health and liveness
cr0x@server:~$ cockroach node status --insecure
id | address | sql_address | build | started_at | updated_at | is_available | is_live
-----+-------------------------------+---------------+---------+----------------------------------+----------------------------------+--------------+----------
1 | db-node-1:26257 | db-node-1:26257 | v23.2.6 | 2025-12-30 11:02:17.123456+00:00 | 2025-12-30 12:25:01.123456+00:00 | true | true
2 | db-node-2:26257 | db-node-2:26257 | v23.2.6 | 2025-12-30 11:02:19.223456+00:00 | 2025-12-30 12:25:00.923456+00:00 | true | true
3 | db-node-3:26257 | db-node-3:26257 | v23.2.6 | 2025-12-30 11:02:21.323456+00:00 | 2025-12-30 12:25:01.003456+00:00 | true | true
Signification : Tous les nœuds sont vivants et disponibles. Si l’un bascule en indisponible de façon intermittente, attendez-vous à des pics de latence d’écriture et des réessais transactionnels.
Décision : Corrigez la stabilité du nœud avant d’ajuster le SQL. « Il flappe parfois » n’est pas un détail mineur dans les systèmes de consensus.
Task 11: CockroachDB—inspect range distribution and under-replication
cr0x@server:~$ cockroach node ranges --insecure
node_id | ranges | leaseholders | replicas | avg_range_size
----------+--------+--------------+----------+----------------
1 | 412 | 190 | 824 | 64MiB
2 | 398 | 145 | 796 | 66MiB
3 | 421 | 205 | 842 | 63MiB
Signification : Répartition raisonnablement équilibrée. Si un nœud détient la majorité des leaseholders, il devient le point chaud de latence pour les lectures/écritures sur ces plages.
Décision : Si déséquilibré, ajustez les contraintes de localité, ajoutez de la capacité, ou investiguez pourquoi le rééquilibrage est bloqué (souvent disque ou réseau).
Task 12: CockroachDB—look for contention and transaction retries in SQL stats
cr0x@server:~$ cockroach sql --insecure -e "SELECT app_name, sum(retry_count) AS retries, sum(cnt) AS stmts FROM crdb_internal.statement_statistics GROUP BY app_name ORDER BY retries DESC LIMIT 5;"
app_name | retries | stmts
------------+---------+--------
web-api | 1842 | 98412
worker | 210 | 12001
console | 0 | 1422
Signification : Votre API subit beaucoup de réessais. C’est du temps que l’utilisateur ressent comme de la latence (même si la transaction réussit finalement).
Décision : Trouvez les clés chaudes, réduisez la contention (sharder les compteurs, regrouper les écritures différemment), et assurez-vous que les réessais clients sont bien configurés plutôt que d’échouer bruyamment.
Task 13: CockroachDB—identify leaseholder locality for a hot table
cr0x@server:~$ cockroach sql --insecure -e "SHOW RANGES FROM TABLE app.orders;"
start_key | end_key | range_id | replicas | lease_holder
------------+---------+----------+----------+--------------
NULL | /1000 | 84 | {1,2,3} | 2
/1000 | /2000 | 91 | {1,2,3} | 2
/2000 | /3000 | 99 | {1,2,3} | 1
Signification : Des leaseholders concentrés sur le nœud 2 signifient que le nœud 2 gère la « coordination » pour ces plages. Si le nœud 2 est plus lent, tout le monde est plus lent.
Décision : Pincez les leaseholders via des configurations de zone/localité, ou corrigez le disque/réseau/CPU du nœud 2 pour qu’il cesse d’être l’anneau d’humeur du cluster.
Task 14: Compare query latency distributions from the client side
cr0x@server:~$ pt-query-digest --type slowlog /var/log/mysql/mysql-slow.log | head -n 12
# 2.1s user time, 20ms system time, 28.11M rss, 100.00% CPU
# Query_time distribution
# 1us
# 10us
# 100us ################################################
# 1ms ###############################################
# 10ms ######
# 100ms ##
# 1s #
Signification : La distribution vous dit si vous avez un petit nombre de requêtes pathologiques lentes ou une dégradation de la queue plus large.
Décision : Peu pathologiques → corrections d’index/plan. Queue large → regardez stockage/réseau/contention de verrou et travail en arrière-plan.
Task 15: Check Linux scheduler and IRQ imbalance (small-node classic)
cr0x@server:~$ cat /proc/interrupts | egrep "eth0|nvme" | head -n 6
48: 18823401 0 0 0 IR-PCI-MSI 524288-edge eth0-TxRx-0
49: 0 0 0 0 IR-PCI-MSI 524289-edge eth0-TxRx-1
50: 0 0 0 0 IR-PCI-MSI 524290-edge eth0-TxRx-2
51: 0 0 0 0 IR-PCI-MSI 524291-edge eth0-TxRx-3
Signification : Si toutes les interruptions atterrissent sur un CPU (comme ci-dessus), vous pouvez obtenir une latence étrange sous charge même avec une utilisation CPU moyenne « basse ».
Décision : Activez irqbalance ou épinglez correctement les files ; pour les petits nœuds, cela peut faire la différence entre un p99 stable et le chaos.
Mode d’emploi pour un diagnostic rapide
Quand la latence pique, vous n’avez pas le temps pour la philosophie. Vous avez besoin d’une séquence courte qui trouve le goulot d’étranglement avec une forte probabilité.
Voilà le playbook que j’utilise quand quelqu’un dit « Cockroach est lent » ou « MySQL ralentit soudainement » sur des petits serveurs.
Première étape : est-ce le réseau, le disque ou la contention ?
-
Vérifier le RTT et les retransmissions entre nœuds (ping + ss).
Si le RTT/le jitter ou les retransmissions se corrèlent avec les pics de latence, arrêtez et réparez le réseau. -
Vérifier l’attente disque et l’utilisation (iostat).
Si les écritures font la queue (w_awaitélevé,%utilhaut), arrêtez et corrigez le stockage ou l’amplification d’écriture. -
Vérifier les réessais transactionnels / attentes de verrous (statistiques SQL Cockroach pour les réessais ; performance_schema ou InnoDB status pour MySQL).
Si les réessais/attentes montent, vous avez de la contention, pas du « hardware lent ».
Deuxième étape : confirmer que la topologie et la localité sont saines
- CockroachDB : placement des leaseholders pour les ranges chauds ; équilibre de distribution des ranges ; sous-réplication.
- MySQL : rôles primaire/réplica, latence de réplication, routage des lectures, et si le semi-sync est activé (ou désactivé) de manière inattendue.
Troisième étape : identifier le travail en arrière-plan qui vous vole le déjeuner
- CockroachDB : compactions, rééquilibrage de ranges, backfills de schéma. Sur petits nœuds, ils peuvent être bruyants.
- MySQL : purge lag, pression de checkpoint, longues transactions, ou un job de sauvegarde qui fait des E/S « polies » mais pas si polies que ça.
Conditions d’arrêt (aka éviter les réglages au hasard)
- Si
iostatmontre un await élevé, ne touchez pas aux réglages SQL tout de suite. - Si les retransmissions de paquets montent, ne refondez pas le schéma tout de suite.
- Si les réessais/attentes de verrous dominent, n’achetez pas de nouveau hardware avant de corriger le point chaud.
Trois mini-histoires du monde de l’entreprise (anonymisées, plausibles, techniquement exactes)
Mini-histoire 1 : L’incident causé par une mauvaise hypothèse
Une entreprise SaaS de taille moyenne a migré un service de profils utilisateur de MySQL vers CockroachDB. Le document d’architecture disait : « Nous avons besoin de HA ; un cluster trois nœuds nous le donne. »
L’équipe était intelligente, le code propre, et les répétitions de migration se sont bien passées — sur un environnement staging avec peu de charge et des voisins amicaux.
L’hypothèse qui a échoué : « Si chaque nœud est à moins de 30% CPU, nous avons suffisamment de marge. »
En production, la latence a grimpé après le lancement, mais le CPU est resté calme. L’ingénieur on-call a fixé les graphiques CPU comme s’ils allaient avouer quelque chose.
Entre-temps, les utilisateurs attendaient 200–600ms de plus pour la mise à jour de profils pendant les pics.
Le vrai goulot d’étranglement était la latence tail du stockage sur un nœud. Son SSD avait des pauses fsync longues occasionnelles.
MySQL avait masqué cela auparavant parce que le primaire était sur une autre machine, et le délai de réplication n’était pas perçu par l’utilisateur.
Dans CockroachDB, ce nœud faisait partie du quorum pour une grande part des ranges, donc ses pauses sont devenues des pauses de quorum.
La correction fut embarrassante et non liée à la base : remplacer le disque et rééquilibrer les leaseholders.
Ils ont aussi changé les règles d’achat : pas de « SSD mystère », et pas de classes de stockage mélangées à l’intérieur d’un cluster à consensus.
La leçon retenue : avec le SQL distribué, un seul nœud lent n’est pas « juste un peu plus lent ». Il devient la personnalité du cluster.
Mini-histoire 2 : L’optimisation qui s’est retournée contre eux
Une plateforme e‑commerce tournait MySQL avec réplication asynchrone. Le checkout était rapide, mais la direction voulait « plus de cohérence » pendant les pannes.
Quelqu’un a proposé d’activer la réplication semi-sync pour s’assurer qu’au moins un réplica accuse réception des écritures avant le commit.
Cela semblait une amélioration de sécurité gratuite. Ce ne l’était pas.
Ils ont activé semi-sync pendant une fenêtre de maintenance et n’ont vu qu’une augmentation modeste de la latence moyenne.
Une semaine plus tard, la première vraie perturbation réseau est arrivée : un switch top-of-rack a commencé à perdre des paquets de manière intermittente.
Le primaire a commencé à attendre les acks des réplicas qui arrivaient en retard ou pas du tout.
La latence n’a pas seulement augmenté. Elle est devenue piquée. Le trafic de checkout s’est accumulé, les pools de threads se sont saturés, puis la couche applicative a commencé à timeouter.
L’incident ressemblait à « la base est lente ». La cause racine était « le réseau est instable, et nous l’avons mis dans le chemin de commit ».
L’optimisation qui a mal tourné n’était pas semi-sync en soi ; c’était de l’activer sans valider la qualité du réseau est-ouest et sans ajuster les timeouts à la réalité.
Après l’incident, ils ont conservé semi-sync — mais seulement après avoir placé les réplicas sur un segment de réseau meilleur et défini un comportement clair quand semi-sync bascule.
La leçon : tout ce qui ajoute un accusé de réception au chemin de commit transforme des micro-coupures réseau en douleur visible par l’utilisateur. C’est vrai pour MySQL et c’est la valeur par défaut dans CockroachDB.
Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une équipe de services financiers utilisait CockroachDB sur des nœuds petits mais corrects. Le budget n’était pas infini, donc ils ont opté pour la discipline :
types d’instances stables, disques dédiés, et un calendrier strict de changements de schéma.
Leur pratique la moins glamour était aussi la plus précieuse : avant chaque release, ils exécutaient un « test d’acceptation de latence queue » fixe mesurant p95 et p99 sur un ensemble de transactions critiques,
tout en faisant tourner simultanément un job d’E/S en arrière-plan simulant des conditions bruyantes.
Un jour, le test a échoué. La latence médiane semblait correcte ; le p99 a doublé. Le changement ? Un nouvel index sur une table à fort trafic écrit accompagné d’un backfill qui a augmenté l’amplification d’écritures.
Les devs disaient que le code était correct, et ils avaient raison. Mais la correction en production inclut la physique.
Parce qu’ils avaient le test, ils l’ont détecté avant que les clients ne le subissent. Ils ont replanifié le backfill hors pic, ajusté les contraintes pour garder les leaseholders proches de la couche API,
et ajouté un throttling pour le job de migration.
La journée a été sauvée par une routine ennuyeuse et une refus de considérer le p99 comme « la métrique de quelqu’un d’autre ».
Erreurs courantes : symptômes → cause racine → correction
Ce sont les schémas qui apparaissent dans les canaux d’incident. Les symptômes se répètent ; les causes racines sont généralement ennuyeuses.
Les corrections sont spécifiques, pas inspirantes.
CockroachDB : pics de latence d’écriture p99 toutes les quelques minutes
- Symptômes : falaises de latence brèves, réessais de transaction, nœuds « sains » à première vue.
- Cause racine : compactions ou flushs de stockage concurrençant les écritures au premier plan ; ou un nœud avec une longue queue fsync.
- Correction : valider la queue fsync avec fio, réduire la saturation disque, utiliser un meilleur stockage, et s’assurer que les nœuds sont homogènes. Envisagez de séparer les charges et de dimensionner pour la marge de compaction.
CockroachDB : lectures inattendues lentes dans un cluster « une seule région »
- Symptômes : latence de lecture plus élevée que prévu, même pour des SELECT simples.
- Cause racine : leaseholders pas situés près de la passerelle SQL/tier applicatif ; requêtes rebondissant entre nœuds.
- Correction : inspecter la distribution des leaseholders, définir les contraintes de localité/zone, et router les connexions SQL de façon appropriée.
CockroachDB : l’application voit des échecs de sérialisation sporadiques
- Symptômes : erreurs retryable, temps de requête de bout en bout augmenté, échecs « aléatoires » sous charge.
- Cause racine : contention sur des lignes/ranges chauds ; transactions longues ; mises à jour de style compteur.
- Correction : repenser les points chauds (sharder les compteurs, batcher différemment), raccourcir les transactions, ajouter des index appropriés, et s’assurer que la logique de réessai client est correcte et bornée.
MySQL : réplicas en retard pendant les pics et qui ne rattrapent jamais
- Symptômes :
Seconds_Behind_Sourcequi monte, lectures retardées, basculements risqués. - Cause racine : requêtes lentes sur le réplica, apply parallèle insuffisant, DDL lourd, ou saturation I/O.
- Correction : optimiser les requêtes chaudes, activer/ajuster la réplication parallèle, isoler les réplicas pour les lectures, et planifier les DDL soigneusement.
MySQL : augmentation soudaine de la latence après « l’avoir rendu plus sûr »
- Symptômes : commits plus lents, timeouts applicatifs, CPU normal.
- Cause racine : activation de semi-sync ou réglages de durabilité plus stricts sans vérification de la latence tail réseau/disque.
- Correction : mesurer RTT et retransmissions, définir des timeouts sensés, placer les réplicas mieux, et décider explicitement des sémantiques de défaillance souhaitées.
Les deux : la latence moyenne est correcte, les utilisateurs se plaignent quand même
- Symptômes : tableaux de bord « verts », tickets support « lent parfois ».
- Cause racine : latence queue due à contention, GC/compaction, jobs en arrière-plan, ou jitter réseau.
- Correction : instrumenter et alerter sur p95/p99, corréler avec métriques disque/réseau, et faire de la latence queue un critère de sortie en production.
Listes de vérification / plan étape par étape
Checklist A : choisir MySQL vs CockroachDB pour petits serveurs
- Si vous avez besoin de p99 en millisecondes pour l’OLTP dans une seule localisation : commencez par MySQL sur un primaire solide. Ajoutez des réplicas pour les lectures et les sauvegardes. N’ayez pas honte.
- Si vous avez besoin d’un basculement automatique avec peu d’effort opérationnel et pouvez tolérer une prime de latence : CockroachDB est un choix raisonnable, mais dimensionnez disques et réseau comme s’ils comptaient (parce que c’est le cas).
- Si vous avez besoin de plusieurs écrivains sans sharder l’app : CockroachDB correspondra mieux. MySQL vous forcera à sharder ou à coordonner soigneusement.
- Si vos nœuds sont « minuscules » et le stockage médiocre : ne choisissez pas SQL distribué pour la performance. Choisissez-le pour la disponibilité et le comportement opérationnel, et acceptez la taxe.
- Si le business exige « pas de perte de données » : assurez-vous de ne pas compter sur la sémantique asynchrone de MySQL, et assurez-vous que votre cluster CockroachDB peut effectivement conserver un quorum en cas de panne.
Checklist B : faire bien se comporter CockroachDB sur petits nœuds
- Maintenez les nœuds aussi identiques que possible (CPU, RAM, type de disque, réglages kernel).
- Mesurez et contrôlez la queue fsync ; ne devinez pas.
- Surveillez les réessais transactionnels et la contention ; corrigez les points chauds au niveau du schéma et des patterns d’accès.
- Vérifiez la localité des leaseholders pour les ranges chauds ; ne supposez pas que la base « connaît » votre topologie applicative.
- Planifiez les changements de schéma et les backfills ; limitez-les ; traitez-les comme des événements de production.
- Laissez de la marge pour les compactions et le rééquilibrage. « 80% disque occupé » n’est pas de la marge.
Checklist C : rendre MySQL sûr sans détruire la latence
- Gardez
innodb_flush_log_at_trx_commit=1sauf si vous pouvez expliquer le risque en une phrase à un non‑ingénieur. - Définissez la cohérence nécessaire pour les lectures ; routez en conséquence (primaire vs réplicas).
- Entraînez-vous au basculement. Un runbook jamais exécuté est de la fiction.
- Surveillez le retard de réplication et définissez des seuils qui déclenchent une action opérationnelle, pas seulement un tableau de bord.
- Gardez les sauvegardes et restaurations banales et testées ; la réplication n’est pas une sauvegarde.
- Faites les changements de schéma en ligne avec des outils éprouvés et un plan de rollback.
FAQ
1) CockroachDB est‑il « plus lent » que MySQL ?
Sur petits serveurs pour de l’OLTP basse latence, souvent oui — surtout sur p95/p99 — parce que la réplication par quorum et les compactions LSM ajoutent un travail inévitable.
Sur des charges qui nécessitent une montée en charge horizontale des écritures ou un basculement automatisé, « plus lent par transaction » peut malgré tout être « plus rapide pour le business » parce que les pannes coûtent plus que des millisecondes.
2) Pourquoi la latence CockroachDB semble correcte en moyenne mais mauvaise au p99 ?
Parce que la latence queue est l’endroit où la coordination et le travail de stockage en arrière-plan se manifestent : fsync lent occasionnel, rafales de compaction, hiccups de répliques, jitter réseau et réessais.
Les médianes cachent cela ; les utilisateurs ne le sont pas.
3) Puis‑je rendre CockroachDB aussi rapide qu’un primaire MySQL mono‑nœud ?
Vous pouvez réduire l’écart avec du bon matériel, une configuration consciente de la localité et des corrections de contention. Vous ne pouvez pas enlever le quorum et prétendre aux mêmes sémantiques de défaillance.
Si vous avez besoin de la latence d’un nœud unique, exécutez une base mono‑nœud pour ce chemin.
4) Un cluster CockroachDB à trois nœuds suffit‑il ?
C’est le minimum pour une HA basée sur quorum, et ça fonctionne. C’est aussi fragile dans le sens où toute maintenance ou instabilité de nœud consomme immédiatement votre marge de sécurité.
Si vous le pouvez, cinq nœuds achètent de l’air opérationnel et souvent un meilleur comportement en queue.
5) Quelle est l’équivalence MySQL de la forte cohérence de CockroachDB ?
MySQL peut approcher une durabilité/cohérence plus forte en utilisant la réplication semi-sync ou group replication, mais vous changez le chemin de commit et prenez un coût en latence.
La différence clé est que CockroachDB est conçu autour de ce modèle ; MySQL peut le faire, mais c’est plus facile à mal configurer et plus dur à raisonner pendant les pannes.
6) Lequel est plus facile à exploiter avec une petite équipe ?
Si votre charge tient sur un primaire, MySQL est généralement plus simple au quotidien.
Si vous avez besoin d’un basculement automatisé et ne pouvez pas vous permettre des opérations HA manuelles, CockroachDB peut réduire la charge — à condition d’investir dans la mesure du disque/réseau et la compréhension de la contention.
7) CockroachDB requiert‑il du NVMe rapide ?
Il n’en a pas besoin pour fonctionner. Il en a besoin pour « bien » se comporter sous charge, surtout sur petits nœuds.
Un stockage lent ou avec du jitter se traduit en latence de validation quorum et en arrêts de compaction.
8) Puis‑je utiliser CockroachDB sur un réseau 1Gbps ?
Oui, mais vous devez surveiller les retransmissions et la congestion est‑ouest, et garder les nœuds proches (faible RTT, faible jitter).
Si votre réseau est partagé et rafaleux, votre p99 reflétera cette réalité.
9) Pourquoi les petits clusters semblent « corrects » jusqu’à ce que le trafic augmente un peu ?
Parce que la première ressource à manquer est la marge, pas le CPU. Le travail en arrière-plan et les effets de mise en file augmentent de façon non linéaire.
À petite échelle, le système a assez de temps idle pour cacher les péchés ; à échelle modérée, il commence à facturer les intérêts.
10) Si je suis déjà sur MySQL, quand devrais‑je migrer vers CockroachDB ?
Migrez quand votre douleur est principalement autour du basculement, de la croissance multi‑writer, de la fragilité opérationnelle, ou de la complexité du sharding et de la correction.
Ne migrez pas parce que vous voulez une base tendance. Si votre douleur principale est la latence des requêtes, un système distribué est une manière coûteuse d’acheter plus de latence.
Conclusion : que faire la semaine prochaine
Si vous êtes sur des petits serveurs et hésitez entre MySQL et CockroachDB, traitez cela comme une décision d’ingénierie, pas une décision de marque.
MySQL est la référence en latence. CockroachDB est la référence en disponibilité. Vous pouvez tuner les deux, mais vous ne pouvez pas renégocier leurs choix par défaut.
Prochaines étapes pratiques qui changent réellement les résultats :
- Mesurez le RTT et la queue fsync du disque sur vos nœuds réels. Si l’un ou l’autre est mauvais, corrigez‑le avant de changer de base.
- Choisissez votre modèle de vérité : réplication asynchrone (rapide, plus risquée) vs quorum/forte cohérence (plus sûre, plus lente). Écrivez‑le.
- Exécutez un test de charge axé p99 avec des E/S en arrière‑plan. Si vous ne testez pas les queues, vous les découvrirez en production.
- Si vous choisissez CockroachDB sur petits nœuds : investissez dans du matériel homogène, la conscience de localité/leaseholder, et le diagnostic de contention dès le premier jour.
- Si vous choisissez MySQL : investissez dans un basculement discipliné, la surveillance du retard de réplication, et des sauvegardes testées. Ne laissez pas le « simple » devenir « non entretenu ».
La taxe de latence n’est pas un frais caché. Elle est sur le reçu. Il vous suffit de regarder le p99 pour la voir.