Introduction
Le nombre d’étapes manuelles pour configurer une réplication est élevé (réplication basée sur la position dans le log binaire ou GTID), en particulier lorsque l’instantané des bases de données du serveur source est effectué.
À partir de MySQL 8.0.17, le nouveau plugin CLONE simplifie le provisionnement des replica.
Dans cet article, une instance MySQL est clonée pour de la réplication à l’aide de ce plugin.
La terminologie suivante est adoptée lors de l’utilisation du plugin CLONE :
- Le serveur source est appelé le serveur donateur (donor).
- Le serveur cible est appelé le serveur destinataire (recipient).
Quelques limitations :
- Les instructions DDL (
CREATE DROP ALTER
) etTRUNCATE
ne sont pas permises durant un clônage, seules les intructions DML concurrentes sont autorisées. Les commandes DDL sont bloquées dans le serveur donateur lorsqu’un clônage est en cours. - Les versions MySQL doivent être exactement les mêmes, jusqu’aux numéros de versions mineures.
- Les fichiers de logs binaires (Binary logs) ne sont pas clônées.
- Seules les tables InnoDB sont clônées. Les tables MyISAM ou CSV sont clônées mais uniquement les structures, pas les données.
La progression de l’opération CLONE peut être surveillée.
Explorons cette nouvelle fonctionnalité : étapes, mécanisme interne… Un clônage distant est réalisé dans cet article.
Installation du plugin CLONE
Sur les deux serveurs (donateur et destinataire), le plugin CLONE est installé : au démarrage du serveur ou à l’exécution
Au démarrage du serveur :
$CFG/vpsfrsqlpac(1|2).cfg
[mysqld]
plugin-load-add=mysql_clone.so
clone=FORCE_PLUS_PERMANENT
En cours d’exécution (runtime) :
(vpsfrsqlpac1|2) mysql> INSTALL PLUGIN CLONE SONAME 'mysql_clone.so';
S’il y a un problème lors de l’installation, vérifier la variable plugin_dir
:
(vpsfrsqlpac1|2) mysql> SHOW VARIABLES LIKE 'plugin_dir';
+---------------+----------------------------------+ | Variable_name | Value | +---------------+----------------------------------+ | plugin_dir | /opt/mysql/mysql-8.0/lib/plugin/ | +---------------+----------------------------------+
Vérifier l’installation :
(vpsfrsqlpac1|2) mysql> SELECT plugin_name, plugin_status FROM information_schema.plugins WHERE plugin_name='clone';
+-------------+---------------+ | plugin_name | plugin_status | +-------------+---------------+ | clone | ACTIVE | +-------------+---------------+
Vérification des prérequis (optionnel)
Vérifier certains prérequis si une personnalisation a été configurée (innodb_data_file_path
, localisation et nom des fichiers undo…).
Si il n’y a pas de personnalisation, sauter cette étape.
Vérifier les variables innodb_data_file_path
et innodb_page_size
, elles doivent être identiques :
(vpsfrsqlpac1|2) mysql> SHOW VARIABLES LIKE 'innodb_data_file_path'; (vpsfrsqlpac1|2) mysql> SHOW VARIABLES LIKE 'innodb_page_size';
+-----------------------+------------------------+ | Variable_name | Value | +-----------------------+------------------------+ | innodb_data_file_path | ibdata1:12M:autoextend | | innodb_page_size | 16384 | +-----------------------+------------------------+
Les noms des fichiers Undo dans le donateur doivent être uniques car ils vont être regroupés et clônés vers le destinataire dans le répertoire innodb_undo_directory
.
(vpsfrsqlpac1) mysql> SELECT tablespace_name, file_name FROM information_schema.files WHERE file_type LIKE 'UNDO LOG';
+-----------------+------------+ | TABLESPACE_NAME | FILE_NAME | +-----------------+------------+ | innodb_undo_001 | ./undo_001 | | innodb_undo_002 | ./undo_002 | +-----------------+------------+
Le paramètre max_allowed_packet
doit être supérieur à 2MB dans les serveurs donateur et destinataire :
(vpsfrsqlpac1|2) mysql> SHOW VARIABLES LIKE 'max_allowed_packet';
+--------------------+----------+ | Variable_name | Value | +--------------------+----------+ | max_allowed_packet | 67108864 | +--------------------+----------+
Préparation du serveur donateur
Un user avec le privilège BACKUP_ADMIN
est créé dans le serveur donateur :
(vpsfrsqlpac1) mysql> CREATE USER clone_user@'%' IDENTIFIED BY '***************'; (vpsfrsqlpac1) mysql> GRANT BACKUP_ADMIN on *.* TO clone_user@'%'; (vpsfrsqlpac1) mysql> SHOW GRANTS FOR clone_user@'%';
+-----------------------------------------------+ | Grants for clone_user@% | +-----------------------------------------------+ | GRANT USAGE ON *.* TO `clone_user`@`%` | | GRANT BACKUP_ADMIN ON *.* TO `clone_user`@`%` | +-----------------------------------------------+
Préparation du serveur donateur
Garder à l’esprit que la base mysql
est également clônée : les propriétés et le mot de passe du compte root
seront ceux du serveur donateur.
Aussi, sauvegarder quelques informations avant le clônage si nécessaire :
- Users, passwords, plugin d’authentification (
mysql.user
). - Grants.
- Serveurs distants (
mysql.servers
) …
Si l’opération de clônage n’est pas réalisée avec le compte root
,
le compte utilisé pour le clônage doit avoir le privilège CLONE_ADMIN
:
(vpsfrsqlpac2) mysql> CREATE USER clone_user@'%' IDENTIFIED BY '***************'; (vpsfrsqlpac2) mysql> GRANT CLONE_ADMIN on *.* TO clone_user@'%'; (vpsfrsqlpac2) mysql> SHOW GRANTS FOR clone_user@'%';
+----------------------------------------------+ | Grants for clone_user@% | +----------------------------------------------+ | GRANT USAGE ON *.* TO `clone_user`@`%` | | GRANT CLONE_ADMIN ON *.* TO `clone_user`@`%` | +----------------------------------------------+
Le privilège CLONE_ADMIN
comprend les privilèges BACKUP_ADMIN
et SHUTDOWN
.
L’adresse du serveur donateur est ajoutée dans la variable clone_valid_donor_list
, il s’agit d’une couche de sécurité :
(vpsfrsqlpac2) mysql> SET GLOBAL clone_valid_donor_list = 'vpsfrsqlpac1:40008';
Exécution de la commande CLONE
La commande CLONE
est exécutée depuis le serveur destinataire :
(vpsfrsqlpac2) mysql> CLONE INSTANCE FROM clone_user@vpsfrsqlpac1:40008 IDENTIFIED BY '**********'
Ajouter l’option DATA DIRECTORY = '<dir>'
pour clôner une instance dans un autre répertoire sans supprimer les données existantes du serveur destinataire.
Avec cette option, l’opération de clônage ne redémarre pas le serveur destinataire pour basculer vers ce répertoire.
Vérification de la progression
La progression du clônage est disponible dans la table performance_schema.clone_status
:
SELECT state as "State", CAST(BEGIN_TIME AS DATETIME) as "Start time", CASE WHEN end_time IS NULL THEN LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(begin_time))), 10, ' ') ELSE LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(begin_time))), 10, ' ') END as "Duration" FROM performance_schema.clone_status;
+-------------+---------------------+------------+ | State | Start time | Duration | +-------------+---------------------+------------+ | In Progress | 2021-01-20 01:34:29 | 1.22 m | +-------------+---------------------+------------+
Les détails de la progression du clônage peuvent être surveillés en interrogeant la table performance_schema.clone_progress
:
SELECT stage as "Stage", state as "State", CAST(begin_time AS TIME) as "Start time", CASE WHEN end_time IS NULL THEN LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(begin_time))), 10, ' ') ELSE LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(begin_time))), 10, ' ') END as "Duration", LPAD(CONCAT(ROUND(estimate/1024/1024,0), " MB"), 16, ' ') as "Estimate", CASE WHEN begin_time IS NULL THEN LPAD('0%', 7, ' ') WHEN estimate > 0 THEN LPAD(CONCAT(CAST(ROUND(data*100/estimate, 0) AS CHAR), "%"), 7, ' ') WHEN end_time IS NULL THEN LPAD('0%', 7, ' ') ELSE LPAD('100%', 7, ' ') END as "Done(%)" FROM performance_schema.clone_progress;
+-----------+-------------+------------+------------+------------------+---------+ | Stage | State | Start time | Duration | Estimate | Done(%) | +-----------+-------------+------------+------------+------------------+---------+ | DROP DATA | Completed | 09:59:21 | 845.87 ms | 0 MB | 100% | | FILE COPY | In Progress | 09:59:21 | 1.98 m | 3254 MB | 42% | | PAGE COPY | Not Started | NULL | NULL | 0 MB | 0% | | REDO COPY | Not Started | NULL | NULL | 0 MB | 0% | | FILE SYNC | Not Started | NULL | NULL | 0 MB | 0% | | RESTART | Not Started | NULL | NULL | 0 MB | 0% | | RECOVERY | Not Started | NULL | NULL | 0 MB | 0% | +-----------+-------------+------------+------------+------------------+---------+ +-----------+-----------+------------+------------+------------------+---------+ | Stage | State | Start time | Duration | Estimate | Done(%) | +-----------+-----------+------------+------------+------------------+---------+ | DROP DATA | Completed | 09:59:21 | 845.87 ms | 0 MB | 100% | | FILE COPY | Completed | 09:59:21 | 4.65 m | 3254 MB | 100% | | PAGE COPY | Completed | 10:04:01 | 301.54 ms | 0 MB | 100% | | REDO COPY | Completed | 10:04:01 | 300.47 ms | 0 MB | 100% | | FILE SYNC | Completed | 10:04:01 | 477.28 ms | 0 MB | 100% | | RESTART | Completed | 10:04:02 | 3.06 s | 0 MB | 100% | | RECOVERY | Completed | 10:04:05 | 470.53 ms | 0 MB | 100% | +-----------+-----------+------------+------------+------------------+---------+
Le statut final (succès / échec) est stocké dans la table performance_schema.clone_status
:
(vpsfrsqlpac2) mysql> SELECT state, begin_time, end_time, source, error_no, error_message FROM performance_schema.clone_status
+-----------+-------------------------+-------------------------+--------------------+----------+---------------+ | state | begin_time | end_time | source | error_no | error_message | +-----------+-------------------------+-------------------------+--------------------+----------+---------------+ | Completed | 2021-01-20 09:59:21.126 | 2021-01-20 10:04:06.204 | vpsfrsqlpac1:40008 | 0 | | +-----------+-------------------------+-------------------------+--------------------+----------+---------------+
Gestion des erreurs
Un verrou de sauvegarde (backup lock) est pris pour bloquer les opérations DDL dans le serveur donateur et
le timeout pour acquérir ce verrou est contrôlé par le paramètre clone_ddl_timeout
: les opérations DDL sont susceptibles de générer une erreur si ce timeout est atteint.
Si une erreur se produit, l’opération de clônage est annulée (roll back) et toutes les données clônées sont supprimées.
À ce stade, les données utilisateur ont été détruites dans le serveur destinataire (bases de données…), mais pas dans la base de données mysql
,
le serveur destinataire est toujours dans un état cohérent pour exécuter des commandes d’administration.
L’échange de la base mysql
par son clône est effectué juste avant l’étape finale de redémarrage, le clônage peut être réexécuté sans étapes supplémentaires
une fois que la cause de l’erreur a été identifiée et corrigée.
+--------+-------------------------+-------------------------+--------------------+----------+---------------------------+
| state | begin_time | end_time | source | error_no | error_message |
+--------+-------------------------+-------------------------+--------------------+----------+---------------------------+
| Failed | 2021-01-20 12:20:50.535 | 2021-01-20 12:23:26.844 | vpsfrsqlpac1:40008 | 3862 | Clone Donor Error: 1317 : |
| | | | | | Query execution was |
| | | | | | interrupted. |
+--------+-------------------------+-------------------------+--------------------+----------+---------------------------+
(vpsfrsqlpac2) mysql> CLONE INSTANCE FROM clone_user@vpsfrsqlpac1:40008 IDENTIFIED BY '**********';
L’étape en erreur est extraite en interrogeant la table performance_schema.clone_progress
:
+-----------+-------------+------------+------------+------------------+---------+
| Stage | State | Start time | Duration | Estimate | Done(%) |
+-----------+-------------+------------+------------+------------------+---------+
| DROP DATA | Completed | 02:20:51 | 917.33 ms | 0 MB | 100% |
| FILE COPY | Failed | 02:20:52 | 2.59 m | 3254 MB | 55% |
| PAGE COPY | Not Started | NULL | NULL | 0 MB | 0% |
| REDO COPY | Not Started | NULL | NULL | 0 MB | 0% |
Pour les tables non InnoDB (MyISAM, CSV), un simple avertissement est consigné dans le fichier de log du serveur destinataire:
2021-01-20T09:52:23.533528Z 0 [Warning] [MY-013461] [InnoDB] Non innodb table: sqlpac.article_en_details is not cloned and is empty.
Étapes du clônage
Les bases de données utiliseur sont supprimées pour être remplacées mais le process n’écrase pas les fichiers systèmes (tablespace système mysql
, undo, tablespace par défaut innodb, buffer pool…),
il créé des fichiers .#clone
pour ceux-ci :
-rw-r----- 1 mysql dba 68852 Jan 20 09:38 ib_buffer_pool
-rw-r----- 1 mysql dba 86048 Jan 20 09:38 ib_buffer_pool.#clone
-rw-r----- 1 mysql dba 79691776 Jan 20 09:38 ibdata1
-rw-r----- 1 mysql dba 79691776 Jan 20 09:38 ibdata1.#clone
-rw-r----- 1 mysql dba 26214400 Jan 20 09:38 mysql.ibd
-rw-r----- 1 mysql dba 26214400 Jan 20 09:38 mysql.ibd.#clone
-rw-r----- 1 mysql dba 22020096 Jan 20 09:38 undo_001
-rw-r----- 1 mysql dba 0 Jan 20 09:38 undo_001.#clone
-rw-r----- 1 mysql dba 22020096 Jan 20 09:38 undo_002
-rw-r----- 1 mysql dba 0 Jan 20 09:38 undo_002.#clone
drwxr-x--- 2 mysql dba 4096 Jan 20 09:38 '#clone'
Un répertoire #clone
est créé, répertoire qui contient des fichiers temporaires ou persistents pour la mécanique interne du clônage :
#new_files
#old_files
#replace_files
#status_error
#status_files
#status_in_progress
#status_recovery
#view_progress
#view_status
Les 2 derniers fichiers #view_progress
et #view_status
sont persistents et utilisés pour alimenter respectivement les tables
performance_schema.clone_progress
et performance_schema.clone_status
.
Lorsque le processus de clônage terminé arrive à son terme, il échange les fichiers .#clone
et si l’option DATA DIRECTORY
n’est pas utilisée, il redémarre le serveur destinataire
avec la nouvelle commande SQL MySQL 8.0 RESTART
.
Activation de la réplication
Lors du clônage, le fichier binlog + la position et la valeur GTID si elle existe sont extraits du serveur donateur et transférés dans la table performance_schema.clone_status
du serveur destinataire.
(vpsfrsqlpac2) mysql> SELECT * FROM performance_schema.clone_status \G;
ID: 1 PID: 0 STATE: Completed BEGIN_TIME: 2021-01-19 09:32:17.855 END_TIME: 2021-01-19 09:37:02.582 SOURCE: vpsfrsqlpac1:40008 DESTINATION: LOCAL INSTANCE ERROR_NO: 0 ERROR_MESSAGE: BINLOG_FILE: binlog-srvmysqlpac.000010 BINLOG_POSITION: 184592856 GTID_EXECUTED:
C’est fini ! La réplication peut être démarrée en utilisant ces valeurs (binary log file + position dans ce cas pratique) :
MySQL >= 8.0.23 | |
---|---|
|
|
Pas besoin de redéfinir les filtres de réplication : ils sont spécifiés dans les fichiers de configuration ou en paramètres de démarrage des serveurs MySQL,
ils ne sont pas modifiés et affectés par les commandes CLONE
/ RESTART
.
Conclusion
Le nouveau plugin CLONE est puissant pour provisionner des réplica. 2 inconvénients majeurs :
- Les instructions DDL et
TRUNCATE
sont verrouillées lors du clônage d’un serveur source : certaines applications utilisent intensivement ces commandes (tables temporaires…). - Les versions MySQL doivent être rigoureusement les mêmes, en raison du dictionnaire MySQL clôné avec la base
mysql
.