22
0
Fork 0
wiki/HowtoMySQL.md

1000 lines
30 KiB
Markdown
Raw Normal View History

2016-11-01 23:37:14 +01:00
---
2016-12-16 00:41:21 +01:00
categories: web
2016-11-02 12:12:48 +01:00
title: Howto MySQL : installation et utilisation courante.
2016-11-02 12:18:19 +01:00
...
2016-11-01 23:37:14 +01:00
2016-12-16 02:33:28 +01:00
* Documentation : <http://dev.mysql.com/doc/refman/5.5/en/>
* Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/show/mysql>
2016-12-16 00:41:21 +01:00
[MySQL](https://www.mysql.com/) est une base de données très populaire au sein des infrastructures web. Nous utilisons au choix la version libre de MySQL distribuée par Oracle, et [MariaDB](https://mariadb.org/) un fork créé en 2009 par le créateur initial de MySQL.
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Installation
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Pour la version libre de MySQL distribuée par Oracle :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# apt install mysql-server
2016-12-16 00:41:21 +01:00
$ mysql --version
mysql Ver 14.14 Distrib 5.5.53, for debian-linux-gnu (x86_64) using readline 6.3
~~~
Pour MariaDB :
~~~
# apt install mariadb-server-10.0
$ mysql --version
mysql Ver 15.1 Distrib 10.0.28-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
L'installation sous Debian demande un mot de passe pour le superutilisateur (par défaut *root*) de MySQL.
En laissant un mot de passe vide, on peut se connecter sans mot de passe :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
$ mysql -u root
2016-11-01 23:37:14 +01:00
Welcome to the MySQL monitor. Commands end with ; or \g.
2016-12-16 00:41:21 +01:00
Your MySQL connection id is 45
Server version: 5.5.53-0+deb8u1 (Debian)
2016-11-01 22:50:26 +01:00
2016-11-02 15:29:14 +01:00
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
mysql>
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Il faut ensuite mettre un mot de passe pour le superutilisateur de MySQL, on conseille d'utiliser l'identifiant *adminmysql* car *root* peut prêter à confusion :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> GRANT ALL PRIVILEGES ON *.* TO adminmysql@localhost IDENTIFIED BY 'PASSWORD' WITH GRANT OPTION;
2016-11-01 23:37:14 +01:00
mysql> DELETE FROM mysql.user where User='root';
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
On notera sous Debian la présence d'un utilisateur *debian-sys-maint* qui sert à certains scripts Debian :
2016-11-01 22:50:26 +01:00
il ne doit pas être supprimé ! Au niveau sécurité, le mot de passe est généré à l'installation
2016-12-16 00:41:21 +01:00
(stocké dans `/etc/mysql/debian.cnf` lisible que par *root*) par la commande :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
perl -e 'print map{("a".."z","A".."Z",0..9)[int(rand(62))]}(1..16)'
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Enfin, on peut utiliser un fichier `.my.cnf` pour conserver l'identifiant et le mot de passe.
Par exemple pour *root*, dans `/root/.my.cnf` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
[client]
user = adminmysql
2016-12-16 00:41:21 +01:00
password = PASSWORD
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Pour changer le mot de passe, on fera simplement :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
# mysqladmin password PASSWORD
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Configuration
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Les fichiers de configuration se trouvent dans `/etc/mysql/` et notamment `my.cnf` qui centralise les directives par défaut.
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Le fichier `/etc/mysql/conf.d/z_evolinux.cnf` contient nos optimisations basiques :
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
~~~{.ini}
[mysqld]
###### Connexions
# Maximum de connexions concurrentes (defaut = 100)... provoque un "Too many connections"
max_connections = 250
# Maximum de connexions en attente en cas de max_connections atteint (defaut = 50)
back_log = 100
# Maximum d'erreurs avant de blacklister un hote
max_connect_errors = 10
# Loguer les requetes trop longues
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 10
###### Tailles
# Taille reservee au buffer des index MyIsam
# A ajuster selon les resultats
key_buffer_size = 512M
# Taille max des paquets envoyés/reçus … provoque un "Packet too large"
max_allowed_packet = 64M
# Taille de la memoire reserve pour un thread
thread_stack = 192K
# A mettre le nombre de threads CPU alloues pour MySQL
thread_cache_size = 1
# Taille maximum des tables de type MEMORY
max_heap_table_size = 64M
###### Cache
# max_connections x nbre max de tables dans une jointure (defaut = 64)
table_cache = 4096
table_open_cache = 4096
table_definition_cache = 4096
# Taille max des requetes cachees (defaut = 1M)
query_cache_limit = 8M
# Taille reservee pour le cache (defaut = 0)
query_cache_size = 256M
# Type de requetes a cacher (defaut = 1 : tout peut etre cache)
query_cache_type = 1
# Cache tables
max_heap_table_size = 128M
tmp_table_size = 128M
###### InnoDB
# Si InnoDB n'est pas utilise... le desactiver
#skip-innodb
# En general, il est plus optimum d'avoir un fichier par table
innodb_file_per_table
# Taille memoire allouee pour le cache des datas et index
# A ajuster en fonction de sa RAM (si serveur dedie a MySQL, on peut aller jusqu'a 80%)
innodb_buffer_pool_size = 512M
# Taille buffer memoire pour structures internes InnoDB
innodb_additional_mem_pool_size = 16M
# Nombre maximum de threads systeme concurents
innodb_thread_concurrency = 16
# Ajuste la valeur des logs InnoDB
# (attention, il faut ensuite stopper MySQL et effacer les fichiers ib_logfile*)
#innodb_log_file_size = 128M
#innodb_log_files_in_group = 2
###### Misc
# charset utf8 par defaut
default-character-set = utf8
collation-server = utf8_unicode_ci
~~~
Le fichier `/etc/mysql/conf.d/zzz_evolinux.cnf` contient nos optimisations spécifiques.
Par défaut, MySQL écoute en réseau sur `127.0.0.1` (port TCP/3306) et sur la socket Unix `/var/run/mysqld/mysqld.sock`
Pour activer les connexions réseau à distance, il faut ajouter la configuration suivante dans `zzz_evolinux.cnf` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
2016-12-16 00:41:21 +01:00
[mysqld]
2016-11-01 23:37:14 +01:00
bind-address = 0.0.0.0
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Selon les ressources de la machine, il faut optimiser davantage les options (par défaut, la configuration est adaptée pour une machine avec très peu de mémoire vive !). Sous Debian, on trouvera quelques exemples dans le répertoire `/usr/share/doc/mysql-server-5.5/examples/`
On conseille au minimum d'ajuster *thread_cache_size* et *innodb_buffer_pool_size* :
~~~{.ini}
[mysqld]
# Nombre de threads CPU alloués pour MySQL
thread_cache_size = 2
# Mémoire allouée pour le cache InnoDB (si serveur dédié, on peut aller jusqu'à 80% de la RAM)
innodb_buffer_pool_size = 2G
~~~
Pour plus d'informations sur l'optimisation avancée de MySQL, consultez le guide [/MySQL/HowtoOptimize]().
## datadir / tmpdir
Par défaut, le *datadir* (le répertoire où sont stockées les données brutes) est `/var/lib/mysql/`.
Pour diverses raisons il peut être intéressant de le déplacer (partition ou disque dédié etc.).
Pour des raisons de compatibilité, on conseille de conserver un lien symbolique :
~~~
# systemctl stop mysql
# mv /var/lib/mysql /srv/mysql-datadir
# ln -s /srv/mysql-datadir /var/lib/mysql
# systemctl start mysql
~~~
Pour certaines opérations lourdes, MySQL a besoin d'un *tmpdir* (répertoire où il va écrire des tables temporaires).
Par défaut il utilise `/tmp` mais vu qu'il est parfois nécessaire d'avoir plusieurs Go de libre, on pourra utiliser un répertoire différents :
~~~{.ini}
[mysqld]
tmpdir = /srv/mysql-tmpdir
~~~
## Logs
Sous Debian, les journaux de MySQL (démarrage, arrêt, erreurs, informations) sont envoyés via *syslog*.
Par défaut, ils seront donc visibles dans `/var/log/syslog`.
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Le répertoire `/var/log/mysql/` contient les *binlogs* (trace de toutes les requêtes INSERT/UPDATE/DELETE exécutées).
2016-11-01 23:37:14 +01:00
2016-11-02 12:12:48 +01:00
## Utilisation courante
2016-11-01 23:37:14 +01:00
2016-12-16 00:41:21 +01:00
Créer une nouvelle base de données nommée _foo_ :
2016-11-01 23:37:14 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> CREATE DATABASE foo;
2016-11-02 12:12:48 +01:00
~~~
2016-11-01 23:37:14 +01:00
2016-11-02 12:12:48 +01:00
Voir les bases de données créées :
2016-11-01 23:37:14 +01:00
2016-11-02 12:12:48 +01:00
~~~
mysql> SHOW DATABASES;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Utiliser la base de données _foo_ :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> USE foo
2016-11-02 12:12:48 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Voir les tables créées :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-11-02 12:12:48 +01:00
mysql> SHOW TABLES;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 00:41:21 +01:00
Créer une table nommée _bar_ avec différents champs :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> CREATE TABLE bar (id INT not null AUTO_INCREMENT, prenom VARCHAR
2016-11-02 12:12:48 +01:00
(50) not null , nom VARCHAR (50) not null , ne_le DATE not null ,
ville VARCHAR (90), enfants INT, PRIMARY KEY (id));
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Décrire une table :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> DESC bar;
2016-11-02 12:12:48 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Ajouter un champ à une table :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> ALTER TABLE bar ADD another VARCHAR(100) DEFAULT NULL;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Ajouter un champ à une table en précisant sa place :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> ALTER TABLE bar ADD another VARCHAR(100) DEFAULT NULL AFTER prenom;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Supprimer un champ à une table :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> ALTER TABLE bar DROP another;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Renommer un champ :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> ALTER TABLE bar CHANGE COLUMN another anotherone TEXT;
2016-11-02 12:12:48 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Changer le type d'un champ :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> ALTER TABLE bar CHANGE another another enum('foo',bar');
2016-11-02 12:12:48 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Insertion de données dans une table :
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> INSERT INTO bar VALUES (1,'jp','papin','2005-06-12','Marseille',2);
2016-11-02 12:12:48 +01:00
INSERT INTO test (id,prenom,nom,ne_le) VALUES (2,'c','waddle','2004-06-17');
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Sélectionner tous les champs d'une table :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> SELECT * FROM bar;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Effacer des données d'une table :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> DELETE FROM bar WHERE nom='waddle';
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Effacer TOUTES les données d'une table :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> DELETE FROM bar;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Supprimer une table :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> DROP TABLE bar;
2016-11-02 12:12:48 +01:00
~~~
Supprimer une base de données :
2016-11-01 23:37:14 +01:00
2016-11-02 12:12:48 +01:00
~~~
2016-12-16 00:41:21 +01:00
mysql> DROP DATABASE foo;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Administration
2016-11-01 22:50:26 +01:00
On crée une base de données et un utilisateur associé :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 00:41:21 +01:00
# mysqladmin create foo
2016-11-01 23:37:14 +01:00
# mysql
2016-12-16 00:41:21 +01:00
mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@localhost IDENTIFIED BY 'PASSWORD';
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Cette opération revient à insérer des lignes suivante dans les tables `mysql.user` et `mysql.db` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> INSERT INTO mysql.user VALUES ('localhost','jdoe',password('PASSWORD'),'N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0,0,'',NULL);
mysql> INSERT INTO mysql.db VALUES ('localhost','foo','jdoe','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
2016-11-01 23:37:14 +01:00
mysql> FLUSH PRIVILEGES;
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
*Note* :
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Pour migrer de Debian 6 à 7 :
- 3 colonnes ont été ajoutées dans `mysql.user` : Create_tablespace_priv, plugin et authentication_string (pour migrer il faut ajouter 'N' en 32ème position + '' et NULL à la fin)
- 2 colonnes ont été ajoutées dans `mysql.db` : Event_priv et Trigger_priv (pour migrer il faut ajouter 'Y' et 'Y' à la fin)
2016-11-01 22:50:26 +01:00
2016-11-15 10:42:16 +01:00
On pourra ainsi régler finement les droits d'un utilisateur en connaissant la signification de chaque colonne :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql> desc user;
+------------------------+-----------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+-----------------------------------+------+-----+---------+-------+
| Host | char(60) | NO | PRI | | |
| User | char(16) | NO | PRI | | |
| Password | char(41) | NO | | | |
| Select_priv | enum('N','Y') | NO | | N | |
| Insert_priv | enum('N','Y') | NO | | N | |
| Update_priv | enum('N','Y') | NO | | N | |
| Delete_priv | enum('N','Y') | NO | | N | |
| Create_priv | enum('N','Y') | NO | | N | |
| Drop_priv | enum('N','Y') | NO | | N | |
| Reload_priv | enum('N','Y') | NO | | N | |
| Shutdown_priv | enum('N','Y') | NO | | N | |
| Process_priv | enum('N','Y') | NO | | N | |
| File_priv | enum('N','Y') | NO | | N | |
| Grant_priv | enum('N','Y') | NO | | N | |
| References_priv | enum('N','Y') | NO | | N | |
| Index_priv | enum('N','Y') | NO | | N | |
| Alter_priv | enum('N','Y') | NO | | N | |
| Show_db_priv | enum('N','Y') | NO | | N | |
| Super_priv | enum('N','Y') | NO | | N | |
| Create_tmp_table_priv | enum('N','Y') | NO | | N | |
| Lock_tables_priv | enum('N','Y') | NO | | N | |
| Execute_priv | enum('N','Y') | NO | | N | |
| Repl_slave_priv | enum('N','Y') | NO | | N | |
| Repl_client_priv | enum('N','Y') | NO | | N | |
| Create_view_priv | enum('N','Y') | NO | | N | |
| Show_view_priv | enum('N','Y') | NO | | N | |
| Create_routine_priv | enum('N','Y') | NO | | N | |
| Alter_routine_priv | enum('N','Y') | NO | | N | |
| Create_user_priv | enum('N','Y') | NO | | N | |
| Event_priv | enum('N','Y') | NO | | N | |
| Trigger_priv | enum('N','Y') | NO | | N | |
| Create_tablespace_priv | enum('N','Y') | NO | | N | |
| ssl_type | enum('','ANY','X509','SPECIFIED') | NO | | | |
| ssl_cipher | blob | NO | | NULL | |
| x509_issuer | blob | NO | | NULL | |
| x509_subject | blob | NO | | NULL | |
| max_questions | int(11) unsigned | NO | | 0 | |
| max_updates | int(11) unsigned | NO | | 0 | |
| max_connections | int(11) unsigned | NO | | 0 | |
| max_user_connections | int(11) unsigned | NO | | 0 | |
| plugin | char(64) | YES | | | |
| authentication_string | text | YES | | NULL | |
+------------------------+-----------------------------------+------+-----+---------+-------+
42 rows in set (0.00 sec)
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Par exemple, pour permettre à un utilisateur (ici *debian-sys-maint*) de faire des `SHOW VIEW` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql> UPDATE user SET Show_view_priv='Y' WHERE User='debian-sys-maint';
mysql> FLUSH PRIVILEGES;
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
…que l'on peut aussi faire via :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql> GRANT SHOW VIEW on *.* to `debian-sys-maint`@localhost;
~~~
2016-11-01 22:50:26 +01:00
Pour créer un utilisateur sans droit particulier, par exemple pour du monitoring :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> create user nagios@localhost identified by 'PASSWORD';
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
On peut aussi gérer des droits sur les tables :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> GRANT Select,Insert,Update ON foo.bar TO 'jdoe'@localhost;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Pour révoquer des droits sur une table, on utilisera `REVOKE` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> REVOKE ALL PRIVILEGES ON foo.bar FROM 'jdoe'@localhost;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
/!\\ Un droit est particulier : pour utiliser LOAD DATA INFILE ou SELECT INTO OUTFILE, il faut avoir le droit `FILE` … mais il est global (et dangereux) !
2016-11-01 22:50:26 +01:00
On le positionnera ainsi :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> GRANT FILE ON *.* TO 'jdoe'@localhost;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Vérifications et réparations
2016-12-16 01:49:46 +01:00
Pour vérifier et réparer toutes les tables (une sorte de *fsck* pour les tables), on lancera :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# mysqlcheck --auto-repair --check --all-databases
~~~
2016-11-01 22:50:26 +01:00
On peut aussi réparer qu'une base en particulier :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqlcheck --auto-repair --check foo
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
*Note* : ceci peut être à faire en cas d'arrêt inopiné du service.
2016-11-01 22:50:26 +01:00
2016-12-16 12:21:26 +01:00
On pourra également ajouter l'option `--optimize` pour ajouter une optimisation des tables :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# mysqlcheck --auto-repair --check --optimize --all-databases
~~~
2016-11-01 22:50:26 +01:00
Pour réparer une seule table :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> CHECK TABLE foo.bar;
mysql> REPAIR TABLE foo.bar;
mysql> OPTIMIZE TABLE foo.bar;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Dans le cas des tables MyISAM, si le REPAIR échoue, une réparation est aussi possible via `myisamchk`… à faire avec
le service MySQL arrêté :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# myisamchk -r -q /var/lib/mysql/foo/bar.MYD
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
En cas d'échec (*segfault* par exemple), on peut tenter :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# myisamchk --safe-recover -v -f --key_buffer_size=512M --sort_buffer_size=512M --read_buffer_size=4M --write_buffer_size=4M /var/lib/mysql/BASE/TABLE.MYD
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### routines MySQL
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
mysql> select * from INFORMATION_SCHEMA.routines;
~~~
### Changement mot de passe utilisateur
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql> SET PASSWORD FOR 'jdoe'@'localhost' = PASSWORD('PASSWORD');
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Par rapport à un autre utilisateur :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-11-02 12:12:48 +01:00
mysql> use mysql;
2016-12-16 01:49:46 +01:00
mysql> UPDATE mysql.user SET Password='PASSWORD' WHERE User='jdoe' and Host='localhost';
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Changer variables global d'environnement
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
~~~
mysql> SET GLOBAL max_connect_errors=50;
~~~
ou
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-11-02 12:12:48 +01:00
mysql> SET @@max_connect_errors=50;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Sauvegarde
2016-11-01 22:50:26 +01:00
Pour sauvegarder une base de données (sans et avec compression) :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump foo > foo.sql
# mysqldump foo | gzip > foo.sql.gz
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Pour restaurer une base de données (sans et avec compression) :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqladmin create foo
# mysql foo < foo.sql
# gunzip < foo.sql.gz | mysql foo
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Sauvegarder toutes les bases :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump --opt --all-databases > all.sql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Pour sauvegarder uniquement certaines tables :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump foo TABLE0 [TABLE1…] > foo_tables.sql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 12:21:26 +01:00
Pour presque faire un `--exclude` (qui manque cruellement à *mysqldump*):
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql -B -N -e 'show databases' | \
perl -ne 'print unless /\b(?:phpmyadmin|mysql|information_schema)\b/' | \
xargs echo mysqldump -B
~~~
2016-11-01 22:50:26 +01:00
Et pour sauvegarder des tables correspondant à un motif (préfixe le plus souvent) :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump foo $(mysql foo -B --column-names=False -e "show tables like 'exemple_%'") > foo_motif.sql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Pour dumper avec une condition particulière :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysqldump -t foo bar --where="id='66666666'"
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Ce qui permet de réinjecter des données résultantes d'un `SELECT * FROM foo.bar WHERE id='66666666'`.
2016-11-01 22:50:26 +01:00
2016-12-14 14:23:53 +01:00
Il est évidement possible de faire toutes ces opérations sur une instance en
2016-12-16 01:49:46 +01:00
précisant son port avec l'option `--port` (valable pour *mysqldump* et *mysql*).
2016-11-01 22:50:26 +01:00
Pour obtenir une liste des utilisateurs mysql, on peut utiliser cette fonction (glanée sur [serverfault](http://serverfault.com/questions/8860/how-can-i-export-the-privileges-from-mysql-and-then-import-to-a-new-server/)) :
2016-11-01 23:37:14 +01:00
~~~{.bash}
mygrants()
{
mysql -B -N -e "SELECT DISTINCT CONCAT(
'SHOW GRANTS FOR *, user, _'@'_, host, *;'
) AS query FROM mysql.user" | \
mysql | \
sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
}
~~~
2016-11-01 22:50:26 +01:00
Pour avoir un dump avec un seul insert par ligne, pratique pour restaurer partiellement les bases `mysql.user` et `mysql.db` par exemple :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump --skip-extended-insert mysql > mysql.sql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Pour restaurer une seule base d'un dump complet on peut utiliser :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
mysql -o foo < all.sql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Pour restaurer une base, dont la structure de chaque table est stockée dans un fichier SQL indépendant, et dont les données sont dans des fichiers de type "tab-separated data files" (option -T de mysqldump) avec une extension .txt :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.bash}
db=test1
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
for file in *.sql; do
mysql $db <$file
done
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
grep CHARSET= *txt
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
for file in *.txt; do
tablename=`basename $file .txt` #tablename=${file%.*}
echo "LOAD DATA INFILE '$PWD/$file' INTO TABLE $tablename" CHARACTER SET utf8 | mysql $db
done
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
*Note 1* : Attention, l'utilisateur MySQL doit avoir le droit de lecture sur les fichiers .txt
2016-11-01 22:50:26 +01:00
Se positionner dans un répertoire où mysql a les droits (mysqltmp - /home/mysqltmp par ex).
2016-12-16 01:49:46 +01:00
*Note 2* : Si vous n'avez pas toutes vos tables en utf8 (par exemple du `CHARSET=LATIN1`), ce n'est pas bien… et vous devrez pour la peine adapter le script (en détectant le charset utilisé avec « file » si nécessaire)
2016-11-01 22:50:26 +01:00
Il est possible d'exporter le contenu d'une base au format CSV :
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysqldump -T /tmp --fields-enclosed-by=\" --fields-terminated-by=, --no-create-db --no-create-info foo
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
*Note* : il est nécessaire que MySQL ait les droits d'écriture dans le répertoire de destination (ici `/tmp`).
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Monitoring
2016-11-01 22:50:26 +01:00
Pour surveiller un service MySQL en production, on pourra faire :
2016-11-01 23:37:14 +01:00
~~~
# mysqladmin status
# mysqladmin extended-status
# mysqladmin processlist
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
### mytop
Pour avoir une version conviviale et dynamique des process en cours, on utilisera l'outil *mytop*.
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# apt install mytop
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
On édite le fichier `/root/.mytop` ainsi :
2016-11-01 23:37:14 +01:00
~~~{.ini}
user = debian-sys-maint
2016-12-16 01:49:46 +01:00
pass = PASSWORD
2016-11-01 23:37:14 +01:00
db = mysql
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Reste plus qu'à lancer la commande `mytop -s1` (pour un rafraichissement toutes les secondes) : on appréciera les raccourcis `p` (mettre en pause l'affichage), `o` (pour voir en 1er les requêtes les plus longues), `k` (pour killer une requête… par exemple celle qui bloque toutes les autres) et `?` (pour voir les autres raccourcis possibles).
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
L'outil *mytop* se sert principalement de la requête `SHOW PROCESSLIST` que l'on pourra bien sûr lancer manuellement. Tout comme `KILL` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql> SHOW PROCESSLIST;
2016-12-16 01:49:46 +01:00
mysql> KILL <id_requête>;
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Pour lister les requêtes qui durent plus de 30 secondes pour pouvoir les tuer facilement :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql -e 'select group_concat(concat("kill ",ID) separator ";") from information_schema.processlist where TIME>=30;'
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Puis exécuter le résultat avec la commande *mysql*, exemple :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql -e 'kill 1854;kill 1853;kill 1852;kill 1851;kill 1850;kill 1848'
~~~
2016-11-01 22:50:26 +01:00
Pour surveiller le moteur InnoDB, on utilisera la commande suivante :
2016-11-01 23:37:14 +01:00
~~~
mysql> SHOW ENGINE INNODB STATUS;
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
### Munin
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Pour activer les plugins MySQL pour Munin :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# cd /etc/munin/plugins
# ln -s /usr/share/munin/plugins/mysql_bytes
# ln -s /usr/share/munin/plugins/mysql_queries
# ln -s /usr/share/munin/plugins/mysql_slowqueries
# ln -s /usr/share/munin/plugins/mysql_threads
~~~
On pourra aussi activer le plugin *mysql_* avec des liens symboliques nommés connections, files_tables, innodb_bpool, innodb_bpool_act, innodb_io, innodb_log, innodb_rows, innodb_semaphores, myisam_indexes, qcache, qcache_mem, sorts ou tmp_tables.
Pour tester le bon fonctionnement des plugins MySQL pour Munin :
~~~
# munin-run mysql_bytes
~~~
### log2mail
Afin d'être alerté en cas de souci, il est conseillé d'ajouter la configuration suivante au logiciel `log2mail` :
~~~
file = /var/log/syslog
pattern = "is marked as crashed and should be repaired"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
2016-11-01 23:37:14 +01:00
file = /var/log/syslog
2016-12-16 01:49:46 +01:00
pattern = "init function returned error"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
file = /var/log/syslog
2016-12-16 01:49:46 +01:00
pattern = "try to repair it"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
file = /var/log/syslog
2016-12-16 01:49:46 +01:00
pattern = "InnoDB: Fatal error"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
file = /var/log/syslog
2016-12-16 01:49:46 +01:00
pattern = "as a STORAGE ENGINE failed"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
Le fichier `/etc/log2mail/template.mysql` contenant :
2016-11-01 23:37:14 +01:00
~~~
From: %f
To: %t
Subject: MySQL problem
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
Hello!
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
We have matched your pattern "%m" in "%F" %n times:
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
%l
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
Yours,
log2mail.
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
*Note* : il faut ajouter l'utilisateur `log2mail` dans le groupe `adm`.
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Gestion des binlogs
2016-11-01 22:50:26 +01:00
Par défaut, MySQL stocke chaque requête en écriture dans des fichiers appelés *binlogs*.
2016-11-02 12:12:48 +01:00
### Configuration
2016-11-01 22:50:26 +01:00
2016-12-14 14:23:53 +01:00
Par défaut les binlogs sont conservés sur 10 jours, avec des fichiers n'excédant pas 100 Mo :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
2016-12-16 01:49:46 +01:00
[mysqld]
2016-11-01 23:37:14 +01:00
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
binlog_format = mixed
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Format
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
<http://dev.mysql.com/doc/refman/5.5/en/binary-log-setting.html>
2016-11-01 22:50:26 +01:00
On peut choisir 3 types de format pour les binlogs :
2016-11-01 23:37:14 +01:00
* **statement** : les requêtes INSERT / UPDATE sont conservées
2016-12-14 14:23:53 +01:00
* **row** : les modifications de chaque ligne sont conservées (via une sorte de code « binaire » propre à MySQL)
2016-11-01 23:37:14 +01:00
* **mixed** : en mode statement… sauf dans certains cas où cela passe en mode row
2016-11-01 22:50:26 +01:00
Avantages et inconvénients :
2016-11-01 23:37:14 +01:00
Le mode **statement** est utile pour conserver en clair toutes les requêtes. Il permet aussi de meilleures performances quand des UPDATE contiennent des clauses WHERE qui modifient de nombreuses lignes.
2016-11-01 22:50:26 +01:00
Pour de la réplication, il peut être non fiable car le résultat d'un UPDATE peut donner des résultats différents sur un serveur SLAVE. Cela peut aussi poser des soucis avec les transactions InnoDB.
2016-11-01 23:37:14 +01:00
Le mode **row** a l'inconvénient de rendre illisibles toutes les requêtes. Dans certains cas particuliers (UPDATE contiennent des clauses WHERE qui modifient de nombreuses lignes), il peut être moins performant.
2016-11-01 22:50:26 +01:00
Il a l'avantage d'être plus fiable pour de la réplication.
2016-11-01 23:37:14 +01:00
Le mode **mixed** est un bon compromis pour de la réplication : il permet de voir la plupart des requêtes en clair, mais évite le problème de fiabilité en passant en mode row quand c'est nécessaire.
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Suppression
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
Pour supprimer les binlogs antérieurs à `mysql-bin.00NNNN` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
mysql> PURGE BINARY LOGS TO `mysql-bin.00NNNN`;
~~~
2016-11-01 22:50:26 +01:00
ou par rapport à une date :
2016-11-01 23:37:14 +01:00
~~~
mysql> PURGE BINARY LOGS BEFORE "2011-12-07 00:00:00";
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Désactivation
2016-11-01 22:50:26 +01:00
Pour désactiver les binlogs, on ajoutera l'option suivante dans la configuration :
2016-12-16 01:49:46 +01:00
~~~{.ini}
[mysqld]
2016-11-01 23:37:14 +01:00
disable-log-bin
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Lecture
2016-11-01 22:50:26 +01:00
On pourra lire en ligne de commande le contenu d'un binlog via la commande :
2016-11-01 23:37:14 +01:00
~~~
# mysqlbinlog /var/log/mysql/mysql-bin.001789 | less
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
* Note* : si vous obtenez une erreur `mysqlbinlog: unknown variable 'default-character-set=utf8'` c'est que la directive `default-character-set`
2016-11-01 22:50:26 +01:00
a été placée dans la configuration MySQL (`/etc/mysql` ou `.my.cnf`) dans la mauvaise section : `[client]` au lieu de `[mysql]` (ou `[mysqldump]`).
2016-11-02 12:12:48 +01:00
### Replay
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
/!\\ **ATTENTION, CES MANIPULATIONS PEUVENT ÊTRE DANGEREUSES VOS DONNÉES, BIEN SAVOIR CE QUE L'ON FAIT ! **
2016-11-01 22:50:26 +01:00
On pourra ainsi injecter le contenu d'un binlog dans une base… tout simplement avec une commande du type :
2016-11-01 23:37:14 +01:00
~~~
# mysqlbinlog /var/log/mysql/mysql-bin.001789 | mysql -P3307
~~~
2016-11-01 22:50:26 +01:00
À noter que si une partie des données étaient déjà présentes (cas d'un binlog corrompu lors d'incident lors d'une réplication), on pourra procéder ainsi :
2016-11-01 23:37:14 +01:00
~~~
# mysqlbinlog /var/log/mysql/mysql-bin.001789 > mysql-bin.001789.txt
# sed -i 's/INSERT INTO/INSERT IGNORE INTO/gi' mysql-bin.001789.txt
# cat mysql-bin.001789.txt | mysql -P3307
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Log des requêtes lentes
2016-11-01 22:50:26 +01:00
2016-12-14 14:23:53 +01:00
Pour débugger les applications lentes, c'est une fonctionnalité intéressante de trouver quelle requête est longue.
2016-11-15 10:42:16 +01:00
Pour cela on peut spécifier quand une requête est considérée comme longue, le chemin où stocker les requêtes, et l'activation des logs.
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
2016-12-16 01:49:46 +01:00
[mysqld]
long_query_time = 5
2016-11-01 23:37:14 +01:00
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## Multiples instances MySQL
2016-11-01 22:50:26 +01:00
2016-11-15 10:42:16 +01:00
Il est possible de faire fonctionner plusieurs instances de MySQL sur un serveur ; chacune avec ses propres données et sa propre configuration.
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Installation
2016-11-01 22:50:26 +01:00
Avant toute opération, il est nécessaire de commenter cette ligne dans le `/etc/mysql/my.cnf` :
2016-11-01 23:37:14 +01:00
~~~{.ini}
#user = mysql
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
et de rajouter ces lignes (_à voir l'utilité en fait…_)
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
[mysqld_multi]
2016-11-02 12:12:48 +01:00
user = mysqladmin
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Créer un utilisateur pour l'instance (il doit avoir un shell valide comme `/bin/sh`) :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# useradd mysql-foo
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Créer ensuite le *datadir* :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mysql_install_db --datadir=/srv/mysql-instances/foo
# chown -R mysql-foo:mysql-foo /srv/mysql-instances/foo
# chmod 700 /srv/mysql-instances/foo
2016-11-01 23:37:14 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Ajouter ces lignes dans `/etc/mysql/conf.d/zzz_evolinux.cnf` :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.ini}
[mysqld1]
2016-11-02 12:12:48 +01:00
mysqld = /usr/bin/mysqld_safe
2016-12-16 01:49:46 +01:00
user = mysql-foo
2016-11-02 12:12:48 +01:00
port = 3307
2016-12-16 01:49:46 +01:00
socket = /var/run/mysqld-foo/mysqld.sock
pid-file = /var/run/mysqld-foo/mysqld.pid
datadir = /home/mysql-foo
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
*Note 1* : même si l'on ne prévoit pas de faire tourner le mysqld principal sur le port 3306,
on préfère tout de même utiliser le port 3307 pour la première instance afin de ne pas
2016-11-01 22:50:26 +01:00
confondre une configuration avec et sans instance.
2016-12-16 01:49:46 +01:00
*Note 2* : dans le cas où une réplication est déjà active sur l'instance principale, la nouvelle instance créée va automatiquement hériter des paramètres de réplication.
2016-11-01 22:50:26 +01:00
Pour éviter ça, il suffit de rajouter :
2016-11-01 23:37:14 +01:00
~~~{.ini}
[mysqld1]
skip-slave-start
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Créer le répertoire qui contiendra le socket et le fichier PID :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
2016-12-16 01:49:46 +01:00
# mkdir /var/run/mysqld-foo
# chown mysql-foo:mysql-foo /var/run/mysqld-foo
2016-12-16 01:52:54 +01:00
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Puis lancer la nouvelle instance :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# mysqld_multi start 1
~~~
2016-11-01 22:50:26 +01:00
Enfin, n'oubliez pas de définir un mot de passe root/mysqladmin pour la nouvelle instance !
Pour voir l'état des instances :
2016-11-01 23:37:14 +01:00
~~~
# mysqld_multi report
~~~
2016-11-01 22:50:26 +01:00
2016-12-14 14:23:53 +01:00
Et pour stopper une instance, on évite la commande « mysqld_multi stop 1 » qui n'est que rarement fiable et peut laisser l'instance dans un état incorrect, difficile à récupérer.
2016-11-01 22:50:26 +01:00
2016-12-14 14:23:53 +01:00
On préfère passer la commande « shutdown » en interne :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# mysqladmin -P3307 shutdown
~~~
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
**Note** : a priori cela revient à envoyer un signal SIGTERM (kill -15) au process mysqld
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Nettoyage
2016-11-01 22:50:26 +01:00
2016-12-16 01:49:46 +01:00
Si le *mysqld* principal n'est pas utilisé, on désactivera le script d'init.d /etc/init.d/mysql (en ajoutant `exit 0`
2016-12-14 14:23:53 +01:00
au début du script) et on pourra se créer un script `/etc/init.d/mysql-instance` du type :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~{.bash}
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: mysql-instance
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $network $time
# Should-Stop: $network $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop the mysql database server daemon
# Description: Controls the main MySQL database server daemon "mysqld"
# and its wrapper script "mysqld_safe".
### END INIT INFO
#
set -e
set -u
case "$1" in
start)
mysqld_multi start
;;
stop)
mysqld_multi stop
;;
restart)
mysqld_multi stop
mysqld_multi start
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
### Administration
2016-11-01 22:50:26 +01:00
Pour voir le statut de l'instance n°1, logiquement nommée mysqld1 (GNR=1) et tournant sur le port 3307 :
2016-11-01 23:37:14 +01:00
~~~
# mysqld_multi report 1
Reporting MySQL servers
MySQL server from group: mysqld1 is running
~~~
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
Pour l'arrêter/redémarrer, même principe (attention, `mysqld_multi` est peu verbeux) :
2016-11-01 22:50:26 +01:00
2016-11-01 23:37:14 +01:00
~~~
# ps auwx | grep 3307
# mysqladmin -P 3307 shutdown
# ps auwx | grep 3307
# mysqld_multi start 1
# ps auwx | grep 3307
~~~
2016-11-01 22:50:26 +01:00
2016-12-16 01:52:54 +01:00
## Optimisation avancée
2016-11-02 12:20:02 +01:00
2016-11-02 14:12:08 +01:00
Voir [/MySQL/HowtoOptimize]().
2016-11-02 12:20:02 +01:00
2016-12-16 01:52:54 +01:00
## Réplication MySQL
2016-11-01 22:50:26 +01:00
2016-11-02 14:12:08 +01:00
Voir [/MySQL/HowtoReplication]().
2016-11-01 22:50:26 +01:00
2016-11-02 12:12:48 +01:00
## FAQ et erreurs courantes
2016-11-01 22:50:26 +01:00
2016-11-02 14:12:08 +01:00
Voir [/MySQL/HowtoTroubleshooting]().