MySQL-Replikationsprobleme nach einem Stromausfall

MySQL-Replikationsprobleme nach einem Stromausfall

Nach einem Stromausfall in unserem Rechenzentrum haben die untergeordneten MySQL-Datenbanken Probleme.

Dies steht in den Protokollen für einen der Slaves:

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

Und die Konsole zeigt etwas mehr Details:

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

Wenn wir uns die Bin-Protokolle auf dem Master ansehen, sehen wir:

-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. Der Slave-Status zeigt, dass Exec_Master_Log_Pos und Read_Master_Log_Pos beide 724207814 sind, für das Binärprotokoll bin-log.004712. Meines Wissens ist dieser Wert die Byteposition in der Binärprotokolldatei.
  2. Diese Datei bin-log.004712 ist nur 724200412 Bytes groß, daher denken die Slaves, dass sie 7402 Bytes mehr Arbeit geleistet haben, als tatsächlich in der Datei gespeichert ist (die sich auf einem ext3-FS, RAID-10, RHEL5 befindet). Daher die Fehlermeldung über eine unmögliche Protokollposition usw.

Wie lassen sich die Sklaven am besten reparieren?

Optionen, die ich in Betracht ziehe:

  1. Ich stelle jeden Slave so ein, dass er auf Position 0 in der nächsten Binärprotokolldatei (bin-log.004713) zeigt, und lasse sie los. Ich bin mir jedoch nicht sicher, wie sicher das ist oder wie viele Daten dabei verloren gehen könnten.
  2. Muss ich stattdessen eine vollständige Sicherung und Wiederherstellung durchführen (mit vermutlich damit verbundenen Ausfallzeiten aufgrund von Tabellensperren für die InnoDB-Tabellen)? Das möchte ich nach Möglichkeit vermeiden.

AKTUALISIEREN:

Ich habe eine weitere Option vergessen: die Ausführungsposition jedes Slaves ein wenig zurückzuverweisen, damit er versucht, Befehle zu replizieren, die er bereits aus bin-log.004712 verarbeitet hat.

Antwort1

Ich habe mich für die erste Option entschieden.

Das funktionierte bis zu dem Punkt, an dem der Slave versuchte, Einfügungen vorzunehmen, die mit den Primärschlüsseln in Konflikt gerieten. Der Slave hatte mehr Arbeit erledigt, als das Binärprotokoll des Masters gespeichert hatte, wie bereits erwähnt. Ein Aspekt, den ich nicht erwartet hatte, war, dass der Slave Daten enthielt, die nicht im Master vorhanden waren; d. h. der Slave speicherte einige Transaktionen vor dem Stromausfall, den der MasterHATTE NICHTblieb bestehen.

Da es sich in meinem Fall nicht um zahlungsbezogene oder ähnliche Transaktionen handelte, habe ich die Daten vom Slave gelöscht (wodurch einige Daten verloren gingen, die zwar stattgefunden hatten, aber im Master nicht vorhanden waren) und die Replikation dann erneut ausgeführt. Dadurch wurden die Slaves vollständig auf den neuesten Stand gebracht. Wären die Daten wichtiger gewesen, hätten wir über ausreichende Auto-Increment-Offsets verfügt, um uns etwas Spielraum für die manuelle Bearbeitung der Daten zu geben und sicherzustellen, dass die referenzielle Integrität nicht beeinträchtigt wurde. Zum Glück mussten wir das in diesem Fall nicht tun.

Für eine Maschine in (passiver) Master-Master-Konfiguration, die sich in dieser misslichen Lage befand, habe ich einen ähnlichen Ansatz gewählt. Mit passivem Master-Master meine ich, dass wir einen aktiven Master (ServerA) haben, auf den alle Schreibvorgänge gehen, und einen passiven Master (ServerB), der dafür sorgt, dass Schemaaktualisierungen ohne Ausfallzeiten stattfinden können. Die Daten im aktiven Master (ServerA) wurden als die wahren Werte gewählt, obwohl wir wussten, dass wir dadurch einige persistente Transaktionen verloren, die nicht als wichtig erachtet wurden.

  • Die Protokolldatei und die Position auf dem Slave wurden geändert.

    CHANGE MASTER MASTER_LOG_FILE='bin-log.004713', MASTER_LOG_POS=0; -- on serverB
    
  • Die Slave-Replikation wurde auf dem passiven Master (Server B) neu gestartet, bis sie, wie bei den anderen Slaves, aufgrund von Verletzungen der Primärschlüsseleinschränkung fehlschlug.

     START SLAVE; -- on serverB
    
  • Slave-Replikation vom passiven Master (ServerB) zum aktiven Master (ServerA) gestoppt.

    STOP SLAVE; -- on serverA
    
  • LÖSCHEN Sie die Zeilen auf dem Slave (Server B), die im Master auf Server A nicht vorhanden waren.

    DELETE FROM SOME_TABLE WHERE ID IN (???,????); -- on serverB
    SHOW MASTER STATUS\G; -- get the new master log position on serverB
    
  • Verschieben Sie die Slave-Exec-Position des aktiven Masters (ServerA), um diese Löschungen vom passiven Master (ServerB) zu überspringen.

    CHANGE MASTER TO MASTER_LOG_POS=???; --on serverA; use the value just obtained from serverB
    
  • Starten Sie die Replikation sowohl auf dem aktiven Master (Server A) als auch auf dem passiven Master neu.

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

Antwort2

Es hängt davon ab, wie wichtig es ist, dass die Slaves exakte Repliken des Masters sind. Ihre erste Option wird bis zu einem gewissen Grad funktionieren, aber den Slaves könnten durchaus Informationen des Masters fehlen. Wenn Sie damit leben können, weil die Daten flüchtig sind oder so, dann entscheiden Sie sich dafür. Wenn es wichtig ist, dass die Slaves richtige Repliken sind, dann ist die zweite Option wahrscheinlich Ihre einzige Wahl. Leider reagiert die MySQL-Replikation nicht freundlich auf unerwartete Unterbrechungen jeglicher Art. Ich habe festgestellt, dass diese Art von Problemen in meiner Replikationsarchitektur viel häufiger auftreten, als mir lieb ist.

verwandte Informationen