Qual é a maneira mais segura de alternar o formato do binlog em tempo de execução?

25

Por causa do seguinte aviso em mysqld.log:

[Aviso] Instrução não segura gravada no log binário usando o formato de instrução desde BINLOG_FORMAT = STATEMENT. A instrução é insegura porque usa uma cláusula LIMIT. Isso não é seguro porque o conjunto de linhas incluídas não pode ser previsto.

Eu quero mudar o formato de replicação para MIXED.

Mas de acordo com o documento MySQL:

Não é recomendável alternar o formato de replicação em tempo de execução quando existirem tabelas temporárias, porque as tabelas temporárias são registradas apenas ao usar a replicação baseada em instruções, enquanto que na replicação baseada em linhas elas não são registradas.

Portanto, a questão é como identificar se existem tabelas temporárias para alterar o formato de log binário com segurança?

quanta
fonte
11
Aviso rápido. Cuidado com este quando se passa de RBR-> SBR e usando comprometida leitura: bugs.mysql.com/bug.php?id=62493
Morgan Tocker

Respostas:

35

Como um binlog terá um formato específico no momento em que você fizer isso, você pode decidir não jogar com os dois formatos juntos, embora o MySQL (eh Oracle [ainda não consiga sair da minha língua]) tenha construído esse recurso.

Para jogá-lo totalmente seguro sem uma reinicialização do mysql, tente o seguinte:

FLUSH TABLES WITH READ LOCK;
FLUSH LOGS;
SET GLOBAL binlog_format = 'MIXED';
FLUSH LOGS;
UNLOCK TABLES;

Isso deixará o último binlog no formato 'MIXED'. O penúltimo (próximo ao último) binlog existe apenas para encerrar o último binlog que estava no formato anterior.

Todas as sessões existentes anteriores à primeira FLUSH LOGS;começarão a ser gravadas no último binlog após a UNLOCK TABLES;execução.

De uma chance !!!

EMBARGO

Dando crédito onde o crédito é devido, minha resposta está realmente pegando carona com a resposta de @ Jonathan . Apenas fecho e abro binlogs em cima disso. Ele recebe um +1 por trazer isso à tona primeiro.

UPDATE 2011-10-12 13:58 EDT

Se você fizer isso com um mestre ativo e houver um ou mais escravos replicando a partir desse mestre, será necessário se preocupar com o fato de os logs de retransmissão também estarem no novo formato. Aqui está o que você pode fazer:

No Escravo, corra STOP SLAVE;

No Master, execute estes:

FLUSH TABLES WITH READ LOCK;
FLUSH LOGS;
SET GLOBAL binlog_format = 'MIXED';
FLUSH LOGS;
UNLOCK TABLES;

No Escravo, corra START SLAVE;

A execução STOP SLAVE;e START SLAVE;gira os logs de retransmissão e faz com que as novas entradas sejam replicadas, seja qual for o formato. Você também pode aplicar a alteração binlog_format no escravo.

RolandoMySQLDBA
fonte
3
Uma coisa a ter em mente é que as configurações de replicação do mysql são realmente definidas por sessão de cliente. Definir o global binlog_format apenas altera o valor para NOVAS sessões. Portanto, se você estiver executando em um sistema com clientes persistentemente conectados, quaisquer alterações feitas nas configurações não serão aplicadas imediatamente, mesmo se você executar a liberação e o bloqueio conforme especificado aqui - eles não terão efeito até os clientes reconectar (ou definir o valor em sua própria sessão, mas, na minha experiência, a primeira é mais provável).
Austin Mills
Para os curiosos, você também pode colocar este "binlog_format = 'MIXED';" no seu my.cnf.
Christian
2
Para sua informação, esta resposta não está de acordo com uma resposta aqui: dba.stackexchange.com/questions/58539/…
HTTP500
O manual declara : Isso significa que alterar o formato de log em um mestre de replicação não faz com que um escravo altere seu formato de log para corresponder. (..snip ..) Alterar o formato de log binário no mestre enquanto a replicação está em andamento, ou sem alterá-lo também no escravo, pode causar resultados inesperados ou até mesmo causar falha na replicação.
Halfgaar 22/09/14
@ Halfgaar Apenas na semana passada, troquei um escravo de MIXED para STATEMENT três vezes sem causar efeitos negativos. Eu estava fazendo isso porque a replicação estava interrompendo devido a uma condição de corrida. A tabela tornou-se inexistente em um escravo antes da execução da consulta. Então, mudei para STATEMENT para estável como essa situação. Obviamente, todas as gravações foram interrompidas enquanto eu fazia isso. BTW eu fiz o mestre também.
RolandoMySQLDBA 22/09
6

Para alternar binlog_format em tempo de execução, você pode:

set global binlog_format = 'MIXED';

Isso definirá todas as NOVAS sessões para serem no formato binlog misto. Todas as sessões existentes serão definidas anteriormente até o final.

Você também pode fazer set session binlog_format = 'MIXED';manualmente para resolver qualquer problema com a sessão especificamente.

Jonathan
fonte
Não pergunto o caminho, pergunto o caminho mais seguro e como posso verificar se existe alguma tabela temporária.
quanta
3
Definir a variável global primeiro e aguardar o término das sessões restantes é a maneira mais segura.
Jonathan