How to fix Mysql replication with GTID

Mysql replication

A partire da mysql 5.6 è stato introdotto un nuovo modo per gestire la replicazione master-slave chiamata GTID (global transaction identifier).
Questa nuova modalità fondamentalmente fa si che le varie "transazioni" quando applicate vengano battezzate in maniera univoca all'interno del master e vengano propagate agli slave con l'identificazione completa della transazione. Gli slave applicano quindi le varie transazioni seguendo i GTID uno per volta.
Ma come si ripristina una replica master slave che si è rotta?

Procediamo con ordine....

1) chiediamo a mysql come sta (il nostro demone apprezzerà che gli si chieda con gentilezza il suo stato di salute):

mysql> show slave status\G;

e lui sbrodolerà qualcosa del tipo:

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: slave22.uccio.org
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000332
          Read_Master_Log_Pos: 780374059
               Relay_Log_File: relay-bin.000986
                Relay_Log_Pos: 924034745
        Relay_Master_Log_File: mysql-bin.000323
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1032
                   Last_Error: Could not execute Delete_rows event on table mikymouse.disney; Can't find record in 'timezone', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000323, end_log_pos 924878703
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 924034532
              Relay_Log_Space: 10444179934
              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
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1032
               Last_SQL_Error: Could not execute Delete_rows event on table mikymouse.disneye; Can't find record in 'timezone', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000323, end_log_pos 924878703
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1002
                  Master_UUID: 9c8faad2-6451-11ea-8e25-005056bd4b73
             Master_Info_File: /mysql/db/data/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State:
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp: 211001 08:28:23
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 9c8faad2-6451-11ea-8e25-005056bd4b73:66-474899604
            Executed_Gtid_Set: 9a07ef63-6451-11ea-9f73-005056bdfb0b:1-13076215, 9c8faad2-6451-11ea-8e25-005056bd4b73:1-340827328:340827330-340827341:340827343-340827678:340827680-460249141
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.01 sec)

Ora che sappimo cosa non gli è piaciuto... dobbiamo capire come aggiustarlo.

2) questo passo diciamo che dipende dall'errore, qui dobbiamo "correggere" i dati, a volte potrebbe bastare non fare nulla ma altre dobbiamo sistemare i dati affinche la query fallita venga in qualche modo eseguita.

3) facciamo ripartire la replica:

ora viene la parte divertente, da che punto faccio ripartire la replica?
Dell'output di prima la parte interessante è:

 Executed_Gtid_Set: 9a07ef63-6451-11ea-9f73-005056bdfb0b:1-13076215, 9c8faad2-6451-11ea-8e25-005056bd4b73:1-340827328:340827330-340827341:340827343-340827678:340827680-599697725

da manuale mysql ci viene detto: ".... fai ripartire dall'ultima transazione eseguita...." wooow facile ma quale è?
Se leggiamo gli esempi del manuale sembra facile perche c'è un ID ed un progressivo ma nel' mondo reale come potete vedere le cose ben diverse.
Ravanando nel DB possiamo però aiutarci:

SELECT * FROM performance_schema.replication_applier_status_by_worker\G;

che ci restituirà una serie di informazioni essenziali:

MySQL [(none)]> SELECT * FROM performance_schema.replication_applier_status_by_worker\G;
*************************** 1. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 0
            THREAD_ID: 53943203
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION: 9c8faad2-6451-11ea-8e25-005056bd4b73:599697725
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
1 row in set (0.036 sec)

a questo punto sappiamo da dove ripartire perche mysql ci ha dato:

  • ID del master: 9c8faad2-6451-11ea-8e25-005056bd4b73
  • Posizione: 599697725

Sapendo che dobbiamo riprendere dalla posizione successiva ci basta eseguire:

STOP SLAVE;
SET GTID_NEXT='9c8faad2-6451-11ea-8e25-005056bd4b73:599697726';
BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC';

che nella pratica inietta una transazione vuota nella posizione "che si è rotta" portandoci di fatto a re-inseguire il master subito dopo alla transazione fallita.

A questo punto se tutto è andato bene la nostra replica starà processando gli arretrati per ri-allinearsi con il master.

Tags