Como você pode impedir o escravo do MySQL de replicar alterações no banco de dados 'mysql'?

9

Eu tenho meu escravo configurado para não replicar o banco de dados 'mysql' como descrito neste SHOW SLAVE STATUS\G;

           Slave_IO_State: Waiting for master to send event
              Master_Host: 127.0.0.1
              Master_User: replication
              Master_Port: 3306
            Connect_Retry: 60
          Master_Log_File: master-bin.000001
      Read_Master_Log_Pos: 1660
           Relay_Log_File: mysql-relay-bin.000004
            Relay_Log_Pos: 478
    Relay_Master_Log_File: master-bin.000001
         Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
          Replicate_Do_DB: 
      **Replicate_Ignore_DB: mysql**
       Replicate_Do_Table: 
   Replicate_Ignore_Table: 
  Replicate_Wild_Do_Table: 
Replicate_Wild_Ignore_Table: 
               Last_Errno: 0
               Last_Error: 
             Skip_Counter: 0
      Exec_Master_Log_Pos: 1660
          Relay_Log_Space: 633
          Until_Condition: None
           Until_Log_File: 
            Until_Log_Pos: 0

Agora, se eu for ao servidor MASTER e emitir um GRANTe FLUSH PRIVILEGES:

GRANT SELECT ON *.* TO `foo`@`localhost` IDENTIFIED BY 'bar';
FLUSH PRIVILEGES;

Volto ao servidor SLAVE e emito:

SHOW GRANTS FOR `foo`@`localhost`;

e receba a resposta:

+-------------------------------------------------------------------------------------------------------------+
| Grants for foo@localhost                                                                                    |
+-------------------------------------------------------------------------------------------------------------+
| GRANT SELECT ON *.* TO 'foo'@'localhost' IDENTIFIED BY PASSWORD '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB' |
+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Como posso parar o escravo de replicar altera o banco de dados mysql? Imaginei que 'replicate_ignore_db' seria suficiente.

Derek Downey
fonte

Respostas:

8

Tudo bem, depois de mais algumas horas de investigação, acho que descobri. Adicionando minha resposta caso isso seja útil para outras pessoas.

De acordo com os documentos em replicate-ignore-db :

Replicação baseada em instruções. Informa ao encadeamento SQL do escravo para não replicar nenhuma instrução em que o banco de dados padrão (ou seja, aquele selecionado por USE) seja db_name.

Obviamente, a replicação baseada em instruções é o padrão e o que eu estava usando. Então, tentei alterar o formato reiniciando o mestre binlog_format=rowpara ver o que aconteceria. Sem dados. CONCESSÕES e REVOGAS ainda foram replicadas.

Uma investigação mais aprofundada sobre os documentos sobre alterações de replicação na tabela mysql revelou

Instruções que alteram o banco de dados mysql indiretamente são registradas como instruções, independentemente do valor de binlog_format. Isso se refere a instruções como GRANT, REVOKE, SET PASSWORD, RENAME USER, CREATE (todos os formulários, exceto CREATE TABLE ... SELECT), ALTER (todos os formulários) e DROP (todos os formulários).

Gah! Ok, verifiquei o binlog usando mysqlbinloge minha GRANTdeclaração não estava emitindo uma USE mysqlchamada ao banco de dados (por que deveria?). Portanto, replicate-ignore-dbnão seria possível, em sã consciência, ignorar a afirmação.

Minha solução foi cortar completamente as alterações na tabela mysql do log binário, adicionando binlog-ignore-db=mysqlao my.cnf e reiniciando o servidor. Funcionou como um encanto.

Derek Downey
fonte
Estude cuidadosamente o algoritmo se você tiver as duas cláusulas _do_e _ignore_. Fica complicado.
Rick James
4

O problema com a resposta de Derek Downey nesta postagem é que sempre funcionará da mesma maneira (ativada ou desativada).

Se você está em uma situação em que deseja que a maioria das concessões seja replicada, mas não esta - ou não deseja devolver o mysql (necessário para carregar o arquivo my.conf modificado), você pode fazer o seguinte:

SET session sql_log_bin = 0;

GRANT SELECT ON *.* TO `foo`@`localhost` IDENTIFIED BY 'bar';

SET session sql_log_bin = 1;

Lembre-se de que a última configuração de linha sql_log_bin = 1é muito importante, porque sem ela você não replicará nada.

user13170
fonte
2
ao fazer referência a outras respostas, você deve fazer referência ao nome do usuário que adicionou a resposta em vez de "a resposta acima". A ordem das respostas muda à medida que as respostas são votadas para cima e para baixo etc.
Max Vernon