mirroir readonly du Gitit wiki.evolix.org (attention, ne rien commiter/merger sur ce dépôt) https://wiki.evolix.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1564 lines
50 KiB

3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
1 year ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 years ago
4 years ago
  1. ---
  2. categories: databases
  3. title: Howto MySQL : installation et utilisation courante.
  4. ---
  5. * Documentation MariaDB : <https://mariadb.com/kb/en/library/documentation/>
  6. * Documentation MySQL 5.5 : <http://dev.mysql.com/doc/refman/5.5/en/>
  7. * Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/show/mysql>
  8. [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.
  9. ## Installation
  10. Sous Debian 9, nous installons MariaDB :
  11. ~~~
  12. # apt install mariadb-server mariadb-client libconfig-inifiles-perl
  13. $ mysql --version
  14. mysql Ver 15.1 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
  15. ~~~
  16. > *Note* : Sous Debian 8, nous installons la version libre de MySQL distribuée par Oracle :
  17. >
  18. > ~~~
  19. > # apt install mysql-server
  20. >
  21. > $ mysql --version
  22. > mysql Ver 14.14 Distrib 5.5.53, for debian-linux-gnu (x86_64) using readline 6.3
  23. > ~~~
  24. >
  25. > ou MariaDB :
  26. >
  27. > ~~~
  28. > # apt install mariadb-server-10.0
  29. >
  30. > $ mysql --version
  31. > mysql Ver 15.1 Distrib 10.0.28-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
  32. > ~~~
  33. L'installation sous Debian demande un mot de passe pour le superutilisateur (par défaut *root*) de MySQL.
  34. En laissant un mot de passe vide, on peut se connecter sans mot de passe :
  35. ~~~
  36. $ mysql -u root
  37. Welcome to the MariaDB monitor. Commands end with ; or \g.
  38. Your MariaDB connection id is 18348
  39. Server version: 10.1.26-MariaDB-0+deb9u1 Debian 9.1
  40. Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
  41. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  42. MariaDB [(none)]>
  43. ~~~
  44. 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 :
  45. ~~~{ .sql }
  46. mysql> GRANT ALL PRIVILEGES ON *.* TO adminmysql@localhost IDENTIFIED BY 'PASSWORD' WITH GRANT OPTION;
  47. mysql> DELETE FROM mysql.user where User='root';
  48. ~~~
  49. Au niveau sécurité, le mot de passe est généré à l'installation
  50. (stocké dans `/etc/mysql/debian.cnf` lisible que par *root*) par la commande :
  51. ~~~
  52. perl -e 'print map{("a".."z","A".."Z",0..9)[int(rand(62))]}(1..16)'
  53. ~~~
  54. Enfin, on peut utiliser un fichier `.my.cnf` pour conserver l'identifiant et le mot de passe.
  55. Par exemple pour *root*, dans `/root/.my.cnf` :
  56. ~~~{.ini}
  57. [client]
  58. user = adminmysql
  59. password = PASSWORD
  60. ~~~
  61. Pour changer le mot de passe, on fera simplement :
  62. ~~~
  63. # mysqladmin password PASSWORD
  64. ~~~
  65. On notera sous Debian la présence d'un utilisateur *debian-sys-maint* qui sert à certains scripts Debian :
  66. il ne doit pas être supprimé !
  67. Sous Debian 8, avec MariaDB 10.0, l'utilisateur *debian-sys-maint* **n'a pas le privilège GRANT**. Il est donc impossible de créer d'autres utilisateurs en étant connecté avec ce compte.
  68. ### bibliothèque client
  69. Certains logiciels tiers nécessitent la "bibliothèque client".
  70. Sur Debian 8, c'est le paquet `libmysqlclient-dev`.
  71. Sur Debian 9 (et Debian 8 avec backports), c'est le meta-paquet `default-libmysqlclient-dev` qui permet de facilement installer la paquet adapté à votre base de données.
  72. ### MySQL 5.7
  73. <https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/>
  74. Pour installer MySQL 5.7 distribuée par Oracle sous Debian 9, on ajoute le dépôt *repo.mysql.com* :
  75. ~~~
  76. # echo "deb http://repo.mysql.com/apt/debian stretch mysql-5.7" > /etc/apt/sources.list.d/mysql57.list
  77. # apt-key adv --keyserver pgp.mit.edu --recv-keys 5072E1F5
  78. ~~~
  79. On peut ensuite installer les paquets :
  80. ~~~
  81. # apt install mysql-server mysql-client
  82. ~~~
  83. > *Note* : il faudra alors installer *mytop* en récupérant le package de Debian 8
  84. ## Configuration
  85. Le fichier de configuration principal est `/etc/mysql/my.cnf` qui inclue notamment les fichiers `.cnf` présents dans les sous-répertoires `conf.d/` et `mariadb.conf.d/`.
  86. > *Note* : attention, si vous avez une configuration MySQL/MariaDB issue d'une Debian 8 (suite upgrade par exemple), le sous-répertoire `mariadb.conf.d/` ne sera **pas** pris en compte.
  87. Le fichier `/etc/mysql/mariadb.conf.d/z-evolinux-defaults.cnf` contient nos optimisations basiques :
  88. ~~~{.ini}
  89. [mysqld]
  90. ###### Connexions
  91. # Maximum de connexions concurrentes (defaut = 100)... provoque un "Too many connections"
  92. max_connections = 250
  93. # Maximum de connexions en attente en cas de max_connections atteint (defaut = 50)
  94. back_log = 100
  95. # Maximum d'erreurs avant de blacklister un hote
  96. max_connect_errors = 10
  97. # Loguer les requetes trop longues
  98. slow_query_log = 1
  99. slow_query_log_file = /var/log/mysql/mysql-slow.log
  100. long_query_time = 10
  101. ###### Tailles
  102. # Taille reservee au buffer des index MyIsam
  103. # A ajuster selon les resultats
  104. key_buffer_size = 512M
  105. # Taille max des paquets envoyés/reçus … provoque un "Packet too large"
  106. max_allowed_packet = 64M
  107. # Taille de la memoire reserve pour un thread
  108. thread_stack = 192K
  109. # A mettre le nombre de threads CPU alloues pour MySQL
  110. thread_cache_size = 1
  111. # Taille maximum des tables de type MEMORY
  112. max_heap_table_size = 64M
  113. ###### Cache
  114. # max_connections x nbre max de tables dans une jointure (defaut = 64)
  115. table_open_cache = 4096
  116. table_definition_cache = 4096
  117. # Taille max des requetes cachees (defaut = 1M)
  118. query_cache_limit = 8M
  119. # Taille reservee pour le cache (defaut = 0)
  120. query_cache_size = 256M
  121. # Type de requetes a cacher (defaut = 1 : tout peut etre cache)
  122. query_cache_type = 1
  123. # Cache tables
  124. max_heap_table_size = 128M
  125. tmp_table_size = 128M
  126. ###### InnoDB
  127. # Si InnoDB n'est pas utilise... le desactiver
  128. #skip-innodb
  129. # En general, il est plus optimum d'avoir un fichier par table
  130. innodb_file_per_table
  131. # Taille memoire allouee pour le cache des datas et index
  132. # A ajuster en fonction de sa RAM (si serveur dedie a MySQL, on peut aller jusqu'a 80%)
  133. innodb_buffer_pool_size = 512M
  134. # Nombre maximum de threads systeme concurents
  135. innodb_thread_concurrency = 16
  136. # Ajuste la valeur des logs InnoDB
  137. # (attention, il faut ensuite stopper MySQL et effacer les fichiers ib_logfile*)
  138. #innodb_log_file_size = 128M
  139. #innodb_log_files_in_group = 2
  140. ###### Misc
  141. # charset utf8 par defaut
  142. character-set-server=utf8
  143. collation-server=utf8_general_ci
  144. # Patch MySQL 5.5.53
  145. secure-file-priv = ""
  146. ~~~
  147. **Note** : MariaDB 10.1 avec Debian 9 est par défaut en `utf8mb4` + collation `utf8mb4_general_ci`.
  148. Le fichier `/etc/mysql/mariadb.conf.d/zzz-evolinux-custom.cnf` contient nos éventuelles optimisations spécifiques.
  149. Nous désactivons également une protection mise en place par l'unité [systemd](HowtoSystemd).
  150. Cela permet d'utiliser la partition `/home` ou `/srv` pour des sauvegardes ou autres opérations :
  151. ~~~
  152. # cat /etc/systemd/system/mariadb.service.d/evolinux.conf
  153. [Service]
  154. ProtectHome=false
  155. ~~~
  156. 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`
  157. Pour activer les connexions réseau à distance, il faut ajouter la configuration suivante dans `zzz-evolinux-custom.cnf` :
  158. ~~~{.ini}
  159. [mysqld]
  160. bind-address = 0.0.0.0
  161. ~~~
  162. 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 !).
  163. On conseille au minimum d'ajuster *thread_cache_size* et *innodb_buffer_pool_size* :
  164. ~~~{.ini}
  165. [mysqld]
  166. # Nombre de threads CPU alloués pour MySQL
  167. thread_cache_size = 2
  168. # Mémoire allouée pour le cache InnoDB (si serveur dédié, on peut aller jusqu'à 80% de la RAM)
  169. innodb_buffer_pool_size = 2G
  170. ~~~
  171. Pour plus d'informations sur l'optimisation avancée de MySQL, consultez le guide [/HowtoMySQL/Optimize]().
  172. > *Note* : Sous Debian 8, nous mettons notre configuration dans `/etc/mysql/conf.d/evolinux.cnf`
  173. ## datadir / tmpdir
  174. Par défaut, le *datadir* (le répertoire où sont stockées les données brutes) est `/var/lib/mysql/`.
  175. Pour diverses raisons il peut être intéressant de le déplacer (partition ou disque dédié etc.).
  176. Pour des raisons de compatibilité, on conseille de conserver un lien symbolique :
  177. ~~~
  178. # systemctl stop mysql
  179. # mv /var/lib/mysql /srv/mysql-datadir
  180. # ln -s /srv/mysql-datadir /var/lib/mysql
  181. # systemctl start mysql
  182. ~~~
  183. Pour certaines opérations lourdes, MySQL a besoin d'un *tmpdir* (répertoire où il va écrire des tables temporaires).
  184. 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 :
  185. ~~~{.ini}
  186. [mysqld]
  187. tmpdir = /srv/mysql-tmpdir
  188. ~~~
  189. ## Logs
  190. Sous Debian, les journaux de MySQL (démarrage, arrêt, erreurs, informations) sont envoyés via *syslog*.
  191. Par défaut, ils seront donc visibles dans `/var/log/syslog`.
  192. Le répertoire `/var/log/mysql/` contient les *binlogs* (trace de toutes les requêtes INSERT/UPDATE/DELETE exécutées).
  193. ## Utilisation courante
  194. ### Créer
  195. Créer une nouvelle base de données nommée _foo_ :
  196. ~~~{.sql}
  197. mysql> CREATE DATABASE foo;
  198. ~~~
  199. Créer une table nommée _bar_ avec différents champs :
  200. ~~~{.sql}
  201. mysql> CREATE TABLE bar (id INT not null AUTO_INCREMENT, prenom VARCHAR
  202. (50) not null , nom VARCHAR (50) not null , ne_le DATE not null ,
  203. ville VARCHAR (90), enfants INT, PRIMARY KEY (id));
  204. ~~~
  205. Ajouter un champ à une table :
  206. ~~~{.sql}
  207. mysql> ALTER TABLE bar ADD another VARCHAR(100) DEFAULT NULL;
  208. ~~~
  209. Ajouter un champ à une table en précisant sa place :
  210. ~~~{.sql}
  211. mysql> ALTER TABLE bar ADD another VARCHAR(100) DEFAULT NULL AFTER prenom;
  212. ~~~
  213. ### Lister
  214. Voir les bases de données créées :
  215. ~~~{.sql}
  216. mysql> SHOW DATABASES;
  217. ~~~
  218. Lister les accès créés :
  219. ~~~{.sql}
  220. mysql> select Host,user from mysql.user;
  221. ~~~
  222. Connaître les privilèges de ces derniers :
  223. ~~~{.sql}
  224. mysql> show grants for USER@'HOST';
  225. ~~~
  226. Utiliser la base de données _foo_ :
  227. ~~~{.sql}
  228. mysql> USE foo
  229. ~~~
  230. Voir les tables créées :
  231. ~~~{.sql}
  232. mysql> SHOW TABLES;
  233. ~~~
  234. Décrire une table :
  235. ~~~{.sql}
  236. mysql> DESC bar;
  237. ~~~
  238. Sélectionner tous les champs d'une table :
  239. ~~~{.sql}
  240. mysql> SELECT * FROM bar;
  241. ~~~
  242. Lancer des commandes bash depuis l'invite de commande :
  243. ~~~{ .sql }
  244. mysql> \! ls -l
  245. -rw-r----- 1 user user 208774 Jan 11 14:31 dump_base.sql
  246. ~~~
  247. Lister les droits pour tous les accès MySQL créés :
  248. ~~~
  249. # mysql -e "select concat('\'',User,'\'@\'',Host,'\'') as '' from mysql.user" | sort | \
  250. ( while read user; do [ -z "$user" ] && continue; echo "-- $user :"; mysql -e "show grants for $user"; done )
  251. -- 'accesbase'@'localhost' :
  252. Grants for accesbase@localhost
  253. GRANT USAGE ON *.* TO 'accesbase'@'localhost' IDENTIFIED BY PASSWORD '*XXXX'
  254. GRANT ALL PRIVILEGES ON `base`.* TO 'accesbase'@'localhost'
  255. ~~~
  256. ~~~
  257. # mysql -e "select * from information_schema.user_privileges;"
  258. ~~~
  259. ### Supprimer
  260. Supprimer un champ à une table :
  261. ~~~{.sql}
  262. mysql> ALTER TABLE bar DROP another;
  263. ~~~
  264. Effacer des données d'une table :
  265. ~~~{.sql}
  266. mysql> DELETE FROM bar WHERE nom='waddle';
  267. ~~~
  268. Effacer TOUTES les données d'une table :
  269. ~~~{.sql}
  270. mysql> DELETE FROM bar;
  271. ~~~
  272. Supprimer une table :
  273. ~~~{.sql}
  274. mysql> DROP TABLE bar;
  275. ~~~
  276. Supprimer une base de données :
  277. ~~~{ .sql }
  278. mysql> DROP DATABASE foo;
  279. ~~~
  280. Supprimer les différents privilèges pour un utilisateur mysql :
  281. ~~~{ .sql }
  282. mysql> REVOKE ALL PRIVILEGES ON base.* FROM 'user'@'localhost';
  283. ~~~
  284. Lister les bases de données dont l'utilisateur à le droit d'accès:
  285. ~~~{ .sql }
  286. SELECT * FROM mysql.db WHERE User="nvmpubli";
  287. ~~~
  288. Supprimer un accès (utilisateur) :
  289. ~~~{ .sql }
  290. mysql> DROP USER 'user'@'localhost';
  291. ~~~
  292. ### Renommer
  293. #### Base
  294. - Créer une base vide
  295. - Renommer toutes les tables vers cette dernière (utilisation script ci-dessous)
  296. ~~~{.bash}
  297. BASE_FROM=db1; BASE_TO=db2
  298. for table in $(mysql -e "use $BASE_FROM; show tables\G;" | grep -v '^\*\*\*' | cut -d':' -f2 | sed 's/^ //'); do echo $table; mysql -e "RENAME TABLE ${BASE_FROM}.${table} TO ${BASE_TO}.${table};"; done
  299. ~~~
  300. - Appliquer les bons droits à la bdd
  301. #### Table
  302. Renommer un champ :
  303. ~~~{.sql}
  304. mysql> ALTER TABLE bar CHANGE COLUMN another anotherone TEXT;
  305. ~~~
  306. Changer le type d'un champ :
  307. ~~~{.sql}
  308. mysql> ALTER TABLE bar CHANGE another another enum('foo',bar');
  309. ~~~
  310. ### Insérer
  311. Insertion de données dans une table :
  312. ~~~{.sql}
  313. mysql> INSERT INTO bar VALUES (1,'jp','papin','2005-06-12','Marseille',2);
  314. INSERT INTO test (id,prenom,nom,ne_le) VALUES (2,'c','waddle','2004-06-17');
  315. ~~~
  316. ### Vues
  317. Lister les vues de la base foo :
  318. ~~~{.sql}
  319. mysql> SHOW FULL TABLES IN foo WHERE TABLE_TYPE LIKE 'VIEW';
  320. ~~~
  321. Créer une vue baz à partir du contenu de la table bar :
  322. ~~~{.sql}
  323. mysql> CREATE VIEW baz AS SELECT * FROM bar;
  324. ~~~
  325. Voir la vue :
  326. ~~~{.sql}
  327. mysql> SHOW CREATE VIEW `baz`;
  328. ~~~
  329. Supprimer une vue baz :
  330. ~~~{.sql}
  331. mysql> DROP VIEW `baz`;
  332. ~~~
  333. ## Administration
  334. On crée une base de données et un utilisateur associé :
  335. ~~~
  336. # mysqladmin create foo
  337. # mysql
  338. mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@localhost IDENTIFIED BY 'PASSWORD';
  339. ~~~
  340. Cette opération revient à insérer des lignes suivante dans les tables `mysql.user` et `mysql.db` :
  341. ~~~{.sql}
  342. 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);
  343. 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');
  344. mysql> FLUSH PRIVILEGES;
  345. ~~~
  346. *À savoir* :
  347. Pour migrer de Debian 6 à 7 :
  348. - 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)
  349. - 2 colonnes ont été ajoutées dans `mysql.db` : Event_priv et Trigger_priv (pour migrer il faut ajouter 'Y' et 'Y' à la fin)
  350. On pourra ainsi régler finement les droits d'un utilisateur en connaissant la signification de chaque colonne :
  351. ~~~{.sql}
  352. mysql> desc user;
  353. +------------------------+-----------------------------------+------+-----+---------+-------+
  354. | Field | Type | Null | Key | Default | Extra |
  355. +------------------------+-----------------------------------+------+-----+---------+-------+
  356. | Host | char(60) | NO | PRI | | |
  357. | User | char(16) | NO | PRI | | |
  358. | Password | char(41) | NO | | | |
  359. | Select_priv | enum('N','Y') | NO | | N | |
  360. | Insert_priv | enum('N','Y') | NO | | N | |
  361. | Update_priv | enum('N','Y') | NO | | N | |
  362. | Delete_priv | enum('N','Y') | NO | | N | |
  363. | Create_priv | enum('N','Y') | NO | | N | |
  364. | Drop_priv | enum('N','Y') | NO | | N | |
  365. | Reload_priv | enum('N','Y') | NO | | N | |
  366. | Shutdown_priv | enum('N','Y') | NO | | N | |
  367. | Process_priv | enum('N','Y') | NO | | N | |
  368. | File_priv | enum('N','Y') | NO | | N | |
  369. | Grant_priv | enum('N','Y') | NO | | N | |
  370. | References_priv | enum('N','Y') | NO | | N | |
  371. | Index_priv | enum('N','Y') | NO | | N | |
  372. | Alter_priv | enum('N','Y') | NO | | N | |
  373. | Show_db_priv | enum('N','Y') | NO | | N | |
  374. | Super_priv | enum('N','Y') | NO | | N | |
  375. | Create_tmp_table_priv | enum('N','Y') | NO | | N | |
  376. | Lock_tables_priv | enum('N','Y') | NO | | N | |
  377. | Execute_priv | enum('N','Y') | NO | | N | |
  378. | Repl_slave_priv | enum('N','Y') | NO | | N | |
  379. | Repl_client_priv | enum('N','Y') | NO | | N | |
  380. | Create_view_priv | enum('N','Y') | NO | | N | |
  381. | Show_view_priv | enum('N','Y') | NO | | N | |
  382. | Create_routine_priv | enum('N','Y') | NO | | N | |
  383. | Alter_routine_priv | enum('N','Y') | NO | | N | |
  384. | Create_user_priv | enum('N','Y') | NO | | N | |
  385. | Event_priv | enum('N','Y') | NO | | N | |
  386. | Trigger_priv | enum('N','Y') | NO | | N | |
  387. | Create_tablespace_priv | enum('N','Y') | NO | | N | |
  388. | ssl_type | enum('','ANY','X509','SPECIFIED') | NO | | | |
  389. | ssl_cipher | blob | NO | | NULL | |
  390. | x509_issuer | blob | NO | | NULL | |
  391. | x509_subject | blob | NO | | NULL | |
  392. | max_questions | int(11) unsigned | NO | | 0 | |
  393. | max_updates | int(11) unsigned | NO | | 0 | |
  394. | max_connections | int(11) unsigned | NO | | 0 | |
  395. | max_user_connections | int(11) unsigned | NO | | 0 | |
  396. | plugin | char(64) | YES | | | |
  397. | authentication_string | text | YES | | NULL | |
  398. +------------------------+-----------------------------------+------+-----+---------+-------+
  399. 42 rows in set (0.00 sec)
  400. ~~~
  401. Par exemple, pour permettre à un utilisateur (ici *debian-sys-maint*) de faire des `SHOW VIEW` :
  402. ~~~{.sql}
  403. mysql> UPDATE user SET Show_view_priv='Y' WHERE User='debian-sys-maint';
  404. mysql> FLUSH PRIVILEGES;
  405. ~~~
  406. …que l'on peut aussi faire via :
  407. ~~~{.sql}
  408. mysql> GRANT SHOW VIEW on *.* to `debian-sys-maint`@localhost;
  409. ~~~
  410. Pour créer un utilisateur sans droit particulier, par exemple pour du monitoring :
  411. ~~~{.sql}
  412. mysql> create user nrpe@localhost identified by 'PASSWORD';
  413. ~~~
  414. On peut aussi gérer des droits sur les tables :
  415. ~~~{.sql}
  416. mysql> GRANT Select,Insert,Update ON foo.bar TO 'jdoe'@localhost;
  417. ~~~
  418. Pour révoquer des droits sur une table, on utilisera `REVOKE` :
  419. ~~~{.sql}
  420. mysql> REVOKE ALL PRIVILEGES ON foo.bar FROM 'jdoe'@localhost;
  421. ~~~
  422. /!\\ 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) !
  423. On le positionnera ainsi :
  424. ~~~{.sql}
  425. mysql> GRANT FILE ON *.* TO 'jdoe'@localhost;
  426. ~~~
  427. Si l'on veux autoriser l’accès a une base depuis un utilisateur MySQL, depuis l’extérieur :
  428. /!\\ Il faut s'assurer que MySQL écoute bien sur toutes les IPs (bind-address = 0.0.0.0 dans la configuration MySQL)
  429. Depuis une ip particulière :
  430. ~~~{.sql}
  431. mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@'IP_ADDRESS' IDENTIFIED BY 'PASSWORD';
  432. ~~~
  433. Depuis toutes les IPs :
  434. ~~~{.sql}
  435. mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@'%' IDENTIFIED BY 'PASSWORD';
  436. ~~~
  437. Si l'on ne connait pas le mot de passe, on peux utiliser le hash du mot de passe de l'utilisateur mysql comme ceci
  438. ~~~{.sql}
  439. mysql> GRANT ALL PRIVILEGES ON foo.* TO 'jdoe'@'%' IDENTIFIED BY PASSWORD '*E355A1AB8251C0B7E02ED8483696B2F3954C05CC';
  440. ~~~
  441. ### Vérifications et réparations
  442. Pour vérifier et réparer toutes les tables (une sorte de *fsck* pour les tables), on lancera :
  443. ~~~
  444. # mysqlcheck --auto-repair --check --all-databases
  445. ~~~
  446. On peut aussi réparer qu'une base en particulier :
  447. ~~~
  448. # mysqlcheck --auto-repair --check foo
  449. ~~~
  450. > *Note* : ceci peut être à faire en cas d'arrêt inopiné du service.
  451. Pour réparer une seule table :
  452. ~~~{.sql}
  453. mysql> CHECK TABLE foo.bar;
  454. mysql> REPAIR TABLE foo.bar;
  455. ~~~
  456. Dans le cas des tables MyISAM, si le REPAIR échoue, une réparation est aussi possible via `myisamchk`… à faire avec
  457. le service MySQL arrêté :
  458. ~~~
  459. # myisamchk -r -q /var/lib/mysql/foo/bar.MYD
  460. ~~~
  461. En cas d'échec (*segfault* par exemple), on peut tenter :
  462. ~~~
  463. # 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
  464. ~~~
  465. ### OPTIMIZE
  466. Il est conseillé de lancer régulièrement la commande `OPTIMIZE TABLE` sur ses tables.
  467. Cela va réaliser une sorte de défragmentation des tables, notamment sur les indexes.
  468. C'est particulièrement recommandé sur les tables qui subissent beaucoup de changement, notamment des modifications/suppressions de lignes.
  469. Voici comment on lance l'opération sur une table :
  470. ~~~{.sql}
  471. mysql> OPTIMIZE TABLE foo.bar;
  472. ~~~
  473. On peut également lancer cela sur l'ensemble des tables d'une base (mais cela peut être très long) :
  474. ~~~
  475. # mysqlcheck --optimize --all-databases
  476. ~~~
  477. > *Note* : lors d'un OPTIMIZE TABLE, la table est lockée.
  478. Suivant le moteur utilisé pour une table, les opérations vont être différentes. Notamment pour le moteur *InnoDB* vous aurez un message du type `Table does not support optimize, doing recreate + analyze instead` et une table temporaire sera complètement recréée et remplacera l'ancienne (attention à l'espace disque !).
  479. ### routines MySQL
  480. ~~~{.sql}
  481. mysql> select * from INFORMATION_SCHEMA.routines;
  482. ~~~
  483. ### Changement mot de passe utilisateur
  484. ~~~{.sql}
  485. mysql> SET PASSWORD FOR 'jdoe'@'localhost' = PASSWORD('my_password');
  486. MariaDB [(none)]> GRANT USAGE ON *.* TO 'jdoe'@'%' IDENTIFIED BY "passwd";
  487. ~~~
  488. Par rapport à un autre utilisateur :
  489. ~~~{.sql}
  490. mysql> use mysql;
  491. mysql> UPDATE mysql.user SET Password=PASSWORD('my_new_password') WHERE User='jdoe' and Host='localhost';
  492. ~~~
  493. Ou encore plus simple en se connectant avec le compte utilisateur puis lancer les commandes suivantes sans oublier de modifier le fichier de configuration :
  494. ~~~
  495. $ mysql
  496. > set password = password("mon-mot-de-passe-en-clair");
  497. $ vim ~/my.cnf
  498. ~~~
  499. ### Changer variables globales d'environnement
  500. On peut changer à chaud certaines variables globales d'environnement :
  501. ~~~{.sql}
  502. mysql> SET GLOBAL max_connect_errors=50;
  503. ~~~
  504. ou
  505. ~~~{.sql}
  506. mysql> SET @@max_connect_errors=50;
  507. ~~~
  508. Voici les changements utiles :
  509. ~~~{ .sql }
  510. mysql> set global max_connections = 350;
  511. ~~~
  512. > *Note* : on prendra garde à modifier aussi en dur dans la configuration si le changement doit être persistent.
  513. ### Lister les variables de configuration
  514. Pour voir la liste de toutes les variables :
  515. ~~~{.sql}
  516. mysql> show variables;
  517. ~~~
  518. Pour ne voir qu'un sous-ensemble de variables :
  519. ~~~{.sql}
  520. mysql> show variables like 'read_only';
  521. mysql> show variables like '%thread%';
  522. ~~~
  523. ### Lecture seule
  524. Si on veut qu'une instance de MySQL soit démarrée en lecture seule, on peut ajouter la variable `read_only = 1` dans la section `[mysqld]`. Seules les requêtes faites par des utilisateurs ayant le privilège SUPER seront alors exécutées.
  525. C'est par exemple utile dans une situation où une instance "slave" doit pouvoir être utilisée en lecture seule, tout en utilisant les mêmes comptes utilisateurs qui ont accès en écriture sur le "master". La réplication en elle-même n'est pas impactée.
  526. ### Tailles de bases et de tables
  527. Pour lister la taille de chaque base :
  528. ~~~{.sql}
  529. mysql> SELECT table_schema "DB Name",
  530. Round(Sum(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB"
  531. FROM information_schema.tables
  532. GROUP BY table_schema;
  533. ~~~
  534. Pour lister la taille de toutes les tables de toutes les bases :
  535. ~~~{.sql}
  536. mysql> SELECT
  537. table_schema as `Database`,
  538. table_name AS `Table`,
  539. round(((data_length + index_length) / 1024 / 1024), 2) `Size in MB`
  540. FROM information_schema.TABLES
  541. ORDER BY (data_length + index_length) DESC;
  542. ~~~
  543. ## Logs
  544. ### Log de toutes les requêtes
  545. On peut activer à chaud le logging de l'ensemble des requêtes :
  546. ~~~{.sql}
  547. mysql> SET GLOBAL GENERAL_LOG=ON;
  548. ~~~
  549. Toutes les requêtes seront immédiatemment écrites dans le fichier `DATADIR/HOSTNAME.log`.
  550. Pour désactiver à chaud :
  551. ~~~{.sql}
  552. mysql> SET GLOBAL GENERAL_LOG=OFF;
  553. ~~~
  554. > *Note* : évidemment, sur un serveur de production il faut éviter d'activer cela plus de quelques secondes car cela impacte fortement la performance et cela va rapidement remplir l'espace disque.
  555. ### Log des requêtes lentes (slow queries)
  556. Pour débugger les applications lentes, c'est une fonctionnalité intéressante de trouver quelle requête est longue.
  557. Pour cela on peut spécifier par exemple que l'on veut avoir toutes les requêtes qui durent plus de 5 secondes :
  558. ~~~{.ini}
  559. [mysqld]
  560. slow_query_log = 1
  561. long_query_time = 5
  562. slow_query_log_file = /var/log/mysql/slow.log
  563. ~~~
  564. Ou à chaud :
  565. ~~~{.sql}
  566. mysql> SET GLOBAL slow_query_log=ON;
  567. mysql> SET GLOBAL long_query_time=5;
  568. mysql> SET GLOBAL slow_query_log_file= "/var/log/mysql/slow.log";
  569. ~~~
  570. Il est également possible de remonter les requêtes n'utilisant pas d'index (qu'importe le temps qu'elle prennent pour s'exécuter), avec le paramètre booléen `log_queries_not_using_indexes` mais nous déconseillons de le faire car cela ajoute de nombreuses requêtes inintéressantes en général.
  571. #### long_query_time=0
  572. Une astuce pour analyser l'ensemble des requêtes et de positionner `long_query_time=0` mais il faut évidemment faire très attention car la taille du fichier de logs peut grossier très vite. C'est intéressant à faire pendant quelques secondes, ou exceptionnellement pendant quelques heures pour une analyse avec `pt-query-digest` par exemple.
  573. #### mysqldumpslow
  574. Pour avoir une meilleure lecture des slow queries, on peut utiliser la commande [mysqldumpslow](https://dev.mysql.com/doc/refman/5.7/en/mysqldumpslow.html) :
  575. ~~~
  576. # mysqldumpslow /var/log/mysql/mysql-slow.log
  577. ~~~
  578. #### pt-query-digest
  579. On peut aussi utilise la commande `pt-query-digest` disponible dans le paquet `percona-toolkit` afin d'avoir une analyse plus poussée des slow queries :
  580. ~~~
  581. # pt-query-digest /var/log/mysql/mysql-slow.log
  582. ~~~
  583. **ATTENTION** : Si le fichier de slow query est trop lourd, il n'est pas recommandé de l'analyser sur un serveur de production, car l'analyse peut nécessiter un cœur CPU à 100%, pendant quelques minutes.
  584. Cet outil analyse le fichier `mysql-slow.log` et fait un rapport général des requêtes qui prennent le plus de temps, par temps de réponse, pourcentage d’exécution, nombres d'appels et le type de requête.
  585. Exemple :
  586. ~~~
  587. # Profile
  588. # Rank Query ID Response time Calls R/Call V/M Item
  589. # ==== ================== ============== ===== ======= ===== =============
  590. # 1 0x67A347A2812914DF 830.5323 62.8% 41 20.2569 87.06 SELECT foo_bar
  591. # 2 0xC5C7772FD65D8C64 141.2796 10.7% 35 4.0366 0.07 SELECT lignes commandes lignes
  592. # 3 0x6DEF8BB001FA8845 139.9141 10.6% 7 19.9877 0.04 SELECT commandes commandes_remboursements vendeurs_factures_remises paiements livraisons commandes_statut commandes_groupes acheteurs codes_promos adresses pays adresses pays vendeurs adresses pays
  593. # 4 0xC8A44AAD56105646 41.5405 3.1% 17 2.4436 0.02 SELECT produits_tendances vendeurs declinaisons texteproduits produits_tendances
  594. # 5 0xFD38100E607E1331 26.7823 2.0% 2 13.3912 5.07 SELECT OUTFILE commandes_etiquettes
  595. # 6 0xFD7F7A9702EE1C3C 21.4709 1.6% 6 3.5785 0.00 UPDATE commandes
  596. # 7 0xE63D0402530F63BE 9.5435 0.7% 4 2.3859 0.00 UPDATE commandes
  597. # 8 0x4EEE742BBDA4EE47 8.9621 0.7% 2 4.4810 0.02 SELECT OUTFILE vendeurtracking
  598. # 9 0xB28EA31EC4438F2F 8.6173 0.7% 2 4.3087 0.02 SELECT OUTFILE lignes
  599. # 10 0xFFAD96608E3F459B 6.7241 0.5% 2 3.3620 0.38 SELECT produits_tendances vendeurs declinaisons texteproduits produits_tendances
  600. ~~~
  601. ### Log des dead lock
  602. > *Note* : Seulement possible depuis MySQL 5.6 ou MariaDB 10.
  603. ~~~{.ini}
  604. [mysqld]
  605. innodb_print_all_deadlocks = on
  606. ~~~
  607. À chaud :
  608. ~~~{.sql}
  609. mysql> SET GLOBAL innodb_print_all_deadlocks=on;
  610. ~~~
  611. ## Sauvegarde
  612. Pour sauvegarder une base de données dans un seul fichier (sans et avec compression) :
  613. ~~~
  614. $ mysqldump --hex-blob foo > foo.sql
  615. $ mysqldump --hex-blob foo | gzip > foo.sql.gz
  616. ~~~
  617. > *Note* : l'option *--hex-blob* est importante pour ne pas risquer de perdre certains caractères dans les colonnes de type BINARY/BLOB/BIT
  618. Il est aussi possible de sauvegarder une seule table avec mysqldump.
  619. Exemple avec la table *bar* de la base *foo* : `$ mysqldump --hex-blob foo bar`
  620. Pour sauvegarder une base de données au format *tab-separated data files*, avec - pour chaque table - un fichier .sql contenant la structure de la table (CREATE TABLE) et un fichier .txt contenant les données brutes (ré-injectable avec `LOAD DATA INFILE`) :
  621. ~~~
  622. # mkdir /tmp/foo && chown mysql:mysql /tmp/foo
  623. $ mysqldump -T foo > /tmp/foo
  624. ~~~
  625. > *Note* : le répertoire de destination doit exister et *mysqld* doit avoir les droits d'écrire dedans.
  626. On peut utiliser les options `--fields-xxx` pour obtenir des fichiers au format CSV :
  627. ~~~
  628. $ mysqldump --hex-blob --fields-enclosed-by='\"' --fields-terminated-by=',' -T /tmp/foo foo
  629. ~~~
  630. Pour sauvegarder toutes les bases (exemples en mode classique et en mode `-T`) :
  631. ~~~
  632. $ mysqldump --opt --all-databases --events --hex-blob > all.sql
  633. $ for db in $(mysql -P3308 -e "SHOW DATABASES" | egrep -v "^(Database|information_schema|performance_schema)"); do \
  634. mkdir /backupmysql/$db && chown mysql:mysql /backupmysql/$db && \
  635. mysqldump --events --hex-blob -T /backupmysql/$db $db; done
  636. ~~~
  637. Pour sauvegarder uniquement certaines tables :
  638. ~~~
  639. $ mysqldump --hex-blob foo TABLE0 [TABLE1…] > foo_tables.sql
  640. ~~~
  641. Pour presque faire un `--exclude` (qui manque cruellement à *mysqldump*):
  642. ~~~
  643. $ mysql -B -N -e 'show databases' | \
  644. perl -ne 'print unless /\b(?:phpmyadmin|mysql|information_schema)\b/' | \
  645. xargs echo mysqldump --hex-blob -B
  646. ~~~
  647. Et pour sauvegarder des tables correspondant à un motif (préfixe le plus souvent) :
  648. ~~~
  649. $ mysqldump --hex-blob foo $(mysql foo -B --column-names=False -e "show tables like 'exemple_%'") > foo_motif.sql
  650. ~~~
  651. Pour exclure les VIEWS d'un mysqldump :
  652. ~~~
  653. EXCLUDE_VIEWS=$(echo "SELECT TABLE_SCHEMA, TABLE_NAME from INFORMATION_SCHEMA.VIEWS" | mysql information_schema | sed '/^TABLE_SCHEMA/d' | gawk {'print $1"." $2'} |tr '\n' ',')
  654. mysqldump --opt --all-databases --force --ignore-table=$EXCLUDE_VIEWS --events --hex-blob > foo.sql
  655. ~~~
  656. Pour dumper avec une condition particulière :
  657. ~~~
  658. $ mysqldump -t foo bar --hex-blob --where="id='66666666'"
  659. ~~~
  660. Ce qui permet de réinjecter des données résultantes d'un `SELECT * FROM foo.bar WHERE id='66666666'`.
  661. Il est évidement possible de faire toutes ces opérations sur une instance en
  662. précisant son port avec l'option `--port` (valable pour *mysqldump* et *mysql*).
  663. 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/)) :
  664. ~~~{.bash}
  665. mygrants()
  666. {
  667. mysql -B -N -e "SELECT DISTINCT CONCAT(
  668. 'SHOW GRANTS FOR *, user, _'@'_, host, *;'
  669. ) AS query FROM mysql.user" | \
  670. mysql | \
  671. sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
  672. }
  673. ~~~
  674. Pour avoir un dump avec un seul insert par ligne, pratique pour restaurer partiellement les bases `mysql.user` et `mysql.db` par exemple :
  675. ~~~
  676. $ mysqldump --skip-extended-insert --events --hex-blob mysql > mysql.sql
  677. ~~~
  678. Pour sauvegarder une grosse base de donnée en **innodb** (et uniquement avec ce moteur!), on peut ajouter l'argument [`--single-transaction`](https://dev.mysql.com/doc/refman/5.5/en/mysqldump.html#option_mysqldump_single-transaction) qui permet d'effectuer le dump dans une transaction et ainsi ne pas verrouiller les tables.
  679. ### Restauration
  680. Pour restaurer une base de données (sans et avec compression) :
  681. ~~~
  682. $ mysqladmin create foo
  683. $ mysql -o foo < foo.sql
  684. $ gunzip < foo.sql.gz | mysql foo
  685. ~~~
  686. Pour restaurer uniquement la base _foo_ :
  687. ~~~
  688. $ mysql -o foo < all.sql
  689. ~~~
  690. Mais si venant d'un dump complet voir aussi : [Restaurer une base depuis un dump complet](HowtoMySQL/Troubleshooting#restauration-dune-base-depuis-un-dump-complet)
  691. Pour restaurer une table de type "tab-separated data files" (`mysqldump -T`) dans une base _foo_ (exemples par défaut et avec des options `--fields-xxx`) :
  692. ~~~
  693. $ mysqlimport --default-character-set=utf8 foo /tmp/foo/bar.txt
  694. $ mysqlimport --default-character-set=utf8 --fields-enclosed-by='\"' --fields-terminated-by=',' foo /tmp/foo/bar.txt
  695. ~~~
  696. Pour restaurer une base entière avec un dump de type "tab-separated data files" (exemples par défaut et avec des options `--fields-xxx`) :
  697. ~~~{.bash}
  698. db=test1
  699. for file in *.sql; do
  700. mysql $db <$file
  701. done
  702. grep CHARSET= *txt
  703. for file in *.txt; do
  704. tablename=$(basename $file .txt)
  705. echo "LOAD DATA INFILE '$PWD/$file' INTO TABLE \`$tablename\`" CHARACTER SET utf8 | mysql $db
  706. #echo "LOAD DATA INFILE '$PWD/$file' INTO TABLE \`$tablename\`" CHARACTER SET utf8 FIELDS TERMINATED BY ',' ENCLOSED BY '"' | mysql $db
  707. done
  708. ~~~
  709. > *Note 1* : Attention, l'utilisateur MySQL doit avoir le droit de lecture sur les fichiers .txt
  710. Se positionner dans un répertoire où mysql a les droits (mysqltmp - /home/mysqltmp par ex).
  711. > *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)
  712. > *Note 3* : Si erreur 150 : «Can't create table» voir du côté des foreign keys :
  713. >
  714. >~~~{.bash}
  715. >$ mysql -e 'SHOW ENGINE INNODB STATUS\G;' | grep LATEST\ FOREIGN -A3
  716. >~~~
  717. >
  718. >et ignorer les erreurs pour pouvoir recréer les tables :
  719. >
  720. >~~~{.bash}
  721. >$ mysql -e "set GLOBAL foreign_key_checks=OFF;"
  722. >~~~
  723. Si cela concerne plusieurs bases réparties dans différents sous-répertoires :
  724. ~~~{.bash}
  725. cd /home/mysqldump
  726. for dir in *
  727. do
  728. echo "=======base $dir========="
  729. db=$dir
  730. mysql -e "create database ${dir};"
  731. ls $dir/*.sql || continue
  732. for file in $dir/*.sql
  733. do
  734. mysql $db <$file
  735. done
  736. grep CHARSET= $dir/*txt
  737. ls $dir/*.txt || continue
  738. for file in $dir/*.txt
  739. do
  740. tablename=$(basename $file .txt)
  741. echo "LOAD DATA INFILE '$PWD/$file' INTO TABLE $tablename" CHARACTER SET utf8 | mysql $db
  742. done
  743. done
  744. ~~~
  745. On peut également restaurer un dump _foo.sql_ (ou tout script au format SQL) de façon interactive via la commande `source` :
  746. ~~~{.sql}
  747. mysql> source foo.sql
  748. ~~~
  749. > *Note 1* : il est nécessaire que MySQL ait les droits de lecture sur le fichier _foo.sql_
  750. > *Note 2* : les sorties des requêtes sont renvoyées sur la sortie standard (au contraire de la restauration avec `mysql < foo.sql`)
  751. Pour [extraire une table précise d'un dump complet pour ensuite la restaurer](https://wiki.evolix.org/HowtoMySQL/Troubleshooting#restauration-dune-table-depuis-un-dump-complet)
  752. ## Monitoring
  753. Pour surveiller un service MySQL en production, on pourra faire :
  754. ~~~
  755. # mysqladmin status
  756. # mysqladmin extended-status
  757. # mysqladmin processlist
  758. ~~~
  759. ### mytop
  760. Pour avoir une version conviviale et dynamique des process en cours, on utilisera l'outil *mytop*.
  761. ~~~
  762. # apt install mariadb-client-10.1 libconfig-inifiles-perl libterm-readkey-perl
  763. ~~~
  764. > *Note* : Pour Debian 7 et 8, c'était dans un package indépendant :
  765. >
  766. > ~~~
  767. > # aptitude install mytop
  768. > ~~~
  769. On édite le fichier `/root/.mytop` ainsi :
  770. ~~~{.ini}
  771. user = debian-sys-maint
  772. pass = PASSWORD
  773. db = mysql
  774. ~~~
  775. 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).
  776. L'outil *mytop* se sert principalement de la requête `SHOW PROCESSLIST` que l'on pourra bien sûr lancer manuellement. Tout comme `KILL` :
  777. ~~~{.sql}
  778. mysql> SHOW PROCESSLIST;
  779. mysql> KILL <id_requête>;
  780. ~~~
  781. Pour lister les requêtes qui durent plus de 30 secondes pour pouvoir les tuer facilement :
  782. ~~~
  783. # mysql -e 'select group_concat(concat("kill ",ID) separator ";") from information_schema.processlist where TIME>=30;'
  784. ~~~
  785. Puis exécuter le résultat avec la commande *mysql*, exemple :
  786. ~~~
  787. # mysql -e 'kill 1854;kill 1853;kill 1852;kill 1851;kill 1850;kill 1848'
  788. ~~~
  789. Pour surveiller le moteur InnoDB, on utilisera la commande suivante :
  790. ~~~{.sql}
  791. mysql> SHOW ENGINE INNODB STATUS;
  792. ~~~
  793. ### Installation de mytop sur Debian9 avec MySQL 5.7 (Oracle)
  794. Sur debian9 mytop fait partie du paquet mariadb-client, et n'est plus disponible en stand alone, cela pose un problème si on installe MySQL depuis les dépôts d'oracle.
  795. Il faut prendre le paquet mytop de jessie et l'installer sur stretch :
  796. ~~~
  797. # wget http://ftp.de.debian.org/debian/pool/main/m/mytop/mytop_1.9.1-2_all.deb
  798. # dpkg -i mytop_1.9.1-2_all.deb
  799. ~~~
  800. Il se peut qu'il y est des dépendances manquante dans ce cas il faut les installer :
  801. ~~~
  802. # apt install libdbi-perl libdbd-mysql-perl libconfig-inifiles-perl
  803. # apt --fix-broken install
  804. ~~~
  805. ### Munin
  806. Pour activer les plugins MySQL pour Munin :
  807. ~~~
  808. # cd /etc/munin/plugins
  809. # ln -s /usr/share/munin/plugins/mysql_bytes
  810. # ln -s /usr/share/munin/plugins/mysql_queries
  811. # ln -s /usr/share/munin/plugins/mysql_slowqueries
  812. # ln -s /usr/share/munin/plugins/mysql_threads
  813. ~~~
  814. 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.
  815. Pour tester le bon fonctionnement des plugins MySQL pour Munin :
  816. ~~~
  817. # munin-run mysql_bytes
  818. ~~~
  819. ### log2mail
  820. Afin d'être alerté en cas de souci, il est conseillé d'ajouter la configuration suivante au logiciel `log2mail` :
  821. ~~~
  822. file = /var/log/syslog
  823. pattern = "is marked as crashed and should be repaired"
  824. mailto = monitoring@example.com
  825. template = /etc/log2mail/template.mysql
  826. file = /var/log/syslog
  827. pattern = "init function returned error"
  828. mailto = monitoring@example.com
  829. template = /etc/log2mail/template.mysql
  830. file = /var/log/syslog
  831. pattern = "try to repair it"
  832. mailto = monitoring@example.com
  833. template = /etc/log2mail/template.mysql
  834. file = /var/log/syslog
  835. pattern = "InnoDB: Fatal error"
  836. mailto = monitoring@example.com
  837. template = /etc/log2mail/template.mysql
  838. file = /var/log/syslog
  839. pattern = "as a STORAGE ENGINE failed"
  840. mailto = monitoring@example.com
  841. template = /etc/log2mail/template.mysql
  842. ~~~
  843. Le fichier `/etc/log2mail/template.mysql` contenant :
  844. ~~~
  845. From: %f
  846. To: %t
  847. Subject: MySQL problem
  848. Hello!
  849. We have matched your pattern "%m" in "%F" %n times:
  850. %l
  851. Yours,
  852. log2mail.
  853. ~~~
  854. > *Note* : il faut ajouter l'utilisateur `log2mail` dans le groupe `adm`.
  855. ## binlogs
  856. Par défaut, MySQL stocke chaque requête en écriture dans des fichiers appelés *binlogs*.
  857. ### Configuration
  858. Par défaut les binlogs sont conservés sur 10 jours, avec des fichiers n'excédant pas 100 Mo :
  859. ~~~{.ini}
  860. [mysqld]
  861. log_bin = /var/log/mysql/mysql-bin.log
  862. expire_logs_days = 10
  863. max_binlog_size = 100M
  864. #binlog_do_db = include_database_name
  865. #binlog_ignore_db = include_database_name
  866. binlog_format = mixed
  867. ~~~
  868. > *Note :* depuis Debian 9, il faut explicitement préciser la directive `log_bin` pour activer les binlogs.
  869. ### Format
  870. <http://dev.mysql.com/doc/refman/5.5/en/binary-log-setting.html>
  871. On peut choisir 3 types de format pour les binlogs :
  872. * **statement** : les requêtes INSERT / UPDATE sont conservées
  873. * **row** : les modifications de chaque ligne sont conservées (via une sorte de code « binaire » propre à MySQL)
  874. * **mixed** : en mode statement… sauf dans certains cas où cela passe en mode row
  875. Avantages et inconvénients :
  876. 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.
  877. 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.
  878. 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.
  879. Il a l'avantage d'être plus fiable pour de la réplication.
  880. 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.
  881. ### Informations
  882. On peut savoir le dernier binlog écrit :
  883. ~~~
  884. mysql> show master status;
  885. +------------------+----------+--------------+------------------+
  886. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  887. +------------------+----------+--------------+------------------+
  888. | mysql-bin.020505 | 17736280 | | |
  889. +------------------+----------+--------------+------------------+
  890. 1 row in set (0.00 sec)
  891. ~~~
  892. On peut lister l'ensemble des binlogs vus par MySQL :
  893. ~~~
  894. mysql> show binary logs;
  895. +------------------+-----------+
  896. | Log_name | File_size |
  897. +------------------+-----------+
  898. | mysql-bin.020437 | 18697341 |
  899. | mysql-bin.020438 | 104858013 |
  900. | mysql-bin.020439 | 104858274 |
  901. | mysql-bin.020440 | 104863158 |
  902. […]
  903. ~~~
  904. Et les visualiser d'un point de vue filesystem :
  905. ~~~
  906. # ls -l /var/log/mysql/
  907. -rw-rw---- 1 mysql adm 18697341 Nov 29 00:01 mysql-bin.020437
  908. -rw-rw---- 1 mysql adm 104858013 Nov 29 09:41 mysql-bin.020438
  909. -rw-rw---- 1 mysql adm 104858274 Nov 29 13:10 mysql-bin.020439
  910. -rw-rw---- 1 mysql adm 104863158 Nov 29 17:28 mysql-bin.020440
  911. […]
  912. -rw-rw---- 1 mysql adm 17863542 Dec 9 01:24 mysql-bin.020505
  913. -rw-rw---- 1 mysql adm 2208 Dec 9 00:01 mysql-bin.index
  914. ~~~
  915. ### Suppression
  916. Il faut vérifier sur le slave quel est le dernier binlog qu'il a récupéré/traité. Pour cela on fait `SHOW SLAVE STATUS\G`, puis on note la ligne `Relay_Master_Log_File:`. Elle indique le dernier binlog récupéré/traité. On peut donc supprimer sur le master, tout ceux d'avant. Par précaution, on peut en garder 10.
  917. Exemple : `Relay_Master_Log_File: mysql-bin.009628` → sur le master `BINARY LOGS TO 'mysql-bin.009618';`
  918. Pour supprimer les binlogs antérieurs à `mysql-bin.00NNNN` :
  919. ~~~{.sql}
  920. mysql> PURGE BINARY LOGS TO 'mysql-bin.00NNNN';
  921. ~~~
  922. ou par rapport à une date :
  923. ~~~{.sql}
  924. mysql> PURGE BINARY LOGS BEFORE "2011-12-07 00:00:00";
  925. ~~~
  926. Si cela vient à se reproduire régulièrement, on peut baisser le nombre de jour durant lesquels les binlogs sont gardés avec la directive *expire_logs_days*.
  927. On peut automatiser la tâche avec l'outil [mysqlbinlogpurge](https://dev.mysql.com/doc/mysql-utilities/1.6/en/mysqlbinlogpurge.html).
  928. Exemple :
  929. ```
  930. mysqlbinlogpurge --master=login:password@192.0.2.1:3306 --slaves=login:password@192.0.2.2:3306
  931. ```
  932. **Note** : Il est nécessaire que le slave s'annonce avec --report-host et --report-port.
  933. ### Désactivation
  934. Pour désactiver les binlogs, on ajoutera l'option suivante dans la configuration :
  935. ~~~{.ini}
  936. [mysqld]
  937. disable-log-bin
  938. ~~~
  939. ### Lecture
  940. On pourra lire en ligne de commande le contenu d'un binlog via la commande :
  941. ~~~
  942. # mysqlbinlog /var/log/mysql/mysql-bin.001789 | less
  943. ~~~
  944. > * 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]`). On peut aussi lancer la commande avec l'option `--no-defaults`.
  945. ### Replay
  946. /!\\ **ATTENTION, CES MANIPULATIONS PEUVENT ÊTRE DANGEREUSES VOS DONNÉES, BIEN SAVOIR CE QUE L'ON FAIT ! **
  947. On pourra ainsi injecter le contenu d'un binlog dans une base… tout simplement avec une commande du type :
  948. ~~~
  949. # mysqlbinlog /var/log/mysql/mysql-bin.001789 | mysql -P3307
  950. ~~~
  951. À 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 :
  952. ~~~
  953. # mysqlbinlog /var/log/mysql/mysql-bin.001789 > mysql-bin.001789.txt
  954. # sed -i 's/INSERT INTO/INSERT IGNORE INTO/gi' mysql-bin.001789.txt
  955. # cat mysql-bin.001789.txt | mysql -P3307
  956. ~~~
  957. On peut aussi injecter les binlogs, sur une intervale de date et heure précise, en précisant le début et la fin comme ceci :
  958. ~~~
  959. # mysqlbinlog --database foo --start-datetime='2018-12-27 16:44:57' --stop-datetime='2018-12-27 16:58:00' binlog.*|mysql -u user -p password
  960. ~~~
  961. ### SET sql_log_bin = 0
  962. On peut effectuer des requêtes SQL qui ne seront pas écrites dans le binlog. Pour cela on positionne la variable _sql_log_bin_ à 0 et les requêtes interactives suivantes ne seront pas prises en compte dans le binlog (bien sûr, si l'on quitte le CLI MySQL, cela ne sera plus valable) :
  963. ~~~{.sql}
  964. mysql> SET sql_log_bin = 0;
  965. ~~~
  966. > *Note* : cela nécessite le droit MySQL _SUPER_
  967. ## Multiples instances MySQL
  968. Il est possible de faire fonctionner plusieurs instances de MySQL sur un serveur ; chacune avec ses propres données et sa propre configuration.
  969. ### Installation
  970. Avant toute opération, **il est nécessaire de commenter cette ligne** dans le `/etc/mysql/my.cnf` :
  971. ~~~{.ini}
  972. #user = mysql
  973. ~~~
  974. Et de rajouter ces lignes dans `/etc/mysql/conf.d/50-multi.cnf` :
  975. ~~~{.ini}
  976. [mysqld_multi]
  977. user = mysqladmin
  978. ~~~
  979. Créer un utilisateur pour l'instance (il doit avoir un shell valide comme `/bin/sh`) :
  980. ~~~
  981. # useradd mysqld1
  982. ~~~
  983. Créer le dossier qui va accueillir le *datadir* et donner les bons droits :
  984. ~~~
  985. # mkdir -p /srv/mysqld_instances/mysqld1 /var/log/mysql/mysqld1
  986. # chmod 755 /srv /srv/mysqld_instances
  987. # chown -R mysqld1:mysqld1 /srv/mysqld_instances/mysqld1 /var/log/mysql/mysqld1
  988. ~~~
  989. Créer un repertoire temporaire dédié à cette instance :
  990. ~~~
  991. # mkdir /home/mysqld1-tmp
  992. # chown mysqld1:mysqld1 /home/mysqld1-tmp
  993. ~~~
  994. Créer ensuite le *datadir* :
  995. ~~~
  996. # mysql_install_db --user=mysqld1 --datadir=/srv/mysqld_instances/mysqld1
  997. # chmod 700 /srv/mysqld_instances/mysqld1
  998. ~~~
  999. Ajouter ces lignes dans `/etc/mysql/conf.d/zzz_mysqld1.cnf` :
  1000. ~~~{.ini}
  1001. [mysqld1]
  1002. mysqld = /usr/bin/mysqld_safe
  1003. user = mysqld1
  1004. port = 3307
  1005. tmpdir = /home/mysqld1-tmp/
  1006. socket = /var/run/mysqld_instances/mysqld1/mysqld.sock
  1007. pid-file = /var/run/mysqld_instances/mysqld1/mysqld.pid
  1008. datadir = /srv/mysqld_instances/mysqld1
  1009. log_error = /var/log/mysql/mysqld1/error.log
  1010. slow_query_log_file = /var/log/mysql/mysqld1/mysql-slow.log
  1011. ~~~
  1012. > *Note 1* : même si l'on ne prévoit pas de faire tourner le mysqld principal sur le port 3306,
  1013. on préfère tout de même utiliser le port 3307 pour la première instance afin de ne pas
  1014. confondre une configuration avec et sans instance.
  1015. > *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.
  1016. Pour éviter ça, il suffit de rajouter :
  1017. ~~~{.ini}
  1018. [mysqld1]
  1019. skip-slave-start
  1020. ~~~
  1021. Si /usr est monté en RO, déplacer le log de mysqld_multi :
  1022. ~~~
  1023. # mv /usr/share/mysql/mysqld_multi.log /var/log/mysql/mysqld_multi.log
  1024. # ln -s /var/log/mysql/mysqld_multi.log /usr/share/mysql/mysqld_multi.log
  1025. # chown mysql:adm /var/log/mysql/mysqld_multi.log
  1026. ~~~
  1027. Puis lancer la nouvelle instance :
  1028. ~~~
  1029. # mysqld_multi start 1
  1030. ~~~
  1031. Enfin, n'oubliez pas de définir un mot de passe root/mysqladmin pour la nouvelle instance !
  1032. Pour voir l'état des instances :
  1033. ~~~
  1034. # mysqld_multi report
  1035. ~~~
  1036. 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.
  1037. On préfère passer la commande « shutdown » en interne :
  1038. ~~~
  1039. # mysqladmin -h 127.0.0.1 -P3307 shutdown
  1040. ~~~
  1041. > **Note** : a priori cela revient à envoyer un signal SIGTERM (kill -15) au process mysqld
  1042. ### Nettoyage
  1043. Si le *mysqld* principal n'est pas utilisé, on désactivera le script d'init.d /etc/init.d/mysql (en ajoutant `exit 0`
  1044. au début du script) et on pourra se créer un script `/etc/init.d/mysqld_instances` du type :
  1045. ~~~{.bash}
  1046. #!/bin/sh
  1047. #
  1048. ### BEGIN INIT INFO
  1049. # Provides: mysqld_instances
  1050. # Required-Start: $remote_fs $syslog
  1051. # Required-Stop: $remote_fs $syslog
  1052. # Should-Start: $network $time
  1053. # Should-Stop: $network $time
  1054. # Default-Start: 2 3 4 5
  1055. # Default-Stop: 0 1 6
  1056. # Short-Description: Start and stop the mysql database server daemon
  1057. # Description: Controls the main MySQL database server daemon "mysqld"
  1058. # and its wrapper script "mysqld_safe".
  1059. ### END INIT INFO
  1060. #
  1061. set -e
  1062. set -u
  1063. mkdir -p /run/mysqld_instances && chown root:mysql /run/mysqld_instances && chmod 770 /run/mysqld_instances
  1064. case "$1" in
  1065. start)
  1066. mysqld_multi start
  1067. ;;
  1068. stop)
  1069. for pid in /run/mysqld_instances/*/mysqld.pid; do
  1070. pkill -F "${pid}"
  1071. done
  1072. ;;
  1073. status)
  1074. mysqld_multi report
  1075. ;;
  1076. restart)
  1077. $0 stop
  1078. $0 start
  1079. ;;
  1080. *)
  1081. echo "Usage: $0 {start|stop|status|restart}"
  1082. exit 1
  1083. esac
  1084. exit 0
  1085. ~~~
  1086. ### Administration
  1087. Pour voir le statut de l'instance n°1, logiquement nommée mysqld1 (GNR=1) et tournant sur le port 3307 :
  1088. ~~~
  1089. # mysqld_multi report 1
  1090. Reporting MySQL servers
  1091. MySQL server from group: mysqld1 is running
  1092. ~~~
  1093. Pour l'arrêter/redémarrer, même principe (attention, `mysqld_multi` est peu verbeux) :
  1094. ~~~
  1095. # ps auwx | grep 3307
  1096. # mysqladmin -P 3307 shutdown
  1097. # ps auwx | grep 3307
  1098. # mysqld_multi start 1
  1099. # ps auwx | grep 3307
  1100. ~~~
  1101. ## Optimisation avancée
  1102. Voir [/HowtoMySQL/Optimize]().
  1103. ## Réplication MySQL
  1104. Voir [/HowtoMySQL/Replication]().
  1105. ## Mariabackup / Percona XtraBackup
  1106. Voir [/HowtoMySQL/mariabackup]().
  1107. ## FAQ et erreurs courantes
  1108. Voir [/HowtoMySQL/Troubleshooting]().