@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 sur 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 maître est quelque chose qui se produit «en dehors» des serveurs MySQL, par opposition à quelque chose qui se produit «en interne» aux 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 ... qu'il a également signalé comme hypothèse erronée s'il STOP SLAVE;
est émis. Mais un esclave arrêté est toujours un esclave, donc «pas un esclave» (à tout moment) ne signifie 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 échoué, il ne sera pas connecté. Donc cela ne résout 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 pouvez / devez définir la variable globale read_only
afin que les utilisateurs sans SUPER
privilège ne puissent pas y écrire involontairement (et que votre application ne devrait pas en avoir SUPER
). Si vous "promouvez" manuellement l'esclave au rôle de maître, vous devez SET GLOBAL read_only = OFF
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 soit une option de configuration matérielle, soit l'application ne doit pas être au courant et la destination de connexion à la base de données doit être 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 qui ou quoi que ce soit - de faire d'un autre serveur le maître, l'application ne peut pas être autorisée pour une raison quelconque à 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 d'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 maître ... la information_schema.processlist
requête sur l'esclave renverra 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 les 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 transfère 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 fonctionnant 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 /etc/hosts
fichier 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 la promotion de l'esclave vers master est censé ê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 fonctionnent toujours), les 2 serveurs continuent de fonctionner heureusement mais le serveur 1 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.