J'installe la réplication MySQL maître-esclave et j'essaie de comprendre comment gérer la situation de basculement où je promeut l'esclave à maître (dans le cas où le maître tombe en panne).
Mon serveur d'applications doit diriger toutes les écritures vers le maître actuel, mais je ne peux pas utiliser HA de niveau serveur entre le maître et l'esclave (battement de cœur, keepalived) car les deux serveurs db sont sur des sous-réseaux complètement différents dans des emplacements physiques différents.
Je pense que c'est quelque chose que je dois gérer au niveau de l'application. Je peux interroger les deux serveurs et demander lequel est un maître, puis effectuer toutes les requêtes vers celui-ci.
Existe-t-il une requête dans MySQL pour voir si le serveur actuel est un maître dans une réplique maître-esclave?
@RolandoMySQLDBA a répondu à la question avec précision ... mais il a également souligné que sa solution était "rapide et sale".
Et c'est une déclaration très vraie. :)
La chose qui me préoccupe ici n'est pas avec cette réponse, mais plutôt que la question d'origine semble faire une hypothèse incorrecte:
Je peux interroger les deux serveurs et demander lequel est un maître, puis effectuer toutes les requêtes vers celui-ci.
Le problème est que dans la réplication MySQL, le maître n'est jamais vraiment conscient qu'il est le maître.
Le concept de "promotion à maîtriser" n'est pas vraiment un concept dans la réplication asynchrone MySQL. La "promotion" d'un serveur MySQL au rôle de maître est quelque chose qui se produit "à l'extérieur" des serveurs MySQL, par opposition à quelque chose qui se produit "à l'intérieur" des serveurs MySQL.
La "promotion vers le maître" n'est effectuée par aucun type de provisionnement de serveur, car, techniquement parlant, chaque serveur MySQL sur lequel la journalisation binaire est activée est un maître, même s'il n'a jamais d'esclave. SHOW MASTER STATUS
Fonctionne exactement de la même manière et renvoie exactement le même résultat, esclaves ou non, et un maître avec 2 esclaves n'est ni plus ni moins maître qu'un maître avec 1 esclave ou 0 esclave. De même, un maître dont les esclaves sont tous hors ligne est toujours autant un maître, car lorsque les esclaves reviendront en ligne, ils reprendront la réplication là où ils se sont arrêtés.
Dans un sens, la seule "prise de conscience" de l'un ou l'autre serveur n'est pas de savoir s'il s'agit d'un maître, mais plutôt s'il s'agit d'un esclave (ou "non").
C'est ce que la solution de Rolando demande: "êtes-vous un esclave?" Si la réponse est non, alors l'hypothèse est que ce doit être le maître ... ce qu'il a également souligné comme une hypothèse erronée si STOP SLAVE;
Est émis. Mais un esclave arrêté est toujours un esclave, donc "pas un esclave" (à tout moment) n'équivaut pas à "être un maître".
Un test similaire pourrait être effectué sur le maître présumé:
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
ou
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
Si la valeur est zéro, le thread IO de l'esclave n'est pas connecté. Ce test présente un défaut similaire, en ce sens que si l'esclave est déconnecté administrativement, isolé ou a échoué, il ne le sera pas être connecté. Donc, cela ne résout vraiment rien non plus.
Pire encore (pour l'un ou l'autre de ces scénarios), la "table" information_schema.processlist est une table virtuelle qui se matérialise à chaque fois qu'elle est sélectionnée, ce qui prend du temps et coûte des ressources. Plus votre serveur est occupé, plus il en coûte, car l'activité de chaque thread doit être examinée.
Une solution plus légère serait:
SELECT @@global.read_only;
Sur un esclave, vous pourriez/devriez définir la variable globale read_only
Afin que les utilisateurs sans le privilège SUPER
ne puissent pas y écrire involontairement (et votre application ne devrait pas avoir SUPER
). Si vous "promouvez" manuellement l'esclave au rôle de maître, vous SET GLOBAL read_only = OFF
Pour activer les écritures. (La réplication peut toujours écrire sur l'esclave, quel que soit le réglage).
Mais cela manque encore, je pense, à un point important:
Je proposerais que l'application ne prenne pas cette décision de manière heuristique dans une configuration maître/esclave, et certainement pas sur une base connexion par connexion. L'application doit utiliser une option de configuration matérielle, ou l'application doit rester ignorante et avoir la destination de connexion à la base de données gérée par autre chose.
Ou, au minimum, l'application ne doit jamais basculer jusqu'à ce que le maître tombe en panne, puis elle ne doit jamais revenir en arrière d'elle-même.
Voici pourquoi je dis cela: une fois que la "décision" est prise - par quiconque ou quoi que ce soit - de faire d'un autre serveur le maître, l'application ne peut être autorisée pour aucune raison à revenir au maître d'origine, même après sa remise en ligne. , sans intervention.
Supposons que vous rencontriez un bogue et qu'il y ait un plantage forcé par logiciel; mysqld_safe
Redémarre consciencieusement mysqld
, et la récupération après incident InnoDB fonctionne parfaitement. Mais cela prend quelques minutes.
Pendant ce temps, le maître est en panne, votre application est donc passée à l'esclave. Les transactions ont été créées, les commandes passées, les fonds transférés, les commentaires publiés, les blogs modifiés, quoi que fasse votre système.
Maintenant, le maître d'origine revient en ligne.
Si votre application revient au maître d'origine, vous êtes dans un monde de souffrance absolu, car la prochaine chose qui risque de se produire est que la réplication s'arrête en raison d'une incohérence, car votre application a modifié les données sur l'esclave en moyenne temps. Vous avez maintenant deux serveurs de base de données avec des données incohérentes que vous devrez réconcilier manuellement. S'il y a des dollars ou des points ou des crédits impliqués, vous avez maintenant des soldes incompatibles.
Il est donc essentiel que l'application ne soit pas autorisée à revenir au maître d'origine sans votre intervention.
Attendez, vous venez de trouver le problème avec ce scénario tel que je l'ai décrit? Le maître a échoué mais votre application n'utilisera pas l'esclave, car il pense que l'esclave est toujours l'esclave et non le master ... la requête information_schema.processlist
sur l'esclave retournera toujours non nul même si le serveur maître est hors tension.
Il n'y a donc pas grand intérêt à ce que l'application découvre quoi que ce soit, car vous devrez manuellement STOP SLAVE
Pour que ce test soit utile.
Peut-être une meilleure approche si vous voulez que l'application puisse basculer serait de configurer les serveurs avec une réplication circulaire.
La réplication circulaire a ses propres problèmes, mais tant que votre application n'écrit que toujours sur un serveur à la fois, la plupart de ces problèmes deviennent des problèmes non liés. En d'autres termes, les deux machines sont toujours et simultanément à la fois maître et esclave, dans un sens de réplication, mais votre application, via un mécanisme, ne pointe toujours que sur une machine à la fois comme le "maître" sur lequel elle peut et doit écrire. .
Vous ne pouvez pas déployer d'outils HA sur les serveurs MySQL en raison de leur séparation, mais vous pouvez l'implémenter avec HAProxy exécuté sur le ou les serveurs d'applications. L'application se connecte à "MySQL" sur localhost, qui n'est pas du tout MySQL, mais est en fait HAProxy ... et il transmet la connexion TCP à la machine MySQL appropriée).
HAProxy peut tester les connexions aux serveurs MySQL et n'offrir du trafic qu'à une machine MySQL qui accepte les connexions et autorise l'authentification.
La combinaison de HAProxy s'exécutant sur le serveur d'applications (sa demande de ressources ne sera pas substantielle par rapport à tout ce que le serveur d'applications doit faire - c'est à peu près simplement relier les sockets ensemble et ignorer leur charge utile) ... et la réplication circulaire MySQL serait l'approche que je prendrais probablement dans ce cas, basée sur ce que l'on sait de la question.
Ou, pour une configuration strictement manuelle, optez pour quelque chose de beaucoup plus simple que "découverte", comme une entrée dans le fichier /etc/hosts
Du serveur d'application avec un nom d'hôte que l'application utilise pour se connecter à MySQL, que vous pouvez mettre à jour manuellement - - en supposant que la promotion de l'esclave au maître est censée être un processus manuel.
Ou quelque chose de plus complexe, en utilisant Percona XtraDB Cluster. Pour cela, cependant, vous voudriez ajouter un troisième serveur, car avec 3 nœuds dans PXC, si 2 serveurs peuvent se voir mais être isolés d'un seul serveur (si les trois sont toujours en cours d'exécution), les 2 serveurs continuent de fonctionner heureusement mais le 1 serveur se recroqueville en une petite boule et refuse de faire quoi que ce soit car il se rend compte qu'il doit être le plus étrange. Cela fonctionne parce que les 2 réalisent qu'ils constituent toujours la majorité des nœuds qui étaient en ligne avant la division du réseau et le 1 se rend compte que ce n'est pas le cas. Avec PXC, peu importe le serveur auquel votre application se connecte.
Je dis que tout cela revient à dire "ne demandez pas à l'application d'interroger les serveurs pour voir lequel est le maître", car cela vous mordra tôt ou tard et grignotera vos performances jusqu'au jour où il mordra.
Si vous utilisez uniquement Master/Slave, voici quelque chose de rapide et sale:
SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';
Qu'est-ce que cela vous dit?
SlaveThreadCount
= 0, vous avez le maîtreSlaveThreadCount
> 0, vous avez l'esclave MISE EN GARDE : Cela fonctionne tant que vous n'exécutez pas STOP SLAVE;
Une autre chose à essayer est la suivante: si vous désactivez la journalisation binaire sur l'esclave et que vous exécutez SHOW MASTER STATUS;
, le maître vous donne le journal binaire actuel. L'esclave ne vous donne rien.
exécuter cette instruction à partir de l'invite mysql
mysql> affiche le statut de l'esclave;
Sur l'esclave, il montre beaucoup de paramètres et leurs valeurs/état tandis que sur le maître, il montre Ensemble vide