Si vous utilisez les fonctions de réplication de MySQL ou MariaDB, il peut arriver que votre slave bloque sur une instruction qui devrait avoir un identifiant unique mais que le serveur tente d’insérer deux fois.
Et quand c’est le cas, la réplication des données prend fin donc c’est un problème à corriger rapidement si vous voulez que votre système haute disponibilité perdure et soit vraiment efficace en cas de coup dur.
Identification du problème
Je me suis rendu compte du problème lorsque j’ai ajouté de nouvelles bases à répliquer : j’ai relancé la procédure d’installation, relancé les serveurs, ajouté les nouvelles positions, démarré les slaves.
On regarde le status du slave :
MariaDB [(none)]> SHOW SLAVE STATUS\G
Code language: CSS (css)
Résultat :
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.134.23.164
Master_User: replicator
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000210
Read_Master_Log_Pos: 2753885
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 103794
Relay_Master_Log_File: mariadb-bin.000210
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: 1062
Last_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
Skip_Counter: 0
Exec_Master_Log_Pos: 1563407
Relay_Log_Space: 1296874
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: 1062
Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
1 row in set (0.00 sec)
Code language: JavaScript (javascript)
Comme on peut le constater, plusieurs choses ne tournent pas rond et empêchent la synchronisation des données entre nos deux serveurs :
Slave_SQL_Running: No
Last_SQL_Errno: 1062
Last_SQL_Error: Error 'Duplicate entry '56-724' for key 'PRIMARY'' on query. Default database: 'frenchy'. Query: 'INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`) VALUES (56, 724)'
Code language: JavaScript (javascript)
Solution : un RESET sur le slave
En me documentant sur le problème, j’ai lu pas mal de choses sur le net. Certains préfèrent cacher l’erreur, au risque de perdre des données. D’autres préfèrent tout effacer pour recommencer la réplication.
Aucune de ces “solutions” ne me conviennent donc nous allons procéder autrement. Comme l’erreur n’apparaît que sur le serveur BACKUP
et non sur le serveur principal, c’est sur lui que nous travaillerons.
Sur le serveur BACKUP
, dans MariaDB, on arrête notre slave :
MariaDB [(none)]> STOP SLAVE;
Query OK, 0 rows affected (0.01 sec)
Code language: CSS (css)
On flush les privilèges et donc les utilisateurs connectés :
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
Code language: CSS (css)
On efface les fichiers logs de notre slave. C’est comme effacer une ardoise pour repartir sur des bases saines. Cela ne supprime aucune donnée – cf le manuel sur RESET :
MariaDB [(none)]> RESET SLAVE;
Query OK, 0 rows affected (0.00 sec)
Code language: CSS (css)
Et on redémarre notre slave :
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
Code language: CSS (css)
On vérifie de nouveau le status de notre slave :
MariaDB [(none)]> SHOW SLAVE STATUS\G
Code language: CSS (css)
Résultat :
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.134.23.164
Master_User: replicator
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000196
Read_Master_Log_Pos: 77900062
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 6318821
Relay_Master_Log_File: mariadb-bin.000192
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
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: 6318531
Relay_Log_Space: 344030331
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: 833890
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
1 row in set (0.00 sec)
Code language: CSS (css)
Nous avons bien :
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Code language: HTTP (http)
Et voilà, plus d’erreur et une réplication active dans les deux sens.