@RolandoMySQLDBA respondeu à pergunta com precisão ... mas ele também apontou que sua solução era "rápida e suja".
E essa é uma afirmação muito verdadeira. :)
O que me preocupa aqui não é com essa resposta, mas é que a pergunta original parece fazer uma suposição incorreta:
Posso consultar os dois servidores e perguntar qual deles é um mestre e, em seguida, executar todas as consultas nesse servidor.
O problema é que, na replicação do MySQL, o mestre nunca está verdadeiramente ciente de que é o mestre.
O conceito de "promoção para dominar" não é realmente um conceito na replicação assíncrona do MySQL. "Promover" um servidor MySQL para a função principal é algo que acontece "externo a" servidores MySQL, em oposição a algo que acontece "interno a" servidores MySQL.
A "promoção para mestre" não é feita por nenhum tipo de provisionamento de servidor, porque, tecnicamente, todo servidor MySQL que possui o log binário ativado é um mestre, mesmo que nunca tenha um escravo. SHOW MASTER STATUS
funciona exatamente da mesma maneira e retorna exatamente o mesmo resultado, escravos ou não, e um mestre com 2 escravos não é mais ou menos mestre do que um mestre com 1 escravo ou 0 escravos. Da mesma forma, um mestre cujos escravos estão todos off-line ainda é um mestre, porque quando os escravos se conectam novamente, eles começam a replicar de onde pararam.
Em certo sentido, a única "conscientização" por parte de qualquer servidor não é se é um mestre, mas se é um escravo (ou "não").
É o que a solução de Rolando pergunta: "você é escravo?" Se a resposta for não, então a suposição é de que esse deve ser o mestre ... o qual ele também apontou como uma suposição defeituosa se STOP SLAVE;
for emitida. Mas um escravo parado ainda é escravo, então "não um escravo" (a qualquer momento) não significa "ser um mestre".
Um teste semelhante poderia ser feito no suposto mestre:
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';
Se o valor for zero, o encadeamento IO do escravo não está conectado. Esse teste tem um defeito semelhante, pois se o escravo for desconectado administrativamente, isolado ou falhar, ele não será conectado. Portanto, isso também não resolve nada.
Pior ainda (para qualquer um desses cenários), a "tabela" information_schema.processlist é uma tabela virtual que se materializa toda vez que é selecionada, e isso leva tempo e custa recursos. Quanto mais ocupado o servidor, mais ele custa, porque a atividade de cada encadeamento deve ser examinada.
Uma solução mais leve seria:
SELECT @@global.read_only;
Em um escravo, você pode / deve definir a variável global read_only
para que usuários sem o SUPER
privilégio não possam gravá-la acidentalmente (e seu aplicativo não deve ter SUPER
). Se você "promover" manualmente o escravo para a função principal, SET GLOBAL read_only = OFF
habilite as gravações. (A replicação sempre pode gravar no escravo, não importa como isso esteja definido).
Mas, ainda assim, acho que falta um ponto importante:
Eu proporia que o aplicativo não deveria tomar essa decisão heuristicamente em uma configuração mestre / escravo, e certamente não em uma conexão por conexão. O aplicativo deve usar uma opção de configuração rígida ou permanecer inconsciente e ter o destino da conexão com o banco de dados tratado por outra coisa.
Ou, no mínimo, o aplicativo nunca deve alternar até que o mestre falhe e nunca deve voltar sozinho.
Aqui está o porquê de eu dizer o seguinte: depois que a "decisão" é tomada - por quem quer que seja - para tornar outro servidor o mestre, o aplicativo não pode, por qualquer motivo, voltar ao mestre original, mesmo depois de ficar on-line , sem intervenção.
Digamos que você tenha atingido um bug e houve uma falha forçada por software; mysqld_safe
reinicia obedientemente mysqld
e a recuperação de falhas do InnoDB é executada na perfeição. Mas isso leva alguns minutos.
Enquanto isso, o mestre está inativo, portanto, seu aplicativo mudou para o escravo. As transações foram criadas, pedidos feitos, fundos transferidos, comentários postados, blogs editados, independentemente do sistema.
Agora, o mestre original volta a ficar online.
Se seu aplicativo voltar ao mestre original, você estará em um mundo absoluto de dano, porque a próxima coisa que provavelmente acontecerá é que a replicação será interrompida devido a uma inconsistência, porque seu aplicativo alterou os dados no escravo nesse sentido. Tempo. Agora você tem dois servidores de banco de dados com dados inconsistentes que precisarão reconciliar manualmente. Se houver dólares, pontos ou créditos envolvidos, agora você tem saldos incompatíveis.
Portanto, é fundamental que o aplicativo não possa voltar ao mestre original sem a sua intervenção.
Espere, você acabou de encontrar o problema com este cenário como eu o descrevi? O mestre falhou, mas seu aplicativo não utilizará o escravo, porque acha que o escravo ainda é o escravo e não o mestre ... a information_schema.processlist
consulta no escravo ainda retornará diferente de zero, mesmo se o servidor mestre estiver desligado .
Portanto, não há muito sentido em o aplicativo descobrir algo, pois você precisará manualmente STOP SLAVE
para que esse teste seja útil.
Talvez uma abordagem melhor, se você deseja que o aplicativo possa alternar, seria configurar os servidores com replicação circular.
A replicação circular tem seus próprios problemas, mas desde que seu aplicativo sempre esteja sempre gravando em um servidor por vez, a maioria desses problemas se tornará não-problemas. Em outras palavras, ambas as máquinas são sempre e simultaneamente mestre e escravo, no sentido de replicação, mas sua aplicação, através de algum mecanismo, está sempre apontando apenas uma máquina por vez como o "mestre" no qual pode e deve escrever .
Você não pode implantar ferramentas de alta disponibilidade nos servidores MySQL devido à sua separação, mas pode implementá-las com o HAProxy em execução nos servidores de aplicativos. O aplicativo se conecta ao "MySQL" no host local, que não é MySQL, mas na verdade é HAProxy ... e encaminha a conexão TCP à máquina MySQL apropriada.
O HAProxy pode testar as conexões com os servidores MySQL e oferecer apenas tráfego para uma máquina MySQL que esteja aceitando conexões e permitindo autenticação.
A combinação do HAProxy em execução no servidor de aplicativos (sua demanda por recursos não será substancial em comparação com tudo o que o servidor de aplicativos tem que fazer - é praticamente unir soquetes e ignorar sua carga útil) ... e replicação circular do MySQL seria a abordagem que eu provavelmente adotaria neste caso, com base no que é conhecido da pergunta.
Ou, para uma configuração estritamente manual, opte por algo muito mais simples do que "descoberta", como uma entrada no /etc/hosts
arquivo do servidor de aplicativos com um nome de host que o aplicativo usa para se conectar ao MySQL, que você pode atualizar manualmente - assumindo a promoção de escravo para master pretende ser um processo manual.
Ou, algo mais complexo, usando o Percona XtraDB Cluster. Para isso, no entanto, você deseja adicionar um terceiro servidor, porque com 3 nós no PXC, se 2 servidores puderem se ver, mas ficarem isolados de 1 servidor (se todos os três ainda estiverem em execução), os 2 servidores continuarão funcionando alegremente, mas o servidor 1 se enrola e se recusa a fazer qualquer coisa, pois percebe que deve ser o estranho. Isso funciona porque os 2 percebem que ainda constituem a maioria dos nós que estavam online antes da divisão da rede e o 1 percebe que não. Com o PXC, não importa realmente a qual servidor seu aplicativo se conecta.
Eu digo que tudo isso é para dizer "não faça com que o aplicativo faça uma pesquisa nos servidores para ver qual deles é o mestre", porque ele o morderá mais cedo ou mais tarde e diminuirá seu desempenho até o dia em que ele morder.