La gestion de transactions importantes a toujours été un point sensible dans Galera Cluster. La façon dont la certification Galera writeset fonctionne provoque des problèmes lorsque les transactions sont longues ou lorsqu'une seule ligne est souvent modifiée sur plusieurs nœuds. Par conséquent, les transactions doivent être annulées et réessayées, ce qui entraîne une baisse des performances. Heureusement, ce problème a été résolu dans Galera 4, une nouvelle version de Galera de Codership. Cette bibliothèque est utilisée dans MariaDB 10.4, donc l'installation de MariaDB 10.4 est le moyen le plus simple de tester les fonctionnalités nouvellement introduites. Dans cet article de blog, nous verrons comment la réplication en continu peut être utilisée pour atténuer les problèmes qui étaient un problème standard dans les versions précédentes de Galera.
Nous utiliserons trois nœuds du cluster MariaDB Galera version 10.4.6, qui est fourni avec la version Galera 26.4.2.
MariaDB [(none)]> show global status like 'wsrep_provider%';
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <[email protected]> |
| wsrep_provider_version | 26.4.2(r4498) |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.001 sec)
Il y a trois principaux problèmes que la réplication en streaming est censée traiter :
- Transactions longues
- Transactions importantes
- Points chauds dans les tableaux
Examinons-les un par un et voyons comment la réplication en continu peut nous aider à les gérer, mais concentrons-nous d'abord sur la certification du jeu d'écriture - la cause première de ces problèmes.
Certification Writeset dans Galera Cluster
Le cluster Galera se compose de plusieurs nœuds inscriptibles. Chaque transaction exécutée sur le cluster Galera forme un jeu d'écriture. Chaque jeu d'écriture doit être envoyé à tous les nœuds du cluster pour certification - un processus qui garantit que tous les nœuds peuvent appliquer une transaction donnée. Les jeux d'écriture doivent être exécutés sur tous les nœuds du cluster, donc s'il y a un conflit, la transaction ne peut pas être validée. Quelles sont les raisons typiques pour lesquelles la transaction ne peut pas être validée ? Eh bien, les trois points que nous avons énumérés plus tôt :
- Longues transactions :plus la transaction prend de temps, plus il est probable qu'entre-temps un autre nœud exécute des mises à jour qui finiront par entrer en conflit avec le jeu d'écriture et l'empêcheront de passer la certification
- Grandes transactions :tout d'abord, les grandes transactions sont également plus longues que les petites, ce qui déclenche le premier problème. Le deuxième problème, strictement lié aux grosses transactions, est le volume des changements. Plus de lignes vont être mises à jour, plus il est probable que certaines écritures sur un autre nœud entraînent un conflit et que toute la transaction doive être annulée.
- Points chauds dans les tables :il est plus probable qu'une ligne donnée doive être mise à jour, il est plus probable qu'une telle mise à jour se produise simultanément sur plusieurs nœuds, ce qui entraînera l'annulation de certaines transactions
Le principal problème ici est que Galera n'introduit aucun verrouillage sur les nœuds autres que le nœud initial, sur lequel la transaction a été ouverte. Le processus de certification est basé sur l'espoir que si un nœud pouvait exécuter une transaction, d'autres devraient également pouvoir le faire. C'est vrai mais, comme nous en avons discuté, il existe des cas particuliers dans lesquels la probabilité que cela se produise est considérablement réduite.
Dans Galera 4, avec la réplication en continu, le comportement a changé et tous les verrous sont pris dans tous les nœuds. Les transactions seront divisées en parties et chaque partie sera certifiée sur tous les nœuds. Une fois la certification réussie, les lignes seront verrouillées sur tous les nœuds du cluster. Il y a quelques variables qui régissent exactement comment cela est fait - wsrep_trx_fragment_size et wsrep_trx_fragment_unit définissent la taille du fragment et comment il doit être défini. Il s'agit d'un contrôle très fin :vous pouvez définir l'unité de fragment sous forme d'octets, d'instructions ou de lignes, ce qui permet d'exécuter la certification pour chaque ligne modifiée dans la transaction. Voyons comment vous pouvez bénéficier de la réplication en continu dans la vie réelle.
Travailler avec la réplication en continu
Considérons le scénario suivant. Nous avons une transaction à exécuter qui prend au moins 30 secondes :
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Ensuite, pendant son exécution, nous exécuterons SQL qui touche des lignes similaires. Ceci sera exécuté sur un autre nœud :
BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Quel serait le résultat ?
La première transaction est annulée dès que la seconde est exécutée :
MariaDB [sbtest]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT;
Query OK, 0 rows affected (0.001 sec)
Query OK, 667 rows affected (0.020 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.010 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (0.009 sec)
Rows matched: 667 Changed: 667 Warnings: 0
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
Query OK, 0 rows affected (0.001 sec)
La transaction sur le deuxième nœud a réussi :
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (0.002 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.004 sec)
Ce que nous pouvons faire pour l'éviter, c'est d'utiliser la réplication en continu pour la première transaction. Nous demanderons à Galera de certifier chaque changement de ligne :
MariaDB [sbtest]> BEGIN; SET SESSION wsrep_trx_fragment_size=1 ; SET SESSION wsrep_trx_fragment_unit='rows' ; UPDATE sbtest.sbtest1 SET k = k - 2 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 2000 ; SELECT SLEEP(30); COMMIT; SET SESSION wsrep_trx_fragment_size=0;
Query OK, 0 rows affected (0.001 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 0 rows affected (0.000 sec)
Query OK, 667 rows affected (1.757 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.708 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Query OK, 667 rows affected (1.685 sec)
Rows matched: 667 Changed: 667 Warnings: 0
Comme vous pouvez le voir, cette fois, cela a très bien fonctionné. Sur le deuxième nœud :
MariaDB [(none)]> BEGIN; UPDATE sbtest.sbtest1 SET k = k - 1 WHERE id < 20 ; UPDATE sbtest.sbtest1 SET k = k + 1 WHERE id < 20 ; COMMIT;
Query OK, 0 rows affected (0.000 sec)
Query OK, 7 rows affected (33.942 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 7 rows affected (0.001 sec)
Rows matched: 7 Changed: 7 Warnings: 0
Query OK, 0 rows affected (0.026 sec)
Ce qui est intéressant, vous pouvez voir que la mise à jour a pris près de 34 secondes pour s'exécuter - cela a été causé par le fait que la transaction initiale, via la réplication en continu, a verrouillé toutes les lignes modifiées sur tous les nœuds et que notre deuxième transaction a dû attendre le premier à se terminer même si les deux transactions ont été exécutées sur des nœuds différents.
C'est fondamentalement tout en ce qui concerne la réplication en continu. En fonction des exigences et du trafic, vous pouvez l'utiliser de manière moins stricte - nous avons certifié chaque ligne, mais vous pouvez modifier cela à chaque n-ième ligne ou à chaque instruction. Vous pouvez même décider du volume de données à certifier. Cela devrait être suffisant pour répondre aux exigences de votre environnement.
Il y a quelques autres choses que nous aimerions que vous gardiez à l'esprit et que vous vous souveniez. Tout d'abord, la réplication en streaming n'est en aucun cas une solution à utiliser par défaut. C'est la raison pour laquelle il est, par défaut, désactivé. Le cas d'utilisation recommandé consiste à décider manuellement des transactions qui bénéficieraient de la réplication en continu et à l'activer au niveau de la session. C'est la raison pour laquelle nos exemples se terminent par :
SET SESSION wsrep_trx_fragment_size=0;
Cette instruction (définir wsrep_trx_fragment_size sur 0) désactive la réplication en continu pour la session en cours.
Une autre chose à retenir - si vous utilisez la réplication en continu, elle utilisera la table "wsrep_streaming_log" dans le schéma "mysql" pour stocker de manière persistante les données en streaming. À l'aide de ce tableau, vous pouvez avoir une idée des données transférées dans le cluster à l'aide de la réplication en continu.
Enfin, les performances. C'est également l'une des raisons pour lesquelles vous ne souhaitez pas utiliser la réplication en continu tout le temps. La raison principale en est le verrouillage - avec la réplication en continu, vous devez acquérir des verrous de ligne sur tous les nœuds. Cela prend du temps pour obtenir les verrous et, si vous devez annuler la transaction, cela mettra également la pression sur tous les nœuds pour effectuer l'annulation. Nous avons effectué un test très rapide de l'impact sur les performances de la réplication en continu. L'environnement est strictement un environnement de test, donc ne présumez pas que ces résultats sont les mêmes sur le matériel de production, c'est plutôt à vous de voir quel pourrait être l'impact.
Nous avons testé quatre scénarios :
- Base de référence, définissez global wsrep_trx_fragment_size=0 ;
- set global wsrep_trx_fragment_unit='rows' ; définir global wsrep_trx_fragment_size=1 ;
- set global wsrep_trx_fragment_unit='statements' ; définir global wsrep_trx_fragment_size=1 ;
- set global wsrep_trx_fragment_unit='statements' ; définir global wsrep_trx_fragment_size=5 ;
Nous avons utilisé le test r/w sysbench :
sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=4 --events=0 --time=300 --mysql-host=10.0.0.141 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=3306 --tables=32 --report-interval=1 --skip-trx=off --table-size=100000 --db-ps-mode=disable run
Les résultats sont :
- Transactions :82,91 par seconde, requêtes :1 658,27 par seconde. (100 %)
- Transactions :54,72 par seconde, requêtes :1 094,43 par seconde. (66%)
- Transactions :54,76 par seconde, requêtes :1 095,18 par seconde. (66%)
- Transactions :70,93 par seconde, requêtes :1 418,55 par seconde. (86 %)
Comme vous pouvez le constater, l'impact est significatif, les performances chutent même de 33 %.
Nous espérons que vous avez trouvé cet article de blog informatif et qu'il vous a donné un aperçu de la réplication en continu fournie avec Galera 4 et MariaDB 10.4. Nous avons essayé de couvrir les cas d'utilisation et les inconvénients potentiels liés à cette nouvelle technologie.