MySQL vs MariaDB : latence de paiement WooCommerce — un réglage la corrige, l’autre la masque

Cet article vous a aidé ?

Le paiement devrait être ennuyeux. Cliquer sur « Passer la commande », le paiement est traité, le reçu arrive, tout le monde rentre chez soi. Quand le paiement prend 6–20 secondes (ou expire), ce n’est rarement « WordPress qui fait WordPress ». C’est généralement votre base de données qui fait exactement ce que vous lui avez demandé — juste pas ce que vous vouliez.

J’ai vu des équipes passer des semaines à basculer MySQL vers MariaDB (ou l’inverse), ajouter du CPU, mettre en cache des pages qui ne peuvent pas être cachées, et même accuser les passerelles de paiement. Puis un seul réglage InnoDB change et la latence disparaît. Le hic : il existe un autre réglage que les gens aiment modifier et qui ne fait que masquer le problème — jusqu’au jour où cela tourne en attentes corrompues et restaurations nocturnes.

À quoi ressemble vraiment la latence du paiement en production

La « latence » du paiement WooCommerce n’est presque jamais une seule chose. C’est un ensemble de petites étapes synchrones qui se transforment en un gros délai réel :

  • Totaux du panier et taxes recalculés.
  • Insertion de la ligne de commande (et parfois ré-mise à jour plusieurs fois).
  • Réductions de stock et insertions d’éléments de commande.
  • Mises à jour des métadonnées client/session.
  • Le plugin de paiement écrit des logs, ajoute des métadonnées, et effectue peut-être des appels distants.
  • Emails transactionnels mis en file ou envoyés.

Dans la base de données, cela devient une rafale courte d’écritures qui doivent être cohérentes. Si votre BD ne peut pas absorber cette rafale — parce que le redo log est trop petit, la latence fsync est élevée, les verrous s’accumulent, ou le buffer pool est sous-dimensionné — vous verrez :

  • TTFB élevé sur /checkout ou /?wc-ajax=checkout.
  • Pics de « Threads running ».
  • Attentes de verrou dans InnoDB.
  • Le CPU n’est pas forcément saturé (la BD attend l’I/O).
  • Les paiements aboutissent mais la page de confirmation se bloque (classique : le web attend le commit DB, la passerelle a déjà pris l’argent).

Cadre opérationnel : le paiement est votre chemin d’écriture. Votre chemin d’écriture est votre test de vérité. Les caches peuvent masquer beaucoup de choses ; ils ne peuvent pas cacher la latence de commit indéfiniment.

Les deux réglages : l’un corrige, l’autre masque

Le réglage qui corrige réellement la latence du paiement (la plupart du temps) : capacité du redo log

Quand les rafales d’écritures du paiement frappent InnoDB, le redo log est l’amortisseur. S’il est trop petit, InnoDB est forcé en checkpoints fréquents, vidant agressivement les pages modifiées. Cela transforme votre modèle « écrire et continuer » en « écrire, bloquer, vider, bloquer, checkpoint, bloquer ». Le paiement devient une file d’attente.

Approche MySQL 8+ (préférée) : ajuster innodb_redo_log_capacity.

Approche MariaDB et anciens MySQL : ajuster innodb_log_file_size (et innodb_log_files_in_group si applicable), en comprenant les implications opérationnelles.

Pourquoi c’est le réglage « correctif » : il réduit la pression des checkpoints forcés pendant les rafales d’écriture. Il ne triche pas sur la durabilité ; il permet simplement à InnoDB de regrouper le travail intelligemment.

Le réglage que les gens changent et qui masque surtout le problème : le basculement fsync/durabilité

Le placebo efficace est :

  • innodb_flush_log_at_trx_commit (réglé sur 2 ou 0)
  • parfois accompagné de sync_binlog mis bas (par exemple 0)

Oui, cela peut rendre le paiement plus rapide parce que vous cessez de payer le coût complet de fsync par transaction. Mais ce n’est pas une correction de performance ; c’est un compromis de durabilité. En cas de crash ou de coupure de courant, vous pouvez perdre des transactions commises (ou répliquer de manière inconsistante si la durabilité du binlog est aussi relâchée). Ce n’est pas du « tuning », c’est choisir quel type d’incident vous préférez.

Cas d’usage où c’est acceptable : environnements éphémères, boutiques non critiques, ou si vous avez explicitement conçu autour de ce compromis (cache sur batterie, alimentation fiable, et vous acceptez une petite fenêtre de perte).

Cas d’usage où cela vous mordra : tout ce qui implique de l’argent réel, du stock réel, des rétrofacturations ou des attentes réglementaires. Ce qui correspond à la plupart des boutiques WooCommerce qui font vivre des salariés.

Blague #1 : Mettre innodb_flush_log_at_trx_commit=0 revient à enlever votre ceinture de sécurité parce qu’elle froisse votre chemise.

À quoi ressemble « l’un corrige, l’autre masque » sur des graphiques

Quand la capacité du redo log est trop petite, vous verrez souvent :

  • Pics d’écritures disque et d’attente fsync.
  • L’âge du checkpoint InnoDB atteignant un plafond.
  • La latence du paiement corrélée avec le vidage en arrière-plan.

Quand vous « masquez » avec innodb_flush_log_at_trx_commit=2, vous verrez le p95 s’améliorer — mais vous n’avez pas traité la pression de vidage. Vous l’avez juste retardée et réduit la fréquence des fsync. Sous charge soutenue, les blocages reviennent sous une autre forme (ou apparaissent comme un retard de réplication, un temps de récupération prolongé, et des conversations désagréables).

MySQL vs MariaDB : où les différences comptent vraiment

Pour WooCommerce, la question n’est pas « lequel est plus rapide en général ». C’est « lequel échoue de manière plus prévisible sous ma charge, avec mes plugins, sur mon stockage ». MySQL et MariaDB partagent une ascendance mais ont divergé au point où « remplacement transparent » est du marketing, pas de l’ingénierie.

1) Journalisation redo et comportement des checkpoints : le point chaud barbant

MySQL 8 a introduit innodb_redo_log_capacity, qui est opérationnellement plus pratique que l’ancien rituel « arrêter le serveur, déplacer ib_logfile*, redémarrer ». MariaDB utilise encore communément innodb_log_file_size selon la version, et le chemin opérationnel peut être plus manuel.

En pratique, cela signifie que MySQL 8 facilite la bonne pratique : dimensionner les redo logs pour des rafales d’écriture sans planifier une fenêtre de maintenance que tout le monde « oublie » de programmer.

2) Gestion des threads sous concurrence : le pool de threads de MariaDB peut aider

MariaDB propose un pool de threads dans certaines builds/éditions qui peut stabiliser les performances quand vous avez beaucoup de connexions courtes. WooCommerce derrière PHP-FPM peut créer un motif de connexions turbulent si vous n’utilisez pas de connexions persistantes (et souvent vous ne devriez pas).

MySQL a aussi amélioré la gestion de la concurrence au fil du temps, mais si votre douleur est « trop de connexions/threads » plutôt que des blocages I/O, le thread pool de MariaDB peut être un gain pragmatique.

3) Optimiseur de requêtes et différences d’instrumentation : les outils influent sur les résultats

Quand vous diagnostiquez la latence du paiement, vous avez besoin d’une visibilité crédible sur les attentes, les verrous et les requêtes chaudes. Le performance schema et l’ergonomie du sys schema de MySQL 8 sont généralement excellents pour ce travail. L’instrumentation de MariaDB diffère ; vous devrez peut-être vous appuyer davantage sur information_schema, l’état du moteur et des slow logs ciblés.

4) Comportement de réplication et valeurs par défaut : ne présumez pas la parité

Si vous utilisez des réplicas pour la lecture ou le basculement, les différences dans les implémentations GTID, les formats de binlog et les réglages par défaut importent. Les réglages de durabilité qui « masquent » sont particulièrement dangereux : vous pouvez obtenir un paiement qui a « marché » sur le primaire mais qui n’a jamais été correctement enregistré dans le binlog avant un crash.

5) Le facteur décisif réel : votre stockage et la réalité fsync

Les deux moteurs peuvent être rapides sur un bon stockage et misérables sur un mauvais. Le NVMe avec une politique de cache d’écriture cohérente est un autre univers comparé à des disques en réseau à latence imprévisible. La latence du paiement est souvent l’histoire de fsync sur un disque triste.

Faits et historique intéressants qui expliquent l’étrangeté actuelle

  • Fait 1 : MariaDB a été forké depuis MySQL après qu’Oracle a racheté Sun, et la compatibilité a été « en grande partie » plutôt que « toujours ». C’est dans ce « en grande partie » que vivent les pannes.
  • Fait 2 : InnoDB n’était pas à l’origine « le moteur MySQL ». Il est devenu le défaut parce qu’il survit aux charges réelles : récupération après crash, verrouillage au niveau ligne, et transactions.
  • Fait 3 : L’ancien modèle de dimensionnement du redo log (taille du fichier × fichiers dans le groupe) explique pourquoi le modifier exigeait historiquement de supprimer/renommer ib_logfiles et de redémarrer. MySQL 8 a amélioré cela avec la gestion de la capacité redo.
  • Fait 4 : innodb_flush_log_at_trx_commit par défaut vaut 1 pour une raison : c’est le réglage durable. La pression de performance n’a pas changé la physique ; elle a juste incité davantage de gens à tricher.
  • Fait 5 : Les tables cœur de WooCommerce ont grossi avec le temps (order items, tables meta, tables d’analytics). Le pattern meta-table est flexible mais punis les lectures mal indexées et les écritures lourdes.
  • Fait 6 : Historiquement, WordPress utilisait MyISAM par défaut dans un passé ancien. Beaucoup de mythes « WordPress est lent » viennent de cette époque ; les goulots modernes sont différents et plus subtils.
  • Fait 7 : MariaDB a introduit Aria comme remplacement de MyISAM, mais WooCommerce ne devrait pas mélanger les moteurs pour des écritures transactionnelles de commande à moins d’aimer les bugs mystères.
  • Fait 8 : Le « query cache » était autrefois une fonctionnalité MySQL sur laquelle les gens comptaient. Il a disparu dans MySQL 8 car il créait de la contention. Si quelqu’un vous dit « activez le query cache », vous écoutez une histoire de fantôme.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Voici comment trouver le goulot sans passer trois jours à vous disputer avec un fournisseur de plugin.

Premier : confirmez que c’est une attente DB, pas PHP ou réseau

  • Mesurez le TTFB au niveau du load balancer / reverse proxy et comparez au temps de réponse upstream.
  • Vérifiez la saturation PHP-FPM (processus actifs, slowlog).
  • Si l’upstream est lent et que PHP n’est pas saturé, suspectez des attentes DB.

Deuxième : identifiez si vous êtes limité par l’I/O, par des verrous ou par le CPU

  • Limité par l’I/O : latence fsync élevée, vidage des pages sales, attentes InnoDB.
  • Limité par les verrous : temps d’attente de verrou, de nombreux threads en attente, lignes/tables chaudes (souvent wp_options ou meta de commande).
  • Limité par le CPU : CPU élevé, requêtes lourdes, index manquants, tris/tablaux temporaires volumineux.

Troisième : corrigez la chose qui retire la file d’attente

  • Si I/O-bound et redo log petit : augmentez la capacité redo (le vrai correctif).
  • Si lock-bound : réduisez la contention de verrou (index, portée des transactions, comportement des plugins).
  • Si CPU-bound : optimisez les requêtes, les index et le buffer pool ; stoppez la requête qui fait un scan de table au moment du paiement.

Puis — et seulement alors — considérez des compromis de durabilité ou des changements de moteur.

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

Tout ce qui suit est conçu pour être exécutable sur un hôte Linux typique avec MySQL/MariaDB. Remplacez socket/identifiants selon le besoin. Chaque tâche inclut : commande, sortie exemple, ce que cela signifie, et la décision à prendre.

Task 1: Confirm server version and vendor (don’t guess)

cr0x@server:~$ mysql --version
mysql  Ver 8.0.36 for Linux on x86_64 (MySQL Community Server - GPL)

Signification : Vous êtes sur MySQL 8.0. Le tuning du redo log utilise innodb_redo_log_capacity.

Décision : Ne suivez pas des conseils spécifiques à MariaDB (configs thread pool, tables de statut différentes) sans vérifier les équivalents.

Task 2: Verify the active durability settings (spot the “mask”)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES WHERE Variable_name IN ('innodb_flush_log_at_trx_commit','sync_binlog');"
innodb_flush_log_at_trx_commit	1
sync_binlog	1

Signification : Valeurs durables complètes par défaut. Bon pour l’argent réel. Cela signifie aussi que les coûts fsync sont réels et doivent être traités par un I/O et un dimensionnement redo appropriés.

Décision : Gardez cela à 1 sauf si vous avez un modèle de risque écrit et des comportements de crash testés.

Task 3: Measure connection and concurrency pressure

cr0x@server:~$ mysql -Nse "SHOW GLOBAL STATUS LIKE 'Threads_running'; SHOW GLOBAL STATUS LIKE 'Threads_connected';"
Threads_running	18
Threads_connected	120

Signification : 18 threads activement en exécution n’est pas insensé, mais 120 connexions suggère du churn de connexion ou une forte concurrence web.

Décision : Si Threads_running augmente pendant les rafales de paiement, corrélez avec les attentes de verrou et les attentes I/O ensuite.

Task 4: Check InnoDB buffer pool sizing (are you reading from RAM?)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
innodb_buffer_pool_size	4294967296

Signification : Buffer pool de 4 GiB. Sur une boutique avec un trafic substantiel et de grandes tables meta, cela peut être trop petit.

Décision : Si l’hôte a de la RAM disponible, ciblez 60–75% de la mémoire système pour des hôtes DB dédiés (moins sur des hôtes partagés).

Task 5: Check redo log capacity / size (the “fix” lever)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'innodb_redo_log_capacity';"
innodb_redo_log_capacity	104857600

Signification : Capacité redo de 100 MiB. Pour des workloads transactionnels rafaleux, c’est souvent comiquement petit.

Décision : Augmentez à quelque chose de sensé (souvent 1–4 GiB selon le débit d’écriture et la tolérance de récupération). Validez l’espace disque et les attentes de temps de récupération.

Task 6: Observe checkpoint and flushing pressure

cr0x@server:~$ mysql -e "SHOW ENGINE INNODB STATUS\G" | sed -n '1,120p'
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
=====================================
2025-12-29 09:17:21 0x7f3b3c0  INNODB MONITOR OUTPUT
=====================================
...
Log sequence number          112233445566
Log flushed up to            112233440000
Pages flushed up to          112233000000
Last checkpoint at           112232900000
...
Modified db pages            84210
...
Pending flushes (fsync) log: 0; buffer pool: 37

Signification : Beaucoup de pages modifiées et des flushes de buffer pool en attente indiquent que le flusher en arrière-plan est occupé. Si cela monte pendant le paiement, vous êtes contraint par l’I/O/redo.

Décision : Augmentez la capacité redo et assurez-vous que votre stockage peut gérer des écritures soutenues ; envisagez d’ajuster innodb_io_capacity seulement après mesure du disque.

Task 7: Check for lock waits and deadlocks during checkout spikes

cr0x@server:~$ mysql -Nse "SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_time'; SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';"
Innodb_row_lock_time	98342
Innodb_row_lock_waits	217

Signification : Des attentes de verrou existent. Pas forcément catastrophique, mais si cela saute pendant le paiement, vous avez de la contention.

Décision : Identifiez les tables/requêtes chaudes (tâches suivantes). Si les attentes de verrou corrèlent avec des mises à jour autoload de wp_options ou des mises à jour de stock, corrigez les index/portée des transactions.

Task 8: Find the top slow queries (use the slow log, not vibes)

cr0x@server:~$ mysql -Nse "SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'long_query_time';"
slow_query_log	ON
long_query_time	1.000000

Signification : Slow query log activé, seuil 1s. Bien — les problèmes de paiement cachent souvent quelques requêtes à 2–5s.

Décision : Si c’est désactivé, activez-le temporairement et capturez une fenêtre de paiement. Ne travaillez pas à l’aveugle.

Task 9: Inspect disk latency and confirm the fsync reality

cr0x@server:~$ iostat -x 1 3
Linux 6.5.0 (server) 	12/29/2025 	_x86_64_	(8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.50    0.00    6.25   18.75    0.00   62.50

Device            r/s     w/s   rkB/s   wkB/s  await  svctm  %util
nvme0n1         45.0   220.0  2200.0  9800.0   9.80   0.35  85.00

Signification : await ~10ms avec forte utilisation et iowait ~19%. Pour une BD transactionnelle occupée, 10ms en moyenne peut déjà être pénible. Si cela monte pendant les rafales de paiement, vous le ressentirez.

Décision : Si await est élevé : corrigez le stockage (NVMe, politique de cache du contrôleur RAID, système de fichiers, voisin bruyant) avant de blâmer le moteur SQL.

Task 10: Check for table bloat and missing indexes on WooCommerce hotspots

cr0x@server:~$ mysql -e "SELECT table_name, engine, table_rows, round((data_length+index_length)/1024/1024,1) AS MB FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name IN ('wp_postmeta','wp_options','wp_woocommerce_order_items','wp_woocommerce_order_itemmeta') ORDER BY MB DESC;"
+------------------------------+--------+------------+--------+
| table_name                   | engine | table_rows | MB     |
+------------------------------+--------+------------+--------+
| wp_postmeta                  | InnoDB |    8200000 | 2150.4 |
| wp_options                   | InnoDB |      98000 |  210.7 |
| wp_woocommerce_order_itemmeta| InnoDB |    2400000 |  640.9 |
| wp_woocommerce_order_items   | InnoDB |     310000 |   96.2 |
+------------------------------+--------+------------+--------+

Signification : Grosses tables meta. C’est normal. La question est de savoir si les requêtes qui les frappent sont indexées et si wp_options a un autoload surchargé.

Décision : Planifiez une revue d’index et un nettoyage des options. Les grosses tables ne sont pas un crime ; les accès non indexés le sont.

Task 11: Detect autoload bloat (a quiet checkout killer)

cr0x@server:~$ mysql -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
+-------------+
| autoload_mb |
+-------------+
|       18.74 |
+-------------+

Signification : ~19 MiB autoloadés à chaque requête. C’est lourd ; cela augmente le churn mémoire et le temps de requête, et peut amplifier la contention de verrou si les options sont souvent mises à jour.

Décision : Réduisez l’autoload. Identifiez les coupables ; déplacez les caches transitoires hors de l’autoload ; auditez les plugins qui stockent de gros tableaux dans options.

Task 12: Find which options are the offenders

cr0x@server:~$ mysql -e "SELECT option_name, ROUND(LENGTH(option_value)/1024,1) AS kb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 10;"
+---------------------------+--------+
| option_name               | kb     |
+---------------------------+--------+
| plugin_x_cache_blob       | 2048.0 |
| woocommerce_sessions      | 1536.0 |
| theme_builder_settings    |  980.4 |
| plugin_y_rules            |  620.7 |
| rewrite_rules             |  410.2 |
| cron                      |  350.1 |
| widget_text               |  290.5 |
| wp_user_roles             |  210.3 |
| plugin_z_feed_state       |  185.9 |
| woocommerce_tax_rates     |  160.4 |
+---------------------------+--------+

Signification : Certains plugins stockent des mégaoctets en autoload. Ce n’est pas « WordPress » ; c’est quelqu’un qui utilise la table options comme poubelle.

Décision : Changez autoload en ‘no’ là où c’est sûr, ou ajustez les réglages du plugin. Validez le comportement en staging.

Task 13: Verify binary log format and durability for transactional safety

cr0x@server:~$ mysql -Nse "SHOW VARIABLES WHERE Variable_name IN ('log_bin','binlog_format','sync_binlog');"
log_bin	ON
binlog_format	ROW
sync_binlog	1

Signification : Compatible réplication et durable. Le binlog en mode row réduit les surprises de réplication pour des écritures complexes.

Décision : Si quelqu’un propose sync_binlog=0 pour « réparer le paiement », demandez quel est leur plan de restauration si le binlog ne contient pas les commandes « payées ».

Task 14: Identify top wait events (MySQL 8 performance schema)

cr0x@server:~$ mysql -e "SELECT event_name, COUNT_STAR, ROUND(SUM_TIMER_WAIT/1000000000000,2) AS seconds_waited FROM performance_schema.events_waits_summary_global_by_event_name WHERE event_name LIKE 'wait/io/file/innodb/%' ORDER BY SUM_TIMER_WAIT DESC LIMIT 8;"
+------------------------------------------+------------+----------------+
| event_name                               | COUNT_STAR | seconds_waited |
+------------------------------------------+------------+----------------+
| wait/io/file/innodb/innodb_redo          |   18422091 |          812.34|
| wait/io/file/innodb/innodb_data_file     |    3922011 |          244.12|
| wait/io/file/innodb/innodb_log_file      |    1200099 |          120.44|
| wait/io/file/innodb/innodb_temp_file     |      22011 |           11.02|
+------------------------------------------+------------+----------------+

Signification : Les attentes redo dominent. C’est une flèche clignotante vers le dimensionnement redo et la latence disque.

Décision : Augmentez la capacité redo et recontrôlez. Si les attentes redo persistent, le stockage/fsync est le suspect suivant.

Task 15: Capture a real-time view during a checkout test

cr0x@server:~$ mysqladmin -i 1 -c 5 processlist status
Uptime: 123456  Threads: 125  Questions: 9933221  Slow queries: 18  Opens: 322  Flush tables: 1  Open tables: 256  Queries per second avg: 80.50
Id: 31142  User: wp   Host: 10.0.2.15:43218  db: shop  Command: Query  Time: 3  State: Waiting for handler commit  Info: UPDATE wp_postmeta SET meta_value='...'
Id: 31151  User: wp   Host: 10.0.2.15:43222  db: shop  Command: Query  Time: 3  State: Waiting for handler commit  Info: INSERT INTO wp_posts ...
Uptime: 123457  Threads: 128  Questions: 9933310  Slow queries: 18  Opens: 322  Flush tables: 1  Open tables: 256  Queries per second avg: 92.10

Signification : « Waiting for handler commit » est un signe classique de pression de commit/fsync (pas toujours, mais souvent). Si les requêtes de paiement restent bloquées ici, vous payez la latence du stockage au moment du commit.

Décision : Ne jetez pas des caches sur ce problème. Corrigez le chemin d’écriture : capacité redo, latence du stockage, et comportement de flush.

Trois mini-récits d’entreprise depuis les tranchées du paiement

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

Une entreprise de taille moyenne a migré une stack WooCommerce de MySQL vers MariaDB parce que « c’est un remplaçant transparent et plus rapide ». Le plan de migration était propre sur le papier : dump, import, basculer les endpoints, terminé. Ils ont fait un test de navigation rapide, exécuté quelques commandes en staging, et déployé un mardi tranquille.

Le paiement a semblé correct pendant un jour. Puis une newsletter marketing est partie et le site a pris une forme de trafic familière : beaucoup de navigation, puis une forte rafale de paiements sur 10–15 minutes. Les commandes ont commencé à expirer, mais les autorisations de paiement se faisaient toujours. Les tickets support sont arrivés : « On m’a débité mais pas de confirmation. » Vous savez déjà où ça mène.

La mauvaise hypothèse n’était pas « MariaDB est mauvais ». C’était « le changement de moteur va résoudre la latence ». Le vrai problème était la latence du stockage au fsync plus des redo logs trop petits. La nouvelle BD se comportait suffisamment différemment pour que les blocages paraissent nouveaux, mais la physique était la même. Ils faisaient simplement des checkpoints constamment sous pression.

Ils se sont stabilisés en augmentant correctement la taille des redo logs et en ajustant la capacité I/O pour le périphérique. Puis ils ont comblé le manque opérationnel : tests de charge incluant des rafales de paiement, pas seulement des hits sur la page d’accueil. Personne n’a apprécié la semaine, mais la boutique a arrêté de débiter les clients dans le vide.

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

Une agence SaaS gérant plusieurs boutiques WooCommerce par nœud avait une plainte récurrente : « le paiement est lent en période de pointe ». Quelqu’un a remarqué que innodb_flush_log_at_trx_commit était réglé à 1 et a décidé que c’était « trop strict ». Ils l’ont passé à 2 sur toute la flotte pendant une fenêtre de maintenance. La latence s’est améliorée immédiatement. Hauts les cœurs.

Deux mois plus tard, un hôte a redémarré brutalement après un panic du noyau. Une boutique a signalé des commandes manquantes : des clients avaient reçu des reçus du fournisseur de paiement, mais les commandes n’étaient pas dans WooCommerce. L’équipe a d’abord accusé le plugin de paiement. Puis ils ont trouvé un trou : des transactions qui avaient été reconnues côté application n’étaient pas garanties d’avoir leur redo flushé au moment du crash. Certaines écritures n’ont tout simplement jamais atteint le stockage stable.

Ils avaient troqué la performance pour une fenêtre réelle de perte de données. Ce n’est pas toujours catastrophique. C’est catastrophique exactement quand ça compte : quand le serveur meurt au mauvais milliseconde. Les serveurs finissent par le faire, avec un timing admirablement mauvais.

La correction n’a pas été « ne jamais tuner la durabilité ». La correction a été d’arrêter d’utiliser la relaxation de durabilité comme béquille de performance. Ils sont revenus à 1, ont augmenté la capacité redo, et ont migré les boutiques les plus critiques vers un meilleur stockage. Le paiement est resté suffisamment rapide, et les « commandes payées manquantes » ont cessé d’exister.

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

Une équipe d’entreprise faisait tourner WooCommerce comme « activité annexe » sur une plateforme partagée avec d’autres apps. Rien d’excitant, ce qui est exactement ce qu’on veut. Leur SRE lead insistait sur deux pratiques ennuyeuses : garder le slow query log activé (avec rotation correcte) et faire un topo hebdomadaire des « top 10 queries ». Pas d’héroïsme, juste de l’hygiène.

Un vendredi, la latence du paiement a grimpé. Pas une panne sévère — juste le genre de lenteur qui tue la conversion pendant que personne n’alerte. Parce que le slow log était déjà en place, ils n’ont pas eu à « activer le logging pendant l’incident », ce qui est la version opérationnelle d’apprendre à nager pendant une crue.

Le slow log montrait un nouveau motif de requête martelant wp_options avec un scan complet. Une mise à jour de plugin avait introduit une requête qui contournait un accès index-friendly et tournait pendant le paiement. Ils ont rollbacké le plugin, ajouté un index ciblé où approprié et ouvert un ticket fournisseur avec des preuves.

Le paiement s’est rétabli en moins d’une heure. Pas d’échange de base de données, pas de tricherie sur la durabilité, pas d’ajout de serveurs. Juste la compétence terne d’avoir des données quand il le faut.

Erreurs courantes : symptôme → cause racine → correctif

1) Symptom: Checkout p95 jumps during traffic bursts; CPU is fine

Cause racine : Checkpointing forcé d’InnoDB dû à des redo logs trop petits ; la pression de vidage disque crée des blocages.

Correctif : Augmenter innodb_redo_log_capacity (MySQL 8) ou innodb_log_file_size (MariaDB/anciens MySQL). Valider la latence de stockage avec iostat.

2) Symptom: “Waiting for handler commit” dominates processlist

Cause racine : Latence de commit/fsync (stockage dégradé, périphérique saturé, ou trop de petits commits).

Correctif : Améliorer le stockage, garder les réglages durables à 1, augmenter la capacité redo ; réduire le nombre de transactions quand c’est possible (comportement des plugins).

3) Symptom: Lock wait timeouts around checkout

Cause racine : Lignes/tables chaudes (lignes de stock, options, tables de session), transactions longues, index manquants.

Correctif : Identifier les requêtes bloquantes ; ajouter des index ; réduire la portée des transactions ; corriger les plugins qui gardent les transactions ouvertes pendant des appels distants.

4) Symptom: Swapping MySQL ↔ MariaDB “helps” but doesn’t solve it

Cause racine : Le changement de moteur a modifié un comportement par défaut mais n’a pas corrigé les problèmes d’I/O et de schéma sous-jacents.

Correctif : Traitez le moteur DB comme un choix, pas comme un remède. Corrigez d’abord le dimensionnement redo, le buffer pool, le stockage et les points chauds.

5) Symptom: Checkout slow only after installing “performance” plugin

Cause racine : Le plugin ajoute du logging synchrone, des options autoload excessives, ou exécute des requêtes lourdes sur les hooks de paiement.

Correctif : Désactivez le plugin pour confirmer ; déplacez le logging en async ; nettoyez l’autoload ; profilez les requêtes pendant le paiement.

6) Symptom: Replica lag spikes when checkouts spike

Cause racine : Le primaire est contraint par l’I/O ; réglages de flush du binlog ; la réplica applique lentement de grosses transactions.

Correctif : Corrigez d’abord le chemin d’écriture du primaire ; vérifiez sync_binlog=1 ; assurez-vous que le stockage des réplicas est comparable ; surveillez le lag d’application.

Checklists / step-by-step plan

Step-by-step: fix checkout lag without gambling your data

  1. Latence de référence : capturez p50/p95 pour le point de terminaison checkout et les indicateurs de temps de commit DB.
  2. Confirmez le moteur/version : MySQL 8 vs MariaDB change les commandes et les tableaux de bord.
  3. Mesurez la latence du stockage : vérifiez iostat -x pendant une rafale de test checkout contrôlée.
  4. Inspectez le dimensionnement redo : si le redo est <1 GiB sur une vraie boutique, supposez qu’il est sous-dimensionné jusqu’à preuve du contraire.
  5. Augmentez la capacité redo en sécurité : MySQL 8 le fait plus facilement ; planifiez une maintenance pour MariaDB/anciennes versions si nécessaire.
  6. Gardez la durabilité raisonnable : laissez innodb_flush_log_at_trx_commit=1 sauf si vous avez un modèle de risque écrit et testé.
  7. Vérifiez le buffer pool : assurez-vous que le working set chaud tient en mémoire ; évitez le swap.
  8. Trouvez les hotspots de verrou : utilisez InnoDB status, lock waits et processlist pendant le paiement.
  9. Nettoyez l’autoload bloat : réduisez les Mo autoloadés ; c’est un fruit facile avec un impact disproportionné.
  10. Indexez ce que le paiement touche : en particulier les accès postmeta et order meta utilisés par les plugins.
  11. Validez sous charge rafale : ne testez pas avec une commande ; testez avec 20–50 checkouts sur une courte fenêtre.
  12. Déployez prudemment : une boutique/nœud à la fois, surveillez les métriques, puis étendez.

When you should choose MySQL vs MariaDB for WooCommerce

  • Choisissez MySQL 8 si vous souhaitez une instrumentation intégrée robuste, une gestion moderne des redo et une compatibilité large avec les plateformes managées.
  • Choisissez MariaDB si votre plateforme standardise dessus, si vous bénéficiez de ses fonctionnalités de thread pool/concurrence, et si votre équipe opérationnelle connaît bien ses spécificités.
  • Évitez de changer comme « correction de performance » sauf si vous pouvez nommer le mécanisme exact que vous espérez améliorer (et comment vous le mesurerez).

Blague #2 : « Changeons de base de données » est la version adulte d’éteindre et rallumer l’écran parce que le tableau semble faux.

One quote you should tattoo on your runbook (mentally)

Paraphrase d’une idée de John Allspaw : la fiabilité est une fonctionnalité, et on ne l’obtient pas par accident.

FAQ

1) Is MariaDB faster than MySQL for WooCommerce?

Parfois, dans des scénarios de concurrence spécifiques. Mais la latence du paiement est plus souvent due à l’I/O et à la pression redo/checkpoint qu’à la vitesse brute des requêtes. Choisissez selon l’adéquation opérationnelle et l’observabilité, pas selon le folklore.

2) What’s the single most common real fix for checkout lag?

Augmenter la capacité/taille du redo log pour qu’InnoDB cesse de se checkpoint-er jusqu’à la mort pendant les rafales d’écriture. Puis confirmer que la latence du stockage est raisonnable.

3) Why not just set innodb_flush_log_at_trx_commit=2?

Parce que c’est un compromis de durabilité. Ça peut perdre des transactions récemment commises en cas de crash. Ce n’est pas théorique ; c’est exactement ce que signifie ce réglage.

4) How big should redo logs be?

Il n’y a pas de chiffre unique. Pour beaucoup de boutiques WooCommerce avec du vrai trafic, 1–4 GiB est une plage de départ courante. Vous balancez : moins de blocages vs temps de récupération plus long. Mesurez avant et après.

5) If my CPU is low, why is checkout slow?

Parce que la BD peut attendre l’I/O (fsync, écritures de fichiers de données) ou des verrous. Les graphiques CPU n’affichent pas bien les attentes ; le performance schema et les métriques I/O le font.

6) Can autoloaded options really affect checkout?

Oui. L’autoload bloat augmente le travail par requête, le churn mémoire, et peut créer de la contention si les options sont fréquemment mises à jour. C’est un classique « mort par commodité ».

7) Should I put WooCommerce tables on MyISAM/Aria for speed?

Non. Le paiement est transactionnel. Vous voulez la récupération après crash et le verrouillage au niveau ligne. Si vous échangez cela contre un benchmark, la production accumulera la dette avec intérêt.

8) Do I need a query cache to speed up WooCommerce?

Non. MySQL 8 l’a supprimé. Utilisez des index appropriés, un dimensionnement du buffer pool, et un cache côté application là où il a du sens (pas sur le paiement).

9) What if increasing redo capacity doesn’t help?

Alors votre goulot est probablement la latence du stockage, la contention de verrous, ou une voie de requête lente spécifique pendant le paiement (souvent induite par un plugin). Utilisez les résumés d’attente et les slow logs pour le localiser.

10) Should I move to a managed database service?

Si votre contrainte actuelle est « nous ne savons pas gérer le stockage et les sauvegardes de manière fiable », oui — les services managés peuvent éliminer beaucoup de modes de panne. Mais ils ne corrigeront pas magiquement de mauvais schémas ou le comportement de plugins.

Prochaines étapes que vous pouvez faire aujourd’hui

  1. Exécutez les vérifications de version et de durabilité. Confirmez que vous ne « masquez » pas déjà le problème.
  2. Mesurez la latence disque pendant une petite rafale de test checkout. Si await est moche, corrigez d’abord le stockage.
  3. Vérifiez la capacité/taille des redo logs. Si c’est minuscule, augmentez-la prudemment et surveillez la pression des checkpoints.
  4. Mesurez les attentes de verrou et inspectez l’autoload bloat dans wp_options. Nettoyez les principaux coupables.
  5. Activez/vérifiez le slow query logging et capturez une fenêtre de paiement. Corrigez ce qui est réellement lent, pas ce qui est à la mode.

Si vous ne faites qu’une chose : cessez de traiter les réglages de durabilité comme du tuning de performance. Dimensionnez les redo logs, vérifiez le disque, et rendez le paiement ennuyeux à nouveau.

← Précédent
Roulette des mises à jour du BIOS : le clic le plus courageux de l’informatique
Suivant →
Prise en charge du mouvement réduit : prefers-reduced-motion bien implémenté

Laisser un commentaire