Lors de migration de bases, ou tout simplement restauration de dump, un des problèmes les plus courants est d'avoir des problèmes d'encodage de caractères.
L'encodage de caractères est complexe sous MySQL car il peut être géré à plusieurs niveaux (serveur, base, table, etc.).
Voici donc quelques astuces qui peuvent servir (ou pas) :
MySQL dispose d'un cache, par exemple si vous faites deux fois un SELECT identique (et simple) sur une table qui n'a pas été modifiée, le 2ᵉ SELECT devrait être renvoyé par le CACHE.
Pour vérifier que cela fonctionne, vous pouvez observer le compteur de cache hits :
~~~
mysql> show status like 'Qcache_hits';
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| Qcache_hits | 544667 |
+---------------+--------+
1 row in set (0.00 sec)
~~~
Un bug vicieux impacte MySQL 5.1 et 5.5 (corrigé à partir de 5.6.9) : si le nom de la base comporte des caractères spéciaux (le `-` par exemple) et que les tables sont en InnoDB… **le cache ne marche pas !!!!**
Pour augmenter le nombre maximal de fichiers pouvant être ouverts, vous pouvez ajuster le paramètre suivant(dans la limite permise par votre système d'exploitation) :
Un problème classique qui peut arriver suite à une migration d'une base de données contenant des vues. Si l'utilisateur qui a créé la vue (le _definer_) n'existe pas sur le nouveau serveur, la vue sera inutilisable:
~~~
mysql> SELECT * FROM myview;
MySQL ERROR 1449 (HY000) : The user specified as a definer ('root'@'localhost') does not exist
~~~
Il faut donc soit faire un sed dans le dump MySQL pour remplacer le definer si on est à l'étape de préparation de la migration.
Si la migration a déjà été faite et qu'il n'est plus possible de réinjecter un dump, il faut modifier la vue via `ALTER VIEW`, mais il est nécessaire d'indiquer la définition complète de la vue. Pour la connaitre:
~~~
mysql> SHOW CREATE VIEW myview;
~~~
Copier ensuite la définition complète, en remplaçant `CREATE` par `ALTER`, et bien sûr le definer de la vue par un utilisateur existant qui aura les droits sur la vue.
Si vous obtenez l'erreur ci-dessus, lors d'un mysqldump par exemple, et que les fichiers `${mysql_datadir}/foo/bar.{MYD,MYI}` sont vides mais pas le `.frm`, il faut réparer la table comme ceci:
Got error: 1290: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement when executing 'SELECT INTO OUTFILE'
Lors du passage à la version 5.5.53, la valeur par défaut est passée de _vide_ à `/var/lib/mysql-files` ce qui casse les *mysqldump* qui écrivent leurs fichiers ailleurs (malgré des droits systèmes adaptés).
Sur Debian, la nouvelle valeur par défaut est `/var/lib/mysql-files`. L'utilisation d'un lien symbolique de cet emplacement vers le dossier réel (par exemple `/home/mysqldump`) ne suffit pas et MySQL continue de refuser le dump.
Lorsqu'on souhaite que certains utilisateurs soient restreints en fonction de leur origine de connexion, on utilise le champ `Host` dans lequel on met autre chose que les valeurs classiques telles que `%` ou `localhost`.
Pour une restriction sur une seule IP, c'est simple on l'indique dans ce champ.
Pour une restriction par plage IP il faut donner une valeur de la forme `192.168.2.0/255.255.255.0`.
La notation CIDR (`192.168.2.0/24`) n'est pas supportée.
## Restauration d'une table depuis un dump complet
Pour extraire une table depuis un dump complet `dump.sql`, on détermine la liste des tables via `grep -n "Table structure"`, par exemple :
~~~
$ grep -n "Table structure" dump.sql
19:-- Table structure for table `wp-cgp`
43:-- Table structure for table `wp_WP_SEO_404_links`
73:-- Table structure for table `wp_WP_SEO_Redirection`
109:-- Table structure for table `wp_WP_SEO_Redirection_LOG`
143:-- Table structure for table `wp_acccess`
170:-- Table structure for table `wp_avant_premiere`
196:-- Table structure for table `wp_commentmeta`
223:-- Table structure for table `wp_comments`
265:-- Table structure for table `wp_icl_string_translations`
294:-- Table structure for table `wp_icl_strings`
322:-- Table structure for table `wp_investments`
396:-- Table structure for table `wp_links`
431:-- Table structure for table `wp_login_redirects`
458:-- Table structure for table `wp_mtouchquiz_answer`
486:-- Table structure for table `wp_mtouchquiz_question`
~~~
Si l'on veut extraire la table `wp_investments`, on détermine où commence et finit la table, ici elle commence à la ligne 322 et finit à la ligne 395 (juste avant la table suivante).
On peut ainsi utiliser `sed -n` pour extraire la table :
~~~
$ sed -n '[numéro_du_début_de_la_ligne],[numéro_de_fin_de_la_ligne] p' dump.sql > table.sql
~~~
Exemple avec la table *wp_investments* :
~~~
$ sed -n '322,395 p' dump.sql > wp_investments.sql
## Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
En cas d'erreur du type :
~~~
Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
~~~
cela signifie que votre BINLOG_FORMAT doit être en ROW car il l'était précédemment.
Vous pouvez vérifier que c'est bien le cas en faisant :
~~~
MariaDB [(none)]> show variables LIKE 'BINLOG_FORMAT';
## ERROR 1148: The used command is not allowed with this MySQL version
Si cette erreur survient lors d'une requête avec un LOAD DATA LOCAL INFILE il faut vérifié sur la variable *local_infile* est bien activé :
~~~
mysql> SHOW GLOBAL VARIABLES LIKE 'local_infile';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile | ON |
+---------------+-------+
~~~
Dans la configuration de mysql mettre :
~~~
local-infile=1
~~~
Et pour l'activer à chaud :
~~~
SET GLOBAL local_infile=ON;
~~~
Si une requête LOAD DATA LOCAL INFILE est faite par un script ou un applicatif qui lit la variable global [client], comme le .my.cnf d'un utilisateur, il faut ajouter la variable *loose-local-infile* dans le .my.cnf :
## Colonne Create Function à nulle lors de l'appel de procédures stockées
Avec Mysql <8.x,lorsdel'utilisationdeSHOWCREATEPROCEDUREouSHOWCREATEFUNCTION,silacolonneCreateFunctionrenvoieNULL,ilfautaccorderàl'utilisateurlesdroitsSELECTsurlatablemysql.proc:
~~~
GRANT SELECT ON mysql.proc TO user;
~~~
Pour MySQL >= 8.x, les droits SELECT globaux sont nécessaires.
Si une action ou une réplication est bloquée avec le message `incorrect key file` et incitant à réparer la table, c'est une fausse piste (il n'y a pas de REPAIR sur les tables InnoDB). Il se peut que ça soit en fait un tmpdir insuffisant en espace disponible pour accueillir les données temporaires. Il faut alors passer sur un tmpdir plus important (`/home/mysql-tmpdir` par exemple). Attention, cela nécessite un redémarrage du service.
## Lister les tables fragmentés
Souvent on execute un mysqltuner et celui ci indique que mysql contient des tables fragmentés, mais sans indiqués lequelles.
Si on veux lister toutes les tables fragmenté d'une instance MySQL, on peux executer cette requête :
~~~
SELECT ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables where DATA_FREE > 0;
~~~
Cela liste les tables qui ont un différentiel entre al longeur des données et la longeur de l'index, et le nombre de données non utilisé dans chaque table (data_free)
On peux égelement calculer le ratio d'espace non utilisé sur une table, exemple avec cette table `champ_supp_contact` :
C'est à dire que la table contient 50% d'espace vide.
Voici une requêtes SQL qui indique également le ratio de fragmentation de chaque tables :
~~~
SELECT ENGINE, concat(TABLE_SCHEMA, '.', TABLE_NAME) as table_name, round(DATA_LENGTH/1024/1024, 2) as data_length, round(INDEX_LENGTH/1024/1024, 2) as index_length, round(DATA_FREE/1024/1024, 2) as data_free, (data_free/(index_length+data_length)) as frag_ratio FROM information_schema.tables WHERE DATA_FREE > 0 ORDER BY frag_ratio DESC;
## Problème pour créer ou modifié des TRIGGER d'une base
Si un utilisateur mysql veut créer ou modifié un TRIGGER, par default il ne peut pas le faire, et mysql retourne l'erreur suivante :
~~~
You do not have the SUPER privilege and binary logging is enabled
~~~
Pour qu'un utilisateur puisse créer / modifié des TRIGGER, sans avoir le privilège SUPER, et lorsque les binlogs sont activé, il faut activer la variable *log_bin_trust_function_creators* de manière globale :
## Calculer la taille adéquate pour innodb_buffer_pool_size
On peux calculer la taille adéquate pour la variable innodb_buffer_pool_size sur un serveur mysql, avec la requête suivante :
~~~
SELECT CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3)) RIBPS FROM ( SELECT SUM(data_length+index_length) Total_InnoDB_Bytes FROM information_schema.tables WHERE engine='InnoDB') A;
~~~
Il ne faut pas oublié d'augmenté également le innodb_buffer_pool_instances si innodb_buffer_pool_size et suppérieur ou égal à 4Gio.
On mets une instances par Gigaoctet pour le innodb_buffer_pool_instances.
## Le plugin Munin "mysql2" ne graph rien
Dans les logs de Munin /var/log/munin/munin-node.log on voit des erreurs du style `Unknown section: INDIVIDUAL BUFFER POOL INFO at /etc/munin/plugins/mysql_tmp_tables line 1098`.
Il faut modifier le plugin `/usr/share/munin/plugins/mysql_`, dans la foncion `parse_innodb_status` et ajouter dans la `%section_map` la ligne suivante :
~~~
'INDIVIDUAL BUFFER POOL INFO' => \&skip,
~~~
On peut vérifier tout de suite le bon fonctionnement avec la commande `munin-run mysql_connections` ou n'importe quel autre module géré par ce plugin.
Après une relance de `munin-node` et attente de 10 minutes (2 passage de munin-node en cron), on devrait avoir des valeurs.
## Erreur Row Size Too Large avec InnoDB
Si lors de requêtes SQL il y a des erreurs du type, avec les bases / tables qui utilise le moteur InnoDB :
~~~
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
~~~
C'est qu'il faut convertir la table en format de ligne dynamique (DYNAMIC rox format) comme ceci :
Puis faire une recherche sur le definer dans le fichier généré.
## Extraire des logs dans les binlogs par rapport a une date de début et de fin avec mysqlbinlog
Si l'on veux extraire des requêtes des binlogs par rapport a une date de début et de fin, utile pour voir toutes les écritures qui ont été faite sur un serveur a un moment donner, on peux utilisé mysqldump comme ceci :
## Listé les Indexs non utilisé, avec la base information_schema
Voici une requêtes SQL qui se base sur la base `information_schema` et les tables `STATISTICS` et `INDEX_STATISTICS` qui liste les Indexes non utilisés.
Attention, le résultat de cette requête n'est pas fiable à 100%, car ça suppose qu'un index est inutilisé que s'il n'a jamais provoqué IO wait.
Les clés primaire et les indexs UNIQUE sont exclus :
On vérifie les erreurs avec les commandes `SHOW SLAVE STATUS` et `SHOW MASTER STATUS`.
En cas d'erreur, il faut « simplement » résoudre l'erreur, puis relancer la réplication avec la commande `START SLAVE`. Voici quelques erreurs possibles :
### Zapper l'erreur en cours
On peut faire manuellement :
~~~
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;
~~~
### Fichier de clé incorrect
~~~
Incorrect key file for table './base/table.MYI'; try to repair it
~~~
Il faut réparer la table concernée.
### Doublon sur clé unique
~~~
Duplicate entry 'NNNNNN' for key N
~~~
Une solution *peut* être de supprimer la ligne concernée (ou de zapper l'erreur).
### Beaucoup d'erreurs à ignorer
Si pour une raison ou un autre, on a plein de `DUPLICATE ENTRY` mais que l'est **sûr** de vouloir les ignorer, on peut faire cela en redémarrant MySQL avec le paramètre : `slave-skip-errors = 1062` ; on peut faire également cela avec d'autres types d'erreurs. Malheureusement, il faut forcément redémarrer MySQL car cette commande ne se fait pas à chaud : <http://bugs.mysql.com/bug.php?id=35611>
On peut également avoir d'autres erreurs, par exemple _Could not execute Delete_rows event on table foo.bar; Can't find record in 'bar', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log [...]_ et on mettre cette fois `slave-skip-errors = 1032`
Si plusieurs types d'erreur à ignorer : `slave-skip-errors = 1032,1062`
L'inconvénient est qu'il faut redémarrer MySQL. Pour éviter cela on peut automatiser le zap de l'erreur.
Exemple avec l'erreur _1062_ :
~~~
# while true; do while mysql -e "show slave status" | grep '1062.Error.*REPORT'; \
do mysql -e "SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;"; done ; sleep 1; done
~~~
Exemple avec l'erreur _1032_ (« Could not execute Delete_rows event ») :
~~~
# while true; do while mysql -e "show slave status" | grep 'Error_code: 1032'; \
do mysql -e "SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;"; done ; sleep 1; done
~~~
On peut également utilisé un script Shell plus évolué qui prendre les motifs à ignorer dans un fichier *error.txt* (expressions rationnelles étendues, compatibles _grep -E_) et qui proposera de zapper manuellement (ou pas) si l'erreur ne correspondant aux motifs :
~~~{.sh}
#!/bin/sh
# File containing error messages to skip (one per line).
error_messages="errors.txt"
# Sleep interval between 2 check.
sleep_interval="1"
# Exit when Seconds_Behind_Master reached 0.
exit_when_uptodate="false"
# Options to pass to mysql.
#mysql_opt="-P 3307"
# File to log skipped queries to (leave empty for no logs).
log_file=""
mysql_skip_error() {
error="$1"
printf "Skiping: $error\n"
mysql $mysql_opt -e 'SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;'
if $exit_when_uptodate && [ "$seconds_behind_master" = "0" ]; then
printf 'Replication is up to date!\n'
exit 0
elif [ -z "$last_SQL_error" ]; then
sleep $sleep_interval
elif echo "$last_SQL_error" |grep -q -f $error_messages; then
mysql_skip_error "$last_SQL_error"
else
printf "Current SQL error doesn't match the pattern:\n"
printf "$last_SQL_error\n"
printf "Skip it? [y/N]: "
read reply
if [ "$reply" = "y" ] || [ "$reply" = "Y" ]; then
mysql_skip_error $last_SQL_error
fi
fi
done
~~~
### Récupération de position impossible
~~~
[ERROR] Error reading packet from server: Client requested master to start replication from impossible position (server_errno=1236)
~~~
Cela signifie que la position indiquée sur le binlog du master est impossible à récupérer. On peut le vérifier avec une commande du type `mysqlbinlog mysqld-bin.00123 --start-position=251` sur le master.
Si l'on constate que le binlog est corrompu avec des erreurs du type _ERROR: Error in Log_event::read_log_event(): 'read error' # Warning: this binlog is either in use or was not closed properly._ ou _ERROR: Error in Log_event::read_log_event(): 'Event too small', data_len: 0, event_type: 0_ l'idée est d'identifier les requêtes non jouées sur le slave dans le binlog corrompu (voir le *Relay_Master_Log_File* via `SHOW SLAVE STATUS`) et de les rejouer (cf [HowtoMySQL#Replay]()) puis de passer au binlog suivant via une commande du type `CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000124' , MASTER_LOG_POS=106; START SLAVE;` (la position à indiquer est souvent `106`, cf `mysqlbinlog mysql-bin.000124`).
Si l'on juge cela non nécessaire (données non critiques), on pourra bien sûr passer directement au binlog suivant en ignorant les requêtes du binlog corrompu. Bien sûr, suite à ces manipulations risquées, on vérifiera ensuite la cohérence de la base de données répliquée (`COUNT(*)` ou outils plus avancés).
### Could not parse relay log event entry
~~~
Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log),
the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code.
If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
~~~
Souvent un binlog corrompu, voir le *Relay_Master_Log_File*`SHOW SLAVE STATUS`.
**Note**: Jusqu'à MySQL <= 5.1 au moins, changer la position dans un `Relay_log` avec un `CHANGE MASTER TO` ne marche pas. Voir [Changement de la position dans un Relay_log](#ChangementdelapositiondansunRelay_log).
**Error 1594 - Relay log read failure - Could not parse relay log event entry**
On peut changer la position du Relay_log, sur le serveur slave, il faut bien identifier sur quel `Relay_Master_Log_File` et a quelle position du `Exec_Master_Log_Pos` se trouve le slave.
Il faut, avant toute chose, faire un `SHOW SLAVE STATUS\G` (copier la sortie complète dans un fichier à part, pour mémoire) pour voir les valeurs de `Relay_Master_Log_File` et `Exec_Master_Log_Pos` :
Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
Skip_Counter: 0
Exec_Master_Log_Pos: 617884110
Relay_Log_Space: 3192816253
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: 1594
Last_SQL_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
Replicate_Ignore_Server_Ids:
Master_Server_Id: 13
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: conservative
~~~
Il faut donc stopper le slave :
~~~
MariaDB [(none)]> STOP SLAVE;
~~~
Ensuite faire un `CHANGE MASTER TO` en indiquant le `Relay_Master_Log_File` et la position du `Exec_Master_Log_Pos` comme ceci dans l'exemple ci-dessus :
~~~
MariaDB [(none)]> CHANGE MASTER TO master_log_file='mysql-bin.001273', master_log_pos=617884110;
MariaDB [(none)]> START SLAVE;
~~~
Normalement a ce stade là, la réplication continue à la position indiquée. Il se peut qu'il y ait des `Duplicate Entry`, qu'il faut alors étudier de près pour envisager de les sauter.
### Erreur fatale à la lecture du binlog
Erreur : `Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'`
On obtient apparemment cela dans différents cas.
* L'un d'eux serait si max_allowed_packet est inférieur à read_buffer_size ; voir <http://www.mysqlperformanceblog.com/2012/06/06/read_buffer_size-can-break-your-replication/> ;
* dans d'autre cas, il faudra forcer la réplication à se poursuivre via `STOP SLAVE; CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.00XXXX' , MASTER_LOG_POS=XXXX; START SLAVE;`
* dans un autre cas, la position indiquée n'existe pas dans le binlog
Dans certains cas **exceptionnels**, une solution radicale est de réinitialiser la réplication avec un `STOP SLAVE; RESET SLAVE; START SLAVE;` Attention, cela doit être fait dans de très rares cas maîtrisés (attention notamment aux conflits _DUPLICATE ENTRY_ que cela risque de provoquer).
**Status OK, mais pas de réplication**
Si un `SHOW SLAVE STATUS` ne retourne pas d'erreur mais que la réplication ne se fait pas, les logs du slave peuvent contenir une erreur du type :
~~~
[Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log 'mysql-bin.003357' at position 389449
[Note] Slave: received end packet from server, apparent master shutdown:
~~~
Il se peut que le master se réplique sur 2 slaves ayant un server-id identique !
### Erreur de checksum fatale
Si vous rencontrez une erreur du type :
```
Got fatal error 1236 from master when reading data from binary log: 'Slave can not handle replication events with the checksum that master is configured to log; the first event 'mysql-bin.015405' at 4, the last event read from 'mysql-bin.015405' at 4, the last byte read from 'mysql-bin.015405' at 256.'
```
Il est possible que l'erreur soit dûe au fait le master et le slave n'ont pas la même version.
### ERROR 1201 lors de l'injection du dump
Si lors de l'injection du dump sur le slave cette erreur apparaît :
`ERROR 1201 (HY000) at line 22: Could not initialize master info structure`
Il faut supprimer toute traces des anciennes réplications avec :
~~~
RESET SLAVE;
~~~
Et ensuite réinjecter le dump.
### Changement de la position dans un Relay_log
À faire uniquement si en tentant de changer la position d'un _Relay_log_ sur un slave, vous obtenez cette erreur :
~~~
Error initializing relay log position: Could not find target log during
relay log initialization
~~~
Il faut alors stopper le processus slave de réplication :
~~~
mysql> STOP SLAVE;
~~~
Puis éditer (en gardant une sauvegarde) le fichier `${datadir}/relay-log.info`. La première ligne correspond au `Relay_Log_File`, la seconde au `Relay_Log_Pos`.
Redémarrer MySQL.
### Réintégrer dans la réplication une base qui aurait été exclue.
Dans cet exemple, la base avait été exclue de la réplication, avec `replicate-ignore-db`, les lectures des requêtes de la base est ignoré sur le slave, mais le master continue d'écrire les requêtes de la base dans les binlogs.
1 - On enlève l'exclusion de la base dans le fichier de configuration :
~~~
#replicate-ignore-db = foo
~~~
2 - On fait un dump de cette base sur le *master* :
~~~
# mysqldump foo > foo.sql
~~~
3- On réinjecte ce dump sur le *slave* :
~~~
# mysql -o foo < foo.sql
~~~
4- On redémarre MySQL (ou l'instance) sur le *slave*, pour qu'il relise le fichier de configuration et ignore l'exclusion de la base sur le slave :
~~~
# systemctl restart mysql.service
~~~
S'il s'agit d'une instance, exemple si l'instance se trouve sur le port 3307 :
~~~
# mysqladmin -P 3307 shutdown
# mysqld_multi start 1
~~~
En cas de réplication master - master, avec un slave de chaque côté, il faut le faire des deux côtés.
Il existe d'autres méthodes, pour faire cela, celle-ci est la plus simple et elle a l'avantage de gérés les locks des tables, on ne doit pas le faire à la main.
### Erreurs de réplication par "Channel" ou "Group réplication"
Dans le cas d'une réplication par channel, ou Group Réplication, la sortie de `SHOW SLAVE STATUS\G' indique sur quels Channel il y a une erreur, mais sans forcément indiquer de manière explicite l'erreur en question.
Exemple :
~~~
mysql> SHOW SLAVE STATUS\G
.....
Exec_Master_Log_Pos: 18089090
Relay_Log_Space: 1104382466
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: 1064
Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'ANONYMOUS' at master log mysql-bin.000807, end_log_pos 18089265. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
Replicate_Ignore_Server_Ids:
Master_Server_Id: 62
Master_UUID:
Master_Info_File: mysql.slave_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: 200703 10:56:11
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name: su6-sql2
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
~~~
On vois que la réplication sur le Channel nommée `su6-sql2` est en erreur, mais on ne sait pas sur quelle requête.
Le message d'erreur suggère de regarder les logs d'erreurs dans la table `performance_schema.replication_applier_status_by_worker`.
On peut le faire comme ceci, en indiquant le Channel en erreur, et le numéro du Worker, comme indiqué dans le message d'erreur précédent:
Exemple :
~~~
mysql> SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE WORKER_ID=1 AND CHANNEL_NAME='su6-sql2'\G;
LAST_ERROR_MESSAGE: Worker 1 failed executing transaction 'ANONYMOUS' at master log mysql-bin.000807, end_log_pos 18089265; Error 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1' at line 1' on query. Default database: 'DB_content_cfbe'. Query: 'delete from toppops_cfbe_null_20200702_104153_V220 where rank=1'
Error 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1' at line 1' on query. Default database: 'DB_content_cfbe'. Query: 'delete from toppops_cfbe_null_20200702_104153_V220 where rank=1'