Problemas de replicação do MySQL após uma queda de energia

Problemas de replicação do MySQL após uma queda de energia

Após uma queda de energia em nosso data center, os bancos de dados escravos MySQL estão com dificuldades.

Isto está nos logs de um dos escravos:

100118 10:05:56 [Note] Slave I/O thread: connected to master 'repl@db1:3306',  replication started in log 'bin-log.004712' at position 724207814
100118 10:05:56 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236)
100118 10:05:56 [ERROR] Got fatal error 1236: 'Client requested master to start replication from impossible position' from master when reading data from binary log
100118 10:05:56 [Note] Slave I/O thread exiting, read up to log 'bin-log.004712', position 724207814

E o console mostra um pouco mais de detalhes:

mysql> show slave status \G;
*************************** 1. row ***************************
             Slave_IO_State:
                Master_Host: db1
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 10
            Master_Log_File: bin-log.004712
        Read_Master_Log_Pos: 724207814
             Relay_Log_File: mysqld-relay-bin.000105
              Relay_Log_Pos: 98
      Relay_Master_Log_File: bin-log.004712
           Slave_IO_Running: No
          Slave_SQL_Running: Yes
            Replicate_Do_DB: mmplive1,mmpjcr,fui
        Replicate_Ignore_DB:
         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: 724207814
            Relay_Log_Space: 98
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: NULL
1 row in set (0.00 sec)

ERROR:
No query specified

Observando os logs do bin no mestre, temos:

-rw-rw---- 1 mysql mysql  724200412 Jan 18 09:22 bin-log.004712
-rw-rw---- 1 mysql mysql       1904 Jan 18 09:27 bin-log.index
-rw-rw---- 1 mysql mysql    5046830 Jan 18 11:22 slow-log
-rw-rw---- 1 mysql mysql  198249613 Jan 18 11:24 bin-log.004713
  1. O status Slave mostra que Exec_Master_Log_Pos e Read_Master_Log_Pos são ambos 724207814, para o log binário bin-log.004712. Entendo que esse valor é a posição do byte no arquivo de log binário.
  2. Esse arquivo bin-log.004712 tem apenas 724200412 bytes, então os escravos pensam que fizeram 7402 bytes a mais de trabalho do que realmente persistiu no arquivo (que está em um ext3 fs, RAID-10, RHEL5). Daí a mensagem de erro sobre posição impossível do log, etc.

Qual é a melhor maneira de consertar os escravos?

Opções que estou considerando:

  1. Definir cada escravo para apontar para a posição 0 no próximo arquivo bin-log (bin-log.004713) e deixá-los ir, mas não tenho certeza de quão seguro isso é ou de quantos dados podem ser perdidos.
  2. Em vez disso, preciso fazer um backup e restauração completos (com tempo de inatividade associado presumido devido a bloqueios de tabela nas tabelas do InnoDB)? Eu gostaria de evitar isso, se possível.

ATUALIZAR:

Perdi outra opção: apontar um pouco para trás cada posição executada do escravo, para que ele tentasse replicar comandos que já havia processado do bin-log.004712.

Responder1

Eu optei pela primeira opção.

Isso funcionou até o ponto em que o escravo começou a tentar fazer inserções que conflitavam com as chaves primárias. O escravo fez mais trabalho do que o log-bin mestre persistiu, como mencionado anteriormente. Um aspecto que não previ foi que o escravo continha dados que não estavam no mestre; ou seja, o escravo persistiu algumas transações antes da queda de energia que o mestreNÃO TINHApersistiu.

Como no meu caso essas transações não eram relacionadas a pagamentos ou similares, optei por deletar os dados do escravo (perdendo assim alguns dados que haviam acontecido, mas que não existiam no mestre) e depois deixei a replicação rodar novamente . Isso atualizou completamente os escravos. Se os dados fossem mais importantes, teríamos compensações de incremento automático suficientes para nos dar alguma margem de manobra para organizar manualmente os dados e garantir que a integridade referencial não fosse comprometida. Felizmente não precisamos fazer isso neste caso.

Para uma máquina em configuração mestre-mestre (passiva) que estava nessa situação, escolhi uma abordagem semelhante. Por mestre-mestre passivo, quero dizer que temos um mestre ativo (servidorA), que é para onde vão todas as gravações, e um mestre passivo (servidorB) que está em vigor para permitir que as atualizações do esquema ocorram sem tempo de inatividade. Os dados do mestre ativo (serverA) foram escolhidos como valores verdadeiros, apesar de sabermos que isso significava que perdemos algumas transações persistentes que não foram consideradas importantes.

  • Alterado o arquivo de log e posição no escravo.

    CHANGE MASTER MASTER_LOG_FILE='bin-log.004713', MASTER_LOG_POS=0; -- on serverB
    
  • Reiniciada a replicação do escravo no mestre passivo (servidorB) até falhar com violações de restrição de chave primária, como acontece com os outros escravos.

     START SLAVE; -- on serverB
    
  • Replicação escrava interrompida do mestre passivo (servidorB) para o mestre ativo (servidorA).

    STOP SLAVE; -- on serverA
    
  • DELETE as linhas do escravo (servidorB) que não existiam no mestre do servidorA.

    DELETE FROM SOME_TABLE WHERE ID IN (???,????); -- on serverB
    SHOW MASTER STATUS\G; -- get the new master log position on serverB
    
  • Mova a posição exec do escravo mestre ativo (servidorA) para ignorar essas exclusões do mestre passivo (servidorB).

    CHANGE MASTER TO MASTER_LOG_POS=???; --on serverA; use the value just obtained from serverB
    
  • Reinicie a replicação no mestre ativo (serverA) e no mestre passivo.

    START SLAVE; -- on both machines. serverA does nothing and serverB starts catching up.
    

Responder2

Dependeria da importância de os escravos serem réplicas exatas do mestre. Sua primeira opção funcionará até certo ponto, mas os escravos podem muito bem estar perdendo informações do mestre. Se você consegue conviver com isso porque os dados são transitórios ou algo assim, vá em frente. Se for importante que os escravos sejam réplicas adequadas, então a segunda opção é provavelmente sua única opção. Infelizmente, a replicação do MySQL não aceita nenhum tipo de interrupção inesperada. Descobri que esses tipos de problemas são muito mais frequentes do que gostaria em minha arquitetura de replicação.

informação relacionada