22
0
Fork 0

relecture [2/n]

This commit is contained in:
gcolpart 2016-12-16 01:49:46 +01:00
parent bae9ecbc6e
commit edf818f205
1 changed files with 122 additions and 101 deletions

View File

@ -321,20 +321,19 @@ On crée une base de données et un utilisateur associé :
mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@localhost IDENTIFIED BY 'PASSWORD';
~~~
Cette opération revient à insérer des lignes brutes dans les tables `mysql.user` et `mysql.db` :
Cette opération revient à insérer des lignes suivante dans les tables `mysql.user` et `mysql.db` :
~~~
mysql> INSERT INTO user VALUES ('localhost','USER_BASE',password('XXX'),'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 db VALUES ('localhost','NOM_BASE','USER_BASE','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
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');
mysql> FLUSH PRIVILEGES;
~~~
**Note** : sous Debian 6, les valeurs dans `mysql.user` avaient 3 colonnes de moins : Create_tablespace_priv, plugin et authentication_string :
(par défaut, pour migrer on ajoutera donc 'N' en 32ème position + '' et NULL à la fin) :
*Note* :
~~~
mysql> INSERT INTO user VALUES ('localhost','USER_BASE',password('XXX'),'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);
~~~
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)
On pourra ainsi régler finement les droits d'un utilisateur en connaissant la signification de chaque colonne :
@ -389,14 +388,14 @@ mysql> desc user;
42 rows in set (0.00 sec)
~~~
Par exemple, pour permettre à un utilisateur (ici `debian-sys-maint`) de faire des `SHOW VIEW` :
Par exemple, pour permettre à un utilisateur (ici *debian-sys-maint*) de faire des `SHOW VIEW` :
~~~
mysql> UPDATE user SET Show_view_priv='Y' WHERE User='debian-sys-maint';
mysql> FLUSH PRIVILEGES;
~~~
que l'on peut aussi faire via :
…que l'on peut aussi faire via :
~~~
mysql> GRANT SHOW VIEW on *.* to `debian-sys-maint`@localhost;
@ -405,32 +404,31 @@ mysql> GRANT SHOW VIEW on *.* to `debian-sys-maint`@localhost;
Pour créer un utilisateur sans droit particulier, par exemple pour du monitoring :
~~~
mysql> create user nagios@localhost identified by 'XXX';
mysql> create user nagios@localhost identified by 'PASSWORD';
~~~
On peut aussi gérer des droits sur les tables :
~~~
mysql> GRANT Select,Insert,Update ON BASE.TABLE TO 'USER_BASE'@localhost;
mysql> GRANT Select,Insert,Update ON foo.bar TO 'jdoe'@localhost;
~~~
Pour révoquer des droits sur une table, on utilisera `REVOKE` :
~~~
mysql> REVOKE ALL PRIVILEGES ON BASE.TABLE FROM 'USER_BASE'@localhost;
mysql> REVOKE ALL PRIVILEGES ON foo.bar FROM 'jdoe'@localhost;
~~~
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) !
/!\\ 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) !
On le positionnera ainsi :
~~~
mysql> GRANT FILE ON *.* TO 'USER_BASE'@localhost;
mysql> GRANT FILE ON *.* TO 'jdoe'@localhost;
~~~
### Vérifications et réparations
Pour vérifier et réparer toutes les tables (une sorte de `fsck` pour les tables),
on lancera la commande suivante :
Pour vérifier et réparer toutes les tables (une sorte de *fsck* pour les tables), on lancera :
~~~
# mysqlcheck --auto-repair --check --all-databases
@ -439,12 +437,12 @@ on lancera la commande suivante :
On peut aussi réparer qu'une base en particulier :
~~~
# mysqlcheck --auto-repair --check mabase
# mysqlcheck --auto-repair --check foo
~~~
Note : ceci est à faire en général en cas d'arrêt inopiné du serveur.
*Note* : ceci peut être à faire en cas d'arrêt inopiné du service.
On pourra également ajouter l'option *--optimize* pour ajouter une optimisation des tables :
On pourra également ajouter l'option **--optimize* pour ajouter une optimisation des tables :
~~~
# mysqlcheck --auto-repair --check --optimize --all-databases
@ -453,19 +451,19 @@ On pourra également ajouter l'option *--optimize* pour ajouter une optimisation
Pour réparer une seule table :
~~~
mysql> CHECK TABLE mabase.matable;
mysql> REPAIR TABLE mabase.matable;
mysql> OPTIMIZE TABLE mabase.matable;
mysql> CHECK TABLE foo.bar;
mysql> REPAIR TABLE foo.bar;
mysql> OPTIMIZE TABLE foo.bar;
~~~
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é :
~~~
# myisamchk -r -q /var/lib/mysql/BASE/TABLE.MYD
# myisamchk -r -q /var/lib/mysql/foo/bar.MYD
~~~
En cas d'échec (segfault par exemple), on peut tenter :
En cas d'échec (*segfault* par exemple), on peut tenter :
~~~
# 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
@ -480,14 +478,14 @@ mysql> select * from INFORMATION_SCHEMA.routines;
### Changement mot de passe utilisateur
~~~
> SET PASSWORD FOR 'user'@'hostname' = PASSWORD('pwd');
mysql> SET PASSWORD FOR 'jdoe'@'localhost' = PASSWORD('PASSWORD');
~~~
Par rapport à un autre utilisateur:
Par rapport à un autre utilisateur :
~~~
mysql> use mysql;
mysql> UPDATE USER SET Password='XXXXX' WHERE User='XXXXX' and Host='XX.XX.XX.XX';
mysql> UPDATE mysql.user SET Password='PASSWORD' WHERE User='jdoe' and Host='localhost';
~~~
### Changer variables global d'environnement
@ -507,31 +505,31 @@ mysql> SET @@max_connect_errors=50;
Pour sauvegarder une base de données (sans et avec compression) :
~~~
# mysqldump NOM_BASE > NOM_FICHIER
# mysqldump NOM_BASE | gzip > NOM_FICHIER
# mysqldump foo > foo.sql
# mysqldump foo | gzip > foo.sql.gz
~~~
Pour restaurer une base de données (sans et avec compression) :
~~~
# mysqladmin create NOM_BASE
# mysql NOM_BASE < NOM_FICHIER
# gunzip < NOM_FICHIER | mysql NOM_BASE
# mysqladmin create foo
# mysql foo < foo.sql
# gunzip < foo.sql.gz | mysql foo
~~~
Sauvegarder toutes les bases :
~~~
# mysqldump --opt --all-databases > NOM_FICHIER
# mysqldump --opt --all-databases > all.sql
~~~
Pour sauvegarder uniquement certaines tables :
~~~
# mysqldump NOM_BASE NOM_TABLE0 [NOM_TABLE1…] > NOM_FICHIER
# mysqldump foo TABLE0 [TABLE1…] > foo_tables.sql
~~~
Pour presque faire un "--exclude" (qui manque cruellement à mysqldump):
Pour presque faire un *--exclude* (qui manque cruellement à *mysqldump*):
~~~
mysql -B -N -e 'show databases' | \
@ -542,19 +540,19 @@ mysql -B -N -e 'show databases' | \
Et pour sauvegarder des tables correspondant à un motif (préfixe le plus souvent) :
~~~
# mysqldump NOM_BASE $(mysql NOM_BASE -B --column-names=False -e "show tables like 'exemple_%'") > NOM_FICHIER
# mysqldump foo $(mysql foo -B --column-names=False -e "show tables like 'exemple_%'") > foo_motif.sql
~~~
Pour dumper avec une condition particulière :
~~~
mysqldump -t <base> <table> --where="my_id='66666666'"
mysqldump -t foo bar --where="id='66666666'"
~~~
Ce qui permet de réinjecter des données résultantes d'un `SELECT * FROM base.table WHERE my_id='66666666'`.
Ce qui permet de réinjecter des données résultantes d'un `SELECT * FROM foo.bar WHERE id='66666666'`.
Il est évidement possible de faire toutes ces opérations sur une instance en
précisant son port avec l'option `--port` (valable pour mysqldump et mysql).
précisant son port avec l'option `--port` (valable pour *mysqldump* et *mysql*).
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/)) :
@ -572,17 +570,16 @@ mygrants()
Pour avoir un dump avec un seul insert par ligne, pratique pour restaurer partiellement les bases `mysql.user` et `mysql.db` par exemple :
~~~
# mysqldump --skip-extended-insert mysql > mysql.dump
# mysqldump --skip-extended-insert mysql > mysql.sql
~~~
Pour restaurer une seule base d'un dump complet on peut utiliser :
~~~
mysql -o MaBase < dump.sql
mysql -o foo < all.sql
~~~
Pour restaurer une base, dont la structure de chaque table est stocké 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 :
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 :
~~~{.bash}
db=test1
@ -599,19 +596,19 @@ for file in *.txt; do
done
~~~
**Note 1** : Attention, l'utilisateur MySQL doit avoir le droit de lecture sur les fichiers .txt
*Note 1* : Attention, l'utilisateur MySQL doit avoir le droit de lecture sur les fichiers .txt
Se positionner dans un répertoire où mysql a les droits (mysqltmp - /home/mysqltmp par ex).
**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)
*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)
Il est possible d'exporter le contenu d'une base au format CSV :
~~~
mysqldump -T /tmp --fields-enclosed-by=\" --fields-terminated-by=, --no-create-db --no-create-info MaBase
# mysqldump -T /tmp --fields-enclosed-by=\" --fields-terminated-by=, --no-create-db --no-create-info foo
~~~
NOTE : il est nécessaire que MySQL ait les droits d'écriture dans le répertoire de destination (ici `/tmp`).
*Note* : il est nécessaire que MySQL ait les droits d'écriture dans le répertoire de destination (ici `/tmp`).
## Monitoring
@ -623,36 +620,38 @@ Pour surveiller un service MySQL en production, on pourra faire :
# mysqladmin processlist
~~~
Pour avoir une version plus conviviale et dynamique des process en cours, on utilisera l'indispensable outil `mytop`.
### mytop
Pour avoir une version conviviale et dynamique des process en cours, on utilisera l'outil *mytop*.
~~~
# aptitude install mytop
# apt install mytop
~~~
On édite le fichier `/root/.mytop` ainsi :
~~~{.ini}
user = debian-sys-maint
pass = MOT_DE_PASSE
pass = PASSWORD
db = mysql
~~~
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).
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).
L'outil mytop se sert principalement de la requête `SHOW PROCESSLIST` que l'on pourra bien sûr lancer manuellement. Tout comme `KILL` :
L'outil *mytop* se sert principalement de la requête `SHOW PROCESSLIST` que l'on pourra bien sûr lancer manuellement. Tout comme `KILL` :
~~~
mysql> SHOW PROCESSLIST;
mysql> KILL <id_interne_requête>;
mysql> KILL <id_requête>;
~~~
Lister les requêtes qui durent plus de 30 secondes pour pouvoir les tuer facilement :
Pour lister les requêtes qui durent plus de 30 secondes pour pouvoir les tuer facilement :
~~~
mysql -e 'select group_concat(concat("kill ",ID) separator ";") from information_schema.processlist where TIME>=30;'
~~~
Puis exécuter le résultat avec la commande mysql, ex :
Puis exécuter le résultat avec la commande *mysql*, exemple :
~~~
mysql -e 'kill 1854;kill 1853;kill 1852;kill 1851;kill 1850;kill 1848'
@ -664,30 +663,55 @@ Pour surveiller le moteur InnoDB, on utilisera la commande suivante :
mysql> SHOW ENGINE INNODB STATUS;
~~~
Enfin, reste Munin qui permet d'obtenir de jolis graphes.
### Munin
Afin d'être alerté en cas de soucis, il est conseillé d'ajouter la configuration suivante au logiciel `log2mail` :
Pour activer les plugins MySQL pour Munin :
~~~
# 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 = "should be repaired"
mailto = ADRESSE-MAIL-ALERTE
template = /etc/log2mail/template.mysql
pattern = "is marked as crashed and should be repaired"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
file = /var/log/syslog
pattern = "try to repair it"
mailto = ADRESSE-MAIL-ALERTE
template = /etc/log2mail/template.mysql
pattern = "init function returned error"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
file = /var/log/syslog
pattern = "InnoDB: Fatal error"
mailto = ADRESSE-MAIL-ALERTE
template = /etc/log2mail/template.mysql
pattern = "try to repair it"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
file = /var/log/syslog
pattern = "as a STORAGE ENGINE failed"
mailto = ADRESSE-MAIL-ALERTE
template = /etc/log2mail/template.mysql
pattern = "InnoDB: Fatal error"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
file = /var/log/syslog
pattern = "as a STORAGE ENGINE failed"
mailto = monitoring@example.com
template = /etc/log2mail/template.mysql
~~~
Le fichier `/etc/log2mail/template.mysql` contenant :
@ -707,7 +731,7 @@ Yours,
log2mail.
~~~
Note : il faut ajouter l'utilisateur `log2mail` dans le groupe `adm`.
*Note* : il faut ajouter l'utilisateur `log2mail` dans le groupe `adm`.
## Gestion des binlogs
@ -719,6 +743,7 @@ Par défaut, MySQL stocke chaque requête en écriture dans des fichiers appelé
Par défaut les binlogs sont conservés sur 10 jours, avec des fichiers n'excédant pas 100 Mo :
~~~{.ini}
[mysqld]
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
@ -729,7 +754,7 @@ binlog_format = mixed
### Format
http://dev.mysql.com/doc/refman/5.5/en/binary-log-setting.html
<http://dev.mysql.com/doc/refman/5.5/en/binary-log-setting.html>
On peut choisir 3 types de format pour les binlogs :
@ -765,7 +790,8 @@ mysql> PURGE BINARY LOGS BEFORE "2011-12-07 00:00:00";
Pour désactiver les binlogs, on ajoutera l'option suivante dans la configuration :
~~~
~~~{.ini}
[mysqld]
disable-log-bin
~~~
@ -777,12 +803,12 @@ On pourra lire en ligne de commande le contenu d'un binlog via la commande :
# mysqlbinlog /var/log/mysql/mysql-bin.001789 | less
~~~
Note : si vous obtenez une erreur `mysqlbinlog: unknown variable 'default-character-set=utf8'` c'est que la directive `default-character-set`
* Note* : si vous obtenez une erreur `mysqlbinlog: unknown variable 'default-character-set=utf8'` c'est que la directive `default-character-set`
a été placée dans la configuration MySQL (`/etc/mysql` ou `.my.cnf`) dans la mauvaise section : `[client]` au lieu de `[mysql]` (ou `[mysqldump]`).
### Replay
**ATTENTION, CES MANIPULATIONS PEUVENT ÊTRE DANGEREUSES VOS DONNÉES, BIEN SAVOIR CE QUE L'ON FAIT.**
/!\\ **ATTENTION, CES MANIPULATIONS PEUVENT ÊTRE DANGEREUSES VOS DONNÉES, BIEN SAVOIR CE QUE L'ON FAIT ! **
On pourra ainsi injecter le contenu d'un binlog dans une base… tout simplement avec une commande du type :
@ -798,19 +824,18 @@ On pourra ainsi injecter le contenu d'un binlog dans une base… tout simplement
# cat mysql-bin.001789.txt | mysql -P3307
~~~
### Log des requêtes lentes
Pour débugger les applications lentes, c'est une fonctionnalité intéressante de trouver quelle requête est longue.
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.
~~~{.ini}
long_query_time = 2 #Default 10 !
[mysqld]
long_query_time = 5
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
~~~
## Multiples instances MySQL
Il est possible de faire fonctionner plusieurs instances de MySQL sur un serveur ; chacune avec ses propres données et sa propre configuration.
@ -830,55 +855,51 @@ et de rajouter ces lignes (_à voir l'utilité en fait…_)
user = mysqladmin
~~~
Créez un utilisateur pour l'instance (il doit avoir un shell valide comme `/bin/sh`) :
Créer un utilisateur pour l'instance (il doit avoir un shell valide comme `/bin/sh`) :
~~~
useradd mysql-INSTANCE_NAME
# useradd mysql-foo
~~~
Créez ensuite le « datadir » :
Créer ensuite le *datadir* :
~~~
# mysql_install_db --datadir=/home/mysql/INSTANCE_NAME
# chown -R mysql-INSTANCE_NAME:mysql-INSTANCE_NAME /home/mysql/INSTANCE_NAME
# chmod 700 /home/mysql/INSTANCE_NAME
# mysql_install_db --datadir=/srv/mysql-instances/foo
# chown -R mysql-foo:mysql-foo /srv/mysql-instances/foo
# chmod 700 /srv/mysql-instances/foo
~~~
**Note** : Sous Debian Etch, l'option `--user` n'est pas présente.
Ajoutez ces lignes dans `/etc/mysql/my.cnf` :
Ajouter ces lignes dans `/etc/mysql/conf.d/zzz_evolinux.cnf` :
~~~{.ini}
[mysqld1]
mysqld = /usr/bin/mysqld_safe
user = mysql-INSTANCE_NAME
user = mysql-foo
port = 3307
socket = /var/run/mysqld-INSTANCE_NAME/mysqld.sock
pid-file = /var/run/mysqld-INSTANCE_NAME/mysqld.pid
datadir = /home/mysql-INSTANCE_NAME
socket = /var/run/mysqld-foo/mysqld.sock
pid-file = /var/run/mysqld-foo/mysqld.pid
datadir = /home/mysql-foo
~~~
**Note 1** : même si l'on ne prévoit pas de faire tourner le mysqld principal sur le port 3306,
on préfèrera tout de même utiliser le port 3307 pour la première instance afin de ne pas
*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
confondre une configuration avec et sans instance.
**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.
*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.
Pour éviter ça, il suffit de rajouter :
~~~{.ini}
[mysqld1]
skip-slave-start
~~~
Créez le répertoire qui contiendra le socket et le fichier PID :
Créer le répertoire qui contiendra le socket et le fichier PID :
~~~
mkdir /var/run/mysqld-INSTANCE_NAME
chown mysql-INSTANCE_NAME:mysql-INSTANCE_NAME /var/run/mysqld-INSTANCE_NAME
~~~
# mkdir /var/run/mysqld-foo
# chown mysql-foo:mysql-foo /var/run/mysqld-foo
Puis lancez la nouvelle instance :
Puis lancer la nouvelle instance :
~~~
# mysqld_multi start 1
@ -904,7 +925,7 @@ On préfère passer la commande « shutdown » en interne :
### Nettoyage
Si le mysqld principal n'est pas utilisé, on désactivera le script d'init.d /etc/init.d/mysql (en ajoutant `exit 0`
Si le *mysqld* principal n'est pas utilisé, on désactivera le script d'init.d /etc/init.d/mysql (en ajoutant `exit 0`
au début du script) et on pourra se créer un script `/etc/init.d/mysql-instance` du type :
~~~{.bash}