La réplication dans MySQL existe depuis longtemps et n'a cessé de s'améliorer au fil des ans. Cela ressemble plus à une évolution qu'à une révolution. C'est parfaitement compréhensible, car la réplication est une fonctionnalité importante dont beaucoup dépendent - elle doit fonctionner.
Dans les dernières versions de MySQL, nous avons constaté des améliorations des performances de réplication grâce à la prise en charge de l'application de transactions en parallèle. Dans MySQL 5.6, la parallélisation était effectuée au niveau du schéma - toutes les transactions exécutées dans des schémas séparés pouvaient être exécutées en même temps. C'était une belle amélioration pour les charges de travail qui avaient plusieurs schémas sur un seul serveur, et la charge était répartie plus ou moins uniformément sur les schémas.
Dans MySQL 5.7, une autre méthode de parallélisation a été ajoutée, appelée "horloge logique". Cela permettait d'obtenir un certain niveau de concurrence sur un esclave, même si toutes vos données ont été stockées dans un seul schéma. Il était basé, en bref, sur le fait que certaines transactions s'engageraient ensemble en raison d'une latence ajoutée par le matériel. Vous pouvez même ajouter cette latence manuellement, pour obtenir une meilleure parallélisation sur les esclaves en utilisant binlog_group_commit_sync_delay.
Cette solution était vraiment sympa mais pas sans inconvénients. Chaque retard dans la validation d'une transaction pourrait éventuellement affecter les parties de l'application destinées à l'utilisateur. Bien sûr, vous pouvez définir des délais dans une plage de plusieurs millisecondes, mais même dans ce cas, c'est une latence supplémentaire qui ralentit l'application.
Améliorations des performances de réplication dans MySQL 8.0
MySQL 8.0, qui à ce jour (août 2017) est encore en version bêta, apporte de belles améliorations à la réplication. À l'origine, il a été développé pour la réplication de groupe (GR), mais comme GR utilise une réplication régulière sous le capot, la réplication MySQL "normale" en a bénéficié. L'amélioration que nous avons mentionnée concerne les informations de suivi des dépendances stockées dans le journal binaire. Ce qui se passe, c'est que MySQL 8.0 a maintenant un moyen de stocker des informations sur les lignes qui ont été affectées par une transaction donnée (ce qu'on appelle le jeu d'écriture), et il compare les jeux d'écriture de différentes transactions. Cela permet d'identifier les transactions qui n'ont pas fonctionné sur le même sous-ensemble de lignes et, par conséquent, celles-ci peuvent être appliquées en parallèle. Cela peut permettre d'augmenter le niveau de parallélisation de plusieurs fois par rapport à l'implémentation de MySQL 5.7. Ce que vous devez garder à l'esprit, c'est que, finalement, un esclave verra une vue différente des données, une vue qui n'est jamais apparue sur le maître. En effet, les transactions peuvent être appliquées dans un ordre différent de celui sur le maître. Cela ne devrait pas être un problème cependant. L'implémentation actuelle de la réplication multithread dans MySQL 5.7 peut également causer ce problème, sauf si vous activez explicitement slave-preserve-commit-order.
Pour contrôler ce nouveau comportement, une variable binlog_transaction_dependency_tracking a été introduit. Il peut prendre trois valeurs :
- COMMIT_ORDER :c'est celui par défaut, il utilise le mécanisme par défaut disponible dans MySQL 5.7.
- WRITSET :cela permet une meilleure parallélisation et le maître commence à stocker les données du jeu d'écriture dans un journal binaire.
- WRITSET_SESSION :Cela garantit que les transactions seront exécutées sur l'esclave dans l'ordre et le problème avec un esclave qui voit un état de la base de données qui n'a jamais été vu sur le maître est éliminé. Il réduit la parallélisation, mais il peut toujours fournir un meilleur débit que les paramètres par défaut.
Référence
En juillet, sur mysqlhighavailability.com, Vitor Oliveira a écrit un post où il tentait de mesurer les performances des nouveaux modes. Il a utilisé le meilleur scénario - aucune durabilité, pour montrer la différence entre les anciens et les nouveaux modes. Nous avons décidé d'utiliser la même approche, cette fois dans une configuration plus réelle :journal binaire activé avec log_slave_updates. Les paramètres de durabilité ont été laissés par défaut (donc, sync_binlog=1 - c'est la nouvelle valeur par défaut dans MySQL 8.0, tampon en double écriture activé, sommes de contrôle InnoDB activées, etc.) La seule exception en matière de durabilité était innodb_flush_log_at_trx_commit défini sur 2.
Nous avons utilisé des instances m4.2xl, 32G, 8 cœurs (donc slave_parallel_workers a été défini sur 8). Nous avons également utilisé sysbench, le script oltp_read_write.lua. 16 millions de lignes dans 32 tables ont été stockées sur un volume gp2 de 1000 Go (soit 3000 IOPS). Nous avons testé les performances de tous les modes pour 1, 2, 4, 8, 16 et 32 connexions sysbench simultanées. Le processus était le suivant :arrêtez l'esclave, exécutez 100 000 transactions, démarrez l'esclave et calculez le temps nécessaire pour effacer le décalage de l'esclave.
Tout d'abord, nous ne savons pas vraiment ce qui s'est passé lorsque sysbench a été exécuté en utilisant 1 seul thread. Chaque test a été exécuté cinq fois après une course d'échauffement. Cette configuration particulière a été testée deux fois - les résultats sont stables :la charge de travail monothread était la plus rapide. Nous allons l'examiner plus en détail pour comprendre ce qui s'est passé.
A part cela, le reste des résultats est conforme à ce que nous attendions. COMMIT_ORDER est le plus lent, en particulier pour un faible trafic, 2 à 8 threads. WRITSET_SESSION fonctionne généralement mieux que COMMIT_ORDER, mais il est plus lent que WRITSET pour un faible trafic simultané.
Comment cela peut-il m'aider ?
Le premier avantage est évident :si votre charge de travail est lente mais que vos esclaves ont tendance à se replier dans la réplication, ils peuvent bénéficier de performances de réplication améliorées dès que le maître sera mis à niveau vers la version 8.0. Deux remarques ici :premièrement, cette fonctionnalité est rétrocompatible et les esclaves 5.7 peuvent également en bénéficier. Deuxièmement - un rappel que 8.0 est toujours en version bêta, nous ne vous encourageons pas à utiliser le logiciel bêta en production, bien qu'en cas de besoin urgent, il s'agit d'une option à tester. Cette fonctionnalité peut vous aider non seulement lorsque vos esclaves sont à la traîne. Ils peuvent être complètement rattrapés, mais lorsque vous créez un nouvel esclave ou réapprovisionnez un esclave existant, cet esclave sera en retard. Avoir la possibilité d'utiliser le mode "WRITSET" rendra le processus de provisionnement d'un nouvel hôte beaucoup plus rapide.
Dans l'ensemble, cette fonctionnalité aura un impact beaucoup plus important que vous ne le pensez. Compte tenu de tous les benchmarks montrant des régressions de performances lorsque MySQL gère un trafic à faible simultanéité, tout ce qui peut aider à accélérer la réplication dans de tels environnements est une énorme amélioration.
Si vous utilisez des maîtres intermédiaires, c'est également une fonctionnalité à rechercher. Tout maître intermédiaire ajoute une certaine sérialisation dans la façon dont les transactions sont gérées et exécutées - dans le monde réel, la charge de travail sur un maître intermédiaire sera presque toujours moins parallèle que sur le maître. L'utilisation de jeux d'écriture pour permettre une meilleure parallélisation améliore non seulement la parallélisation sur le maître intermédiaire, mais peut également améliorer la parallélisation sur tous ses esclaves. Il est même possible (bien que cela nécessiterait des tests sérieux pour vérifier que toutes les pièces correspondent correctement) d'utiliser un maître intermédiaire 8.0 pour améliorer les performances de réplication de vos esclaves (veuillez garder à l'esprit que l'esclave MySQL 5.7 peut comprendre les données du jeu d'écriture et les utiliser même si il ne peut pas le générer tout seul). Bien sûr, la réplication de 8.0 à 5.7 semble assez délicate (et ce n'est pas seulement parce que 8.0 est toujours en version bêta). Dans certaines circonstances, cela peut fonctionner et accélérer l'utilisation du processeur sur vos esclaves 5.7.
Autres changements dans la réplication MySQL
L'introduction des jeux d'écriture, bien qu'elle soit la plus intéressante, n'est pas la seule modification apportée à la réplication MySQL dans MySQL 8.0. Passons en revue d'autres changements, également importants. Si vous utilisez un maître antérieur à MySQL 5.0, 8.0 ne prendra pas en charge son format de journal binaire. Nous ne nous attendons pas à voir beaucoup de configurations de ce type, mais si vous utilisez un très ancien MySQL avec réplication, c'est certainement le moment de mettre à niveau.
Les valeurs par défaut ont changé pour s'assurer que la réplication est aussi sûre que possible :master_info_repository et relay_log_info_repository sont définis sur TABLE. Expire_log_days a également été modifié - maintenant la valeur par défaut est 30. En plus de expire_log_days , une nouvelle variable a été ajoutée, binlog_expire_log_seconds , ce qui permet une politique de rotation binlog plus précise. Certains horodatages supplémentaires ont été ajoutés au journal binaire pour améliorer l'observabilité du décalage de réplication, en introduisant une granularité de l'ordre de la microseconde.
Bien entendu, il ne s'agit pas d'une liste complète des modifications et des fonctionnalités liées à la réplication MySQL. Si vous souhaitez en savoir plus, vous pouvez consulter les journaux des modifications MySQL. Assurez-vous de les avoir toutes examinées :jusqu'à présent, des fonctionnalités ont été ajoutées dans toutes les versions 8.0.
Comme vous pouvez le constater, la réplication MySQL continue d'évoluer et de s'améliorer. Comme nous l'avons dit au début, cela doit être un processus lent, mais c'est vraiment formidable de voir ce qui nous attend. Il est également agréable de voir le travail de réplication de groupe se répercuter et être réutilisé dans la réplication MySQL "normale".