@RolandoMySQLDBA ha respondido la pregunta con precisión ... pero también señaló que su solución fue "rápida y sucia".
Y esa es una afirmación muy verdadera. :)
Lo que me preocupa aquí no es con esa respuesta, sino que la pregunta original parece hacer una suposición incorrecta:
Puedo consultar los dos servidores y preguntar cuál es un maestro, luego realizar todas las consultas a ese.
El problema es que en la replicación MySQL, el maestro nunca es realmente consciente de que es el maestro.
El concepto de "promoción a maestro" no es realmente un concepto en la replicación asincrónica de MySQL. "Promover" un servidor MySQL a la función de maestro es algo que sucede "externo a" los servidores MySQL, en lugar de algo que sucede "interno" a los servidores MySQL.
La "promoción al maestro" no se realiza mediante ningún tipo de aprovisionamiento del servidor, porque, técnicamente hablando, cada servidor MySQL que tiene habilitado el registro binario es un maestro, incluso si nunca tiene un esclavo. SHOW MASTER STATUS
funciona exactamente de la misma manera y devuelve exactamente el mismo resultado, esclavos o no, y un maestro con 2 esclavos no es más o menos maestro que un maestro con 1 esclavo o 0 esclavos. Del mismo modo, un maestro cuyos esclavos están todos fuera de línea sigue siendo igual de maestro, porque cuando los esclavos vuelvan a conectarse, continuarán replicando donde lo dejaron.
En cierto sentido, la única "conciencia" por parte de cualquiera de los servidores no es si es un maestro, sino más bien si es un esclavo (o "no").
Eso es lo que pregunta la solución de Rolando: "¿eres un esclavo?" Si la respuesta es no, entonces la suposición es que este debe ser el maestro ... que también señaló como una suposición defectuosa si STOP SLAVE;
se emite. Pero un esclavo detenido sigue siendo un esclavo, por lo que "no es un esclavo" (en ningún momento) no equivale a "ser un maestro".
Se podría hacer una prueba similar en el supuesto maestro:
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
o
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
Si el valor es cero, entonces el hilo IO del esclavo no está conectado. Esta prueba tiene un defecto similar, ya que si el esclavo se desconecta administrativamente, se aísla o falla, no se conectará. Así que esto tampoco resuelve nada realmente.
Peor aún (para cualquiera de estos escenarios), la "tabla" de information_schema.processlist es una tabla virtual que se materializa cada vez que se selecciona, y esto toma tiempo y cuesta recursos. Cuanto más ocupado esté su servidor, más cuesta, porque la actividad de cada subproceso debe ser analizada.
Una solución más ligera sería:
SELECT @@global.read_only;
En un esclavo, podría / debería establecer la variable global read_only
para que los usuarios sin el SUPER
privilegio no puedan escribirle involuntariamente (y su aplicación no debería tenerla SUPER
). Si "promueve" manualmente al esclavo a la función de maestro, puede SET GLOBAL read_only = OFF
habilitar las escrituras. (La replicación siempre puede escribir en el esclavo, sin importar cómo se configure).
Pero esto todavía, creo, pierde un punto importante:
Yo propondría que la aplicación no tome esta decisión heurísticamente en una configuración maestro / esclavo, y ciertamente no en una conexión por conexión. La aplicación debe usar una opción de configuración rígida, o la aplicación debe permanecer inconsciente y tener el destino de conexión de la base de datos manejado por otra cosa.
O, como mínimo, la aplicación nunca debe cambiar hasta que el maestro falle, y luego nunca debe volver a cambiar por sí sola.
He aquí por qué digo eso: una vez que la "decisión" se toma, por quien sea o lo que sea, de convertir a otro servidor en el maestro, no se puede permitir que la aplicación cambie por ningún motivo al maestro original, incluso después de que vuelva a estar en línea , sin intervención.
Digamos que chocas con un error y hay un bloqueo forzado por el software; mysqld_safe
se reinicia debidamente mysqld
, y la recuperación de fallos de InnoDB se realiza sin problemas. Pero eso lleva unos minutos.
Mientras tanto, el maestro está inactivo, por lo que su aplicación se ha cambiado al esclavo. Se han creado transacciones, se han realizado pedidos, se han transferido fondos, se han publicado comentarios, se han editado blogs, haga lo que haga su sistema.
Ahora, el maestro original vuelve a estar en línea.
Si su aplicación vuelve al maestro original, se encuentra en un mundo de dolor absoluto, porque lo siguiente que probablemente sucederá es que la replicación se detiene debido a una inconsistencia, porque su aplicación ha cambiado los datos en el esclavo en la media hora. Ahora tiene dos servidores de bases de datos con datos inconsistentes que tendrá que conciliar manualmente. Si hay dólares o puntos o créditos involucrados, ahora tiene saldos no coincidentes.
Por lo tanto, es fundamental que no se permita que la aplicación vuelva al maestro original sin su intervención.
Espera, ¿acabas de encontrar el problema con este escenario como lo describí? El maestro ha fallado, pero su aplicación no usará el esclavo, porque cree que el esclavo sigue siendo el esclavo y no el maestro ... la information_schema.processlist
consulta sobre el esclavo aún devolverá un valor distinto de cero, incluso si el servidor maestro está apagado .
Por lo tanto, no tiene mucho sentido que la aplicación descubra algo, ya que tendrá que hacerlo manualmente STOP SLAVE
para que esa prueba sea útil.
Quizás un mejor enfoque si desea que la aplicación pueda cambiar sería configurar los servidores con replicación circular.
La replicación circular tiene sus propios problemas inherentes, pero siempre que su aplicación siempre escriba en un servidor a la vez, la mayoría de esos problemas se convierten en problemas. En otras palabras, ambas máquinas son siempre y simultáneamente maestro y esclavo, en un sentido de replicación, pero su aplicación, a través de algún mecanismo, siempre apunta a una máquina a la vez como el "maestro" en el que puede y debe escribir .
No puede implementar herramientas HA en los servidores MySQL debido a su separación, pero puede implementarlo con HAProxy ejecutándose en los servidores de aplicaciones. La aplicación se conecta a "MySQL" en localhost, que no es MySQL en absoluto, pero en realidad es HAProxy ... y reenvía la conexión TCP a la máquina MySQL adecuada.
HAProxy puede probar las conexiones a los servidores MySQL y solo ofrece tráfico a una máquina MySQL que acepta conexiones y permite la autenticación.
La combinación de HAProxy que se ejecuta en el servidor de aplicaciones (su demanda de recursos no será sustancial en comparación con todo lo demás que el servidor de aplicaciones tiene que hacer; es más que solo unir sockets e ignorar su carga útil) ... y la replicación circular de MySQL sería el enfoque que probablemente tomaría en este caso, basado en lo que se sabe de la pregunta.
O, para una configuración estrictamente manual, vaya con algo mucho más simple que "descubrimiento", como una entrada en el /etc/hosts
archivo del servidor de aplicaciones con un nombre de host que la aplicación utiliza para conectarse a MySQL, que puede actualizar manualmente, suponiendo la promoción de esclavo a master está destinado a ser un proceso manual.
O, algo más complejo, utilizando Percona XtraDB Cluster. Sin embargo, para esto, desearía agregar un tercer servidor, porque con 3 nodos en PXC, si 2 servidores pueden verse pero se aíslan de 1 servidor (si los tres todavía se están ejecutando) los 2 servidores siguen funcionando felizmente, pero el servidor 1 se acurruca en una pequeña bola y se niega a hacer nada, ya que se da cuenta de que debe ser el extraño. Esto funciona porque los 2 se dan cuenta de que todavía constituyen la mayoría de los nodos que estaban en línea antes de la división de la red y el 1 se da cuenta de que no lo es. Con PXC, realmente no importa a qué servidor se conecta su aplicación.
Digo que todo esto es para decir "no haga que la aplicación sondee los servidores para ver cuál es el maestro" porque tarde o temprano lo morderá y afectará su rendimiento hasta el día en que muerde.