Manuel de référence MySQL 5.0

MySQL Reference

Ceci est une traduction du manuel de référence MySQL qui se trouve ici dev.mysql.com. Le manuel de référence MySQL est en anglais et cette traduction n'est pas nécessairement à jour par rapport à la version anglaise.

Cette version fait référence à la version 5.0.6-bêta du serveur MySQL, mais elle est aussi valable pour toute version plus ancienne, là où c'est indiqué.

Commentez

- Titre : Manuel de référence MySQL 5.0

- Auteur : MySQL Reference

- Parution : 14 juin 2017

- Licence :

Sommaire

- 1. Informations générales

- 1-1. À propos du manuel

- 1-1-1. Conventions utilisées dans ce manuel

- 1-2. Présentation du système de base de données MySQL

- 1-2-1. Histoire de MySQL

- 1-2-2. Les fonctionnalités principales de MySQL

- 1-2-3. Jusqu'à quel point MySQL est-il stable ?

- 1-2-4. Quelles tailles peuvent atteindre les tables MySQL

- 1-2-5. Compatibilité an 2000

- 1-3. Plan de développement de MySQL

- 1-3-1. MySQL 4.0 en bref

- 1-3-1-1. Fonctionnalités disponibles en MySQL 4.0

- 1-3-1-2. MySQL Server intégré (embedded)

- 1-3-2. MySQL 4.1 en bref

- 1-3-2-1. Fonctionnalités disponibles en MySQL 4.1

- 1-3-3. MySQL 5.0, les prochains développements

- 1-4. Sources d'informations MySQL

- 1-4-1. Listes de diffusion MySQL

- 1-4-1-1. Les listes de diffusion de MySQL

- 1-4-1-2. Poser des questions ou rapporter un bogue

- 1-4-1-3. Comment rapporter un bogue ou un problème

- 1-4-1-4. Conseils pour répondre sur la liste de diffusion

- 1-4-2. Support de la communauté MySQL sur IRC (Internet Relay Chat)

- 1-4-3. Support de la communauté MySQL sur les forums MySQL

- 1-5. Quels standards respecte MySQL ?

- 1-5-1. Quels standards suit MySQL ?

- 1-5-2. Sélectionner les modes SQL

- 1-5-3. Exécuter MySQL en mode ANSI

- 1-5-4. Extensions MySQL au standard SQL-92

- 1-5-5. Différences entre MySQL et le standard SQL-92

- 1-5-5-1. Sous-requêtes

- 1-5-5-2. SELECT INTO TABLE

- 1-5-5-3. Transactions et opérations atomiques

- 1-5-5-4. Procédures stockées et triggers

- 1-5-5-5. Les clés étrangères

- 1-5-5-6. Les vues

- 1-5-5-7. '--' comme début de commentaire

- 1-5-6. Comment MySQL gère les contraintes

- 1-5-6-1. Contrainte avec PRIMARY KEY / UNIQUE

- 1-5-6-2. Contraintes sur les valeurs invalides

- 1-5-6-3. Constante avec ENUM et SET

- 1-5-7. Erreurs connues et limitations de MySQL

- 1-5-7-1. Erreurs connues en 3.23 et corrigées ultérieurement

- 1-5-7-2. Erreurs de la version 4.0, corrigées plus tard

- 1-5-7-3. Erreurs de la version 4.1 corrigées dans d'autres versions de MySQL

- 1-5-7-4. Bogues connus/limitations de MySQL

- 2. Installer MySQL

- 2-1. Notes générales à propos de l'installation

- 2-1-1. Systèmes d'exploitation supportés par MySQL

- 2-1-2. Choisir votre version de MySQL

- 2-1-2-1. Quelle version de MySQL utiliser ?

- 2-1-2-2. Choisir le format de distribution

- 2-1-2-3. Quand et comment sont publiées les nouvelles versions de MySQL

- 2-1-2-4. Politique de publication : aucun bogue connu dans les versions

- 2-1-2-5. Binaires compilés par MySQL AB

- 2-1-3. Comment obtenir MySQL ?

- 2-1-4. Vérifier l'intégrité des paquets avec MD5 ou GnuPG

- 2-1-4-1. Vérifier la signature MD5

- 2-1-4-2. Vérification de la signature avec GnuPG

- 2-1-4-3. Contrôle d'intégrité avec RPM

- 2-1-5. Dispositions d'installation

- 2-2. Installation standard rapide de MySQL

- 2-2-1. Installer MySQL sous Windows

- 2-2-1-1. Prérequis système sur Windows

- 2-2-2. Choisir un paquet d'installation

- 2-2-3. Installer MySQL avec l'assistant automatique

- 2-2-4. Installation de MySQL avec l'assistant

- 2-2-4-1. Introduction

- 2-2-4-2. Télécharger et lancer l'assistant d'installation MySQL

- 2-2-4-3. Choisir le type d'installation

- 2-2-4-4. Le dialogue d'installation personnalisée

- 2-2-4-5. Le dialogue de confirmation

- 2-2-4-6. Modifications apportées par l'assistant d'installation MySQL

- 2-2-4-7. Mise à jour de MySQL

- 2-2-5. Utiliser l'assistant de configuration

- 2-2-5-1. Introduction

- 2-2-5-2. Lancement de l'assistant de configuration MySQL

- 2-2-5-3. Choisir une option d'entretien

- 2-2-5-4. Choisir un type de configuration

- 2-2-5-5. Le dialogue de type de serveur

- 2-2-5-6. Le dialogue d'utilisation des bases de données

- 2-2-5-7. Le dialogue d'installation des espaces de tables InnoDB

- 2-2-5-8. Le dialogue de connexions simultanées

- 2-2-5-9. Le dialogue d'options de réseau

- 2-2-5-10. Le dialogue de jeux de caractères

- 2-2-5-11. Le dialogue d'options de service

- 2-2-5-12. Le dialogue d'options de sécurité

- 2-2-5-13. Le dialogue de confirmation

- 2-2-5-14. L'emplacement du fichier my.ini

- 2-2-5-15. Éditer le fichier my.ini

- 2-2-6. Installer MySQL à partir d'une archive ZIP sans assistant

- 2-2-7. Extraction de l'archive d'installation

- 2-2-8. Créer un fichier d'options

- 2-2-8-1. Choisir un serveur MySQL sur Windows

- 2-2-8-2. Démarrer le serveur pour la première fois

- 2-2-9. Démarrer MySQL depuis la ligne de commande Windows

- 2-2-9-1. Lancer MySQL comme un service Windows

- 2-2-10. Tester son installation MySQL

- 2-2-10-1. Résolution de problèmes d'installation de MySQL sous Windows

- 2-2-11. Mettre à jour MySQL sous Windows

- 2-2-11-1. MySQL pour Windows face à MySQL pour Unix

- 2-2-12. Installer MySQL sous Linux

- 2-2-13. Installer MySQL sur Mac OS X

- 2-2-14. Installer MySQL sur NetWare

- 2-3. Installer MySQL sur d'autres systèmes type Linux

- 2-4. Installation de MySQL avec une distribution source

- 2-4-1. Installation depuis les sources : présentation

- 2-4-2. Options habituelles de configure

- 2-4-3. Installer à partir de l'arbre source de développement

- 2-4-4. Problèmes de compilation ?

- 2-4-5. Notes relatives aux MIT-pthreads

- 2-4-6. La distribution source Windows

- 2-4-6-1. Compiler MySQL avec VC++

- 2-4-6-2. Compiler MySQL sur Windows à partir des sources de développement

- 2-4-7. Compiler les clients MySQL sous Windows

- 2-5. Procédure de postinstallation

- 2-5-1. Post-installation sous Windows

- 2-5-2. Procédures de postinstallation sous Unix

- 2-5-2-1. Problèmes d'exécution de mysql_install_db

- 2-5-2-2. Lancer et arrêter MySQL automatiquement

- 2-5-2-3. Problèmes de démarrage du serveur MySQL

- 2-5-3. Création des premiers droits MySQL

- 2-6. Changer de version de MySQL

- 2-6-1. Passer de version 4.1 en version 5.0

- 2-6-2. Passer de la version 4.0 à la version 4.1

- 2-6-3. Passer de la version 3.23 à la version 4.0

- 2-6-4. Passer de la version 3.22 à la version 3.23

- 2-6-5. Passer de la version 3.21 à la version 3.22

- 2-6-6. Passer de la version 3.20 à la version 3.21

- 2-6-7. Mise à jour des tables de droits

- 2-6-8. Migrer depuis une autre architecture

- 2-7. Réduire de version de MySQL

- 2-7-1. Revenir en version 4.1

- 2-7-2. Revenir en version 4.0

- 2-8. Notes spécifiques aux systèmes d'exploitation

- 2-8-1. Notes relatives à Linux (toutes versions)

- 2-8-1-1. Notes sur Linux

- 2-8-1-2. Notes relatives à Linux pour les distributions binaires

- 2-8-1-3. Notes sur la distribution source de Linux

- 2-8-1-4. Notes de postinstallation pour Linux

- 2-8-1-5. Notes relatives à Linux x86

- 2-8-1-6. Notes relatives à Linux SPARC

- 2-8-1-7. Notes relatives à Linux Alpha

- 2-8-1-8. Note relative à Linux PowerPC

- 2-8-1-9. Notes relatives à Linux MIPS

- 2-8-1-10. Notes relatives à Linux IA64

- 2-8-2. Notes relatives à Mac OS X

- 2-8-2-1. Mac OS X 10.x

- 2-8-2-2. Mac OS X Server 1.2 (Rhapsody)

- 2-8-3. Notes pour Solaris

- 2-8-3-1. Notes relatives à Solaris 2.7/2.8

- 2-8-3-2. Remarques pour Solaris x86

- 2-8-4. Notes relatives à BSD

- 2-8-4-1. Notes relatives à FreeBSD

- 2-8-4-2. Notes concernant NetBSD

- 2-8-4-3. Notes relatives à OpenBSD 2.5

- 2-8-4-4. Notes relatives à OpenBSD 2.8

- 2-8-4-5. Notes relatives aux versions 2.x de BSD/OS

- 2-8-4-6. Notes relatives aux versions 3.x de BSD/OS

- 2-8-4-7. Notes relatives aux versions 4.x de BSD/OS

- 2-8-5. Notes sur les autres Unix

- 2-8-5-1. Notes relatives à la version 10.20 de HP-UX

- 2-8-5-2. HP-UX Version 11.x Notes

- 2-8-5-3. Notes relatives à IBM-AIX

- 2-8-5-4. Notes relatives à SunOS 4

- 2-8-5-5. Notes pour Alpha-DEC-UNIX (Tru64)

- 2-8-5-6. Notes pour Alpha-DEC-OSF/1

- 2-8-5-7. Notes relatives à SGI Irix

- 2-8-5-8. Notes sur SCO

- 2-8-5-9. Notes sur SCO UnixWare Version 7.1.x

- 2-8-6. Notes relatives à OS/2

- 2-8-7. Notes relatives à BeOS

- 2-9. Commentaires sur l'installation de Perl

- 2-9-1. Installer Perl sur Unix

- 2-9-2. Installer ActiveState Perl sur Windows

- 2-9-3. Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

- 3. Tutoriels d'introduction

- 3-1. Connexion et déconnexion au serveur

- 3-2. Entrer des requêtes

- 3-3. Création et utilisation d'une base de données

- 3-3-1. Créer et sélectionner une base de données

- 3-3-2. Création d'une table

- 3-3-3. Charger des données dans une table

- 3-3-4. Récupérer des informations à partir d'une table

- 3-3-4-1. Sélectionner toutes les données

- 3-3-4-2. Sélectionner des lignes particulières

- 3-3-4-3. Sélectionner des colonnes particulières

- 3-3-4-4. Trier les enregistrements

- 3-3-4-5. Calcul sur les dates

- 3-3-4-6. Travailler avec la valeur NULL

- 3-3-4-7. Recherche de modèles

- 3-3-4-8. Compter les lignes

- 3-3-4-9. Utiliser plus d'une table

- 3-4. Obtenir des informations à propos des bases de données et des tables

- 3-5. Utilisation de mysql en mode batch

- 3-6. Exemples de requêtes usuelles

- 3-6-1. La valeur maximale d'une colonne

- 3-6-2. La ligne contenant le maximum d'une certaine colonne

- 3-6-3. Maximum d'une colonne par groupe

- 3-6-4. La ligne contenant la plus grande valeur d'un certain champ par rapport à un groupe

- 3-6-5. Utiliser les variables utilisateur

- 3-6-6. Utiliser les clefs étrangères

- 3-6-7. Recherche sur deux clefs

- 3-6-8. Calcul du nombre de visites par jour

- 3-6-9. Utiliser AUTO_INCREMENT

- 3-7. Requêtes du projet Twin

- 3-7-1. Trouver tous les jumeaux répondant aux critères

- 3-7-2. Afficher une table avec l'état des paires de jumeaux

- 3-8. Utilisation de MySQL avec Apache

- 4. Utiliser les programmes MySQL

- 4-1. Présentation des logiciels MySQL

- 4-2. Appeler des programmes MySQL

- 4-3. Spécifier des options aux programmes

- 4-3-1. Options de ligne de commande de mysqld

- 4-3-2. Fichier d'options my.cnf

- 4-3-3. Utiliser les variables d'environnement pour spécifier des options

- 4-3-4. Utiliser les options pour configurer des variables de programme

- 5. Administration du serveur

- 5-1. Scripts serveur MySQL et utilitaires

- 5-1-1. Présentation des scripts serveur et des utilitaires

- 5-1-2. mysqld-max, la version étendue du serveur mysqld

- 5-1-3. safe_mysqld, le script père de mysqld

- 5-1-4. Le script de démarrage mysql.server

- 5-1-5. mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

- 5-2. Configuration de MySQL

- 5-2-1. Options de ligne de commande de mysqld

- 5-2-2. Le mode SQL du serveur

- 5-2-3. Variables serveur système

- 5-2-3-1. Variables système dynamiques

- 5-2-4. Variables de statut du serveur

- 5-3. Le processus d'extinction de MySQL

- 5-4. Sécurité générale du serveur

- 5-4-1. Guide de sécurité

- 5-4-2. Protéger MySQL contre les attaques

- 5-4-3. Options de démarrage qui concernent la sécurité

- 5-4-4. Problèmes de sécurité avec LOAD DATA LOCAL

- 5-5. Règles de sécurité et droits d'accès au serveur MySQL

- 5-5-1. Rôle du système de privilèges

- 5-5-2. Comment fonctionne le système de droits

- 5-5-3. Droits fournis par MySQL

- 5-5-4. Se connecter au serveur MySQL

- 5-5-5. Contrôle d'accès, étape 1 : vérification de la connexion

- 5-5-6. Contrôle d'accès, étape 2 : vérification de la requête

- 5-5-7. Quand les modifications de privilèges prennent-elles effet ?

- 5-5-8. Causes des erreurs Access denied

- 5-5-9. Hashage de mots de passe en MySQL 4.1

- 5-5-9-1. Implications des modifications de mot de passe pour les applications

- 5-5-9-2. Gestion des mots de passe en MySQL 4.1.0

- 5-6. Gestion des comptes utilisateur de MySQL

- 5-6-1. Noms d'utilisateurs MySQL et mots de passe

- 5-6-2. Ajouter de nouveaux utilisateurs à MySQL

- 5-6-3. Supprimer un compte utilisateur de MySQL

- 5-6-4. Limiter les ressources utilisateur

- 5-6-5. Configurer les mots de passe

- 5-6-6. Garder vos mots de passe en lieu sûr

- 5-6-7. Utilisation des connexions sécurisées

- 5-6-7-1. Introduction aux connexions sécurisées

- 5-6-7-2. Prérequis aux connexions sécurisées

- 5-6-7-3. Configurer les certificats SSL pour MySQL

- 5-6-7-4. Options de GRANT avec SSL

- 5-6-7-5. Options SSL en ligne de commande

- 5-6-7-6. Connexion à MySQL à distance avec Windows et SSH

- 5-7. Prévention des désastres et restauration

- 5-7-1. Sauvegardes de base de données

- 5-7-2. Exemples de stratégie de sauvegarde et restauration

- 5-7-2-1. Politique de sauvegarde

- 5-7-2-2. Utiliser les sauvegardes pour la restauration

- 5-7-2-3. Résumé des stratégies de sauvegarde

- 5-7-3. Utilisation de myisamchk pour la maintenance des tables et leur recouvrement

- 5-7-3-1. Syntaxe de l'utilitaire myisamchk

- 5-7-3-2. Options générales de myisamchk

- 5-7-3-3. Options de vérifications pour myisamchk

- 5-7-3-4. Options de réparation de myisamchk

- 5-7-3-5. Autres options de myisamchk

- 5-7-3-6. Utilisation de la mémoire par myisamchk

- 5-7-3-7. Utiliser myisamchk pour restaurer une table

- 5-7-3-8. Comment vérifier la cohérence d'une table

- 5-7-3-9. Comment réparer des tables

- 5-7-3-10. Optimisation de table

- 5-7-4. Mettre en place un régime d'entretien de MySQL

- 5-7-5. Obtenir des informations sur une table

- 5-8. Localisation MySQL et utilisation internationale

- 5-8-1. Le jeu de caractères utilisé pour les données et le stockage

- 5-8-1-1. Jeu de caractères allemand

- 5-8-2. Langue des messages d'erreurs

- 5-8-3. Ajouter un nouveau jeu de caractères

- 5-8-4. Le tableau de définition des caractères

- 5-8-5. Support d'assemblage des chaînes

- 5-8-6. Support des caractères multioctets

- 5-8-7. Problèmes avec les jeux de caractères

- 5-8-8. Support des fuseaux horaires avec MySQL

- 5-9. Les fichiers de log de MySQL

- 5-9-1. Le log d'erreurs

- 5-9-2. Le log général de requêtes

- 5-9-3. Le log de modifications

- 5-9-4. Le log binaire

- 5-9-5. Le log des requêtes lentes

- 5-9-6. Entretien des fichiers de log

- 5-10. Faire fonctionner plusieurs serveurs MySQL sur la même machine

- 5-10-1. Utiliser plusieurs serveurs MySQL un serveur Windows

- 5-10-1-1. Lancer plusieurs serveurs depuis la console

- 5-10-1-2. Lancer plusieurs serveurs comme services Windows

- 5-10-2. Utiliser plusieurs serveurs sous Unix

- 5-10-3. Utiliser les clients dans un environnement multiserveur

- 5-11. Cache de requêtes MySQL

- 5-11-1. Comment fonctionne le cache de requêtes

- 5-11-2. Options relatives au cache de requêtes dans un SELECT

- 5-11-3. Configuration du cache de requêtes

- 5-11-4. Statut du cache de requêtes et maintenance

- 6. Réplication de MySQL

- 6-1. Introduction à la réplication

- 6-2. Présentation de l'implémentation de la réplication

- 6-3. Détails d'implémentation de la réplication

- 6-3-1. État de réplication du maître

- 6-3-2. États du thread esclave d'E/S

- 6-3-3. États des esclaves de réplication

- 6-3-4. Fichiers de relais et de statut de la réplication

- 6-4. Comment mettre en place la réplication

- 6-5. Compatibilité de la réplication entre les versions de MySQL

- 6-6. Changer de version de réplication

- 6-6-1. Passer à la réplication version 4.0

- 6-6-2. Passer à la réplication version 5.0

- 6-7. Fonctionnalités de la réplication et problèmes connus

- 6-8. Options de démarrage de la réplication

- 6-9. FAQ de la réplication

- 6-10. Correction de problèmes courants

- 6-11. Rapporter des bogues de réplication

- 7. Optimisation de MySQL

- 7-1. Présentation de l'optimisation

- 7-1-1. Limitations et inconvénients des choix conceptuels de MySQL

- 7-1-2. Portabilité

- 7-1-3. Pourquoi avons-nous utilisé MySQL ?

- 7-1-4. La suite de tests MySQL

- 7-1-5. Utiliser vos propres tests de performance

- 7-2. Optimisation des commandes SELECT et autres requêtes

- 7-2-1. Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

- 7-2-2. Mesurer les performances d'une requête

- 7-2-3. Vitesse des requêtes SELECT

- 7-2-4. Comment MySQL optimise les clauses WHERE

- 7-2-5. Optimisation d'intervalle

- 7-2-5-1. Méthode d'accès par intervalle pour les index multicolonnes

- 7-2-5-2. Méthode d'accès par intervalle pour les index multicolonnes

- 7-2-6. Optimisation de combinaison d'index

- 7-2-6-1. Algorithme d'accès aux intersections de combinaisons d'index

- 7-2-6-2. Algorithme d'accès aux unions de combinaison d'index

- 7-2-6-3. Algorithme d'accès aux unions triées de combinaison d'index

- 7-2-7. Comment MySQL optimise IS NULL

- 7-2-8. Comment MySQL optimise DISTINCT

- 7-2-9. Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN

- 7-2-10. Comment MySQL optimise ORDER BY

- 7-2-11. Comment MySQL optimise les clauses GROUP BY

- 7-2-11-1. Scan restreint d'index

- 7-2-11-2. Scan d'index systématique

- 7-2-12. Comment MySQL optimise LIMIT

- 7-2-13. Comment éviter les analyses de tables

- 7-2-14. Vitesse des requêtes INSERT

- 7-2-15. Vitesses des commandes UPDATE

- 7-2-16. Rapidité des requêtes DELETE

- 7-2-17. Autres conseils d'optimisation

- 7-3. Verrouillage de tables

- 7-3-1. Méthodes de verrouillage

- 7-3-2. Problème de verrouillage de tables

- 7-4. Optimiser la structure de la base de données

- 7-4-1. Conception

- 7-4-2. Rendre vos tables aussi compactes que possible

- 7-4-3. Index de colonnes

- 7-4-4. Index sur plusieurs colonnes

- 7-4-5. Comment MySQL utilise les index

- 7-4-6. Le cache de clés des tables MyISAM

- 7-4-6-1. Accès au cache de clés partagé

- 7-4-6-2. Caches multiples de clés

- 7-4-6-3. Stratégie d'insertion au milieu

- 7-4-6-4. Préchargement des index

- 7-4-6-5. Taille des blocs du cache de clés

- 7-4-6-6. Restructurer le cache de clés

- 7-4-7. Comment MySQL compte les tables ouvertes

- 7-4-8. Quand MySQL ouvre et ferme les tables

- 7-4-9. Inconvénients de la création d'un grand nombre de tables dans la même base de données

- 7-5. Optimiser le serveur MySQL

- 7-5-1. Réglage du système, au moment de la compilation, et paramètres du démarrage

- 7-5-2. Réglage des paramètres du serveur

- 7-5-3. Contrôle des performances de l'optimiseur de requêtes

- 7-5-4. Influences de la compilation et des liaisons sur la vitesse de MySQL

- 7-5-5. Comment MySQL gère la mémoire

- 7-5-6. Comment MySQL utilise le DNS

- 7-6. Problèmes avec les disques

- 7-6-1. Utiliser des liens symboliques

- 7-6-1-1. Utiliser les liens symboliques pour les bases

- 7-6-1-2. Utiliser les liens symboliques avec les tables sous Unix

- 7-6-1-3. Utiliser des liens symboliques pour les bases de données sous Windows

- 8. MySQL Scripts clients et utilitaires

- 8-1. Présentation des scripts serveur et utilitaires

- 8-2. myisampack, le générateur de tables MySQL compressées en lecture seule

- 8-3. mysql, l'outil en ligne de commande

- 8-3-1. Commandes mysql

- 8-3-2. Comment exécuter des commandes SQL depuis un fichier texte

- 8-3-3. Conseils avec mysql

- 8-3-3-1. Affichage des résultats verticalement

- 8-3-3-2. Utilisation de l'option --safe-updates

- 8-3-3-3. Désactiver la reconnexion automatique de mysql

- 8-4. mysqladmin, administration d'un serveur MySQL

- 8-5. mysqlbinlog, Exécuter des requêtes dans le log binaire

- 8-6. mysqlcc, MySQL Control Center

- 8-7. Utiliser mysqlcheck pour l'entretien et la réparation

- 8-8. mysqldump, sauvegarde des structures de tables et les données

- 8-9. mysqlhotcopy, copier les bases et tables MySQL

- 8-10. mysqlimport, importer des données depuis des fichiers texte

- 8-11. Afficher les bases, tables et colonnes

- 8-12. perror, expliquer les codes d'erreurs

- 8-13. L'utilitaire de remplacement de chaînes replace

- 9. Structure du langage

- 9-1. Littéraux : comment écrire les chaînes et les nombres

- 9-1-1. Chaînes

- 9-1-2. Nombres

- 9-1-3. Valeurs hexadécimales

- 9-1-4. Valeurs booléennes

- 9-1-5. Champs de bits

- 9-1-6. Valeurs NULL

- 9-2. Noms de bases, tables, index, colonnes et alias

- 9-2-1. Identifiants

- 9-2-2. Sensibilité à la casse pour les noms

- 9-3. Variables utilisateur

- 9-4. Variables système

- 9-4-1. Variables système structurées

- 9-5. Syntaxe des commentaires

- 9-6. Cas des mots réservés MySQL

- 10. Jeux de caractères et Unicode

- 10-1. Jeux de caractères et collation : généralités

- 10-2. Jeux de caractères et collation dans MySQL

- 10-3. Déterminer le jeu de caractères et la collation par défaut

- 10-3-1. Jeu de caractères et collation serveur

- 10-3-2. Jeu de caractères et collation de base de données

- 10-3-3. Jeu de caractères de tables et collation

- 10-3-4. Jeu de caractères de colonne et collation

- 10-3-5. Exemples d'attribution de jeu de caractères et collation

- 10-3-6. Jeux de caractères et collations de connexion

- 10-3-7. Jeu de caractères et collation des chaînes littérales

- 10-3-8. Clause COLLATE dans différentes parties d'une requête SQL

- 10-3-9. COLLATE clause de précédence

- 10-3-10. Opérateur BINARY

- 10-3-11. Quelques cas spéciaux où la détermination de la collation est difficile

- 10-3-12. Les collations doivent correspondre au bon jeu de caractères

- 10-3-13. Un exemple de l'effet de collation

- 10-4. Opérations affectées par le support de jeux de caractères

- 10-4-1. Chaînes résultats

- 10-4-2. CONVERT()

- 10-4-3. CAST()

- 10-4-4. Commande SHOW

- 10-5. Support de Unicode

- 10-6. UTF8 pour les métadonnées

- 10-7. Compatibilité avec d'autres bases de données

- 10-8. Nouveau format de fichier de configuration de jeux de caractères

- 10-9. Jeux de caractères nationaux

- 10-10. Préparer le passage de version 4.0 en 4.1

- 10-10-1. Jeux de caractères 4.0 et binômes de jeux de caractères/collations 4.1 correspondants

- 10-10-2. Conversion de colonnes version 4.0 en version 4.1

- 10-11. Les jeux de caractères et collation supportés par MySQL

- 10-11-1. Les jeux de caractère Unicode

- 10-11-2. Les jeux de caractères d'Europe de l'Ouest

- 10-11-3. Les jeux de caractères d'Europe centrale

- 10-11-4. Jeu de caractères pour l'Europe du Sud et le Moyen-Orient

- 10-11-5. Les jeux de caractères baltes

- 10-11-6. Les jeux de caractère cyrilliques

- 10-11-7. Les jeux de caractères asiatiques

- 11. Types de colonnes

- 11-1. Introduction aux types de colonnes

- 11-1-1. Présentation des types numériques

- 11-1-2. Présentation des types de données temporels : dates et heures

- 11-1-3. Présentation des types de chaînes

- 11-2. Types numériques

- 11-3. Les types date et heure

- 11-3-1. Les types DATETIME, DATE et TIMESTAMP

- 11-3-1-1. Comportement de TIMESTAMP avant MySQL 4.1

- 11-3-1-2. Propriétés de TIMESTAMP depuis la version 4.1

- 11-3-2. Le type TIME

- 11-3-3. Le type YEAR

- 11-3-4. An 2000 et les types date

- 11-4. Les types chaînes

- 11-4-1. Les types CHAR et VARCHAR

- 11-4-2. Les types BINARY and VARBINARY

- 11-4-3. Les types BLOB et TEXT

- 11-4-4. Le type ENUM

- 11-4-5. Le type SET

- 11-5. Capacités des colonnes

- 11-6. Choisir le bon type de colonne

- 11-7. Utilisation des types de données issues d'autres SGBDR

- 12. Fonctions à utiliser dans les clauses SELECT et WHERE

- 12-1. Opérateurs et fonctions tous types

- 12-1-1. Précédence des opérateurs

- 12-1-2. Parenthèses

- 12-1-3. Opérateurs de comparaison

- 12-1-4. Opérateurs logiques

- 12-2. Les fonctions de contrôle

- 12-3. Fonctions de chaînes de caractères

- 12-3-1. Opérateurs de comparaison pour les chaînes de caractères

- 12-4. Fonctions numériques

- 12-4-1. Opérations arithmétiques

- 12-4-2. Fonctions mathématiques

- 12-5. Fonctions de dates et d'heures

- 12-6. Recherche en texte intégral (Full-text) dans MySQL

- 12-6-1. Booléens de recherches en texte intégral

- 12-6-2. Recherche en texte intégral avec extension de requête

- 12-6-3. Restrictions avec la recherche en texte intégral

- 12-6-4. Paramétrage précis de la recherche en texte intégral de MySQL

- 12-6-5. À faire dans la recherche Full-text

- 12-7. Fonctions de transtypage

- 12-8. Autres fonctions

- 12-8-1. Fonctions sur les bits

- 12-8-2. Fonctions de chiffrements

- 12-8-3. Fonctions d'informations

- 12-8-4. Fonctions diverses

- 12-9. Fonctions et options à utiliser dans les clauses GROUP BY

- 12-9-1. Fonctions avec GROUP BY

- 12-9-2. Options de GROUP BY

- 12-9-3. GROUP BY avec les champs cachés

- 13. Syntaxe des commandes SQL

- 13-1. Manipulation de données : SELECT, INSERT, UPDATE, DELETE

- 13-1-1. Syntaxe de DELETE

- 13-1-2. Syntaxe de DO

- 13-1-3. Syntaxe de HANDLER

- 13-1-4. Syntaxe de INSERT

- 13-1-4-1. Syntaxe de INSERT ... SELECT

- 13-1-4-2. Syntaxe de INSERT DELAYED

- 13-1-5. Syntaxe de LOAD DATA INFILE

- 13-1-6. Syntaxe de REPLACE

- 13-1-7. Syntaxe de SELECT

- 13-1-7-1. Syntaxe de JOIN

- 13-1-7-2. Syntaxe de UNION

- 13-1-8. Sous-sélections (SubSELECT)

- 13-1-8-1. Les sous-requêtes comme opérateur scalaire

- 13-1-8-2. Comparaisons avec les sous-requêtes

- 13-1-8-3. Sous-requêtes avec les clauses ANY, IN et SOME

- 13-1-8-4. Sous-requêtes avec ALL

- 13-1-8-5. Sous-requêtes de ligne

- 13-1-8-6. EXISTS et NOT EXISTS

- 13-1-8-7. Sous-requêtes corrélées

- 13-1-8-8. Sous-requêtes dans la clause FROM

- 13-1-8-9. Erreurs de sous-requêtes

- 13-1-8-10. Optimisation des sous-requêtes

- 13-1-8-11. Se passer des sous-requêtes avec les premières versions de MySQL

- 13-1-9. Syntaxe de TRUNCATE

- 13-1-10. Syntaxe de UPDATE

- 13-2. Définition de données : CREATE, DROP, ALTER

- 13-2-1. Syntaxe de ALTER DATABASE

- 13-2-2. Syntaxe de ALTER TABLE

- 13-2-3. Syntaxe de CREATE DATABASE

- 13-2-4. Syntaxe de CREATE INDEX

- 13-2-5. Syntaxe de CREATE TABLE

- 13-2-5-1. Modification automatique du type de colonnes

- 13-2-6. Syntaxe de DROP DATABASE

- 13-2-7. Syntaxe de DROP INDEX

- 13-2-8. Syntaxe de DROP TABLE

- 13-2-9. Syntaxe de RENAME TABLE

- 13-3. Commandes de base de l'utilisateur de MySQL

- 13-3-1. Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

- 13-3-2. Syntaxe de USE

- 13-4. Commandes relatives aux verrous et aux transactions

- 13-4-1. Syntaxes de START TRANSACTION, COMMIT et ROLLBACK

- 13-4-2. Commandes qui ne peuvent pas être annulées

- 13-4-3. Commandes qui peuvent causer une validation implicite

- 13-4-4. Syntaxe de SAVEPOINT et ROLLBACK TO SAVEPOINT

- 13-4-5. Syntaxe de LOCK TABLES/UNLOCK TABLES

- 13-4-6. Syntaxe de SET TRANSACTION

- 13-5. Référence de langage d'administration de la base de données

- 13-5-1. Commande de gestion des comptes utilisateur

- 13-5-1-1. Syntaxe de CREATE USER

- 13-5-1-2. Effacer des utilisateurs MySQL

- 13-5-1-3. Syntaxe de GRANT et REVOKE

- 13-5-1-4. Syntaxe de RENAME USER

- 13-5-1-5. Syntaxe de SET PASSWORD

- 13-5-2. Commandes d'entretien des tables

- 13-5-2-1. Syntaxe de ANALYZE TABLE

- 13-5-2-2. Syntaxe de BACKUP TABLE

- 13-5-2-3. Syntaxe de CHECK TABLE

- 13-5-2-4. Syntaxe de CHECKSUM TABLE

- 13-5-2-5. Syntaxe de OPTIMIZE TABLE

- 13-5-2-6. Syntaxe de REPAIR TABLE

- 13-5-2-7. Syntaxe de RESTORE TABLE

- 13-5-2-8. Syntaxe de SET

- 13-5-3. Syntaxe de SHOW

- 13-5-3-1. Commande SHOW CHARACTER SET

- 13-5-3-2. Syntaxe de SHOW COLLATION

- 13-5-3-3. Syntaxe de SHOW COLUMNS

- 13-5-3-4. Syntaxe de SHOW CREATE DATABASE

- 13-5-3-5. Syntaxe de SHOW CREATE TABLE

- 13-5-3-6. Syntaxe de SHOW DATABASES

- 13-5-3-7. Syntaxe SHOW ENGINES

- 13-5-3-8. Syntaxe de SHOW ERRORS

- 13-5-3-9. SHOW GRANTS

- 13-5-3-10. Syntaxe de SHOW INDEX

- 13-5-3-11. Syntaxe de SHOW INNODB STATUS

- 13-5-3-12. Syntaxe de SHOW LOGS

- 13-5-3-13. SHOW PRIVILEGES

- 13-5-3-14. Syntaxe de SHOW PROCESSLIST

- 13-5-3-15. Syntaxe de SHOW STATUS

- 13-5-3-16. SHOW TABLE STATUS

- 13-5-3-17. Syntaxe de SHOW TABLES

- 13-5-3-18. Syntaxe de SHOW VARIABLES

- 13-5-3-19. SHOW WARNINGS | ERRORS

- 13-5-4. Autres commandes d'administration

- 13-5-4-1. Syntaxe de CACHE INDEX

- 13-5-4-2. Syntaxe de FLUSH

- 13-5-4-3. Syntaxe de KILL

- 13-5-4-4. Syntaxe de LOAD INDEX INTO CACHE

- 13-5-4-5. Syntaxe de la commande RESET

- 13-6. Commandes de réplication

- 13-6-1. Requêtes SQL pour contrôler les maîtres de réplication

- 13-6-1-1. PURGE MASTER LOGS

- 13-6-1-2. RESET MASTER

- 13-6-1-3. SET SQL_LOG_BIN

- 13-6-1-4. SHOW BINLOG EVENTS

- 13-6-1-5. SHOW MASTER LOGS

- 13-6-1-6. SHOW MASTER STATUS

- 13-6-1-7. SHOW SLAVE HOSTS

- 13-6-2. Commandes SQL de contrôle des esclaves de réplication

- 13-6-2-1. CHANGE MASTER TO

- 13-6-2-2. LOAD DATA FROM MASTER

- 13-6-2-3. Syntaxe de LOAD TABLE tbl_name FROM MASTER

- 13-6-2-4. MASTER_POS_WAIT()

- 13-6-2-5. RESET SLAVE

- 13-6-2-6. SET GLOBAL SQL_SLAVE_SKIP_COUNTER

- 13-6-2-7. SHOW SLAVE STATUS

- 13-6-2-8. START SLAVE

- 13-6-2-9. STOP SLAVE

- 13-7. Syntaxe SQL pour les commandes préparées

- 14. Moteurs de tables MySQL et types de table

- 14-1. Le moteur de tables MyISAM

- 14-1-1. Options de démarrage MyISAM

- 14-1-2. Espace nécessaire pour stocker les index

- 14-1-3. Formats de table MyISAM

- 14-1-3-1. Caractéristiques des tables statiques (taille fixée)

- 14-1-3-2. Caractéristiques des tables à format de ligne dynamique

- 14-1-3-3. Caractéristiques des tables compressées

- 14-1-4. Problèmes avec les tables MyISAM

- 14-1-4-1. Tables MyISAM corrompues

- 14-1-4-2. Des clients utilisent la table, ou bien elle n'a pas été fermée correctement

- 14-2. Tables assemblées MERGE

- 14-2-1. Problèmes avec les tables MERGE

- 14-3. Le moteur de table MEMORY (HEAP)

- 14-4. Tables BDB ou BerkeleyDB

- 14-4-1. Systèmes d'exploitation supportés par BDB

- 14-4-2. Installation de BDB

- 14-4-3. Options de démarrage BDB

- 14-4-4. Caractéristiques des tables BDB

- 14-4-5. Ce que nous devons corriger dans BDB dans un futur proche :

- 14-4-6. Restrictions avec les tables BDB

- 14-4-7. Erreurs pouvant survenir lors de l'utilisation des tables BDB

- 14-5. Le moteur de table EXAMPLE

- 14-6. Le moteur de table FEDERATED

- 14-6-1. Installation du moteur de table FEDERATED

- 14-6-2. Description du moteur de stockage FEDERATED

- 14-6-3. Comment utiliser les tables FEDERATED

- 14-6-4. Limitations du moteur de stockage FEDERATED

- 14-7. Le moteur de table ARCHIVE

- 14-8. Le moteur CSV

- 14-9. Tables ISAM

- 15. Le moteur de tables InnoDB

- 15-A. Présentation des tables InnoDB

- 15-B. Informations de contact InnoDB

- 15-C. InnoDB avec MySQL version 3.23

- 15-D. Configuration InnoDB

- 15-E. Options de démarrage InnoDB

- 15-F. Créer des bases InnoDB

- 15-F-1. Si quelque chose se passe mal à la création de la base de données

- 15-G. Créer des tables InnoDB

- 15-G-1. Comment utiliser les transactions de InnoDB avec différentes API

- 15-G-2. Convertir des tables MyISAM vers InnoDB

- 15-G-3. Comment les colonnes AUTO_INCREMENT fonctionnent avec InnoDB

- 15-G-4. Contraintes de clés étrangères FOREIGN KEY

- 15-G-5. InnoDB et la réplication MySQL

- 15-G-6. Espaces de tables multiples : chaque table InnoDB a son fichier .ibd

- 15-H. Ajouter et retirer des données et des logs InnoDB

- 15-I. Sauver et restaurer une base InnoDB

- 15-I-1. Forcer la restauration

- 15-I-2. Points de contrôle

- 15-J. Transférer une base de données InnoDB vers une autre machine

- 15-K. Modèle de transactions et verrouillage InnoDB

- 15-K-1. InnoDB et AUTOCOMMIT

- 15-K-2. InnoDB et SET ... TRANSACTION ISOLATION LEVEL ...

- 15-K-3. Lecture cohérente non bloquante

- 15-K-4. Verrous de lecture SELECT ... FOR UPDATE et SELECT ... LOCK IN SHARE MODE

- 15-K-5. Verrou de clé suivante : éviter le problème des lignes fantômes

- 15-K-6. Un exemple de lecture cohérente avec InnoDB

- 15-K-7. Les verrous posés par différentes requêtes SQL avec InnoDB

- 15-K-8. Quand est-ce que MySQL valide ou annule implicitement une transaction ?

- 15-K-9. Détection des blocages et annulation

- 15-K-10. Comment gérer les blocages de verrous ?

- 15-L. Conseils pour l'amélioration des performances InnoDB

- 15-L-1. Le moniteur InnoDB

- 15-M. Implémentation du multiversionnage

- 15-N. Structures de tables et d'index

- 15-N-1. Structure physique d'un index

- 15-N-2. Bufferisation des insertions

- 15-N-3. Index hash adaptatifs

- 15-N-4. Structure physique d'une ligne

- 15-O. Gestion de l'espace fichiers et des entrées/sorties disque

- 15-O-1. Accès disques

- 15-O-2. Utiliser les raw devices pour l'espace de tables

- 15-O-3. Gestion de l'espace fichier

- 15-O-4. Défragmentation des tables

- 15-P. Gestion des erreurs InnoDB

- 15-P-1. Codes d'erreurs InnoDB

- 15-P-2. Codes d'erreur système

- 15-Q. Restrictions sur les tables InnoDB

- 15-R. Résolution de problèmes avec InnoDB

- 15-R-1. Solutions pour le dictionnaire de données InnoDB

- 16. Introduction à MySQL Cluster

- 16-1. Présentation de MySQL Cluster

- 16-2. Concepts de base de MySQL Cluster

- 16-3. Configuration simple multiserveur

- 16-3-1. Matériel, logiciels et réseau

- 16-3-2. Installation

- 16-3-3. Configuration

- 16-3-4. Démarrage initial

- 16-3-5. Charger les données d'exemple et exécuter des requêtes

- 16-3-6. Arrêt et redémarrage du cluster

- 16-4. Configuration de MySQL Cluster

- 16-4-1. Compilation du cluster

- 16-4-2. Installation du logiciel

- 16-4-3. Vérification rapide du fonctionnement du cluster

- 16-4-4. Fichier de configuration

- 16-4-4-1. Exemple de configuration d'un cluster MySQL

- 16-4-4-2. La chaîne connectstring du Cluster MySQL

- 16-4-4-3. Définition des ordinateurs dans un cluster MySQL

- 16-4-4-4. Définition du serveur de gestion du cluster

- 16-4-4-5. Définitions des nœuds de stockage dans un cluster MySQL

- 16-4-4-6. Définition des serveurs MySQL dans un Cluster MySQL

- 16-4-4-7. Définition des connexions TCP/IP dans un cluster MySQL

- 16-4-4-8. Définition des connexions par mémoire partagée dans un cluster MySQL

- 16-4-4-9. Définition d'un transporteur SCI dans un cluster

- 16-5. Serveur de gestion du cluster MySQL

- 16-5-1. Utilisation des processus serveurs MySQL par MySQL Cluster

- 16-5-2. ndbd, le processus de stockage du cluster

- 16-5-3. ndb_mgmd, le serveur de gestion

- 16-5-4. ndb_mgm, le client de gestion du cluster

- 16-5-5. Options des commandes pour le cluster MySQL

- 16-5-5-1. Options de cluster de mysqld

- 16-5-5-2. Options de la commande ndbd

- 16-5-5-3. Options de commande pour ndb_mgmd

- 16-5-5-4. Options de commande pour ndb_mgm

- 16-6. Administration de MySQL Cluster

- 16-6-1. Commandes du client de gestion du Cluster

- 16-6-2. Rapport d'événements générés par le cluster MySQL

- 16-6-2-1. Historique des commandes de gestion

- 16-6-2-2. Événements

- 16-6-3. Utilisateur unique du cluster

- 16-6-4. Sauvegarde en ligne de MySQL Cluster

- 16-6-4-1. Sauvegarde du cluster

- 16-6-4-2. Utilisation du serveur de gestion pour une sauvegarde de cluster

- 16-6-4-3. Comment restaurer une sauvegarde du cluster

- 16-6-4-4. Configuration pour la sauvegarde du Cluster

- 16-6-4-5. Résolution de problèmes avec la sauvegarde du cluster

- 16-7. Utilisation d'interconnexions haute vitesse avec MySQL Cluster

- 16-7-1. Configurer le cluster MySQL avec les sockets SCI

- 16-7-2. Mesures de vitesses pour comprendre les impacts sur le cluster

- 16-8. Limitations du cluster dans MySQL 4.1

- 16-9. Cluster MySQL en 5.0 et 5.1

- 16-9-1. Évolutions de MySQL Cluster en MySQL 5.0

- 16-9-2. Plans de développement de MySQL 5.1 pour le cluster MySQL

- 16-10. FAQ MySQL Cluster

- 16-11. MySQL Cluster Glossary

- 17. Introduction à MaxDB

- 17-1. Historique de MaxDB

- 17-2. Licence et support MaxDB

- 17-3. Liens traitant de MaxDB

- 17-4. Concepts de base de MaxDB

- 17-5. Différences de fonctionnalités entre MaxDB et MySQL

- 17-6. Interopérabilité entre MaxDB et MySQL

- 17-7. Mots réservés de MaxDB

- 18. Données spatiales avec MySQL

- 18-A. Introduction à GIS

- 18-B. Le modèle géométrique OpenGIS

- 18-B-1. La hiérarchie des classes géométriques

- 18-B-2. Classe Geometry

- 18-B-3. Classe Point

- 18-B-4. Classe Curve

- 18-B-5. Classe LineString

- 18-B-6. Classe Surface

- 18-B-7. Classe Polygon

- 18-B-8. Classe GeometryCollection

- 18-B-9. Classe MultiPoint

- 18-B-10. Classe MultiCurve

- 18-B-11. Classe MultiLineString

- 18-B-12. Classe MultiSurface

- 18-B-13. Classe MultiPolygon

- 18-C. Formats géométriques supportés

- 18-C-1. Format Well-Known Text (WKT)

- 18-C-2. Le format Well-Known Binary (WKB)

- 18-D. Créer une base de données avec les fonctionnalités géographiques

- 18-D-1. Types de données géographiques MySQL

- 18-D-2. Créer des objets géographiques

- 18-D-2-a. Créer des objets géométriques avec les fonctions WKT

- 18-D-2-b. Créer des objets géométriques avec les fonctions WKB

- 18-D-2-c. Création de formes géométriques avec les fonctions spécifiques de MySQL

- 18-D-3. Créer des colonnes géométriques

- 18-D-4. Remplir des colonnes géométriques

- 18-D-5. Lire des données géométriques

- 18-D-5-a. Lire des données géométriques au format interne

- 18-D-5-b. Lire des données géométriques au format WBT

- 18-D-5-c. Lire des données géométriques au format WBK

- 18-E. Analyser des données géographiques

- 18-E-1. Fonctions pour convertir les formes de format

- 18-E-2. Fonction d'analyse des propriétés des formes Geometry

- 18-E-2-a. Fonctions générales d'analyse géométrique

- 18-E-2-b. Fonctions d'analyse des Points

- 18-E-2-c. Fonctions d'analyse des lignes LineString

- 18-E-2-d. Fonctions d'analyse des lignes MultiLineString

- 18-E-2-e. Fonctions d'analyse des lignes Polygon

- 18-E-2-f. Fonctions d'analyse des lignes MultiPolygon

- 18-E-2-g. Fonctions d'analyse des lignes GeometryCollection

- 18-E-3. Fonctions qui génèrent des formes géométriques à partir d'autres formes

- 18-E-3-a. Fonctions géométriques qui génèrent de nouvelles formes

- 18-E-3-b. Opérateurs géométriques

- 18-E-4. Fonctions de tests des relations géométriques entre les formes

- 18-E-5. Relations avec les Rectangles enveloppes (MBRs)

- 18-E-6. Fonctions qui testent les relations géométriques entre les formes

- 18-F. Optimiser l'analyse géographique

- 18-F-1. Créer un index géométrique

- 18-F-2. Utiliser un index géométrique

- 18-G. MySQL compatibilité avec GIS

- 18-G-1. Les fonctionnalités de GIS que nous n'avons pas encore implémentées

- 19. Procédures stockées et fonctions

- 19-A. Procédures stockées et tables de droits

- 19-B. Syntaxe des procédures stockées

- 19-B-1. CREATE PROCEDURE et CREATE FUNCTION

- 19-B-2. ALTER PROCEDURE et ALTER FUNCTION

- 19-B-3. DROP PROCEDURE et DROP FUNCTION

- 19-B-4. SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION

- 19-B-5. SHOW PROCEDURE STATUS et SHOW FUNCTION STATUS

- 19-B-6. CALL

- 19-B-7. La commande composée BEGIN... END

- 19-B-8. La commande DECLARE

- 19-B-9. Les variables dans les procédures stockées

- 19-B-9-a. DECLARE : déclarer une variable locale

- 19-B-9-b. Commande d'affectation de variables SET

- 19-B-9-c. Syntaxe de SELECT... INTO

- 19-B-10. Conditions et gestionnaires

- 19-B-10-a. DECLARE une condition

- 19-B-10-b. DECLARE un gestionnaire

- 19-B-11. Curseurs

- 19-B-11-a. Déclaration des curseurs

- 19-B-11-b. Commande de curseur OPEN

- 19-B-11-c. Commande de curseur FETCH

- 19-B-11-d. Commande de curseur CLOSE

- 19-B-12. Instructions de contrôle

- 19-B-12-a. Commande IF

- 19-B-12-b. Commande CASE

- 19-B-12-c. Commande LOOP

- 19-B-12-d. Commande LEAVE

- 19-B-12-e. Commande ITERATE

- 19-B-12-f. Commande REPEAT

- 19-B-12-g. Syntaxe WHILE

- 20. Déclencheurs

- 20-A. Syntaxe de CREATE TRIGGER

- 20-B. Syntaxe de DROP TRIGGER

- 20-C. Utiliser les déclencheurs

- 21. Vues

- 21-A. Syntaxe ALTER VIEW

- 21-B. Syntaxe de CREATE VIEW

- 21-C. Syntaxe DROP VIEW

- 21-D. Syntaxe SHOW CREATE VIEW

- 22. La base de données d'informations INFORMATION_SCHEMA

- 22-A. Les tables INFORMATION_SCHEMA

- 22-A-1. La table INFORMATION_SCHEMA SCHEMATA

- 22-A-2. La table INFORMATION_SCHEMA TABLES

- 22-A-3. La table INFORMATION_SCHEMA COLUMNS

- 22-A-4. La table INFORMATION_SCHEMA STATISTICS

- 22-A-5. La table INFORMATION_SCHEMA USER_PRIVILEGES

- 22-A-6. La table INFORMATION_SCHEMA SCHEMA_PRIVILEGES

- 22-A-7. La table INFORMATION_SCHEMA TABLE_PRIVILEGES

- 22-A-8. La table INFORMATION_SCHEMA COLUMN_PRIVILEGES

- 22-A-9. La table INFORMATION_SCHEMA CHARACTER_SETS

- 22-A-10. La table INFORMATION_SCHEMA COLLATIONS

- 22-A-11. La table INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY

- 22-A-12. La table INFORMATION_SCHEMA TABLE_CONSTRAINTS

- 22-A-13. La table INFORMATION_SCHEMA KEY_COLUMN_USAGE

- 22-A-14. La table INFORMATION_SCHEMA ROUTINES

- 22-A-15. La table INFORMATION_SCHEMA VIEWS

- 22-A-16. Autres tables INFORMATION_SCHEMA

- 22-B. Extensions à la commande SHOW

- 23. Mathématiques de précision

- 23-A. Types de valeurs numériques

- 23-B. Changements de type de données avec DECIMAL

- 23-C. Gestion des expressions

- 23-D. Arrondissement de valeurs

- 23-E. Exemples de calculs mathématiques

- 24. API MySQL

- 24-A. Utilitaires de développement des programmes MySQL

- 24-A-1. msql2mysql, convertit des programmes mSQL vers MySQL

- 24-A-2. mysql_config lit les options de compilations du client MySQL

- 24-B. API MySQL C

- 24-B-1. Types de données de l'API C

- 24-B-2. Vue d'ensemble des fonctions de l'API C

- 24-B-3. Description des fonctions de l'API C

- 24-B-3-a. mysql_affected_rows()

- 24-B-3-b. mysql_change_user()

- 24-B-3-c. mysql_character_set_name()

- 24-B-3-d. mysql_close()

- 24-B-3-e. mysql_connect()

- 24-B-3-f. mysql_create_db()

- 24-B-3-g. mysql_data_seek()

- 24-B-3-h. mysql_debug()

- 24-B-3-i. mysql_drop_db()

- 24-B-3-j. mysql_dump_debug_info()

- 24-B-3-k. mysql_eof()

- 24-B-3-l. mysql_errno()

- 24-B-3-m. mysql_error()

- 24-B-3-n. mysql_escape_string()

- 24-B-3-o. mysql_fetch_field()

- 24-B-3-p. mysql_fetch_fields()

- 24-B-3-q. mysql_fetch_field_direct()

- 24-B-3-r. mysql_fetch_lengths()

- 24-B-3-s. mysql_fetch_row()

- 24-B-3-t. mysql_field_count()

- 24-B-3-u. mysql_field_seek()

- 24-B-3-v. mysql_field_tell()

- 24-B-3-w. mysql_free_result()

- 24-B-3-x. mysql_get_client_info()

- 24-B-3-y. mysql_get_client_version()

- 24-B-3-z. mysql_get_host_info()

- 24-B-3-aa. mysql_get_proto_info()

- 24-B-3-ab. mysql_get_server_info()

- 24-B-3-ac. mysql_get_server_version()

- 24-B-3-ad. mysql_hex_string()

- 24-B-3-ae. mysql_info()

- 24-B-3-af. mysql_init()

- 24-B-3-ag. mysql_insert_id()

- 24-B-3-ah. mysql_kill()

- 24-B-3-ai. mysql_library_end()

- 24-B-3-aj. mysql_library_end()

- 24-B-3-ak. mysql_list_dbs()

- 24-B-3-al. mysql_list_fields()

- 24-B-3-am. mysql_list_processes()

- 24-B-3-an. mysql_list_tables()

- 24-B-3-ao. mysql_num_fields()

- 24-B-3-ap. mysql_num_rows()

- 24-B-3-aq. mysql_options()

- 24-B-3-ar. mysql_ping()

- 24-B-3-as. mysql_query()

- 24-B-3-at. mysql_real_connect()

- 24-B-3-au. mysql_real_escape_string()

- 24-B-3-av. mysql_real_query()

- 24-B-3-aw. mysql_reload()

- 24-B-3-ax. mysql_row_seek()

- 24-B-3-ay. mysql_row_tell()

- 24-B-3-az. mysql_select_db()

- 24-B-3-ba. mysql_set_server_option()

- 24-B-3-bb. mysql_shutdown()

- 24-B-3-bc. mysql_sqlstate()

- 24-B-3-bd. mysql_ssl_set()

- 24-B-3-be. mysql_stat()

- 24-B-3-bf. mysql_store_result()

- 24-B-3-bg. mysql_thread_id()

- 24-B-3-bh. mysql_use_result()

- 24-B-3-bi. mysql_warning_count()

- 24-B-3-bj. mysql_commit()

- 24-B-3-bk. mysql_rollback()

- 24-B-3-bl. mysql_autocommit()

- 24-B-3-bm. mysql_more_results()

- 24-B-3-bn. mysql_next_result()

- 24-B-4. Fonctions C de commandes préparées

- 24-B-5. Types de données de l'API C

- 24-B-6. Présentation des fonctions de l'interface C

- 24-B-7. Description des fonctions C pour les requêtes préparées

- 24-B-7-a. mysql_stmt_affected_rows()

- 24-B-7-b. mysql_stmt_attr_get()

- 24-B-7-c. mysql_stmt_attr_set()

- 24-B-7-d. mysql_stmt_bind_param()

- 24-B-7-e. mysql_stmt_bind_result()

- 24-B-7-f. mysql_stmt_close()

- 24-B-7-g. mysql_stmt_data_seek()

- 24-B-7-h. mysql_stmt_errno()

- 24-B-7-i. mysql_stmt_error()

- 24-B-7-j. mysql_stmt_execute()

- 24-B-7-k. mysql_stmt_free_result()

- 24-B-7-l. mysql_stmt_insert_id()

- 24-B-7-m. mysql_stmt_fetch()

- 24-B-7-n. mysql_stmt_fetch_column()

- 24-B-7-o. mysql_stmt_field_count()

- 24-B-7-p. mysql_stmt_init()

- 24-B-7-q. mysql_stmt_num_rows()

- 24-B-7-r. mysql_stmt_param_count()

- 24-B-7-s. mysql_stmt_param_metadata()

- 24-B-7-t. mysql_stmt_prepare()

- 24-B-7-u. mysql_stmt_reset()

- 24-B-7-v. mysql_stmt_result_metadata()

- 24-B-7-w. mysql_stmt_row_seek()

- 24-B-7-x. mysql_stmt_row_tell()

- 24-B-7-y. mysql_stmt_send_long_data()

- 24-B-7-z. mysql_stmt_sqlstate()

- 24-B-7-aa. mysql_stmt_store_result()

- 24-B-8. Problèmes avec l'interface C des commandes préparées

- 24-B-9. Gestion des commandes multiples avec l'interface C

- 24-B-10. Gestion des dates et horaires avec l'interface C

- 24-B-11. Description des fonctions threadées de C

- 24-B-11-a. my_init()

- 24-B-11-b. mysql_thread_init()

- 24-B-11-c. mysql_thread_end()

- 24-B-11-d. mysql_thread_safe()

- 24-B-12. Description des fonctions C du serveur embarqué

- 24-B-12-a. mysql_server_init()

- 24-B-12-b. mysql_server_end()

- 24-B-13. Questions courantes sur la bibliothèque C

- 24-B-13-a. Pourquoi est-ce que mysql_store_result() retourne parfois NULL après que mysql_query() ait réussi

- 24-B-13-b. Quels résultats puis-je obtenir d'une requête?

- 24-B-13-c. Comment lire l'identifiant unique de la dernière ligne insérée

- 24-B-13-d. Problèmes lors de la liaison avec l'API C

- 24-B-14. Compiler les clients

- 24-B-15. Comment faire un client MySQL threadé

- 24-B-16. libmysqld, la bibliothèque du serveur embarqué MySQL

- 24-B-16-a. Vue d'ensemble de la bibliothèque du serveur embarqué MySQL

- 24-B-16-b. Compiler des programmes avec libmysqld

- 24-B-16-c. Restrictions lors de l'utilisation du serveur embarqué MySQL

- 24-B-16-d. Utilisation de fichiers d'options avec le serveur embarqué

- 24-B-16-e. Choses à faire pour le serveur embarqué (TODO)

- 24-B-16-f. Un exemple simple de serveur embarqué

- 24-B-16-g. Licence du serveur embarqué

- 24-C. API PHP pour MySQL

- 24-C-1. Problèmes fréquents avec MySQL et PHP

- 24-D. API Perl pour MySQL

- 24-E. Interface MySQL C++

- 24-E-1. Borland C++

- 24-F. MySQL Python API

- 24-G. MySQL Tcl API

- 24-H. Couche MySQL pour Eiffel

- 25. Pilotes MySQL

- 25-A. Support ODBC de MySQL

- 25-A-1. Introduction à MyODBC

- 25-A-1-a. Qu'est-ce que ODBC ?

- 25-A-1-b. Qu'est-ce que Connector/ODBC ?

- 25-A-1-c. Qu'est-ce que MyODBC 2.50 ?

- 25-A-1-d. Qu'est-ce que MyODBC 3.51 ?

- 25-A-1-e. Où obtenir MyODBC ?

- 25-A-1-f. Plateformes supportées

- 25-A-1-g. Listes de diffusion MyODBC

- 25-A-1-h. Forum MyODBC

- 25-A-1-i. Rapporter des problèmes avec MYODBC

- 25-A-1-j. Comment soumettre un correctif MyODBC

- 25-A-2. Informations générales sur ODBC et MyODBC

- 25-A-2-a. Introduction à ODBC

- 25-A-2-b. Architecture MyODBC

- 25-A-2-c. Gestionnaire de pilotes ODBC

- 25-A-2-d. Types de pilotes MySQL ODBC

- 25-A-3. Comment installer MyODBC

- 25-A-4. Installer MyODBC depuis une distribution binaire sur Windows

- 25-A-5. Installer MyODBC depuis une distribution binaire Unix

- 25-A-5-a. Installer MyODBC depuis un RPM d'une distribution

- 25-A-5-b. Installer MyODBC depuis une distribution binaire Tarball

- 25-A-6. Installer MyODBC depuis la version source sur Windows

- 25-A-6-a. Prérequis

- 25-A-6-b. Compiler MyODBC 3.51

- 25-A-6-c. Tests de MyODBC

- 25-A-6-d. Compiler MyODBC 2.50

- 25-A-7. Installer MyODBC depuis une source sur Unix

- 25-A-7-a. Prérequis

- 25-A-7-b. Options de configuration générales

- 25-A-7-c. Thread-Safe Client

- 25-A-7-d. Options partagées ou statiques

- 25-A-7-e. Activation des informations de débogage

- 25-A-7-f. Activation de la documentation

- 25-A-7-g. Génération et compilation

- 25-A-7-h. Création des bibliothèques partagées

- 25-A-7-i. Installation des bibliothèques de pilotes

- 25-A-7-j. Tester MyODBC sur Unix

- 25-A-7-k. Notes Mac OS X

- 25-A-7-l. Notes HP-UX

- 25-A-7-m. Notes pour AIX

- 25-A-8. Installer MyODBC depuis le serveur de versions BitKeeper

- 25-A-9. Configuration MyODBC

- 25-A-9-a. Qu'est-ce qu'un Data Source Name, ou Nom de Source de Données ?

- 25-A-9-b. Configuration du DSN MyODBC sur Windows

- 25-A-9-c. Configuration d'un DSN MyODBC sous Unix

- 25-A-9-d. Paramètres de connexion

- 25-A-9-e. Se connecter sans définir de DSN

- 25-A-9-f. Établir une connexion distante d'un système A à un système B

- 25-A-9-g. Obtenir un fichier de trace ODBC

- 25-A-9-h. Applications testées avec MyODBC

- 25-A-9-i. Programmes fonctionnant avec MyODBC

- 25-A-10. Problèmes avec les connexions MyODBC

- 25-A-10-a. Durant la configuration d'un DSN MyODBC, une erreur Could Not Load Translator or Setup Library survient

- 25-A-10-b. Lors de la connexion, une erreur Access denied survient

- 25-A-10-c. Informations  à propos des pools de connexions ODBC

- 25-A-11. MyODBC et Microsoft Access

- 25-A-11-a. Comment configurer Microsoft Access pour travailler avec MySQL via MyODBC ?

- 25-A-11-b. Comment exporter une table ou une requête depuis Access vers MySQL ?

- 25-A-11-c. Comment importer ou relier des bases de données MySQL avec Access ?

- 25-A-11-d. La structure ou la localisation d'une table liée a changé. Est-ce que je peux voir ces changements localement ?

- 25-A-11-e. Lorsque j'insère ou modifie une ligne dans des tables liées, j'obtiens #DELETED#

- 25-A-11-f. Comment puis-je éviter les conflits d'écriture ou de localisation ?

- 25-A-11-g. Lorsque j'exporte une table depuis Access 97, une erreur de syntaxe étrange survient

- 25-A-11-h. Access retourne l'erreur Another user has modified the record that you have modified durant l'édition de lignes

- 25-A-11-i. Comment intercepter les messages d'erreur d'identification ODBC ?

- 25-A-11-j. Comment optimiser les performances d'accès avec MyODBC ?

- 25-A-11-k. J'ai de très grandes tables. Quelle est la meilleure configuration pour que MyODBC accède à ces tables ?

- 25-A-11-l. Comment spécifier la valeur de QueryTimeout pour les connexions ODBC ?

- 25-A-11-m. INFO : outils pour exporter/importer des données entre Access et MySQL

- 25-A-12. MyODBC et Microsoft VBA et ASP

- 25-A-12-a. Pourquoi est-ce que SELECT COUNT(*) FROM tbl_name retourne une erreur ?

- 25-A-12-b. Quand j'utilise les méthodes ADO AppendChunk() ou GetChunk(), j'ai une erreur Multiple-step operation generated errors. Check each status value ?

- 25-A-12-c. Comment connaître le nombre total de lignes affectées par une requête SQL, avec ADO ?

- 25-A-12-d. Comment puis-je gérer des données BLOB avec Visual Basic ?

- 25-A-12-e. Comment associer les types de données de Visual Basic avec ceux de MySQL ?

- 25-A-12-f. Exemple VB avec ADO, DAO et RDO

- 25-A-12-g. ASP et MySQL avec MyODBC

- 25-A-12-h. INFO : Question fréquemment posée sur les objets ActiveX Data Objects (ADO)

- 25-A-13. MyODBC et les outils tierce partie

- 25-A-13-a. Comment lire les données MySQL dans un document Word ou Excel ?

- 25-A-13-b. L'export des tables depuis MS DTS vers MySQL avec MyODBC conduit à une erreur de syntaxe

- 25-A-13-c. HOWTO : configuration de MySQL, MyODBC, unixODBC et ColdFusion sur Solaris

- 25-A-14. Fonctionnalités générales de MyODBC

- 25-A-14-a. Comment obtenir la valeur d'une colonne AUTO_INCREMENT avec ODBC ?

- 25-A-14-b. Est-ce que MyODBC accepte les curseurs dynamiques ?

- 25-A-14-c. Quelle est la cause de l'erreur Transactions are not enabled ?

- 25-A-14-d. Quelle est la cause de l'erreur Cursor not found ?

- 25-A-14-e. Puis-je utiliser des applications MyODBC 2.50 avec MyODBC 3.51 ?

- 25-A-14-f. Puis-je accéder à MySQL depuis .NET avec MyODBC ?

- 25-A-14-g. Pourquoi est-ce que MyODBC s'exécute lentement et fait beaucoup d'accès disques pour de petites requêtes ?

- 25-A-15. Instructions de base pour utiliser MyODBC

- 25-A-16. Table de référence MyODBC

- 25-A-17. Les types de données MyODBC

- 25-A-18. Codes d'erreurs MyODBC

- 25-A-19. MyODBC avec VB : ADO, DAO et RDO

- 25-A-19-a. ADO: rs.addNew, rs.delete et rs.update

- 25-A-19-b. DAO : rs.addNew, rs.update et scrolls

- 25-A-19-c. RDO : rs.addNew et rs.update

- 25-A-20. MyODBC avec Microsoft .NET

- 25-A-20-a. ODBC.NET : CSHARP(C#)

- 25-A-20-b. ODBC.NET: VB

- 25-A-21. Crédits

- 25-B. MySQL et Java (JDBC)

- 26. Gestion des erreurs avec MySQL

- 27. Étendre MySQL

- 27-A. Rouages de MySQL

- 27-A-1. Threads MySQL

- 27-A-2. Suite de tests de MySQL

- 27-A-2-a. Exécuter la suite des tests MySQL

- 27-A-2-b. Améliorer la suite de tests MySQL

- 27-A-2-c. Rapporter des bogues dans la suite de tests MySQL

- 27-B. Ajouter des fonctions à MySQL

- 27-B-1. Fonctionnalités des fonctions utilisateur

- 27-B-2. Syntaxe de CREATE FUNCTION/DROP FUNCTION

- 27-B-3. Ajouter une nouvelle fonction définie par l'utilisateur (UDF)

- 27-B-3-a. Fonctions utilisateur : appeler des fonctions simples

- 27-B-3-b. Appeler des fonctions utilisateur pour les groupements

- 27-B-3-c. Traitement des arguments

- 27-B-3-d. Valeurs de retour et gestion d'erreurs

- 27-B-3-e. Compiler et installer des fonctions utilisateur

- 27-B-3-f. Précautions à prendre avec les fonctions utilisateur

- 27-B-4. Ajouter de nouvelles fonctions natives

- 27-C. Ajouter une nouvelle procédure à MySQL

- 27-C-1. La procédure Analyse

- 27-C-2. Écrire une procédure

- 28. Problèmes et erreurs communs

- 28-A. Comment déterminer ce qui pose problème

- 28-B. Erreurs communes rencontrées avec MySQL

- 28-B-1. Erreur Access denied

- 28-B-2. Erreur Can't connect to [local] MySQL server

- 28-B-3. Erreur Client does not support authentication protocol

- 28-B-4. Échec de saisie du mot de passe avec le client interactif

- 28-B-5. Erreur Host '...' is blocked

- 28-B-6. Erreur Too many connections

- 28-B-7. Erreur Out of memory

- 28-B-8. Erreur MySQL server has gone away

- 28-B-9. Erreur Packet too large

- 28-B-10. Erreurs de communication / Connexion annulée

- 28-B-11. Erreur The table is full

- 28-B-12. Erreur Can't create/write to file

- 28-B-13. Erreur du client Commands out of sync

- 28-B-14. Erreur Ignoring user

- 28-B-15. Erreur Table 'xxx' doesn't exist

- 28-B-16. Erreur Can't initialize character set xxx

- 28-B-17. Fichier non trouvé

- 28-C. Notes relatives à l'installation

- 28-C-1. Problèmes lors de la liaison avec la bibliothèque du client MySQL

- 28-C-2. Comment exécuter MySQL comme un utilisateur normal

- 28-C-3. Problèmes avec les permissions sur fichiers

- 28-D. Notes relatives à l'administration

- 28-D-1. Comment réinitialiser un mot de passe Root oublié

- 28-D-2. Que faire si MySQL plante constamment ?

- 28-D-3. Comment MySQL gère un disque plein

- 28-D-4. Où MySQL stocke les fichiers temporaires ?

- 28-D-5. Comment protéger ou changer le fichier socket /tmp/mysql.sock

- 28-D-6. Problèmes de fuseaux horaires

- 28-E. Problèmes relatifs aux requêtes

- 28-E-1. Sensibilité à la casse dans les recherches

- 28-E-2. Problèmes avec l'utilisation des colonnes DATE

- 28-E-3. Problèmes avec les valeurs NULL

- 28-E-4. Problèmes avec les alias

- 28-E-5. Erreur Some non-transactional changed tables couldn't be rolled back

- 28-E-6. Effacer des lignes de tables reliées

- 28-E-7. Résoudre les problèmes des lignes non retournées

- 28-E-8. Problèmes de comparaisons avec nombres à virgule flottante

- 28-F. Problèmes liés à l'optimiseur

- 28-G. Questions relatives aux définitions de tables

- 28-G-1. Problèmes avec ALTER TABLE.

- 28-G-2. Comment changer l'ordre des colonnes dans une table

- 28-G-3. Problèmes avec les tables temporaires

- 29. Crédits

- 29-A. Développeurs chez MySQL AB

- 29-B. Contributeurs à MySQL

- 29-C. Documenteurs et traducteurs

- 29-D. Bibliothèques utilisées et incluses dans MySQL

- 29-E. Applications qui supportent MySQL

- 29-F. Outils utilisés pour créer MySQL

- 29-G. Supporters de MySQL

- 29-H. Les évolutions de MySQL (la liste des tâches)

- 29-H-1. Nouvelles fonctionnalités prévues pour la version 5.0

- 29-H-2. Nouvelles fonctionnalités prévues pour 5.1

- 29-H-3. Ce qui doit être fait dans un futur proche

- 29-H-4. Ce qui est prévu à moyen terme

- 29-H-5. Ce qui n'est pas prévu

- 30. Historique des changements MySQL

- 30-A. Changements de la version 5.0.0 (Développement)

- 30-A-1. Changements de la version 5.0.6 (pas encore publiée)

- 30-A-2. Changements de la version 5.0.5 (Bientôt publiée)

- 30-A-3. Changements de la version 5.0.4 (16 avril 2005)

- 30-A-4. Changements de la version 5.0.3 (23 mars 2005 : Beta)

- 30-A-5. Changements de la version 5.0.2 (1er Décembre 2004)

- 30-A-6. Changements de la version 5.0.1 (pas encore publiée)

- 30-A-7. Changements de la version 5.0.0 (22 décembre 2003 : Alpha)

- 30-B. Changements de la version 4.1.x (Alpha)

- 30-B-1. Changements de la version 4.1.12 (Pas encore publiée)

- 30-B-2. Changements de la version 4.1.11 (1 avril 2005)

- 30-B-3. Changements de la version 4.1.10 (12 février 2005)

- 30-B-4. Changements de la version 4.1.9 (11 Janvier 2005)

- 30-B-5. Changements de la version 4.1.8 (14 Décembre 2004)

- 30-B-6. Changements de la version 4.1.7 (bientôt publiée)

- 30-B-7. Changements de la version 4.1.6 (10 Octobre 2004)

- 30-B-8. Changements de la version 4.1.4 (16 Septembre 2004)

- 30-B-9. Changements de la version 4.1.4 (26 Août 2004)

- 30-B-10. Changements de la version 4.1.3 (pas encore publiée)

- 30-B-11. Changements de la version 4.1.2

- 30-B-12. Changements de la version 4.1.1 (01 décembre 2003)

- 30-B-13. Changements de la version 4.1.0 (03 Avril 2003 : alpha)

- 30-C. Changements de la version 4.0.x (Production)

- 30-C-1. Changements de la version 4.0.25 (pas encore publié)

- 30-C-2. Changements de la version 4.0.24 (04 Mars 2005)

- 30-C-3. Changements de la version 4.0.23 (18 Décembre 2004)

- 30-C-4. Changements de la version 4.0.22 (27 Octobre 2004)

- 30-C-5. Changements de la version 4.0.21

- 30-C-6. Changements de la version 4.0.20

- 30-C-7. Changements de la version 4.0.19 (04 mai 2004)

- 30-C-8. Changements de la version 4.0.18 (pas encore publiée)

- 30-C-9. Changements de la version 4.0.17 (14 décembre 2003)

- 30-C-10. Changements de la version 4.0.16 (17 octobre 2003)

- 30-C-11. Changements de la version 4.0.15 (03 septembre 2003)

- 30-C-12. Changements de la version 4.0.14 (18 juillet 2003)

- 30-C-13. Changements de la version 4.0.13 (16 Mai 2003)

- 30-C-14. Changements de la version 4.0.12 (15 Mars 2003 : Production)

- 30-C-15. Changements de la version 4.0.11 (20 Février 2003)

- 30-C-16. Changements de la version 4.0.10 (29 janvier 2003)

- 30-C-17. Changements de la version 4.0.9 (09 janvier 2003)

- 30-C-18. Changements de la version 4.0.8 (07 janvier 2003)

- 30-C-19. Changements de la version 4.0.7 (20 Décembre 2002)

- 30-C-20. Changements de la version 4.0.6 (14 Décembre 2002 : Gamma)

- 30-C-21. Changements de la version 4.0.5 (13 novembre 2002)

- 30-C-22. Changements de la version 4.0.4 (29 septembre 2002)

- 30-C-23. Changements de la version 4.0.3 (26 Août 2002 : Beta)

- 30-C-24. Changements de la version 4.0.2 (01 Juillet 2002)

- 30-C-25. Changements de la version 4.0.1 (23 décembre 2001)

- 30-C-26. Changements de la version 4.0.0 (Octobre 2001 : alpha)

- 30-D. Changements de la version 3.23.x (Recent; still supported)

- 30-D-1. Changements de la version 3.23.59 (not released yet)

- 30-D-2. Changements de la version 3.23.58 (11 septembre 2003)

- 30-D-3. Changements de la version 3.23.57 (06 juin 2003)

- 30-D-4. Changements de la version 3.23.56 (13 mars 2003)

- 30-D-5. Changements de la version 3.23.55 (23 janvier 2003)

- 30-D-6. Changements de la version 3.23.54 (05 décembre 2002)

- 30-D-7. Changements de la version 3.23.53 (09 octobre 2002)

- 30-D-8. Changements de la version 3.23.52 (14 août 2002)

- 30-D-9. Changements de la version 3.23.51 (31 mai 2002)

- 30-D-10. Changements de la version 3.23.50 (21 avril 2002)

- 30-D-11. Changements de la version 3.23.49

- 30-D-12. Changements de la version 3.23.48 (07 février 2002)

- 30-D-13. Changements de la version 3.23.47 (27 décembre 2001)

- 30-D-14. Changements de la version 3.23.46 (29 novembre 2001)

- 30-D-15. Changements de la version 3.23.45 (22 novembre 2001)

- 30-D-16. Changements de la version 3.23.44 (31 octobre 2001)

- 30-D-17. Changements de la version 3.23.43 (04 octobre 2001)

- 30-D-18. Changements de la version 3.23.42 (08 septembre 2001)

- 30-D-19. Changements de la version 3.23.41 (11 août 2001)

- 30-D-20. Changements de la version 3.23.40

- 30-D-21. Changements de la version 3.23.39 (12 juin 2001)

- 30-D-22. Changements de la version 3.23.38 (09 mai 2001)

- 30-D-23. Changements de la version 3.23.37 (17 avril 2001)

- 30-D-24. Changements de la version 3.23.36 (27 mars 2001)

- 30-D-25. Changements de la version 3.23.35 (15 mars 2001)

- 30-D-26. Changements de la version 3.23.34a

- 30-D-27. Changements de la version 3.23.34 (10 mars 2001)

- 30-D-28. Changements de la version 3.23.33 (09 février 2001)

- 30-D-29. Changements de la version 3.23.32 (22 Jan 2001: Production)

- 30-D-30. Changements de la version 3.23.31 (17 janvier 2001)

- 30-D-31. Changements de la version 3.23.30 (04 janvier 2001)

- 30-D-32. Changements de la version 3.23.29 (16 décembre 2000)

- 30-D-33. Changements de la version 3.23.28 (22 Nov 2000: Gamma)

- 30-D-34. Changements de la version 3.23.27 (24 octobre 2000)

- 30-D-35. Changements de la version 3.23.26 (18 octobre 2000)

- 30-D-36. Changements de la version 3.23.25 (29 septembre 2000)

- 30-D-37. Changements de la version 3.23.24 (08 septembre 2000)

- 30-D-38. Changements de la version 3.23.23 (01 septembre 2000)

- 30-D-39. Changements de la version 3.23.22 (31 juillet 2000)

- 30-D-40. Changements de la version 3.23.21

- 30-D-41. Changements de la version 3.23.20

- 30-D-42. Changements de la version 3.23.19

- 30-D-43. Changements de la version 3.23.18

- 30-D-44. Changements de la version 3.23.17

- 30-D-45. Changements de la version 3.23.16

- 30-D-46. Changements de la version 3.23.15 (May 2000: Beta)

- 30-D-47. Changements de la version 3.23.14

- 30-D-48. Changements de la version 3.23.13

- 30-D-49. Changements de la version 3.23.12 (07 mars 2000)

- 30-D-50. Changements de la version 3.23.11

- 30-D-51. Changements de la version 3.23.10

- 30-D-52. Changements de la version 3.23.9

- 30-D-53. Changements de la version 3.23.8 (02 janvier 2000)

- 30-D-54. Changements de la version 3.23.7 (10 décembre 1999)

- 30-D-55. Changements de la version 3.23.6

- 30-D-56. Changements de la version 3.23.5 (20 octobre 1999)

- 30-D-57. Changements de la version 3.23.4 (28 septembre 1999)

- 30-D-58. Changements de la version 3.23.3

- 30-D-59. Changements de la version 3.23.2 (09 août 1999)

- 30-D-60. Changements de la version 3.23.1

- 30-D-61. Changements de la version 3.23.0 (05 Aug 1999: Alpha)

- 30-E. Changements de la version 3.22.x (Old; discontinued)

- 30-E-1. Changements de la version 3.22.35

- 30-E-2. Changements de la version 3.22.34

- 30-E-3. Changements de la version 3.22.33

- 30-E-4. Changements de la version 3.22.32 (14 février 2000)

- 30-E-5. Changements de la version 3.22.31

- 30-E-6. Changements de la version 3.22.30

- 30-E-7. Changements de la version 3.22.29 (02 janvier 2000)

- 30-E-8. Changements de la version 3.22.28 (20 octobre 1999)

- 30-E-9. Changements de la version 3.22.27

- 30-E-10. Changements de la version 3.22.26 (16 septembre 1999)

- 30-E-11. Changements de la version 3.22.25

- 30-E-12. Changements de la version 3.22.24 (05 juillet 1999)

- 30-E-13. Changements de la version 3.22.23 (08 juin 1999)

- 30-E-14. Changements de la version 3.22.22 (30 avril 1999)

- 30-E-15. Changements de la version 3.22.21

- 30-E-16. Changements de la version 3.22.20 (18 mars 1999)

- 30-E-17. Changements de la version 3.22.19 (Mar 1999: Production)

- 30-E-18. Changements de la version 3.22.18

- 30-E-19. Changements de la version 3.22.17

- 30-E-20. Changements de la version 3.22.16 (Feb 1999: Gamma)

- 30-E-21. Changements de la version 3.22.15

- 30-E-22. Changements de la version 3.22.14

- 30-E-23. Changements de la version 3.22.13

- 30-E-24. Changements de la version 3.22.12

- 30-E-25. Changements de la version 3.22.11

- 30-E-26. Changements de la version 3.22.10

- 30-E-27. Changements de la version 3.22.9

- 30-E-28. Changements de la version 3.22.8

- 30-E-29. Changements de la version 3.22.7 (Sep 1998: Beta)

- 30-E-30. Changements de la version 3.22.6

- 30-E-31. Changements de la version 3.22.5

- 30-E-32. Changements de la version 3.22.4

- 30-E-33. Changements de la version 3.22.3

- 30-E-34. Changements de la version 3.22.2

- 30-E-35. Changements de la version 3.22.1 (Jun 1998: Alpha)

- 30-E-36. Changements de la version 3.22.0

- 30-F. Changements de la version 3.21.x

- 30-F-1. Changements de la version 3.21.33

- 30-F-2. Changements de la version 3.21.32

- 30-F-3. Changements de la version 3.21.31

- 30-F-4. Changements de la version 3.21.30

- 30-F-5. Changements de la version 3.21.29

- 30-F-6. Changements de la version 3.21.28

- 30-F-7. Changements de la version 3.21.27

- 30-F-8. Changements de la version 3.21.26

- 30-F-9. Changements de la version 3.21.25

- 30-F-10. Changements de la version 3.21.24

- 30-F-11. Changements de la version 3.21.23

- 30-F-12. Changements de la version 3.21.22

- 30-F-13. Changements de la version 3.21.21a

- 30-F-14. Changements de la version 3.21.21

- 30-F-15. Changements de la version 3.21.20

- 30-F-16. Changements de la version 3.21.19

- 30-F-17. Changements de la version 3.21.18

- 30-F-18. Changements de la version 3.21.17

- 30-F-19. Changements de la version 3.21.16

- 30-F-20. Changements de la version 3.21.15

- 30-F-21. Changements de la version 3.21.14b

- 30-F-22. Changements de la version 3.21.14a

- 30-F-23. Changements de la version 3.21.13

- 30-F-24. Changements de la version 3.21.12

- 30-F-25. Changements de la version 3.21.11

- 30-F-26. Changements de la version 3.21.10

- 30-F-27. Changements de la version 3.21.9

- 30-F-28. Changements de la version 3.21.8

- 30-F-29. Changements de la version 3.21.7

- 30-F-30. Changements de la version 3.21.6

- 30-F-31. Changements de la version 3.21.5

- 30-F-32. Changements de la version 3.21.4

- 30-F-33. Changements de la version 3.21.3

- 30-F-34. Changements de la version 3.21.2

- 30-F-35. Changements de la version 3.21.0

- 30-G. Changements de la version 3.20.x

- 30-G-1. Changements de la version 3.20.18

- 30-G-2. Changements de la version 3.20.17

- 30-G-3. Changements de la version 3.20.16

- 30-G-4. Changements de la version 3.20.15

- 30-G-5. Changements de la version 3.20.14

- 30-G-6. Changements de la version 3.20.13

- 30-G-7. Changements de la version 3.20.11

- 30-G-8. Changements de la version 3.20.10

- 30-G-9. Changements de la version 3.20.9

- 30-G-10. Changements de la version 3.20.8

- 30-G-11. Changements de la version 3.20.7

- 30-G-12. Changements de la version 3.20.6

- 30-G-13. Changements de la version 3.20.3

- 30-G-14. Changements de la version 3.20.0

- 30-H. Changements de la version 3.19.x

- 30-H-1. Changements de la version 3.19.5

- 30-H-2. Changements de la version 3.19.4

- 30-H-3. Changements de la version 3.19.3

- 30-I. Evolutions de InnoDB

- 30-I-1. MySQL/InnoDB-4.0.21, pas publiée

- 30-I-2. MySQL/InnoDB-4.1.4, 31 Août 2004

- 30-I-3. MySQL/InnoDB-4.1.3, 28 Juin 2004

- 30-I-4. MySQL/InnoDB-4.1.2, pas publiée

- 30-I-5. MySQL/InnoDB-4.0.20, 18 mai 2004

- 30-I-6. MySQL/InnoDB-4.0.19, 4 mai 2004

- 30-I-7. MySQL/InnoDB-4.0.18, 13 février 2004

- 30-I-8. MySQL/InnoDB-5.0.0, 24 décembre 2003

- 30-I-9. MySQL/InnoDB-4.0.17, 17 décembre 2003

- 30-I-10. MySQL/InnoDB-4.1.1, 4 décembre 2003

- 30-I-11. MySQL/InnoDB-4.0.16, 22 octobre 2003

- 30-I-12. MySQL/InnoDB-3.23.58, 15 septembre 2003

- 30-I-13. MySQL/InnoDB-4.0.15, 10 septembre 2003

- 30-I-14. MySQL/InnoDB-4.0.14, 22 juillet 2003

- 30-I-15. MySQL/InnoDB-3.23.57, 20 juin 2003

- 30-I-16. MySQL/InnoDB-4.0.13, 20 mai 2003

- 30-I-17. MySQL/InnoDB-4.1.0, 3 avril 2003

- 30-I-18. MySQL/InnoDB-3.23.56, 17 mars 2003

- 30-I-19. MySQL/InnoDB-4.0.12, 18 mars 2003

- 30-I-20. MySQL/InnoDB-4.0.11, 25 février 2003

- 30-I-21. MySQL/InnoDB-4.0.10, 4 février 2003

- 30-I-22. MySQL/InnoDB-3.23.55, 24 janvier 2003

- 30-I-23. MySQL/InnoDB-4.0.9, 14 janvier 2003

- 30-I-24. MySQL/InnoDB-4.0.8, 7 janvier 2003

- 30-I-25. MySQL/InnoDB-4.0.7, 26 décembre 2002

- 30-I-26. MySQL/InnoDB-4.0.6, 19 décembre 2002

- 30-I-27. MySQL/InnoDB-3.23.54, 12 décembre 2003

- 30-I-28. MySQL/InnoDB-4.0.5, 18 novembre 2002

- 30-I-29. MySQL/InnoDB-3.23.53, 9 octobre 2002

- 30-I-30. MySQL/InnoDB-4.0.4, 2 octobre 2002

- 30-I-31. MySQL/InnoDB-4.0.3, 28 août 2002

- 30-I-32. MySQL/InnoDB-3.23.52, 16 août 2002

- 30-I-33. MySQL/InnoDB-4.0.2, 10 juillet 2002

- 30-I-34. MySQL/InnoDB-3.23.51, 12 juin 2002

- 30-I-35. MySQL/InnoDB-3.23.50, 23 avril 2002

- 30-I-36. MySQL/InnoDB-3.23.49, 17 février 2002

- 30-I-37. MySQL/InnoDB-3.23.48, 9 février 2002

- 30-I-38. MySQL/InnoDB-3.23.47, 28 décembre 2001

- 30-I-39. MySQL/InnoDB-4.0.1, 3 décembre 2001

- 30-I-40. MySQL/InnoDB-3.23.46, 30 novembre 2001

- 30-I-41. MySQL/InnoDB-3.23.45, 23 novembre 2001

- 30-I-42. MySQL/InnoDB-3.23.44, 2 novembre 2001

- 30-I-43. MySQL/InnoDB-3.23.43, 4 octobre 2001

- 30-I-44. MySQL/InnoDB-3.23.42, 9 septembre 2001

- 30-I-45. MySQL/InnoDB-3.23.41, 13 août 2001

- 30-I-46. MySQL/InnoDB-3.23.40, 16 juillet 2001

- 30-I-47. MySQL/InnoDB-3.23.39, 13 juin 2001

- 30-I-48. MySQL/InnoDB-3.23.38, 12 mai 2001

- 30-J. Historique de MySQL Cluster

- 30-J-1. MySQL Cluster-4.1.11 (01 Apr 2005)

- 30-J-2. MySQL Cluster-4.1.10 (12 Feb 2005)

- 30-J-3. MySQL Cluster-4.1.9 (13 Jan 2005)

- 30-J-4. MySQL Cluster-4.1.8 (14 Dec 2004)

- 30-J-5. MySQL Cluster-4.1.7, (23 Octobre 2004)

- 30-J-6. MySQL Cluster-4.1.6, 10 octobre 2004

- 30-J-7. MySQL Cluster-4.1.5, 16 septembre 2004

- 30-J-8. MySQL Cluster-4.1.4, 31 août 2004

- 30-J-9. MySQL Cluster-5.0.1, 27 juillet 2004

- 30-J-10. MySQL Cluster-4.1.3, 28 juin 2004

- 30-K. Historique de MyODBC

- 30-K-1. Changes in MyODBC 3.51.12

- 30-K-2. Changes in MyODBC 3.51.11

- 31. Port vers d'autres systèmes

- 31-A. Déboguer un serveur MySQL

- 31-A-1. Compiler MYSQL pour le débogage

- 31-A-2. Créer un fichier de traçage

- 31-A-3. Déboguer mysqld sous gdb

- 31-A-4. Utilisation d'un traçage de pile mémoire

- 31-A-5. Utilisation des fichiers de log pour trouver d'où viennent les erreurs de mysqld

- 31-A-6. Faire une batterie de tests lorsque vous faites face à un problème de table corrompue

- 31-B. Débogage un client MySQL

- 31-C. Le paquet DBUG

- 31-D. Commentaires à propos des threads RTS

- 31-E. Différences entre les types de paquets de threads

- 32. Variables d'environnement

- 33. Expressions régulières MySQL

- 34. Licence Publique Générale GNU

- 35. Exception de licence MySQL FLOSS

- 36. Index

1 - Informations générales

Le logiciel MySQL (TM) est un serveur de base de données SQL très rapide, multithreadé, multiutilisateur et robuste. Le serveur MySQL est destiné aux missions stratégiques et aux systèmes de production à forte charge, ainsi qu'à l'intégration dans des logiciels déployés à grande échelle. MySQL est une marque déposée de MySQL AB.

Le logiciel MySQL dispose de deux licences. Les utilisateurs peuvent choisir entre utiliser MySQL comme un logiciel Open Source/Logiciel libre, sous les termes de la licence GNU General Public License (http://www.gnu.org/licenses/) ou bien, ils peuvent acheter une licence commerciale auprès de MySQL AB. Voyez http://www.mysql.com/company/legal/licensing/ pour plus d'informations sur les licences.

Le site web de MySQL (http://www.mysql.com/) fournit les dernières informations sur le serveur MySQL.

La liste suivante décrit les sections particulières de ce manuel :

- pour une présentation des capacités de serveur de base de données MySQL, voyez Section 1.2.2, « Les fonctionnalités principales de MySQL » ;

- pour les instructions d'installation, voyez Chapitre 2, Installer MySQL ;

- pour des conseils sur le port du serveur de base de données MySQL sur de nouvelles architectures ou systèmes d'exploitation, voyez Annexe D, Port vers d'autres systèmes ;

- pour des informations sur la mise à jour vers la version 4.0, voyez Section 2.6.2, « Passer de la version 4.0 à la version 4.1 » ;

- pour des informations sur la mise à jour vers la version 3.23, voyez Section 2.6.3, « Passer de la version 3.23 à la version 4.0 » ;

- pour des informations sur la mise à jour vers la version 3.22, voyez Section 2.6.4, « Passer de la version 3.22 à la version 3.23 » ;

- pour une introduction au serveur de base de données MySQL, voyez Chapitre 3, Tutoriels d'introduction ;

- pour des exemples de SQL et des tests de performance, voyez le dossier de tests (sql-bench) de la distribution ;

- pour connaître l'historique des fonctionnalités et bogues, voyez Annexe C, Historique des changements MySQL ;

- pour une liste des bogues connus et des limitations, voyez Section 1.5.7, « Erreurs connues, et limitations de MySQL » ;

- pour les plans de développement, voyez Section B.8, « Les évolutions de MySQL (la liste des tâches) » ;

- pour une liste de tous les contributeurs à ce projet, voyez Annexe B, Crédits.

Important

Les rapports d'erreurs (aussi appelés bogues), ainsi que les questions et commentaires, doivent être envoyés à la liste de diffusion générale. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ». Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

Le script mysqlbug doit être utilisé pour générer le rapport de bogues. (Les distributions Windows contiennent un fichier mysqlbug.txt dans le dossier racine qui peut être utilisé comme formulaire pour un rapport de bogue).

Pour les distributions source, le script mysqlbug est accessible dans le dossier scripts. Pour les distributions binaires, mysqlbug est installé dans le dossier bin (/usr/bin pour le paquet RPM du serveur MySQL).

Si vous avez trouvé un problème de sécurité critique dans le code du serveur MySQL, vous devez envoyez un email à <security@mysql.com>.

1-1 - À propos du manuel

Ceci est le manuel de référence de MySQL; il documente MySQL jusqu'à la version 5.0.6-beta. Les évolutions fonctionnelles sont toujours indiquées avec une référence à la version d'évolution, de manière à ce que ce manuel soit toujours valable, même si vous utilisez une ancienne version de MySQL. Étant un manuel de référence, il ne fournit aucune description générale sur le langage SQL ou les concepts de base de données relationnelle.

Comme le logiciel de base de données MySQL est en développement constant, ce manuel est mis à jour fréquemment. La version la plus récente est disponible à http://dev.mysql.com/doc/ en différents formats, incluant HTML, PDF et Windows HLP.

L'original du document est un fichier au format Texinfo. La version HTML est produite automatiquement avec une version modifiée de texi2html. La version en texte plein et version Info sont produites par makeinfo. La version PostScript est produite avec texi2dvi et dvips. La version PDF est produite avec pdftex.

Si vous avez du mal à trouver des informations dans ce manuel, vous pouvez essayer notre version avec moteur de recherche, sur notre site web : http://www.mysql.com/doc/.

Si vous avez des suggestions concernant des ajouts ou des corrections à ce manuel, vous pouvez les envoyez à l'équipe de documentation à <docs@mysql.com>.

Ce manuel a été écrit initialement par David Axmark et Michael « Monty » Widenius. Il est actuellement entretenu par l'équipe de documentation MySQL, constituée de Paul DuBois, Stefan Hinz, Mike Hillyer, Jon Stephens et Russell Dyer. Pour les autres contributeurs, voyez les Annexe B, Crédits.

La traduction de ce manuel a été faite sous la direction de Damien Séguy. Mehdi Achour, Patrick Haond, David Manusset, Sylvain Maugiron, Guillaume Plessis et Yannick Torres ont contribué largement à cette traduction.

Le copyright (2002) de ce manuel est la propriété de la société suédoise MySQL AB.

1-1-1 - Conventions utilisées dans ce manuel

Ce manuel utilise certaines conventions typographiques :

- constant

La police à largeur fixe est utilisée pour les noms de commandes et les options, les requêtes SQL, les noms de base de données, de tables et de colonnes, le code C et Perl, les variables d'environnement. Par exemple, « Pour voir comment mysqladmin fonctionne, exécutez-le avec l'option --help » ;

- filename

La police à largeur fixe avec des guillemets d'encadrement indique des noms de fichiers et de chemins de dossiers. Par exemple : « La distribution est installée dans le dossier /usr/local/ » ;

- 'c'

La police à largeur fixe avec des guillemets d'encadrement est aussi utilisée pour indiquer des séquences de caractères. Par exemple : « Pour spécifier un caractère joker, utilisez le caractère '%' » ;

- italique

Les polices en italique sont utilisées pour attirer l'attention, comme ceci ;

- gras

Le gras est utilisé pour les entêtes de tables, et aussi pour attirer fortement votre attention.

Lorsque les commandes qui sont affichées sont destinées à être exécutées par un programme particulier, le nom du programme est indiqué dans l'invite de la commande. Par exemple, shell> indique une commande que vous exécutez depuis votre console Shell, et mysql> indique une commande que vous exécutez depuis le client mysql :

shell> tapez une commande shell ici
mysql> tapez une requête SQL ici

Le « Shell » est votre interpréteur de ligne de commande. Sous Unix, c'est typiquement un programme comme sh ou csh. Sous Windows, le programme équivalent est command.com ou cmd.exe, typiquement utilisée en console.

Lorsque vous saisissez une commande dans un exemple, omettez simplement de saisir l'invite de commande affichée.

Souvent, les noms de base de données, tables ou colonnes doivent être remplacés dans les commandes. Pour indiquer qu'une telle substitution est nécessaire, ce manuel utilise les noms de nom_de_base, nom_de_table et nom_colonne. Par exemple, vous pourriez avoir une requête comme ceci :

mysql> SELECT nom_colonne FROM nom_de_base.nom_de_table;

Cela signifie que si vous devez saisir une requête semblable, vous devriez utiliser votre propre nom de colonne, table et base de données, ce qui pourrait se traduire par ceci :

mysql> SELECT author_name FROM biblio_db.author_list;

Les mots réservés SQL ne sont pas sensibles à la casse, et peuvent être écrits en majuscules ou minuscules. Ce manuel utilise les majuscules.

Dans les illustrations de syntaxe, les crochets ('[' et ']') sont utilisés pour indiquer des clauses ou mots optionnels. Par exemple, dans la requête suivante, IF EXISTS est optionnel :

DROP TABLE [IF EXISTS] nom_de_table

Lorsqu'un élément de syntaxe propose plusieurs choix possibles, ces choix sont séparés par des barres verticales ('|'). Lorsque l'un des choix peut être sélectionné, les choix sont listés entre crochets ('[' et ']') :

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)

Lorsqu'un élément d'un jeu de possibilités doit être choisi, les alternatives sont placées entre accolades ('{' et '}') :

{DESCRIBE | DESC} nom_de_table {nom_colonne | wild}

Des crochets peuvent aussi indiquer que l'élément syntaxique précédent peut être répété. Dans l'exemple suivant, plusieurs valeurs reset_option peuvent être données, séparées par des virgules :

RESET reset_option [,reset_option] ...

Les commandes d'assignation des variables de Shell sont présentées avec la syntaxe Bourne Shell. Par exemple, la syntaxe suivante modifie une variable d'environnement :

shell> VARNAME=value some_command

Si vous utilisez csh ou tcsh, vous devez utiliser une syntaxe légèrement différente. Il faut écrire :

shell> setenv VARNAME value
shell> some_command

1-2 - Présentation du système de base de données MySQL

MySQL, le plus populaire des serveurs de base de données SQL open source, est développé, distribué et supporté par MySQL AB. MySQL AB est une société commerciale, fondée par les développeurs de MySQL, qui développe son activité en fournissant des services autour de MySQL.

Le site web de MySQL (http://www.mysql.com/) fournit les toutes dernières actualités sur le logiciel MySQL et sur la société MySQL AB.

- MySQL est un système de gestion de base de données.

Une base de données est un ensemble organisé de données. Cela peut aller d'une simple liste de courses au supermarché à une galerie de photos, ou encore les grands systèmes d'informations des multinationales. Pour ajouter, lire et traiter des données dans une base de données, vous avez besoin d'un système de gestion de base de données tel que le serveur MySQL. Comme les ordinateurs sont très bons à manipuler de grandes quantités de données, le système de gestion de base de données joue un rôle central en informatique, aussi bien en tant qu'application à part entière, qu'intégré dans d'autres logiciels.

- MySQL est un serveur de base de données relationnelle.

Un serveur de base de données stocke les données dans des tables séparées plutôt que de tout rassembler dans une seule table. Cela améliore la rapidité et la souplesse de l'ensemble. Les tables sont reliées par des relations définies, qui rendent possible la combinaison de données entre plusieurs tables durant une requête. Le SQL dans « MySQL » signifie « Structured Query Language » : le langage standard pour les traitements de base de données.

- MySQL est open source.

Open source (Standard Ouvert) signifie qu'il est possible à chacun d'utiliser et de modifier le logiciel. Tout le monde peut télécharger MySQL sur Internet, et l'utiliser sans payer aucun droit. Toute personne en ayant la volonté peut étudier et modifier le code source pour l'adapter à ses besoins propres. Le logiciel MySQL utilise la licence GPL (GNU General Public License), http://www.gnu.org/licenses/, pour définir ce que vous pouvez et ne pouvez pas faire avec ce logiciel, dans différentes situations. Si vous ne vous sentez pas confortable avec la licence GPL ou bien que vous devez intégrer MySQL dans une application commerciale, vous pouvez acheter une licence commerciale auprès de MySQL AB.

- Le serveur de base de données MySQL est très rapide, fiable et facile à utiliser.

Si c'est ce que vous recherchez, vous devriez faire un essai. Le serveur de base de données MySQL dispose aussi de fonctionnalités pratiques, développées en coopération avec nos utilisateurs. Vous pouvez trouver une comparaison des performances du serveur MySQL avec d'autres systèmes de base de données dans nos pages de tests de performance. Voir Section 7.1.4, « La suite de tests MySQL ».

Le serveur MySQL a été développé à l'origine pour gérer de grandes base de données plus rapidement que les solutions existantes, et a été utilisé avec succès dans des environnements de production très contraints et très exigeants, depuis plusieurs années. Bien que toujours en développement, le serveur MySQL offre des fonctions nombreuses et puissantes. Ses possibilités de connexions, sa rapidité et sa sécurité font du serveur MySQL un serveur hautement adapté à Internet.

- MySQL Server fonctionne en mode client/serveur ou en système embarqué.

Le serveur MySQL est un système client/serveur qui est constitué d'un serveur SQL multithreadé qui supporte différentes interfaces, clients, bibliothèques et outils d'administration, ainsi qu'une large gamme de pilotes pour différents langages (API).

Nous proposons aussi le serveur MySQL comme une bibliothèque embarquée, que vous pouvez intégrer dans vos applications pour en faire des produits plus petits, plus rapides et plus simples à utiliser.

- Il existe un grand nombre de contributions à MySQL.

Il est très probable que vous pourrez trouver votre éditeur préféré ou que votre environnement de programmation supporte déjà le serveur de base de données MySQL.

La prononciation officielle de MySQL est « My Ess Que Ell » (en anglais), ce qui donne « Maille Esse Cu Elle » en phonétique française. Évitez d'utiliser la prononciation « my sequel », mais nous ne nous formaliserons pas que vous utilisiez « my sequel » (ma séquelle, en français) ou une autre prononciation adaptée.

1-2-1 - Histoire de MySQL

Nous avons débuté avec l'intention d'utiliser mSQL pour nous connecter à nos tables en utilisant nos propres routines bas niveau ISAM. Cependant, après quelques tests, nous sommes arrivés à la conclusion que mSQL n'était pas assez rapide et flexible pour nos besoins. Cela nous a conduits à créer une nouvelle interface SQL pour notre base de données, mais en gardant la même API que mSQL. Cette API a été choisie pour la facilité de port des programmes de tiers.

Les liens avec le nom MySQL ne sont pas parfaitement établis. Notre dossier de base et un grand nombre de bibliothèques et outils étaient préfixés par « my » depuis plus de 10 ans. Mais la fille de Monty, plus jeune que lui, était aussi appelée My. Lequel des deux a conduit au nom de MySQL est toujours un mystère, même pour nous.

Le nom du dauphin MySQL (notre logo) est Sakila, qui a été choisi par les fondateurs de MySQL AB à partir d'une grande liste de noms suggérés par les utilisateurs dans le concours "Name the Dolphin" (« Nommez le dauphin »). Le nom a été suggéré par Ambrose Twebaze, un développeur de logiciels libres au Swaziland, en Afrique. D'après Ambrose, le nom Sakila puise ses origines du SiSwati, la langue locale du Swaziland. Sakila est aussi le nom d'une ville en Arusha, Tanzanie, près du pays d'origine d'Ambrose, Uganda.

1-2-2 - Les fonctionnalités principales de MySQL

La liste suivante décrit les caractéristiques principales du logiciel de base de données MySQL. Voyez la Section 1.3, « Plan de développement de MySQL » pour plus d'informations sur les fonctionnalités courantes et à venir.

- Interne et portabilité

- Écrit en C et C++.

- Testé sur un large éventail de compilateurs différents.

- Fonctionne sur de nombreuses plates-formes. Voir Section 2.1.1, « Systèmes d'exploitation supportés par MySQL ».

- Utilise GNU Automake, Autoconf et Libtool pour une meilleure portabilité.

- Dispose d'API pour C, C++, Eiffel, Java, Perl, PHP, Python, Ruby et Tcl. Voir Chapitre 24, API MySQL.

- Complètement multithreadé, grâce aux threads du noyau. Cela signifie que vous pouvez l'utiliser facilement sur un serveur avec plusieurs processeurs.

- Fournit des moteurs de tables transactionnelles et non transactionnelles.

- Index B-tree très rapide, avec compression d'index.

- Facilité relative à ajouter un nouveau moteur de table. C'est utile si vous voulez ajouter une interface SQL à votre base de données maison.

- Système l'allocation mémoire très rapide, exploitant les threads.

- Jointures très rapides, exploitant un système de jointures multiples en une seule passe optimisée.

- Tables en mémoire, pour réaliser des tables temporaires.

- Les fonctions SQL sont implémentées grâce à une bibliothèque de classes optimisées, qui sont aussi rapides que possible ! Généralement, il n'y a aucune allocation mémoire une fois que la requête a été initialisée.

- Le code de MySQL est vérifié avec Purify (un utilitaire de détection des fuites mémoires commercial) ainsi qu'avec Valgrind, un outil GPL (http://developer.kde.org/~sewardj/).

- Types de colonnes

- Nombreux types de colonnes : entiers signés ou non, de 1, 2, 3, 4, et 8 octets, FLOAT, DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME, TIMESTAMP, YEAR, SET et ENUM. Voir Chapitre 11, Types de colonnes.

- Enregistrements de taille fixe ou variable.

- Toutes les colonnes ont des valeurs par défaut. Vous pouvez utiliser la commande INSERT pour insérer un sous-ensemble de colonnes : les colonnes qui ne sont pas explicitement citées prennent alors leur valeur par défaut.

- Commandes et fonctions

- Support complet des opérateurs et fonctions dans la commande SELECT et la clause WHERE. Par exemple :

mysql> SELECT CONCAT(first_name, " ", last_name)
-> FROM tbl_name
-> WHERE income/dependents > 10000 AND age > 30;

- Support complet des clauses SQL GROUP BY et ORDER BY. Support des fonctions de groupages (COUNT(), COUNT(DISTINCT ...), AVG(), STD(), SUM(), MAX() et MIN()).

- Support des clauses LEFT OUTER JOIN et RIGHT OUTER JOIN avec les syntaxes ANSI SQL et ODBC.

- Les alias de tables et colonnes sont compatibles avec le standard SQL92.

- DELETE, INSERT, REPLACE et UPDATE retournent le nombre de lignes affectées. Il est possible d'obtenir le nombre de lignes trouvées en modifiant une option lors de la connexion au serveur.

- La commande spécifique à MySQL SHOW est utilisée pour obtenir des informations sur les bases, tables et index. La commande EXPLAIN sert à optimiser les requêtes.

- Les noms de fonctions ne sont jamais en conflit avec les noms de tables ou colonnes. Par exemple, ABS est un nom de colonne valide. La seule restriction est que, lors d'un appel de fonction, aucun espace n'est toléré entre le nom de la fonction et la parenthèse ouvrante '(' suivante. Voir Section 9.6, « Cas des mots réservés MySQL ».

- Vous pouvez utiliser simultanément des tables de différentes bases (depuis la version 3.22).

- Sécurité

- Un système de droits et de mots de passe très souple et sécuritaire, qui vérifie aussi les hôtes se connectant. Les mots de passe sont bien protégés, car tous les échanges de mot de passe sont chiffrés, même lors des connexions.

- Charges supportées et limites

- Gère les très grandes bases de données. Nous utilisons le serveur MySQL avec des bases qui contiennent 50 millions de lignes et nous connaissons des utilisateurs qui utilisent le serveur MySQL avec plus de 60 000 tables et 5 000 000 000 (milliards) de lignes.

- Jusqu'à 32 index sont permis par table. Chaque index est constitué de 1 à 16 colonnes ou parties de colonnes. La taille maximale d'un index est de 500 octets (ce qui peut être configuré à la compilation du serveur MySQL. Un index peut utiliser un préfixe issu d'un champ CHAR ou VARCHAR.

- Connexions

- Les clients peuvent se connecter au serveur MySQL en utilisant les sockets TCP/IP, les sockets Unix ou les pipes nommés sous NT.

- Support d'ODBC (Open-DataBase-Connectivity) pour Windows 32 bits (avec les sources). Toutes les fonctions ODBC 2.5 et de nombreuses autres. Par exemple, vous pouvez utiliser MS Access pour vous connecter au serveur MySQL. Voir Section 25.1.1.1, « Qu'est-ce que ODBC ? ».

- L'interface Connector/JDBC fournit le support pour les clients Java qui utilisent JDBC. Ces clients peuvent être utilisés sur Windows et Unix. Les sources de Connector/JDBC sont libres. Voir Chapitre 25, Pilotes MySQL.

- Traductions

- Le serveur fournit des messages d'erreurs au client dans de nombreuses langues, y compris le français. Voir Section 5.8.2, « Langue des messages d'erreurs ».

- Support complet de plusieurs jeux de caractères, comprenant ISO-8859-1 (Latin1), german, big5, ujis, etc. Par exemple, les caractères nordiques 'Â', 'ä' et 'ö' sont autorisés dans les noms de tables et colonnes.

- Toutes les données sont sauvées dans le jeu de caractères choisi. Les comparaisons normales de chaînes sont insensibles à la casse.

- Le tri est fait en fonction du jeu de caractères choisi (par défaut, le jeu suédois). Il est possible de le changer lorsque le serveur MySQL est démarré. Pour voir un exemple très avancé de tri, voyez le code de tri pour le tchèque. Le serveur MySQL supporte de nombreux jeux de caractères qui peuvent être spécifiés à la compilation et durant l'exécution.

- Clients et utilitaires

- Inclut myisamchk, un utilitaire rapide pour vérifier les tables, les optimiser et les réparer. Toutes les fonctionnalités de myisamchk sont aussi disponibles via l'interface SQL. Voir Chapitre 5, Administration du serveur.

- Tous les programmes MySQL peuvent être appelés avec l'option --help ou -? pour obtenir de l'aide en ligne.

1-2-3 - Jusqu'à quel point MySQL est-il stable ?

Cette section répond aux questions « Jusqu'à quel point MySQL est-il stable ? » et « Puis-je faire confiance à MySQL pour mon projet ? » Nous allons tenter d'apporter des réponses claires à ces questions importantes qui concernent tous les utilisateurs potentiels. Les informations de cette section sont fournies par les listes de diffusion, qui sont très actives et promptes à identifier les problèmes et les rapporter.

Le code original date du début des années 80 et fournit une base de code stable, tout en assurant une compatibilité ascendante avec le format ISAM. A TcX, le prédécesseur de MySQL AB, le code de MySQL a fonctionné sur des projets depuis la mi 1996, sans aucun problème. Lorsque le Serveur MySQL a été livré à un public plus large, nous avons réalisé qu'il contenait du code « jamais testé » qui a été rapidement identifié par les utilisateurs, qui effectuaient des requêtes différentes des nôtres. Chaque nouvelle version avait moins de problèmes de portabilité, même si chaque nouvelle version avait de nombreuses nouvelles fonctionnalités.

Chaque version du Serveur MySQL était parfaitement fonctionnelle. Les seuls problèmes étaient rencontrés par les utilisateurs de code de ces « zones d'ombre ». Naturellement, les nouveaux utilisateurs ne connaissent pas ces zones : cette section tente de les présenter, dans la mesure de nos connaissances. Les descriptions correspondent surtout aux versions 3.23 du Serveur MySQL. Tous les bogues connus et rapportés ont été corrigés dans la dernière version, à l'exception de ceux qui sont listés dans la section Bogues, qui sont des problèmes de conception. Voir Section 1.5.7, « Erreurs connues, et limitations de MySQL ».

La conception du serveur MySQL est faite en plusieurs couches, avec des modules indépendants. Certains des modules les plus récents sont listés ici, avec leur niveau de test.

- Réplication -- Gamma

De grands serveurs en grappe utilisant la réplication sont en production, avec de bons résultats. L'amélioration de la réplication continue avec MySQL 4.x.

- Tables InnoDB -- Stable (en 3.23 depuis 3.23.49)

Le gestionnaire transactionnel de tables InnoDB a été déclaré stable en MySQL version 3.23, à partir de la version 3.23.49. InnoDB est utilisé dans de grands systèmes complexes, avec forte charge.

- Tables BDB -- Gamma

Le code de Berkeley DB est très stable, mais nous sommes encore en train d'améliorer l'interface du gestionnaire transactionnel de table BDB du serveur MySQL. Cela demande encore du temps pour qu'il soit aussi bien testé que les autres types de tables.

- FULLTEXT -- Beta

La recherche en texte plein fonctionne, mais n'est pas encore largement adoptée. Des améliorations importantes sont prévues pour MySQL 4.0.

- Connector/ODBC 3.51 (Stable)

Connector/ODBC 3.51 utilise le SDK ODBC SDK 3.51 et est en production. Certains problèmes qui ont surgi sont liés aux applications, et indépendants du pilote ODBC ou le serveur sous-jacent.

- Tables à restauration automatique MyISAM -- Gamma

Ce statut ne concerne que le nouveau code du gestionnaire de tables MyISAM qui vérifie si la table a été correctement fermée lors de l'ouverture, et qui exécute automatiquement la vérification et réparation éventuelle de la table.

MySQL AB fournit un support de première qualité pour les clients payants, mais les listes de diffusions de MySQL sont généralement rapides à donner des réponses aux questions les plus communes. Les bogues sont généralement corrigés aussitôt avec un patch. Pour les bogues sérieux, il y a presque toujours une nouvelle version.

1-2-4 - Quelles tailles peuvent atteindre les tables MySQL

MySQL version 3.22 a une limite de 4 Go par table. Avec le nouveau format de table MyISAM, disponible avec MySQL version 3.23, la taille maximale des tables a été poussée à 8 millions de téraoctets (2^63 octets).

Notez, toutefois, que les systèmes d'exploitation ont leurs propres limites. Voici quelques exemples :

Système d'exploitation

Limite

Linux-Intel 32 bits

2 Go, 4 Go ou plus, suivant la version de Linux

Linux-Alpha

8 To (?)

Solaris 2.5.1

2 Go (4 Go possibles avec un patch)

Solaris 2.6

4 Go (peut être modifié avec une option)

Solaris 2.7 Intel

4 Go

Solaris 2.7 UltraSPARC

512 Go

NetWare avec/NSS

8 TB

En Linux 2.2, vous pouvez avoir des tables plus grandes que 2 Go en utilisant le patch LFS pour les systèmes de fichiers ext2. En Linux 2.4, le patch existe aussi pour ReiserFS. La plupart des distributions Linux courantes sont basées sur un noyau 2.4, et supportent déjà tous les patchs pour les grands fichiers (LFS). Cependant, la taille maximale de fichier dépend de nombreux facteurs, notamment le système de fichiers utilisé pour stocker les pages MySQL.

Pour une introduction détaillée à LFS sur Linux, voyez la page d'Andreas Jaeger Large File Support in Linux à http://www.suse.de/~aj/linux_lfs.html.

Par défaut, les tables MySQL peuvent atteindre une taille de 4 Go. Vous pouvez vérifier la taille des tables avec la commande SHOW TABLE STATUS ou la commande en ligne myisamchk -dv nom_de_table. Voir Section 13.5.3, « Syntaxe de SHOW ».

Si vous avez besoin de tables plus grandes que 4 Go (et que votre système d'exploitation le supporte, modifiez les paramètres AVG_ROW_LENGTH et MAX_ROWS lorsque vous créez votre table. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ». Vous pouvez aussi modifier ces valeurs avec la commande ALTER TABLE. Voir Section 13.2.2, « Syntaxe de ALTER TABLE ».

D'autres méthodes pour contourner les limitations des systèmes de fichiers avec les tables MyISAM :

- si votre table est en lecture seule, utilisez myisampack pour la compresser. myisampack compresse une table à 50 %, ce qui double environ la taille des tables. myisampack peut aussi combiner plusieurs tables en une seule. Voir Section 8.2, « myisampack, le générateur de tables MySQL compressées en lecture seule » ;

- une autre méthode pour contourner les limites du système de fichiers pour les tables MyISAM est d'utiliser les options RAID. Voir Section 13.2.5, « Syntaxe de CREATE TABLE » ;

- MySQL inclut une bibliothèque MERGE qui permet de gérer plusieurs tables identiques comme une seule. Voir Section 14.2, « Tables assemblées MERGE ».

1-2-5 - Compatibilité an 2000

Le serveur MySQL lui-même n'a aucun problème de compatibilité avec l'an 2000 (Y2K) :

- le serveur MySQL utilise les fonctions de date Unix, et n'a aucun problème avec les dates jusqu'en 2069 ; toutes les années écrites en deux chiffres sont supposées faire partie de l'intervalle allant de 1970 à 2069, ce qui signifie que si vous stockez la date 01 dans une colonne de type year, le serveur MySQL la traitera comme 2001 ;

- toutes les fonctions de dates de MySQL sont stockées dans un fichier sql/time.cc, et sont codées très soigneusement pour être compatibles avec l'an 2000 ;

- en MySQL version 3.22 et plus récent, le type de colonne YEAR peut stocker les valeurs 0 et de 1901 à 2155 sur un seul octet, tout en affichant 2 ou 4 chiffres.

Vous pouvez rencontrer des problèmes avec les applications qui utilisent le serveur MySQL sans être compatibles avec l'an 2000. Par exemple, les vieilles applications utilisent des valeurs d'années sur deux chiffres (ce qui est ambigu), plutôt qu'avec quatre chiffres. Ce problème peut être complété par des applications qui utilisent des valeurs telles que 00 ou 99 comme indicateur de données « manquantes ».

Malheureusement, ces problèmes peuvent se révéler difficiles à corriger, car différentes applications peuvent être écrites par différents programmeurs, et chacun utilise un jeu différent de conventions et de fonctions de gestion des dates.

Voici une illustration simple qui montre que le serveur MySQL n'a aucun problème avec les dates jusqu'en 2030 :

mysql> DROP TABLE IF EXISTS y2k;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE y2k (date DATE,
->                   date_time DATETIME,
->                   time_stamp TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO y2k VALUES
-> ("1998-12-31","1998-12-31 23:59:59",19981231235959),
-> ("1999-01-01","1999-01-01 00:00:00",19990101000000),
-> ("1999-09-09","1999-09-09 23:59:59",19990909235959),
-> ("2000-01-01","2000-01-01 00:00:00",20000101000000),
-> ("2000-02-28","2000-02-28 00:00:00",20000228000000),
-> ("2000-02-29","2000-02-29 00:00:00",20000229000000),
-> ("2000-03-01","2000-03-01 00:00:00",20000301000000),
-> ("2000-12-31","2000-12-31 23:59:59",20001231235959),
-> ("2001-01-01","2001-01-01 00:00:00",20010101000000),
-> ("2004-12-31","2004-12-31 23:59:59",20041231235959),
-> ("2005-01-01","2005-01-01 00:00:00",20050101000000),
-> ("2030-01-01","2030-01-01 00:00:00",20300101000000),
-> ("2050-01-01","2050-01-01 00:00:00",20500101000000);
Query OK, 13 rows affected (0.01 sec)
Records: 13  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM y2k;
+------------+---------------------+----------------+
| date       | date_time           | time_stamp     |
+------------+---------------------+----------------+
| 1998-12-31 | 1998-12-31 23:59:59 | 19981231235959 |
| 1999-01-01 | 1999-01-01 00:00:00 | 19990101000000 |
| 1999-09-09 | 1999-09-09 23:59:59 | 19990909235959 |
| 2000-01-01 | 2000-01-01 00:00:00 | 20000101000000 |
| 2000-02-28 | 2000-02-28 00:00:00 | 20000228000000 |
| 2000-02-29 | 2000-02-29 00:00:00 | 20000229000000 |
| 2000-03-01 | 2000-03-01 00:00:00 | 20000301000000 |
| 2000-12-31 | 2000-12-31 23:59:59 | 20001231235959 |
| 2001-01-01 | 2001-01-01 00:00:00 | 20010101000000 |
| 2004-12-31 | 2004-12-31 23:59:59 | 20041231235959 |
| 2005-01-01 | 2005-01-01 00:00:00 | 20050101000000 |
| 2030-01-01 | 2030-01-01 00:00:00 | 20300101000000 |
| 2050-01-01 | 2050-01-01 00:00:00 | 00000000000000 |
+------------+---------------------+----------------+
13 rows in set (0.00 sec)

Cet exemple montre que les types DATE et DATETIME ne poseront aucun problème avec les dates futures (ils gèrent les dates jusqu'en 9999).

Le type TIMESTAMP, qui est utilisé pour stocker la date courante, est valide jusqu'en 2030-01-01. TIMESTAMP va de 1970 en 2030 sur les machines 32 bits (valeur signée). Sur les machines 64 bits, il gère les dates jusqu'en 2106 (valeur non signée).

Même si le serveur MySQL est compatible an 2000, il est de votre responsabilité de fournir des données non ambiguës. Voyez Section 11.3.4, « An 2000 et les types date » pour les règles du serveur MySQL pour traiter les dates ambiguës (les données contenant des années exprimées sur deux chiffres).

1-3 - Plan de développement de MySQL

Cette section donne un aperçu du plan de développement de MySQL, incluant les futures fonctionnalités prévues pour MySQL 4.0, 4.1, 5.0 et 5.1. Les sections suivantes donnent plus de détails sur chaque version.

La série de production est MySQL 4.0, qui a été déclarée stable pour un environnement de production depuis la version 4.0.12, publiée en mars 2003. Cela signifie que les développements futurs de la série des 4.0 sont limités aux corrections de bogues. Pour les anciennes versions 3.23, seuls les bogues critiques seront corrigés.

L'effort de développement MySQL a lieu actuellement dans les versions MySQL 4.1 et 5.0. Cela signifie que les nouvelles fonctionnalités sont ajoutées aux versions 4.1 et 5.0. Les versions 4.1 et 5.0 sont disponibles en version alpha.

Avant de mettre à jour une version vers une autre, lisez les notes de la section Section 2.6, « Changer de version de MySQL ».

Les plans de certaines fonctionnalités sont résumés dans ce tableau :

Fonctionnalité

version MySQL

Unions

4.0

Sous-requêtes

4.1

R-trees

4.1 (pour les tables MyISAM)

Procédures stockées

5.0

Vues

5.0 ou 5.1

Curseurs

5.0

Clés étrangères

5.1 (déjà implémentées en 3.23 par InnoDB)

Triggers

5.1

Jointures externes

5.1

Contraintes

5.1

1-3-1 - MySQL 4.0 en bref

Promise depuis longtemps par MySQL AB et attendue avec impatience par nos utilisateurs, le serveur MySQL 4.0 est disponible en version de production.

MySQL 4.0 est disponible au téléchargement depuis http://www.mysql.com/ et nos miroirs. MySQL 4.0 a été testé par un grand nombre d'utilisateurs et il est en production sur de très grands sites.

Les fonctionnalités principales de MySQL serveur 4.0 sont destinées à nos utilisateurs professionnels et communautaires : elles améliorent les capacités de MySQL pour gérer les missions critiques et les systèmes fortement chargés. D'autres fonctionnalités sont destinées aux utilisateurs de solutions intégrées.

1-3-1-1 - Fonctionnalités disponibles en MySQL 4.0

- Amélioration des performances

- MySQL 4.0 dispose d'un cache de requêtes qui peut accélérer grandement vos applications qui utilisent souvent les mêmes requêtes. Voir Section 5.11, « Cache de requêtes MySQL ».

- La version 4.0 accélère la vitesse du serveur MySQL dans de nombreux domaines, notamment les INSERT de masse, la recherche sur les index compressés, la création d'index FULLTEXT ainsi que les comptes COUNT(DISTINCT).

- Serveur MySQL embarqué

- La nouvelle bibliothèque Embedded Server (au lieu de client/serveur) peut être facilement utilisée pour créer des applications indépendantes ou intégrées. Voir Section 1.3.1.2, « MySQL Server intégré (embedded) ».

- Le moteur InnoDB en standard

- Le moteur de tables InnoDB est désormais livré en standard avec le serveur MySQL, apportant le support complet des transactions ACID, les clés étrangères avec modifications et effacement en cascade, ainsi que le verrouillage de ligne. Voir Chapitre 15, Le moteur de tables InnoDB.

- Nouvelles fonctionnalités

- Les nouvelles possibilités de recherche en FULLTEXT de MySQL Serveur 4.0 permettent l'utilisation d'index FULLTEXT sur de grandes quantités de textes, avec des logiques binaires ou en langage naturel. Les utilisateurs peuvent paramétrer la taille minimum des mots, et définir leur propre liste de mots interdits, dans n'importe quelle langue. Cela ouvre la possibilité de nombreuses applications avec MySQL Serveur. Voir Section 12.6, « Recherche en texte intégral (Full-text) dans MySQL ».

- Respect des standards, portabilité et migration

- Simplification de la migration depuis d'autres bases de données vers MySQL Serveur, et notamment TRUNCATE TABLE (comme sous Oracle) et IDENTITY comme synonyme pour les clés automatiquement incrémentées (comme sous Sybase).

- De nombreux utilisateurs seront heureux de savoir que le serveur MySQL supporte aussi les requêtes UNION, une fonctionnalité SQL attendue avec impatience.

- MySQL peut s'exécuter nativement sur les plates-formes NetWare 6.0. Voir Section 2.2.14, « Installer MySQL sur NetWare ».

- Internationalisation

- Nos utilisateurs allemands, autrichiens et suisses remarqueront que nous avons un nouveau jeu de caractères, latin1_de, qui corrige les problèmes de tri des valeurs allemandes, en plaçant les umlauts allemands dans le même ordre que dans l'annuaire d'Allemagne.

- Amélioration de l'ergonomie

Durant la mise en place de fonctionnalités pour de nouveaux utilisateurs, nous n'avons pas oublié notre communauté de loyaux utilisateurs.

- Une fonctionnalité pratique pour les administrateurs de base de données est que la plupart des paramètres de démarrage de mysqld peuvent être modifiées sans redémarrer le serveur. Voir Section 13.5.2.8, « Syntaxe de SET ».

- Les commandes DELETE et UPDATE peuvent désormais fonctionner sur plusieurs tables.

- En ajoutant le support des liens symboliques à MyISAM au niveau des tables (et non plus au niveau des bases, comme auparavant), et en autorisant les liens symboliques sur Windows, nous espérons que nous avons pris au sérieux vos demandes d'amélioration.

- Des fonctions comme SQL_CALC_FOUND_ROWS et FOUND_ROWS() rendent possible le comptage de lignes sans utiliser la clause LIMIT.

La section sur les nouveautés du manuel rassemble toutes les nouveautés. Voir Section C.3, « Changements de la version 4.0.x (Production) ».

1-3-1-2 - MySQL Server intégré (embedded)

libmysqld rend le serveur MySQL disponible pour toute une gamme d'applications très vaste. En utilisant la bibliothèque du serveur MySQL intégré, vous pouvez utiliser MySQL dans différentes applications et appareillages, où l'utilisateur final n'aura même pas idée de sa présence. Le serveur MySQL intégré est idéal pour équiper les bornes internet, les kiosques publics, les paquets matériel/logiciels clé en main, les serveurs MySQL hautes performances, et les bases de données autonomes sur CD-ROM.

De nombreux utilisateurs de libmysqld profiteront de la double licence. Pour ceux qui ne souhaitent pas être liés par la licence GPL, la bibliothèque est aussi disponible avec une licence commerciale. La bibliothèque MySQL intégrée utilise la même interface que la bibliothèque cliente classique, ce qui la rend pratique à utiliser. Voir Section 24.2.16, « libmysqld, la bibliothèque du serveur embarqué MySQL ».

1-3-2 - MySQL 4.1 en bref

MySQL 4.0 a posé les fondations pour de nouvelles fonctionnalités telles que les sous-requêtes imbriquées et l'Unicode qui sont d'ores et déjà implémentées en version 4.1, ainsi que les procédures stockées SQL-99, qui seront disponibles pour la version 5.0. Ils représentent les fonctionnalités les plus demandées par de nombreux clients.

Avec ces améliorations, les critiques du serveur de base de données MySQL devront être plus imaginatifs que jamais pour identifier des manques dans le serveur MySQL. Déjà connu depuis longtemps pour sa stabilité, sa rapidité et sa facilité d'emploi, le serveur MySQL va désormais satisfaire la liste de tous les vœux des clients les plus exigeants.

1-3-2-1 - Fonctionnalités disponibles en MySQL 4.1

Les fonctionnalités ci-dessous sont implémentées en MySQL 4.1. Quelques autres fonctionnalités sont prévues pour MySQL 4.1, mais très peu. Voyez Voir Section B.8.1, « Nouvelles fonctionnalités prévues pour la version 5.0 ».

Les plus récentes fonctionnalités en cours de réalisation, comme les procédures stockées, seront disponibles en MySQL 5.0. Voir Section B.8.1, « Nouvelles fonctionnalités prévues pour la version 5.0 ».

- Support des sous-requêtes et tables dérivées

- Une sous-requête est une commande SELECT imbriquée dans une autre requête. Une table dérivée (une vue anonyme) est une sous-requête dans une clause FROM d'une autre commande. Voir Section 13.1.8, « Sous-sélections (SubSELECT) ».

- Accélération

- Protocole binaire plus rapide, avec préparation des commandes et paramétrage. Voir Section 24.2.4, « Fonctions C de commandes préparées ».

- Indexation BTREE pour les tables HEAP, ce qui améliore significativement le temps de réponse pour les recherches non exactes.

- Nouvelle fonctionnalité

- CREATE TABLE table_name2 LIKE table_name1 vous permet de créer, avec une seule commande, une nouvelle table, avec une structure identique à celle d'une autre table existante.

- Support pour les types géométriques OpenGIS (données géométriques). Voir Chapitre 18, Données spatiales avec MySQL.

- La réplication peut être faite sur connexions SSL.

- Compatibilité avec les standards, portabilité et migration

- Le nouveau protocole client-serveur apporte la possibilité de faire passer plusieurs alertes au client, plutôt qu'une seule. Cela améliore grandement la gestion des erreurs lors des manipulations de masse.

- SHOW WARNINGS affiche les erreurs de la dernière commande. Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

- Internationalisation

- Pour supporter notre base d'utilisateurs en pleine croissance, et leur configuration locale, MySQL exploite désormais l'Unicode (UTF8).

- Les jeux de caractères peuvent désormais être définis par colonnes, tables et bases. Cela permet d'améliorer la souplesse dans la conception des applications, en particulier pour les sites multilangues.

- Pour la documentation sur l'amélioration du support des jeux de caractères, voyez Chapitre 10, Jeux de caractères et Unicode.

- Améliorations d'ergonomie

- En réponse à la demande populaire, nous avons ajouté une commande HELP command côté serveur, qui peut être utilisée en ligne de commande du client mysql et d'autres clients, pour obtenir de l'aide sur les commandes SQL. Avec ces informations sur le serveur, elles seront parfaitement adaptées à la version et configuration du serveur.

- Avec le nouveau protocole client/serveur, les requêtes multiples sont désormais activées. Cela vous permet d'émettre plusieurs requêtes en une seule commande, puis de lire tous les résultats en une seule fois. Voir Section 24.2.9, « Gestion des commandes multiples avec l'interface C ».

- Le nouveau protocole client/serveur supporte aussi les jeux de résultats multiples. Cela peut arriver après une commande multiple, par exemple. Voir le point précédent.

- Nous avons implémenté une syntaxe pratique INSERT ... ON DUPLICATE KEY UPDATE .... Elle vous permet de modifier une ligne avec UPDATE, si l'insertion INSERT avait généré un double dans la colonne PRIMARY ou UNIQUE. Voir Section 13.1.4, « Syntaxe de INSERT ».

- Nous avons ajouté une fonction d'agrégation, GROUP_CONCAT(), qui permet de concaténer des colonnes dans une seule chaîne de résultat. Voir Section 12.9, « Fonctions et options à utiliser dans les clauses GROUP BY ».

La section sur les nouveautés du manuel rassemble toutes les nouveautés. Voir Section C.2, « Changements de la version 4.1.x (Alpha) ».

1-3-3 - MySQL 5.0, les prochains développements

Les nouveaux développements de MySQL sont désormais concentrés sur la version 5.0. Les procédures stockées et d'autres fonctionnalités seront en vedette. Voir Section B.8.1, « Nouvelles fonctionnalités prévues pour la version 5.0 ».

Pour ceux qui veulent jeter un œil aux tout derniers développements de MySQL, nous avons rendu notre serveur BitKeeper disponible au public pour MySQL version 5.0. Voir Section 2.4.3, « Installer à partir de l'arbre source de développement ». Depuis décembre 2003, des paquets binaires de MySQL version 5.0 sont aussi disponibles.

1-4 - Sources d'informations MySQL

1-4-1 - Listes de diffusion MySQL

Cette section vous présente les listes de diffusions MySQL, et donne des conseils quant à leur utilisation. En vous inscrivant à une des listes de diffusion, vous recevrez les messages que les autres auront envoyés, et vous pourrez envoyer vos propres questions et réponses.

1-4-1-1 - Les listes de diffusion de MySQL

Pour vous inscrire ou vous désinscrire à la liste de diffusion principale de MySQL, visitez le site http://lists.mysql.com/. N'envoyez pas de messages pour vous inscrire ou vous désinscrire sur la liste, car ces messages seront transmis automatiquement à des milliers d'utilisateurs.

Votre site local peut avoir beaucoup d'inscrits à une liste de diffusion. Si c'est le cas, vous pouvez avoir une liste de diffusion locale, de façon à ce que les messages envoyés par lists.mysql.com à votre site local soient propagés par votre serveur local. Dans ce cas, contactez votre administrateur local pour être ajouté ou retiré de la liste.

Si vous voulez que le trafic de cette liste soit envoyé à une autre boîte aux lettres de votre client mail, installez un filtre basé sur les entêtes du message. Vous pouvez utiliser notamment les entêtes List-ID: et Delivered-To: pour identifier les messages de la liste.

Les listes de diffusion MySQL suivantes existent :

- announce

Ceci est la liste de diffusion d'annonces des versions de MySQL et des programmes compagnons. C'est une liste à faible volume, et tout utilisateur doit y être inscrit ;

- mysql

La liste de diffusion principale pour les discussions générales sur MySQL. Notez que certains sujets sont à diriger sur les listes spécialisées. Si vous postez sur la mauvaise liste, vous pourriez ne pas avoir de réponse ;

- mysql-digest

La liste mysql en format journalier. Cela signifie que vous recevrez tous les messages de la journée en un seul gros email ;

- bugs

Sur cette liste, vous ne devriez envoyez que des bogues complets, reproductibles ainsi que le rapport qui va avec, en utilisant le script mysqlbug (si vous utilisez Windows, il faut aussi inclure la description du système d'exploitation et la version de MySQL). Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème » ;

- bugs-digest

La liste bugs en format journalier ;

- internals

Une liste pour ceux qui travaillent sur le code MySQL. Sur cette liste, vous pouvez discuter du développement de MySQL et envoyer des correctifs ;

- internals-digest

La liste internals en format journalier ;

- mysqldoc

La liste des personnes qui travaillent sur la documentation MySQL : des employés de MySQL AB, des traducteurs et d'autres membres de la communauté ;

- mysqldoc-digest

La liste mysqldoc en format journalier ;

- benchmarks

Cette liste est pour tous ceux qui sont intéressés par les performances. Les discussions se concentrent sur les performances (mais pas seulement avec MySQL), mais abordent aussi des problèmes de noyau, le système de fichiers, les disques, etc. ;

- benchmarks-digest

La liste benchmarks en format journalier ;

- packagers

Cette liste se concentre sur les paquets et les distributions MySQL. C'est l'un des forums utilisés par les responsables pour échanger des idées sur les paquets MySQL, pour s'assurer que MySQL est le même sur toutes les plates-formes ;

- packagers-digest

La liste packagers en format journalier ;

- java

Une liste pour ceux qui utilisent MySQL et Java. Elle concerne majoritairement les pilotes JDBC ;

- java-digest

La liste java en format journalier ;

- win32

Une liste pour ceux qui utilisent MySQL sur les systèmes d'exploitation de Microsoft, tels que Windows 9x/Me/NT/2000/XP ;

- win32-digest

La liste win32 en format journalier ;

- myodbc

Une liste pour tout ce qui concerne la connexion à MySQL avec le pilote ODBC ;

- myodbc-digest

La liste myodbc en format journalier ;

- mysqlcc

Une liste pour tout ce qui concerne le client graphique MySQL Control Center ;

- mysqlcc-digest

La liste mysqlcc en format journalier ;

- plusplus

Une liste pour tout ce qui concerne la programmation avec les API C++ de MySQL ;

- plusplus-digest

La liste plusplus en format journalier ;

- msql-mysql-modules

Une liste pour tout ce qui concerne Perl et le support du module msql/mysql ;

- msql-mysql-modules-digest

La liste msql-mysql-modules en format journalier.

Vous pouvez vous inscrire ou vous désinscrire de toutes les listes en même temps de la même façon que nous l'avons décrit au début. Dans votre message d'inscription, utilisez simplement le nom de liste approprié. Par exemple, pour vous inscrire à la liste myodbc.

Si vous ne pouvez pas obtenir d'informations sur la liste de diffusion, une de vos options est de prendre un contrat de support auprès de MySQL AB, qui vous donnera un contact direct avec les développeurs MySQL.

L'énumération suivante présente diverses autres listes de diffusions consacrées à MySQL, dans d'autres langues que l'anglais. Notez que ces ressources ne sont pas gérées par MySQL AB, ce qui fait que nous ne pouvons pas garantir leur qualité.

- <mysql-france-subscribe@yahoogroups.com>

Une liste de diffusion française.

- <list@tinc.net>

Une liste de diffusion coréenne. Envoyez un message à subscribe mysql your@e-mail.address.

- <mysql-de-request@lists.4t2.com>

Une liste de diffusion allemande. Envoyez un message à subscribe mysql-de your@e-mail.address. Vous aurez plus d'informations sur cette liste à http://www.4t2.com/mysql/.

- <mysql-br-request@listas.linkway.com.br>

Une liste de diffusion portugaise. Envoyez un message à subscribe mysql-br your@e-mail.address.

- <mysql-alta@elistas.net>

Une liste de diffusion espagnole. Envoyez un message à subscribe mysql your@e-mail.address.

1-4-1-2 - Poser des questions ou rapporter un bogue

Avant de soumettre un rapport de bogue ou une question, commencez par ces étapes simples :

- étudiez le manuel MySQL et faites-y une recherche à : http://www.mysql.com/doc/ Nous nous efforçons de mettre à jour le manuel fréquemment, en y ajoutant les solutions aux nouveaux problèmes. L'historique de modifications (http://www.mysql.com/doc/en/News.html) est particulièrement pratique, car il est possible qu'une nouvelle version de MySQL propose déjà la solution à votre problème ;

- cherchez dans la base de données des bogues sur http://bugs.mysql.com/ pour voir si le bogue a déjà été rapporté ou résolu ;

- recherchez dans les archives des listes de diffusion de MySQL : http://lists.mysql.com/ ;

- vous pouvez aussi utiliser l'URL http://www.mysql.com/search/ pour rechercher dans toutes les pages web (y compris le manuel) sur le site web de MySQL.

Si vous n'arrivez pas à trouver une réponse à votre question dans le manuel ou dans les archives, vérifiez auprès de votre expert MySQL local. Si vous ne trouvez toujours pas la réponse, vous pouvez lire la section suivante.

1-4-1-3 - Comment rapporter un bogue ou un problème

Notre base de données de bogues est publique, et peut être lue par tous sur le site http://bugs.mysql.com/. Si vous vous identifiez sur le système vous serez aussi capable d'envoyer des rapports.

Écrire un bon rapport de bogue requiert de la patience, et le faire dès le début épargnera votre temps et le nôtre. Un bon rapport de bogue qui contient un cas de test complet améliorera vos chances de voir le bogue corrigé à la prochaine version. Cette section vous aidera à écrire correctement un rapport de bogue, de manière à ce que vous ne gaspilliez pas votre temps à faire des textes qui ne nous aideront que peu ou pas.

Nous vous recommandons d'utiliser le script mysqlbug pour générer un rapport de bogue (ou rapporter un problème), dans la mesure du possible. mysqlbug est situé dans le dossier scripts de la distribution, ou, pour les distributions binaires, dans le dossier bin du dossier d'installation de MySQL. Si vous êtes dans l'incapacité d'utiliser mysqlbug, vous devez tout de même inclure toutes les informations nécessaires listées dans cette section.

Le script mysqlbug vous aide à générer un rapport en déterminant automatiquement les informations suivantes, mais si quelque chose d'important lui échappe, ajoutez-le dans votre message ! Lisez cette section avec attention, et assurez-vous que toutes les informations décrites ici sont présentes dans votre message.

De préférence, vous devriez tester le problème avec la dernière version de production ou de développement de MySQL. Il doit être facile de reproduire le test avec simplement la commande 'mysql test < script', appliquée au cas de test, ou en exécutant le script Shell ou Perl inclus dans le rapport.

Tous les bogues postés sur le site de rapports de bogues http://bugs.mysql.com/ seront corrigés ou documentés dans la prochaine version de MySQL. Si seuls, de petits changements sont nécessaires, nous publierons aussi un patch.

Si vous avez découvert un problème de sécurité critique avec MySQL, il faut envoyer un email à <security@mysql.com>.

Si vous avez un rapport de bogue reproductible, envoyez un rapport sur le site http://bugs.mysql.com/. Notez que même dans ce cas, il est bon d'utiliser le script mysqlbug pour rassembler des informations sur votre système. Tous les bogues que nous pourrons reproduire auront de bonnes chances d'être corrigés lors de la prochaine version de MySQL.

Pour signaler d'autres problèmes, utilisez une des listes de diffusion MySQL.

Sachez qu'il est toujours possible de répondre à un message qui contient trop d'informations, alors qu'il est impossible de répondre à un message qui contient trop peu d'informations. Souvent, il est facile d'omettre des faits parce que vous pensez connaître la cause du problème et supposez que ces détails ne sont pas importants. Un bon principe à suivre est : si vous avez un doute à propos de quelque chose, faites-nous-en part. Il est bien plus rapide et bien moins frustrant d'écrire quelques lignes de plus dans un rapport plutôt que d'être obligé de demander une nouvelle fois et d'attendre une réponse parce que vous avez oublié une partie des informations la première fois.

L'erreur la plus commune est de ne pas indiquer le numéro de la version de MySQL qui est utilisé, ou de ne pas indiquer le système d'exploitation que vous utilisez (y compris le numéro de version de ce système d'exploitation). Ce sont des informations de première importance, et dans 99 % des cas, le rapport de bogue est inutilisable sans ces informations. Souvent, nous recevons des questions telles que « Pourquoi est-ce que cela ne fonctionne pas pour moi ? ». Puis nous nous apercevons que la fonctionnalité en question n'est même pas programmée dans la version de MySQL utilisée, ou que le bogue décrit est déjà corrigé dans une nouvelle version de MySQL. Parfois aussi, les erreurs sont dépendantes des plates-formes. Dans ce cas, il est presque impossible de les corriger sans savoir quel système d'exploitation et quelle version exacte est utilisée.

Pensez aussi à fournir des informations concernant votre compilateur, si c'est pertinent. Souvent, les développeurs trouvent des bogues dans les compilateurs, et pensent que c'est lié à MySQL. La plupart des compilateurs sont en constant développement, et s'améliorent de version en version. Pour déterminer si votre problème dépend de votre compilateur, nous avons besoin de savoir quel compilateur est utilisé. Notez que les problèmes de compilation sont des bogues, et doivent être traités avec un rapport de bogues.

Il est particulièrement utile de fournir une bonne description du bogue dans le rapport de bogue. Cela peut être un exemple de ce que vous avez fait qui a conduit au problème, ou une description précise. Les meilleurs rapports sont ceux qui incluent un exemple complet permettant de reproduire le bogue. Voir Section D.1.6, « Faire une batterie de tests lorsque vous faites face à un problème de table corrompue ».

Si un programme produit un message d'erreur, il est très important d'inclure ce message dans votre rapport. Il est préférable que le message soit le message exact, car il est alors possible de le retrouver en utilisant les archives : même la casse doit être respectée. N'essayez jamais de vous rappeler d'un message d'erreur, mais faites plutôt un copier/coller du message complet dans votre rapport.

Si vous avez un problème avec MyODBC, essayez de générer un fichier de trace MyODBC. Voir Section 25.1.1.9, « Rapporter des problèmes avec MYODBC ».

Pensez aussi que de nombreuses personnes qui liront votre rapport utilisent un formatage de 80 colonnes. Lorsque vous générez votre rapport et vos exemples avec l'outil de ligne de commande, utilisez une largeur de 80 colonnes. Utilisez l'option --vertical (ou la fin de commande \G) pour les affichages qui excèdent une telle largeur (par exemple, avec la commande EXPLAIN SELECT; voyez l'exemple un peu plus tard dans cette section.

Voici un pense-bête des informations à fournir dans votre rapport.

- Le numéro de version de la distribution de MySQL que vous utilisez (par exemple MySQL Version 3.22.22). Vous pouvez connaître cette version en exécutant la commande mysqladmin version. mysqladmin est situé dans le dossier bin de votre distribution MySQL.

- Le fabricant et le modèle de votre serveur.

- Le système d'exploitation et la version que vous utilisez. Pour la plupart des systèmes d'exploitation, vous pouvez obtenir cette information en utilisant la commande Unix uname -a.

- Parfois, la quantité de mémoire (physique et virtuelle) est importante. Si vous hésitez, ajoutez-la.

- Si vous utilisez une version de MySQL sous forme de source, le nom et le numéro de version du compilateur sont nécessaires. Si vous utilisez une version exécutable, le nom de la distribution est important.

- Si le problème intervient lors de la compilation, incluez le message d'erreur exact et les quelques lignes de contexte autour du code en question dans le fichier où il est situé.

- Si mysqld s'est arrêté, il est recommandé d'inclure la requête qui a mené à cet arrêt de mysqld. Vous pouvez généralement la trouver en exécutant mysqld en ayant activé les logs. Voir Section D.1.5, « Utilisation des fichiers de log pour trouver d'où viennent les erreurs de mysqld ».

- Si une table ou une base sont liées au problème ajoutez le résultat de la commande mysqldump --no-data db_name tbl_name1 tbl_name2 .... C'est très simple à faire, et c'est un moyen efficace d'obtenir un descriptif de table, qui nous permettra de recréer une situation comparable à la vôtre.

- Pour les problèmes liés à la vitesse, ou des problèmes liés à la commande SELECT, pensez à inclure le résultat de la commande EXPLAIN SELECT ..., et au moins le nombre de lignes que la commande SELECT doit produire. Vous devriez aussi inclure le résultat de la commande SHOW CREATE TABLE table_name pour chaque table impliquée. Plus vous nous fournirez d'informations, plus nous aurons de chances de vous aider efficacement. Par exemple, voici un excellent rapport de bogue (posté avec le script mysqlbug, et effectivement rédigé en anglais) :

Exemple réalisé avec mysql en ligne de commande (notez l'utilisation de la fin de commande \G, pour les résultats qui pourraient dépasser les 80 colonnes de large) :

mysql> SHOW VARIABLES;
mysql> SHOW COLUMNS FROM ...\G
<output from SHOW COLUMNS>
mysql> EXPLAIN SELECT ...\G
<output from EXPLAIN>
mysql> FLUSH STATUS;
mysql> SELECT ...;
<A short version of the output from SELECT,
including the time taken to run the query>
mysql> SHOW STATUS;
<output from SHOW STATUS>

- Si un bogue ou un problème survient lors de l'exécution de mysqld, essayez de fournir un script qui reproduit l'anomalie. Ce script doit inclure tous les fichiers source nécessaires. Plus votre script reproduira fidèlement votre situation, mieux ce sera. Si vous pouvez réaliser un cas de test, postez-le sur le site http://bugs.mysql.com/ pour un traitement prioritaire !

Si vous ne pouvez pas fournir de script, fournissez tout au moins le résultat de la commande mysqladmin variables extended-status processlist dans votre mail pour fournir des informations sur les performances de votre système.

- Si vous ne pouvez pas reproduire votre situation en quelques lignes, ou si une table de test est trop grosse pour être envoyée par mail (plus de 10 lignes), exportez vos tables sous forme de fichier avec la commande mysqldump et créez un fichier README qui décrit votre problème.

Créez une archive compressée de votre fichier en utilisant tar et gzip ou zip, et placez-la via ftp sur le site de ftp://support.mysql.com/pub/mysql/secret/ [ftp://support.mysql.com/pub/mysql/secret/]. Puis, entrez la description de l'anomalie sur le site http://bugs.mysql.com/.

- Si vous pensez que le serveur MySQL fournit des résultats étranges pour une requête, incluez non seulement le résultat, mais aussi votre propre explication sur ce que le résultat devrait être, et un diagnostic de la situation.

- Lorsque vous donnez un exemple du problème, il est mieux d'utiliser des noms de variables et de tables qui existent dans votre situation, plutôt que d'inventer de nouveaux noms. Le problème peut être lié aux noms des variables ou tables que vous utilisez ! Ces cas sont rares, mais il vaut mieux éviter les ambiguïtés. Après tout, il est plus facile pour vous de fournir un exemple qui utilise votre situation réelle, et c'est bien mieux pour nous aussi. Si vous avez des données que vous ne souhaitez pas divulguer, vous pouvez utiliser le site ftp pour les transférer dans le dossier secret ftp://support.mysql.com/pub/mysql/secret/ [ftp://support.mysql.com/pub/mysql/secret/]. Si les données sont vraiment ultrasecrètes et que vous ne souhaitez même pas nous les montrer, alors utilisez d'autres noms et données pour votre rapport, mais considérez cela comme un dernier recours.

- Incluez toutes les options utilisées, si possible. Par exemple, indiquez les options que vous utilisez lors du démarrage de mysqld, et celle que vous utilisez avec les programmes comme mysqld et mysql, et le script configure, qui sont souvent primordiaux et pertinents. Ce n'est jamais une mauvaise idée que de les inclure. Si vous utilisez des modules, comme Perl ou PHP, incluez aussi les versions de ces logiciels.

- Si votre question porte sur le système de droits, incluez le résultat de l'utilitaire mysqlaccess, celui de mysqladmin reload et tous les messages d'erreurs que vous obtenez lors de la connexion. Lorsque vous testez votre système de droits, il faut commencer par utiliser la commande mysqladmin reload version et de vous connecter avec le programme qui vous pose problème. mysqlaccess est situé dans le dossier bin de votre installation de MySQL.

- Si vous avez un patch pour un bogue, c'est une excellente chose. Mais ne supposez pas que nous n'avons besoin que du patch, ou même que nous allons l'utiliser, si vous ne fournissez pas les informations nécessaires pour le tester. Nous pourrions trouver des problèmes générés par votre patch, ou bien nous pourrions ne pas le comprendre du tout. Si tel est le cas, nous ne l'utiliserons pas.

Si nous ne pouvons pas vérifier exactement ce pour quoi est fait le patch, nous ne l'utiliserons pas. Les cas de tests seront utiles ici. Montrez-nous que votre patch va générer toutes les situations qui pourraient arriver. Si nous trouvons un cas limite dans lequel votre patch ne fonctionne pas, même s'il est rare, il risque d'être inutile.

- Les diagnostics sur la nature du bogue, la raison de son déclenchement ou les effets de bord sont généralement faux. Même l'équipe MySQL ne peut diagnostiquer sans commencer par utiliser un débogueur pour déterminer la cause véritable.

- Indiquez dans votre mail que vous avez vérifié le manuel de référence et les archives de courrier, de façon à avoir épuisé les solutions que d'autres avant vous auraient pu trouver.

- Si vous obtenez un message parse error, vérifiez votre syntaxe avec attention. Si vous ne pouvez rien y trouver à redire, il est très probable que votre version de MySQL ne supporte pas encore cette fonctionnalité que vous essayez d'utiliser. Si vous utilisez la version courante de mySQL et que le manuel http://www.mysql.com/doc/ ne couvre pas la syntaxe que vous utilisez, c'est que MySQL ne supporte pas votre syntaxe. Dans ce cas, vos seules options sont d'implémenter vous-même la syntaxe ou d'envoyer un message à <licensing@mysql.com> pour proposer de l'implémenter.

Si le manuel présente la syntaxe que vous utilisez, mais que vous avez une ancienne version du serveur MySQL, il est recommandé de vérifier l'historique d'évolution de MySQL pour savoir quand la syntaxe a été supportée. Dans ce cas, vous avez l'option de mettre à jour votre MySQL avec une version plus récente. Voir Annexe C, Historique des changements MySQL.

- Si vous avez un problème tel que vos données semblent corrompues, ou que vous recevez constamment des erreurs lors d'accès à une table, vous devriez commencer par essayer de réparer votre table avec l'utilitaire de ligne de commande myisamchk ou les syntaxes SQL CHECK TABLE et REPAIR TABLE. Voir Chapitre 5, Administration du serveur.

- Si vous avez des tables qui se corrompent facilement, il vous faut essayer de trouver quand et pourquoi cela arrive. Dans ce cas, le fichier mysql-data-directory/'hostname'.err peut contenir des informations pertinentes qu'il est bon d'inclure dans votre rapport de bogues. Voir Section 5.9.1, « Le log d'erreurs ». Normalement, mysqld ne doit jamais corrompre une table s'il a été interrompu au milieu d'une mise à jour. Si vous pouvez trouver la cause de l'arrêt de mysqld, il est bien plus facile pour nous de fournir un correctif. Voir Section A.1, « Comment déterminer ce qui pose problème ».

- Si possible, téléchargez et installez la version la plus récente du serveur MySQL, et vérifiez si cela résout votre problème. Toutes les versions de MySQL sont testées à fond, et doivent fonctionner sans problème. Nous croyons à la compatibilité ascendante, et vous devriez pouvoir passer d'une version à l'autre facilement. Voir Section 2.1.2, « Choisir votre version de MySQL ».

Si vous disposez de l'accès au support client, contactez aussi le support client à <mysql-support@mysql.com>, en plus de la liste de rapports de bogues, pour un traitement prioritaire.

Pour des informations sur les rapports de bogues avec MyODBC, voyez Section 25.1.1.9, « Rapporter des problèmes avec MYODBC ».

Pour des solutions aux problèmes les plus courants, voyez Annexe A, Problèmes et erreurs communes.

Lorsque des solutions vous sont envoyées individuellement et non pas à la liste, il est considéré comme bien vu de rassembler ces réponses et d'en envoyer un résumé sur la liste, de manière à ce que les autres en profitent aussi.

1-4-1-4 - Conseils pour répondre sur la liste de diffusion

Si vous pensez que votre réponse peut avoir un intérêt général, vous pouvez envisager de l'envoyer sur la liste de diffusion, plutôt que de faire une réponse personnelle aux demandeurs. Essayez de rendre votre réponse aussi générale que possible, pour que suffisamment d'autres personnes puissent en profiter. Lorsque vous envoyez une réponse sur la liste, assurez-vous qu'elle ne représente pas un doublon d'une réponse précédente.

Essayez de résumer l'essentiel de la question dans votre réponse. Ne vous croyez pas obligé de citer tout le message original.

Attention : n'envoyez pas de message avec le mode HTML activé ! De nombreux utilisateurs ne lisent pas leurs emails avec un navigateur.

1-4-2 - Support de la communauté MySQL sur IRC (Internet Relay Chat)

En plus des différentes listes de diffusion MySQL, vous pouvez rencontrer des utilisateurs expérimentés sur IRC (Internet Relay Chat). Voici les meilleurs canaux, à notre connaissance.

- freenode (voyez http://www.freenode.net/ pour les serveurs)

- #mysql Principalement, des questions sur MySQL, mais les autres bases de données et le langage SQL sont aussi acceptés.

- EFnet (voyez http://www.efnet.org/ pour les serveurs)

- #mysql Questions sur MySQL.

Si vous recherchez un client IRC pour vous connecter à un réseau IRC, voyez donc X-Chat (http://www.xchat.org/). X-Chat est disponible sous Unix et sous Windows.

1-4-3 - Support de la communauté MySQL sur les forums MySQL

La ressource ultime de support de la communauté sont les forums sur http://forums.mysql.com.

Il y a une large gamme de serveurs disponibles, regroupés par thèmes comme ceci :

- Migration ;

- Utilisation de MySQL ;

- Connecteurs MySQL ;

- MySQL Technology ;

- Business.

1-5 - Quels standards respecte MySQL ?

Cette section présente comment MySQL interprète les standards SQL ANSI. Le serveur MySQL dispose de nombreuses extensions au standard ANSI et vous trouverez ici comment les exploiter. Vous trouverez aussi des informations sur les fonctionnalités manquantes de MySQL et comment y trouver des palliatifs.

Notre but n'est pas, sans une bonne raison, de restreindre les capacités de MySQL à un usage unique. Même si nous n'avons pas les ressources de développement à consacrer à toutes les opportunités, nous sommes toujours intéressés et prêts à aider ceux qui utilisent MySQL dans de nouveaux domaines.

Un de nos objectifs avec ce produit est de tendre à la compatibilité ANSI 99, mais sans sacrifier la vitesse ou la robustesse. Nous ne reculons pas devant l'ajout de nouvelle fonctionnalité au langage SQL, ou le support de fonctionnalités hors SQL, qui améliorent le confort d'utilisation de MySQL. La nouvelle interface de gestionnaires HANDLER de MySQL 4.0 est un exemple de cette stratégie. (Voir Section 13.1.3, « Syntaxe de HANDLER ».)

Nous continuons de supporter les bases transactionnelles et non transactionnelles pour combler les besoins des sites web ou des applications à fort besoin d'archivage, ainsi que les applications critiques à très haute disponibilité.

Le serveur MySQL a été conçu pour travailler avec des bases de taille moyenne (de 10 à 100 millions de lignes, ou des tables de 100 Mo) sur des systèmes de petite taille. Nous continuons d'améliorer MySQL pour qu'il fonctionne avec des bases gigantesques (téraoctets), tout en conservant la possibilité de compiler une version réduite de MySQL pour qu'il fonctionne sur des appareils embarqués ou nomades. L'architecture compacte de MySQL rend possible le support de ces applications si différentes, sans aucun conflit dans les sources.

Nous n'étudions pas le support du temps réel ou des bases de données en grappe (même si vous pouvez d'ores et déjà réaliser de nombreuses applications avec les services de réplication).

Nous ne croyons pas au support natif du XML en base, mais nous allons faire en sorte d'ajouter le support XML que réclament nos clients du côté client. Nous pensons qu'il est préférable de conserver le serveur central aussi « simple et efficace » que possible, et développer les bibliothèques qui gèrent la complexité du côté client. Cela fait partie de la stratégie que nous avons mentionnée plus tôt, pour ne sacrifier ni la vitesse ni la robustesse du serveur.

1-5-1 - Quels standards suit MySQL ?

Nous nous dirigeons vers le support complet du standard ANSI SQL, mais sans aucune concession sur la vitesse ou la qualité du code.

ODBC niveau 0-3.51.

1-5-2 - Sélectionner les modes SQL

Le serveur MySQL peut opérer avec différents modes SQL, et peut appliquer des modes différents pour chaque client. Cela permet aux applications d'adapter le comportement du serveur à ses attentes.

Le mode définit quelle syntaxe SQL MySQL doit supporter, et quel type de validations il doit effectuer sur les données. Cela facilite l'utilisation de MySQL dans différents environnements, et avec d'autres bases de données.

Vous pouvez configurer le mode SQL par défaut en lançant le serveur mysqld avec l'option --sql-mode="modes". Depuis MySQL 4.1, vous pouvez aussi changer le mode après le lancement, en changeant la variable sql_mode avec la commande SET [SESSION|GLOBAL] sql_mode='modes'.

Pour plus d'informations sur les modes serveur, voyez Section 5.2.2, « Le mode SQL du serveur ».

1-5-3 - Exécuter MySQL en mode ANSI

Vous pouvez lancer mysqld en mode ANSI avec l'option de démarrage --ansi. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Le mode ANSI revient à lancer le serveur avec les options suivantes (spécifiez la valeur de --sql_mode sur une seule ligne) :

--transaction-isolation=SERIALIZABLE
--sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,
IGNORE_SPACE,ONLY_FULL_GROUP_BY

En MySQL version 4.1, vous pouvez arriver à la même configuration avec ces deux options (spécifiez la valeur de --sql_mode sur une seule ligne) :

SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET GLOBAL sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY';

Voir Section 1.5.2, « Sélectionner les modes SQL ».

En MySQL version 4.1.1, les options sql_mode présentées ci-dessus peuvent être configurées avec :

SET GLOBAL sql_mode='ansi';

Dans ce cas, la valeur de la variable sql_mode prendra toutes les options du mode ANSI. Vous pouvez vérifier le résultat comme ceci :

mysql> SET GLOBAL sql_mode='ansi';
mysql> SELECT @@global.sql_mode;
-> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,
IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI';

1-5-4 - Extensions MySQL au standard SQL-92

Le serveur MySQL inclut des extensions que vous ne trouverez probablement pas dans les autres bases de données. Soyez prévenus que si vous les utilisez, votre code ne sera probablement pas portable sur d'autres serveurs SQL. Dans certains cas, vous pouvez écrire du code qui inclut des spécificités de MySQL, mais qui restent portables, en les incluant dans des commentaires de la forme /*! ... */. Dans ce cas, le serveur MySQL va analyser la chaîne et exécuter le code à l'intérieur de ces commentaires comme une commande normale, mais d'autres serveurs ignoreront ces commentaires. Par exemple :

SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...

Si vous ajoutez le numéro de version après le point d'exclamation '!', la syntaxe sera exécutée uniquement si la version du serveur MySQL est égale ou plus récente que le numéro de version utilisé.

CREATE /*!32302 TEMPORARY */ TABLE t (a int);

Cela signifie que si vous avez la version 3.23.02 ou plus récente, le serveur MySQL va utiliser le mot réservé TEMPORARY.

Voici une liste des apports spécifiques de MySQL.

- Organisation des données sur le disque

MySQL fait correspondre à chaque base un dossier dans le dossier de données MySQL, et à chaque table des fichiers portant le même nom. Ceci a plusieurs implications :

- les noms des bases de données et des tables sont sensibles à la casse sur les systèmes d'exploitation qui ont des systèmes de fichiers sensibles à la casse (comme la plupart des systèmes Unix). Voir Section 9.2.2, « Sensibilité à la casse pour les noms » ;

- Vous pouvez utiliser les commandes système standard pour sauver, renommer, déplacer, effacer et copier des tables. Par exemple, pour renommer une table, il suffit de renommer les fichiers .MYD, .MYI et .frm et de leur donner un nouveau nom.

Les noms de bases, tables, index, colonnes ou alias peuvent commencer par des chiffres, mais ne peuvent pas être constitués uniquement de noms.

- Syntaxe générale du langage

- Les chaînes de caractères peuvent être soit délimitées par '"', soit par '''. Pas seulement par '''.

- L'utilisation du caractère de protection '\'.

- Dans une requête SQL, vous pouvez accéder à des tables situées dans différentes bases de données, avec la syntaxe db_name.tbl_name. Certains serveurs SQL fournissent la même fonctionnalité, mais l'appellent un User space. Le serveur MySQL ne supporte par les espaces de nom de tables, comme dans : create table ralph.my_table...IN my_tablespace.

- Syntaxe de commande SQL

- Les commandes ANALYZE TABLE, CHECK TABLE, OPTIMIZE TABLE et REPAIR TABLE.

- Les commandes CREATE DATABASE et DROP DATABASE. Voir Section 13.2.3, « Syntaxe de CREATE DATABASE ».

- La commande DO.

- La commande EXPLAIN SELECT pour avoir le détail des jointures de tables.

- Les commandes FLUSH et RESET.

- La commande SET. Voir Section 13.5.2.8, « Syntaxe de SET ».

- La commande SHOW. Voir Section 13.5.3, « Syntaxe de SHOW ».

- L'utilisation de la commande LOAD DATA INFILE. Dans de nombreuses situations, cette syntaxe est compatible avec la commande d'Oracle LOAD DATA INFILE. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

- L'utilisation de RENAME TABLE. Voir Section 13.2.9, « Syntaxe de RENAME TABLE ».

- L'utilisation de REPLACE au lieu de DELETE + INSERT. Voir Section 13.1.6, « Syntaxe de REPLACE ».

- L'utilisation de CHANGE col_name, DROP col_name ou DROP INDEX, IGNORE ou RENAME dans une commande ALTER TABLE. Voir Section 13.2.2, « Syntaxe de ALTER TABLE ».

- L'utilisation de noms d'index, de préfixes d'index, et l'utilisation des mots-clés INDEX or KEY dans une commande de création de table CREATE TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

- L'utilisation des clauses TEMPORARY et IF NOT EXISTS avec CREATE TABLE.

- L'utilisation de DROP TABLE avec les mots-clés IF EXISTS.

- Vous pouvez effacer plusieurs tables avec une seule commande DROP TABLE.

- La clause LIMIT de la commande DELETE.

- La syntaxe INSERT INTO ... SET col_name = ....

- La clause DELAYED des commandes INSERT et REPLACE.

- La clause LOW_PRIORITY des commandes INSERT, REPLACE, DELETE et UPDATE.

- L'utilisation de INTO OUTFILE et STRAIGHT_JOIN dans les requêtes SELECT. Voir Section 13.1.7, « Syntaxe de SELECT ».

- L'option SQL_SMALL_RESULT de la commande SELECT.

- Vous n'êtes pas obligé de nommer toutes les colonnes que vous sélectionnez dans la clause GROUP BY. Cela donne de meilleures performances pour certaines situations spécifiques, mais classiques. Voir Section 12.9, « Fonctions et options à utiliser dans les clauses GROUP BY ».

- Vous pouvez spécifier ASC ou DESC dans la clause GROUP BY.

- La possibilité de modifier les variables dans les commandes avec l'opérateur := :

SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg FROM test_table;
SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;

- Types de colonnes

- Les types de colonnes MEDIUMINT, SET, ENUM et les types BLOB et TEXT.

- Les attributs de champs AUTO_INCREMENT, BINARY, NULL, UNSIGNED et ZEROFILL.

- Fonctions et opérateurs

- Pour aider les utilisateurs qui viennent d'autres environnements SQL, le serveur MySQL supporte des alias de nombreuses fonctions. Par exemple, toutes les fonctions de chaînes de caractères supportent simultanément les syntaxes ANSI SQL et ODBC.

- Le serveur MySQL comprend les opérateurs || et && comme opérateurs logiques OR et AND, comme en langage C. Pour le serveur MySQL, les opérateurs || et OR sont synonymes, ainsi que && et AND. En conséquence, MySQL ne supporte pas l'opérateur de concaténation de chaînes ANSI SQL ||. Utilisez plutôt la fonction CONCAT(). Comme CONCAT() prend un nombre illimité d'arguments, il est facile de convertir des expressions utilisant ||, pour qu'elles fonctionnent sur le serveur MySQL.

- L'utilisation de COUNT(DISTINCT list) où list contient plus d'un élément.

- Toutes les comparaisons de chaînes sont insensibles à la casse par défaut, et l'ordre de tri est déterminé par le jeu de caractères courant (ISO-8859-1 Latin1 par défaut). Si vous en souhaitez un autre, il faut déclarer les colonnes avec l'attribut BINARY ou utiliser l'opérateur BINARY pour forcer les comparaisons à prendre en compte la casse, en fonction du jeu de caractères utilisé sur l'hôte du serveur MySQL.

- L'opérateur % est synonyme de MOD(). C'est-à-dire que N % M est équivalent à MOD(N,M). % est supporté pour les programmeurs C, et pour la compatibilité avec PostgreSQL.

- Les opérateurs =, <>, <=, <, >=, >, <<, >>, <=>, AND, OR ou LIKE peuvent être utilisés pour les comparaisons de colonnes à gauche de la clause FROM dans les commandes SELECT. Par exemple :

mysql> SELECT col1=1 AND col2=2 FROM tbl_name;

- La fonction LAST_INSERT_ID(), qui retourne la plus récente valeur de colonne AUTO_INCREMENT. Voir Section 12.8.3, « Fonctions d'informations ».

- LIKE est possible avec des colonnes numériques.

- Les opérateurs d'expressions régulières étendus REGEXP et NOT REGEXP.

- CONCAT() et CHAR() avec un argument ou plus de deux arguments. Avec le serveur MySQL, ces fonctions peuvent prendre n'importe quel nombre d'arguments.

- Les fonctions BIT_COUNT(), CASE, ELT(), FROM_DAYS(), FORMAT(), IF(), PASSWORD(), ENCRYPT(), MD5(), ENCODE(), DECODE(), PERIOD_ADD(), PERIOD_DIFF(), TO_DAYS() et WEEKDAY().

- L'utilisation de la fonction TRIM() pour réduire les chaînes. L'ANSI SQL ne supporte que les suppressions de caractères uniques.

- Les fonctions de groupe de la clause GROUP BY STD(), BIT_OR(), BIT_AND(), BIT_XOR() et GROUP_CONCAT(). Voir Section 12.9, « Fonctions et options à utiliser dans les clauses GROUP BY ».

Pour une liste hiérarchisée des nouvelles extensions qui seront ajoutées à MySQL, vous pouvez consulter la liste de tâches en ligne sur http://dev.mysql.com/doc/mysql/en/TODO.html. C'est la dernière liste qui est utilisée dans ce formulaire. Voir Section B.8, « Les évolutions de MySQL (la liste des tâches) ».

1-5-5 - Différences entre MySQL et le standard SQL-92

Nous tâchons de rendre le serveur MySQL compatible avec le standard ANSI SQL, et le standard ODBC SQL, mais dans certains cas, MySQL se comporte différemment.

- Pour les colonnes de type VARCHAR, les espaces terminaux sont supprimés lors du stockage de la valeur. Voir Section 1.5.7, « Erreurs connues, et limitations de MySQL ».

- Dans certains cas, les colonnes CHAR sont transformées automatiquement en colonnes VARCHAR. Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

- Les droits d'un utilisateur sur une table ne sont pas supprimés si la table est détruite. Vous devez explicitement utiliser la commande REVOKE pour supprimer les droits d'un utilisateur sur une table. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

1-5-5-1 - Sous-requêtes

MySQL 4.1 supporte les sous-requêtes et les tables dérivées (vues anonymes). Une « sous-requête » est une commande SELECT imbriquée dans une autre commande. Une « table dérivée » (vues anonymes) est une sous-requête placée dans une clause FROM d'une autre commande. Voir Section 13.1.8, « Sous-sélections (SubSELECT) ».

Pour les versions de MySQL antérieures à la 4.1, la plupart des sous-requêtes peuvent être réécrites avec des jointures et d'autres méthodes. Voyez Section 13.1.8.11, « Se passer des sous-requêtes avec les premières versions de MySQL » pour des exemples d'illustration.

1-5-5-2 - SELECT INTO TABLE

Le serveur MySQL ne supporte pas encore l'extension Oracle SQL : SELECT ... INTO TABLE .... À la place, le serveur MySQL supporte la syntaxe ANSI SQL INSERT INTO ... SELECT ..., qui revient au même. Voir Section 13.1.4.1, « Syntaxe de INSERT ... SELECT ».

INSERT INTO tblTemp2 (fldID)
SELECT tblTemp1.fldOrder_ID
FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;

Alternativement, vous pouvez utiliser SELECT INTO OUTFILE... et CREATE TABLE ... SELECT.

Depuis la version 5.0, MySQL supporte SELECT ... INTO avec les variables serveur. La même syntaxe peut aussi être utilisée dans les procédures stockées, en utilisant les curseurs et les variables locales. Voir Section 19.2.9.3, « Syntaxe de SELECT ... INTO ».

1-5-5-3 - Transactions et opérations atomiques

Le serveur MySQL (version 3.23 MySQL-max et toutes les versions 4.0 et plus récent) supporte les transactions avec les gestionnaires de tables InnoDB et BDB. InnoDB dispose aussi de la compatibilité ACID totale. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

Toutefois, les tables non transactionnelles de MySQL telles que MyISAM exploitent un autre concept pour assurer l'intégrité des données, appelé « opérations atomiques ». Les opérations atomiques disposent d'une bien meilleure protection des données pour des performances également accrues. Comme MySQL supporte les deux méthodes, l'utilisateur est capable de choisir celle qui correspond à ses besoins, suivant qu'il a besoin de vitesse ou de sécurité. Ce choix peut être fait table par table.

Comment exploiter les capacités de MySQL pour protéger l'intégrité des données, et comment ces fonctionnalités se comparent-elles avec les méthodes transactionnelles ?

1. En mode transactionnel, si votre application a été écrite en dépendant de l'appel de ROLLBACK au lieu de COMMIT dans les situations critiques, les transactions sont plus pratiques. Les transactions s'assurent que les modifications non achevées ou les activités corrosives ne sont pas archivées dans la base. Le serveur a l'opportunité d'annuler automatiquement l'opération, et votre base de données est sauve.

Le serveur MySQL, dans la plupart des cas, vous permet de résoudre les problèmes potentiels en incluant de simples vérifications avant les modifications, et en exécutant des scripts simples pour vérifier l'intégrité de vos bases de données, ainsi que les incohérences, et pour réparer automatiquement les problèmes, ou encore vous alerter si une erreur est identifiée. Notez qu'en utilisant simplement le log de MySQL, ou en utilisant un log supplémentaire, vous pouvez normalement réparer à la perfection toutes les tables, sans aucune perte de données.

2. Souvent, les modifications de données transactionnelles fatales peuvent être réécrites de manière atomique. En général, tous les problèmes d'intégrité que les transactions résolvent peuvent être corrigés avec la commande LOCK TABLES ou des modifications atomiques, qui assurent que vous n'aurez jamais d'annulation automatique de la base, ce qui est un problème commun des bases transactionnelles.

3. Même un système transactionnel peut perdre des données si le serveur s'arrête. La différence entre les systèmes repose alors dans ce petit laps de temps où ils peuvent perdre des données. Aucun système n'est sécurisé à 100 %, mais simplement « suffisamment sécurisé ». Même Oracle, réputé pour être la plus sûre des bases de données transactionnelles, est montré du doigt pour perdre des données dans ces situations.

Pour être tranquille avec MySQL, que vous utilisiez les tables transactionnelles ou pas, vous n'avez besoin que de sauvegardes et de logs de modifications. Avec ces deux outils, vous pourrez vous protéger de toutes les situations que vous pourriez rencontrer avec d'autres bases de données transactionnelles. De toute manière, il est bon d'avoir des sauvegardes, indépendamment de la base que vous utilisez.

La méthode transactionnelle a ses avantages et ses inconvénients. De nombreux utilisateurs et développeurs d'applications dépendent de la facilité de pallier un problème lorsqu'une annulation semble nécessaire ou presque. Cependant, même si vous êtes néophyte des opérations atomiques, ou plus familier avec les transactions, prenez en considération le gain de vitesse que les tables non transactionnelles offrent. Ces gains vont de 3 à 5 fois la vitesse des tables transactionnelles les plus rapides et les mieux optimisées.

Dans des situations où l'intégrité est de la plus grande importance, le serveur MySQL assure une intégrité du niveau des transactions, ou encore mieux avec les tables non transactionnelles. Si vous verrouillez les tables avec LOCK TABLES, toutes les modifications seront bloquées jusqu'à ce que la vérification d'intégrité soit faite (à comparer avec un verrou en écriture), les lectures et insertions sont toujours possibles. Les nouvelles lignes ne seront pas accessibles en lecture tant que le verrou n'aura pas été levé. Avec INSERT DELAYED, vous pouvez faire attendre les insertions dans une pile, jusqu'à ce que les verrous soient levés, sans que le client n'attende cette levée de verrou. Voir Section 13.1.4.2, « Syntaxe de INSERT DELAYED ».

« Atomique », avec le sens que nous lui donnons, n'a rien de magique. Ce terme signifie simplement que vous pouvez être certain que lorsque vous modifiez des données dans une table, aucun autre utilisateur ne peut interférer avec votre opération, et qu'il n'y aura pas d'annulation automatique (ce qui pourrait arriver avec des tables transactionnelles si nous ne sommes pas trop soigneux). Le serveur MySQL garantit aussi qu'il n'y aura pas de lectures erronées.

Voici quelques techniques pour travailler avec des tables non transactionnelles :

- les boucles qui requièrent les transactions peuvent normalement être implémentées avec la commande LOCK TABLES, et vous n'avez nul besoin de curseur lorsque vous modifiez des lignes à la volée ;

- pour éviter d'utiliser l'annulation ROLLBACK, vous pouvez adopter la stratégie suivante :

1. Utilisez la commande LOCK TABLES ... pour verrouiller toutes les tables que vous voulez utiliser,

2. Testez vos conditions,

3. Modifiez si tout est correct,

4. Utilisez UNLOCK TABLES pour libérer vos tables.

Ceci est probablement une méthode bien plus rapide que ne le proposent les transactions, avec des annulations ROLLBACK possibles mais pas certaines. La seule situation que ce cas ne prend pas en compte est l'interruption du processus au milieu d'une mise à jour. Dans ce cas, tous les verrous seront levés, mais certaines modifications peuvent ne pas avoir été exécutées ;

- vous pouvez aussi utiliser des fonctions pour modifier des lignes en une seule opération. Vous pouvez créer une application très efficace en utilisant cette technique :

- modifiez les champs par rapport à leur valeur actuelle ;

- modifiez uniquement les champs que vous avez réellement changés.

Par exemple, lorsque nous modifions les données d'un client, nous ne modifions que les données du client qui ont changé et nous vérifions uniquement si les données modifiées ou les données qui en dépendent ont changé comparativement aux données originales. Les tests sur les données modifiées sont faits avec la clause WHERE dans la commande UPDATE. Si la ligne a été modifiée, nous indiquons au client : "Some of the data you have changed has been changed by another user". En français : "certaines données que vous voulez modifier ont été modifiées par un autre utilisateur". Puis nous affichons l'ancienne ligne et la nouvelle ligne, pour laisser l'utilisateur décider quelle version il veut utiliser.

Cela nous conduit à un résultat proche du verrouillage de ligne, mais en fait, c'est bien mieux, car nous ne modifions que les colonnes qui en ont besoin, en utilisant des valeurs relatives. Cela signifie qu'une commande UPDATE typique ressemble à ceci :

UPDATE tablename SET pay_back=pay_back+'relative change';

UPDATE customer
SET
customer_date='current_date',
address='new address',
phone='new phone',
dette=dette+'emprunt'
WHERE
customer_id=id AND address='old address' AND phone='old phone';

Comme vous pouvez le voir, c'est très efficace, et fonctionne même si un autre client a modifié la valeur pay_back ou dette ;

- dans de nombreuses situations, les utilisateurs ont souhaité les commandes ROLLBACK et/ou LOCK TABLES afin de gérer des identifiants uniques pour certaines tables. Ils peuvent être gérés bien plus efficacement en utilisant une colonne de type AUTO_INCREMENT, en corrélation avec la fonction LAST_INSERT_ID() ou la fonction C mysql_insert_id(). Voir Section 12.8.3, « Fonctions d'informations ». Voir Section 24.2.3.33, « mysql_insert_id() ».

Vous pouvez éviter le verrouillage de ligne. Certaines situations le requièrent vraiment, mais elles sont rares. Les tables InnoDB supportent le verrouillage de ligne. Avec les tables MyISAM, vous pouvez utiliser une colonne de type sémaphore, et faire ceci :

UPDATE tbl_name SET row_flag=1 WHERE id=ID;

MySQL retournera 1 pour le nombre de lignes affectées si la ligne a été trouvée, car row_flag ne vaut pas déjà 1 dans la ligne originale.

Vous pouvez comprendre la requête ci-dessus comme si le serveur MySQL avait utilisé la commande suivante :

UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;

1-5-5-4 - Procédures stockées et triggers

Les procédures stockées sont implémentées en version 5.0. Voir Chapitre 19, Procédures stockées et fonctions.

Un trigger est une procédure stockée qui est activée lorsqu'un événement particulier survient. Par exemple, vous pouvez installer une procédure stockée qui est déclenchée dès qu'une ligne est effacée dans une table d'achat, pour que le client soit automatiquement effacé si tous ses achats sont effacés.

1-5-5-5 - Les clés étrangères

En MySQL version 3.23.44 et plus récentes, les tables InnoDB supportent les vérifications d'intégrité référentielles. Voir Chapitre 15, Le moteur de tables InnoDB. Pour les autres types de tables, le serveur mySQL accepte la syntaxe FOREIGN KEY dans la commande CREATE TABLE, mais ne la prend pas en compte.

Pour les autres moteurs de stockage que InnoDB, MySQL analyse la clause FOREIGN KEY de la commande CREATE TABLE, mais ne l'utilise pas et ne la stocke pas. Dans le futur, l'implémentation va stocker cette information dans le fichier de spécifications de tables, pour qu'elle puisse être lue par mysqldump et ODBC. Ultérieurement, les contraintes de clés étrangères seront incluses dans les tables MyISAM.

Voici des avantages aux contraintes de clés étrangères :

- en supposant que les relations soient proprement conçues, les clés étrangères rendent plus difficile pour un programmeur d'insérer des valeurs incohérentes dans la base ;

- la vérification centralisée de contraintes par le serveur de base de données rend inutile l'application de ces vérifications du côté de l'application. Cela élimine la possibilité que d'autres applications ne fassent pas les vérifications de la même façon que les autres ;

- l'utilisation des modifications et effacement en cascade simplifient le code du client ;

- les règles de clés étrangères proprement conçues aident à la documentation des relations entre les tables.

Gardez bien en tête que ces avantages ont un coût supérieur pour le serveur de base, qui doit effectuer les tests. Les vérifications supplémentaires affectent les performances, ce qui est parfois suffisamment rebutant pour des applications qui les éviteront. Certaines applications commerciales ont placé la logique de vérification dans l'application, pour cette raison.

MySQL donne aux développeurs de bases de données le choix de leur approche. Si vous n'avez pas besoin des clés étrangères, et que vous voulez éviter leur surcoût, vous pouvez choisir un autre type de table, comme MyISAM. Par exemple, les tables MyISAM sont extrêmement rapides pour les applications qui font essentiellement des opérations INSERT et SELECT, car elles peuvent être utilisées simultanément. Voir Section 7.3.2, « Problème de verrouillage de tables ».

Si vous décidez de ne pas tirer avantage des contraintes d'intégrité, vous devez garder en tête ces conseils :

- en l'absence de vérification du côté du serveur, l'application doit se charger de ces vérifications. Par exemple, elle doit s'assurer que les lignes sont insérées dans le bon ordre, et que les lignes ne sont pas orphelines. Il faut aussi pouvoir rattraper une erreur au milieu d'une opération multiple ;

- si la clause ON DELETE est la seule fonctionnalité nécessaire, notez que depuis MySQL version 4.0, vous pouvez utiliser des commandes DELETE multitables pour effacer les lignes dans plusieurs tables en une seule commande. Voir Section 13.1.1, « Syntaxe de DELETE » ;

- un palliatif au manque de ON DELETE est d'ajouter la commande DELETE appropriée lorsque vous effacez des lignes dans une table qui dispose d'une clé étrangère. En pratique, c'est souvent plus rapide que d'utiliser les clés étrangères, et c'est plus portable.

Soyez conscient que l'utilisation des clés étrangères dans certaines circonstances peut conduire à des problèmes :

- les clés étrangères règlent des problèmes de cohérence, mais il est nécessaire de concevoir les contraintes correctement, pour éviter les contraintes circulaires, ou des cascades d'effacements incorrects ;

- il n'est pas exceptionnel pour un administrateur de créer une topologie de relations qui rende difficile la restauration de bases à partir d'une sauvegarde. MySQL résout ce problème en vous permettant de désactiver temporairement les contraintes. Voir Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ». Depuis MySQL 4.1.1, mysqldump génère un fichier d'export qui exploite cette possibilité de désactivation automatique à l'import.

Notez que les clés étrangères SQL sont utilisées pour assurer la cohérence des données, et non pas pour joindre des tables. Si vous voulez obtenir des résultats de tables multiples dans une commande SELECT, vous devez le faire avec une jointure :

SELECT * FROM t1, t2 WHERE t1.id = t2.id;

Voir Section 13.1.7.1, « Syntaxe de JOIN ». Voir Section 3.6.6, « Utiliser les clefs étrangères ».

La syntaxe FOREIGN KEY sans ON DELETE ... est souvent utilisée par les applications ODBC pour produire automatiquement des clauses WHERE.

1-5-5-6 - Les vues

Il est prévu d'implémenter les vues dans la version 5.0 ou 5.1 du serveur MySQL.

Historiquement, MySQL a été utilisé dans des applications et sur les systèmes Web, où l'auteur de l'application a un contrôle complet sur le système de base de données. L'utilisation a évolué au cours du temps, et de nombreux utilisateurs pensent maintenant que c'est important.

Les vues anonymes (tables dérivées, une sous-requête de la clause FROM de la commande SELECT) sont déjà disponibles en version 4.1.

Les vues sont la plupart du temps utiles pour donner accès aux utilisateurs à un ensemble de relations représentées par une table (en mode inaltérable). Beaucoup de bases de données SQL ne permettent pas de mettre à jour les lignes dans une vue, vous devez alors faire les mises à jour dans les tables séparées. Voir Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

De nombreuses bases ne permettent pas les modifications de vues, mais permettent les mises à jour dans des tables individuelles. Lors de la conception de notre système de vues, nous envisageons le support complet de la règle « numéro 6 de Codd » (autant que possible en SQL) : toutes les vues qui sont théoriquement modifiables, et doivent l'être en pratique.

1-5-5-7 - '--' comme début de commentaire

Certaines bases de données SQL utilisent '--' comme début de commentaire. Le serveur MySQL utilise '#'. Vous pouvez aussi utiliser la syntaxe du langage C /* ceci est un commentaire */. Voir Section 9.5, « Syntaxe des commentaires ».

MySQL version 3.23.3 et plus récent supporte les commentaires de type '--', si ce commentaire est suivi d'un espace. Ceci est dû au fait que ce type de commentaire a causé beaucoup de problèmes avec les requêtes générées automatiquement, qui contiennent du code tel que celui-ci, où nous insérons automatiquement la valeur du paiement dans la table !payment! :

UPDATE tbl_name SET credit=credit-!payment!

Pensez à ce qui se passe lorsque la valeur de payment est négative, comme -1 :

UPDATE account SET credit=credit--1

credit--1 est une expression légale en SQL mais -- est interprété comme un commentaire et la fin de l'expression est ignorée. Le résultat est que la commande prend une signification complètement différente :

UPDATE account SET credit=credit

La commande ne produit aucun changement ! Cela montre que l'utilisation des commentaires de type '--' peuvt avoir des conséquences graves.

En utilisant notre implémentation des commentaires avec le serveur MySQL version 3.23.3 et plus récent, 1-- ceci est un commentaire ne pose pas ce type de problème.

Une autre fonctionnalité supplémentaire est que le client en ligne de commande mysql supprime toutes les lignes qui commencent par '--'.

Les informations suivantes sont destinées aux utilisateurs de MySQL avec des versions antérieures à la version 3.23.3.

Si vous avez un programme SQL dans un fichier texte qui contient des commentaires au format '--', il est recommandé d'utiliser l'utilitaire replace pour assurer la conversion en caractères '#' :

shell> replace " --" " #" < text-file-with-funny-comments.sql \
| mysql database

au lieu du classique :

shell> mysql database < text-file-with-funny-comments.sql

Vous pouvez aussi éditer le fichier de commande « lui-même » pour remplacer les commentaires '--' par des commentaires '#' :

shell> replace " --" " #" -- text-file-with-funny-comments.sql

Puis, rétablissez-les avec :

shell> replace " #" " --" -- text-file-with-funny-comments.sql

1-5-6 - Comment MySQL gère les contraintes

Comme MySQL permet de travailler avec des moteurs de tables transactionnelles ou pas, les contraintes sont gérées un peu différemment sur MySQL que sur les autres bases de données.

Nous devons gérer le cas où vous avez modifié beaucoup de lignes avec une table non transactionnelle, qui ne peut annuler les modifications en cas d'erreur.

La philosophie de base est d'essayer de détecter autant d'erreurs que possible au moment de la compilation, mais d'essayer de réparer les erreurs à l'exécution. Nous y arrivons dans la plupart des cas, mais pas tout le temps. Voir Section B.8.3, « Ce qui doit être fait dans un futur proche ».

La solution de base de MySQL est d'interrompre la commande au milieu, ou de faire de son mieux pour réparer le problème et continuer.

Voici ce qui se passe dans les différents types de contraintes.

1-5-6-1 - Contrainte avec PRIMARY KEY / UNIQUE

Normalement, vous allez obtenir une erreur lorsque vous essayerez d'insérer INSERT ou modifier UPDATE une ligne qui causera une violation de clé primaire, unique ou étrangère. Si vous utilisez un moteur transactionnel, comme InnoDB, MySQL va immédiatement annuler la transaction. Si vous utilisez un moteur non transactionnel, MySQL va s'arrêter à la mauvaise ligne, et laisser les dernières lignes intactes.

Pour rendre la vie plus facile, MySQL a ajouté le support de l'option IGNORE aux commandes qui peuvent rencontrer un problème de clé (comme INSERT IGNORE ...). Dans ce cas, MySQL va ignorer les problèmes de clé et la ligne, et continuer à traiter les lignes suivantes. Vous pouvez obtenir la liste des alertes avec la fonction mysql_info() et, dans les prochaines versions de MySQL 4.1, vous pourrez aussi les voir avec la commande SHOW WARNINGS. Voir Section 24.2.3.31, « mysql_info() ». Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

Notez que pour le moment, seules les tables InnoDB supportent les clés étrangères. Voir Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ». Le support des clés étrangères des tables MyISAM est prévu pour la version 5.0.

1-5-6-2 - Contraintes sur les valeurs invalides

Pour être capables de supporter facilement les tables non transactionnelles, tous les champs de MySQL ont des valeurs par défaut.

Si vous insérez une valeur « invalide » dans une colonne, comme NULL dans une colonne NOT NULL, ou une valeur numérique trop grande dans une colonne numérique, MySQL inscrit dans la colonne la « meilleure valeur possible », sans produire d'erreur :

- si vous stockez un chiffre hors de l'intervalle de validité d'une colonne numérique, MySQL stocke à la place zéro, la plus petite valeur possible, ou bien la plus grande valeur possible ;

- pour les chaînes, MySQL stocke la chaîne vide ou bien la plus grande chaîne qui peut être stockée dans cette colonne ;

- si vous essayez de stocker une chaîne qui ne commence pas par un chiffre dans une colonne numérique, MySQL stocke 0 ;

- si vous essayez de stocker NULL dans une colonne qui n'accepte pas la valeur NULL, MySQL stocke 0 ou '' (la chaîne vide). Ce dernier comportement peut, pour des insertions de ligne unique, être modifié par l'option de compilation -DDONT_USE_DEFAULT_FIELDS. Voir Section 2.4.2, « Options habituelles de configure ». Cela fait que les commandes INSERT génèreront une erreur à moins que vous ne spécifiiez explicitement les valeurs pour toutes les colonnes qui requièrent une valeur non NULL ;

- MySQL vous permet de stocker des dates incorrectes dans les colonnes de type DATE et DATETIME (comme '2000-02-31' ou '2000-02-00'). L'idée est que ce n'est pas le travail du serveur SQL de valider les dates. Si MySQL peut stocker une valeur et relire exactement la même valeur, MySQL la stockera. Si la date est totalement erronée (hors de l'intervalle de validité), la valeur spéciale '0000-00-00' est stockée dans la colonne.

La raison de cette règle ci-dessus est que nous ne pouvons pas vérifier ces conditions avant que la requête ne soit exécutée. Si nous rencontrons un problème après la modification de quelques lignes, nous ne pourrons pas annuler la modification, car la table ne le supporte peut-être pas. L'alternative qui consiste à s'arrêter n'est pas envisageable non plus, car nous aurions alors fait la moitié du travail, ce qui sera alors le pire scénario. Dans ce cas, il vaut mieux faire « du mieux possible », et continuer comme si de rien n'était arrivé. En MySQL 5.0, nous envisageons d'améliorer cela en fournissant des alertes de conversions automatiques, ainsi qu'une option pour vous permettre d'annuler la commande si elle n'utilise que des tables transactionnelles.

Ceci signifie qu'il ne faut pas compter sur MySQL pour vérifier le contenu des champs, mais de gérer cela au niveau de l'application.

1-5-6-3 - Constante avec ENUM et SET

En MySQL 4.x ENUM n'est pas une véritable contrainte, mais simplement un moyen plus efficace de stocker des champs qui peuvent prendre un nombre limité de valeurs différentes. C'est la même raison pour laquelle NOT NULL n'est pas respecté.

Si vous insérez une valeur invalide dans un champ ENUM, la colonne prendra la valeur réservée 0, qui sera représentée par une chaîne vide, en mode chaîne. Voir Section 11.4.4, « Le type ENUM ».

Si vous insérez une mauvaise option dans un ensemble SET, la valeur sera ignorée. Voir Section 11.4.5, « Le type SET ».

1-5-7 - Erreurs connues et limitations de MySQL

1-5-7-1 - Erreurs connues en 3.23 et corrigées ultérieurement

Les erreurs suivantes sont connues, mais restent non corrigées en MySQL3.23, car pour les corriger, il nous faudrait modifier trop de code : cela risquerait d'introduire des bogues bien pires. Ces bogues sont considérés comme « non nuisibles » ou « supportables ».

- Il est possible de rencontrer un blocage en utilisant la commande LOCK TABLE sur de multiples tables, puis, avec la même connexion, faire un DROP TABLE sur l'une d'entre elles, alors qu'un autre thread essaie de verrouiller la table. Il est toutefois possible d'utiliser la commande KILL sur l'un des threads en question, pour résoudre ce problème. Corrigé en 4.0.12.

- SELECT MAX(key_column) FROM t1,t2,t3... où l'une des tables est vide ne retourne pas NULL, mais plutôt la valeur maximale de la colonne. Corrigé en 4.0.11.

- DELETE FROM heap_table sans clause WHERE ne fonctionne pas sur une table HEAP.

1-5-7-2 - Erreurs de la version 4.0, corrigées plus tard

Voici la liste des bogues/erreurs qui ne sont pas corrigés en MySQL 4.0, car cette correction prendrait trop de manipulations, qui risqueraient d'introduire encore d'autres bogues. Les bogues sont aussi classés comme « non fatals » ou « supportables ».

- Dans une UNION, le premier SELECT définit le type, et les propriétés max_length et NULL pour les colonnes du résultat. En MySQL 4.1.1, ces propriétés sont définies comme la combinaison de toutes les parties de l'UNION.

- Dans une commande DELETE sur de nombreuses tables, vous ne pouvez pas utiliser les alias pour effacer dans une table. Ceci est corrigé en MySQL 4.1.

- Vous ne pouvez pas mélanger des clauses UNION ALL et UNION DISTINCT dans la même requête. Si vous utilisez l'option ALL dans une des clauses UNION, elle est utilisée pour toutes ces clauses.

1-5-7-3 - Erreurs de la version 4.1 corrigées dans d'autres versions de MySQL

Les erreurs suivantes sont des erreurs connues ou bogues qui n'ont pas été corrigés en MySQL 4.1, car leur correction imposerait des modifications trop importantes au code, et conduirait à l'introduction potentielle de bogues bien pires. Ces bogues sont classés comme « non fatals » ou « tolérables ».

- VARCHAR et VARBINARY suppriment les espaces de fin de chaîne. (Corrigé en version 5.0.3.)

1-5-7-4 - Bogues connus/limitations de MySQL

Les problèmes suivants sont connus, et sont en tête de liste pour être corrigés :

- il n'est pas possible de mélanger UNION ALL et UNION DISTINCT dans la même requête. Si vous utilisez ALL pour UNION alors il faut l'utiliser partout ;

- si un utilisateur a une transaction longue, et qu'un autre utilisateur efface une table qui est modifiée par la même transaction, il y a quelques chances que le log binaire n'enregistre pas la commande DROP TABLE avant que la table ne soit utilisée par la transaction elle-même. Nous envisageons de corriger cela en version 5.0, en forçant DROP TABLE à attendre jusqu'à ce que la table ne soit plus utilisée par la transaction ;

- lors de l'insertion d'un grand entier (valeur entre 2^63 et 2^64-1) dans une colonne de type décimal ou chaîne, il sera enregistré comme une valeur négative, car le nombre est considéré comme un entier signé dans ce contexte. Il est prévu de corriger cela en 4.1 ;

- FLUSH TABLES WITH READ LOCK ne bloque pas CREATE TABLE ou COMMIT, ce qui peut causer des problèmes avec la position du log lors d'une sauvegarde complète des tables et du log binaire ;

- ANALYZE TABLE sur une table de type BDB, peut rendre la table inutilisable, dans certains cas, jusqu'au prochain redémarrage de mysqld. Lorsque cela survient, vous rencontrez les erreurs suivantes dans le fichier d'erreur MySQL :

001207 22:07:56  bdb:  log_flush: LSN past current end-of-log

- MySQL accepte les parenthèses dans la clause FROM, mais les ignore silencieusement. La raison de l'absence d'erreur est que de nombreux clients qui génèrent des requêtes ajoutent les parenthèses dans la clause FROM même si elles sont inutiles ;

- concaténer plusieurs RIGHT JOINS ou combiner des jointures LEFT et RIGHT dans la même requête ne donnera pas de résultat correct si MySQL ne génère que des lignes NULL pour la table précédant le LEFT ou avant la jointure RIGHT. Cela sera corrigé en 5.0, en même temps que le support des parenthèses pour la clause FROM ;

- n'exécutez pas de commande ALTER TABLE sur une table BDB sur laquelle vous avez exécuté des transactions à plusieurs commandes, jusqu'à ce que ces transactions soient achevées : la transaction sera probablement ignorée ;

- ANALYZE TABLE, OPTIMIZE TABLE et REPAIR TABLE peuvent causer des problèmes sur les tables avec lesquelles vous utilisez la commande INSERT DELAYED ;

- faire un LOCK TABLE ... et FLUSH TABLES ... ne vous garantit pas qu'il n'y a pas une transaction en cours sur la table ;

- les tables BDB sont lentes à ouvrir. Si vous avez de nombreuses tables BDB dans une base, cela prendra du temps au client mysql pour accéder à la base si vous n'utilisez pas l'option -A, ou si vous utilisez la commande rehash. C'est particulièrement vrai si vous n'avez pas de cache de table important ;

- la réplication utilise un log de niveau requête : le maître écrit les requêtes exécutées dans le log binaire. C'est une méthode de log rapide, compacte et efficace, qui fonctionne à la perfection dans la plupart des situations. Même si nous n'avons jamais vu d'occurrence de ce problème, il est théoriquement possible pour les données du maître et de l'esclave de différer si une requête non déterministe est utilisée pour modifier les données, c'est-à-dire si elle est laissée au bon vouloir de l'optimiseur, ce qui n'est pas une bonne pratique même sans la réplication. Par exemple :

- des commandes CREATE ... SELECT ou INSERT ... SELECT qui insèrent zéro ou NULL valeurs dans la colonne AUTO_INCREMENT ;

- DELETE si vous effacez des lignes dans une table qui a une propriété ON DELETE CASCADE ;

- les commandes REPLACE ... SELECT, INSERT IGNORE ... SELECT, si vous avez des clés en double, dans les données insérées.

IF et seulement si ces requêtes n'ont pas de clause ORDER BY, qui garantisse un ordre déterministe.

Effectivement, par exemple, pour les commandes INSERT ... SELECT sans clause ORDER BY, le SELECT peut retourner les lignes dans un ordre différent, ce qui aura pour résultat de donner des rangs différents et donnera des numéros d'identifiants différents aux colonnes auto_increment), en fonction des choix faits par les optimiseurs du maître et de l'esclave. Une requête sera optimisée différemment sur l'esclave et sur le maître si :

- les fichiers utilisés par les deux requêtes ne sont pas exactement les mêmes. Par exemple, OPTIMIZE TABLE a été exécuté sur le maître et pas sur l'esclave (pour corriger cela, depuis MySQL 4.1.1, OPTIMIZE, ANALYZE et REPAIR sont aussi écrits dans le log binaire) ;

- la table est stockée sur un moteur de stockage différent sur le maître et sur l'esclave : c'est possible d'utiliser des moteurs de tables différents. Par exemple, pour le maître utiliser InnoDB et pour l'esclave MyISAM, car l'esclave a moins d'espace disque ;

- les tailles de buffer MySQL (key_buffer_size, etc.) sont différentes sur le maître et sur l'esclave ;

- le maître et l'esclave utilisent des versions différentes de MySQL, et le code de l'optimiseur est différent entre ces versions.

Ce problème peut aussi affecter la restauration de bases, utilisant mysqlbinlog ou mysql.

Le plus simple pour éviter ces problèmes dans tous les cas est d'ajouter toujours une clause ORDER BY aux requêtes non déterministes, pour s'assurer que les lignes sont traitées dans le même ordre. Dans le futur, MySQL va ajouter automatiquement une clause ORDER BY si nécessaire ;

Les problèmes suivants sont connus et seront corrigés en leur temps :

- mysqlbinlog n'efface pas les fichiers temporaires laissés après une commande LOAD DATA INFILE. Voir Section 8.5, « mysqlbinlog, Exécuter des requêtes dans le log binaire » ;

- il n'est pas possible de renommer une table temporaire ;

- lors de l'utilisation de la fonction RPAD, ou de toute autre fonction de chaîne qui peut ajouter des espaces à droite de la chaîne, dans une requête qui utilise une table temporaire pour la résolution, alors toutes les chaînes verront leurs espaces terminaux être supprimés. Voici un exemple d'une telle requête :

SELECT RPAD(t1.field1, 50, ' ') AS f2, RPAD(t2.field2, 50, ' ') AS f1
FROM table1 as t1
LEFT JOIN table2 AS t2 ON t1.record=t2.joinID
ORDER BY t2.record;

Le résultat final de ceci est que vous ne pourrez pas obtenir les espaces à gauche dans ces chaînes.

Le comportement décrit ci-dessus existe dans toutes les versions de MySQL.

La raison à cela est due au fait que les tables de type HEAP, qui sont utilisées en premier comme tables temporaires, ne sont pas capables de gérer des colonnes de type VARCHAR.

Ce comportement sera corrigé dans l'une des versions de la série des 4.1 ;

- à cause de la méthode de stockage des tables de définition de fichiers, il n'est pas possible d'utiliser le caractère 255 (CHAR(255)) dans les noms des tables, colonnes ou énumérations. Il est prévu de corriger de problème dans les versions version 5.1, lorsque nous aurons établi un nouveau format de définition des fichiers ;

- lorsque vous utilisez la commande SET CHARACTER SET, il n'est pas possible d'utiliser les caractères traduits dans les noms de bases, de tables ou de colonnes ;

- il n'est pas possible d'utiliser _ ou % avec la commande ESCAPE dans la clause LIKE... ESCAPE ;

- si vous avez une colonne de type DECIMAL avec un nombre stocké dans un autre format (+01.00, 1.00, 01.00), GROUP BY peut considérer ces valeurs comme différentes ;

- lorsque DELETE FROM merge_table est utilisé sans la clause WHERE, elle va simplement effacer le fichier de la table, et ne pas effacer les tables associées ;

- vous ne pouvez pas compiler le serveur dans un autre dossier lorsque vous utilisez les MIT-pthreads. Comme cela requiert une modification des MIT-pthreads, nous ne corrigerons pas ce problème. Voir Section 2.4.5, « Notes relatives aux MIT-pthreads » ;

- les valeurs de type BLOB ne peuvent pas être utilisées « correctement » dans les clauses GROUP BY ou ORDER BY ou DISTINCT. Seuls, les max_sort_length premiers octets (par défaut, 1024) seront utilisés pour les comparaisons de BLOB. Ceci peut être modifié avec l'option -O max_sort_length de mysqld. Un palliatif à ce problème est d'utiliser une sous-partie de chaîne : SELECT DISTINCT LEFT(blob,2048) FROM tbl_name ;

- les calculs sont faits avec des BIGINT ou DOUBLE (les deux sont normalement de 64 bits). La précision dépend alors de la fonction utilisée. La règle générale est que les fonctions de bits utilisent la précision des BIGINT, IF et ELT() utilisent la précision des BIGINT ou DOUBLE, et les autres utilisent la précision des DOUBLE. Il faut donc éviter d'utiliser les entiers non signés de grande taille, surtout s'ils dépassent la taille de 63 bits (9223372036854775807) pour toute autre fonction que les champs de bits ! La version 4.0 gère bien mieux les BIGINT que la 3.23 ;

- toutes les colonnes de type chaîne, hormis les BLOB et TEXT, voient automatiquement leurs caractères blancs finals supprimés. Pour le type CHAR c'est correct, et c'est considéré comme une fonctionnalité par la norme ANSI SQL92. Le hic est que pour le serveur MySQL les colonnes VARCHAR sont traitées de la même façon ;

- vous ne pouvez avoir que des colonnes de taille 255 pour les ENUM et SET ;

- avec les fonctions d'agrégation MIN(), MAX() et compagnie, MySQL compare actuellement les colonnes de type ENUM et SET par leur valeur de chaîne, plutôt que par leur position relative dans l'ensemble ;

- safe_mysqld redirige tous les messages de mysqld vers le log mysqld. Le problème est que si vous exécutez mysqladmin refresh pour fermer et ouvrir à nouveau l'historique, stdout et stderr sont toujours redirigés vers l'ancien log. Si vous utilisez --log, vous devriez éditer safe_mysqld pour envoyer les messages vers 'hostname'.err au lieu de 'hostname'.log, de façon à pouvoir facilement récupérer la place de l'ancien log, en effaçant les vieux, et en exécutant mysqladmin refresh ;

- dans la commande UPDATE, les colonnes sont modifiées de gauche à droite. Si vous faites référence à une colonne modifiée, vous obtiendrez sa valeur modifiée, plutôt que sa valeur originale. Par exemple :

mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;

Cette commande va modifier la colonne KEY avec 2 au lieu de 1 ;

- vous ne pouvez pas utiliser les tables temporaires plus d'une fois dans la même requête. Par exemple, cette commande ne fonctionne pas :

mysql> SELECT * FROM temporary_table, temporary_table AS t2;

- RENAME ne fonctionne pas avec les tables TEMPORARY, ou les tables utilisées dans un rassemblement (MERGE) ;

- l'optimiseur peut gérer la clause DISTINCT différemment si vous utilisez des colonnes cachées dans une jointure. Dans une jointure, les colonnes cachées sont comptées comme une partie du résultat (même si elles ne sont pas montrées), tandis que dans les requêtes normales, les colonnes cachées ne participent pas aux DISTINCT. Nous allons probablement modifier ceci dans le futur, pour ne jamais exploiter les colonnes cachées avec DISTINCT.

Voici un exemple :

SELECT DISTINCT mp3id FROM band_downloads
WHERE userid = 9 ORDER BY id DESC;

et

SELECT DISTINCT band_downloads.mp3id
FROM band_downloads,band_mp3
WHERE band_downloads.userid = 9
AND band_mp3.id = band_downloads.mp3id
ORDER BY band_downloads.id DESC;

Dans le second cas, MySQL 3.23.x pourrait vous donner deux lignes identiques dans le résultat (car les lignes cachées id diffèrent).

Notez que cela n'arrive que pour les requêtes où vous n'avez pas de colonne de la clause ORDER BY dans le résultat, ce que vous ne pourriez pas faire en ANSI SQL ;

- comme le serveur MySQL vous permet de travailler avec des tables qui ne supportent pas les transactions, et donc, l'annulation rollback, certains comportements sont différents avec MySQL d'avec d'autres serveurs SQL. C'est nécessaire pour s'assurer que MySQL n'a jamais besoin d'annuler une commande SQL. Cela peut sembler un peu étrange au moment où les colonnes doivent être vérifiées par l'application, mais cela vous fournit une accélération notable, à cause d'optimisations qui ne pourraient pas avoir lieu ailleurs.

Si vous donnez une valeur incorrecte à une colonne, MySQL va stocker le meilleur code possible dans la colonne, au lieu d'annuler la transaction :

- si vous essayez de stocker une valeur qui est hors de l'intervalle de validité dans une colonne numérique, MySQL va stocker la plus petite ou la plus grande valeur qu'il connaisse dans cette colonne ;

- si vous essayez de stocker une chaîne qui ne commence pas par un chiffre dans une colonne numérique, MySQL va stocker 0 ;

- si vous essayez de stocker la valeur NULL dans une colonne qui n'accepte pas la valeur NULL, le serveur MySQL va stocker 0 ou '' (chaîne vide) à la place : ce comportement peut être modifié avec l'option de compilation -DDONT_USE_DEFAULT_FIELDS) ;

- MySQL vous autorise le stockage de dates erronées dans les colonnes de type DATE et DATETIME (comme 2000-02-31 ou 2000-02-00). L'idée est que ce n'est pas au serveur SQL de faire le travail de validation. Si MySQL peut stocker une date, et relire exactement cette date, alors MySQL va stocker cette date. Si la date est totalement fausse (hors de l'intervalle de validité du serveur), la valeur spéciale 0000-00-00 sera utilisée ;

- si vous utilisez une valeur non supportée avec une colonne de type ENUM, la valeur stockée sera la chaîne vide, de valeur numérique 0 ;

- si vous utilisez une valeur invalide dans une colonne de type SET, la valeur sera ignorée.

- si vous exécutez une PROCEDURE sur une requête qui retourne un résultat vide, dans certains cas, PROCEDURE ne transformera pas les colonnes ;

- la création de table de type MERGE ne vérifie pas si les tables sous-jacentes sont de type compatible ;

- le serveur MySQL ne supporte pas encore les valeurs Server NaN, -Inf et Inf pour les doubles. Utiliser ces valeurs générera des problèmes lorsque vous essayerez d'exporter et d'importer des données. Comme solution temporaire, vous pouvez remplacer NaN par NULL (si possible) et -Inf et Inf par les valeurs maximales possibles des colonnes double ;

- si vous utilisez la commande ALTER TABLE pour ajouter un index de type UNIQUE à une table utilisée dans un rassemblement de tables MERGE, puis que vous utilisez ALTER TABLE pour ajouter un index normal à la table MERGE, l'ordre des clés sera différent pour les tables s'il y avait déjà une ancienne clé qui n'était pas unique. Ceci est dû au fait que ALTER TABLE place les clés UNIQUE avant les clés normales, pour être capable de détecter les clés doublons plus vite.

Les bogues suivants sont connus dans les anciennes versions de MySQL :

- vous pouvez obtenir un thread gelé si vous utilisez la commande DROP TABLE sur une table qui fait partie des tables verrouillées par LOCK TABLES ;

- dans les cas suivants, vous pouvez obtenir un crash :

- le gestionnaire d'insertions retardées a déjà des insertions en attente pour une table,

- LOCK table avec WRITE,

- FLUSH TABLES ;

- pour les versions de MySQL avant la 3.23.2, une commande UPDATE qui modifiait une clé avec la clause WHERE sur la même clé, pouvait échouer, car la même clé était utilisée pour rechercher les lignes et la même ligne pouvait être trouvée plusieurs fois :

UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;

Un palliatif est :

MySQL> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;

Cela fonctionnera, car MySQL ne va pas utiliser d'index sur une expression dans la clause WHERE ;

- avant la version 3.23 de MySQL, tous les types numériques étaient traités comme des champs à virgule fixe. Cela signifie que vous deviez spécifier le nombre de décimales que le champ devait avoir. Tous les résultats étaient retournés avec le nombre correct de décimales.

Pour les bogues spécifiques aux systèmes d'exploitation, voyez la section sur la compilation et le port. Voir Section 2.4, « Installation de MySQL avec une distribution source ». Voir Annexe D, Port vers d'autres systèmes.

2 - Installer MySQL

Ce chapitre décrit comment obtenir et installer MySQL.

1. Déterminez si votre plate-forme est supportée. Notez que tous les systèmes ne supportent pas MySQL de la même façon. MySQL est plus robuste et efficace que sur d'autres. Voyez Section 2.1.1, « Systèmes d'exploitation supportés par MySQL » pour plus de détails.

2. Choisissez une distribution à installer. Plusieurs versions de MySQL sont disponibles, dans plusieurs formats. Vous pouvez choisir une version préparée avec des exécutables précompilés, ou bien une version source. En cas de doute, utilisez la version binaire. Nous fournissons aussi un accès public à notre serveur de développement pour tester le nouveau code. Pour déterminer quelle version et quel type utiliser, voyez Section 2.1.2, « Choisir votre version de MySQL ».

3. Téléchargez la distribution que vous souhaitez. Pour une liste de sites sur lesquels vous pouvez télécharger MySQL, voyez Section 2.1.3, « Comment obtenir MySQL ? ». Vous pouvez vérifier l'intégrité de votre téléchargement en utilisant les instructions de Section 2.1.4, « Vérifier l'intégrité des paquets avec MD5 ou GnuPG ».

4. Installez la distribution. Pour les distributions binaires, voyez Section 2.3, « Installer MySQL sur d'autres systèmes type Linux ». Pour les distributions source, utilisez Section 2.4, « Installation de MySQL avec une distribution source ». Chaque jeu d'instructions inclut une section spécifique aux plates-formes.

Note : si vous envisagez de changer la version d'une installation existante de MySQL vers une nouvelle version, plutôt que d'installer MySQL pour la première fois, voyez la section Section 2.6, « Changer de version de MySQL » pour des informations sur les mises à jour, et sur les problèmes que vous pourriez rencontrer.

Si vous rencontrez les problèmes d'installation, voyez la section Section 2.8, « Notes spécifiques aux systèmes d'exploitation » pour des informations sur les solutions aux problèmes spécifiques des plates-formes.

5. Pour la procédure postinstallation, voyez Section 2.5, « Procédure de postinstallation ». Ces procédures s'appliquent aussi bien à la distribution binaire que la distribution source. Cette section décrit aussi comment sécuriser les comptes initiaux MySQL, qui n'ont pas de mot de passe jusqu'à ce que vous leur en assignez un.

6. Si vous voulez exécuter des scripts de tests MySQL, le support Perl de MySQL doit être disponible. Voir Section 2.9, « Commentaires sur l'installation de Perl ».

2-1 - Notes générales à propos de l'installation

Avant d'installer MySQL, vous devez :

1. Déterminer si MySQL fonctionne ou pas sur votre plate-forme ;

2. Choisir une distribution ;

3. Télécharger la distribution et vérifier son intégrité.

Cette section contient les informations nécessaires pour réaliser ces étapes. Après cela, vous pouvez utiliser les autres instructions des autres chapitres, pour installer la distribution.

2-1-1 - Systèmes d'exploitation supportés par MySQL

Nous utilisons GNU Autoconf, alors il est possible de porter MySQL sur tous les systèmes modernes qui utilisent les threads Posix et un compilateur C++. Pour compiler uniquement le client, un compilateur C++ est simplement nécessaire. Nous utilisons et développons le logiciel nous-mêmes, en commençant par Sun Solaris (versions 2.5 - 2.7) et SuSE Linux version 7.x.

Notez que pour de nombreux systèmes d'exploitation, le support natif des threads ne fonctionne qu'avec les dernières versions. MySQL a été compilé avec succès sur les combinaisons système d'exploitation/paquet de threads suivants :

- AIX 4.x, 5.x avec les threads natifs. Voir Section 2.8.5.3, « Notes relatives à IBM-AIX » ;

- Amiga.

- BSDI 2.x avec le paquet MIT-pthreads. Voir Section 2.8.4.5, « Notes relatives aux versions 2.x de BSD/OS » ;

- BSDI 3.0, 3.1 et 4.x avec les threads natifs. Voir Section 2.8.4.5, « Notes relatives aux versions 2.x de BSD/OS » ;

- DEC Unix 4.x avec les threads natifs. Voir Section 2.8.5.5, « Notes pour Alpha-DEC-UNIX (Tru64) » ;

- FreeBSD 2.x avec le paquet MIT-pthreads. Voir Section 2.8.4.1, « Notes relatives à FreeBSD » ;

- FreeBSD 3.x et 4.x avec les threads natifs. Voir Section 2.8.4.1, « Notes relatives à FreeBSD » ;

- FreeBSD 4.x avec LinuxThreads. Voir Section 2.8.4.1, « Notes relatives à FreeBSD » ;

- HP-UX 10.20 avec les threads DCE ou avec le paquet MIT-pthreads. Voir Section 2.8.5.1, « Notes relatives à la version 10.20 de HP-UX » ;

- HP-UX 11.x avec les threads natifs Voir Section 2.8.5.2, « HP-UX Version 11.x Notes » ;

- Linux 2.0+ avec LinuxThreads 0.7.1+ ou glibc 2.0.7+. Voir Section 2.8.1, « Notes relatives à Linux (toutes versions) » ;

- Mac OS X. Voir Section 2.8.2, « Notes relatives à Mac OS X » ;

- NetBSD 1.3/1.4 Intel et NetBSD 1.3 Alpha (requiert GNU make). Voir Section 2.8.4.2, « Notes concernant NetBSD » ;

- Novell NetWare 6.0. Voir Section 2.2.14, « Installer MySQL sur NetWare » ;

- OpenBSD > 2.5 avec les threads natifs. OpenBSD < 2.5 avec le paquet MIT-pthreads. Voir Section 2.8.4.3, « Notes relatives à OpenBSD 2.5 » ;

- OS/2 Warp 3, FixPack 29 et OS/2 Warp 4, FixPack 4. Voir Section 2.8.6, « Notes relatives à OS/2 » ;

- SCO OpenServer avec un port récent du paquet FSU Pthreads. Voir Section 2.8.5.8, « Notes sur SCO » ;

- SCO UnixWare 7.1.x. Voir Section 2.8.5.9, « Notes sur SCO UnixWare Version 7.1.x » ;

- SGI Irix 6.x avec les threads natifs. Voir Section 2.8.5.7, « Notes relatives à SGI Irix » ;

- Solaris 2.5 et plus récents, avec les threads natifs sur SPARC et x86. Voir Section 2.8.3, « Notes pour Solaris » ;

- SunOS 4.x avec le paquet MIT-pthreads. Voir Section 2.8.3, « Notes pour Solaris » ;

- Tru64 Unix ;

- Windows 9x, Me, NT, 2000 et XP. Voir Section 2.2.1, « Installer MySQL sous Windows ».

Notez que toutes les plates-formes ne sont pas équipées de la même façon pour faire fonctionner MySQL. Les capacités d'une plate-forme pour supporter de fortes charges avec MySQL sont déterminées par ceci :

- stabilité générale de la bibliothèque de threads. Une plate-forme qui a une excellente réputation en général, mais une bibliothèque de threads instable, dont le code est utilisé par MySQL, même si le reste est parfait, fera de MySQL une application instable ;

- la capacité du noyau et/ou de la bibliothèque de threads de profiter des capacités multiprocesseurs, symétrique ou pas. En d'autres termes, lorsqu'un processus crée un thread, il doit être possible pour ce thread de s'exécuter sur différents processeurs ;

- la capacité du noyau et/ou de la bibliothèque de threads de faire fonctionner de nombreux threads qui posent et lèvent des verrous mutex en peu de temps, fréquemment, sans changement de contexte excessif. En d'autres termes, si l'implémentation de pthread_mutex_lock() est trop soucieuse du temps CPU, cela va ralentir sérieusement MySQL. Si ce problème n'est pas réglé, ajouter des processeurs supplémentaires va finalement ralentir MySQL ;

- performance et stabilité générale du système de fichiers ;

- la capacité du système d'exploitation de gérer de grands fichiers, et de le faire efficacement, si vos tables sont grandes ;

- notre niveau d'expertise avec la plate-forme, chez MySQL AB. Si vous connaissons bien une plate-forme, vous pourront introduire des optimisations et des corrections spécifiques à la plate-forme, et activé lors de la compilation. Nous pouvons aussi fournir des conseils judicieux pour configurer votre système optimalement pour MySQL ;

- le temps de tests que vous avez consacré à des configurations similaires, en interne ;

- le nombre d'utilisateurs de MySQL qui font fonctionner MySQL avec succès sur cette plate-forme, avec des configurations similaires. Si ce nombre est grand, les chances de rencontrer un problème spécifique sont faibles.

En se basant sur les critères précédents, les meilleures plates-formes pour MySQL sont x86 avec SuSE Linux 7.1, noyau 2.4, et ReiserFS (ou toute autre distribution Linux similaire) et SPARC avec Solaris 2.7 ou 2.8. FreeBSD vient en troisième, mais nous espérons bien le voir rejoindre le groupe de tête, une fois que la bibliothèque de threads sera améliorée. Nous espérons aussi être bientôt capables d'ajouter les autres plates-formes sur lesquelles MySQL compile, et fonctionne correctement, mais pas toujours le bon niveau de stabilité et de performance. Cela réclame des efforts de notre part, en coopération avec les développeurs de ces plates-formes. Si vous êtes intéressé par l'amélioration de ces composants, et que vous êtes en position pour influencer le développement, demandez des instructions détaillées à MySQL en envoyant un email aux listes internes. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

Notez bien que la comparaison précédente ne signifie pas qu'un système d'exploitation est meilleur que l'autre, en général. Nous avons classé les systèmes en fonction de leur capacité à faire fonctionner un système MySQL, et nous nous limitons à cette comparaison. Avec cela en tête, le résultat de cette comparaison serait différent si nous y ajoutions d'autres problèmes. Et dans certains cas, la seule raison qui fait qu'un OS est meilleur que l'autre est parce que nous y avons consacré plus de temps, pour optimiser et tester. Nous nous bornons à exprimer notre point de vue pour vous aider à décider quelle plate-forme choisir pour votre serveur MySQL.

2-1-2 - Choisir votre version de MySQL

Lorsque vous vous préparez à installer MySQL, vous devez décider quelle version utiliser. Le développement de MySQL procède par série de versions, et vous pouvez prendre celle qui vous convient le mieux. Après avoir décidé de la version à installer, vous pouvez choisir le format de distribution : elles sont compilées ou au format source.

2-1-2-1 - Quelle version de MySQL utiliser ?

La première décision à prendre est de savoir si vous voulez utiliser la dernière version de développement ou la dernière version stable :

- MySQL 5.0 est la nouvelle version de développement, et les nouvelles fonctionnalités sont activement développées. Jusque récemment, elle n'était disponible qu'en avant-première, sous BitKeeper. Une version alpha a été publiée depuis, pour permettre la diffusion large de la version, à des fins de tests ;

- MySQL 4.1 est la version de développement, qui propose de nouvelles fonctionnalités majeures. Elle est toujours en version alpha. Les sources et le binaire sont disponibles pour tests et développement ;

- MySQL 4.0 est la version stable courante, pour la production. Les nouvelles versions publiées sont des corrections de bogues. Aucune nouvelle fonctionnalité ne sera ajoutée, pour ne pas diminuer la stabilité du code ;

- MySQL 3.23 est l'ancienne version de production. Cette série est retirée, et les nouvelles versions ne feront que corriger les bogues critiques.

Nous ne croyons pas au gel complet d'une version, et cela nous laisse de la place pour les corrections de bogues et les fonctionnalités qui « doivent être faites. » « Un peu gelé » signifie que nous pourrions ajouter de petites touches, qui « n'affecteront pas ce qui fonctionne déjà, presque sûrement. » Naturellement, les corrections de bogues des séries précédentes se propagent aux nouvelles versions.

En règle générale, si vous utilisez MySQL pour la première fois ou si vous essayez de le porter vers un système pour lequel il n'existe pas de distribution binaire, nous vous recommandons d'utiliser la dernière version stable (actuellement la version 4.0). Notez que toutes les versions de MySQL sont passées aux bancs de tests MySQL avant chaque sortie (même les versions de développement).

D'autre part, si vous utilisez un vieux système et que vous voulez procéder à une mise à jour, sans pour autant risquer de mettre à jour sans raison, vous devriez mettre à jour vers la dernière version de la même branche que celle que vous êtes en train d'utiliser (dans le cas où un numéro de version supérieur existe). Nous avons essayé de résoudre uniquement les bogues fatals et de produire des correctifs petits et sûrs pour cette version.

Si vous voulez utiliser de nouvelles versions qui ne sont pas présentes dans la version de production, vous pouvez utiliser la version de développement. Notez que les versions de développement ne sont pas aussi stables que les versions de production.

Si vous voulez utiliser les toutes dernières sources, qui contiennent tous les patches courants, et les corrections de bogues, vous pouvez utiliser notre entrepôt BitKeeper. Il n'y a pas de « versions » en tant que telles, mais des paquets, sur lesquels le code futur est basé.

La politique de nommage de MySQL utilise des numéros de version qui consiste en trois nombres suivis d'un suffixe. Par exemple, une version nommée mysql-3.21.17-beta doit être interprétée de la façon suivante :

- le premier nombre (3) décrit le format de fichier. Toutes les versions 3 ont le même format de fichier ;

- le second nombre (21) correspond au niveau de version. Normalement, il y a le choix entre deux d'entre eux. L'un correspond à la version/branche stable (actuellement 23) et l'autre se réfère à la branche de développement (actuellement 4.0). Normalement, les deux versions sont stables, mais la version de développement peut comporter des lacunes, manquer de documentation sur des nouvelles fonctionnalités, ou peut ne pas compiler sur certains systèmes ;

- le troisième nombre (17) est le numéro de version au sein du niveau de version. Celui-ci est incrémenté à chaque nouvelle publication. En temps normal, vous souhaiterez utiliser la dernière version du niveau de version que vous avez choisi.

Pour chaque modification mineure, le dernier nombre de la version est incrémenté. Lorsque les nouvelles fonctionnalités sont majeures, ou que des incompatibilités mineures apparaissent avec les anciennes versions, le deuxième chiffre est incrémenté. Lorsque le format de fichier change, le premier chiffre est incrémenté.

Les noms de versions incluent aussi un suffixe qui indique le niveau de stabilité de la version. Une série progresse avec différents suffixes, qui indiquent sa stabilité. Les suffixes possibles sont :

- alpha indique que la publication contient de grandes portions de nouveau code qui n'a pas été testé à 100 %. Les bogues connus (d'ordinaire, il n'y en a aucun) doivent être documentés dans la section nouveautés. Voir Annexe C, Historique des changements MySQL. Il existe aussi de nouvelles commandes et extensions dans la plupart des versions alpha. Du développement actif qui inclut des changements majeurs dans le code peut concerner les versions alpha, mais tout sera testé avant de faire une publication. Il ne devrait pas y avoir de bogues connus dans les publications de MySQL ;

- beta signifie que tout le nouveau code a été testé. Aucune fonctionnalité majeure qui pourrait causer corruption du code n'est ajoutée. Il ne doit pas y avoir un seul bogue connu. Une version alpha passe en beta quand il n'y a pas eu de bogue fatal rapporté depuis au moins un mois et que nous ne prévoyons pas de nouvelle fonctionnalité qui pourrait corrompre d'anciennes commandes ;

- gamma est une version bêta qui existe depuis un certain temps et qui semble fonctionner correctement. Seulement des changements mineurs sont effectués. C'est ce que de nombreuses autres compagnies appellent une publication ;

- S'il n'y a pas de suffixe, cela signifie que la version fonctionne depuis un certain temps sur différents sites avec aucun rapport de bogue autre que des bogues spécifiques à une plate-forme. Seules des corrections critiques sont appliquées à la publication. C'est ce que l'on appelle une version stable.

MySQL utilise un schéma de nommage qui est légèrement différent des autres produits. En général, il est plutôt sûr d'utiliser une des versions qui est disponible depuis quelques semaines, sans avoir été remplacée par une nouvelle version de la même série.

Toutes les versions de MySQL passent par nos tests et bancs d'essai standard pour nous assurer qu'elles peuvent être utilisées sans danger. Les séries de tests s'améliorent en permanence, car les tests standard sont étendus dans le temps pour traquer tous les bogues précédemment trouvés.

Notez bien que toutes les versions de MySQL ont été testées au moins avec :

- une batterie de tests internes

Le dossier mysql-test contient de nombreux cas de tests.

Nous utilisons ces tests pour virtuellement tous les systèmes d'exploitation. Voyez Section 27.1.2, « Suite de test de MySQL » pour plus d'informations sur ces fichiers ;

- les bancs de tests MySQL

Ils effectuent une série de requêtes communes. C'est aussi un test pour savoir si le dernier processus d'optimisation rend le code plus rapide. Voir Section 7.1.4, « La suite de tests MySQL » ;

- le test crash-me

Il tente de déterminer de quelles fonctionnalités disposent les bases de données et quelles en sont les limites. Voir Section 7.1.4, « La suite de tests MySQL ».

Un autre test provient du fait que nous avons la version la plus récente de MySQL dans notre propre environnement de production interne, sur au moins une machine. Nous avons plus de 100 Go de données à manipuler.

2-1-2-2 - Choisir le format de distribution

Après avoir choisi votre version de MySQL, il faut décider si vous voulez utiliser les versions binaires ou source. Dans la plupart des cas, vous choisirez une version binaire, si elle existe pour votre plate-forme. Les distributions binaires sont disponibles en format natif pour de nombreuses plates-formes, comme les paquets RPM de Linux ou les paquets DMG pour Mac OS X. Les distributions sont aussi disponibles sous forme d'archives Zip ou tar compressées.

Les raisons de choisir une distribution binaire sont :

- les distributions binaires sont généralement plus faciles à installer que les distributions source ;

- pour satisfaire différents niveaux de besoin, nous fournissons deux versions binaires : une version compilée avec des moteurs de stockage non transactionnels (petits et rapides), et une version compilée avec les extensions les plus importantes, comme les transactions. Les deux versions sont compilées à partir des mêmes sources. Tous les clients natifs MySQL peuvent se connecter aux serveurs MySQL, quelle que soit leur version.

La distribution MySQL maximale est suffixée avec -max et est configurée avec les mêmes options que mysqld-max. Voir Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld ».

Si vous voulez installer le RPM MySQL-Max, vous devez commencer par installer le RPM MySQL-server.

Dans certaines circonstances, il est préférable d'installer MySQL à partir de la distribution source :

- vous voulez installer MySQL dans un dossier spécial. Les distributions standard sont « prêtes à exécuter » depuis n'importe quel dossier, mais vous voudrez peut-être avoir plus de libertés pour dispatcher les composants de MySQL,

- vous voulez configurer mysqld avec certaines extensions qui ne font pas partie des distributions binaires. Voici les extensions les plus courantes, que vous souhaiterez utiliser :

- --with-innodb (par défaut pour MySQL 4.0 et plus récents),

- --with-berkeley-db (disponible pour quelques plates-formes),

- --with-raid,

- --with-libwrap,

- --with-named-z-libs (disponible pour certains binaires),

- --with-debug[=full] ;

- vous devez configurer mysqld sans certaines fonctionnalités qui font partie de la configuration standard. Par exemple, les distributions sont normalement compilées avec le support de tous les jeux de caractères. Si vous voulez rendre le serveur MySQL plus compact, vous pouvez recompiler MySQL avec uniquement les jeux de caractères dont vous avez besoin ;

- si vous avez un compilateur spécial, comme pgcc, ou que vous voulez utiliser des options particulières de votre compilateur pour optimiser MySQL pour votre architecture. Les distributions binaires sont compilées avec les options qui doivent fonctionner sur une large gamme de processeurs ;

- vous voulez utiliser les toutes dernières versions de MySQL, issues du serveur BitKeeper, pour avoir accès à toutes les corrections de bogues archivées. Par exemple, si vous avez découvert un bogue, le correctif sera archivé dans le serveur de sources, et vous pourrez y accéder là. Le correctif n'apparaîtra pas avant la prochaine publication de MySQL ;

- vous voulez lire et modifier le code C et C++ de MySQL. Pour cela, obtenez une distribution source, car le code source est toujours le code ultime ;

- les distributions sources contiennent plus de tests et d'exemples que les distributions binaires.

2-1-2-3 - Quand et comment sont publiées les nouvelles versions de MySQL

MySQL évolue rapidement ici, à MySQL AB, et nous voulons le partager avec les autres utilisateurs de MySQL. Nous essayons de faire une nouvelle version à chaque fois que nous avons implanté des fonctionnalités qui seront utiles à d'autres.

Nous essayons aussi d'aider les utilisateurs dont les requêtes sont faciles à programmer. Nous prenons en considération tout ce que nos clients nous demandent, et nous accordons une attention particulière à nos clients qui ont pris une licence e-mail étendue.

Personne n'est obligé de télécharger une nouvelle version. La section News vous indiquera si la nouvelle version contient une fonctionnalité que vous attendez. Voir Annexe C, Historique des changements MySQL.

Nous utilisons la politique suivante, lors de la mise à jour de MySQL :

- pour chaque modification mineure, le dernier numéro de la chaîne de version est incrémenté. Lorsqu'il y a des nouvelles fonctionnalités importantes ou des incompatibilités mineures avec la version précédente, nous incrémentons le chiffre du milieu. Lorsque le format de fichier change, le premier numéro est incrémenté ;

- des versions tables et testées sont publiées une à deux fois dans l'année, mais si de petits bogues apparaissent, une version qui ne va corriger que ces bogues sera publiée ;

- des versions fonctionnelles avec des corrections de bogues pour les vieilles versions sont publiées toutes les une à huit semaines ;

- les distributions binaires de certaines plates-formes seront compilées par nos soins pour les versions majeures. D'autres personnes font des versions binaires pour d'autres systèmes, mais probablement moins fréquemment ;

- nous rendons généralement publics les correctifs, une fois que nous avons découvert de petits bogues. Ils sont postés sur le serveur de versions BitKeeper et seront ajoutés à la prochaine version ;

- s'il y a un bogue fatal dans une version, nous publierons une nouvelle version aussitôt que possible. Nous apprécions que les autres éditeurs fassent la même chose.

2-1-2-4 - Politique de publication : aucun bogue connu dans les versions

Nous mettons beaucoup d'efforts et de temps à la publication de version sans bogue. À notre connaissance, nous n'avons jamais publié une version de MySQL qui contienne un bogue fatal connu et reproductible.

Un bogue fatal est un problème qui fait planter MySQL en utilisation normale, fournit des réponses erronées à des requêtes classiques, ou a des problèmes de sécurité.

Nous documentons tous les problèmes ouverts, bogues et tout ce qui dépend des choix de conception. Voir Section 1.5.7, « Erreurs connues, et limitations de MySQL ».

Nous avons pour but de corriger tout ce qui peut être corrigé, sans risquer la stabilité des versions de MySQL. Dans certains cas, cela signifie que nous pouvons corriger une erreur dans la version de développement, mais pas dans la version stable. Naturellement, nous documentons ces problèmes, pour que les utilisateurs soient avertis.

Voici une description de notre processus de publication :

- nous surveillons les bogues sur les listes de support utilisateur, les listes externes et la base de données de bogues sur le site http://bugs.mysql.com/ ;

- tous les bogues rapportés pour les versions en production entrent dans la base de données des bogues ;

- lorsque nous corrigeons un bogue, nous essayons de réaliser un cas de test, que nous incluons dans notre système de tests, pour nous assurer que le bogue ne reviendra jamais (environ 90 % des bogues ont des cas de tests) ;

- nous créons aussi des cas de test pour toutes les nouvelles fonctionnalités que nous voulons ajouter à MySQL ;

- avant de commencer à compiler une nouvelle version de MySQL, nous nous assurons que tous les bogues reproductibles pour les versions anciennes (3.23.x, 4.0.x, etc.) sont corrigés. Si le bogue ne peut être corrigé (pour des raisons de choix de conception), nous le documentons dans le manuel. Voir Section 1.5.7, « Erreurs connues, et limitations de MySQL » ;

- nous compilons MySQL sur toutes les plates-formes pour lesquelles nous distribuons des paquets binaires (plus de 15 plates-formes à ce jour), et nous exécutons notre suite de tests et notre suite de performance sur chacune d'entre elles ;

- nous ne publions pas un paquet binaire sur une plate-forme pour laquelle la suite de test ou de performance échoue. Si c'est une erreur générale, nous la corrigeons, et nous recommençons les tests sur toutes les plates-formes, à partir de zéro ;

- si nous recevons, durant le temps de compilation et de tests qui peut prendre deux à trois jours, un rapport de bogues concernant un bogue fatal (par exemple, un bogue qui crée un coredump), nous le corrigeons, et nous recommençons le processus de tests ;

- après avoir publié les paquets binaires sur http://www.mysql.com/, nous envoyons une annonce par email aux listes de diffusion. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ». Le message d'annonce contient une liste de tous les changements de la version, et de tous les bogues connus. La section des problèmes connus, 'known problems', dans les notes de publications n'a été utilisée que dans quelques versions ;

- pour donner rapidement accès aux dernières fonctionnalités de MySQL, nous réalisons une publication de MySQL toutes les quatre à cinq semaines. http://downloads.mysql.com/snapshots.php ;

- si, après une publication, nous recevons des rapports de bogues qui prouvent qu'il y a, malgré tout, un bogue critique dans une version spécifique à une plate-forme, nous le corrigeons rapidement, et nous annonçons une version 'a' pour la plate-forme. Grâce à notre large communauté d'utilisateurs, les problèmes sont trouvés rapidement ;

- nos résultats de bonne publication sont excellents. Dans les dernières 150 versions, nous avons dû reprendre la compilation moins de 10 fois (dans trois des cas, le bogue était dû à glibc sur l'une de nos machines de tests, qu'il a été difficile de trouver.

2-1-2-5 - Binaires compilés par MySQL AB

MySQL AB, propose un jeu de distributions binaires de MySQL qui sont compilées sur nos machines, ou les machines auxquelles nos clients nous ont gracieusement donné accès.

En plus des versions binaires adaptées à chaque plate-forme, (Voir Section 2.2, « Installation standard rapide de MySQL ».), nous proposons aussi des distributions binaires au format .tar.gz.

Pour les distributions Windows, voyez Section 2.2.1, « Installer MySQL sous Windows ».

Ces distributions sont générées avec le script Build-tools/Do-compile qui compile le code source, et crée l'archive tar.gz en utilisant le script scripts/make_binary_distribution.

Ces archives sont configurées et compilées avec les options suivantes. Cette information peut aussi être obtenue en lisant les variables COMP_ENV_INFO et CONFIGURE_LINE dans le script bin/mysqlbug, disponible dans toutes les distributions binaires tar.

Les programmes suivants ont été compilés par les équipes de MySQL AB :

- Linux 2.4.xx x86 avec gcc 2.95.3 :

CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2 -mcpu=pentiumpro -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static ;

- Linux 2.4.xx Intel Itanium 2 avec ecc (Intel C++ Itanium Compiler 7.0) :

CC=ecc CFLAGS="-O2 -tpp2 -ip -nolib_inline" CXX=ecc CXXFLAGS="-O2 -tpp2 -ip -nolib_inline" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile ;

- Linux 2.4.xx Intel Itanium avec ecc (Intel C++ Itanium Compiler 7.0) :

CC=ecc CFLAGS=-tpp1 CXX=ecc CXXFLAGS=-tpp1 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile ;

- Linux 2.4.xx alpha avec ccc (Compaq C V6.2-505 / Compaq C++ V6.3-006) :

CC=ccc CFLAGS="-fast -arch generic" CXX=cxx CXXFLAGS="-fast -arch generic -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --disable-shared ;

- Linux 2.x.xx ppc avec gcc 2.95.4 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb ;

- Linux 2.4.xx s390 avec gcc 2.95.3 :

CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static ;

- Linux 2.4.xx x86_64 (AMD64) avec gcc 3.2.1 :

CXX=gcc ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared ;

- Sun Solaris 8 x86 avec gcc 3.2.3 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb ;

- Sun Solaris 8 SPARC avec gcc 3.2 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared ;

- Sun Solaris 8 SPARC 64-bit avec gcc 3.2 :

CC=gcc CFLAGS="-O3 -m64 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -m64 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared ;

- Sun Solaris 9 SPARC avec gcc 2.95.3 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-curses-libs=-lcurses --disable-shared ;

- Sun Solaris 9 SPARC avec cc-5.0 (Sun Forte 5.0) :

CC=cc-5.0 CXX=CC ASFLAGS="-xarch=v9" CFLAGS="-Xa -xstrconst -mt -D_FORTEC_ -xarch=v9" CXXFLAGS="-noex -mt -D_FORTEC_ -xarch=v9" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --enable-thread-safe-client --disable-shared ;

- IBM AIX 4.3.2 ppc avec gcc 3.2.3 :

CFLAGS="-O2 -mcpu=powerpc -Wa,-many " CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared ;

- IBM AIX 4.3.3 ppc avec xlC_r (IBM Visual Age C/C++ 6.0) :

CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS ="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-innodb ;

- IBM AIX 5.1.0 ppc avec gcc 3.3 :

CFLAGS="-O2 -mcpu=powerpc -Wa,-many" CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --with-server-suffix="-pro" --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared ;

- IBM AIX 5.2.0 ppc avec xlC_r (IBM Visual Age C/C++ 6.0) :

CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-embedded-server --with-innodb ;

- HP-UX 10.20 pa-risc1.1 avec gcc 3.1 :

CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc CXXFLAGS="-DHPUX -I/opt/dce /include -felide-constructors -fno-exceptions -fno-rtti -O3 -fPIC" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-pthread --with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC --disable-shared ;

- HP-UX 11.00 pa-risc avec aCC (HP ANSI C++ B3910B A.03.50) :

CC=cc CXX=aCC CFLAGS=+DAportable CXXFLAGS=+DAportable ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb ;

- HP-UX 11.11 pa-risc2.0 64bit avec aCC (HP ANSI C++ B3910B A.03.33) :

CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared ;

- HP-UX 11.11 pa-risc2.0 32bit avec aCC (HP ANSI C++ B3910B A.03.33) :

CC=cc CXX=aCC CFLAGS="+DAportable" CXXFLAGS="+DAportable" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb ;

- HP-UX 11.22 ia64 64bit avec aCC (HP aC++/ANSI C B3910B A.05.50) :

CC=cc CXX=aCC CFLAGS="+DD64 +DSitanium2" CXXFLAGS="+DD64 +DSitanium2" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb ;

- Apple Mac OS X 10.2 powerpc avec gcc 3.1 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared ;

- FreeBSD 4.7 i386 avec gcc 2.95.4 :

CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=not-used --disable-shared ;

- FreeBSD 4.7 i386 avec LinuxThreads et gcc 2.95.4 :

CFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" CXXFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-thread-libs="-DHAVE_GLIBC2_STYLE_GETHOSTBYNAME_R -D_THREAD_SAFE -I /usr/local/include/pthread/linuxthreads -L/usr/local/lib -llthread -llgcc_r" --disable-shared --with-embedded-server --with-innodb ;

- QNX Neutrino 6.2.1 i386 avec gcc 2.95.3qnx-nto 20010315 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared.

Les paquets binaires suivants sont compilés sur des systèmes que des tiers prêtent gracieusement à MySQL AB. Notez que ces paquets sont fournis gracieusement. Comme MySQL AB n'a pas le contrôle complet sur ces systèmes, nous ne pouvons proposer qu'un support limité :

- SCO Unix 3.2v5.0.6 i386 avec gcc 2.95.3 :

CFLAGS="-O3 -mpentium" LDFLAGS=-static CXX=gcc CXXFLAGS="-O3 -mpentium -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared ;

- SCO OpenUnix 8.0.0 i386 avec CC 3.2 :

CC=cc CFLAGS="-O" CXX=CC ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared ;

- Compaq Tru64 OSF/1 V5.1 732 alpha avec cc/cxx (Compaq C V6.3-029i / DIGITAL C++ V6.1-027) :

CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -fast -inline speed -speculate all -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-prefix=/usr/local/mysql --with-named-thread-libs="-lpthread -lmach -lexc -lc" --disable-shared --with-mysqld-ldflags=-all-static ;

- SGI Irix 6.5 IP32 avec gcc 3.0.1 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared ;

- FreeBSD/sparc64 5.0 avec gcc 3.2.1 :

CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb.

Les options suivantes de compilations ont été utilisées pour les paquets binaires de MySQL, qui étaient fournis auparavant. Ces paquets ne sont plus mis à jour, mais les options de compilation sont conservées ici pour mémoire.

- Linux 2.2.xx SPARC avec egcs 1.1.2 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared ;

- Linux 2.2.x avec x686 avec gcc 2.95.2 :

CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charsets=complex ;

- SunOS 4.1.4 2 sun4c avec gcc 2.7.2.1 :

CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-assembler ;

- SunOS 5.5.1 (et plus récents) sun4u avec egcs 1.0.3a or 2.90.27 or gcc 2.95.2 et plus récents :

CC=gcc CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex --enable-assembler ;

- SunOS 5.6 i86pc avec gcc 2.8.1 :

CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex ;

- BSDI BSD/OS 3.1 i386 avec gcc 2.7.2.1 :

CC=gcc CXX=gcc CXXFLAGS=-O ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex ;

- BSDI BSD/OS 2.1 i386 avec gcc 2.7.2 :

CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex ;

- AIX 2 4 avec gcc 2.7.2.2 :

CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex.

Si vous avez des options plus optimales pour l'une des configurations précédemment listées, vous pouvez toujours nous en faire part sur la liste de distribution des développeurs. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

Les distributions RPM antérieures à la version 3.22 de MySQL sont fournies par nos utilisateurs. À partir de la version 3.22, les RPM sont générés par nous chez MySQL AB.

Si vous voulez compiler une version de débogage de MySQL, vous devez ajouter --with-debug ou --with-debug=full aux lignes de configuration précédentes et effacer les options -fomit-frame-pointer.

2-1-3 - Comment obtenir MySQL ?

Visitez le site de MySQL (http://www.mysql.com/) pour des informations à propos de la version courante et les instructions de téléchargement.

Notre miroir principal est situé sur http://mirrors.sunsite.dk/mysql/.

Pour une liste complète et à jour des miroirs web/téléchargement de MySQL, voyez http://www.mysql.com/downloads/mirrors.html. Vous trouverez là des informations à propos des futurs miroirs et de quoi nous informer de la non-validité de l'un d'entre eux.

2-1-4 - Vérifier l'intégrité des paquets avec MD5 ou GnuPG

Une fois que vous avez téléchargé le paquet MySQL qui vous convient, et avant de l'installer, vous devriez vous assurer qu'il est intact, et n'a pas été altéré.

MySQL AB propose deux moyens de vérifier l'intégrité :

- signatures MD5 ;

- signatures chiffrées avec GnuPG, GNU Privacy Guard ;

- pour les paquets RPM, le mécanisme de vérification d'intégrité intégré.

Les sections suivantes décrivent comment utiliser ces méthodes.

Dans le cas où vous vous apercevez que la somme de contrôle MD5 checksum ou la signature GPG ne correspond pas, essayez de télécharger à nouveau le même paquet, éventuellement depuis un autre miroir. Si vous échouez plusieurs fois à vérifier l'intégrité du paquet, faites-nous part de votre problème, en incluant le nom complet du paquet désiré, et les sites de téléchargement que vous avez utilisés. Envoyez-nous un courriel à l'adresse <webmaster@mysql.com> ou <build@mysql.com>.

2-1-4-1 - Vérifier la signature MD5

Une fois que vous avez téléchargé le paquet, vous devez vérifier si la somme de contrôle MD5 correspond à celle qui est disponible sur le site de MySQL. Chaque paquet a une somme de contrôle individuelle, que vous pouvez obtenir avec la commande suivante :

shell> md5sum <paquet>

Exemple :

shell> md5sum mysql-standard-4.0.17-pc-linux-i686.tar.gz
60f5fe969d61c8f82e4f7f62657e1f06
mysql-standard-4.0.17-pc-linux-i686.tar.gz

Ainsi, vous devez vérifier si la somme de contrôle résultante correspond à celle qui est imprimée sur la page de téléchargement, en dessous du paquet téléchargé.

Notez que tous les systèmes d'exploitation ne supportent pas la commande md5sum : sur certains, elle s'appelle simplement md5, sur d'autres, elle n'est pas du tout disponible. Sur Linux, elle a fait partie des utilitaires texte GNU (GNU Text Utilities), qui sont disponibles pour toute une gamme de plates-formes. Vous pouvez télécharger le code source sur le site http://www.gnu.org/software/textutils/. Si vous avez installé OpenSSL, vous pouvez utiliser la commande openssl md5 <paquet> à la place. Une implémentation DOS/Windows de la commande md5 est disponible sur le site http://www.fourmilab.ch/md5/.

2-1-4-2 - Vérification de la signature avec GnuPG

Une méthode plus sûre pour vérifier l'intégrité d'un paquet est d'utiliser la signature GnuPG. C'est une méthode plus sûre que le MD5, mais elle requiert un peu plus de travail.

Depuis MySQL 4.0.10 (février 2003), MySQL AB utilise GNU Privacy Guard (GnuPG), une alternative Open Source du très connu Pretty Good Privacy (PGP) par Phil Zimmermann. Voir http://www.gnupg.org/. La plupart des distributions Linux disposent d'une version de GnuPG installée par défaut. Pour plus de détails sur OpenPGP, voir http://www.openpgp.org/.

Pour vérifier la signature d'un paquet spécifique, vous devez obtenir en premier lieu une copie de la clé publique GPG. Vous pouvez soit la copier/coller directement depuis ce manuel, ou la demander sur le serveur http://www.keyserver.net/.

Key ID:
pub  1024D/5072E1F5 2003-02-03
MySQL Package signing key (www.mysql.com) <build@mysql.com>
Fingerprint: A4A9 4068 76FC BD3C 4567  70C8 8C71 8D3B 5072 E1F5

Public Key (ASCII-armored):

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3
RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ
fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3
BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW
hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV
K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE
kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI
QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep
rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFj
a2FnZSBzaWduaW5nIGtleSAod3d3Lm15c3FsLmNvbSkgPGJ1aWxkQG15c3FsLmNv
bT6IXQQTEQIAHQUCPj6jDAUJCWYBgAULBwoDBAMVAwIDFgIBAheAAAoJEIxxjTtQ
cuH1cY4AnilUwTXn8MatQOiG0a/bPxrvK/gCAJ4oinSNZRYTnblChwFaazt7PF3q
zIhMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAn1mxHijft00bKXvu
cSo/pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJ
YiKJAAoJELb1zU3GuiQ/lpEAoIhpp6BozKI8p6eaabzF5MlJH58pAKCu/ROofK8J
Eg2aLos+5zEYrB/LsrkCDQQ+PqMdEAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/l
xaZoJYc3a6M02WCnHl6ahT2/tBK2w1QI4YFteR47gCvtgb6O1JHffOo2HfLmRDRi
Rjd1DTCHqeyX7CHhcghj/dNRlW2Z0l5QFEcmV9U0Vhp3aFfWC4Ujfs3LU+hkAWzE
7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iM1BzELqX1DY7LwoPEb/O9Rkbf4fm
Le11EzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p
/1oIDznkg/p8kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqq
a8CGrRfsOAJxim63CHfty5mUc5rUSnTslGYEIOCR1BeQauyPZbPDsDD9MZ1ZaSaf
anFvwFG6Llx9xkU7tzq+vKLoWkm4u5xf3vn55VjnSd1aQ9eQnUcXiL4cnBGoTbOW
I39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0Ec8bsM8b3Ev42Lmu
QT5NdKHGwHsXTPtl0klk4bQk4OajHsiy1BMahpT27jWjJlMiJc+IWJ0mghkKHt92
6s/ymfdf5HkdQ1cyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZ
Whe70YGNPw1yjWJT1IhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4A
n3r1QpVC9yhnW2cSAjq+kr72GX0eAJ4295kl6NxYEuFApmr1+0uUq/SlsQ==
=YJkx
-----END PGP PUBLIC KEY BLOCK-----

Vous pouvez importer cette clé dans votre trousseau de clés publiques GPG avec la commande gpg --import. Par exemple, si vous avez sauvé la clé dans un fichier appelé mysql_pubkey.asc, la commande d'importation est :

shell> gpg --import mysql_pubkey.asc

Voyez la documentation GPG pour plus de détails sur comment travailler avec les clés publiques.

Une fois que vous avez téléchargé et importé la clé publique, vous pouvez télécharger le paquet MySQL et la signature qui lui est associée, sur la même page. Le fichier de signature a pour extension .asc. Par exemple :

Fichier de distribution Linux

mysql-standard-4.0.17-pc-linux-i686.tar.gz

Fichier de signature

mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc

Assurez-vous que les deux fichiers sont stockés dans le même dossier, puis exécutez la commande suivante pour vérifier la signature du fichier :

shell> gpg --verify <package>.asc

Exemple :

shell> gpg --verify mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc
gpg: Warning: using insecure memory!
gpg: Signature made Mon 03 Feb 2003 08:50:39 PM MET
using DSA key ID 5072E1F5
gpg: Good signature from
"MySQL Package signing key (www.mysql.com) <build@mysql.com>"

La mention « Good signature » (bonne signature) indique que le paquet est correct.

2-1-4-3 - Contrôle d'intégrité avec RPM

Pour les paquets RPM, il n'y a pas de signature séparée : les paquets RPM disposent d'une signature GPG intégrée, et d'une somme de contrôle MD5. Vous pouvez les vérifier avec la commande suivante :

shell> rpm --checksig package_name.rpm

Exemple :

shell> rpm --checksig MySQL-server-4.0.10-0.i386.rpm
MySQL-server-4.0.10-0.i386.rpm: md5 gpg OK

Note : si vous utilisez RPM 4.1 et qu'il se plaint que (GPG) NOT OK (MISSING KEYS: GPG#5072e1f5) (même si vous l'avez importé dans votre trousseau de clés), vous devez alors importer la clé dans votre trousseau RPM d'abord. RPM 4.1 n'utilise pas votre trousseau de clés GPG (ni GPG lui-même), car il entretient son propre trousseau de clés (car c'est une application de niveau système, et que le trousseau de clé est spécifique à chaque utilisateur). Pour importer la clé publique mysql_pubkey.asc MySQL dans votre trousseau de clés RPM, utilisez la commande suivante :

shell> rpm --import mysql_pubkey.asc

2-1-5 - Dispositions d'installation

Cette section décrit les répertoires par défaut créés en installant les distributions binaires et les distributions de sources.

Sous Windows, le dossier d'installation par défaut est C:\mysql, qui a la structure suivante :

Dossier

Contenu du dossier

bin

Clients et serveur mysqld

data

Fichiers de log et bases de données

Docs

Documentation

examples

Programmes d'exemple et scripts

include

Fichiers d'inclusion (entêtes)

lib

Bibliothèques

scripts

Utilitaires

share

Fichiers de messages d'erreur

Les installations créées sur les distributions Linux RPM placent les fichiers dans les sous-dossiers suivants :

Dossier

Contenu du dossier

/usr/bin

Programmes clients

/usr/sbin

serveur mysqld

/var/lib/mysql

Fichiers de log et bases de données

/usr/share/doc/packages

Documentation

include

Fichiers d'inclusion (entêtes)

lib

Bibliothèques

/usr/share/mysql

Fichiers de messages d'erreur et jeux de caractères

sql-bench

Suites de tests

Sous Unix, une archive tar avec la distribution binaire s'installe en la désarchivant dans le dossier d'installation que vous voulez (typiquement le dossier /usr/local/mysql) et crée les dossiers suivants au même endroit :

Dossier

Contenu du dossier

bin

Clients et serveur mysqld

data

Fichiers de log et bases de données

docs

Documentation, historique

include

Fichiers d'inclusion (entêtes)

lib

Bibliothèques

scripts

mysql_install_db

share/mysql

Fichiers de messages d'erreur

sql-bench

Suites de tests

Une distribution source est installée après compilation. Par défaut, les étapes d'installation installent les fichiers dans /usr/local, dans les sous-dossiers suivants :

Dossier

Contenu du dossier

bin

Programmes clients et scripts

include/mysql

Fichiers d'inclusion (entêtes)

info

Documentation

lib/mysql

Bibliothèques

libexec

The serveur mysqld

share/mysql

Fichiers de messages d'erreur

sql-bench

Suites de tests

var

Fichiers de log et bases de données

Dans le répertoire d'installation, les dispositions d'une installation des sources diffèrent d'une installation binaire des façons suivantes :

- le serveur mysqld est installé dans le répertoire libexec plutôt que dans le répertoire bin ;

- le répertoire des données est var plutôt que data ;

- mysql_install_db est installé dans le répertoire /usr/local/bin plutôt que dans /usr/local/mysql/scripts ;

- le répertoire des fichier d'entête et les répertoires des bibliothèques sont include/mysql et lib/mysql au lieu de include et lib.

Vous pouvez créer votre propre installation binaire à partir d'une distribution de sources compilées en exécutant le script scripts/make_binary_distribution.

2-2 - Installation standard rapide de MySQL

Cette section couvre l'installation de MySQL sur les plates-formes pour lesquelles nous offrons un système d'installation spécifique. Cela s'appelle aussi une installation binaire. Toutefois, des installations binaires sont disponibles pour de nombreuses autres plates-formes. Voyez Section 2.3, « Installer MySQL sur d'autres systèmes type Linux » pour des instructions génériques, qui s'appliqueront aussi à ces plates-formes.

Voyez Section 2.1, « Notes générales à propos de l'installation » pour plus d'informations sur les autres distributions binaires qui sont disponibles, et comment les obtenir.

2-2-1 - Installer MySQL sous Windows

Le processus d'installation de MySQL sous Windows est le suivant :

1. Installez la distribution ;

2. Configurez un fichier d'options si nécessaire ;

3. Sélectionnez un serveur à utiliser ;

4. Lancez le serveur ;

5. Assignez des mots de passe aux comptes MySQL initiaux.

MySQL pour Windows est disponible en deux formats :

- la distribution binaire, qui contient un programme d'installation, qui se charge de placer tout ce qui est nécessaire ;

- la distribution source, qui contient tout le code et les fichiers de support pour compiler les exécutables avec VC++ 6.0.

En général, vous devriez utiliser la distribution binaire. Elle est plus facile à installer, et vous n'avez besoin d'aucun autre outil pour faire fonctionner MySQL.

Cette section décrit comment installer MySQL sur Windows en utilisant la distribution binaire. Pour installer une distribution source, voyez Section 2.4.6, « La distribution source Windows ».

2-2-1-1 - Prérequis système sur Windows

Pour utiliser MySQL sur Windows, vous avez besoin de :

- un système d'exploitation 32 bits Windows, tels que 9x, Me, NT, 2000 ou XP. La famille NT (Windows NT/2000/XP) vous permet de faire fonctionner MySQL comme un service. Voir Section 2.2.9.1, « Lancer MySQL comme un service Windows » ;

- support du protocole TCP/IP ;

- une copie de la distribution binaire MySQL pour Windows, qui peut être téléchargé sur http://www.mysql.com/downloads/. Voir Section 2.1.3, « Comment obtenir MySQL ? ».

Note : les fichiers de la distribution sont fournis dans un format compressé, et nous vous recommandons d'utiliser le client FTP approprié, avec des capacités de reprise sur erreur, pour éviter les corruptions d'archive au cours du téléchargement,

- WinZip ou un programme ZIP pour décompresser l'archive .zip ;

- assez d'espace sur votre disque pour décompresser l'archive, et pour créer les bases selon vos besoins ;

- si vous envisagez d'utiliser MySQL via ODBC, vous aurez aussi besoin du pilote MyODBC. Voir Section 25.1.1.1, « Qu'est-ce que ODBC? » ;

- si vous avez besoin de table d'une taille supérieure à 4 Go, installez MySQL sur un système de fichier NTFS ou plus récent. N'oubliez pas d'utiliser les options MAX_ROWS et AVG_ROW_LENGTH lorsque vous créez les tables. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

2-2-2 - Choisir un paquet d'installation

Depuis MySQL 4.1.5, il y a trois paquets d'installation à choisir avant d'installer MySQL sur Windows. Les paquets sont les suivants :

- The Essentials Package : ce paquet porte un nom du type mysql-essential-4.1.9-win32.msi et contient le minimum de fichiers nécessaires pour installer MySQL sur Windows, y compris l'assistant de configuration. Ce paquet n'inclut pas de composants optionnels tels que le serveur embarqué ou la suite de performance ;

- The Complete Package : ce paquet porte un nom du type mysql-4.1.9-win32.zip et contient tous les fichiers nécessaires pour créer une installation Windows complète, y compris l'assistant de configuration. Ce paquet inclut les composants optionnels tels que le serveur embarqué et la suite de performances ;

- The Noinstall Archive : ce paquet porte un nom du type mysql-noinstall-4.1.9-win32.zip et contient tous les fichiers du paquet Complete Package, à l'exception de l'assistant de configuration. Ce paquet n'inclut pas l'installeur automatique, et doit être manuellement installé et configuré.

Le paquet Essentials Package est recommandé pour la plupart des utilisateurs.

Votre choix de paquet d'installation affecte le processus d'installation. Si vous choisissez les paquets Essentials Package ou Complete Packages, voyez Section 2.2.3, « Installer MySQL avec l'assistant automatique ». Si vous choisissez l'installation de MySQL avec le paquet Noinstall Archive, voyez Section 2.2.6, « Installer MySQL à partir d'une archive ZIP sans assistant ».

2-2-3 - Installer MySQL avec l'assistant automatique

Depuis MySQL 4.1.5, les utilisateurs peuvent utiliser les nouveaux assistants MySQL Installation Wizard et MySQL Configuration Wizard pour installer MySQL sur Windows. MySQL Installation Wizard et MySQL Configuration Wizard sont conçus pour installer et configurer MySQL pour qu'un nouvel utilisateur puisse immédiatement commencer à utiliser MySQL.

MySQL Installation Wizard et MySQL Configuration Wizard sont disponibles parmi les paquets d'installation essentiels et complets : ils sont recommandés pour la plupart des installations standard de MySQL. Les exceptions sont les utilisateurs qui ont besoin de plusieurs instances de serveurs MySQL sur un serveur, et des utilisateurs experts qui veulent avoir le contrôle de leur configuration.

Si vous installez une version de MySQL antérieure à la version 4.1.5, suivez les instructions d'installation de MySQL à partir des paquets Noinstall. Voir Section 2.2.6, « Installer MySQL à partir d'une archive ZIP sans assistant ».

2-2-4 - Installation de MySQL avec l'assistant

2-2-4-1 - Introduction

L'assistant d'installation MySQL est un nouvel installeur pour le serveur MySQL, qui utilise les dernières technologies de Microsoft Windows. L'assistant d'installation de MySQL, combiné à l'assistant de configuration MySQL, permet à l'utilisateur d'installer et de configurer un serveur MySQL prêt à l'emploi dès son installation.

L'assistant d'installation MySQL est l'installeur standard de toutes les distributions MySQL à partir de la version 4.1.5. Les utilisateurs des anciennes versions doivent faire l'installation manuellement, en éteignant le serveur, supprimant leur installation existante avant d'installer la nouvelle version. Voyez la section Section 2.2.4.7, « Mise à jour de MySQL » pour plus d'informations sur la mise à jour depuis les anciennes versions.

Microsoft a inclus une version améliorée de leur Microsoft Windows Installer (MSI) dans les versions récentes de Windows. L'utilisation de MSI est devenue le standard de fait pour les applications sur Windows 2000, Windows XP et Windows Server 2003. L'assistant d'installation MySQL utilise cette technologie pour améliorer et simplifier le processus d'installation.

Le Microsoft Windows Installer Engine a été mis à jour avec la version Windows XP; ceux qui utilisent une version antérieure de Windows peuvent se reporter à cet article de la Microsoft Knowledge Base pour plus d'informations sur la mise à jour de Windows Installer Engine.

De plus, Microsoft a introduit le WiX (Windows Installer XML) récemment. C'est le premier projet open source de Microsoft qui soit recommandé. Nous sommes passés à WiX, car c'est un projet open source, et qu'il nous permet de gérer entièrement le processus d'installation sur Windows de manière souple, via des scripts.

L'amélioration de l'assistant d'installation de MySQL dépend du support et des rapports que les utilisateurs comme vous font. Si vous trouvez que l'assistant d'installation MySQL manque de certaines fonctionnalités vitales, ou si vous rencontrez un bogue, utilisez notre système de rapport de bogues pour demander une nouvelle fonctionnalité ou une correction de problème.

2-2-4-2 - Télécharger et lancer l'assistant d'installation MySQL

Les paquets d'installation du serveur MySQL sont disponibles au téléchargement sur le site http://dev.mysql.com/downloads/. Si le paquet que vous téléchargez est une archive Zip, il faudra commencer par décompresser cette archive.

Le processus de lancement de l'assistant dépend du contenu du paquet d'installation que vous téléchargez. S'il existe un fichier setup.exe, faites un double-clic dessus pour le lancer. S'il y a un fichier .msi, faites un double-clic dessus pour lancer l'installation.

2-2-4-3 - Choisir le type d'installation

Il y a trois types d'installations disponibles : le standard Typical, le complet Complete et le personnalisé Custom.

L'installation Typical installe le serveur MySQL, le client en ligne de commande mysql et les utilitaires de ligne de commande. Les utilitaires en ligne de commande incluent mysqldump, myisamchk et plusieurs autres outils pour vous aider à gérer le serveur MySQL.

L'installation Complete installe tous les composants du paquet d'installation. L'installation complète inclut des composants tels que les bibliothèques embarquées, les tests de performance, les scripts de support et la documentation.

L'installation personnalisée Custom vous donne le contrôle sur les composants que vous voulez installer, et le chemin de l'installation. Voyez Section 2.2.4.4, « Le dialogue d'installation personnalisée » pour plus de détails sur ce type d'installation.

Si vous choisissez les installations Typical ou Complete et que vous cliquez sur le bouton Next, vous irez directement à l'écran de confirmation, et vous commencerez l'installation. Si vous choisissez l'installation Custom, le dialogue d'installation personnalisée s'affichera, tel que présenté dans Section 2.2.4.4, « Le dialogue d'installation personnalisée »

2-2-4-4 - Le dialogue d'installation personnalisée

Si vous voulez changer le nom du dossier d'installation ou installer un composant spécifique, il faut utiliser l'installation personnalisée Custom.

Tous les composants disponibles sont listés dans un arbre hiérarchisé à gauche du dialogue d'installation. Les composants qui ne seront pas installés auront une icône rouge X, et les composants qui sont déjà installés ont une icône grisée. Pour installer un nouveau composant, il faut cliquer sur l'icône du composant, et choisir une nouvelle option dans la liste déroulante qui apparaît.

Vous pouvez changer le chemin d'installation par défaut en cliquant sur le bouton Change... à droite du chemin d'installation affiché.

Après avoir fait le choix des composants à installer et du dossier d'installation, cliquez sur le bouton Next pour passer au dialogue de confirmation.

2-2-4-5 - Le dialogue de confirmation

Une fois que vous avez choisi un type d'installation et que vous avez choisi tous vos composants à installer, vous passez au dialogue de confirmation. Le type d'installation et les options sont présentés pour que vous puissiez les vérifier.

Pour installer MySQL dès que vous êtes satisfait de vos choix, cliquez sur le bouton 'install'. Pour modifier vos options, cliquez sur le bouton 'Back'. Pour quitter l'assistant d'installation MySQL, cliquez sur le bouton 'Cancel'.

Une fois l'installation terminée, vous pouvez vous enregistrer sur le site Web de MySQL. L'enregistrement vous donne accès aux forums à l'URL forums.mysql.com, ainsi qu'aux rapports de bogues à l'URL bugs.mysql.com et à l'inscription des lettres d'informations. Le dernier écran de l'installeur fournit un résumé de l'opération, et vous donne l'occasion de lancer l'assistant de configuration de MySQL, qui vous servira à créer un fichier de configuration, à installer un service MySQL et à mettre en place les sécurités.

2-2-4-6 - Modifications apportées par l'assistant d'installation MySQL

Une fois que vous avez cliqué sur le bouton d'installation, l'assistant d'installation MySQL commence le processus d'installation et s'assure que les modifications apportées à votre système sont celles que vous avez demandées.

Modifications du registre

L'assistant d'installation MySQL crée une clé dans le registre de Windows : HKEY_LOCAL_MACHINE\SOFTWARE\MySQL AB.

L'assistant d'installation MySQL crée une clé à partir du numéro de version majeur du serveur en cours d'installation, tel que MySQL Server 4.1. Elle contient deux valeurs, les chaînes Location et Version. La chaîne Location contient le chemin jusqu'au dossier d'installation. Dans une installation par défaut, elle contient C:\Program Files\MySQL\MySQL Server 4.1\. La chaîne Version contient le numéro de version. Par exemple, pour une installation de MySQL Server 4.1.5, la clé contient la valeur 4.1.5.

Les clés du registre servent aux outils externes pour identifier le dossier d'installation, évitant ainsi une recherche dans l'ensemble du disque dur pour déterminer le bon dossier. Les clés de registre ne sont pas obligatoires pour faire fonctionner le serveur, et lorsque vous faites une installation noinstall, ces clés ne sont pas créées.

Modification dans le menu de démarrage

L'assistant d'installation MySQL crée une nouvelle entrée dans le menu de démarrage de Windows, sous le nom commun de MySQL que vous avez installé. Par exemple, si vous installez MySQL 4.1, l'assistant d'installation MySQL crée une section MySQL Server 4.1.

Les éléments suivants sont créés dans ce menu :

- MySQL Command Line Client : c'est un raccourci vers le client de ligne de commande mysql et il est configuré pour se connecter en tant que root. Le raccourci demande le mot de passe de root ;

- MySQL Server Instance Config Wizard : ceci est un raccourci vers l'assistant de configuration MySQL. Utilisez ce raccourci pour configurer un nouveau serveur ou reconfigurer un serveur en fonctionnement ;

- Documentation MySQL : ceci est un lien vers la documentation du serveur MySQL qui est stockée localement dans le dossier d'installation. Cette option n'est pas disponible lorsque le serveur est installé avec le paquet essential.

Modifications dans le système de fichiers

L'assistant d'installation MySQL installe le serveur MySQL dans le dossier C:\Program Files\MySQL\MySQL Server 4.1, où Program Files est le dossier par défaut pour les applications sur votre système et 4.1 est la version majeure du serveur. C'est l'emplacement recommandé pour le serveur MySQL, qui remplace le dossier précédent de c:\mysql.

Par défaut, toutes les applications MySQL sont stockées dans le dossier C:\Program Files\MySQL, où Program Files est le dossier pour les applications sur votre système Windows. Une installation typique de MySQL sur une machine ressemble à ceci :

C:\Program Files\MySQL\MySQL Server 4.1
C:\Program Files\MySQL\MySQL Server 5.0
C:\Program Files\MySQL\MySQL Administrator 1.0
C:\Program Files\MySQL\MySQL Query Browser 1.0

Cette approche rend plus simples la gestion et l'entretien des applications MySQL sur un système Windows.

2-2-4-7 - Mise à jour de MySQL

Depuis MySQL 4.1.5, le nouvel assistant d'installation MySQL peut réaliser automatiquement des installations en exploitant des capacités de MSI. Cela signifie que vous n'avez pas à modifier l'ancienne installation manuellement, avant de faire une nouvelle installation. L'installeur se charge d'éteindre automatiquement le serveur et de le supprimer avant d'installer la nouvelle version.

Les mises à jour automatiques sont uniquement disponibles lors de la mise à jour entre deux installations qui ont le même numéro de version majeure et mineure. Par exemple, vous pouvez mettre à jour automatiquement le serveur depuis MySQL 4.1.5 vers MySQL 4.1.6, mais pas de MySQL 4.1 vers MySQL 5.0.

Si vous passez de version MySQL 4.1.4 ou plus ancienne à la version 4.1.5 ou plus récente, vous devez commencer par manuellement éteindre le serveur et supprimer l'ancienne installation avant de faire la mise à jour. Assurez-vous de sauver les bases de données avant de faire une telle mise à jour, pour que vous puissiez restaurer les données après la migration. Il est toujours recommandé de faire une sauvegarde des données avant de faire une mise à jour.

Voir Section 2.2.11, « Mettre à jour MySQL sous Windows ».

2-2-5 - Utiliser l'assistant de configuration

2-2-5-1 - Introduction

L'assistant de configuration MySQL vous aide dans le processus de configuration de votre serveur MySQL sous Windows. L'assistant de configuration MySQL crée un fichier my.ini personnalisé en vous posant différentes questions, et en enregistrant vos réponses dans un fichier my.ini modèle.

L'assistant de configuration MySQL est inclus avec le serveur MySQL depuis MySQL version 4.1.5, mais il est conçu pour fonctionner avec les versions 4.1 ou plus récentes. L'assistant de configuration MySQL est actuellement disponible uniquement pour Windows.

L'assistant de configuration MySQL est, pour l'essentiel, le résultat des retours que MySQL AB a reçu de nombreux utilisateurs depuis quelques années. Cependant, si vous pensez que ce logiciel manque de fonctionnalités importantes pour vous, ou si vous rencontrez un bogue, utilisez notre système MySQL Bug System pour demander une nouvelle fonctionnalité ou rapporter un problème.

2-2-5-2 - Lancement de l'assistant de configuration MySQL

L'assistant de configuration MySQL est simplement lancé lorsque l'assistant d'installation MySQL se termine. Vous pouvez aussi lancer le l'assistant de configuration MySQL en cliquant sur l'élément du programme dans le menu démarrer.

De plus, vous pouvez vous rendre dans le dossier bin du dossier d'installation de MySQL pour lancer manuellement le programme MySQLInstanceConfig.exe.

2-2-5-3 - Choisir une option d'entretien

Si l'assistant de configuration MySQL détecte un fichier my.ini, vous aurez l'option de reconfigurer votre serveur ou de supprimer cette instance du fichier my.ini, stopper et supprimer le serveur MySQL.

Pour reconfigurer un serveur existant, choisissez l'option Re-configure Instance et cliquez sur le bouton de suite. Votre fichier my.ini actuel sera renommé en mytimestamp.ini.bak, où timestamp est la date et l'heure où le fichier my.ini a été créé. Pour supprimer l'instance actuelle du serveur, choisissez l'option Remove Instance et cliquez sur le bouton Next.

Si vous choisissez l'option Remove Instance, vous passez à une fenêtre de confirmation. Cliquez sur le bouton d'exécution, et l'assistant de configuration MySQL va arrêter et supprimer le serveur MySQL, puis effacer le fichier my.ini. L'installation du serveur et le dossier de données data ne sont pas touchés.

Si vous choisissez l'option Re-configure Instance, vous passez au dialogue de Configuration du type où vous pouvez choisir le type d'installation à configurer.

2-2-5-4 - Choisir un type de configuration

Lorsque vous lancez l'assistant de configuration MySQL pour une nouvelle installation ou que vous choisissez l'option Re-configure Instance pour une installation existante, vous passez au dialogue Configuration Type.

Il y a deux types de configuration disponibles : Detailed Configuration et Standard Configuration. L'option Standard Configuration sert aux nouveaux utilisateurs qui veulent lancer rapidement MySQL sans avoir à prendre beaucoup de décisions concernant la configuration du serveur. L'option Detailed Configuration sert pour les utilisateurs avancés qui veulent avoir le contrôle complet de leur configuration.

Si vous êtes nouveau avec MySQL et que vous voulez avoir un serveur configuré en mode utilisateur seul, la Standard Configuration devrait vous convenir. Choisir l'option Standard Configuration fait que l'assistant de configuration MySQL va effectuer toutes les configurations sauf Service Options et Security Options.

La Standard Configuration choisit des options qui peuvent être incompatibles avec les systèmes qui supportent déjà d'autres installations MySQL. Si vous avez une installation MySQL sur votre système en plus de celle que vous voulez configurer, il faut utiliser l'option Detailed Configuration.

Pour terminer la Standard Configuration, voyez les sections concernant les options de service et les options de sécurité, accessibles à Section 2.2.5.11, « Le dialogue d'options de service  » et Section 2.2.5.12, « Le dialogue d'options de sécurité ».

2-2-5-5 - Le dialogue de type de serveur

Il y a différents types de serveurs disponibles et ce type affecte les décisions prises par l'assistant de configuration MySQL en ce qui concerne la mémoire, le disque et l'utilisation du processeur.

- Developer Machine : choisissez cette option pour installer MySQL pour une utilisation personnelle. L'assistant suppose qu'il y aura de nombreuses autres applications qui fonctionneront simultanément. Le serveur est configuré pour utiliser un minimum de ressources.

- Server Machine : choisissez cette option pour un serveur, où MySQL fonctionne avec d'autres applications serveur, telles qu'un serveur FTP, email et web. Le serveur est configuré pour utiliser une portion raisonnable des ressources.

- Dedicated MySQL Server Machine : choisissez ce type pour une machine qui est dédiée à MySQL. L'assistant suppose alors qu'aucune autre application ne fonctionne, et que le serveur peut occuper toutes les ressources disponibles.

2-2-5-6 - Le dialogue d'utilisation des bases de données

Le dialogue Database Usage vous permet d'indiquer les moteurs de tables que vous voulez utiliser lorsque vous créez les tables MySQL. Les options que vous choisissez alors déterminent si le moteur InnoDB est disponible, et quel pourcentage des ressources du serveur sont disponibles pour ce moteur.

- Multifunctional Database : cette option active simultanément InnoDB et MyISAM et divise les ressources équitablement entre les deux. Cette option est recommandée pour les utilisateurs qui utilisent les deux types de tables régulièrement.

- Transactional Database Only : cette option active les deux moteurs InnoDB et MyISAM, mais consacre plus de ressources InnoDB. Cette option est recommandée pour les utilisateurs qui emploient exclusivement InnoDB, et très rarement MyISAM.

- Non-Transactional Database Only : cette option désactive complètement InnoDB et consacre toutes les ressources du serveur à MyISAM. Cette option est recommandée pour les utilisateurs qui n'emploient pas InnoDB.

2-2-5-7 - Le dialogue d'installation des espaces de tables InnoDB

Certains utilisateurs souhaitent ranger leurs espaces de tables InnoDB hors du dossier de données de MySQL. En plaçant ces fichiers comme cela, vous pouvez gagner en performances ou en capacité en choisissant le bon système de stockage, comme un système RAID, par exemple.

Pour changer le dossier par défaut des espaces de tables InnoDB, vous devez choisir un autre volume dans la liste disponible. Pour créer un chemin particulier, il suffit de cliquer... sur le bouton.

Si vous modifiez la configuration d'un serveur existant, vous devez cliquer sur le bouton de modification Modify avant de changer le chemin. Dans la situation où vous changez manuellement les fichiers d'espace de table, il faut déplacer les fichiers dans leur nouveau dossier avant de relancer le serveur.

2-2-5-8 - Le dialogue de connexions simultanées

Il est important de mettre une limite au nombre de connexions simultanées qu'un serveur MySQL va accepter pour éviter que le serveur ne consomme tous les processus existants. Le dialogue Concurrent Connections vous permet de choisir le nombre maximum d'utilisateurs sur le serveur, et configure la limite de connexions simultanées. Il est aussi possible de modifier manuellement cette limite.

- Decision Support (DSS)/OLAP : choisissez cette option si votre serveur ne requiert par beaucoup de connexions simultanées. Le nombre maximal de connexions est de 100, avec une moyenne de 20 connexions simultanées.

- Online Transaction Processing (OLTP) : choisissez cette option si votre serveur requiert de nombreuses connexions simultanées. Le nombre maximal de connexions est de 500.

- Manual Setting : choisissez cette option pour spécifier manuellement le nombre maximal de connexions concurrentes au serveur. Choisissez un nombre de connexions dans la liste fournie, ou bien tapez directement le nombre choisi dans cette liste.

2-2-5-9 - Le dialogue d'options de réseau

Utilisez le dialogue Networking Options pour activer ou désactiver la pile TCP/IP et pour confirmer le numéro de port à utiliser pour se connecter à MySQL.

La pile TCP/IP est activée par défaut. Pour désactiver le réseau TCP/IP, décochez la boîte Enable TCP/IP Networking.

Le port 3306 est utilisé par défaut. Pour changer le port utilisé pour se connecter à MySQL, choisissez un port dans la liste fournie, ou tapez un nouveau numéro de port directement dans cette zone. Si le numéro de port que vous choisissez est déjà utilisé, vous devrez confirmer votre choix.

2-2-5-10 - Le dialogue de jeux de caractères

Le serveur MySQL supporte plusieurs jeux de caractères, et il est possible de configurer un jeu de caractères qui sera utilisé par défaut à toutes les tables, colonnes et bases de données, à moins qu'il ne soit spécifié autrement. Utilisez le dialogue Character Set pour changer le jeu de caractères par défaut du serveur MySQL.

- Standard Character Set : choisissez cette option si vous voulez utiliser Latin1 comme jeu de caractères par défaut. Latin1 sert pour l'anglais et la plupart des langues occidentales.

- Best Support For Multilingualism : choisissez cette option si vous voulez utiliser UTF8 comme jeu de caractères par défaut. UTF8 peut stocker les caractères de très nombreuses langues dans un même jeu.

- Manual Selected Default Character Set / Collation : choisissez cette option si vous voulez choisir le jeu de caractères par défaut manuellement. Choisissez le jeu de caractères souhaité dans la liste fournie.

2-2-5-11 - Le dialogue d'options de service

Sur les plates-formes Windows NT, le serveur MySQL peut être installé comme un service. Lorsque c'est le cas, le serveur MySQL peut être démarré automatiquement lors du lancement du serveur, et même, redémarré automatiquement par Windows dans le cas d'une panne de service.

L'assistant de configuration MySQL installe le serveur MySQL comme service par défaut, en utilisant le service appelé MySQL. Si vous ne voulez pas installer le service, décochez la boîte à côté de l'option Install As Windows Service. Vous pouvez changer le nom du service en en donnant un nouveau dans le champ fourni ou dans le menu déroulant proposé.

Pour installer le serveur MySQL comme un service, mais sans le démarrage automatique au démarrage, décochez la boîte à côté de l'option Launch the MySQL Server automatically.

2-2-5-12 - Le dialogue d'options de sécurité

Il est recommandé de donner un mot de passe à l'utilisateur root pour votre serveur, et l'assistant de configuration MySQL vous impose de configurer un mot de passe root par défaut. Si vous ne voulez pas spécifier le mot de passe root, il faut décocher l'option Modify Security Settings.

Pour choisir un mot de passe root, tapez le mot que vous voulez dans les deux champs New root password et Confirm. Si vous reconfigurez un serveur existant, il faut aussi indiquer le mot de passe courant du root dans le champ Current root password.

Pour éviter les connexions root via le réseau, cochez l'option Root may only connect from localhost. Cela améliore la sécurité de votre compte root.

Pour créer un compte anonyme, cochez l'option Create An Anonymous Account. La création d'un compte anonyme peut réduire la sécurité de votre serveur et n'est pas recommandée.

2-2-5-13 - Le dialogue de confirmation

Le dialogue final de l'assistant de configuration MySQL est le Confirmation Dialog. Pour lancer le processus de configuration, cliquez sur le bouton Execute. Pour retourner à un dialogue précédent, cliquez sur le bouton Back. Pour quitter l'assistant de configuration MySQL, cliquez sur le bouton Cancel.

Une fois que vous avez cliqué sur le bouton Execute, l'assistant de configuration MySQL effectue différentes tâches et affiche sa progression à l'écran.

L'assistant de configuration MySQL détermine différentes options de configuration en fonction de vos choix, en utilisant un gabarit préparé par MySQL AB. Ce gabarit est appelé my-template.ini et est situé dans le dossier d'installation.

L'assistant de configuration MySQL écrit alors ces options dans le fichier my.ini. L'emplacement final du fichier my.ini est affiché à côté de la tâche Write configuration file.

Si vous choisissez de créer un service pour le serveur MySQL, l'assistant de configuration MySQL va créer le service et le démarrer. Si vous reconfigurez un service existant, l'assistant de configuration MySQL va redémarrer le service pour qu'il prenne en compte vos modifications.

Si vous choisissez de configurer un mot de passe root, l'assistant de configuration MySQL va se connecter au serveur, configurer votre mot de passe, et appliquer les options de sécurité que vous lui avez spécifiées.

Une fois que l'assistant de configuration MySQL a terminé, un résumé est affiché. Cliquez sur le bouton Finish pour terminer avec l'assistant de configuration MySQL.

2-2-5-14 - L'emplacement du fichier my.ini

Dans les installations MySQL antérieures à la version 4.1.5, il était de coutume de donner le nom de my.cnf au fichier de configuration du serveur, ou bien de le baptiser my.ini et de placer ce fichier dans c:\my.cnf ou c:\Windows\my.ini.

Le nouvel assistant de configuration MySQL place le fichier my.ini dans le dossier d'installation du serveur MySQL. Cela permet d'associer le fichier de configuration avec la bonne instance du serveur.

Pour s'assurer que le serveur MySQL sait où trouver le fichier my.ini, un argument similaire à celui-ci qui est passé durant l'installation du service : --defaults-file="C:\Program Files\MySQL\MySQL Server 4.1\my.ini", où C:\Program Files\MySQL\MySQL Server 4.1 est remplacé par le chemin de l'installation du serveur MySQL.

L'option --defaults-file indique au serveur MySQL qu'il doit lire le fichier spécifié pour trouver les options de configuration.

2-2-5-15 - Éditer le fichier my.ini

To modify the my.ini file, open it with a text editor and make any necessary changes. You can also modify the server configuration with the MySQL Administrator utility.

MySQL clients and utilities such as the mysql command-line client and mysqldump are not able to locate the my.ini file located in the server installation directory. To configure the client and utility applications, create a new my.ini file in the c:\Windows directory.

2-2-6 - Installer MySQL à partir d'une archive ZIP sans assistant

Les utilisateurs qui réalisent leur installation à partir d'une archive sans assistant (paquet Noinstall), ou qui installent une version antérieure à la version 4.1.5, peuvent utiliser les instructions de cette section pour réaliser leur installation manuelle de MySQL. Si vous utilisez une version antérieure à la version 4.1.5 avec une distribution qui dispose d'un assistant, remplacez l'exécution du programme Setup par l'extraction de l'archive.

Les instructions d'installation de MySQL à partir de l'archive ZIP sont les suivantes :

1. Décompressez l'archive dans le dossier d'installation souhaité ;

2. Créez un fichier d'options ;

3. Choisissez un type de serveur MySQL ;

4. Démarrez le serveur MySQL ;

5. Sécurisez les mots de passe des utilisateurs créés par défaut.

Ce processus est décrit dans les sections suivantes.

2-2-7 - Extraction de l'archive d'installation

Pour installer MySQL manuellement, suivez ces instructions :

1. Si vous mettez à jour votre installation depuis une installation ancienne, voyez la section Section 2.2.11, « Mettre à jour MySQL sous Windows » avant de commencer le processus de mise à jour ;

2. Si vous utilisez un serveur basé sur Windows NT, comme Windows NT, Windows 2000, Windows XP ou Windows Server 2003, assurez-vous que vous êtes connecté avec un utilisateur qui a les droits d'administration ;

3. Choisissez un dossier d'installation. Traditionnellement, le serveur MySQL est installé dans le dossier C:\mysql, et le nouvel assistant d'installation MySQL installe MySQL dans C:\Program Files\MySQL. Si vous n'installez pas MySQL dans C:\mysql, vous devez spécifier le chemin jusqu'au dossier d'installation durant le démarrage, ou bien dans un fichier d'options. Voir Section 2.2.8, « Créer un fichier d'options » ;

4. Extrayez l'archive d'installation dans le dossier d'installation, en utilisant votre outil de Zip préféré. Certains outils vont extraire l'archive dans un dossier du dossier que vous aurez désigné. Si cela arrive, il faudra déplacer le contenu de ce sous-dossier dans le dossier que vous souhaitez.

2-2-8 - Créer un fichier d'options

Si vous avez besoin de spécifier des options lorsque vous exécutez le serveur, vous pouvez les indiquer à la ligne de commande ou les placer dans un fichier d'options. Pour les options qui sont utilisées à chaque démarrage du serveur, il est plus pratique de les ranger dans un fichier d'options. C'est particulièrement vrai dans les situations suivantes :

- le dossier d'installation et le dossier de données sont à des emplacements différents de leur valeur par défaut (C:\mysql et C:\mysql\data) ;

- vous devez adapter le paramétrage du serveur. Par exemple, vous utilisez les tables transactionnelles InnoDB de MySQL 3.23, et vous devez manuellement ajouter des lignes d'options telles que décrites dans Section 15.4, « Configuration InnoDB ». (Depuis MySQL 4.0, InnoDB crée le fichier de données et de log dans le dossier de données, par défaut.) Avoir un fichier d'options signifie que vous n'avez plus à configurer InnoDB explicitement. Vous pouvez toujours le faire si vous le voulez, mais le fichier d'options est très pratique dans ce cas.

Lorsque le serveur MySQL démarre sur Windows, il recherche les options dans deux fichiers : le fichier my.ini dans le dossier Windows, et le fichier C:\my.cnf. Le dossier Windows est typiquement C:\WINDOWS ou C:\WinNT. Vous pouvez déterminer son chemin exact en affichant la valeur de la variable d'environnement WINDIR avec la commande suivante :

C:\> echo %WINDIR%

MySQL recherche les options en premier dans le fichier my.ini, puis dans le fichier my.cnf. Cependant, pour éviter les confusions, il est mieux de n'utiliser qu'un seul fichier. Si votre PC utilise un boot loader où le volume C: n'est pas le disque de démarrage, votre seule issue est d'utiliser le fichier my.ini. Quelle que soit l'option que vous utilisiez, le fichier d'options est un simple fichier texte.

Vous pouvez aussi utiliser les fichiers d'options d'exemple inclus dans votre distribution MySQL. Regardez dans le dossier d'installation et recherchez des fichiers tels que my-small.cnf, my-medium.cnf, my-large.cnf, etc., que vous pouvez copier ou renommer, et placer dans le chemin approprié pour avoir un fichier de configuration de base.

Un fichier d'options peut être créé et modifié par n'importe quel éditeur de texte, tel que Notepad. Par exemple, si MySQL est installé dans le dossier E:\mysql et que le dossier de données est situé dans E:\mydata\data, vous pouvez créer un fichier d'options et configurer la section [mysqld] pour spécifier les valeurs de basedir et datadir :

[mysqld]
# set basedir to your installation path
basedir=E:/mysql
# set datadir to the location of your data directory
datadir=E:/mydata/data

Notez que les noms de chemin Windows sont spécifiés dans les options avec des slashs, et non pas des antislashs. Si vous utilisez des antislashs, il faut les doubler :

[mysqld]
# set basedir to your installation path
basedir=E:\\mysql
# set datadir to the location of your data directory
datadir=E:\\mydata\\data

Sur Windows, l'installeur MySQL place les données directement dans le dossier où vous installez MySQL. Si vous voulez utiliser un dossier de données différent, il faut copier l'intégralité du dossier data dans le nouveau chemin. Par défaut, l'installeur place MySQL dans C:\mysql et le dossier de données dans C:\mysql\data. Si vous voulez utiliser le dossier E:\mydata, vous devez faire ceci :

- déplacer le dossier de données depuis C:\mysql\data vers E:\mydata ;

- utiliser l'option --datadir pour spécifier le nouveau dossier de données, à chaque fois que vous lancez le serveur.

2-2-8-1 - Choisir un serveur MySQL sur Windows

Depuis MySQL 3.23.38, la distribution Windows inclut le serveur MySQL classique et le serveur MySQL-Max. Voici la description de toutes les versions livrées :

Programme

Description

mysqld

Compilé avec les informations de débogage, la vérification d'allocation de mémoire, le support des liens symboliques et les tables InnoDB et BDB tables.

mysqld-opt

Optimisé. Depuis la version 4.0, InnoDB est activé. Avant la version 4.0, ce serveur n'incluait aucune table transactionnelle.

mysqld-nt

Optimisé pour Windows NT/2000/XP avec support pour les pipes nommés.

mysqld-max

Optimisé, avec le support des liens symboliques et des tables InnoDB et BDB.

mysqld-max-nt

Comme mysqld-max, mais compilé avec le support des pipes nommés.

Tous les serveurs précédents sont optimisés pour les processeurs Intel modernes, mais ils fonctionneront sur toutes les architectures Intel de classe i386 et plus récentes.

MySQL supporte TCP/IP sur toutes les plates-formes Windows. Les serveurs mysqld-nt et mysql-max-nt supportent les pipes nommés sur NT, 2000 et XP. Cependant, par défaut, MySQL utilise TCP/IP quelle que soit la plate-forme. Les pipes nommés sont plus lents que TCP/IP.

Les pipes nommés sont sujets aux limitations suivantes :

- depuis MySQL 3.23.50, les pipes nommés sont activés uniquement si vous lancez le serveur avec l'option --enable-named-pipe. Il est nécessaire d'utiliser explicitement cette option, car des utilisateurs ont rencontré des problèmes lors de l'extinction du serveur MySQL, avec les pipes nommés ;

- les connexions par pipes nommés ne sont permises qu'avec mysqld-nt et mysqld-max-nt, et uniquement si le serveur fonctionne sur une version de Windows qui supporte les pipes nommés (NT, 2000, XP) ;

- ces serveurs peuvent fonctionner avec Windows 98 et Me, mais ils requièrent la pile TCP/IP; les pipes nommés seront ignorés ;

- sur Windows 95, ces serveurs ne peuvent être utilisés.

Note : la plupart des exemples dans les prochaines sections, utilisent mysqld comme nom de serveur. Si vous choisissez un autre nom de serveur, comme mysqld-opt, assurez-vous de bien faire les bons remplacements dans les commandes des exemples. Une bonne raison de choisir un nom de serveur différent est que mysqld contient le support complet du débogage, il utilise plus de mémoire et fonctionne plus lentement que les autres serveurs Windows.

2-2-8-2 - Démarrer le serveur pour la première fois

Sur Windows 95, 98 et Me, les clients MySQL utilisent toujours TCP/IP pour se connecter au serveur. Cela permet à toute machine du réseau de se connecter à votre serveur MySQL. À cause de cela, assurez-vous que le support TCP/IP est installé avant de lancer MYSQL. Vous pouvez trouver TCP/IP dans votre CD d'installation Windows.

Notez que si vous utilisez une vieille version Windows 95 (par exemple, OSR2), il est probable que vous ayez un vieux paquet Winsock; MySQL requiert Winsock 2 ! Vous pouvez télécharger un nouveau paquet Winsock sur http://www.microsoft.com/. Windows 98 dispose de la bibliothèque Winsock 2, et il est donc inutile de la mettre à jour.

Sur les systèmes NT, comme Windows NT, 2000 ou XP, les clients ont deux options. Soit utiliser TCP/IP, soit les pipes nommés, si le serveur les supporte.

Pour des informations sur quel serveur choisir, voyez Section 2.2.8.1, « Choisir un serveur MySQL sur Windows ».

Cette section donne un aperçu général du lancement du serveur MySQL. La section suivante fournit des informations spécifiques pour une version particulière de Windows.

Les exemples de ces sections supposent que MySQL est installé dans son dossier par défaut : C:\mysql. Adaptez les noms de chemin si vous avez installé MySQL ailleurs.

Tester à partir d'une console DOS est la meilleure chose à faire, car le serveur affiche des messages qui y apparaissent. Si quelque chose n'est pas bon dans votre configuration, ces messages vous aideront à identifier et corriger le problème.

Assurez-vous d'être dans le répertoire où se situe le serveur, puis entrez cette commande :

C:\mysql\bin> mysqld --console

Vous devriez voir ce qui suit pendant le démarrage du serveur :

InnoDB: The first specified datafile c:\ibdata\ibdata1 did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280
InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280
InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be created
InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280
InnoDB: Doublewrite buffer not found: creating new
InnoDB: Doublewrite buffer created
InnoDB: creating foreign key constraint system tables
InnoDB: foreign key constraint system tables created
011024 10:58:25  InnoDB: Started

Lorsque le serveur finit sa séquence de démarrage, vous devriez voir une ligne comme celle-ci, qui indique que le serveur est fonctionnel, et attend les connexions :

mysqld: ready for connections
Version: '4.0.14-log'  socket: ''  port: 3306

Le serveur va continuer à écrire dans la console les logs. Vous pouvez ouvrir une autre console pour utiliser un client.

Si vous omettez l'option --console, le serveur va écrire les logs dans un fichier du dossier de données (C:\mysql\data par défaut). Le fichier d'erreurs est celui dont l'extension est .err.

Les comptes initiaux, qui sont dans les tables de droits de MySQL n'ont pas de mot de passe. Après le démarrage du serveur, vous devriez modifier leur mot de passe avec les instructions de Section 2.5, « Procédure de postinstallation ».

Note : les comptes sont listés dans les tables de droits MySQL qui n'ont pas de mot de passe initialement. Après avoir démarré le serveur, il est recommandé de les modifier, comme indiqué dans la documentation Section 2.5, « Procédure de postinstallation ».

2-2-9 - Démarrer MySQL depuis la ligne de commande Windows

Le serveur MySQL peut être lancé manuellement depuis la ligne de commande. Ceci est valable pour toutes les versions de Windows.

Pour lancer le serveur mysqld depuis la ligne de commande, vous devez ouvrir une fenêtre de console (une « fenêtre DOS ») et entrer ces lignes :

C:\> C:\Program Files\MySQL\MySQL Server 4.1\bin\mysqld

Le chemin utilisé dans l'exemple précédent dépend de votre installation de MySQL.

Sur les versions non NT de Windows, cette commande lance mysqld en tâche de fond. C'est-à-dire qu'après le démarrage du serveur, vous devriez retrouver votre invite de commande. Si vous lancez le serveur de cette manière sur Windows NT, 2000, XP ou 2003, le serveur va fonctionner en tâche principale jusqu'à ce que le serveur se termine. À cause de cela, il faudra ouvrir une autre console pour exécuter le client.

Vous pouvez arrêter le serveur MySQL en exécutant cette commande :

C:\> C:\Program Files\MySQL\MySQL Server 4.1\bin\mysqladmin -u root shutdown

Cela appelle l'utilitaire MySQL mysqladmin qui se connecte au serveur et lui indique de s'arrêter. L'utilitaire se connecte en tant que root MySQL, qui est le compte d'administration par défaut dans le système de droits MySQL. Notez que les utilisateurs MySQL sont totalement indépendants des utilisateurs Windows.

Si mysqld ne se lance pas, vérifiez le log d'erreurs pour voir si le serveur y a inscrit un message pour indiquer la nature du problème. Le fichier d'erreurs est rangé dans le dossier C:\mysql\data. C'est le fichier qui porte le suffixe .err. Vous pouvez aussi essayer de lancer le serveur avec la commande mysqld --console; dans ce cas, vous pourrez lire la totalité des informations d'erreurs directement à l'écran.

La dernière option est de lancer mysqld avec l'option --standalone --debug. Dans ce cas, mysqld écrit un fichier de log dans le fichier C:\mysqld.trace qui contiendra la raison qui fait que mysqld ne se lance pas. Voir Section D.1.2, « Créer un fichier de traçage ».

Utilisez mysqld --verbose --help pour afficher toutes les options que mysqld comprend. (Avant MySQL 4.1, omettez l'option --verbose.)

2-2-9-1 - Lancer MySQL comme un service Windows

Dans la famille NT (Windows NT, 2000 ou XP), la méthode recommandée pour faire fonctionner MySQL est de l'installer comme service Windows. Windows lance et arrête le serveur MySQL lorsque le système d'exploitation se lance ou s'arrête. Un serveur installé comme un service peut aussi être contrôlé en ligne de commande, avec la commande NET, ou avec l'utilitaire graphique Services.

L'utilitaire Services (le gestionnaire Windows Service Control Manager) est disponible dans le panneau d'administration Windows (sous la section Utilitaires d'administration sous Windows 2000). Il est conseillé de fermer l'utilitaire Services lorsque vous faites une installation ou une suppression à partir de la ligne de commande : cela évite certaines erreurs étranges.

Pour faire fonctionner MySQL avec TCP/IP sous Windows NT 4, vous devez installer le service pack 3 ou plus récent.

Avant d'installer MySQL comme service Windows, vous devez commencer par arrêter le serveur en marche, avec cette commande :

C:\> C:\mysql\bin\mysqladmin -u root shutdown

Elle appelle l'utilitaire MySQL mysqladmin, qui se connecte au serveur et l'arrête. La commande se connecte en tant que root, qui est le compte d'administration par défaut. Notez que les utilisateurs du système de droits MySQL sont totalement indépendants de ceux de Windows.

Ensuite, installez le serveur comme un service :

C:\> mysqld --install

Si vous avez des problèmes d'installation de mysqld en tant que service en utilisant simplement le nom du serveur, essayez d'utiliser le chemin complet :

C:\> C:\mysql\bin\mysqld --install

Depuis MySQL 4.0.2, vous pouvez spécifier un nom de service personnalisé avec l'option --install. Depuis MySQL 4.0.3, vous pouvez spécifier en plus l'option --defaults-file après le nom du service, pour indiquer où le serveur doit lire les options au démarrage. Les règles qui déterminent le nom du service et le fichier d'options à utiliser sont les suivantes :

- si vous ne spécifiez pas de nom de service, le serveur utilise le nom de service par défaut de MySQL et le serveur lit les options du groupe [mysqld] dans le fichier d'options standard ;

- si vous spécifiez un nom de service après l'option --install, le serveur va ignorer le groupe d'options [mysqld] et lire les options dans le groupe du même nom que le nom du service. Le serveur lit ces options dans le fichier d'options standard ;

- si vous spécifiez une option --defaults-file après le nom du service, le serveur va ignorer les fichiers d'options standard et ne lire les options que dans le groupe [mysqld].

Note : avant MySQL 4.0.17, un serveur installé comme service Windows avait des problèmes à se lancer si le chemin ou le nom du service contenait des espaces. Pour cette raison, évitez d'installer MySQL dans un dossier tel que C:\Program Files ou avec un nom qui contient des espaces.

Dans le cas général où vous installez le serveur avec l'option --install, mais sans nom de service, le serveur est installé sous le nom de MySQL.

Un exemple plus complexe : voyez la commande suivante, qui peut être saisie sur une seule ligne :

C:\> C:\mysql\bin\mysqld --install mysql
--defaults-file=C:\my-opts.cnf

Ici, le nom du service est donné après l'option --install. Si aucune option --defaults-file n'est donnée, cette commande aurait pour effet de faire lire au serveur le groupe [mysql] dans les fichiers d'options standard. Cela est une mauvaise idée, car ce groupe d'options est aussi celui du client mysql. Cependant, comme l'option --defaults-file est présente, le serveur lit les options uniquement dans le fichier indiqué, et uniquement dans le groupe d'options [mysqld].

Vous pouvez aussi spécifier les options comme « Start parameters » dans l'utilitaire Windows Services avant de lancer le service.

Une fois que le serveur MySQL est installé, Windows va lancer automatiquement le service lorsque Windows se lance. Le service peut aussi être lancé immédiatement depuis l'utilitaire Services, ou avec la commande en ligne NET START MySQL. La commande NET n'est pas sensible à la casse.

Lorsqu'il fonctionne comme un service, mysqld n'a pas accès à la console Windows, et aucun message n'apparaîtra là. Si mysqld ne démarre pas, vérifiez dans le fichier d'erreurs si le serveur a inscrit des messages qui indiquent la cause du problème. Le fichier d'erreurs est situé dans le dossier C:\mysql\data. Il porte le suffixe .err.

Lorsque mysqld fonctionne comme un service, il peut être stoppé par l'utilitaire Services, la commande NET STOP MySQL, ou la commande mysqladmin shutdown. Si le service fonctionne lors de l'extinction de Windows, ce dernier va stopper automatiquement le serveur.

Depuis MySQL 3.23.44, vous avez le choix d'installer le serveur comme un service Manuel, si vous ne voulez pas que le serveur soit lancé automatiquement au lancement du serveur Windows. Pour cela, utilisez l'option --install-manual plutôt que --install :

C:\> C:\mysql\bin\mysqld --install-manual

Pour supprimer un serveur qui a été installé comme service, commencez par l'arrêter s'il fonctionnait. Puis, utilisez l'option --remove pour le supprimer :

C:\> C:\mysql\bin\mysqld --remove

Pour les versions MySQL antérieures à la 3.23.49, un problème avec l'arrêt automatique réside dans le fait que Windows n'attend que quelques secondes avant l'extinction complète, et tue les processus si cette limite est dépassée. C'est la cause de problèmes potentiels (par exemple, le moteur InnoDB devra faire une restauration de base au prochain redémarrage). Depuis MySQL 3.23.49, Windows attend suffisamment longtemps pour que le serveur s'arrête. Si vous remarquez que ce n'est pas suffisant pour votre installation, il est plus prudent de ne pas faire tourner MySQL comme un service. Au lieu de cela, lancez-le en ligne de commande, et stoppez-le avec mysqladmin shutdown.

L'augmentation du délai d'attente de Windows fonctionne avec Windows 2000 et XP. Elle ne fonctionne pas pour Windows NT, où Windows attend 20 s l'extinction d'un service. Vous pouvez augmenter cette valeur par défaut en ouvrant la base de registres : \winnt\system32\regedt32.exe, et en éditant la valeur de WaitToKillServiceTimeout à HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control. Spécifiez une nouvelle valeur plus grande, exprimée en millisecondes. Par exemple, la valeur de 120000 indique à Windows NT d'attendre 2 minutes (120 secondes).

Si vous ne voulez pas lancer mysqld comme un service, vous pouvez le lancer en ligne de commande, comme vous le faites sur les versions qui ne sont pas Windows NT. Pour des instructions, voyez Section 2.2.9, « Démarrer MySQL depuis la ligne de commande Windows ».

Voyez Section 2.2.10.1, « Résolution de problèmes d'installation de MySQL sous Windows » si vous rencontrez des difficultés durant l'installation.

2-2-10 - Tester son installation MySQL

Vous pouvez tester le bon fonctionnement du serveur MySQL en exécutant une des commandes suivantes :

C:\> C:\mysql\bin\mysqlshow
C:\> C:\mysql\bin\mysqlshow -u root mysql
C:\> C:\mysql\bin\mysqladmin version status proc
C:\> C:\mysql\bin\mysql test

Si mysqld est lent à répondre sur les connexions TCP/IP depuis les clients sur Windows 9x/Me, c'est qu'il y a vraisemblablement un problème sur vos DNS. Dans ce cas, lancez mysqld avec l'option --skip-name-resolve et utilisez uniquement le serveur localhost et les IP au format numérique dans la colonne Host des tables de droits de MySQL.

Vous pouvez forcer un client MySQL à utiliser les connexions de pipes nommés à la place de TCP/IP en spécifiant l'option --pipe ou en spécifiant un point . comme nom d'hôte. Utilisez l'option --socket pour spécifier le nom du pipe. Depuis MySQL 4.1, vous pouvez utiliser l'option --protocol=PIPE.

Il y a deux versions des utilitaires de ligne de commande MySQL sous Windows :

Binary

Description

mysql

Compilé nativement sur Windows, avec des capacités limitées d'édition de texte.

mysqlc

Compilé avec le compilateur Cygnus GNU et les bibliothèques associées, qui offrent les fonctionnalités d'édition de readline. mysqlc a été originellement prévu pour être le principal outil avec Windows 9x/Me. Il ne supporte pas le nouveau protocole d'identification de MySQL 4.1, et il n'est pas supporté à partir de MySQL 4.1. Depuis MySQL 4.1.8, il n'est plus inclus dans les distributions Windows de MySQL.

Pour utiliser mysqlc, vous devez avoir une copie de la bibliothèque cygwinb19.dll installée là où mysqlc peut la trouver. Si votre distribution ne dispose pas de cygwinb19.dll dans le dossier bin sous le dossier racine de MySQL, recherchez-le dans le dossier lib et copiez-le dans le dossier système de Windows (\Windows\system ou équivalent).

2-2-10-1 - Résolution de problèmes d'installation de MySQL sous Windows

Lorsque vous installez et lancez MySQL pour la première fois, vous pouvez rencontrer des erreurs qui empêchent MySQL de démarrer. Le but de cette section est de vous aider à comprendre et corriger ces erreurs.

Votre première ressource lorsque vous rencontrez un problème est le log d'erreurs. Le serveur MySQL utilise un log d'erreurs pour enregistrer les informations pertinentes relevant d'une erreur. Le log d'erreurs est situé dans le dossier de données, spécifié dans votre fichier de configuration my.ini. Le dossier de données par défaut est C:\mysql\data. Voir Section 5.9.1, « Le log d'erreurs ».

L'autre source d'information sur les erreurs possibles est la console, qui affiche les messages que MySQL envoie. Utilisez la commande NET START mysql depuis la ligne de commande après avoir installé mysqld comme service, pour voir apparaître les messages d'erreur du lancement de MySQL comme service. Voir Section 2.2.9.1, « Lancer MySQL comme un service Windows ».

Ci-dessous, vous trouverez les exemples des messages d'erreur les plus courants lors du premier lancement du serveur MySQL :

System error 1067 has occurred.
Fatal error: Can't open privilege tables: Table 'mysql.host' doesn't exist

Ce message survient lorsque le serveur ne peut pas trouver la table de droits mysql ou d'autres fichiers critiques. Cette erreur survient lorsque la base de mysql ou le dossier de données est installé dans un autre dossier que le dossier par défaut : C:\mysql et C:\mysql\data, respectivement.

Si vous avez installé MySQL dans un autre dossier que C:\mysql, vous devez vous assurer que le serveur MySQL le sait grâce à son fichier de configuration, my.ini. Le fichier my.ini a besoin d'être situé dans le dossier Windows, typiquement C:\WinNT ou C:\WINDOWS. Vous pouvez déterminer sa localisation exacte à partir de la valeur de la variable d'environnement WINDIR, grâce à la commande suivante :

C:\> echo %WINDIR%

Un fichier d'options peut être créé et modifié avec n'importe quel éditeur de texte, tel que Notepad. Par exemple, si MySQL est installé dans le dossier E:\mysql et que les données sont situées dans D:\MySQLdata, vous pouvez créer un fichier d'options avec une section [mysqld] pour spécifier la valeur du dossier de données et ses paramètres :

[mysqld]
# set basedir to your installation path
basedir=E:/mysql
# set datadir to the location of your data directory
datadir=D:/MySQLdata

Notez que les noms de chemins Windows sont spécifiés en utilisant des slashs, plutôt que des antislashs. Si vous utilisez des antislashs, vous devez les doubler :

[mysqld]
# set basedir to your installation path
basedir=C:\\Program Files\\mysql
# set datadir to the location of your data directory
datadir=D:\\MySQLdata

Voir Section 2.2.8, « Créer un fichier d'options ».

2-2-11 - Mettre à jour MySQL sous Windows

Lors de la mise à jour de MySQL sous Windows, suivez ces instructions :

1. Téléchargez la dernière version de MySQL pour Windows ;

2. Cherchez un horaire dans la journée où l'utilisation du serveur est faible, et où une interruption de service est acceptable ;

3. Prévenez les utilisateurs que vous allez interrompre le serveur ;

4. Stoppez le serveur MySQL (par exemple, avec la commande NET STOP MySQL ou avec l'utilitaire de Services si vous utilisez MySQL sous forme de service, ou encore avec mysqladmin shutdown) ;

5. Quittez le programme WinMySQLAdmin, s'il fonctionnait ;

6. Exécutez les scripts d'installation de la distribution Windows, en cliquant sur le bouton « Install » dans WinZip et en suivant les instructions d'installation.

Note importante : les premières versions des distributions Windows de MySQL 4.1 ne contenaient pas de programme d'installation. Voyez « Windows binary installation » pour les instructions d'installation d'une telle distribution ;

7. Vous pouvez écraser votre précédente installation (généralement installée dans C:\mysql), ou l'installer dans un nouveau dossier, comme C:\mysql4. Supprimer l'ancienne version est recommandé ;

8. Relancez le serveur (par exemple, avec NET START MySQL si vous utilisez MySQL comme un service, ou directement avec la commande mysqld) ;

9. Mettez à jour les tables de droits. La procédure est décrite dans la section Section 2.6.7, « Mise à jour des tables de droits ».

Situations possibles :

A system error has occurred.
System error 1067 has occurred.
The process terminated unexpectedly.

Cette erreur signifie que votre fichier d'options, qui est par défaut C:\my.cnf, contient une option qui n'est pas reconnue par MySQL. Vous pouvez vérifier que c'est le cas en renommant le fichier my.cnf en my_cnf.old, pour éviter que le serveur l'utilise. S'il démarre correctement, il vous faut alors identifier la partie du fichier d'options qui cause le problème. Créez un nouveau fichier my.cnf, puis déplacez progressivement toutes les parties de l'ancien fichier d'options, en redémarrant le serveur entre deux copies : vous allez identifier à coup sûr le problème.

2-2-11-1 - MySQL pour Windows face à MySQL pour Unix

MySQL pour Windows a prouvé qu'il était très stable. Cette version de MySQL a les mêmes fonctionnalités que la version Unix, à quelques exceptions :

- Windows 95 et les threads

Windows 95 perd environ 200 octets de mémoire central lors de la création de chaque thread. Chaque connexion MySQL crée un nouveau thread, ce qui fait qu'il n'est pas recommandé d'exécuter mysqld pour des durées longues sur Windows 95 si votre serveur gère de nombreuses connexions. Les autres versions de Windows ne souffrent pas du même problème ;

- Nombre limité de ports de connexions

Les systèmes Windows disposent d'environ 4,000 ports pour les connexions clientes, et après connexion, cela prend de 2 à 4 minutes avant qu'un port soit de nouveau utilisable. Dans des situations où les clients se connectent et se déconnectent à haute vitesse, il est possible que tous les ports soient utilisés, avant que les anciens ports ne redeviennent utilisables. Lorsque cela arrive, le serveur semblera inaccessible, même s'il fonctionne bien. Notez que des ports peuvent aussi être utilisés par d'autres applications, ce qui réduit encore le nombre de ports disponibles pour MySQL ;

- Lectures concurrentes

MySQL dépend des fonctions pread() et pwrite() pour être capable de mêler des INSERT et des SELECT. Actuellement, nous utilisons les mutexes pour émuler les fonctions pread()/pwrite(). Nous allons, à long terme, remplacer ce niveau d'interface par une interface virtuelle de façon à ce que nous puissions utiliser l'interface readfile()/writefile() de Windows NT/2000/XP pour gagner de la vitesse. L'implémentation courante limite le nombre de fichiers ouverts par MySQL à 1024, ce qui signifie que vous ne pouvez pas utiliser d'aussi nombreux threads concurrents sur Windows NT/2000/XP que sur Unix ;

- Blocking read

MySQL utilise une lecture bloquée pour chaque connexion. Cela signifie que :

- une connexion ne sera pas déconnectée automatiquement après 8 heures d'inactivité, comme c'est le cas sous Unix,

- si une connexion se bloque, il est impossible de la détruire sans tuer MySQL,

- mysqladmin kill ne fonctionne pas sur une connexion endormie,

- mysqladmin shutdown ne peut pas s'exécuter tant qu'il y a des connexions qui dorment.

Nous envisageons de corriger ce problème, lorsque les développeurs Windows auront fourni un palliatif ;

- DROP DATABASE

Vous ne pouvez pas détruire une base qui est utilisée par un autre thread ;

- Interrompre MySQL depuis le gestionnaire de tâches

Vous ne pouvez pas tuer MySQL depuis le gestionnaire de tâches ou avec un utilitaire d'extinction de Windows 95. Vous devez l'éteindre avec mysqladmin shutdown ;

- Noms sensibles à la casse

Les noms de fichiers sont insensibles à la casse sous Windows, ce qui fait que les noms de tables et de bases ne sont pas sensibles à la casse pour MySQL sur Windows. La seule restriction est que les noms de tables et de bases doivent être donnés avec même casse dans le nom (tout en majuscules, ou en minuscules). Voir Section 9.2.2, « Sensibilité à la casse pour les noms » ;

- Le caractère '\'

Les composants d'un chemin sont séparés par le caractère '\' sous Windows, qui est aussi le caractère de protection de MySQL. Si vous utilisez la commande LOAD DATA INFILE ou SELECT ... INTO OUTFILE, vous devez doubler le caractère '\' :

mysql> LOAD DATA INFILE "C:\\tmp\\skr.txt" INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;

Alternativement, vous pouvez utiliser les noms de fichiers au format Unix, avec le caractère '/' :

mysql> LOAD DATA INFILE "C:/tmp/skr.txt" INTO TABLE skr;
mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;

- Problèmes avec les pipes

Les pipes ne fonctionnent pas de manière fiable depuis la ligne de commande Windows. Si le pipe reçoit un caractère ^Z / CHAR(24), Windows va croire qu'il atteint la fin du fichier et arrête le programme.

C'est un problème, notamment lorsque vous essayez d'utiliser le log binaire de cette manière :

mysqlbinlog binary-log-name | mysql --user=root

Si vous rencontrez un problème lors de l'utilisation du log, et que vous pensez que c'est à cause du caractère ^Z / CHAR(24), vous pouvez utiliser le palliatif suivant :

mysqlbinlog binary-log-file --result-file=/tmp/bin.sql
mysql --user=root --execute "source /tmp/bin.sql"

Cette dernière commande peut aussi être utilisée pour lire fiablement tout fichier SQL qui contient des données binaires ;

- L'erreur Can't open named pipe

Si vous utilisez MySQL 3.22 sous NT avec les derniers clients mysql, vous allez obtenir cette erreur :

error 2017: can't open named pipe to host: . pipe...

Ceci est dû au fait que les versions modernes de MySQL utilisent des pipes nommés sous NT, par défaut. Pour éviter cette erreur, vous devez utiliser l'option --host=localhost sur les nouveaux clients, ou bien créer le fichier d'options C:\my.cnf, qui contiendra les informations suivantes :

[client]
host = localhost

Depuis la version 3.23.50, les pipes nommés sont les seuls activés si mysqld est démarré avec --enable-named-pipe ;

- Erreur Access denied for user

Si vous rencontrez l'erreur Access denied for user: 'utilisateur@unknown' to database 'mysql' lors de l'accès au serveur MySQL sur la même machine, cela signifie que MySQL ne peut résoudre proprement votre nom d'hôte.

Pour corriger cela, vous devriez créer un fichier \windows\hosts dans l'information suivante :

127.0.0.1       localhost

- ALTER TABLE

Lorsque vous exécutez la commande ALTER TABLE, la table est verrouillée, empêchant les autres threads d'y accéder. Cela est lié au fait que sous Windows, vous ne pouvez pas effacer un fichier qui est en cours d'utilisation par d'autres threads : à l'avenir, vous pourriez trouver un moyen de contourner ce problème ;

- DROP TABLE

La commande DROP TABLE sur une table qui est utilisée dans le cadre d'un MERGE ne fonctionne pas sous Windows, car le gestionnaire de MERGE garde la carte des tables cachée de la couche supérieure de MySQL. Comme Windows ne vous autorise pas à effacer des fichiers qui sont ouverts, vous devez d'abord vider de la mémoire toutes les tables du MERGE (avec la commande FLUSH TABLES) puis effacer la table MERGEavant d'effacer les tables. Nous allons corriger cela lorsque nous introduirons la notion de VIEWs ;

- DATA DIRECTORY et INDEX DIRECTORY

Les directives DATA DIRECTORY et INDEX DIRECTORY de CREATE TABLE sont ignorées sous Windows, car Windows ne supporte pas les liens symboliques.

Voici quelques problèmes connus et pas encore corrigés, si jamais quelqu'un souhaite nous aider sur la version Windows :

- ajouter des icônes pour le démarrage et l'arrêt de MySQL, dans l'installateur ;

- il serait vraiment pratique de pouvoir arrêter le processus mysqld depuis le gestionnaire de tâches. Pour le moment, il faut passer par mysqladmin shutdown ;

- le port de readline sur Windows pour pouvoir l'utiliser avec l'outil de ligne de commande mysql ;

- des versions graphiques des clients standard MySQL (mysql, mysqlshow, mysqladmin et mysqldump) seraient bien ;

- il serait bien si les fonctions de lecture et d'écriture sur les sockets de net.c pouvaient être interrompues. Cela rendrait possible l'arrêt des threads en cours avec mysqladmin kill sous Windows ;

- ajouter des macros pour utiliser les méthodes rapides d'incrément/décrément compatibles avec les threads, fournies par Windows.

2-2-12 - Installer MySQL sous Linux

Il est recommandé d'installer MySQL sous Linux en utilisant un fichier RPM. Les RPM de MySQL sont actuellement compilés sur une Red Hat en version 6.2, mais devraient fonctionner sur toute autre version de Linux qui supporte rpm et utilise glibc. Pour obtenir les paquets RPM, voyez la section Section 2.1.3, « Comment obtenir MySQL ? ».

Note : les distributions RPM de MySQL sont souvent fournies par d'autres éditeurs. Soyez prévenus qu'elles peuvent contenir des fonctionnalités différentes de celles proposées par MySQL AB, et les instructions de ce manuel ne s'appliquent pas forcément. Les instructions de l'éditeur doivent alors être utilisées.

Si vous avez des problèmes avec un fichier RPM, si vous obtenez par exemple l'erreur « Sorry, the host 'xxxx' could not be looked up », référez-vous à Section 2.8.1.2, « Notes relatives à Linux pour les distributions binaires ».

Dans la plupart des cas, vous n'aurez besoin que d'installer les paquets du serveur MySQL et du client MySQL pour obtenir une installation MySQL fonctionnelle. Les autres paquets ne sont pas nécessaires pour une installation standard. Si vous voulez utiliser la version MySQL Max qui a des fonctionnalités supplémentaires, vous devez installer le RPM MySQL-Max. Cependant, il est recommandé de ne faire cela qu'après avoir installé le RPM MySQL-server. Voir Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld ».

Si vous obtenez un message d'erreur de dépendance lors de l'installation des paquets MySQL 4.0 (par exemple, « error: removing these paquets would break dependencies: libmysqlclient.so.10 is needed by ... »), vous devriez aussi installer le paquet MySQL-shared-compat, qui inclut les bibliothèques partagées pour compatibilité ascendante (libmysqlclient.so.12 pour MySQL 4.0 et libmysqlclient.so.10 pour MySQL 3.23).

De nombreuses distributions Linux sont livrées avec MySQL 3.23, et elles sont dynamiquement liées à d'autres applications pour économiser de l'espace. Si ces bibliothèques partagées sont dans un paquet séparé (par exemple, MySQL-shared), il suffit de laisser le paquet installé, puis de mettre à jour le serveur et les clients qui sont statiquement liés à la bibliothèque, et ne dépendent pas des bibliothèques partagées. Pour les distributions qui incluent les bibliothèques partagées dans le même paquet que le serveur MySQL, (par exemple, Red Hat Linux), vous pouvez soit installer notre RPM MySQL-shared 3.23, soit utiliser le paquet MySQL-shared-compat.

Les fichiers RPM dont vous pourriez avoir besoin sont :

- MySQL-server-VERSION.i386.rpm

Le serveur MySQL. Vous en aurez besoin à moins que vous ne vouliez vous connecter à un serveur MySQL tournant sur une autre machine. Notez bien : les fichiers du RPM de serveur étaient appelés MySQL-VERSION.i386.rpm avant MySQL 4.0.10. C'est-à-dire qu'ils n'avaient pas le mot -server dans leur nom ;

- MySQL-Max-VERSION.i386.rpm

Le serveur MySQL Max. Ce serveur a des capacités supplémentaires par rapport au serveur MySQL-server. Vous devez installer le RPM MySQL-server d'abord, parce que le RPM MySQL-Max dépend de lui ;

- MySQL-client-VERSION.i386.rpm

Les programmes clients MySQL standard. Vous avez certainement besoin d'installer ce paquet ;

- MySQL-bench-VERSION.i386.rpm

Tests et bancs d'essai. Nécessite Perl et les modules RPM msql et mysql ;

- MySQL-devel-VERSION.i386.rpm

Bibliothèques et fichiers d'inclusions dont vous aurez besoin pour compiler d'autres clients MySQL, tels que les modules Perl ;

- MySQL-shared-VERSION.i386.rpm

Ce paquet contient les bibliothèques partagées (libmysqlclient.so*) que certains langages et applications recherchent pour les charger dynamiquement, afin d'utiliser MySQL ;

- MySQL-shared-compat-VERSION.i386.rpm

Ce paquet inclut la bibliothèque partagée pour MySQL 3.23 et MySQL 4.0. Installez ce paquet au lieu de MySQL-shared, si vous avec des applications installées qui utilisent dynamiquement MySQL 3.23, mais que vous voulez passer à MySQL 4.0 sans briser les dépendances. Ce paquet est disponible depuis MySQL 4.0.13 ;

- MySQL-embedded-VERSION.i386.rpm

La bibliothèque intégrée MySQL (depuis MySQL 4.0) ;

- MySQL-VERSION.src.rpm

Celui-ci contient le code source de tous les paquets précédents. Il peut donc être utilisé pour construire des fichiers RPM pour d'autres architectures (par exemple, l'Alpha ou le SPARC).

Pour voir tous les fichiers présents dans un paquet RPM, lancez :

shell> rpm -qpl MySQL-VERSION.i386.rpm

Pour effectuer une installation standard minimale, lancez :

shell> rpm -i MySQL-VERSION.i386.rpm MySQL-client-VERSION.i386.rpm

Pour installer uniquement le paquet du client MySQL, lancez :

shell> rpm -i MySQL-client-VERSION.i386.rpm

Les RPM fournissent une fonctionnalité qui permet de vérifier l'authenticité du paquet avant de l'installer. Si vous voulez en savoir plus sur cette fonctionnalité, voyez Section 2.1.4, « Vérifier l'intégrité des paquets avec MD5 ou GnuPG ».

Le fichier RPM place les données dans /var/lib/mysql. Le RPM crée aussi les entrées appropriées dans /etc/rc.d/ pour lancer le serveur automatiquement au démarrage. (Cela signifie que, si vous avez déjà effectué une installation auparavant, vous pouvez avoir besoin de faire une sauvegarde de vos fichiers de démarrage précédents si vous les changez, de façon à ne pas les perdre.) Voyez Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement » pour plus d'informations sur comment démarrer automatiquement MySQL au lancement du serveur.

Si vous voulez installer le RPM MySQL sur une ancienne distribution MySQL, qui ne supporte pas les scripts d'initialisation de /etc/init.d (directement ou via un lien symbolique), vous devez créer un lien symbolique qui pointe sur le dossier où les scripts d'initialisation sont installés. Par exemple, si ce dossier est /etc/rc.d/init.d, utilisez une de ces commandes avant d'installer le RPM, pour créer /etc/init.d sous forme de lien symbolique, qui pointe ici :

shell> cd /etc; ln -s rc.d/init.d .

Cependant, toutes les distributions Linux courantes doivent supporter le nouveau dossier /etc/init.d, car c'est imposé par la compatibilité LSB (Linux Standard Base).

Si les fichiers RPM que vous installez incluent MySQL-server, le démon mysqld devrait fonctionner après l'installation. Vous devriez être capable d'utiliser MySQL immédiatement.

Si quelque chose cloche, vous pouvez trouver plus d'informations dans le chapitre d'installation binaire. Voir Section 2.3, « Installer MySQL sur d'autres systèmes type Linux ».

Note : les comptes qui sont listés dans les tables de droits MySQL initiales n'ont pas de mot de passe. Après démarrage du serveur, il est recommandé de configurer ces mots de passe, en suivant les instructions de la section Section 2.5, « Procédure de postinstallation ».

2-2-13 - Installer MySQL sur Mac OS X

Depuis MySQL 4.0.11, vous pouvez installer MySQL sur Mac OS X 10.2 ("Jaguar") avec le paquet binaire Mac OS X PKG au lieu d'utiliser la distribution binaire compressée. Notez que les anciennes versions de Mac OS X (i.e. 10.1.x) ne sont pas supportées par ce paquet.

Le paquet est situé dans une image disque (.dmg), que vous devez monter en double-cliquant son icône sur le Finder. Le disque devrait alors se monter, et afficher son contenu.

Pour télécharger MySQL, voyez Section 2.1.3, « Comment obtenir MySQL ? ».

Note : avant de lancer l'installation, assurez-vous qu'il n'y a pas de serveur MySQL en fonctionnement ! Arrêtez tous les serveurs MySQL avant de continuer, soit en utilisant l'application manager (pour les serveurs Mac OS X) ou via mysqladmin shutdown en ligne de commande.

Pour installer le paquet MySQL, double-cliquez sur l'icône. Cela va lancer l'installeur de paquet MacOSX, qui vous guidera durant l'installation.

À cause d'un bogue dans l'installeur de paquets MySQL, vous pourriez rencontrer le message d'erreur

You cannot install this software on this disk. (null)

dans le dialogue de sélection du disque de destination. Si cette erreur survient, cliquez sur le bouton de retour (Go Back) pour retourner à l'écran précédent. Puis, cliquez sur le bouton d'avance (Continue) pour passer à nouveau à la page de sélection des disques. Nous avons indiqué ce bogue à Apple, qui travaille sur le sujet.

Le paquet Mac OS X de MySQL va s'installer lui-même dans le dossier /usr/local/mysql-VERSION et va aussi ajouter un lien symbolique /usr/local/mysql, qui pointe sur le nouveau dossier. Si un dossier appelé /usr/local/mysql existe déjà, il sera renommé en /usr/local/mysql.bak. De plus, il va installer les tables de droits MySQL en exécutant le script mysql_install_db après l'installation.

Le schéma d'installation est semblable à celui de la distribution binaire, tous les programmes MySQL sont situés dans le dossier /usr/local/mysql/bin. Les sockets MySQL sont installées dans le fichier /etc/mysql.sock par défaut. Voir Section 2.1.5, « Dispositions d'installation ».

L'installation requiert un compte nommé mysql (qui existe par défaut en Mac OS X 10.2 et plus récents).

Si vous utilisez Mac OS X Server, vous devez avoir déjà une version de MySQL installée :

Version Mac OS X Server

Version MySQL

10.2-10.2.2

3.23.51

10.2.3-10.2.6

3.23.53

10.3

4.0.14

10.3.2

4.0.16

Cette section du manuel couvre l'installation du paquet binaire MySQL pour Mac OS X uniquement. Assurez-vous de bien lire l'aide d'Apple concernant l'installation de MySQL. (Lancez le visualiseur d'aide, sélectionnez la rubrique "Serveur Mac OS X", et faites une recherche sur "MySQL", puis lisez l'entrée appelée "Installing MySQL".)

Notez bien que la version preinstallée de MySQL sur Mac OS X Server peut être lancée avec la commande safe_mysqld au lieu de mysqld_safe !

Si vous avez utilisé auparavant les paquets MySQL de Marc Liyanage pour Mac OS X, depuis le site de http://www.entropy.ch, vous pouvez simplement suivre le processus de mise à jour, en utilisant les conseils de ses pages.

Si vous faites une mise à jour depuis les versions de Marc, ou depuis une ancienne version de MySQL pour Mac OS X Server, avec le nouveau paquet officiel, vous devrez convertir les tables de droits. Voir Section 2.6.3, « Passer de la version 3.23 à la version 4.0 ».

Si vous voulez lancer automatiquement MySQL au démarrage du système, vous devez aussi installer le MySQL Startup Item. Depuis MySQL 4.0.15, il fait partie du disque d'installation MySQL pour Mac OS X dans un paquet séparé. Il suffit de double-cliquer sur l'icône MySQLStartupItem.pkg et de suivre les instructions pour l'installer.

Notez que le MySQL Startup Item ne doit être installé qu'une seule fois. Il n'y a pas besoin de le mettre à jour avec les versions de MySQL.

Le MySQL Startup Item est installé dans le dossier /Library/StartupItems/MySQLCOM. (Avant MySQL 4.1.2, le dossier était /Library/StartupItems/MySQL, mais cela créait un conflit avec le MySQL Startup Item du serveur Mac OS X Server.) Il ajoute la variable MYSQLCOM=-YES- au fichier de configuration /etc/hostconfig. Si vous voulez désactiver le démarrage automatique de MySQL, modifiez simplement la variable avec MYSQLCOM=-NO-.

Sur Mac OS X Server, l'installation par défaut de MySQL utilise la variable MYSQL dans /etc/hostconfig. Le MySQL Startup Item désactive cette variable en lui donnant la valeur de MYSQL=-NO-. Cela évite que des conflits de démarrage surviennent, si la variable MYSQLCOM est utilisée par MySQL Startup Item. Cependant, cela n'éteint pas un serveur MySQL en fonctionnement.

Après cette installation, vous pouvez lancer le serveur MySQL avec ces commandes, exécutées dans le terminal. Notez bien que vous devez avoir des droits d'administrateur pour cela !

Si vous avez installé le MySQL Startup Item :

shell> sudo /Library/StartupItems/MySQL/MySQL start
(Enter your password, if necessary)
(Press Control-D or enter "exit" to exit the shell)

Si vous n'avez pas installé le MySQL Startup Item :

shell> cd /usr/local/mysql
shell> sudo ./bin/mysqld_safe
(Enter your password)
(Press CTRL+Z)
shell> bg
(Press CTRL+D to exit the shell)

Vous devez alors être capable de vous connecter au serveur MySQL, notamment en exécutant la commande /usr/local/mysql/bin/mysql.

Note : cette procédure ne configure aucun mot de passe pour les comptes MySQL. Après avoir suivi cette procédure, lisez la section Section 2.5, « Procédure de postinstallation », pour les instructions de postinstallation et les tests.

Vous pouvez faire cela avec les commandes suivantes :

/usr/local/mysql/bin/mysqladmin -u root password <password>
/usr/local/mysql/bin/mysqladmin -u root -h `hostname` password <password>

Vous pouvez aussi ajouter des alias à votre fichier de ressources Shell, pour accéder à mysql et mysqladmin depuis la ligne de commande :

alias mysql '/usr/local/mysql/bin/mysql'
alias mysqladmin '/usr/local/mysql/bin/mysqladmin'

Alternativement, vous pouvez simplement ajouter /usr/local/mysql/bin à votre variable d'environnement PATH, par exemple, en ajoutant la ligne suivante dans votre fichier $HOME/.tcshrc :

setenv PATH ${PATH}:/usr/local/mysql/bin

Si aucun fichier .tcshrc n'existe dans votre dossier d'utilisateur, créez-le avec un éditeur texte.

Notez que l'installation d'un nouveau paquet MySQL ne supprime pas le dossier d'une vieille installation : l'installeur de Mac OS X n'offre pas encore les fonctionnalités nécessaires pour mettre à jour proprement une vieille version.

Après avoir copié les fichiers de bases depuis votre ancien dossier vers le nouveau, et que vous avez réussi à redémarrer MySQL avec la nouvelle version, vous devriez pensez à supprimer les vieilles versions des fichiers, situées dans /Library/Receipts/mysql-<version>.pkg.

2-2-14 - Installer MySQL sur NetWare

Porter MySQL sur NetWare a été un effort dirigé par Novell. Les clients Novell seront heureux de constater que NetWare 6.5 est distribué avec les exécutables MySQL et une licence de support commercial pour tous les serveurs qui fonctionnent sur cette version de NetWare.

MySQL pour NetWare est compilé avec une combinaison de Metrowerks CodeWarrior pour NetWare et d'une version spéciale de compilation de GNU autotools.

Les derniers paquets binaires pour NetWare sont disponibles sur le site http://dev.mysql.com/downloads/. Voir Section 2.1.3, « Comment obtenir MySQL ? ».

Pour pouvoir héberger un serveur MySQL, un serveur NetWare doit avoir les prérequis suivants :

- NetWare version 6.5, ou NetWare 6.0 avec Support Pack 3 installé (vous pouvez obtenir cela sur http://support.novell.com/filefinder/13659/index.html). Le système doit passer les prérequis minimaux de Novell pour faire tourner cette version de NetWare ;

- le système doit satisfaire les prérequis minimaux de NetWare ;

- les données MySQL, ainsi que les logiciels, doivent être installés dans un volume NSS ; les volumes traditionnels ne sont pas supportés.

Les fichiers binaires de NetWare sont téléchargeables sur le site http://www.mysql.com/downloads/.

Pour installer MySQL pour NetWare, utilisez la procédure suivante :

1. Si vous mettez à jour une ancienne installation, stoppez le serveur MySQL. Vous pouvez le faire en console, avec la commande suivante :

SERVER:  mysqladmin -u root shutdown

2. Connectez-vous sur le serveur depuis une machine cliente, avec un accès à l'endroit où vous voulez installer MySQL ;

3. Décompressez l'archive binaire zip sur le serveur. Assurez-vous d'autoriser les chemins utilisés dans l'archive zip. Il est sécuritaire d'utiliser le dossier SYS:\.

Si vous mettez à jour une ancienne installation, vous pouvez copier le dossier de données (par exemple, SYS:MYSQL\DATA), ainsi que my.cnf si vous l'avez modifié. Vous pouvez alors effacer l'ancienne copie de MySQL ;

4. Vous pouvez renommer le dossier avec un nom plus cohérent, et facile à utiliser. Nous recommandons d'utiliser SYS:MYSQL ; les exemples du manuel feront référence à ce dossier d'installation ;

5. Depuis la console du serveur, ajoutez un chemin de recherche pour le dossier contenant les NLM MySQL. Par exemple :

SERVER:  SEARCH ADD SYS:MYSQL\BIN

6. Installez la base de données initiale, si nécessaire, en exécutant le script mysql_install_db depuis la console ;

7. Lancez le serveur MySQL en utilisant le script mysqld_safe depuis la console ;

8. Pour finir l'installation, vous devriez aussi installer les commandes suivantes dans le fichier autoexec.ncf. Par exemple, si votre installation MySQL est dans le dossier SYS:MYSQL et que vous voulez que MySQL se lance automatiquement, vous pouvez ajouter ces lignes :

#Starts the MySQL 4.0.x database server
SEARCH ADD SYS:MYSQL\BIN
MYSQLD_SAFE

Si vous utilisez MySQL sur NetWare 6.0, nous vous recommandons fortement d'ajouter l'option --skip-external-locking à la ligne de commande :

#Starts the MySQL 4.0.x database server
SEARCH ADD SYS:MYSQL\BIN
MYSQLD_SAFE --skip-external-locking

Il est aussi nécessaire d'utiliser CHECK TABLE et REPAIR TABLE au lieu de myisamchk, car myisamchk utilise un verrouillage externe. Le verrouillage externe est reconnu pour poser des problèmes sur NetWare 6.0, ce problème a été supprimé sur NetWare 6.5.

mysqld_safe sur NetWare fournit un écran de présence. Lorsque vous déchargez (extinction) le NLM mysqld_safe, l'écran ne se ferme pas par défaut. Au lieu de cela, il demande une action de l'utilisateur :

*<NLM has terminated; Press any key to close the screen>*

Si vous voulez que NetWare ferme automatiquement cet écran, utilisez l'option --autoclose de mysqld_safe. Par exemple :

#Starts the MySQL 4.0.x database server
SEARCH ADD SYS:MYSQL\BIN
MYSQLD_SAFE --autoclose

Le comportement de mysqld_safe sur NetWare est décrit plus en détail dans Section 5.1.3, « safe_mysqld, le script père de mysqld ».

S'il y avait une installation MySQL sur le serveur, assurez-vous de vérifier les commandes de démarrage de MySQL dans autoexec.ncf, et éditez ou effacez-les autant que nécessaire.

Note : les comptes qui sont stockés dans les tables de droits n'ont pas de mot de passe initial. Après avoir lancé le serveur, il est recommandé de leur donner des mots de passe en suivant les instructions de la section Section 2.5, « Procédure de postinstallation ».

2-3 - Installer MySQL sur d'autres systèmes type Linux

Cette section couvre l'installation des distributions binaires de MySQL, qui sont fournies pour différentes plates-formes au format d'archive tar (les fichiers avec l'extension .tar.gz). Voyez Section 2.1.2.5, « Binaires compilés par MySQL AB » pour une liste détaillée.

Pour télécharger une distribution source de MySQL, voyez Section 2.1.3, « Comment obtenir MySQL ? ».

En plus de ces paquets génériques, nous offrons aussi des compilations spécifiques pour certaines plates-formes. Voyez Section 2.2, « Installation standard rapide de MySQL » pour plus d'informations sur leur installation.

Vous avez besoin des utilitaires suivants pour installer une archive tar MySQL :

- GNU gunzip pour décompresser la distribution ;

- un utilitaire tar raisonnable pour ouvrir l'archive. GNU tar est reconnu pour cette tâche. Certains systèmes d'exploitation disposent d'une version préinstallée de tar qui pose des problèmes. Par exemple, Sun tar et Mac OS X tar ont des soucis avec les noms de fichiers longs. Dans ce cas, installez GNU tar. Sur Mac OS X, vous pouvez installer le logiciel préinstallé gnutar.

Si vous rencontrez des problèmes, utilisez toujours mysqlbug pour poser des questions à la liste MySQL. Même si le problème n'est pas un bogue, mysqlbug rassemble des informations sur le système qui nous aideront à résoudre votre problème. Si vous n'utilisez pas mysqlbug, vous réduisez les chances de résolution de votre problème. Vous trouverez mysqlbug dans le dossier bin après avoir décompressé la distribution. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

Les commandes de base que vous devez exécuter pour installer MySQL à partir des sources sont :

shell> groupadd mysql
shell> useradd -g mysql mysql
shell> cd /usr/local
shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql
shell> cd mysql
shell> scripts/mysql_install_db
shell> chown -R root  .
shell> chown -R mysql data
shell> chgrp -R mysql .
shell> bin/mysqld_safe --user=mysql &

Pour les versions de MySQL plus anciennes que la 4.0, remplacez bin/safe_mysqld par bin/mysqld_safe dans la commande finale.

Note : cette procédure ne configure aucun mot de passe pour les comptes MySQL. Après avoir suivi cette procédure, lisez la section Section 2.5, « Procédure de postinstallation », pour les instructions de postinstallation et les tests.

Plus de détails suivent.

Pour installer une distribution binaire, suivez les étapes ci-après, puis reportez-vous à Section 2.5, « Procédure de postinstallation », pour la configuration postinstallation et les tests :

1. Ajoutez un utilisateur et un groupe avec les droits desquels mysqld fonctionnera :

shell> groupadd mysql
shell> useradd -g mysql mysql

Ces commandes ajoutent le groupe mysql group et l'utilisateur mysql. La syntaxe de useradd et de groupadd peut varier de façon significative suivant les versions d'Unix. Elles peuvent aussi s'appeler adduser et addgroup. Vous pouvez aussi souhaiter nommer le groupe et l'utilisateur autrement que mysql.

2. Choisissez le dossier dans lequel vous voulez décompresser la distribution, et placez-vous-y. Dans l'exemple suivant, nous allons décompresser la distribution dans le dossier /usr/local. Les instructions suivantes supposeront que vous avez les droits pour créer des dossiers de fichiers dans /usr/local. Si ce dossier est protégé, vous aurez besoin des droits de root pour faire l'installation.

shell> cd /usr/local

3. Téléchargez la distribution sur l'un des sites listés sur Section 2.1.3, « Comment obtenir MySQL ? ».

Les archives MySQL tar ont des noms de la forme mysql-VERSION-OS.tar.gz, où VERSION est le numéro de version (par exemple, 4.0.17), et OS indique le système d'exploitation de la distribution (par exemple, pc-linux-gnu-i586). Pour une version donnée, les distributions binaires pour toutes les plates-formes sont compilées sur les mêmes sources MySQL.

4. Décompressez la distribution dans le répertoire courant :

shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf -
shell> ln -s full-path-to-mysql-VERSION-OS mysql

La commande tar crée un dossier appelé mysql-VERSION-OS. La commande ln crée un lien symbolique dans ce dossier. Cela vous laisse le moyen de transférer facilement votre installation dans le dossier /usr/local/mysql.

Avec GNU tar, il n'est pas nécessaire d'utiliser séparément gunzip. Vous pouvez remplacer la première ligne par celle-ci pour décompresser et ouvrir l'archive dans le même temps :

shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz

5. Placez-vous dans le répertoire racine de la distribution décompressée :

shell> cd mysql

Vous trouverez plusieurs fichiers et sous-dossiers dans le dossier mysql. Le plus important pour l'installation sont les dossiers bin et scripts.

- bin

Ce dossier contient les programmes clients et le serveur. Vous devez ajouter le chemin complet de ce dossier à votre variable PATH pour que votre shell trouve MySQL facilement. Voir Annexe E, Variables d'environnement.

- scripts

Ce dossier contient le script mysql_install_db, utilisé pour initialiser la base mysql, qui contient les tables de droits du serveur.

6. Si vous n'avez jamais installé MySQL auparavant, vous devez créer les tables de droits :

shell> scripts/mysql_install_db

Notez que pour les versions de MySQL plus anciennes que la version 3.22.10, mysql_install_db laisse le serveur fonctionner après avoir créé les tables. Ce n'est plus vrai : vous devez redémarrer le serveur après avoir exécuté ce script.

7. Changez le propriétaire du binaire pour root et le propriétaire des données pour l'utilisateur qui va faire tourner mysqld. En supposant que vous avez installé les données dans le dossier /usr/local/mysql, la commande est :

shell> chown -R root  .
shell> chown -R mysql data
shell> chgrp -R mysql .

La première commande change l'attribut owner du fichier pour root. La seconde change l'attribut owner du dossier de données pour l'utilisateur mysql. La troisième change l'attribut group pour le groupe mysql.

8. Si vous voulez que MySQL démarre automatiquement après le démarrage de votre serveur, vous pouvez copier le fichier support-files/mysql.server là où votre serveur recherche les scripts de démarrage. Plus d'informations sur support-files/mysql.server sont disponibles dans Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ».

9. Vous pouvez configurer de nouveaux comptes en utilisant le script bin/mysql_setpermission si vous installez les modules Perl DBI et DBD::mysql. Pour des instructions, voyez Section 2.9, « Commentaires sur l'installation de Perl ».

10. Si vous voulez utiliser mysqlaccess et avoir accès à la distribution MySQL dans un dossier non standard, vous devez modifier le chemin où mysqlaccess va rechercher le client mysql. Éditez le script bin/mysqlaccess à la ligne 18, environ. Recherchez une ligne qui ressemble à ceci :

$MYSQL     = '/usr/local/bin/mysql';    # path to mysql executable

Changez le dossier pour qu'il prenne la valeur du chemin où mysql est situé. Si vous ne le faites pas, vous allez recevoir une erreur Broken pipe lorsque vous utilisez mysqlaccess.

Après que tout a été ouvert et installé, il faut tester votre distribution :

Lancez le serveur MySQL avec les commandes suivantes :

shell> bin/mysqld_safe --user=mysql &

Pour les versions de MySQL plus anciennes que 4.0, remplacez bin/safe_mysqld par bin/mysqld_safe dans la commande.

Puis, passez à Section 5.1.3, « safe_mysqld, le script père de mysqld », et Section 2.5, « Procédure de postinstallation ».

Note : cette procédure ne configure aucun mot de passe pour les comptes MySQL. Après avoir suivi cette procédure, lisez la section Section 2.5, « Procédure de postinstallation », pour les instructions de postinstallation et les tests.

2-4 - Installation de MySQL avec une distribution source

Avant de procéder à l'installation à partir des sources, vérifiez auparavant que notre distribution binaire pour votre plate-forme ne fonctionne pas. Nous faisons un maximum d'efforts pour nous assurer que nos binaires sont compilés avec les meilleures options possible.

Les distributions source de MySQL sont fournies sous forme d'archive tar, dont le nom est sous la forme mysql-VERSION.tar.gz, où VERSION est un nombre comme 5.0.6-beta.

Pour télécharger une distribution source de MySQL, voyez Section 2.1.3, « Comment obtenir MySQL ? ».

Vous avez besoin des outils suivants pour compiler et installer MySQL à partir des sources :

- GNU gunzip pour décompresser la distribution ;

- un programme tar pour désarchiver la distribution. GNU tar est connu pour fonctionner. Le tar de Sun connaît quelques problèmes ;

- un compilateur C++ ANSI fonctionnel. gcc >= 2.95.2, egcs >= 1.0.2 ou egcs 2.91.66, SGI C++, et SunPro C++ sont quelques-uns des compilateurs réputés pour fonctionner. libg++ n'est pas nécessaire si vous utilisez gcc. gcc 2.7.x souffre d'un bogue qui l'empêche de compiler quelques fichiers C++ correctement écrits, tels que sql/sql_base.cc. Si vous disposez seulement de gcc 2.7.x, vous devez mettre à jour votre gcc afin de compiler MySQL. gcc 2.8.1 est aussi reconnu pour rencontrer des problèmes sur certaines plates-formes, il devrait donc être désactivé si un autre compilateur existe pour la plate-forme.

gcc >= 2.95.2 est recommandé pour compiler MySQL dans ses versions 3.23.x ;

- un bon programme make. GNU make est une fois de plus recommandé et est quelquefois requis. Si vous rencontrez des problèmes, nous vous recommandons d'essayer GNU make 3.75 ou supérieur.

Si vous utilisez une version récente de gcc, suffisamment récente pour reconnaître l'option -fno-exceptions, il est très important que vous l'utilisiez. Sinon, vous risquez de compiler un binaire qui crashe aléatoirement. Nous recommandons donc l'utilisation de -felide-constructors et -fno-rtti en même temps que -fno-exceptions. En cas de doute, faites la chose suivante :

CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions \
-fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static

Sur la plupart des systèmes, il en résultera un binaire rapide et stable.

Si vous rencontrez des problèmes, utilisez toujours mysqlbug pour poster des questions sur les listes internes. Même si le problème n'est pas un bogue, mysqlbug rassemble des informations sur le système qui aidera les autres à résoudre votre problème. En n'utilisant pas mysqlbug, vous amoindrissez vos chances d'obtenir une solution à votre problème ! Vous trouverez mysqlbug dans le répertoire scripts après avoir désarchivé la distribution. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

2-4-1 - Installation depuis les sources : présentation

Les commandes de pages que vous devez exécuter pour installer la distribution source de MySQL sont :

shell> groupadd mysql
shell> useradd -g mysql mysql
shell> gunzip < mysql-VERSION.tar.gz | tar -xvf -
shell> cd mysql-VERSION
shell> ./configure --prefix=/usr/local/mysql
shell> make
shell> make install
shell> cp support-files/my-medium.cnf /etc/my.cnf
shell> cd /usr/local/mysql
shell> bin/mysql_install_db
shell> chown -R root  .
shell> chown -R mysql var
shell> chgrp -R mysql .
shell> bin/mysqld_safe --user=mysql &

Pour les versions de MySQL 4.0 ou plus récentes, remplacez bin/safe_mysqld par bin/mysqld_safe dans la commande finale.

Si vous commencez avec un paquet RPM, commencez comme ceci :

shell> rpm --rebuild --clean MySQL-VERSION.src.rpm

Cela va compiler un paquet RPM binaire que vous pouvez installer.

Note : cette procédure ne configure aucun mot de passe pour les comptes MySQL. Après avoir suivi la procédure, passez à la section Section 2.5, « Procédure de postinstallation », pour les instructions de postinstallation et de tests.

Une description plus détaillée suit.

1. Ajoutez un utilisateur et un groupe pour mysqld comme ceci :

shell> groupadd mysql
shell> useradd -g mysql mysql

Ces commandes ajoutent le groupe mysql et l'utilisateur mysql. La syntaxe de useradd et groupadd peut différer légèrement suivant votre version d'Unix. Elles peuvent aussi s'appeler adduser et addgroup.

Vous pouvez donner un autre nom à l'utilisateur et au groupe, à la place de mysql. Si vous le faites, adaptez les commandes dans les prochaines instructions.

2. Choisissez un dossier dans lequel vous allez décompresser les sources de MySQL. Rendez-vous dans ce dossier.

3. Téléchargez une distribution sur un des sites listés sur Section 2.1.3, « Comment obtenir MySQL ? ».

4. Décompressez la distribution dans le dossier courant :

shell> gunzip < /path/to/mysql-VERSION.tar.gz | tar xvf -

Cette commande crée un dossier appelé mysql-VERSION.

Avec GNU tar, il n'est pas besoin de faire un appel séparé à gunzip. Vous pouvez utiliser cette commande alternative pour décompresser et extraire la distribution :

shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz

5. Placez-vous à la racine de la distribution :

shell> cd mysql-VERSION

Notez qu'actuellement, vous devez configurer et compiler MySQL depuis la racine de la distribution. Vous ne pouvez pas la compiler ailleurs.

6. Configurez votre version et compilez le tout :

shell> ./configure --prefix=/usr/local/mysql
shell> make

Lorsque vous exécutez le code configure, vous pouvez aussi ajouter des options. Utilisez la commande ./configure --help pour avoir une liste des options disponibles. Section 2.4.2, « Options habituelles de configure », présente certaines options pratiques.

Si configure échoue et que vous allez envoyer un courriel aux listes MySQL pour demander de l'aide, ajouter surtout le contenu du fichier config.log qui vous semble pertinent. Incluez aussi les dernières lignes affichées par configure. Postez votre rapport de bogue avec le script mysqlbug. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

Si la compilation échoue, voyez la section Section 2.4.4, « Problèmes de compilation? », pour avoir de l'aide immédiate sur les problèmes les plus courants.

7. Installez la distribution :

shell> make install

Si vous voulez écrire un fichier d'options, utilisez un des fichiers présents dans le dossier support-files. Par exemple,

shell> cp support-files/my-medium.cnf /etc/my.cnf

Il est possible que vous ayez à exécuter certaines commandes en tant que root.

Si vous voulez ajouter le support des tables InnoDB, vous devez éditer le fichier /etc/my.cnf, supprimer le caractère # dans les lignes d'options qui commencent par innodb_..., et donnez à ces options la valeur que vous souhaitez. Voyez Section 4.3.2, « Fichier d'options my.cnf » et Section 15.4, « Configuration InnoDB ».

8. Déplacez-vous dans le dossier d'installation :

shell> cd /usr/local/mysql

9. Si vous n'avez jamais installé MySQL auparavant, vous devez créer les tables de droits :

shell> bin/mysql_install_db

Si vous utilisez la commande en tant que root, il est recommandé d'utiliser l'option --user présentée. La valeur de l'option doit être le nom de l'utilisateur créé dans les premières étapes pour faire fonctionner le serveur. Si vous exécutez la commande après vous être connecté sous cet utilisateur, vous pouvez omettre l'utilisation de l'option --user.

Notez que pour les versions de MySQL plus anciennes que la version 3.22.10, mysql_install_db laisse le serveur en fonctionnement après avoir créé les tables. Ce n'est plus vrai. Vous devez démarrer le serveur vous-même après avoir fait les dernières étapes d'installation.

10. Changez le propriétaire des exécutables pour les donner à root et le propriétaire des données pour les donner à mysqld. En supposant que vous êtes dans le dossier d'installation, /usr/local/mysql, la commande ressemble à ceci :

shell> chown -R root  .
shell> chown -R mysql var
shell> chgrp -R mysql .

La première commande modifie l'attribut owner des fichiers pour les donner à root user. La seconde donne les fichiers de données à mysql. La troisième commande change le groupe group pour les donner au groupe mysql.

11. Si vous voulez que MySQL se lance automatiquement au démarrage de votre serveur, vous pouvez copier le fichier support-files/mysql.server là ou votre système cherche les fichiers de démarrage. Plus d'informations sont disponibles dans le script support-files/mysql.server et dans la section Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ».

12. Vous pouvez créer de nouveaux comptes en utilisant le script bin/mysql_setpermission si vous avez installé les modules Perl DBI et DBD::mysql. Pour les instructions, voyez Section 2.9, « Commentaires sur l'installation de Perl ».

Après avoir installé tout, il est recommandé d'initialiser et tester votre installation avec cette commande :

shell> /usr/local/mysql/bin/mysqld_safe --user=mysql &

Pour les versions de MySQL plus anciennes que 4.0, remplacez bin/safe_mysqld par bin/mysqld_safe dans la commande.

Si la commande échoue immédiatement avec le message mysqld ended, vous pouvez trouver certaines informations dans le fichier mysql-data-directory/'hostname'.err.

Plus d'informations sur mysqld_safe sont disponibles dans Section 5.1.3, « safe_mysqld, le script père de mysqld ».

Note : les comptes qui sont listés dans les tables de droits MySQL n'ont pas de mot de passe initial. Après le démarrage du serveur, il est recommandé de configurer les mots de passe en utilisant les instructions de Section 2.5, « Procédure de postinstallation ».

2-4-2 - Options habituelles de configure

Le script configure vous donne un bon moyen de contrôler la configuration de votre distribution MySQL. Habituellement, vous faites cela en spécifiant les options dans la ligne de commande de configure. Vous pouvez aussi affecter le comportement de configure en utilisant certaines variables d'environnement. Voir Annexe E, Variables d'environnement. Pour une liste des options supportées par configure, exécutez cette commande :

shell> ./configure --help

Les options de configure les plus utilisées sont décrites ci-après.

- Pour ne compiler que les bibliothèques et programmes clients, et non le serveur, utilisez l'option --without-server :

shell> ./configure --without-server

Si vous n'avez pas de compilateur C++, mysql ne compilera pas (c'est le programme client qui requiert C++). Dans ce cas, vous pouvez supprimer la partie de code dans configure qui vérifie l'existence d'un compilateur C++, puis exécuter ./configure avec l'option --without-server. La compilation essaiera encore de construire mysql, mais vous pouvez ignorer les messages d'erreur concernant mysql.cc. (Si make stoppe, essayez make -k pour dire de continuer même si on rencontre des erreurs.)

- Si vous voulez obtenir une bibliothèque MySQL intégrée (libmysqld.a) vous devez utiliser l'option --with-embedded-server.

- Si vous ne voulez pas que vos fichiers de log et bases de données soient dans /usr/local/var, utiliser une commande configure se rapprochant de l'une des commandes suivantes :

shell> ./configure --prefix=/usr/local/mysql
shell> ./configure --prefix=/usr/local \
--localstatedir=/usr/local/mysql/data

La première change le préfixe de l'installation pour que tout soit installé dans /usr/local/mysql au lieu de /usr/local par défaut. La seconde commande préserve le préfixe d'installation par défaut, mais change le répertoire par défaut pour les bases de données (normalement /usr/local/var) en /usr/local/mysql/data. Après que vous ayez compilé MySQL, vous pouvez changer ces options dans les fichiers d'options. Voir Section 4.3.2, « Fichier d'options my.cnf ».

- Si vous utilisez Unix et que vous voulez que la socket de MySQL soit à un autre endroit que celui par défaut (normalement /tmp ou /var/run) utilisez une commande configure comme celle-ci :

shell> ./configure \
--with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock

Notez que le fichier donné doit avoir un chemin absolu ! Vous pourrez aussi changer le chemin vers mysql.sock plus tard en utilisant les fichiers d'options de MySQL. Voir Section A.4.5, « Comment protéger ou changer le fichier socket /tmp/mysql.sock ».

- Si vous voulez compiler des programmes liés statiquement (par exemple, pour créer une distribution binaire, pour obtenir plus de vitesse, ou pour résoudre des problèmes avec quelques distributions RedHat Linux), exécutez configure de la manière suivante :

shell> ./configure --with-client-ldflags=-all-static \
--with-mysqld-ldflags=-all-static

- Si vous utilisez gcc et n'avez pas libg++ ou libstdc++ d'installés, vous pouvez dire à configure d'utiliser gcc en tant que compilateur C++ :

shell> CC=gcc CXX=gcc ./configure

Quand vous utilisez gcc en tant que compilateur C++, aucune tentative de liaison avec libg++ ou libstdc++ ne sera effectuée. Il peut être bon d'utiliser cette méthode même si vous avez les bibliothèques citées, car quelques versions de celles-ci ont causé des problèmes à des utilisateurs MySQL par le passé.

Voici quelques variables d'environnement à définir selon le compilateur que vous utilisez :

- gcc 2.7.2 :

CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors"

- egcs 1.0.3a :

CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors \
-fno-exceptions -fno-rtti"

- gcc 2.95.2 :

CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \
-felide-constructors -fno-exceptions -fno-rtti"

- pgcc 2.90.29 ou plus récents :

CFLAGS="-O3 -mpentiumpro -mstack-align-double" CXX=gcc \
CXXFLAGS="-O3 -mpentiumpro -mstack-align-double \
-felide-constructors -fno-exceptions -fno-rtti"

Dans la plupart des cas, vous pouvez obtenir un binaire MySQL raisonnablement optimal en utilisant les options de la table précédente et en ajoutant les options suivantes aux lignes de configuration :

--prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static

En d'autres termes, la ligne de configuration ressemble à ce qui suit pour les versions récentes de gcc :

CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \
-felide-constructors -fno-exceptions -fno-rtti" ./configure \
--prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static

Les binaires que nous fournissons sur le site de MySQL à http://www.mysql.com/ sont tous compilés avec une optimisation totale et devraient être parfaits pour la plupart des utilisateurs. Voir Section 2.1.2.5, « Binaires compilés par MySQL AB ». Il y a quelques choses que vous pouvez modifier pour rendre le binaire encore plus rapide, mais cela est réservé aux utilisateurs avancés. Voir Section 7.5.4, « Influences de la compilation et des liaisons sur la vitesse de MySQL ».

Si la génération échoue et produit des erreurs disant que votre compilateur ou outil de liaison n'est pas capable de créer la bibliothèque partagée libmysqlclient.so.# ('#' étant un numéro de version), vous pouvez contourner ce problème en donnant l'option --disable-shared à configure. Dans ce cas, configure ne générera pas de bibliothèque partagée libmysqlclient.so.#.

- Par défaut, MySQL utilise le jeu de caractères ISO-8859-1 (Latin1). Pour changer le jeu par défaut, utilisez l'option --with-charset :

shell> ./configure --with-charset=CHARSET

CHARSET peut être l'un des big5, cp1251, cp1257, czech, danish, dec8, dos, euc_kr, gb2312, gbk, german1, hebrew, hp8, hungarian, koi8_ru, koi8_ukr, latin1, latin2, sjis, swe7, tis620, ujis, usa7, ou win1251ukr. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

Depuis MySQL 4.1.1, la collation par défaut peut aussi être spécifiée. MySQL utilise la collation latin1_swedish_ci. Pour le changer, utilisez l'option --with-collation :

shell> ./configure --with-collation=COLLATION

Pour changer le jeu de caractères et la collation, utilisez les options --with-charset et --with-collation. La collation doit être valide pour le jeu de caractères spécifié. Utilisez la commande SHOW COLLATION pour déterminer les collations valides pour un jeu de caractères donné.

Si vous voulez convertir les caractères entre le serveur et le client, regardez du côté de la commande SET CHARACTER SET. Voir Section 13.5.2.8, « Syntaxe de SET ».

Attention : si vous changez les jeux de caractères après avoir créé des tables, vous devrez exécuter myisamchk -r -q --set-character-set=charset sur chaque table. Vos index pourraient être stockés de manière incorrecte sinon. (Cela peut survenir si vous installez MySQL, créez quelques tables, puis reconfigurez MySQL pour qu'il utilise un jeu de caractères différent et le réinstallez.)

Avec l'option --with-extra-charsets=LIST vous pouvez définir les jeux de caractères additionnels à compiler dans le serveur.

Ici LIST est soit une liste de jeux de caractères séparés par des espaces, soit complex pour inclure tous les jeux de caractères ne pouvant être chargés dynamiquement, ou encore all pour inclure tous les jeux de caractères dans les binaires.

- Pour configurer MySQL avec le code de débogage, utilisez l'option --with-debug :

shell> ./configure --with-debug

Cela alloue un vérificateur d'allocation de mémoire qui peut trouver quelques erreurs et qui fournit des informations sur ce qui se produit. Voir Section D.1, « Déboguer un serveur MySQL ».

- Si vos programmes clients utilisent les threads, vous avez besoin de compiler une version sûre pour les threads de la bibliothèque du client MySQL avec l'option de configuration --enable-thread-safe-client. Cela créera une bibliothèque libmysqlclient_r avec laquelle vous devez lier vos applications threadées. Voir Section 24.2.15, « Comment faire un client MySQL threadé ».

- Les options relatives à un système d'exploitation particulier peuvent être trouvées dans la section spécifique aux systèmes de ce manuel. Voir Section 2.8, « Notes spécifiques aux systèmes d'exploitation ».

2-4-3 - Installer à partir de l'arbre source de développement

Attention : vous devez lire cette partie seulement si vous voulez nous aider à tester notre nouveau code. Si vous souhaitez seulement faire fonctionner MySQL sur votre système, vous devriez utiliser la distribution d'une version standard (que ce soit une distribution sous forme de sources ou de binaire).

Pour obtenir notre arbre source de développement le plus récent, suivez les instructions suivantes :

1. Téléchargez BitKeeper à partir de http://www.bitmover.com/cgi-bin/download.cgi. Vous aurez besoin de Bitkeeper 2.0 ou supérieur pour accéder à notre dépôt ;

2. Suivez les instructions pour l'installer ;

3. Après avoir installé BitKeeper, commencez par vous déplacer dans le répertoire à partir duquel vous voulez travailler, et lancez l'une des commandes suivantes pour dupliquer la branche MySQL de votre choix :

pour dupliquer la branche 3.23, utilisez cette commande :

shell> bk clone bk://work.mysql.com:7000 mysql-3.23

pour dupliquer la branche 4.0, utilisez cette commande :

shell> bk clone bk://work.mysql.com:7001 mysql-4.0

pour dupliquer la branche 4.1, utilisez cette commande :

shell> bk clone bk://work.mysql.com:7004 mysql-4.1

pour dupliquer la branche 5.0, utilisez cette commande :

shell> bk clone bk://mysql.bkbits.net/mysql-5.0 mysql-5.0

Dans l'exemple précédent, les sources seront respectivement placées dans les dossiers mysql-3.23/, mysql-4.0/, mysql-4.1/ ou mysql-5.0/, de votre dossier courant.

Si vous êtes derrière un firewall et que vous ne pouvez utiliser que des connexions HTTP, vous pouvez aussi accéder à BitKeeper via HTTP.

Si vous devez utiliser un serveur proxy, assignez la variable d'environnement http_proxy pour qu'elle pointe sur votre proxy :

shell> export http_proxy="http://your.proxy.server:8080/"

Puis, remplacez le protocole bk:// par http:// lors de votre export. Par exemple :

shell> bk clone http://mysql.bkbits.net/mysql-4.1 mysql-4.1

Le premier téléchargement de l'arbre source peut prendre un certain temps, selon la vitesse de votre connexion. Soyez patients ;

4. Vous aurez besoin de GNU make, autoconf 2.53 (ou plus récent), automake 1.5, libtool 1.4 et m4 pour lancer la prochaine série de commandes. Même si la plupart des systèmes d'exploitation sont livrés avec leur propre implémentation de make, les chances sont fortes pour que la compilation échoue avec des messages d'erreur étranges. Par conséquent, il est fortement recommandé d'utiliser GNU make (parfois aussi appelé gmake).

Heureusement, d'autres systèmes d'exploitation sont livrés avec les utilitaires GNU, ou proposent des paquets facilement installables. Dans tous les cas, vous pouvez les télécharger sur ces sites :

- http://www.gnu.org/software/autoconf/

- http://www.gnu.org/software/automake/

- http://www.gnu.org/software/libtool/

- http://www.gnu.org/software/m4/

- http://www.gnu.org/software/make/

Si vous essayez de configurer MySQL 4.1 ou plus récent, vous aurez besoin de GNU bison 1.75 ou plus récent. Les anciennes versions de bison peuvent indiquer cette erreur :

sql_yacc.yy:#####: fatal error: maximum table size (32767) exceeded

Note : la taille maximale de la table n'est pas dépassée. L'erreur est causée par un bogue dans les versions plus anciennes de bison.

Les versions de MySQL avant la version 4.1 peuvent aussi se compiler avec d'autres versions de yacc (par exemple, BSD yacc 91.7.30). Pour les versions plus récentes, GNU bison est une obligation.

Les commandes typiques nécessaires pour compiler MySQL sont présentées ci-dessous. La première commande cd change le dossier de travail : remplacez mysql-4.0 avec le bon nom de dossier.

shell> cd mysql-4.0
shell> bk -r get -Sq
shell> aclocal; autoheader; autoconf;  automake;
shell> ./configure  # Ajoutez ici vos options favorites
shell> make

Les lignes de commande qui passent dans les dossiers innobase et bdb/dist sont utilisées pour configurer InnoDB et Berkeley DB (BDB). Vous pouvez omettre ces lignes si vous n'avez pas besoin du support InnoDB ou BDB.

Si vous obtenez des erreurs étranges pendant cette étape, vérifiez bien que vous avez vraiment installé libtool !

Une collection de nos scripts de configuration les plus courants de trouve dans le sous-répertoire BUILD/. Si vous êtes fainéant, vous pouvez utiliser BUILD/compile-pentium-debug. Pour compiler sur une architecture différente, modifiez ce script en enlevant les drapeaux spécifiques au Pentium ;

5. Quand la compilation est achevée, lancez make install. Prenez garde sur des machines de production. Cette commande pourrait écraser votre installation actuelle. Si vous avez une autre installation de MySQL, nous vous recommandons de lancer ./configure avec des valeurs des options prefix, with-tcp-port, et unix-socket-path différentes de celles de votre serveur de production ;

6. Torturez votre nouvelle installation et tentez de faire planter les nouvelles fonctionnalités. Commencez par lancer make test. Voir Section 27.1.2, « Suite de test de MySQL » ;

7. Si vous avez échoué avec l'étape make et que la distribution ne compile pas, envoyez un rapport sur le site http://bugs.mysql.com/. Si vous avez installé la dernière version des indispensables outils GNU, et qu'ils échouent dans l'analyse de vos fichiers de configuration, envoyez aussi un rapport. D'autre part, si vous exécutez aclocal et que vous obtenez l'erreur command not found ou un problème du même type, n'envoyez pas de rapport. À la place, assurez-vous que les outils nécessaires sont bien installés et que votre variable PATH est configurée de telle façon que votre interpréteur de commandes les trouve ,

8. Après la première opération bk clone pour obtenir l'arbre source, vous devez lancer régulièrement bk pull pour obtenir les mises à jour ;

9. Vous pouvez examiner l'historique des changements de l'arbre avec toutes les différences en utilisant bk sccstool. Si vous apercevez des différences anormales ou sur lesquelles vous avez des questions, n'hésitez pas à envoyer un e-mail aux listes internes. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ». De même, si vous pensez avoir une meilleure méthode pour traiter un problème, envoyez un e-mail accompagné d'un patch à la même adresse. bk diffs vous fournira un patch après que vous aurez fait vos changements aux sources. Si vous n'avez pas le temps de coder votre idée, envoyez-en juste une description ;

10. BitKeeper dispose d'une aide agréable à laquelle vous pouvez accéder via bk helptool ;

11. Veuillez noter que chaque commit (bk ci ou bk citool) postera un message avec un aperçu des changements à notre liste de diffusion interne, à la façon habituelle des propositions openlogging.org avec seulement les commentaires des changements. Généralement, vous n'aurez pas besoin d'utiliser commit (l'arbre public interdisant les bk push), mais plutôt d'utiliser la méthode bk diffs décrite plus haut.

Vous pouvez aussi naviguer dans les fichiers d'historiques, les commentaires et le code source en ligne. Par exemple, pour lire ses informations pour MySQL 4.1, allez à http://mysql.bkbits.net:8080/mysql-4.1.

Le manuel est dans un module séparé, qui peut être obtenu comme ceci  :

shell> bk clone bk://mysql.bkbits.net/mysqldoc mysqldoc

Il y a aussi des arbres BitKeeper pour MySQL Control Center et Connector/ODBC. Ils sont disponibles comme ceci :

pour obtenir le MySQL Control Center, utilisez cette commande :

shell> bk clone http://mysql.bkbits.net/mysqlcc mysqlcc

pour obtenir le Connector/ODBC, utilisez cette commande :

shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc3

2-4-4 - Problèmes de compilation ?

Tous les programmes MySQL compilent proprement chez nous, sans aucune alerte sur Solaris avec gcc. Sur d'autres systèmes, des alertes peuvent apparaître à cause de différences dans le système d'inclusions. Voyez Section 2.4.5, « Notes relatives aux MIT-pthreads » pour les alertes qui peuvent apparaître avec MIT-pthreads. Pour d'autres problèmes, voyez la liste suivante.

La solution à de nombreux problèmes implique une nouvelle configuration. Si vous avez besoin de refaire une configuration voici quelques conseils généraux.

- Si configure est exécuté après une première exécution, il peut utiliser des informations qui ont été rassemblées durant une première invocation. Ces informations sont stockées dans le fichier config.cache. Lorsque configure est lancé, il commence par regarder dans ce fichier, et lire le contenu qui existe, en supposant que ces données sont toujours correctes. Cette supposition est invalide si vous faites une reconfiguration.

- Chaque fois que vous exécutez configure, vous devez exécuter à nouveau make pour recompiler. Toutefois, vous devrez peut-être supprimer les vieux fichiers d'objets qui ont été compilés en utilisant différentes configurations précédentes.

Pour éviter d'utiliser de vieilles informations de configuration, ou des vieux fichiers d'objets, vous pouvez utiliser ces commandes, avant configure :

shell> rm config.cache
shell> make clean

Alternativement, vous pouvez aussi utiliser make distclean.

La liste suivante décrit certains problèmes lors de la compilation de MySQL, qui surviennent souvent :

- si vous avez des problèmes lors de la compilation de sql_yacc.cc, comme ceux qui sont décrits ci-dessous, vous avez probablement été à court de mémoire ou d'espace de swap :

Internal compiler error: program cc1plus got fatal signal 11
Out of virtual memory
Virtual memory exhausted

Le problème est que gcc requiert de grandes quantités de mémoire pour compiler sql_yacc.cc avec les options inline. Essayez d'exécuter configure avec l'option --with-low-memory :

shell> ./configure --with-low-memory

Cette option ajoute -fno-inline dans la ligne de compilation, si vous utilisez gcc et -O0 si vous utilisez autre chose. Vous pouvez essayer --with-low-memory même s'il vous reste suffisamment de mémoire, et que vous ne pensez pas être limité. Ce problème a été observé sur des systèmes avec de généreuses configurations, et --with-low-memory résout ce problème ;

- par défaut, configure choisit c++ comme compilateur, et GNU c++ pour les liens avec -lg++. Si vous utilisez gcc, ce comportement peut poser les problèmes suivants :

configure: error: installation or configuration problem:
C++ compiler cannot create executables.

Vous pourriez aussi observer des problèmes durant la compilation, avec g++, libg++ ou libstdc++.

La cause de ces problèmes est que vous n'avez peut-être pas g++, ou que vous avez g++, mais pas libg++, ou libstdc++. Regardez le fichier de log config.log. Il va sûrement contenir la raison exacte du mauvais fonctionnement de votre compilateur. Pour contourner ce problème, vous pouvez utiliser gcc comme compilateur C++. Essayez de modifier la variable d'environnement CXX avec la valeur "gcc -O3". Par exemple :

shell> CXX="gcc -O3" ./configure

Cela fonctionne, car gcc compile les sources C++ aussi bien que g++, mais il n'est pas lié avec libg++ ou libstdc++ par défaut.

Un autre moyen pour régler ces problèmes, bien sûr, est d'installer g++, libg++ et libstdc++. Nous vous recommandons toutefois de ne pas utiliser libg++ ou libstdc++ avec MySQL, car cela ne fera qu'accroître la taille de votre exécutable binaire, sans vous apporter d'avantages. Par le passé, certaines versions de ces bibliothèques ont posé des problèmes étranges aux utilisateurs MySQL.

Utiliser gcc comme compilateur C++ est aussi nécessaire, si vous voulez compiler MySQL avec le support de RAID (voyez Section 13.2.5, « Syntaxe de CREATE TABLE » pour plus d'informations sur le type de table RAID, ou utilisez GNU gcc version 3 plus récente). Si vous avez des erreurs de compilation comme celles ci-dessous avec l'option --with-raid, essayez d'utiliser gcc comme compilateur C++ en définissant la variable d'environnement CXX ci-dessus :

gcc -O3 -DDBUG_OFF -rdynamic -o isamchk isamchk.o sort.o  libnisam.a
../mysys/libmysys.a ../dbug/libdbug.a ../strings/libmystrings.a
-lpthread -lz -lcrypt -lnsl -lm -lpthread
../mysys/libmysys.a(raid.o)(.text+0x79): In function
'my_raid_create':: undefined reference to 'operator new(unsigned)'
../mysys/libmysys.a(raid.o)(.text+0xdd): In function
'my_raid_create':: undefined reference to 'operator delete(void*)'
../mysys/libmysys.a(raid.o)(.text+0x129): In function
'my_raid_open':: undefined reference to 'operator new(unsigned)'
../mysys/libmysys.a(raid.o)(.text+0x189): In function
'my_raid_open':: undefined reference to 'operator delete(void*)'
../mysys/libmysys.a(raid.o)(.text+0x64b): In function
'my_raid_close':: undefined reference to 'operator delete(void*)'
collect2: ld returned 1 exit status

- Si votre compilation échoue avec des erreurs, ou si l'une des erreurs suivantes apparaît, vous devez changer la version de make en GNU make :

making all in mit-pthreads
make: Fatal error in reader: Makefile, line 18:
Badly formed macro assignment

ou :

make: file 'Makefile' line 18: Must be a separator (:

ou :

pthread.h: No such file or directory

Solaris et FreeBSD sont connus pour avoir des problèmes avec make.

GNU make version 3.75 est reconnu pour fonctionner ;

- si vous voulez définir des options supplémentaires qui seront utilisées par votre compilateur C ou C++, faites-le en ajoutant ces options aux variables d'environnement CFLAGS et CXXFLAGS. Vous pouvez aussi spécifier le nom du compilateur via les variables CC et CXX. Par exemple :

shell> CC=gcc
shell> CFLAGS=-O3
shell> CXX=gcc
shell> CXXFLAGS=-O3
shell> export CC CFLAGS CXX CXXFLAGS

Voyez Section 2.1.2.5, « Binaires compilés par MySQL AB », pour avoir une liste des définitions des options disponibles sur divers systèmes ;

- si vous obtenez un message d'erreur comme celui-ci, vous devrez mettre à jour votre version de gcc :

client/libmysql.c:273: parse error before '__attribute__'

gcc 2.8.1 est connu pour fonctionner, mais nous recommandons l'utilisation de gcc 2.95.2 ou egcs 1.0.3a ;

- si vous obtenez des erreurs telles que celles qui sont affichées ci-dessous lors de la compilation de mysqld, c'est que configure n'a pas correctement détecté le dernier argument des fonctions accept(), getsockname() ou getpeername() :

cxx: Error: mysqld.cc, line 645: In this statement, the referenced
type of the pointer value "&length" is "unsigned long", which
is not compatible with "int".
new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);

Pour corriger ce problème, éditez le fichier config.h (qui est généré par le fichier configure). Recherchez ces lignes :

/* Define as the base type of the last arg to accept */
#define SOCKET_SIZE_TYPE XXX

Remplacez XXX par size_t ou int, suivant votre système d'exploitation. Notez que vous devrez faire cette manipulation à chaque fois que vous exécuterez le script configure car configure régénère config.h ;

- le fichier sql_yacc.cc est généré à partir du fichier sql_yacc.yy. Normalement, le processus de création ne s'occupe pas de sql_yacc.cc, car MySQL en a déjà une copie. Cependant, si vous devez le recréer, vous pouvez rencontrer cette erreur :

"sql_yacc.yy", line xxx fatal: default action causes potential...

Cela indique que votre version de yacc est inadéquate. Vous devrez probablement réinstaller bison (la version GNU de yacc) et l'utiliser à la place ;

- sur Debian Linux 3.0, vous devez installer gawk au lieu du programme par défaut mawk si vous voulez compiler MySQL 4.1 ou plus récent avec le support Berkeley DB ;

- si vous avez besoin de déboguer mysqld ou un client MySQL, exécutez le script configure avec l'option --with-debug, puis recompilez vos clients avec la nouvelle bibliothèque. Voir Section D.2, « Débogage un client MySQL » ;

- si vous rencontrez une erreur de compilation sous Linux (e.g. SuSE Linux 8.1 ou Red Hat Linux 7.3) similaire à celle-ci :

libmysql.c:1329: warning: passing arg 5 of 'gethostbyname_r' from
incompatible pointer type
libmysql.c:1329: too few arguments to function 'gethostbyname_r'
libmysql.c:1329: warning: assignment makes pointer from integer
without a cast
make[2]: *** [libmysql.lo] Error 1

Par défaut, le script configure tente de déterminer le nombre correct d'arguments en utilisant g++, le compilateur GNU C++. Ce test retourne des résultats erronés si g++ n'est pas installé. Il y a deux façons de contourner le problème :

- assurez-vous que GNU C++ g++ est installé. Sur certains Linux, le paquet nécessaire est appelé gpp, et sur d'autres, c'est gcc-c++,

- utilisez gcc comme compilateur C++ en donnant à la variable d'environnement CXX, la valeur de gcc:

export CXX="gcc"

Notez bien que vous devez lancer configure après cela.

2-4-5 - Notes relatives aux MIT-pthreads

Cette section décrit quelques informations concernant l'utilisation des MIT-pthreads.

Notez que sur Linux vous ne devez pas utiliser les MIT-pthreads mais installer LinuxThreads ! Voir Section 2.8.1, « Notes relatives à Linux (toutes versions) ».

Si votre système ne fournit pas un support natif des threads, vous aurez besoin de construire MySQL en utilisant le paquet des MIT-pthreads. Cela inclut les anciens systèmes FreeBSD, SunOS 4.x, Solaris 2.4 et plus anciens, et quelques autres systèmes. Voir Section 2.1.1, « Systèmes d'exploitation supportés par MySQL ».

Notez qu'à partir de la version 4.0.2 de MySQL les MIT-pthreads ne font plus partie de la distribution des sources ! Si vous avez besoin de ce paquet, vous pouvez l'obtenir sur http://www.mysql.com/Downloads/Contrib/pthreads-1_60_beta6-mysql.tar.gz

Après l'avoir récupéré, décompressez l'archive dans le répertoire racine de votre répertoire des sources de MySQL. Cela créera le répertoire mit-pthreads.

- Sur la plupart des systèmes, vous pouvez forcer l'utilisation des MIT-pthreads en exécutant configure avec l'option --with-mit-threads :

shell> ./configure --with-mit-threads

La compilation dans un dossier non source n'est pas supporté lors de l'utilisation des MIT-pthreads, car nous voulons minimiser les changements de leur code.

- La vérification pour l'utilisation des MIT-pthreads ne survient que durant la partie du processus de configuration qui s'occupe du code du serveur. Si vous avez configuré la distribution en utilisant --without-server pour ne construire que le client, les clients ne sauront pas si les MIT-pthreads sont utilisés et utiliseront les sockets Unix pour les connexions par défaut. Puisque les sockets Unix ne fonctionnent pas avec les MIT-pthreads sur certaines plates-formes, cela signifie que vous devrez utiliser -h ou --host quand vous exécuterez les programmes clients.

- Lorsque MySQL est compilé en utilisant les MIT-pthreads, le verrouillage système est désactivé par défaut pour des soucis de performance. Vous pouvez demander au serveur d'utiliser les verrous système avec l'option --external-locking. Cela n'est requis que si vous avez besoin de faire fonctionner deux serveurs MySQL avec les mêmes données (non recommandé).

- De temps en temps, la commande bind() des pthreads n'arrive pas à attacher une socket sans afficher d'erreurs (du moins, sous Solaris). Le résultat est que toutes les connexions au serveur échouent. Par exemple :

shell> mysqladmin version
mysqladmin: connect to server at '' failed;
error: 'Can't connect to mysql server on localhost (146)'

La solution est de terminer le serveur mysqld et de le redémarrer. Cela ne nous est arrivé que quand nous avons forcé le serveur à se terminer et que nous l'avons redémarré immédiatement après.

- Avec les MIT-pthreads, l'appel système à sleep() ne peut pas être interrompu avec SIGINT (break). On ne s'en rend compte que quand on exécute mysqladmin --sleep. Vous devez attendre que l'appel système à sleep() se termine avant que le processus ne s'arrête.

- Lors de la liaison, vous pouvez obtenir des messages d'erreur comme ceux-ci (du moins sur Solaris), ils peuvent être ignorés :

ld: warning: symbol '_iob' has differing sizes:
(file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
file /usr/lib/libc.so value=0x140);
/my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
ld: warning: symbol '__iob' has differing sizes:
(file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
file /usr/lib/libc.so value=0x140);
/my/local/pthreads/lib/libpthread.a(findfp.o) definition taken

- D'autres avertissements peuvent être ignorés :

implicit declaration of function 'int strtoll(...)'
implicit declaration of function 'int strtoul(...)'

- Nous n'avons pas réussi à faire fonctionner readline avec les MIT-pthreads. (Cela n'est pas nécessaire, mais peut être utile à quelqu'un.)

2-4-6 - La distribution source Windows

Ces instructions décrivent comment compiler MySQL version 4.1, depuis les sources, pour Windows. Les instructions sont fournies pour compiler les versions standard à partir des sources standard, ou depuis la version de développement de BitKeeper.

Note : les instructions de ce document sont strictement destinées aux utilisateurs qui veulent tester MySQL sur Windows, à partir des toutes dernières sources de BitKeeper. Pour un serveur de production, MySQL vous recommande de ne pas compiler votre serveur vous-même. Normalement, il est mieux d'utiliser une distribution binaire précompilée, et optimisée pour l'utilisation sur Windows par MySQL AB. Les instructions d'installation pour les distributions binaires sont disponibles dans la section Section 2.2.1, « Installer MySQL sous Windows ».

Pour compiler MySQL sur Windows depuis les sources, vous avez besoin des logiciels et ressources suivantes sur votre système :

- le compilateur VC++ 6.0 (mis à jour avec le service pack 4 ou 5, et paquet préprocesseur). Le paquet préprocesseur est nécessaire pour l'assembleur macro. Plus de détails à : http://msdn.microsoft.com/vstudio/downloads/updates/sp/vs6/sp5/faq.aspx.

- environ 45 Mo d'espace disque ;

- 64 Mo de RAM.

Vous aurez besoin de la distribution source MySQL pour Windows. Il y a deux méthodes pour obtenir cette distribution pour MySQL 4.1 et supérieur :

1. Télécharger une distribution source préparée par MySQL AB pour la version de MySQL que vous voulez. Les distributions sources précompilées sont disponibles pour les versions de MySQL publiées, et sont accessibles sur le site de http://www.mysql.com/downloads/ ;

2. Vous pouvez préparer votre propre distribution source vous-même, avec la dernière version disponible sur le serveur BitKeeper. Si vous voulez faire cela, vous devez créer la distribution sur un serveur Unix, et transférer l'archive sur votre système Windows. La raison est que certaines étapes de configuration requièrent des outils qui ne fonctionnent que sous Unix. L'approche BitKeeper requiert :

- un système fonctionnant sous Unix, ou un système équivalent, comme Linux,

- BitKeeper 3.0 sur ce système. Vous pouvez obtenir BitKeeper sur http://www.bitkeeper.com/.

Si vous utilisez une distribution source Windows vous pouvez passer directement à Section 2.4.6.1, « Compiler MySQL avec VC++ ». Pour compiler depuis les sources BitKeeper, commencez par Section 2.4.6.2, « Compiler MySQL sur Windows à partir des sources de développement ».

Si vous découvrez quelque chose qui ne fonctionne pas comme prévu, ou si vous avez des suggestions pour améliorer le processus actuel envoyez un message à la liste de diffusion dédiée à win32. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

2-4-6-1 - Compiler MySQL avec VC++

Note: les fichiers du projet VC++ de MySQL 4.1 et plus récents sont compatibles avec Microsoft Visual Studio 6.0 et plus récents (7.0/.NET) et sont testés par l'équipe de MySQL AB avant chaque publication.

Pour compiler MySQL, suivez ces instructions ci-dessous. Notez que les noms de menus sont laissés en anglais, et devront éventuellement être adaptés à votre interface.

1. Créez un dossier de travail : par exemple, workdir.

2. Décompressez la distribution source dans le dossier ci-dessus, en utilisant WinZip ou un autre utilitaire Windows qui sache lire les fichiers .zip.

3. Lancez le compilateur VC++ 6.0.

4. Dans le menu File, sélectionnez Open Workspace.

5. Ouvrez le fichier mysql.dsw que vous trouverez dans le dossier de travail.

6. Dans le menu Build, sélectionnez le menu Set Active Configuration.

7. Cliquez dans le dialogue pour sélectionner mysqld - Win32 Debug, puis cliquez sur OK.

8. Pressez F7 pour lancer la compilation du serveur de débogage, des bibliothèques et des applications clients.

9. Compilez la version que vous souhaitez, de la même façon.

10. Les versions de débogage et les bibliothèques sont placées dans les dossiers client_debug et lib_debug. Les versions finales des programmes et bibliothèques sont placées dans les dossiers client_release et lib_release. Notez que si vous voulez compiler les versions de débogage et finales, vous pouvez utiliser l'option « build all » dans le menu Build.

11. Testez le serveur. Le serveur compilé avec les instructions suivantes suppose que le dossier de base MySQL et le dossier de données sont situés dans les dossiers C:\mysql et C:\mysql\data, par défaut. Si vous voulez tester votre serveur, utilisez le chemin de votre dossier d'installation comme chemin racine. Vous pouvez faire cela en ligne de commande, avec les options --basedir et --datadir ou bien placer les bonnes options dans le fichier d'options (C:\my.cnf ou my.ini de votre dossier Windows). Si vous avez un dossier de données sur votre disque, vous pouvez spécifier son chemin.

12. Lancez le serveur depuis le dossier client_release ou client_debug, suivant la version que vous voulez utiliser. Les instructions générales de lancement sont dans Section 2.2.1, « Installer MySQL sous Windows ». Vous devrez adapter les instructions à votre configuration, si vous avez un dossier de base ou de données différent.

13. Lorsque le serveur fonctionne en mode indépendant ou comme un service, suivant votre configuration, essayez de vous connecter avec le client interactif mysql, qui est placé dans le dossier client_release ou client_debug.

Lorsque vous êtes satisfait du fonctionnement de votre serveur, stoppez-le. Puis installez MySQL comme ceci :

1. Créez un dossier sur votre disque pour installer MySQL. Par exemple, nous pourrions l'installer dans C:\mysql. Voici les commandes :

C:
mkdir \mysql
mkdir \mysql\bin
mkdir \mysql\data
mkdir \mysql\share
mkdir \mysql\scripts

Si vous voulez compiler d'autres clients et les lier à MySQL, il faudra créer d'autres dossiers :

mkdir \mysql\include
mkdir \mysql\lib
mkdir \mysql\lib\debug
mkdir \mysql\lib\opt

Si vous voulez tester les performances de MySQL, créez ce dossier :

mkdir \mysql\sql-bench

Les tests de performance requièrent Perl ;

2. Depuis le dossier workdir, copiez dans le dossier C:\mysql les fichiers suivants :

copy client_release\*.exe C:\mysql\bin
copy client_debug\mysqld.exe C:\mysql\bin\mysqld-debug.exe
xcopy scripts\*.* C:\mysql\scripts /E
xcopy share\*.* C:\mysql\share /E

Si vous voulez compiler d'autres clients, et les lier avec MySQL, vous devrez aussi faire ceci :

copy lib_debug\mysqlclient.lib C:\mysql\lib\debug
copy lib_debug\libmysql.* C:\mysql\lib\debug
copy lib_debug\zlib.* C:\mysql\lib\debug
copy lib_release\mysqlclient.lib C:\mysql\lib\opt
copy lib_release\libmysql.* C:\mysql\lib\opt
copy lib_release\zlib.* C:\mysql\lib\opt
copy include\*.h C:\mysql\include
copy libmysql\libmysql.def C:\mysql\include

Si vous voulez tester les performances de MySQL, faites aussi ceci :

xcopy sql-bench\*.* C:\mysql\bench /E

Puis lancez votre serveur de la même façon que vous lancez l'exécutable MySQL classique. Voir Section 2.2.1, « Installer MySQL sous Windows ».

2-4-6-2 - Compiler MySQL sur Windows à partir des sources de développement

Pour compiler la dernière version Windows à partir de sources disponibles dans le serveur BitKeeper, suivez les instructions suivantes. Notez que ces commandes doivent être exécutées sur un système fonctionnant sous Unix ou Linux. La procédure fonctionne très bien sous Linux, par exemple.

1. Clonez les sources issues de BitKeeper (version 4.1 ou plus récentes). Pour plus d'informations sur comment cloner les sources sont disponibles dans la section Section 2.4.3, « Installer à partir de l'arbre source de développement ».

2. Configurez et compilez la distribution pour obtenir un serveur fonctionnel. Pour cela, vous pouvez lancer la commande suivante à la racine de vos sources :

shell> ./BUILD/compile-pentium-max

3. Après vous être assuré que le processus est complet et réussi, lancez l'utilitaire suivant depuis la racine de vos sources :

shell> ./scripts/make_win_src_distribution

Ce script crée un paquet source Windows, qui peut être utilisé sur votre système. Vous pouvez passer d'autres options à ce script, suivant vos besoins. Il accepte les options suivantes :

- --help

Affiche ce message d'aide ;

- --debug

Débogage, sans créer le paquet ;

- --tmp

Spécifie le dossier temporaire ;

- --suffix

Suffixe pour le nom du paquet ;

- --dirname

Nom du dossier où copier les fichiers (intermédiaire) ;

- --silent

Ne liste pas tous les fichiers traités ;

- --tar

Crée le paquet au format tar.gz plutôt que .zip.

Par défaut, make_win_src_distribution crée une archive zippée avec le nom mysql-VERSION-win-src.zip, où VERSION représente la version de votre source MySQL.

4. Copiez ou téléchargez le paquet sur votre machine Windows. Pour le compiler, suivez les instructions de la section Section 2.4.6.1, « Compiler MySQL avec VC++ ».

2-4-7 - Compiler les clients MySQL sous Windows

Dans vos fichiers source, vous devez inclure windows.h avant mysql.h :

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
#include <mysql.h>

my_global.h inclut tous les autres fichiers nécessaires pour Windows (comme le fichier windows.h) si vous compilez votre programme sous Windows.

Vous pouvez soit lier votre code avec la bibliothèque dynamique libmysql.lib, qui est juste une interface pour charger libmysql.dll à la demande, soit lier avec la bibliothèque statique mysqlclient.lib.

Notez que puisque les bibliothèques mysqlclient sont compilées en tant que bibliothèques threadées, vous devez aussi compiler votre code pour qu'il soit multithreadé !

2-5 - Procédure de postinstallation

Il y a des manipulations importantes à faire après avoir installé MySQL. Par exemple, sous Unix, vous devez créer les tables de droits. Sur toutes les plates-formes, un point de sécurité important est que les comptes initiaux n'ont pas de mot de passe. Vous devez assigner les mots de passe pour éviter un accès indu au serveur MySQL.

Les sections suivantes décrivent les procédures de postinstallation sur Windows et pour les systèmes Unix. Une autre section, Section 2.5.2.3, « Problèmes de démarrage du serveur MySQL » s'applique aux autres plates-formes : elle décrit ce que vous devez faire si vous avez des problèmes de lancement. La section Section 2.5.3, « Création des premiers droits MySQL » s'applique aussi à toutes les plates-formes. Vous devez suivre les instructions pour vous assurer que vous avez bien protégé vos comptes MySQL en leur assignant un mot de passe.

Lorsque vous êtes prêt à créer d'autres comptes, vous pouvez trouver des informations sur le contrôle d'accès à MySQL et la gestion de comptes dans les sections Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL » et Section 5.6, « Gestion des comptes utilisateurs de MySQL ».

2-5-1 - Post-installation sous Windows

Sous Windows, la table de droits n'a pas besoin d'être créée. Les distributions MySQL pour Windows incluent les tables de droits préconfigurées dans la base mysql, dans le dossier de données data. Cependant, vous devez assigner des mots de passe aux comptes.

Avant de donner des mots de passe aux comptes, vérifiez que le serveur fonctionne avec un client. Assurez-vous que le serveur fonctionne (voir Section 2.2.8.2, « Démarrer le serveur pour la première fois »), puis utilisez les commandes suivantes pour vérifier que vous pouvez lire des données sur le serveur. Le résultat doit être proche de celui présenté ici :

C:\> C:\mysql\bin\mysqlshow
+-----------+
| Databases |
+-----------+
| mysql     |
| test      |
+-----------+

C:\> C:\mysql\bin\mysqlshow mysql
Database: mysql
+--------------+
|    Tables    |
+--------------+
| columns_priv |
| db           |
| func         |
| host         |
| tables_priv  |
| user         |
+--------------+

C:\> C:\mysql\bin\mysql -e "SELECT Host,Db,User FROM db" mysql
+------+-------+------+
| host | db    | user |
+------+-------+------+
| %    | test% |      |
+------+-------+------+

Si vous avez une version fonctionnelle de Windows qui supporte les services, et que vous voulez que MySQL fonctionne automatiquement au lancement de Windows, voyez la section Section 2.2.9.1, « Lancer MySQL comme un service Windows ».

2-5-2 - Procédures de postinstallation sous Unix

Une fois que vous avez installé MySQL sur Unix, vous devez initialiser les tables de droits, lancer le serveur, et vous assurer que tout fonctionne bien. Vous pouvez aussi configurer le démarrage et l'extinction automatique du serveur, lorsque votre serveur se lance et s'arrête.

Sous Unix, les tables de droits sont configurées avec le programme mysql_install_db. Pour certaines méthodes d'installation, ce programme est utilisé automatiquement :

- si vous installez MySQL sous Linux avec un RPM, le serveur RPM exécute mysql_install_db ;

- si vous installez MySQL sous Mac OS X en utilisant la distribution PKG, l'installeur exécute mysql_install_db.

Sinon, vous devez lancer manuellement mysql_install_db.

La procédure suivante décrit comment initialiser les tables de droits (si cela n'a pas été fait), puis comment lancer le serveur. Vous trouverez aussi des suggestions de commandes pour tester l'accessibilité du serveur. Pour des informations sur le démarrage et l'extinction automatique du serveur, voyez Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ».

Une fois que vous avez exécuté la procédure, et que le serveur fonctionne, vous devez assigner des mots de passe aux comptes créés par mysql_install_db. Les instructions pour faire cela Section 2.5.3, « Création des premiers droits MySQL ».

Dans les exemples ici, le serveur fonctionne avec l'utilisateur mysql. On suppose donc que ce compte existe. Créez ce compte, s'il n'existe pas, ou bien utilisez le nom que vous avez choisi.

1. Changez de dossier de travail, pour vous mettre à la racine de l'installation MySQL, représentée ici par BASEDIR :

shell> cd BASEDIR

BASEDIR vaut probablement /usr/local/mysql ou /usr/local. Les étapes suivantes supposent que vous êtes dans ce dossier.

2. Si nécessaire, lancez le programme mysql_install_db pour configurer les tables de droits initiales, qui déterminent les utilisateurs qui sont autorisés à se connecter au serveur. Vous devez faire cela si vous avez installé le programme avec une distribution qui ne lance pas ce programme pour vous.

Typiquement, mysql_install_db doit être utilisé uniquement à la première installation, et vous pouvez éviter cette étape si vous faites une mise à jour. Cependant, mysql_install_db n'écrase pas les tables de droits : vous pouvez l'utiliser, en cas de doute.

Pour initialiser les tables de droits, utilisez une des commandes suivantes, en fonction de la localisation de mysql_install_db dans le dossier bin scripts :

shell> bin/mysql_install_db --user=mysql
shell> scripts/mysql_install_db --user=mysql

Le script mysql_install_db crée la base mysql qui contient les tables de droits, et la base test que vous pouvez utiliser pour les tests avec MySQL. Ce script va aussi créer l'utilisateur root et un compte anonyme. Ces deux comptes sont créés sans mot de passe. Une description des droits initiaux est présentée dans la section Section 2.5.3, « Création des premiers droits MySQL ». Le script mysqld_safe lance le serveur mysqld. Avant la version 4.0, utilisez safe_mysqld au lieu de mysqld_safe.

Il est important de vous assurer que les dossiers et les fichiers appartiennent au compte mysql pour que le serveur puisse lire et écrire dedans. Pour cela, l'option --user doit être utilisée comme présenté si vous utilisez mysql_install_db comme root. Sinon, il est recommandé d'exécuter le script lorsque vous êtes connecté en tant que mysql : dans ce cas, vous pouvez omettre l'option --user.

mysql_install_db crée de nombreuses tables dans la base mysql : user, db, host, tables_priv, columns_priv, func, et même d'autres, en fonction des versions de MySQL.

Si vous ne voulez pas de la base test, vous pouvez la supprimer avec mysqladmin -u root drop test au redémarrage du serveur.

Si vous avez des problèmes avec mysql_install_db, voyez Section 2.5.2.1, « Problèmes d'exécution de mysql_install_db ».

Il y a d'autres alternatives pour lancer mysql_install_db tel que fourni par la distribution MySQL :

- si vous voulez que les droits initiaux soient différents des valeurs par défaut, vous pouvez modifier le script mysql_install_db avant de l'exécuter. Cependant, une technique préférable est d'utiliser GRANT et REVOKE pour changer les droits après avoir configuré les tables de droits. En d'autres termes, vous pouvez lancer mysql_install_db, puis utiliser mysql -u root mysql pour vous connecter au serveur en tant que root MySQL, pour émettre les commandes GRANT et REVOKE.

Si vous voulez installer MySQL sur de nombreuses machines avec les mêmes droits, vous pouvez mettre les commandes GRANT et REVOKE dans un fichier de script, et exécuter ce script avec mysql après avoir utilisé mysql_install_db. Par exemple :

shell> bin/mysql_install_db --user=mysql
shell> bin/mysql -u root < your_script_file

Comme cela, vous pouvez éviter les problèmes de répétition manuelle entre chaque machine ;

- il est possible de recréer entièrement les tables de droits après les avoir créées. Vous pouvez le faire si vous apprenez comment utiliser GRANT et REVOKE et que vous avez fait tellement de modifications après mysql_install_db que vous voulez recommencer à zéro.

Pour recréer les tables de droits, supprimez les fichiers .frm, .MYI et .MYD dans le dossier contenant les tables mysql. C'est le dossier appelé mysql dans le dossier de données, qui est listé dans le dossier datadir lorsque vous utilisez la commande mysqld --help. Puis, utilisez à nouveau le script mysql_install_db.

Note : pour les versions MySQL antérieures à la version 3.22.10, vous ne devez pas supprimer les fichiers .frm. Si vous les supprimez accidentellement, essayez de les retrouver et de les remettre dans le dossier mysql depuis votre distribution MySQL, avant d'utiliser mysql_install_db ;

- vous pouvez lancer mysqld manuellement en utilisant l'option --skip-grant-tables et en ajoutant les droits mysql :

shell> bin/mysqld_safe --user=mysql --skip-grant-tables &
shell> bin/mysql mysql

Depuis mysql, exécutez manuellement les commandes SQL contenues dans le script mysql_install_db. Assurez-vous que vous utilisez mysqladmin flush-privileges ou mysqladmin reload après, pour dire au serveur de relire les tables de droits.

Notez que si vous n'utilisez pas mysql_install_db, vous devez remplir les tables manuellement, et en plus, vous devez commencer par les créer.

3. Lancez le serveur MySQL :

shell> bin/mysqld_safe --user=mysql &

Pour les versions de MySQL antérieures à 4.0, remplacez bin/safe_mysqld par bin/mysqld_safe dans cette commande.

Il est important de vous assurer que le dossier de base de données et les fichiers de mysql sont accessibles, pour que le serveur puisse y lire et écrire. Pour cela, l'option --user peut être utilisée avec mysql_install_db si vous l'exécutez en tant que root. Sinon, vous devez exécuter le script lorsque vous êtes identifié comme mysql, auquel cas, vous pouvez omettre l'option --user.

D'autres instructions pour faire fonctionner MySQL en tant qu'utilisateur sans droits sont données dans la section Section A.3.2, « Comment exécuter MySQL comme un utilisateur normal ».

Si vous n'avez pas créé les tables de droits, l'erreur suivante sera inscrite dans le fichier de log d'erreurs de votre serveur :

mysqld: Can't find file: 'host.frm'

Si vous avez des problèmes au démarrage du serveur, voyez Section 2.5.2.3, « Problèmes de démarrage du serveur MySQL ».

4. Utilisez mysqladmin pour vérifier que le serveur fonctionne. La commande suivante vous permet de faire un test simple pour vérifier que le serveur est actif et qu'il répond aux connexions :

shell> bin/mysqladmin version
shell> bin/mysqladmin variables

Le résultat de mysqladmin version varie légèrement, suivant votre plate-forme et votre version de MySQL, mais il doit être proche de ceci :

shell> bin/mysqladmin version
mysqladmin  Ver 8.40 Distrib 4.0.18, for linux on i586
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license

Server version          4.0.18-log
Protocol version        10
Connection              Localhost via Unix socket
TCP port                3306
UNIX socket             /tmp/mysql.sock
Uptime:                 16 sec

Threads: 1  Questions: 9  Slow queries: 0
Opens: 7  Flush tables: 2  Open tables: 0
Queries per second avg: 0.000
Memory in use: 132K  Max memory used: 16773K

Pour voir ce que vous pouvez faire d'autre avec mysqladmin, utilisez l'option --help.

5. Vérifiez que vous pouvez éteindre le serveur :

shell> BINDIR/mysqladmin -u root shutdown

6. Vérifiez que vous pouvez relancer le serveur. Pour cela, utilisez mysqld_safe ou mysqld directement. Par exemple :

shell> BINDIR/mysqld_safe --log &

Si mysqld_safe échoue, essayez de l'exécuter directement depuis le dossier d'installation MySQL (si vous n'y êtes pas déjà). Si cela ne fonctionne toujours pas, voyez Section 2.5.2.3, « Problèmes de démarrage du serveur MySQL ».

7. Exécutez les tests simples pour vérifier que le serveur fonctionne. Le résultat devrait être proche de celui-ci :

shell> BINDIR/mysqlshow
+-----------+
| Databases |
+-----------+
| mysql     |
+-----------+

shell> BINDIR/mysqlshow mysql
Database: mysql
+--------------+
|    Tables    |
+--------------+
| columns_priv |
| db           |
| func         |
| host         |
| tables_priv  |
| user         |
+--------------+

shell> BINDIR/mysql -e "SELECT host,db,user FROM db" mysql
+------+--------+------+
| host | db     | user |
+------+--------+------+
| %    | test   |      |
| %    | test_% |      |
+------+--------+------+

Il y a aussi une suite de tests dans le dossier sql-bench (sous le dossier d'installation MySQL) que vous pouvez utiliser pour comparer les performances de MySQL sur différentes plates-formes. La suite de tests utilise le module Perl DBI pour assurer une interface avec les autres bases de données. Les modules Perl suivants sont aussi nécessaires pour exécuter la suite de tests :

DBI
DBD::mysql
Data::Dumper
Data::ShowTable

Ces modules sont disponibles sur la bibliothèque CPAN http://www.cpan.org/. Voir Section 2.9.1, « Installer Perl sur Unix ».

Le dossier sql-bench/Results contient des résultats de tests sur différentes plates-formes et bases. Pour lancer tous les tests, exécutez ces commandes :

shell> cd sql-bench
shell> run-all-tests

Si vous n'avez pas de dossier sql-bench, vous avez probablement installé MySQL avec un fichier RPM, différent du RPM source. Le RPM source inclut le dossier sql-bench) Dans ce cas, vous devez d'abord installer la suite de tests avant de l'utiliser. Depuis MySQL version 3.22, il y a des fichiers de tests RPM appelés mysql-bench-VERSION-i386.rpm, qui contiennent le code et les données.

Si vous avez une distribution source, il y a aussi des tests dans le sous-dossier tests. Par exemple, pour lancer auto_increment.tst, faites :

shell> BINDIR/mysql -vvf test < ./tests/auto_increment.tst

Les résultats attendus des tests sont disponibles dans le fichier ./tests/auto_increment.res.

8. À ce point, vous devez avoir un serveur fonctionnel. Cependant, les comptes initiaux n'ont pas de mot de passe : il est recommandé de leur assigner des mots de passe en suivant les instructions de la section Section 2.5.3, « Création des premiers droits MySQL ».

2-5-2-1 - Problèmes d'exécution de mysql_install_db

Le but du script mysql_install_db est de générer un nouveau système de droits pour MySQL. Il ne modifiera aucune autre donnée ! Il ne fera rien du tout si vous avez des tables de droits installées.

Si vous voulez recréer vos tables de droits, vous devez éteindre le serveur mysqld, s'il fonctionnait. Puis, renommez le dossier mysql dans le dossier de données, sauvez-le, et exécutez le script mysql_install_db. Par exemple :

shell> mv mysql-data-directory/mysql mysql-data-directory/mysql-old
shell> mysql_install_db --user=mysql

Cette section liste les problèmes que vous pourriez rencontrer lors de l'exécution du script mysql_install_db :

- mysql_install_db n'installe pas les tables de droits

Vous réalisez que mysql_install_db n'arrive pas à installer les tables de droits, et se termine sur ce message :

starting mysqld daemon with databases from XXXXXX
mysql daemon ended

Dans ce cas, examinez le fichier de log très attentivement ! Le fichier de log est situé dans le dossier XXXXXX indiqué dans le message d'erreur, et il indiquera pourquoi mysqld n'a pas démarré. Si vous ne comprenez pas ce qui est arrivé, incluez le log dans votre message, lors de l'envoi du rapport de bogues avec mysqlbug! Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème » ;

- un démon mysqld fonctionne déjà

Dans ce cas, vous n'avez probablement pas exécuté mysql_install_db du tout. Vous avez exécuté mysql_install_db une fois, lorsque vous avez installé MySQL pour la première fois ;

- installer un second démon mysqld n'est pas possible lorsque le premier fonctionne

Cela arrive lorsque vous avez une installation MySQL préexistante, mais que vous voulez installer une autre version ailleurs (par exemple, pour faire des tests ou simplement pour avoir deux installations). Généralement, le problème survient lorsque le second serveur est démarré, et qu'il essaie d'utiliser les mêmes ports et sockets que le premier. Dans ce cas, vous recevez des messages d'erreur tels que :

Can't start server: Bind on TCP/IP port:
Address already in use
Can't start server: Bind on unix socket...

Pour des instructions sur la configuration de serveurs multiples, voyez la section Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine » ;

- You don't have write access to /tmp

Si vous n'avez pas les droits d'accès suffisants pour créer un fichier de socket à l'endroit prévu ou les permissions pour créer un fichier temporaire dans /tmp, vous allez avoir une erreur lors de l'utilisation de mysql_install_db ou avec mysqld.

Vous pouvez spécifier un socket différent et un dossier temporaire différent avec les options suivantes :

shell> TMPDIR=/some_tmp_dir/
shell> MYSQL_UNIX_PORT=/some_tmp_dir/mysql.sock
shell> export TMPDIR MYSQL_UNIX_PORT

some_tmp_dir doit être le chemin complet d'un dossier dans lequel vous avez les droits en écriture.

Après cela, vous devriez être capable d'exécuter mysql_install_db et lancer le serveur avec ces commandes :

shell> bin/mysql_install_db --user=mysql
shell> bin/mysqld_safe --user=mysql &

Si mysql_install_db est situé dans le dossier scripts, modifiez la première commande pour utiliser scripts/mysql_install_db.

Voyez Section A.4.5, « Comment protéger ou changer le fichier socket /tmp/mysql.sock ». Voir Annexe E, Variables d'environnement.

2-5-2-2 - Lancer et arrêter MySQL automatiquement

Généralement, vous démarrez le serveur mysqld par l'un de ces moyens :

- en appelant mysqld directement. Cela fonctionne sur toutes les plates-formes ;

- en lançant le serveur MySQL comme un service Windows. Cela fonctionne sur les versions de Windows qui supportent les services : comme Windows NT, 2000 et XP. Le service peut être configuré pour démarrer automatiquement au lancement de Windows, ou manuellement, à la demande. Pour des instructions, reportez-vous à Section 2.2.9.1, « Lancer MySQL comme un service Windows » ;

- en appelant mysqld_safe, qui essaie de déterminer les options correctes avant de lancer mysqld. Ce script est utilisé sur les systèmes Unix BSD. Il est aussi appelé par mysql.server. Voir Section 5.1.3, « safe_mysqld, le script père de mysqld » ;

- en appelant mysql.server. Ce script sert principalement au moment du démarrage et de l'extinction du système, sur les systèmes qui utilisent un dossier de processus programmé System V, où il est généralement enregistré sous le nom de mysql. Le script mysql.server lance le serveur en appelant mysqld_safe. Voir Section 5.1.4, « Le script de démarrage mysql.server » ;

- sur Mac OS X, vous pouvez installer un paquet indépendant appelé MySQL Startup Item pour activer le lancement automatique de MySQL au démarrage. Le Startup Item lance le serveur en appelant mysql.server. Voir Section 2.2.13, « Installer MySQL sur Mac OS X » pour plus de détails.

Les scripts mysql.server et safe_mysqld et le StartUp Item de Mac OS X peuvent être utilisés pour démarrer le serveur automatiquement au moment du démarrage du serveur. mysql.server peut aussi servir à arrêter le serveur.

Le script mysql.server peut servir à démarrer ou arrêter le serveur en l'appelant avec les arguments start ou stop :

shell> mysql.server start
shell> mysql.server stop

Avant que mysql.server ne démarre le serveur, il change de dossier pour aller dans le dossier d'installation et appelle safe_mysqld. Si vous voulez que le serveur fonctionne sous un nom d'utilisateur spécifique, ajoutez l'option user appropriée dans le groupe [mysqld] du fichier /etc/my.cnf, tel que présenté ultérieurement dans cette section (il est possible que vous ayez besoin d'éditer mysql.server). Vous pourriez avoir à éditer mysql.server si vous avez une installation binaire dans une situation non standard. Modifiez la commande cd avec le dossier correct, avant qu'il n'exécute safe_mysqld. Si vous voulez que le serveur fonctionne avec un utilisateur spécifique, ajouter l'option user appropriée dans le fichier /etc/my.cnf, tel que présenté ultérieurement dans cette section.

mysql.server stop arrête le serveur en lui envoyant un signal. Vous pouvez éteindre le serveur manuellement avec la commande mysqladmin shutdown.

Pour lancer et arrêter automatiquement MYSQL sur votre serveur, vous devez ajouter les commandes de lancement et d'arrêt dans les bons endroits de vos fichiers /etc/rc*.

Notez que si vous utilisez des paquets Linux RPM (MySQL-server-VERSION.rpm), le script mysql.server est installé sous le nom /etc/init.d/mysql. Vous n'avez pas à l'installer manuellement. Voyez Section 2.2.12, « Installer MySQL sous Linux » pour plus d'informations sur les paquets Linux RPM.

Certains éditeurs fournissent des paquets RPM qui installent un script de démarrage sous un autre nom, comme mysqld.

Si vous installez MySQL depuis une distribution source, ou en utilisant une distribution binaire qui n'installe pas automatiquement le script mysql.server, vous pouvez l'installer manuellement. Le script est disponible dans le dossier support-files du dossier d'installation MySQL, ou dans le dossier source de MySQL.

Pour installer mysql.server manuellement, copiez-le dans le dossier /etc/init.d sous le nom mysql, puis rendez-le exécutable. Pour cela, placez-vous dans le dossier où mysql.server est stocké, et utilisez ces commandes :

shell> cp mysql.server /etc/init.d/mysql
shell> chmod +x /etc/init.d/mysql

Les anciens systèmes Red Hat utilisent le dossier /etc/rc.d/init.d plutôt que /etc/init.d. Adaptez les commandes précédentes. Alternativement, créez un lien symbolique /etc/init.d qui pointe sur /etc/rc.d/init.d :

shell> cd /etc
shell> ln -s rc.d/init.d .

Après installation du script, les commandes doivent être activées pour fonctionner au lancement du système, sur votre système d'exploitation. Sous Linux, vous pouvez utiliser chkconfig :

shell> chkconfig --add mysql

Sur certains systèmes Linux, les commandes suivantes sont aussi nécessaires pour activer totalement le script mysql :

shell> chkconfig --level 345 mysql on

Sous FreeBSD, les scripts de démarrage vont généralement dans le dossier /usr/local/etc/rc.d/. La page de manuel rc(8) indique que les scripts de ce dossier ne sont exécutés que si leur nom est de la forme *.sh. Tout autre fichier de ce dossier sera alors ignoré. En d'autres termes, vous devez installer le script mysql.server sous le nom /usr/local/etc/rc.d/mysql.server.sh pour activer le démarrage automatique.

Alternativement à la configuration précédente, certains systèmes d'exploitation utilisent aussi /etc/rc.local ou /etc/init.d/boot.local pour lancer des services supplémentaires au démarrage. Pour lancer MySQL avec cette méthode, vous pouvez ajouter une commande comme celle-ci au fichier de démarrage :

/bin/sh -c 'cd /usr/local/mysql; ./bin/mysqld_safe --user=mysql &'

Pour les autres systèmes, consultez la documentation de votre système d'exploitation pour savoir comment installer un script de démarrage.

Vous pouvez aussi ajouter des options à mysql.server via le fichier global /etc/my.cnf file. Un fichier /etc/my.cnf typique peut ressembler à ceci :

[mysqld]
datadir=/usr/local/mysql/var
socket=/var/tmp/mysql.sock
port=3306
user=mysql

[mysql.server]
basedir=/usr/local/mysql

Le script mysql.server comprend les options suivantes : basedir, datadir et pid-file. Si spécifiées, elles doivent être placées dans un fichier d'options, et non pas en ligne de commande. mysql.server comprend les options de ligne de commande start et stop.

La table suivante montre quels groupes d'options chaque script de démarrage utilise :

Script

Groupe d'options

mysqld

mysqld et server

mysql.server

mysql.server, mysqld, et server

safe_mysqld

mysql.server, mysqld, et server

[mysqld-major-version] signifie que des groupes ayant des noms tels que [mysqld-4.0], [mysqld-4.1], et [mysqld-5.0] seront lus par les serveurs de versions 4.0.x, 4.1.x, 5.0.x, etc. Cette fonctionnalité a été ajoutée en MySQL 4.0.14. Elle sert à spécifier des options qui ne seront lues que par des serveurs dont les versions sauront les comprendre.

À des fins de compatibilité ascendante, mysql.server lit aussi le groupe d'options [mysql_server] et mysqld_safe lit le groupe d'options [safe_mysqld]. Cependant, il est recommandé de modifier vos fichiers de configuration pour utiliser les groupes [mysql.server] et [mysqld_safe] à la place.

Voir Section 4.3.2, « Fichier d'options my.cnf ».

2-5-2-3 - Problèmes de démarrage du serveur MySQL

Si vous avez des problèmes pour lancer le serveur, voici quelques pistes que vous pouvez essayer :

- spécifiez toutes les options spéciales nécessaires aux moteurs de tables que vous utilisez ;

- assurez-vous que le serveur sait où trouver le dossier de données ;

- assurez-vous que le serveur peut utiliser le dossier de données. Le propriétaire et les droits du dossier de données et son contenu doivent être accessibles au serveur, en lecture et écriture ;

- vérifiez le log d'erreurs pour voir pourquoi le serveur ne démarre pas ;

- vérifiez que les interfaces réseau sont accessibles au serveur.

Certains moteurs de stockage ont des options qui contrôlent leur comportement. Vous devrez créer un fichier d'options my.cnf et y configurer celles des moteurs que vous voulez utiliser. Si vous allez utiliser des tables qui supportent les transactions (InnoDB, BDB), assurez-vous qu'elles sont bien configurées comme vous le souhaitez ;

- si vous utilisez les tables InnoDB, voyez les options de démarrage spécifiques à InnoDB. En MySQL version 3.23, vous devez configurer InnoDB explicitement ou le serveur ne pourra pas démarrer. Depuis MySQL 4.0, InnoDB utilise des valeurs par défaut pour sa configuration, si vous n'en spécifiez pas. Voir Section 15.4, « Configuration InnoDB » ;

- si vous utilisez les tables BDB (Berkeley DB), vous devez vous familiariser avec les différentes options spécifiques à BDB. Voir Section 14.4.3, « Options de démarrage BDB » ;

Lorsque le démon mysqld démarre, il change le dossier de travail par le dossier de données. C'est là qu'il doit trouver les fichiers de log, et le fichier pid (ID de processus), ainsi que les dossiers de base.

Le chemin du dossier de données est codé en dur lorsque la distribution est compilée. Cependant, si mysqld cherche le dossier de données ailleurs que là où il est vraiment, il ne va pas fonctionner correctement. Vous pouvez lire les chemins par défaut en invoquant mysqld avec l'option --verbose ou --help. Avant MySQL 4.1, omettez --verbose.

Si les valeurs par défaut ne correspondent pas à votre installation MySQL, vous pouvez les modifier en spécifiant des options de ligne de commande pour mysqld et mysqld_safe. Vous pouvez aussi lister les options dans un fichier d'options.

Pour spécifier la localisation du dossier de données explicitement, utilisez l'option --datadir. Cependant, vous pouvez spécifier à mysqld le chemin du dossier de base sous lequel MySQL est installé, et il va rechercher le dossier de données là. Vous pouvez faire cela avec l'option --basedir.

Pour vérifier l'effet de ces options, appelez mysqld avec ces options, suivies de --verbose et --help. Par exemple, si vous modifiez le chemin pour celui dans lequel mysqld est installé, alors vous pouvez utiliser la commande suivante, et vous verrez l'effet sur le démarrage du serveur avec une installation de base /usr/local :

shell> ./mysqld --basedir=/usr/local --verbose --help

Vous pouvez spécifier d'autres options comme --datadir, mais notez que --verbose et --help doivent être les dernières options. Avant MySQL 4.1, omettez l'option --verbose.

Une fois que vous déterminez les configurations que vous voulez, lancez le serveur avec --verbose et --help.

Si votre démon mysqld fonctionne déjà, vous pouvez connaître les chemins de configuration avec la commande :

shell> mysqladmin variables

ou :

shell> mysqladmin -h host_name variables

host_name est le nom de l'hôte MySQL.

Si vous avez une erreur Errcode 13 (ce qui signifie Permission denied) lorsque vous démarrez mysqld, cela signifie que les droits d'accès au serveur ou son contenu ne sont pas bons. Dans ce cas, vous devez modifier les droits sur les dossiers et fichiers que le serveur va utiliser. Vous pouvez aussi lancer le serveur en tant que root, mais cela pose des problèmes de sécurité, et il vaut mieux l'éviter.

Sous Unix, vérifiez l'existence du dossier de données et vérifiez le nom du propriétaire du dossier de données et de son contenu. Par exemple, si le dossier est /usr/local/mysql/var, utilisez cette commande :

shell> ls -la /usr/local/mysql/var

Si le dossier, ses sous-dossiers ou ses fichiers ne sont pas au nom du compte qui fait tourner le serveur, changez le propriétaire avec cette commande :

shell> chown -R mysql /usr/local/mysql/var
shell> chgrp -R mysql /usr/local/mysql/var

Quelle que soit la méthode que vous utilisez pour démarrer le serveur, si elle échoue, vérifiez le fichier de logs d'erreurs pour savoir pourquoi. Les fichiers de log sont situés dans le dossier de données (typiquement /usr/local/mysql/data pour une distribution binaire, /usr/local/var pour une distribution source, et \mysql\data\mysql.err sous Windows). Regardez dans le dossier de données et recherchez des fichiers de la forme host_name.err et host_name.log ou host_name est le nom de votre serveur. Vérifiez alors les dernières lignes de ce fichier :

shell> tail host_name.err
shell> tail host_name.log

Recherchez des lignes comme celles-ci :

000729 14:50:10  bdb:  Recovery function for LSN 1 27595 failed
000729 14:50:10  bdb:  warning: ./test/t1.db: No such file or directory
000729 14:50:10  Can't init databases

Cela signifie que vous n'avez pas démarré mysqld avec --bdb-no-recover et Berkeley DB a trouvé une erreur dans les fichiers de logs lorsqu'il a essayé de restaurer votre base. Pour pouvoir continuer, vous devez déplacer le vieux fichier de logs Berkeley DB vers un autre dossier, pour l'examiner plus tard. Les fichiers de logs sont nommés log.0000000001, et ce nombre augmente au fil du temps.

Si vous exécutez mysqld avec les tables BDB et que mysqld fait des core dumps au démarrage, c'est peut-être que vous avez des problèmes avec le fichier de restauration de BDB. Dans ce cas, essayez de démarrer mysqld avec --bdb-no-recover. Si cela aide, vous devriez alors retirer tous les fichiers de logs log.* du dossier de données, et démarrer mysqld à nouveau.

Si vous obtenez l'erreur suivante, cela signifie que d'autres programmes (ou un autre serveur mysqld) fonctionnent déjà avec le port TCP/IP ou la socket que mysqld essaie d'utiliser :

Can't start server: Bind on TCP/IP port: Address already in use
Can't start server : Bind on unix socket...

Utilisez ps pour vous assurer que vous n'avez pas d'autre serveur mysqld qui fonctionne. Si c'est le cas, éteignez le serveur avant de lancer mysqld à nouveau. Si un autre serveur fonctionne, et que vous voulez vraiment en avoir plusieurs, voyez la section Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine ».

Si vous ne pouvez pas trouver d'autre serveur en fonctionnement, essayez d'exécuter la commande telnet votre-nom-d-hote numero-de-port-tcp puis pressez la touche Entrée plusieurs fois. Si vous n'obtenez pas de message d'erreur comme telnet: Unable to connect to remote host: Connection refused, alors un autre processus utilise le port TCP/IP de mysqld. Vous devrez alors rechercher le programme qui utilise ce port, et le désactiver, ou bien dire à mysqld d'écouter sur un autre port avec l'option --port. Dans ce cas, vous devrez aussi spécifier le numéro de port à tous les clients qui se connectent au serveur via TCP/IP.

Une autre raison d'inaccessibilité du port est que vous avez un coupe-feu qui fonctionne, et qui bloque ces ports. Pour cela, modifiez la configuration du coupe-feu pour libérer l'accès au port.

Si safe_mysqld démarre le serveur, mais que vous n'arrivez pas à vous y connecter, vous devriez vous assurer que vous avez une entrée dans le fichier /etc/hosts qui ressemble à ceci :

127.0.0.1       localhost

Ce problème survient uniquement sur les systèmes qui n'ont pas une bibliothèque de threads fonctionnels, ou pour lesquels MySQL a été configuré pour utiliser les MIT-pthreads.

Si vous n'arrivez toujours pas à lancer mysqld, vous pouvez essayer de générer un fichier de traces avec l'option --debug. Voir Section D.1.2, « Créer un fichier de traçage ».

2-5-3 - Création des premiers droits MySQL

Le processus d'installation de MySQL passe par la création de la base de données mysql, qui contient les tables de droits :

- la distribution Windows contient des tables de droits préinitialisées automatiquement ;

- sous Unix, les tables de droits sont remplies par le programme mysql_install_db. Certains assistants d'installation le font pour vous. Les autres vous imposent de le faire manuellement. Pour plus de détails, voyez Section 2.5.2, « Procédures de postinstallation sous Unix ».

Le script mysql_install_db démarre le serveur mysqld et initialise les tables de droits, avec les paramètres suivants :

- deux comptes MySQL root sont créés en tant qu'administrateurs ayant tous les droits. Le mot de passe de l'utilisateur initial root est vide, ce qui permet à n'importe qui de se connecter en tant que root sans mot de passe, pour profiter de tous les droits.

- Sous Windows, un compte root permet de se connecter depuis l'hôte local, et l'autre depuis n'importe quel hôte.

- Sous Unix, les deux comptes root sont destinés à être utilisés depuis le compte local. Les connexions doivent être faites en spécifiant le nom d'hôte localhost, ou le véritable nom d'hôte, ou l'adresse IP ;

- deux comptes utilisateur anonyme sont créés, qui peuvent faire ce qu'ils veulent avec toutes les tables dans la base de données 'test' ou commençant par 'test_'. Cela signifie qu'un utilisateur peut se connecter sans mot de passe et être traité comme un utilisateur anonyme.

- Sous Windows, un compte anonyme sert depuis l'hôte local. Ce compte a tous les droits, comme root. L'autre sert aux connexions depuis les hôtes, et a tous les droits pour les bases test ou commençant par test.

- Sous Unix, les deux comptes anonymes servent depuis l'hôte local. Les connexions doivent être faites en spécifiant le nom d'hôte localhost, ou le véritable nom d'hôte, ou l'adresse IP. Ces comptes ont tous les droits dans les bases test ou dont le nom commence par test_.

Comme indiqué, aucun des comptes initiaux n'a de mot de passe. Cela signifie que votre installation MySQL n'est pas protégée jusqu'à ce que vous y remédiiez :

- si vous voulez éviter que les clients ne se connectent en tant qu'utilisateur anonyme sans mot de passe, vous devez assigner des mots de passe à ces comptes, ou bien les supprimer ;

- vous devez assigner des mots de passe aux comptes root.

Les instructions suivantes décrivent comment configurer les mots de passe pour les comptes initiaux, en commençant par les comptes anonymes, puis pour les comptes root. Remplacez « nouveau_mot » dans les exemples ci-dessous par le nouveau mot de passe que vous voulez utiliser. Ces instructions montrent aussi comment supprimer les comptes anonymes.

Vous pouvez différer le changement de mot de passe jusqu'à plus tard, pour pouvoir utiliser cette configuration pour les tests. Cependant, n'oubliez pas de le faire avant de mettre votre serveur en production.

Pour assigner des mots de passe aux comptes anonymes, vous pouvez utiliser les commandes SET PASSWORD et UPDATE. Dans les deux cas, assurez-vous de chiffrer les mots avec la fonction PASSWORD().

Pour utiliser SET PASSWORD sur Windows, faites :

shell> mysql -u root
mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('nouveau_mot');
mysql> SET PASSWORD FOR ''@'%' = PASSWORD('nouveau_mot');

Pour utiliser SET PASSWORD sur Unix, faites :

shell> mysql -u root
mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('nouveau_mot');
mysql> SET PASSWORD FOR ''@'host_name' = PASSWORD('nouveau_mot');

Dans la seconde commande SET PASSWORD, remplacez host_name par le nom de l'hôte du serveur. C'est le nom qui sera spécifié dans la colonne Host de la ligne du compte root, et qui n'est pas localhost. Si vous ne savez pas quel nom d'hôte c'est, utilisez cette commande avant d'utiliser SET PASSWORD :

mysql> SELECT Host, User FROM mysql.user;

Recherchez une ligne qui contient root dans la colonne User et quelque chose d'autre que localhost dans la colonne Host. Puis, utilisez la valeur de Host dans la seconde commande SET PASSWORD.

L'autre moyen d'assigner des mots de passe à un compte anonyme est d'utiliser la commande UPDATE pour modifier la table user directement. Connectez-vous en tant que root et envoyez une commande UPDATE qui assigne une valeur à la colonne Password dans les lignes appropriées de la table user. La procédure est la même sous Unix et sous Windows. La commande suivante UPDATE met à jour le mot de passe pour les deux comptes en même temps :

shell> mysql -u root
mysql> UPDATE mysql.user SET Password = PASSWORD('nouveau_mot')
->     WHERE User = '';
mysql> FLUSH PRIVILEGES;

Après voir fait la mise à jour des mots de passe dans la table user avec la commande UPDATE, vous devez demander au serveur de relire les tables de droits, avec FLUSH PRIVILEGES. Sinon, les modifications ne seront pas prises en compte avant le prochain redémarrage du serveur.

Si vous préférez supprimer les comptes anonymes, faites ceci :

shell> mysql -u root
mysql> DELETE FROM mysql.user WHERE User = '';
mysql> FLUSH PRIVILEGES;

La commande DELETE s'applique à Windows et Unix. Sous Windows, si vous voulez supprimer uniquement les comptes anonymes qui ont les mêmes droits que root, faites ceci :

shell> mysql -u root
mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;

Ce compte permet un accès anonyme avec les pleins droits : le supprimer améliore la sécurité.

Vous pouvez assigner les mots de passe au compte root de nombreuses façons. La discussion suivante montre trois méthodes :

- utiliser la commande SET PASSWORD ;

- utiliser la commande en ligne mysqladmin ;

- utiliser la commande UPDATE.

Pour assigner un mot de passe avec la commande SET PASSWORD, connectez-vous en tant que root et faites deux commandes SET PASSWORD. Assurez-vous de chiffrer le mot de passe avec PASSWORD().

Pour Windows, faites ceci :

shell> mysql -u root
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('nouveau_mot');
mysql> SET PASSWORD FOR 'root'@'%' = PASSWORD('nouveau_mot');

Pour Unix, faites ceci :

shell> mysql -u root
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('nouveau_mot');
mysql> SET PASSWORD FOR 'root'@'host_name' = PASSWORD('nouveau_mot');

Dans la seconde commande SET PASSWORD, remplacez host_name par le nom de l'hôte du serveur. C'est le même nom que celui qui a été utilisé pour les comptes anonymes.

Pour assigner un mot de passe à root en utilisant mysqladmin, exécutez les commandes suivantes :

shell> mysqladmin -u root password "nouveau_mot"
shell> mysqladmin -u root -h host_name password "nouveau_mot"

Ces commandes s'appliquent à Windows et à Unix. Dans la seconde commande, remplacez host_name par le nom du serveur hôte. Les guillemets doubles autour du mot de passe ne sont pas nécessaires, mais vous devez les utiliser si vous avez des espaces ou d'autres caractères spéciaux.

Si vous utilisez un serveur d'une très vieille version de MySQL, la commande mysqladmin va échouer avec un message d'erreur : parse error near 'SET password'. La solution à ce problème est de changer la version du serveur MySQL.

Vous pouvez aussi utiliser UPDATE pour modifier directement la table user. La commande UPDATE suivante assigne un mot de passe aux comptes root en même temps :

shell> mysql -u root
mysql> UPDATE mysql.user SET Password = PASSWORD('nouveau_mot')
->     WHERE User = 'root';
mysql> FLUSH PRIVILEGES;

La commande UPDATE s'applique à Windows et à Unix.

Après modification des mots de passe, vous devrez les fournir à chaque connexion au serveur. Par exemple, si vous voulez utiliser la commande mysqladmin pour éteindre le serveur, vous devez utiliser une commande de cette forme :

shell> mysqladmin -u root -p shutdown
Enter password: (enter root password here)

Note : si vous perdez votre mot de passe root après l'avoir configuré, la procédure pour le remettre à zéro est présentée dans la section Section A.4.1, « Comment réinitialiser un mot de passe Root oublié ».

Pour créer de nouveaux comptes, utilisez la commande GRANT. Pour les instructions, voyez Section 5.6.2, « Ajouter de nouveaux utilisateurs à MySQL ».

2-6 - Changer de version de MySQL

Vous pouvez toujours mettre à jour les fichiers de structures et de données entre les différentes versions de MySQL. La version de base actuelle est la version 3. Si vous changez le jeu de caractères lors de l'utilisation de MySQL (ce qui va aussi affecter le tri), vous devez exécuter la commande myisamchk -r -q --set-character-set=charset sur toutes les tables. Sinon, vos index ne seront pas correctement triés.

Les instructions suivantes sont un pense-bête de tout ce à quoi vous devez penser lors d'une mise à jour.

- Lisez la section de mise à jour pour la version que vous voulez utiliser, afin de voir les nouvelles fonctionnalités que vous pourrez utiliser. Par exemple, en passant de MySQL 4.1 en 5.0, lisez l'historique de la version 5.0. Voir Annexe C, Historique des changements MySQL.

- Avant de faire une mise à jour, faites une sauvegarde de vos données.

- Si vous utilisez MySQL Server sur Windows, voyez Section 2.2.11, « Mettre à jour MySQL sous Windows ».

- Une mise à jour peut impliquer la modification des tables de droits, dans la base mysql. Certaines colonnes ou tables peuvent être ajoutées pour supporter de nouvelles fonctionnalités. Pour tirer parti de ces fonctionnalités, assurez-vous de mettre à jour vos tables. La procédure de migration est présentée dans Section 2.6.7, « Mise à jour des tables de droits ».

- Si vous utilisez la réplication, voyez la Section 6.6, « Changer de version de réplication » pour savoir comment mettre à jour votre architecture de réplication.

- Si vous installez une distribution MySQL-Max qui inclut le serveur mysqld-max, puis que vous passez à une version non Max de MySQL, mysqld_safe va tenter d'utiliser l'ancien serveur mysqld-max. Si vous faites une telle mise à jour, vous devez supprimer manuellement l'ancien serveur mysqld-max pour vous assurer que mysqld_safe utilise le nouveau mysqld.

Si vous avez peur des nouvelles versions, vous pouvez toujours renommer votre vieux mysqld avec un nom comme mysqld-ancienne_version. Si votre nouveau serveur mysqld se comporte bizarrement, vous pourrez toujours l'éteindre, et redémarrer avec votre vieux mysqld !

Lorsque vous faites une évolution de version, vous devriez toujours faire une sauvegarde de vos anciennes données.

Si après un changement de version, vous rencontrez des problèmes avec les clients recompilés, comme Commands out of sync ou des core dumps inopinés, vous avez probablement utilisé un vieux fichier d'entête ou une vieille bibliothèque lors de la compilation de vos programmes. Dans ce cas, vérifiez la date de votre fichier mysql.h, et de votre bibliothèque libmysqlclient.a, pour vous assurer qu'ils proviennent bien de la nouvelle distribution MySQL. Si ce n'est pas le cas, recompilez vos programmes !

Si vous avez des problèmes tels que le nouveau serveur mysqld ne peut plus démarrer, ou que vous ne pouvez pas vous connecter sans un mot de passe, vérifiez que vous n'avez pas un vieux fichier my.cnf dans votre installation ! Vous pouvez le vérifier comme ceci : program-name --print-defaults. Si cette commande affiche autre chose que le nom du programme, vous avez un fichier my.cnf actif, qui perturbe vos opérations.

C'est une bonne idée que de reconstruire et réinstaller le module Msql-Mysql à chaque fois que vous faites une nouvelle version de MySQL, en particulier si vous rencontrez des symptômes tels que les DBI qui font des core dumps après votre mise à jour de MySQL.

2-6-1 - Passer de version 4.1 en version 5.0

En général, il faut suivre ces instructions pour passer en version 5.0, depuis la version 4.1.

- Lisez la présentation de la version 5.0, pour savoir quelles évolutions et quelles nouveautés vous pourrez utiliser. Voir Section C.1, « Changements de la version 5.0.0 (Développement) ».

- Si vous utilisez MySQL Server sur Windows, voyez la section Section 2.2.11, « Mettre à jour MySQL sous Windows ».

- MySQL 5.0 apporte les procédures stockées. Ce support requiert la table de droits proc dans la base mysql. Après la mise à jour du serveur, mettez aussi à jour les tables de droits pour vous assurer que la table proc existe. La procédure utilise le script mysql_fix_privilege_tables et est décrite dans la section Section 2.6.7, « Mise à jour des tables de droits ».

- Si vous utilisez la réplication, voyez aussi la section Section 6.6, « Changer de version de réplication », pour la mise à jour de votre architecture.

2-6-2 - Passer de la version 4.0 à la version 4.1

En général, vous devez suivre les instructions suivantes pour passer de MySQL 4.0 à 4.1.

- Vérifiez la liste des modifications de cette section, pour voir si elles ont un impact sur vos applications.

- Lisez la liste des nouveautés de la version 4.1 pour identifier les nouvelles fonctionnalités significatives pour vos projets. Voir Section C.2, « Changements de la version 4.1.x (Alpha) ».

- Si vous faites fonctionner MySQL sur Windows, voyez Section 2.2.11, « Mettre à jour MySQL sous Windows ».

- Après mise à jour du serveur, mettez à jour les tables de droits, pour accepter des colonnes Password plus grandes. La procédure utilise le script mysql_fix_privilege_tables et est décrite dans la section Section 2.6.7, « Mise à jour des tables de droits ». Les implications du changement de gestion du mot de passe sont décrites plus loin dans cette section. Si vous ne les faites pas, MySQL ne pourra pas utiliser le protocole sécuritaire pour l'identification.

- Si vous utilisez la réplication, voyez la section Section 6.6, « Changer de version de réplication » pour mettre à jour votre installation.

- Le moteur de table Berkeley DB table est passé en version DB 4.1 (depuis la 3.2), et il dispose d'un nouveau format de log. Si vous devez revenir en version 4.0, vous devrez utiliser mysqldump pour exporter vos tables BDB au format texte, et effacer tous les fichiers log.XXXXXXXXXX avant de redémarrer le serveur MySQL 4.0 et de réimporter les données.

- Le support des jeux de caractères a été amélioré. Si vous avez des tables qui contiennent des données représentées dans un jeu de caractères que MySQL 4.1 supporte directement, vous pouvez convertir ces colonnes vers le bon jeu de caractères avec les instructions du chapitre Section 10.10.2, « Conversion de colonnes version 4.0 en version 4.1 ».

- Si vous utilisez un vieux module DBD-mysql (Msql-MySQL-modules) vous devez mettre à jour le module DBD-mysql. Tout ce qui est plus récent que DBD-mysql 2.xx doit convenir.

Si vous ne mettez pas à jour, certaines commandes telles que DBI->do() ne rapporteront pas correctement les erreurs.

- L'option --defaults-file=option-file-name vous donnera une erreur si le fichier d'options n'existe pas.

Plusieurs comportements visibles ont changé entre MySQL 4.0 et MySQL 4.1 pour corriger des bogues critiques et rendre MySQL plus compatible avec le standard SQL. Ces changements peuvent affecter votre application.

Certains des comportements 4.1 peuvent être testés en version 4.0 avant de passer à la 4.1. Nous avons ajouté l'option --new de démarrage de mysqld pour les versions supérieures à la 4.0.12. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Cette option vous donne le comportement de la version 4.1 pour les modifications les plus critiques. Vous pouvez aussi activer ces comportements pour une connexion particulière en utilisant la commande SET @@new=1, pour désactiver cette option avec SET @@new=0.

Si vous pensez que certains des changements de la version 4.1 vous affecteront, nous vous recommandons, avant de passer en version 4.1, de télécharger la dernière version 4.0, et de l'exécuter avec l'option --new en plus de vos configurations habituelles :

[mysqld-4.0]
new

De cette manière, vous pouvez tester le comportement de la version 4.1 depuis votre serveur 4.0. Cela vous donnera le temps de supprimer les anomalies, et de passer sans problème à la version 4.1, ultérieurement. En faisant cela, vous n'allez pas rencontrer de bogue accidentel lors du changement, que vous n'aurez pas corrigé grâce à --new.

Voici une liste complète, vous indiquant ce à quoi vous devez faire attention lors du changement de version.

Modification du serveur

- Toutes les colonnes et tables ont désormais un jeu de caractères, qui apparaît dans le résultat de la commande SHOW CREATE TABLE et mysqldump. Voir Chapitre 10, Jeux de caractères et Unicode. (MySQL 4.0.6 et plus récents peuvent lire les nouveaux fichiers de dump, mais pas les plus anciennes versions de MySQL). Cela ne doit pas affecter les applications qui n'utilisent qu'un seul jeu de caractères.

- Le format de définition de table du fichier .frm a légèrement changé en version 4.1. Les versions de MySQL 4.0 à partir de la 4.0.11 peuvent lire le nouveau format .frm directement, mais les versions plus anciennes ne le peuvent pas. Si vous devez déplacer des tables de la version 4.1 vers une version 4.0.11, passez plutôt par mysqldump. Voir Section 8.8, « mysqldump, sauvegarde des structures de tables et les données ».

- Note importante : si vous mettez à jour en version InnoDB-4.1.1 ou plus récente, il sera difficile de revenir à une version plus ancienne, 4.0 or 4.1.0 ! Ceci est dû aux versions de InnoDB qui ne reconnaissent pas les espaces de tables multiples.

- Si vous utilisez plusieurs serveurs sur la même machine Windows, vous devriez utiliser l'option --shared_memory_base_name avec des valeurs différentes sur toutes les machines.

- L'interface des fonctions UDF agrégeantes a un peu changé. Vous devez commencer par déclarer une fonction xxx_clear() pour chaque fonction agrégeante XXX().

Évolution du client

- mysqldump dispose des options --opt et --quote-names, qui sont activées par défaut. Vous pouvez les désactiver avec --skip-opt et --skip-quote-names.

Évolution du SQL

- La comparaison de chaînes fonctionne maintenant conformément au standard SQL : au lieu de supprimer les espaces de fin de chaîne avant la comparaison, nous complétons les chaînes courtes avec des espaces. Le problème est que maintenant, 'a' > 'a\t', ce qui n'était pas le cas avant. Si vous avez des tables avec des colonnes CHAR ou VARCHAR dont le dernier caractère peut être de code ASCII(32) ou plus petit, vous devez utiliser la commande REPAIR TABLE ou myisamchk.

- Lorsque vous utilisez des commandes DELETE multitables, vous devez utiliser les alias de tables que vous voulez effacer, et non pas le véritable nom de la table. Par exemple, au lieu de :

DELETE test FROM test AS t1, test2 WHERE ...

faites :

DELETE t1 FROM test AS t1, test2 WHERE ...

- TIMESTAMP est maintenant retourné comme une chaîne, au format 'YYYY-MM-DD HH:MM:SS'. L'option --new peut être utilisée depuis la version 4.0.12, pour que le serveur adopte le comportement de la version 4.1 pour ce point. Si vous voulez recevoir la version entière de la valeur, comme en version 4.0, il suffit d'ajouter +0 à chaque colonne TIMESTAMP :

mysql> SELECT ts_col + 0 FROM tbl_name;

La largeur d'affichage des colonnes TIMESTAMP n'est plus supportée. Par exemple, si vous déclarez une colonne de type TIMESTAMP(10), le nombre (10) est ignoré.

Ces changements sont nécessaires pour respecter les standards SQL. Dans une future version, une autre modification aura lieu, mais restera compatible avec celle-ci : la taille de la valeur TIMESTAMP indiquera le nombre de chiffres voulu pour les fractions de seconde.

- Les valeurs binaires, comme 0xFFDF, sont maintenant supposées être des chaînes et non pas des nombres. Cela corrige des problèmes avec les jeux de caractères, où il est plus pratique d'insérer une chaîne comme une chaîne binaire. Avec cette modification, vous devez utiliser la fonction CAST() si vous voulez comparer des valeurs binaires avec les entiers :

mysql> SELECT CAST(0xFEFF AS UNSIGNED INTEGER) < CAST(0xFF AS UNSIGNED INTEGER);
-> 0

Si vous n'utilisez pas CAST(), une comparaison lexicale de la chaîne aura lieu  :

mysql> SELECT 0xFEFF < 0xFF;
-> 1

Utiliser des chaînes binaires dans un contexte numérique, ou bien comparer des valeurs avec les opérateurs comme = devrait fonctionner comme auparavant. L'option --new peut être utilisée à partir de la version 4.0.13 pour que le serveur 4.0 se comporte comme le serveur 4.1.

- Les fonctions qui retournent des DATE, DATETIME, ou TIME sont désormais traitées lors de leur arrivée sur le client. Par exemple, en MySQL 4.1, vous obtenez le résultat suivant :

mysql> SELECT CAST("2001-1-1" as DATETIME);
-> '2001-01-01 00:00:00'

En MySQL 4.0, le résultat est différent :

mysql> SELECT CAST("2001-1-1" as DATETIME);
-> '2001-01-01'

- Les valeurs DEFAULT ne peuvent plus être spécifiées pour les colonnes de type AUTO_INCREMENT. En 4.0, la clause DEFAULT est ignorée silencieusement. En 4.1, une erreur survient.

- LIMIT n'accepte plus les arguments négatifs. Utilisez 18446744073709551615 au lieu de -1.

- SERIALIZE n'est plus une option valide pour la variable sql_mode. Il faut utiliser la commande SET TRANSACTION ISOLATION LEVEL SERIALIZABLE à la place. SERIALIZE n'est plus valide comme option de --sql-mode pour mysqld, non plus. Utilisez --transaction-isolation=SERIALIZABLE.

Changement de l'interface C

- Certaines fonctions C telles que mysql_real_query() retournent maintenant 1 en cas d'erreur, et non plus -1. Vous aurez peut-être à changer certaines anciennes applications comme ceci :

if (mysql_real_query(mysql_object, query, query_length) == -1)
{
printf("Erreur");
}

Modifiez le test de comparaison à 0 :

if (mysql_real_query(mysql_object, query, query_length) != 0)
{
printf("Erreur");
}

Gestion des mots de passe

Le mécanisme de mot de passe a changé en version 4.1 pour assurer une meilleure sécurité, mais cela pose des problèmes de compatibilité, si vous avez encore des clients qui utilisent les bibliothèques 4.0 ou plus anciennes. Il est probable que vous ayez de tels clients, s'ils se connectent depuis des serveurs distants qui n'ont pas encore adopté la version 4.0. La liste suivante présente les stratégies de mise à jour. Elles représentent différents compromis entre la compatibilité et la sécurité.

- Ne passez pas en version 4.1. Aucun comportement ne changera, mais vous ne pourrez pas utiliser les nouvelles fonctionnalités du protocole de la version 4.1. MySQL a amélioré le protocole client/serveur de la version 4.1, en ajoutant les commandes préparées et le support des jeux de caractères. Voir Section 24.2.4, « Fonctions C de commandes préparées ».

- Passez en version 4.1, utilisez le script mysql_fix_privilege_tables pour agrandir la colonne Password de la table user pour qu'elle puisse contenir les nouveaux hashs de mots de passe. Mais lancez le serveur avec l'option --old-passwords pour que les clients pré-4.1 puissent continuer d'utiliser leurs anciens comptes. Finalement, lorsque tous les clients seront passés en version 4.1, vous pourrez cesser d'utiliser l'option --old-passwords. Vous pouvez aussi changer les mots de passe de vos comptes MySQL pour adopter le nouveau format.

- Passez en version 4.1 et utilisez le script mysql_fix_privilege_tables pour agrandir la colonne Password de la table user. Si vous savez que tous les clients sont passés en version 4.1, n'utilisez pas l'option --old-passwords. Au lieu de cela, changez les mots de passe de tous les comptes, pour qu'ils adoptent le nouveau format. Une installation 100 % 4.1 est la plus sûre.

D'autres informations sur le nouvel algorithme de protection des mots de passe et les opérations les concernant sont disponibles dans la section Section 5.5.9, « Hashage de mots de passe en MySQL 4.1 ». Section A.2.3, « Erreur Client does not support authentication protocol ».

2-6-3 - Passer de la version 3.23 à la version 4.0

En général, ce que vous devez faire pour passer en version 4.0, à partir d'une version 3.23 est listé ici.

- Vérifiez que les changements de la liste ci-dessous n'affectent pas votre application.

- Lisez les nouveautés de la version 4.0, pour savoir quelles nouvelles fonctionnalités vous allez découvrir en 4.0. Voir Section C.3, « Changements de la version 4.0.x (Production) ».

- Après mise à jour, exécutez le script mysql_fix_privilege_tables pour ajouter de nouveaux droits et fonctionnalités à la table MySQL. Voyez Section 2.6.7, « Mise à jour des tables de droits ».

- Éditez les scripts de démarrage MySQL pour les fichiers de configuration pour ne plus utiliser les options abandonnées, listées ci-dessous.

- Convertissez vos vieilles tables ISAM en tables MyISAM avec la commande : mysql_convert_table_format database. Pour convertir toutes les tables d'une base de données, utilisez cette commande :

shell> mysql_convert_table_format database db_name

Notez que cela ne doit être fait que si toutes les tables de la base sont des tables ISAM ou MyISAM. Pour éviter de convertir toutes les tables d'une base au format MyISAM, vous pouvez explicitement utiliser les noms de vos tables ISAM après le nom de la base dans la commande. Vous pouvez aussi utiliser la commande ALTER TABLE table_name TYPE=MyISAM sur toutes les tables ISAM.

Les tables individuelles peuvent être mises au format MyISAM en utilisant la commande ALTER TABLE suivante, pour chaque table :

mysql> ALTER TABLE tbl_name TYPE=MyISAM;

Pour connaître le type d'une table, utilisez cette commande :

mysql> SHOW TABLE STATUS LIKE 'tbl_name';

- Assurez-vous que vous n'avez pas de clients MySQL qui utilisent des bibliothèques partagées (comme les modules Perl Msql-Mysql). Si vous en avez, vous devriez les recompiler, car les structures utilisées dans libmysqlclient.so ont changé.

- Si vous utilisez MySQL sur Windows, voyez aussi Section 2.2.11, « Mettre à jour MySQL sous Windows ».

- Si vous utilisez la réplication, voyez aussi Section 6.6, « Changer de version de réplication » pour plus de détails sur la mise à jour de la réplication.

MySQL 4.0 va fonctionner même si vous ne suivez pas les instructions ci-dessus, mais il ne sera pas capable de profiter des nouveaux droits disponibles avec MySQL 4.0 et vous pourriez rencontrer des problèmes lors de l'évolution vers MySQL 4.1 ou plus récent. Les fichiers ISAM fonctionnent toujours en MySQL 4.0, mais ils sont abandonnés, et ils seront désactivés en MySQL 5.0.

Les anciens clients doivent fonctionner avec le serveur version 4.0 sans aucun problème.

Même si vous suivez les instructions ci-dessus, vous pourrez retourner en version MySQL 3.23.52 ou plus récente, si vous rencontrez des difficultés avec MySQL 4.0. Dans ce cas, vous devez utiliser la commande mysqldump sur toutes les tables qui utilisent un index en texte plein, et restaurer ces tables en 3.23 (car la version 4.0 utilise un nouveau format pour les index en texte plein).

Voici une liste plus complète de points à contrôler lorsque vous passez à la version 4.0.

- MySQL 4.0 a de très nombreux nouveaux droits dans la table mysql.user. Voir Section 5.5.3, « Droits fournis par MySQL ».

Pour installer ces nouveaux droits, suivez la procédure dans Section 2.6.7, « Mise à jour des tables de droits ». Jusqu'à ce que ce script soit exécuté, les utilisateurs auront les droits de SHOW DATABASES, CREATE TEMPORARY TABLES, et LOCK TABLES. Les droits de SUPER et EXECUTE héritent leur valeur du droit de PROCESS. REPLICATION SLAVE et REPLICATION CLIENT héritent leur valeur de FILE.

Si vous avez un script qui crée automatiquement des nouveaux utilisateurs, vous devez le modifier pour y inclure les nouveaux droits. Si vous n'utilisez pas la commande GRANT dans ces scripts, c'est une bonne idée que de les vérifier.

En version 4.0.2, l'option --safe-show-database est abandonnée (et ne fait plus rien du tout). Voir Section 5.4.3, « Options de démarrage qui concernent la sécurité ».

Si vous obtenez des interdictions d'accès pour les nouveaux utilisateurs en version 4.0.2, vous devriez vérifier si vous avez besoin de nouveaux droits que vous n'utilisiez pas avant. En particulier, vous aurez besoin du droit de REPLICATION SLAVE (au lieu de FILE) pour les nouveaux esclaves.

- safe_mysqld a été renommé en mysqld_safe. Pour assurer la compatibilité ascendante, les distributions binaires vont inclure pour quelque temps un lien symbolique de safe_mysqld vers mysqld_safe.

- Le support InnoDB est désormais inclus par défaut dans la distribution binaire. Si vous compilez MySQL depuis les sources, et que vous voulez économiser de la mémoire, utilisez l'option --skip-innodb au démarrage du serveur. Pour compiler MySQL sans le support InnoDB, utilisez le script configure avec l'option --without-innodb.

- Les paramètres de démarrage myisam_max_extra_sort_file_size et myisam_max_extra_sort_file_size sont désormais exprimés en octets, et non plus en Mo, comme cela était le cas jusqu'en version 4.0.3).

- mysqld dispose maintenant de l'option --temp-pool activée par défaut, car cela donne de meilleures performances sur certains systèmes d'exploitation, et notamment Linux.

- Les options de démarrage mysqld --skip-locking et --enable-locking ont été renommées --skip-external-locking et --external-locking.

- Les systèmes externes de verrouillage des tables MyISAM/ISAM sont désormais désactivés par défaut. Vous pouvez les réactiver avec l'option --external-locking. Pour la plupart des utilisateurs, ce n'est jamais nécessaire.

- Les options de démarrage suivantes ont été renommées :

Ancien nom

Nouveau nom.

myisam_bulk_insert_tree_size

bulk_insert_buffer_size

query_cache_startup_type

query_cache_type

record_buffer

read_buffer_size

record_rnd_buffer

read_rnd_buffer_size

sort_buffer

sort_buffer_size

warnings

log-warnings

err-log

--log-error (for mysqld_safe)

Les options de démarrage record_buffer, sort_buffer et warnings vont encore fonctionner avec MySQL 4.0, mais elles sont obsolètes.

Changements SQL :

- Les variables SQL suivantes ont changé de nom.

Ancien nom

Nouveau nom.

SQL_BIG_TABLES

BIG_TABLES

SQL_LOW_PRIORITY_UPDATES

LOW_PRIORITY_UPDATES

SQL_MAX_JOIN_SIZE

MAX_JOIN_SIZE

SQL_QUERY_CACHE_TYPE

QUERY_CACHE_TYPE

Les anciens noms fonctionneront encore en MySQL 4.0, mais sont obsolètes.

- Vous devez utiliser la commande SET GLOBAL SQL_SLAVE_SKIP_COUNTER=# au lieu de SET SQL_SLAVE_SKIP_COUNTER=#.

- SHOW MASTER STATUS retourne désormais une liste vide si les logs binaires ne sont pas activés.

- SHOW SLAVE STATUS retourne désormais une liste vide si l'esclave n'est pas initialisé.

- SHOW INDEX a deux colonnes de plus (Null et Index_type) qu'il n'avait pas en version 3.23.

- Le format de SHOW OPEN TABLE a été changé.

- ORDER BY col_name DESC trie les valeurs NULL en dernier, depuis MySQL 4.0.11. En 3.23 et dans les premières versions de 4.0, ce n'était pas toujours cohérent.

- CHECK, SIGNED, LOCALTIME et LOCALTIMESTAMP sont des mots réservés.

- Les colonnes DOUBLE et FLOAT acceptent désormais l'option UNSIGNED pour le stockage (auparavant, UNSIGNED était ignoré pour ces colonnes).

- Le résultat de toutes les opérations sur les bits, |, &, <<, >> et ~ est maintenant non signé. Cela peut poser des problèmes si vous aviez un contexte dans lequel vous souhaitez un résultat signé. Voir Section 12.7, « Fonctions de transtypage ».

Note : lorsque vous utilisez la soustraction entre des entiers dont l'un est UNSIGNED, le résultat sera non signé ! En d'autres termes, avant de passer à la version MySQL 4.0, vous devriez vérifier les situations où votre application soustrait une valeur d'un entier non signé, et que vous attendez une valeur négative, ou si vous soustrayez une valeur non signée d'une colonne. Vous pouvez désactiver ce comportement en utilisant l'option de démarrage --sql-mode=NO_UNSIGNED_SUBTRACTION lorsque vous démarrez mysqld. Voir Section 12.7, « Fonctions de transtypage ».

- Vous devriez utiliser des entiers pour stocker les valeurs dans les colonnes de type BIGINT (au lieu d'utiliser des chaînes, comme vous le faisiez en MySQL 3.23). Utiliser des chaînes va toujours fonctionner, mais passer des entiers est bien plus efficace.

- En version 3.23, INSERT INTO ... SELECT fonctionne toujours avec l'option IGNORE. En version 4.0.1, MySQL va s'arrêter (et peut-être annuler la transaction) si vous ne spécifiez pas l'option IGNORE.

- Vous devriez utiliser la commande TRUNCATE TABLE lorsque vous voulez effacer toutes les lignes d'une table, et que vous ne souhaitez pas savoir combien de lignes ont été effacées de la table (car TRUNCATE TABLE est plus rapide que DELETE FROM table_name).

- Vous allez rencontrer une erreur si vous avez un verrou actif ou une transaction active, et que vous essayez d'utiliser les commandes TRUNCATE TABLE ou DROP DATABASE.

- Pour utiliser MATCH ... AGAINST (... IN BOOLEAN MODE) avec vos tables, vous devez les reconstruire avec ALTER TABLE table_name TYPE=MyISAM, même si la table est déjà au format MyISAM. Voir Section 12.6.4, « Paramétrage précis de la recherche en text intégral de MySQL ».

- LOCATE() et INSTR() sont sensibles à la casse, si l'un des arguments est une chaîne binaire. Sinon, ils sont insensibles à la casse.

- STRCMP() utilise désormais le jeu de caractères courant pour les comparaisons, ce qui signifie que le comportement par défaut des comparaisons est désormais insensible à la casse.

- HEX(string) retourne désormais les caractères convertis sous la forme d'une chaîne hexadécimale. Si vous voulez convertir un nombre en hexadécimal, vous devez vous assurer d'appeler HEX() avec un argument numérique.

- RAND(seed) retourne un nombre différent en version 4.0 qu'en version 3.23 : cela est fait pour différencier plus fortement RAND(seed) de RAND(seed+1).

- Le type par défaut retourné par IFNULL(A,B) est maintenant le plus général des deux types A et B. (L'ordre est STRING, REAL puis INTEGER).

Changements de l'interface C

- Les fonctions de l'ancienne API C API mysql_drop_db, mysql_create_db et mysql_connect ne sont plus supportées, à moins que vous ne compiliez MySQL avec CFLAGS=-DUSE_OLD_FUNCTIONS. Au lieu de cela, il sera plus sage de changer vos programmes, pour qu'ils utilisent la nouvelle API 4.0.

- Dans la structure MYSQL_FIELD, length et max_length ont évolué de unsigned int en unsigned long. Cela ne va pas causer de problèmes, hormis le fait qu'ils peuvent générer des messages d'alerte lorsqu'ils sont utilisés comme argument de fonctions comme printf().

- Les clients multithreadés doivent utiliser mysql_thread_init() et mysql_thread_end(). Voir Section 24.2.15, « Comment faire un client MySQL threadé ».

Autres changements

- Si vous voulez recompiler le module Perl DBD::mysql, vous devez prendre les versions Msql-Mysql-modules 1.2218 ou plus récentes, car les anciennes versions des modules DBD utilisent une fonction drop_db() abandonnée.

2-6-4 - Passer de la version 3.22 à la version 3.23

Les clients des versions 3.22 et 3.21 vont fonctionner sans problèmes avec la version 3.23 du serveur.

La liste suivante indique les points à vérifier lors de la migration

Changement de tables

- MySQL 3.23 supporte les nouvelles tables MyISAM et l'ancien type ISAM. Par défaut, toutes les nouvelles tables sont créées avec MyISAM à moins que vous ne lanciez mysqld avec l'option --default-table-type=isam. Vous n'avez pas à convertir les anciennes tables ISAM pour les utiliser avec MySQL 3.23. Vous pouvez convertir les tables ISAM en MyISAM avec la commande ALTER TABLE tbl_name TYPE=MyISAM et le script Perl mysql_convert_table_format.

- Toutes les tables qui utilisent le jeu de caractères tis620 doivent être corrigées avec myisamchk -r ou REPAIR TABLE.

- Si vous utilisez le jeu de caractères allemand pour les tris, vous devez réparer vos tables avec isamchk -r, car nous avons fait des modifications dans l'ordre de tri.

Changement au programme client

- Le client MySQL mysql est démarré par défaut avec l'option --no-named-commands (-g). Cette option peut être désactivée avec --enable-named-commands (-G). Cela peut causer des problèmes d'incompatibilité dans certains cas  : par exemple, dans les scripts SQL qui utilisent des commandes nommées sans point-virgule ! Le format long de la commande devrait fonctionner correctement.

- Si vous voulez que les fichiers d'export de mysqldump soient compatibles entre les versions MySQL 3.22 et 3.23, vous ne devez pas utiliser l'option --opt ou --all de mysqldump.

Changements SQL

- Si vous exécutez une commande DROP DATABASE sur un lien symbolique, le lien et la base originale seront effacés. Cela n'arrivait pas en 3.22, car configure ne détectait pas les appels à readlink.

- OPTIMIZE TABLE ne fonctionne que pour les tables MyISAM. Pour les autres types de tables, vous devez utiliser ALTER TABLE pour optimiser la table. Durant la commande OPTIMIZE TABLE, la table est verrouillée.

- Les fonctions de date qui travaillent sur des parties de date (comme MONTH()) vont désormais retourner 0 pour la date 0000-00-00. (MySQL 3.22 retournait NULL.)

- Le type de retour par défaut de IF() dépendant maintenant des deux arguments, et plus seulement du premier.

- AUTO_INCREMENT ne fonctionne pas sur les nombres négatifs. La raison pour cela est que les nombres négatifs posaient des problèmes d'écrasement entre -1 et 0. AUTO_INCREMENT pour les tables MyISAM est maintenant géré à un niveau plus bas, et il est bien plus rapide. Pour les tables MyISAM, les anciens numéros ne sont plus réutilisés, même si vous effacez des lignes dans la table.

- CASE, DELAYED, ELSE, END, FULLTEXT, INNER, RIGHT, THEN et WHEN sont de nouveaux mots réservés.

- FLOAT(p) est maintenant un véritable type de nombre à virgule flottante, avec un nombre défini de décimales.

- Lors de la déclaration de DECIMAL(length,dec), la taille de l'argument n'inclut plus une place pour le signe ou le séparateur décimal.

- Une chaîne TIME doit être fournie au format suivant : [[[DAYS] [H]H:]MM:]SS[.fraction] ou [[[[[H]H]H]H]MM]SS[.fraction].

- LIKE compare maintenant les chaînes en appliquant les mêmes règles que =. Si vous voulez l'ancien comportement, vous pouvez compiler MySQL avec l'option CXXFLAGS=-DLIKE_CMP_TOUPPER.

- REGEXP est maintenant insensible à la casse pour les chaînes normales (non binaires).

- Quand vous vérifiez/réparez des tables, vous devez utiliser CHECK TABLE ou myisamchk pour les tables MyISAM (.MYI) et isamchk pour les tables ISAM (.ISM).

- Vérifiez tous vos appels à DATE_FORMAT() pour vous assurer qu'il y a un signe pourcentage '%' avant chaque caractère de format (MySQL version 3.22 et plus récentes avaient déjà cette syntaxe, mais désormais '%' est obligatoire).

- En MySQL version 3.22, le résultat de SELECT DISTINCT ... était toujours trié. En version 3.23, vous devez spécifier la clause GROUP BY ou ORDER BY pour obtenir un résultat trié.

- SUM() retourne désormais NULL, au lieu de 0, s'il n'y a pas de ligne à calculer. Ceci s'accorde avec la norme SQL.

- AND ou OR avec les valeurs NULL vont désormais retourner NULL au lieu de 0. Cela affecte surtout les requêtes qui utilisaient NOT ou une expression AND/OR telle que NOT NULL = NULL.

- LPAD() et RPAD() vont réduire la taille de la chaîne résultante, si elle est plus grande que l'argument de taille.

Changement de l'interface C

- mysql_fetch_fields_direct est maintenant une fonction (c'était une macro), qui retourne un pointeur sur MYSQL_FIELD au lieu de MYSQL_FIELD.

- mysql_num_fields() ne peut plus être utilisé sur les objets MYSQL* (c'est maintenant une fonction qui prend MYSQL_RES* comme argument. Il faut donc utiliser mysql_field_count() à la place).

2-6-5 - Passer de la version 3.21 à la version 3.22

Rien qui n'affecte la compatibilité n'a changé entre les versions 3.21 et 3.22. Le seul problème courant est que les nouvelles tables qui sont créées avec le type DATE vont désormais utiliser le nouveau format de stockage. Vous ne pourrez pas accéder à ces nouveaux formats depuis les vieilles versions de mysqld.

Lors de la mise à jour en MySQL 3.23 depuis une ancienne version, suivez ces conseils.

- Après avoir installé MySQL version 3.22, vous devriez démarrer le nouveau serveur, et exécuter le script mysql_fix_privilege_tables. Il va ajouter les nouveaux droits à la commande GRANT. Si vous oubliez cela, vous obtiendrez des erreurs Access denied lorsque vous essayez d'utiliser les commandes ALTER TABLE, CREATE INDEX ou DROP INDEX. La procédure pour mettre à jour les tables de droits est décrite dans Section 2.6.7, « Mise à jour des tables de droits ».

- L'interface C de mysql_real_connect() a changé. Si vous avez un vieux client qui appelle cette fonction, vous devez placer un 0 pour le nouvel argument db (ou réécrire le client pour qu'il envoie l'élément db, et accélère les connexions). Vous devez aussi appeler mysql_init() avant d'appeler mysql_real_connect() ! Ce changement a été fait pour permettre l'appel de la fonction mysql_options(), qui sauve les options dans la structure MYSQL.

- La variable key_buffer de mysqld a changé de nom, et est devenue key_buffer_size, mais vous pouvez toujours utiliser l'ancien nom dans vos fichiers de démarrage.

2-6-6 - Passer de la version 3.20 à la version 3.21

Si vous avez une version de MySQL plus ancienne que la version 3.20.28 et que vous voulez passer à la version 3.21, vous devez suivre les étapes décrites ci-après.

Vous pouvez démarrer le serveur mysqld version 3.21 avec le script safe_mysqld --old-protocol pour l'utiliser avec les clients de la version 3.20. Dans ce cas, la fonction mysql_errno() des nouveaux clients ne sera pas fonctionnelle, et seul CR_UNKNOWN_ERROR (mais il fonctionne pour les erreurs client), et le serveur utilisera l'ancienne fonction password() plutôt que la nouvelle.

Si vous n'utilisez pas l'option --old-protocol avec mysqld, vous devez suivre ces instructions :

- tous les clients doivent être recompilés. Si vous utilisez ODBC, vous devez obtenir le nouveau pilote MyODBC 2.x ;

- le script scripts/add_long_password doit être utilisé pour convertir le champ Password de la table mysql.user en CHAR(16) ;

- tous les mots de passe doivent être réassignés dans la table mysql.user pour utiliser les mots de 62 bits au lieu de 31 bits ;

- le format de table n'a pas changé, ce qui vous évite d'avoir à convertir des tables.

MySQL version 3.20.28 et plus récentes peuvent gérer les nouvelles tables user sans affecter les clients. Si vous avez une version plus ancienne que la 3.20.28, les mots de passe ne seront plus valide, si vous convertissez la table user. Pour être tranquille, commencez par faire passer votre version à la 3.20.28 puis passez en version 3.21.

Le nouveau client fonctionne avec le serveur 3.20.x mysqld, alors si vous rencontrez des problèmes avec la version 3.21.x, vous pouvez toujours vous rabattre sur les vieux serveurs 3.20.x sans recompiler les clients.

Si vous n'utilisez pas l'option --old-protocol de mysqld, les vieux clients vont émettre une erreur :

ERROR: Protocol mismatch. Server Version = 10 Client Version = 9

La nouvelle interface Perl DBI/DBD supporte aussi l'ancienne interface mysqlperl. Le seul changement que vous devez faire si vous utilisez mysqlperl est de changer les arguments de la fonction connect(). Les nouveaux arguments sont : host, database, user, et password (les arguments user et password ont été échangés).

Les modifications actuelles affectent les requêtes des anciennes applications :

- HAVING doit être spécifié avant la clause ORDER BY ;

- les paramètres de la fonction LOCATE() ont été échangés ;

- il y a de nouveaux mots réservés. Les plus notables sont DATE, TIME et TIMESTAMP.

2-6-7 - Mise à jour des tables de droits

Certaines versions introduisent des modifications dans la structure des tables de droits (les tables qui sont dans la base mysql), pour ajouter de nouveaux droits ou fonctionnalités. Pour vous assurer que vos tables de droits sont à jour lorsque vous changez de version de MySQL, il est recommandé de les mettre aussi à jour.

Sous Unix ou ses équivalents, la mise à jour des tables de droits se fait en exécutant le script mysql_fix_privilege_tables :

shell> mysql_fix_privilege_tables

Vous devez exécuter ce script lorsque le serveur fonctionne. Le script tente de se connecter au serveur local avec le compte root. Si votre compte root requiert un mot de passe, indiquez-le en ligne de commande. Depuis MySQL 4.1 et plus récents, spécifiez le mot de passe comme ceci :

shell> mysql_fix_privilege_tables --password=root_password

Pour les versions antérieures à la version MySQL 4.1, spécifiez le mot de passe comme ceci :

shell> mysql_fix_privilege_tables root_password

Le script mysql_fix_privilege_tables effectue les manipulations nécessaires pour convertir vos tables de droits au format courant. Vous pouvez apercevoir des alertes Duplicate column name durant l'exécution du script : ces alertes peuvent être ignorées sans danger.

Après avoir exécuté le script, arrêtez le serveur, et relancez-le.

Sous Windows, il n'existe pas de moyen facile de modifier les tables de droits jusqu'à MySQL 4.0.15. Depuis la version 4.0.15, la distribution MySQL inclut un script SQL mysql_fix_privilege_tables.sql que vous pouvez utiliser avec le client mysql. Si votre installation MySQL est située dans le dossier C:\mysql, la commande à utiliser ressemble à celle-ci :

C:\mysql\bin> mysql -u root -p mysql

mysql> SOURCE C:\mysql\scripts\mysql_fix_privilege_tables.sql

Si votre installation est située dans un autre dossier, vous devrez adapter les chemins.

La commande mysql vous demandera le mot de passe pour le compte root : saisissez-le lorsqu'il est demandé.

Comme pour la procédure Unix, vous pouvez voir apparaître des alertes Duplicate column name durant le traitement de votre base mysql par le script mysql_fix_privilege_tables.sql : elles peuvent être ignorées.

Après avoir exécuté le script arrêtez le serveur, et relancez-le.

2-6-8 - Migrer depuis une autre architecture

Si vous utilisez MySQL version 3.23, vous pouvez copier les fichiers .frm, .MYI et .MYD entre les différentes architectures qui supportent le même format de nombre à virgule flottante (MySQL prend en charge les échanges d'octets). Voir Section 14.1, « Le moteur de tables MyISAM ».

Les données MySQL des tables ISAM et les fichiers d'index (.ISD et *.ISM, respectivement) sont dépendantes de l'architecture, et dans certains cas, dépendantes du système d'exploitation. Si vous voulez déplacer des applications vers une autre machine qui a une autre architecture, ou un autre système d'exploitation que votre machine courante, il est recommandé de ne pas faire une simple copie de base en copiant les fichiers vers leur nouvelle destination. Utilisez plutôt mysqldump.

Par défaut, mysqldump va créer un fichier de requêtes SQL. Vous pouvez alors transférer le fichier sur une autre machine, et le fournir comme script à un client mysql.

Essayez la commande mysqldump --help pour voir quelles options sont disponibles. Si vous envoyez les données vers une nouvelle version de MySQL, il est recommandé d'utiliser l'option mysqldump --opt pour obtenir un export compact et plus rapide.

Le plus facile (mais pas le plus rapide) pour déplacer une base de données entre deux machines et d'exécuter les commandes suivantes sur la machine qui héberge la base :

shell> mysqladmin -h 'other hostname' create db_name
shell> mysqldump --opt db_name \
| mysql -h 'other hostname' db_name

Si vous voulez copier la base depuis une machine distante sur un réseau lent, vous pouvez utiliser :

shell> mysqladmin create db_name
shell> mysqldump -h 'other hostname' --opt --compress db_name \
| mysql db_name

Vous pouvez aussi stocker le résultat dans un fichier, et transférer le fichier sur la machine de destination, puis charger ce fichier dans le serveur. Par exemple, vous pouvez exporter la base vers un fichier source comme ceci :

shell> mysqldump --quick db_name | gzip > db_name.contents.gz

Le fichier créé est compressé. Transférez le fichier contenant le contenu de votre base sur la machine de destination, puis utilisez ces commandes :

shell> mysqladmin create db_name
shell> gunzip < db_name.contents.gz | mysql db_name

Vous pouvez aussi utiliser mysqldump et mysqlimport pour accomplir cette opération. Pour les grandes tables, c'est bien plus rapide que d'utiliser simplement mysqldump. Dans les commandes suivantes, DUMPDIR représente le chemin complet du dossier que vous utilisez pour stocker le résultat de mysqldump.

Premièrement, créez un dossier pour les fichiers d'exportation, puis faites l'export :

shell> mkdir DUMPDIR
shell> mysqldump --tab=DUMPDIR db_name

Puis transférez les fichiers du dossier DUMPDIR dans un dossier correspondant, dans la machine de destination, puis chargez ces fichiers dans MySQL comme ceci :

shell> mysqladmin create db_name           # Création de la base
shell> cat DUMPDIR/*.sql | mysql db_name   # Création des tables dans la base
shell> mysqlimport db_name DUMPDIR/*.txt   # Chargement des données dans les tables

N'oubliez pas non plus de copier le contenu de votre base mysql, car c'est là que résident les droits (user, db, host). Vous devrez alors exécuter les commandes en tant que root MySQL sur la nouvelle machine, jusqu'à ce que vous ayez réinstallé mysql.

Après l'importation de la base mysql sur la nouvelle machine, exécutez la commande mysqladmin flush-privileges pour que le serveur relise les droits.

2-7 - Réduire de version de MySQL

Cette section décrit les étapes à suivre pour passer d'une version récente à une version ancienne de MySQL, dans le cas peu probable où vous souhaitez passer à une vieille version qui marchait mieux qu'une version récente.

Si vous changez de version dans une même famille (par exemple, de la version 4.0.20 à 4.0.19) la règle générale est qu'il suffit d'installer les nouveaux exécutables à la place des anciens. Il n'y a pas besoin de toucher aux données. Comme toujours, il est cependant recommandé de faire une sauvegarde.

Les informations suivantes sont à garder comme liste de vérification avant de faire la migration.

- Lisez la section de mise à jour pour les versions que vous allez utiliser, et assurez-vous que vous n'aurez pas besoin de fonctionnalités qui ne seront plus disponibles. Section 2.6, « Changer de version de MySQL ».

- S'il y a une section de réduction de version pour votre installation, lisez-la.

Vous pouvez toujours copier les fichiers de format et de données entre différentes installations de la même famille, sur la même architecture. La version en production actuellement est la version 4.1.

Si vous passez d'une version de production à une autre plus ancienne, il est possible que vous rencontriez des incompatibilités dans les formats de stockage de table. Dans ce cas, utilisez la commande mysqldump pour exporter vos tables avant de faire la migration. Après la mise à jour, importez à nouveau les tables avec la commande mysql ou mysqlimport. Voyez Section 2.6.8, « Migrer depuis une autre architecture » pour des exemples.

Le symptôme normal d'incompatibilité entre deux versions de tables est l'impossibilité d'ouvrir la table. Dans ce cas, utilisez la procédure suivante :

1. Stoppez le vieux serveur MySQL, celui qui est l'objectif de votre migration ;

2. Redémarrez le nouveau serveur, que vous essayez de quitter ;

3. Exportez les tables qui étaient inaccessibles sur le vieux serveur, en utilisant la commande mysqldump pour créer un fichier d'export ;

4. Stoppez le nouveau serveur et relancez l'ancien ;

5. Rechargez les fichiers exportés dans le vieux serveur. Vos tables devraient être disponibles.

2-7-1 - Revenir en version 4.1

Après être passé de MySQL 5.0 en 4.1, vous risquez de trouver les lignes suivantes dans le fichier mysql.err :

Incorrect information in file: './mysql/user.frm'

Dans ce cas, suivez ces instructions :

1. Lancez MySQL 5.0.4 ou plus récent ;

2. Exécutez la commande mysql_fix_privilege_tables, qui va changer la table mysql.user pour qu'elle ait un format que les deux versions 4.1 et 5.0 peuvent utiliser ;

3. Arrêtez le serveur MySQL ;

4. Lancez MySQL 4.1.

Si la procédure précédente échoue, alors il faut suivre ces instructions :

1. Lancez MySQL 5.0.4 ou plus récent ;

2. Exécutez la commande mysqldump --opt --add-drop-table mysql > /tmp/mysql.dump ;

3. Arrêtez le serveur MySQL ;

4. Lancez MySQL 4.1 avec l'option --skip-grant ;

5. Exécutez la commande mysql mysql < /tmp/mysql.dump ;

6. Exécutez la commande mysqladmin flush-privileges.

2-7-2 - Revenir en version 4.0

Le format des tables de la version 4.1 a changé pour accepter les jeux de caractères. À cause de cela, vous devez utiliser la commande mysqldump pour exporter les données qui ont été créées avec des versions plus récentes de MySQL. Par exemple, si toutes les tables d'une base de données doivent être exportées pour être réinsérées, au format MySQL 4.0, utilisez cette commande :

shell> mysqldump --create-options --compatible=mysql40 db_name > dump_file

Puis, arrêtez le nouveau serveur, relancez l'ancien, et importez les données depuis ce fichier :

shell> mysql db_name < dump_file

Dans le cas particulier où vous utilisez des tables MyISAM, aucun traitement spécial n'est nécessaire si toutes les colonnes contiennent des nombres ou des chaînes de caractères (CHAR, VARCHAR, TEXT etc.) qui ne contiennent que des caractères latin1. Dans ce cas, les tables version 4.1 devraient être directement utilisables en version 4.0.

Si vous utilisez le script mysql_fix_privilege_tables pour mettre à jour les tables de droits, vous pouvez utilisez la méthode précédente pour convertir les tables en version 4.0, ou appliquez les commandes suivantes aux tables version 4.1 :

ALTER TABLE mysql.user CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE mysql.db CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE mysql.host CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE mysql.tables_priv CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE mysql.columns_priv CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE mysql.func CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;

2-8 - Notes spécifiques aux systèmes d'exploitation

2-8-1 - Notes relatives à Linux (toutes versions)

Cette section présente les problèmes que nous avons rencontrés avec Linux. Les premières sections décrivent les problèmes liés aux opérations générales, les problèmes qui arrivent avec les distributions binaires ou source, puis les problèmes de postinstallation. Les autres sections discutent de problèmes qui surviennent sur des plates-formes spécifiques.

Notez que la plupart des problèmes surviennent sur les anciennes versions de Linux. Si vous utilisez une version récente, vous ne les verrez jamais ou presque.

2-8-1-1 - Notes sur Linux

MySQL requiert au moins Linux Version 2.0.

Attention : nous avons rencontré d'étranges problèmes avec Linux 2.2.14 et MySQL sur des architectures SMP. Nous avons aussi des rapports d'utilisateurs MySQL qui ont rencontré de sérieux problèmes de stabilité avec le noyau 2.2.14. Si vous utilisez ce noyau, il est recommandé de passer en version 2.2.19 (ou plus récente) ou en 2.4. Si vous avez un serveur multiprocesseur, vous devriez considérer sérieusement la migration vers la version 2.4, car elle vous apportera un gain de vitesse significatif. Votre système sera aussi plus stable.

Lorsque vous utilisez les LinuxThreads, vous verrez un minimum de trois processus mysqld. Ce sont en fait des threads. Il y a un thread de gestion LinuxThreads, un thread pour gérer les connexions et un thread pour gérer les alertes et signaux.

2-8-1-2 - Notes relatives à Linux pour les distributions binaires

MySQL requiert au moins la version 2.0 de Linux.

Attention : certains utilisateurs de MySQL nous ont avertis qu'ils ont rencontré de graves problèmes de stabilité avec MySQL et le noyau 2.2.14 de Linux. Si vous utilisez ce noyau, vous devez mettre à jour à la 2.2.19 (ou plus récente) ou a un noyau 2.4. Si vous utilisez un ordinateur multiprocesseur, vous devriez sérieusement songer à passer au noyau 2.4 qui vous apportera de grandes performances niveau vitesse.

La version binaire est liée avec -static, ce qui signifie que normalement vous n'avez pas besoin de vous soucier des versions des bibliothèques système que vous avez. Vous n'avez pas besoin d'installer LinuxThreads non plus. Un programme lié avec -static est légèrement plus grand qu'un programme lié dynamiquement, mais aussi un peu plus rapide (3-5 %). Un problème, toutefois, est que vous ne pouvez utiliser de fonctions définies par l'utilisateur avec un programme lié statiquement. Si vous allez écrire ou utiliser des fonctions UDF (c'est réservé aux développeurs C ou C++), vous devez compiler MySQL vous-même, en utilisant les liaisons dynamiques.

Si vous utilisez un système basé sur libc (au lieu de glibc2), vous aurez probablement quelques problèmes de résolution des noms d'hôtes et des problèmes avec getpwnam() avec les versions binaires. (Cela vient du fait que glibc dépend malheureusement de quelques bibliothèques externes pour résoudre les noms d'hôtes et getpwent(), même quand elle est compilée avec -static). Dans ce cas, vous obtiendrez probablement l'erreur suivante quand vous exécuterez mysql_install_db :

Sorry, the host 'xxxx' could not be looked up

ou l'erreur suivante quand vous essayez de démarrer mysqld avec l'option --user :

getpwnam: No such file or directory

Vous pouvez résoudre ce problème de la façon suivante :

- Obtenez une distribution des sources MySQL (un distribution RPM ou le tar.gz) et installez-la à la place.

- Exécutez mysql_install_db --force; cela n'exécutera pas le test resolveip dans mysql_install_db. Le mauvais côté est que vous ne pourrez pas utiliser de noms d'hôtes dans les tables de droits, vous devez utiliser les adresses IP à la place (sauf pour localhost). Si vous utilisez une vielle version de MySQL qui ne supporte pas --force, vous devez supprimer le test resolveip dans mysql_install à l'aide d'un éditeur.

- Démarrez mysqld avec su au lieu d'utiliser --user.

Le binaire Linux-Intel et les RPM de MySQL sont configurés pour la vitesse la plus grande possible. Nous essayons toujours d'utiliser le compilateur le plus rapide disponible.

Le support Perl de MySQL requiert la version 5.004_03 de Perl ou plus récente.

Sur quelques versions de Linux 2.2, vous pouvez obtenir l'erreur Resource temporarily unavailable quand vous faites beaucoup de nouvelles connexions à un serveur mysqld en utilisant TCP/IP.

Le problème est que Linux possède un délai entre votre fermeture du socket TCP/IP et sa libération par le système. Vu qu'il y a un nombre fini de places pour les branchements TCP/IP, vous obtiendrez l'erreur précédente si vous essayez de faire beaucoup de connexions TCP/IP en peu de temps, comme quand vous exécutez le benchmark MySQL test-connect via TCP/IP.

Nous avons envoyé des questions plusieurs fois à propos de ce problème à différentes listes de diffusions Linux, mais n'avons jamais réussi à résoudre ce problème proprement.

Le seul correctif connu pour ce problème est d'utiliser des connexions persistantes dans vos clients ou d'utiliser les sockets, si vous utilisez le serveur de bases de données et le client sur la même machine. Nous espérons que le noyau de Linux 2.4 corrigera ce problème bientôt.

2-8-1-3 - Notes sur la distribution source de Linux

Les notes suivantes concernant glibc ne s'appliquent que si vous compilez vous-même MySQL. Si vous utilisez Linux sur une machine x86, dans la plupart des cas, il est mieux d'utiliser notre bibliothèque. Nous compilons nos exécutables avec les meilleures versions corrigées de glibc que nous pouvons trouver, avec les meilleures options de compilation possible, pour faire que notre serveur supporte les hautes charges. Pour un utilisateur typique, même pour une configuration avec de nombreuses connexions ou des tables dépassant les 2 Go, notre programme est meilleur choix. Après avoir lu ce texte, si vous doutez toujours, testez notre compilation pour voir si elle répond à vos besoins. Si vous pensez qu'elle n'est pas à la hauteur, alors essayez de compiler par vous-même. Dans ce cas, nous apprécierons de savoir ce que vous avez fait, pour pouvoir améliorer notre propre version.

MySQL utilise les LinuxThreads sur Linux. Si vous utilisez une vieille version de Linux qui n'a pas glibc2, vous devrez installer LinuxThreads avant de compiler MySQL. Vous pouvez obtenir LinuxThreads sur http://dev.mysql.com/downloads/os-linux.html.

Notez que les versions de glibc avant et incluant la version 2.1.1 ont un bogue critique dans la gestion de pthread_mutex_timedwait(), qui est utilisée lorsque vous envoyez des commandes INSERT DELAYED. Nous vous recommandons de ne pas utiliser INSERT DELAYED avant de mettre à jour glibc.

Notez que le noyau Linux et la bibliothèque LinuxThreads sont limités par défaut à 1024. Si vous envisagez d'avoir plus de 1000 connexions simultanées, vous aurez besoin de faire des changements dans LinuxThreads :

- Augmentez PTHREAD_THREADS_MAX dans sysdeps/unix/sysv/linux/bits/local_lim.h à 4096 et réduisez STACK_SIZE dans linuxthreads/internals.h à 256 ko. Les chemins sont relatifs à la racine de glibc. (Notez que MysQL ne sera pas stable autour de 600 à 1000 connexions si STACK_SIZE vaut les 2 Mo par défaut.

- Recompilez LinuxThreads pour avoir un nouveau libpthread.a, et recompilez MySQL avec.

La page http://www.volano.com/linuxnotes.html contient des informations supplémentaires pour contourner cette limite de LinuxThreads.

Il y a un autre problème qui limite considérablement les performances de MySQL, notamment sur des systèmes multiprocesseurs. L'implémentation mutex de LinuxThreads dans glibc 2.1 est très mauvaise pour les programmes ayant de nombreux threads qui gardent le mutex pour une courte période de temps. Cela produit un résultat paradoxal : si vous compilez MySQL avec une version originale de LinuxThreads, supprimer des processeurs de votre architecture va améliorer les performances. Nous avons fait un correctif de glibc 2.1.3 pour corriger ce comportement (http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch).

Avec glibc 2.2.2, MySQL 3.23.36 va utiliser un mutex adaptatif, qui est bien meilleur que la version corrigée de glibc 2.1.3. Soyez prévenu, que dans certaines conditions, le code courant du mutex de glibc 2.2.2 surchauffe, ce qui bride MySQL. La probabilité de rencontrer cette condition sera réduite en donnant à mysqld la plus haute priorité. Nous avons été capables de corriger le problème avec un correctif, disponible à http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch. Il combine la correction avec l'augmentation du nombre limite de threads et de la taille de pile. Vous devez l'appliquer dans le dossier linuxthreads avec patch -p0 </tmp/linuxthreads-2.2.2.patch. Nous espérons qu'il sera inclus dans une version future de glibc 2.2. Dans tous les cas, si vous compilez avec glibc 2.2.2, vous devrez corriger STACK_SIZE et PTHREAD_THREADS_MAX. Nous espérons que les valeurs par défaut seront corrigées et remplacées par des valeurs plus raisonnables pour les configurations à haut rendement de MySQL : les manipulations futures pour compiler MySQL seront alors réduites à ./configure; make; make install.

Nous recommandons que vous utilisiez ces correctifs pour compiler une version spéciale statique de libpthread.a et que vous l'utilisiez pour compiler MySQL. Nous savons que les correctifs sont sécuritaires pour MySQL, et améliorent significativement les performances, mais nous ne pouvons pas nous avancer pour les autres applications. Si vous compilez d'autres applications qui requièrent les LinuxThreads avec la version statique corrigée de la bibliothèque, faites-le à vos risques et périls.

Si vous rencontrez des problèmes étranges durant l'installation de MySQL, ou si vous voyez les utilitaires se geler, il est très probable que vous ayez un problème de compilateur ou de bibliothèque. Dans ce cas, utiliser notre binaire résoudra vos problèmes.

Si vous compilez vos propres clients MySQL, vous pouvez rencontrer l'erreur suivante durant l'exécution :

ld.so.1: fatal: libmysqlclient.so.#:
open failed: No such file or directory

Ce problème peut être évité avec les méthodes suivantes :

- compilez le client avec l'option -Wl,r/full/path/to/libmysqlclient.so plutôt que -Lpath) ;

- copiez libmysqclient.so dans /usr/lib ;

- Ajoutez le chemin du dossier où libmysqlclient.so est situé dans la variable d'environnement LD_RUN_PATH avant de lancer votre client.

Si vous utilisez le compilateur Fujitsu (fcc/FCC), vous aurez des problèmes pour compiler MySQL car le fichier d'entête Linux est très orienté gcc. La ligne de configuration configure devrait fonctionner avec fcc/FCC :

CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \
-DCONST=const -DNO_STRTOLL_PROTO" \
CXX=FCC CXXFLAGS="-O -K fast -K lib \
-K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE \
-DCONST=const -Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \
'-D_EXTERN_INLINE=static __inline'" \
./configure \
--prefix=/usr/local/mysql --enable-assembler \
--with-mysqld-ldflags=-all-static --disable-shared \
--with-low-memory

2-8-1-4 - Notes de postinstallation pour Linux

mysql.server est stocké dans le dossier support-files dans le dossier d'installation MySQL, ou dans le dossier des sources. Vous pouvez l'installer dans /etc/init.d/mysql pour assurer le démarrage et l'extinction automatique de MySQL. Voir Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ».

Si MySQL n'arrive pas à ouvrir assez de fichiers, ou à créer assez de connexions, il se peut que vous n'ayez pas configuré Linux pour qu'il gère assez de fichiers.

Dans Linux 2.2 ou plus, vous pouvez connaître le nombre de gestionnaires de fichiers alloués en faisant :

shell> cat /proc/sys/fs/file-max
shell> cat /proc/sys/fs/dquot-max
shell> cat /proc/sys/fs/super-max

Si vous avez plus de 16 Mo de mémoire, vous devez ajouter quelque chose comme ce qui suit dans vos scripts d'initialisation (/etc/init.d/boot.local sur SuSE Linux) :

echo 65536 > /proc/sys/fs/file-max
echo 8192 > /proc/sys/fs/dquot-max
echo 1024 > /proc/sys/fs/super-max

Vous pouvez aussi exécuter les commandes précédentes à partir de la ligne de commande en tant que root, mais les changements seront perdus au prochain redémarrage de l'ordinateur.

Vous pouvez sinon définir ces paramètres lors du démarrage de la machine en utilisant l'outil sysctl, qui est utilisé par plusieurs distributions Linux (SuSE l'a aussi ajouté, à partir de SuSE Linux 8.0). Ajoutez simplement les valeurs suivantes dans un fichier nommé /etc/sysctl.conf :

# Increase some values for MySQL
fs.file-max = 65536
fs.dquot-max = 8192
fs.super-max = 1024

Il est recommandé d'ajouter aussi la ligne suivante dans le fichier /etc/my.cnf :

[mysqld_safe]
open-files-limit=8192

Cela va autoriser le serveur à un maximum de 8192 connexions et fichiers ouverts simultanément.

La constante STACK_SIZE des LinuxThreads contrôle l'espacement des piles de threads dans l'espace d'adressage. Elle doit être assez grande pour qu'il y ait plusieurs chambres pour la pile de chaque thread individuel, mais assez petite pour empêcher les piles de certains threads d'agir sur les données globales de mysqld. Malheureusement, l'implémentation Linux de mmap(), comme nous l'avons découvert, va libérer une région réservée, si vous lui demandez de libérer une adresse déjà utilisée, détruisant les données de la page, au lieu de retourner une erreur. Donc, la sécurité de mysqld et des autres applications qui dépendent d'un comportement civil du code qui gère les threads. L'utilisateur doit s'assurer que le nombre de threads fonctionnant simultanément est suffisamment bas pour éviter d'entrer dans la pile globale. Avec mysqld, vous devez suivre cette règle de bon fonctionnement en donnant une valeur raisonnable à max_connections.

Si vous compilez MySQL vous-même, vous pouvez corriger LinuxThreads pour améliorer l'utilisation de la pile. Voir Section 2.8.1.3, « Notes sur la distribution source de Linux ». Si vous ne voulez pas corriger LinuxThreads, vous ne devez pas dépasser 500 pour la valeur de max_connections. Cela devrait même être moins si vous avez un tampon de clefs assez large, de grosses tables heap, ou d'autres choses qui peuvent faire allouer beaucoup de mémoire à mysqld, ou si vous utilisez un noyau 2.2 avec un patch 2G. Si vous utilisez notre binaire ou RPM 3.23.25 ou plus, vous pouvez mettre max_connections à 1500 sans problème, en supposant que vous n'avez ni de grosses tables heap ni grands tampons de clefs. Plus vous réduirez STACK_SIZE dans LinuxThreads plus les threads créés seront sûrs. Nous recommandons une valeur entre 128 ko et 256 ko.

Si vous utilisez beaucoup de connexions simultanées, vous pouvez souffrir d'une « fonctionnalité » du noyau 2.2, qui tente d'éviter les DOS par fork en pénalisant les processus qui forkent ou qui clonent des fils. Cela fait que MySQL ne se comporte pas bien si vous augmentez le nombre de clients simultanés. Sur les systèmes monoprocesseurs, nous avons vu des symptômes sous la forme de ralentissement : il prenait un très long temps pour se connecter (parfois une minute), et il fallait autant de temps pour terminer le processus. Sur les systèmes multiprocesseurs, nous avons observé une décroissance graduelle des performances des requêtes chez de nombreux clients. Durant nos recherches pour corriger le problème, nous avons reçu un patch d'un client qui prétendait avoir résolu le problème pour son site. Ce patch est disponible sur http://www.mysql.com/Downloads/Patches/linux-fork.patch. Nous avons maintenant fait des tests exhaustifs de ce patch en développement et en production. Il a amélioré significativement les performances sans causer de problèmes, et nous l'avons recommandé à nos utilisateurs qui fonctionnent avec des serveurs chargés et un noyau 2.2.

Ce problème a été réglé avec le noyau 2.4 : si vous n'êtes pas satisfait avec les performances courantes de votre système, au lieu de le corriger, passez donc votre noyau 2.2 en 2.4. Sur les systèmes multiprocesseurs, la mise à jour vous donnera d'ailleurs un regain de puissance, en plus de corriger le bogue.

Nous avons testé MySQL sur des noyaux 2.4 et sur des machines biprocesseurs, et nous avons trouvé que MySQL se comporte beaucoup mieux. Il n'y avait pratiquement pas de ralentissement de requêtes même avec 1000 client, et gain de puissance était de 180 % (calculé avec le ratio de vitesse maximale divisé par la vitesse moyenne d'un client). Nous avons observé des résultats similaires sur une machine quadriprocesseurs : virtuellement aucun ralentissement alors que le nombre de clients est monté jusqu'à 1000, et le gain de puissance a atteint 300 %. En se basant sur ces résultats, pour un serveur hautes performances multiprocesseur, nous vous recommandons de passer en noyau 2.4.

Nous avons découvert qu'il est essentiel de faire fonctionner les processus mysqld avec la priorité maximale sur le noyau 2.4 pour atteindre les meilleures performances. Cela peut se faire en ajoutant la commande renice -20 $$ dans mysqld_safe. Durant nos tests sur une machine quadriprocesseurs, augmenter la priorité a engendré 60 % d'amélioration avec 400 clients.

Nous essayons aussi de rassembler plus d'informations sur comment MySQL se comporte sur un système 2.4 quadri- ou octoprocesseurs. Si vous avez accès à de telles données, envoyez-nous un email à <benchmarks@mysql.com> avec les résultats. Nous allons les étudier pour les inclure dans le manuel.

Si vous voyez un processus mysqld mort avec ps, c'est que vous avez découvert un bogue dans MySQL ou qu'une des tables est corrompue. Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

Pour obtenir un core dump sur Linux si mysqld se termine avec un signal SIGSEGV, vous pouvez lancer mysqld avec l'option --core-file. Notez que vous aurez probablement à augmenter la taille du fichier core en ajoutant la commande ulimit -c 1000000 à mysqld_safe ou en lançant mysqld_safe avec --core-file-size=1000000. Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ».

2-8-1-5 - Notes relatives à Linux x86

MySQL requiert la version 5.4.12 de libc ou plus récente. Il est connu pour fonctionner avec libc 5.4.46. La version 2.0.6 de glibc ou plus récente devrait aussi fonctionner. Il y a eu quelques problèmes avec les RPM de glibc de Red Hat, et donc, si vous avez des problèmes, vérifiez s'il existe des mises à jour ! Les RPM de glibc 2.0.7-19 et 2.0.7-29 sont connus pour fonctionner.

Si vous utilisez gcc 3.0 ou plus récent pour compiler MySQL, vous devez installer la bibliothèque libstdc++v3 avant de compiler MySQL, si vous ne le faites pas vous obtiendrez une erreur à propos d'un symbole __cxa_pure_virtual manquant durant la liaison ! Pour corriger ce problème, lancez mysqld avec l'option --thread-stack=192K. Utilisez la syntaxe -O thread_stack=192K avant MySQL 4.) La taille de la pile est maintenant par défaut pour les versions MySQL 4.0.10 et plus récentes, alors vous ne devriez pas rencontrer de problème.

Si vous utilisez gcc 3.0 et plus récent pour compiler MySQL, vous devez installer la bibliothèque libstdc++v3 avant de compiler MySQL, si vous ne le faites pas, vous aurez des erreurs à propos de __cxa_pure_virtual qui manque, durant la résolution des symboles.

Sur quelques vieilles distributions de Linux, configure peut produire une erreur comme celle qui suit :

Syntax error in sched.h. Change _P to __P in the
/usr/include/sched.h file.
See the Installation chapter in the Reference Manual.

Faites ce que le message d'erreur dit et ajoutez un _ à la macro _P qui n'en a qu'un, puis essayez à nouveau.

Vous pouvez obtenir quelques avertissements en compilant ; ceux qui suivent peuvent être ignorés :

mysqld.cc -o objs-thread/mysqld.o
mysqld.cc: In function 'void init_signals()':
mysqld.cc:315: warning: assignment of negative value '-1' to
'long unsigned int'
mysqld.cc: In function 'void * signal_hand(void *)':
mysqld.cc:346: warning: assignment of negative value '-1' to
'long unsigned int'

Si mysqld provoque toujours un plantage au démarrage, le problème peut être que vous avez un vieux /lib/libc.a. Renommez-le, puis supprimez sql/mysqld et faites à nouveau un make install puis réessayez. Ce problème a été reporté sur quelques installations de Slackware.

Si vous obtenez l'erreur suivante en liant mysqld, cela signifie que votre libg++.a n'est pas installé correctement :

/usr/lib/libc.a(putc.o): In function '_IO_putc':
putc.o(.text+0x0): multiple definition of '_IO_putc'

Vous pouvez éviter d'utiliser libg++.a en exécutant configure comme suit :

shell> CXX=gcc ./configure

Si mysqld se plante immédiatement, et que vous utilisez Red Hat Version 5.0, avec une version de glibc plus ancienne que 2.0.7-5, il est recommandé d'installer les patchs glibc. Il y a beaucoup d'informations à ce sujet dans les archives courriel, disponibles sur http://lists.mysql.com/.

2-8-1-6 - Notes relatives à Linux SPARC

Sur quelques implémentations, readdir_r() est cassé. Le symptôme est que SHOW DATABASES retourne toujours un résultat vide. Cela peut être corrigé en supprimant HAVE_READDIR_R de config.h après avoir configuré et avant de commencer à compiler.

2-8-1-7 - Notes relatives à Linux Alpha

La version 3.23.12 de MySQL est la première version de MySQL à être testée sur Linux-Alpha. Si vous voulez utiliser MySQL sur Linux-Alpha, vous devez vous assurer d'avoir cette version ou une version plus récente.

Nous avons testé MySQL sur Alpha avec nos tests de performance et notre suite de tests : tout semble fonctionner correctement.

Nous construisons actuellement les paquets binaires de MySQL sur SuSE Linux 7.0 pour AXP, kernel 2.4.4-SMP, Compaq C compiler (V6.2-505) et Compaq C++ compiler (V6.3-006) sur une machine Compaq DS20 avec un processeur Alpha EV6.

Vous pouvez trouver les précédents compilateurs sur http://www.support.compaq.com/alpha-tools/). En utilisant ces compilateurs, au lieu de gcc, nous obtenons environ 9 à 14 % d'amélioration des performances avec MySQL.

Notez que jusqu'aux versions 3.23.52 et 4.0.2 de MySQL nous avons optimisé l'application pour le processeur courant seulement (en utilisant l'option de compilation -fast); cela signifiait que vous ne pouviez utiliser nos binaires si vous n'aviez pas un processeur Alpha EV6.

Avec les versions suivantes nous avons ajouté l'option -arch generic à nos options de compilation, ce qui assure que le binaire fonctionne sur tous les processeurs Alpha. Nous compilons aussi statiquement pour éviter les problèmes de bibliothèques.

CC=ccc CFLAGS="-fast -arch generic" CXX=cxx \
CXXFLAGS="-fast -arch generic -noexceptions -nortti" \
./configure --prefix=/usr/local/mysql --disable-shared \
--with-extra-charsets=complex --enable-thread-safe-client \
--with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared

Si vous voulez utiliser egcs la ligne de configuration suivante a fonctionné pour nous :

CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--disable-shared

Quelques problèmes connus lors de l'utilisation de MySQL sur Linux-Alpha :

- le débogage d'applications threadées comme MySQL ne fonctionnera pas avec gdb 4.18. Vous devez télécharger et utiliser gdb 5.1 à la place !

- si vous essayez de lier statiquement mysqld en utilisant gcc, l'image résultante videra son noyau (core dump) au démarrage. En d'autres termes, n'utilisez pas --with-mysqld-ldflags=-all-static avec gcc.

2-8-1-8 - Note relative à Linux PowerPC

MySQL devrait fonctionner sur MkLinux avec le dernier paquet glibc (testé avec glibc 2.0.7).

2-8-1-9 - Notes relatives à Linux MIPS

Pour faire fonctionner MySQL sur Qube2, (Linux Mips), vous aurez besoin de la bibliothèque glibc la plus récente (glibc-2.0.7-29C2 est connue pour marcher). Vous devez aussi utiliser le compilateur egcs C++ (egcs-1.0.2-9, gcc 2.95.2 ou plus récent).

2-8-1-10 - Notes relatives à Linux IA64

Pour pouvoir compiler MySQL sous Linux IA64, nous utilisons les lignes de compilation suivantes. En utilisant gcc-2.96 :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
"--with-comment=Official MySQL binary" --with-extra-charsets=complex

Sur IA64 les binaires des clients MySQL utilisent des bibliothèques partagées. Cela signifie que si vous installez notre distribution binaire à un autre endroit que /usr/local/mysql vous devez modifier le fichier /etc/ld.so.conf ou ajouter le chemin vers le répertoire où vous avez libmysqlclient.so à la variable d'environnement LD_LIBRARY_PATH.

Voir Section A.3.1, « Problèmes lors de la liaison avec la bibliothèque du client MySQL ».

2-8-2 - Notes relatives à Mac OS X

Sous Mac OS X, tar ne sait pas gérer les noms de fichiers longs. Si vous avez besoin de décompresser la distribution .tar.gz, utilisez gnutar.

2-8-2-1 - Mac OS X 10.x

MySQL devrait fonctionner sans problème avec les versions Mac OS X 10.x (Darwin). Vous n'avez pas besoin du patch pour les pthreads sur cet OS !

Cela s'applique aussi à Mac OS X 10.x Server. La compilation pour la plate-forme serveur est identique à la compilation pour la version client de Mac OS X. Toutefois, notez que MySQL est préinstallé sur la version Server !

Notre exécutable Mac OS X est compilé sous Darwin 6.3 avec les options de configure suivantes :

CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \
CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile --disable-shared

Voir Section 2.2.13, « Installer MySQL sur Mac OS X ».

2-8-2-2 - Mac OS X Server 1.2 (Rhapsody)

Avant d'essayer de configurer MySQL sur Mac OS X Server, vous devez d'abord installer le paquet pthread. Ce n'est plus nécessaire avec les versions récentes du serveur.

Voir Section 2.2.13, « Installer MySQL sur Mac OS X ».

2-8-3 - Notes pour Solaris

Sous Solaris, vous pouvez rencontrer des problèmes avant même d'avoir désarchivé la distribution MySQL ! Le programme tar de Solaris ne peut pas manipuler de noms de fichiers longs, provoquant les messages suivants quand vous décompressez MySQL :

x mysql-3.22.12-beta/bench/Results/ATIS-mysql_odbc-NT_4.0-cmp-db2,\
informix,ms-sql,mysql,oracle,solid,sybase, 0 bytes, 0 tape blocks
tar: directory checksum error

Dans ce cas, vous devez utiliser GNU tar (gtar) pour désarchiver la distribution. Vous pouvez en trouver une copie précompilée pour Solaris sur http://www.mysql.com/Downloads/.

La gestion native des threads Sun fonctionne uniquement depuis Solaris 2.5. Pour les versions 2.4 et antérieures, MySQL utilisera automatiquement les MIT-pthreads. Voir Section 2.4.5, « Notes relatives aux MIT-pthreads ».

Vous pouvez rencontrer les erreurs suivantes lors du configure :

checking for restartable system calls... configure: error can not run test
programs while cross compiling

Cela signifie que l'installation de votre compilateur est défectueuse ! Dans ce cas, vous devez mettre à jour votre compilateur en faveur d'une version plus récente. Vous pouvez aussi résoudre le problème en intégrant la ligne suivante dans le fichier config.cache :

ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}

Si vous utilisez Solaris sur une architecture SPARC, nous recommandons gcc 2.95.2 comme compilateur. Vous pouvez le trouver sur http://gcc.gnu.org/. Notez que egcs 1.1.1 et gcc 2.8.1 ne fonctionnent pas correctement sur SPARC !

La ligne configure recommandée dans le cas de l'utilisation de gcc 2.95.2 est :

CC=gcc CFLAGS="-O3" \
CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --with-low-memory --enable-assembler

Si vous avez une machine UltraSPARC, vous pouvez gagner 4 % de performance supplémentaire en ajoutant "-mcpu=v8 -Wa,-xarch=v8plusa" à CFLAGS et CXXFLAGS.

Si vous utilisez le compilateur Forte 5.0 (et supérieur) de Sun, vous pouvez lancer configure de la façon suivante :

CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt" \
CXX=CC CXXFLAGS="-noex -mt" \
./configure --prefix=/usr/local/mysql --enable-assembler

Vous pouvez créer un binaire 64 bits avec :

CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt -xarch=v9" \
CXX=CC CXXFLAGS="-noex -mt -xarch=v9" \
./configure --prefix=/usr/local/mysql --enable-assembler

Lors de bancs de tests MySQL, nous avons gagné 4 % en vitesse sur une UltraSPARC en utilisant Forte 5.0 en mode 32 bits plutôt que gcc 3.2 avec les marqueurs -mcpu.

Si vous créez un binaire 64 bits, il est de 4 % plus lent que le binaire 32 bits, mais en contrepartie vous pouvez gérer davantage de treads et de mémoire.

Si vous rencontrez des problèmes avec fdatasync ou sched_yield, vous pouvez les résoudre en ajoutant LIBS=-lrt à la ligne configure.

Le paragraphe suivant ne s'applique qu'aux compilateurs plus anciens que WorkShop 5.3 :

vous pouvez avoir à modifier le script configure et changer la ligne :

#if !defined(__STDC__) || __STDC__ != 1

en :

#if !defined(__STDC__)

Si vous activez __STDC__ avec l'option -Xc, le compilateur Sun ne peut pas compiler avec le fichier d'entêtes pthread.h de Solaris. C'est un bogue de Sun (compilateur ou fichier d'inclusion défectueux).

Si mysqld génère les messages d'erreur suivants lorsque vous le lancez, cela est dû au fait que vous avez compilé MySQL avec le compilateur de Sun sans activer l'option multithreads (-mt) :

libc internal error: _rmutex_unlock: rmutex not held

Ajoutez -mt à CFLAGS et CXXFLAGS puis réessayez.

Si vous utilisez la version SFW de gcc (fournie avec Solaris 8), vous devez ajouter /opt/sfw/lib à la variable d'environnement LD_LIBRARY_PATH avant de lancer le configure.

Si vous utilisez le gcc disponible sur sunfreeware.com, vous pouvez rencontrer de nombreux problèmes. Vous devriez recompiler gcc et les GNU binutils sur la machine à partir de laquelle vous les utiliserez, afin d'éviter tout souci.

Si vous obtenez l'erreur suivante lorsque vous compilez MySQL avec gcc, cela signifie que votre gcc n'est pas configuré pour votre version de Solaris :

shell> gcc -O3 -g -O2 -DDBUG_OFF  -o thr_alarm ...
./thr_alarm.c: In function 'signal_hand':
./thr_alarm.c:556: too many arguments to function 'sigwait'

La meilleure chose à faire dans ce cas est d'obtenir la version la plus récente de gcc et de compiler avec votre gcc actuel ! Au moins pour Solaris 2.5, la plupart des versions binaires de gcc ont d'anciens fichiers d'inclusion inutilisables qui planteront les programmes qui utilisent les threads (ainsi probablement d'autres programmes) !

Solaris ne fournit pas de versions statiques de toutes les bibliothèques système (libpthreads et libdl), vous ne pouvez donc pas compiler MySQL avec --static. Si vous tentez de le faire, vous obtiendrez l'erreur :

ld: fatal: library -ldl: not found
undefined reference to 'dlopen'
cannot find -lrt

Si de nombreux processus essaient de se connecter très rapidement à mysqld, vous verrez cette erreur dans le journal MySQL :

Error in accept: Protocol error

Pour éviter cela, vous pouvez lancer le serveur avec l'option --set-variable back_log=50. Veuillez noter que --set-variable est déprécié depuis MySQL 4.0, utilisez uniquement --back_log=50.

Si vous liez votre propre client MySQL, vous pouvez avoir l'erreur suivante quand vous le lancez :

ld.so.1: ./my: fatal: libmysqlclient.so.#:
open failed: No such file or directory

Le problème peut être évité avec l'une des méthodes suivantes :

- liez le client avec le marqueur suivant (à la place de -Lpath) : -Wl,r/full-path-to-libmysqlclient.so ;

- copiez libmysqclient.so dans /usr/lib ;

- ajoutez le chemin du répertoire où libmysqlclient.so est installé à la variable d'environnement LD_RUN_PATH avant de lancer votre client.

Si vous avez des soucis avec configure qui essaie de lier avec -lz et que vous n'avez pas installé zlib, vous avez deux solutions :

- si vous voulez utiliser le protocole compressé de communication, vous devrez vous procurer et installer zlib sur ftp.gnu.org ;

- configurez avec --with-named-z-libs=no.

Si vous utilisez gcc et rencontrez des problèmes en chargeant la fonction UDF dans MySQL, essayez d'ajouter -lgcc à la ligne de liaison de la fonction UDF.

Si vous voulez que MySQL se lance automatiquement, vous pouvez copier support-files/mysql.server dans /etc/init.d et créer un lien symbolique pointant dessus et s'appelant /etc/rc3.d/S99mysql.server.

Comme Solaris ne supporte pas les fichiers core pour les applications setuid(), vous ne pouvez pas obtenir un fichier core de mysqld si vous utilisez l'option --user.

2-8-3-1 - Notes relatives à Solaris 2.7/2.8

Vous pouvez normalement utiliser les binaires Solaris 2.6 sur Solaris 2.7 et 2.8. La plupart des fonctionnalités de Solaris 2.6 s'appliquent aussi à Solaris 2.7 et 2.8.

Notez que la version 3.23.4 de MySQL et plus doivent être capables de détecter automatiquement les nouvelles versions de Solaris et d'activer les parades pour résoudre les problèmes suivants !

Solaris 2.7 / 2.8 ont quelques bogues dans les fichiers inclus. Vous verrez peut-être l'erreur suivante en utilisant gcc :

/usr/include/widec.h:42: warning: 'getwc' redefined
/usr/include/wchar.h:326: warning: this is the location of the previous definition

Si cela arrive, vous pouvez faire ce qui suit pour résoudre ce problème :

copiez /usr/include/widec.h vers .../lib/gcc-lib/os/gcc-version/include et changez la ligne 41 de :

#if     !defined(lint) && !defined(__lint)

en :

#if     !defined(lint) && !defined(__lint) && !defined(getwc)

Alternativement, vous pouvez éditer directement le fichier /usr/include/widec.h. De toute façon, après avoir apporté la correction, vous devez effacer config.cache et exécuter configure à nouveau !

Si vous obtenez des erreurs comme celles qui suivent quand vous exécutez make, c'est parce que configure n'a pas détecté le fichier curses.h (probablement à cause de l'erreur dans /usr/include/widec.h) :

In file included from mysql.cc:50:
/usr/include/term.h:1060: syntax error before ','
/usr/include/term.h:1081: syntax error before ';'

La solution est de faire l'une des choses qui suivent :

- configurez avec CFLAGS=-DHAVE_CURSES_H CXXFLAGS=-DHAVE_CURSES_H ./configure ;

- éditez /usr/include/widec.h comme indiqué plus haut et réexécutez configure ;

- effacez la ligne #define HAVE_TERM du fichier config.h et exécutez make à nouveau.

Si vous obtenez une erreur disant que votre programme de liaison ne peut trouver -lz lors de la liaison du programme de votre client, le problème est probablement que votre fichier libz.so est installé dans /usr/local/lib. Vous pouvez corriger ceci en utilisant l'une des méthodes suivantes :

- ajoutez /usr/local/lib à LD_LIBRARY_PATH ;

- ajoutez un lien vers libz.so à partir de /lib ;

- si vous utilisez Solaris 8, vous pouvez installer la zlib optionnelle à partir de votre CD Solaris 8 ;

- configurez MySQL avec l'option --with-named-z-libs=no.

2-8-3-2 - Remarques pour Solaris x86

Sous Solaris 2.8 sur x86, mysqld va crasher (core dump) si vous l'exécutez 'strip'.

Si vous utilisez gcc ou egcs sous Solaris x86 et que vous rencontrez des problèmes avec des coredumps, lorsqu'il y a de la charge, il est recommandé d'utiliser la commande de configure suivante :

CC=gcc CFLAGS="-O3 -fomit-frame-pointer -DHAVE_CURSES_H" \
CXX=gcc \
CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors -fno-exceptions \
-fno-rtti -DHAVE_CURSES_H" \
./configure --prefix=/usr/local/mysql

Cela va éviter les problèmes avec la bibliothèque libstdc++ et avec les exceptions C++.

Si cela ne vous aide pas, il est recommandé de compiler une version de débogage, et de l'exécuter avec un fichier de trace sous gdb. Voir Section D.1.3, « Déboguer mysqld sous gdb ».

2-8-4 - Notes relatives à BSD

Cette section fournit des informations pour les différentes variétés de BSD, ainsi que les versions spécifiques de celles-ci.

2-8-4-1 - Notes relatives à FreeBSD

FreeBSD 4.x est recommandé pour exécuter MySQL vu que le paquet des threads est plus intégré.

La façon la plus facile et la plus conseillée d'installer est d'utiliser les ports du serveur et du client MySQL disponibles sur http://www.freebsd.org/.

Les utiliser vous donnera :

- un MySQL fonctionnant avec toutes les optimisations connues pour votre version active de FreeBSD ;

- configuration et construction automatique ;

- scripts de démarrage installés dans /usr/local/etc/rc.d ;

- la possibilité de voir tous les fichiers installés avec pkg_info -L ;

- la possibilité de les effacer tous avec pkg_delete si vous ne voulez plus de MySQL sur cette machine.

Il est recommandé d'utiliser les MIT-pthreads sur FreeBSD 2.x et les threads natifs sur les versions 3 et plus. Il est possible de faire fonctionner le tout avec les threads natifs sur les dernières versions 2.2.x, mais vous rencontrerez probablement des problèmes en coupant mysqld.

Malheureusement, certains appels systèmes sur FreeBSD ne sont pas encore totalement compatibles avec les threads. Le cas le plus notable est la fonction gethostbyname() qui est utilisée par MySQL pour convertir des noms d'hôtes en adresse IP. Dans certaines circonstances, le processus mysqld va soudainement prendre 100 % du processeur, et ne plus répondre. Si vous rencontrez cette situation, essayez de relancer MySQL avec l'option --skip-name-resolve.

Alternativement, vous pouvez compiler MySQL sur FreeBSD 4.x avec la bibliothèque LinuxThreads, qui évite les quelques problèmes que l'implémentation thread native de FreeBSD a. Pour une bonne comparaison entre LinuxThreads et les threads natifs, voyez l'article de Jeremy Zawodny FreeBSD or Linux for your MySQL Server ? à http://jeremy.zawodny.com/blog/archives/000697.html.

Un problème connu lors de l'utilisation des LinuxThreads sur FreeBSD est que wait_timeout ne fonctionne pas (probablement un problème de gestion des signaux sous FreeBSD/LinuxThreads). Cela devrait être corrigé en FreeBSD 5.0. Le symptôme est que les connexions persistantes vont rester bloquées très longtemps sans se refermer.

Le processus de compilation de MySQL requiert GNU make (gmake) pour fonctionner. Si vous voulez compiler MySQL vous devez d'abord installer GNU make.

La méthode recommandée pour compiler et installer MySQL sur FreeBSD avec gcc (2.95.2 et plus récents) est :

CC=gcc CFLAGS="-O2 -fno-strength-reduce" \
CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions \
-felide-constructors -fno-strength-reduce" \
./configure --prefix=/usr/local/mysql --enable-assembler
gmake
gmake install
cd /usr/local/mysql
bin/mysql_install_db --user=mysql
bin/mysqld_safe &

Si vous remarquez que configure va utiliser MIT-pthreads, il faut alors lire les notes MIT-pthreads. Voir Section 2.4.5, « Notes relatives aux MIT-pthreads ».

Si vous avez une erreur durant make install qui dit qu'il ne peut trouver /usr/include/pthreads, configure n'a pas détecté l'absence de MIT-pthreads. Pour corriger le problème, supprimez config.cache, puis relancez configure avec l'option --with-mit-threads.

Assurez-vous que votre configuration de la résolution des noms est bonne. Sinon, vous aurez peut-être quelques problèmes lors de la connexion à mysqld. Assurez-vous que l'entrée localhost dans le fichier /etc/hosts est correcte (sinon, vous aurez des problèmes pour vous connecter à la base de données). Le fichier doit commencer par une ligne similaire à :

127.0.0.1       localhost localhost.votre.domaine

FreeBSD est aussi connu pour avoir une petite limite de gestionnaires de fichiers par défaut. Voir Section A.2.17, « Fichier non trouvé ». Décommentez la section ulimit -n dans safe_mysqld ou enlevez la limite pour l'utilisateur mysqld dans /etc/login.conf (et régénérez-le avec cap_mkdb). Assurez-vous aussi de définir la classe appropriée pour cet utilisateur dans le fichier des mots de passe si vous n'utilisez pas celui par défaut. (Utilisez : chpass nom-utilisateur-mysqld.) Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ».

Si vous avez beaucoup de mémoire, vous devriez penser à recompiler le noyau pour permettre à MySQL d'utiliser plus de 512 Mo de RAM. Regardez l'option MAXDSIZ dans le fichier de configuration de LINT pour plus d'informations.

Si vous avez des problèmes avec la date courante dans MySQL, configurer la variable d'environnement TZ aidera sûrement. Voir Annexe E, Variables d'environnement.

Pour obtenir un système sécurisé et stable, vous ne devez utiliser que les noyaux FreeBSD marqués -RELEASE.

2-8-4-2 - Notes concernant NetBSD

Pour compiler sur NetBSD vous aurez besoin de GNU make. Sinon, la compilation stoppera lorsque make essayera d'exécuter lint sur les fichiers C++.

2-8-4-3 - Notes relatives à OpenBSD 2.5

Dans la version 2.5 d'OpenBSD, vous pouvez compiler MySQL avec les threads natifs avec les options suivantes :

CFLAGS=-pthread CXXFLAGS=-pthread ./configure --with-mit-threads=no

2-8-4-4 - Notes relatives à OpenBSD 2.8

Nos utilisateurs nous ont informés qu'OpenBSD 2.8 comporte un bogue des threads qui pose quelques problèmes avec MySQL. Les développeurs d'OpenBSD ont résolu ce problème, mais depuis le 25 janvier 2001 ce n'est disponible que dans la branche « -current ». Les symptômes de ce bogue sont : réponses lentes, beaucoup de charge, grande utilisation du CPU, et crashes.

Si vous obtenez une erreur comme Error in accept:: Bad file descriptor ou erreur 9 en essayant d'ouvrir les tables ou les dossiers, le problème est probablement que vous n'avez pas alloué assez de descripteurs de fichiers à MySQL.

Dans ce cas, essayez de démarrer safe_mysqld en tant que root avec les options suivantes :

shell> mysqld_safe --user=mysql --open-files-limit=2048 &

2-8-4-5 - Notes relatives aux versions 2.x de BSD/OS

Si vous obtenez l'erreur suivante lors de la compilation de MySQL, votre valeur de ulimit pour la mémoire virtuelle est trop petite :

item_func.h: In method 'Item_func_ge::Item_func_ge(const Item_func_ge &)':
item_func.h:28: virtual memory exhausted
make[2]: *** [item_func.o] Error 1

Essayez d'utiliser ulimit -v 80000 et exécutez make à nouveau. Si cela ne fonctionne pas et que vous utilisez bash, essayez de passer à csh ou sh; quelques utilisateurs de BSDI ont rapporté des problèmes avec bash et ulimit.

Si vous utilisez gcc, vous aurez peut-être aussi à utiliser l'option --with-low-memory de configure pour pouvoir compiler sql_yacc.cc.

Si vous avez des problèmes avec la date courante dans MySQL, configurer la variable TZ vous aidera probablement. Voir Annexe E, Variables d'environnement.

2-8-4-6 - Notes relatives aux versions 3.x de BSD/OS

Mettez à jour à la version 3.1 de BSD/OS. Si cela n'est pas possible, installez le patch BSDIpatch M300-038.

Utilisez la commande suivante lors de la configuration de MySQL :

shell> env CXX=shlicc++ CC=shlicc2 \
./configure \
--prefix=/usr/local/mysql \
--localstatedir=/var/mysql \
--without-perl \
--with-unix-socket-path=/var/mysql/mysql.sock

Ce qui suit fonctionne aussi :

shell> env CC=gcc CXX=gcc CXXFLAGS=-O3 \
./configure \
--prefix=/usr/local/mysql \
--with-unix-socket-path=/var/mysql/mysql.sock

Vous pouvez changer les répertoires si vous voulez, ou utiliser les valeurs par défaut en ne spécifiant pas de chemin.

Si vous avez des problèmes de performance alors que la charge est petite, essayez d'utiliser l'option --skip-thread-priority de mysqld ! Cela exécutera tous les threads avec la même priorité. Sur la version 3.1 de BSDI, cela donne de meilleures performances (en attendant que BSDI corrige son gestionnaire de threads).

Si vous obtenez l'erreur virtual memory exhausted durant la compilation, vous devez essayer en utilisant ulimit -v 80000 et exécutant make à nouveau. Si cela ne fonctionne pas et que vous utilisez bash, essayez de passer à csh ou sh; quelques utilisateurs de BSDI ont rapporté des problèmes avec bash et ulimit.

2-8-4-7 - Notes relatives aux versions 4.x de BSD/OS

Les versions 4.x de BSDI ont quelques bogues relatifs aux threads. Si vous voulez utiliser MySQL sur ce système, vous devez installer tous les patches liés aux threads. Vous devez au moins installer M400-023.

Sur quelques systèmes avec une version 4.x de BSDI, vous pouvez rencontrer des problèmes avec les bibliothèques partagées. Le symptôme est que vous ne pouvez utiliser aucun programme client, comme, mysqladmin. Dans ce cas, vous devez le reconfigurer pour qu'il n'utilise pas les bibliothèques partagées avec l'option --disable-shared de configure.

Quelques utilisateurs ont eu avec BSDI 4.0.1 un problème faisant qu'après un bout de temps, le binaire mysqld ne peut plus ouvrir de tables. Cela est dû au fait qu'un bogue relatif au système ou à la bibliothèque fait changer de répertoire à mysqld sans qu'on ne l'ait demandé !

La solution est soit de mettre à jour vers la version 3.23.34 ou de supprimer la ligne #define HAVE_REALPATH de config.h après avoir exécuté configure et avant d'exécuter make.

Notez que ce qui précède signifie que vous ne pouvez pas créer de lien symbolique sur un dossier de bases de données vers un autre dossier de bases de données ou lier une table symboliquement vers une autre base de données sur BSDI ! (Créer un lien symbolique vers un autre disque fonctionne).

2-8-5 - Notes sur les autres Unix

2-8-5-1 - Notes relatives à la version 10.20 de HP-UX

Il y a quelques petits problèmes que vous pourrez rencontrer lors de la compilation de MySQL sur HP-UX. Nous recommandons l'utilisation de gcc au lieu du compilateur natif de HP-UX, car gcc produit un meilleur code !

Nous recommandons l'utilisation de gcc 2.95 sur HP-UX. N'utilisez pas les options de haute optimisation (comme -O6), car cela pourrait ne pas être sûr sur HP-UX.

La ligne de configuration suivante devrait fonctionner avec gcc 2.95 :

CFLAGS="-I/opt/dce/include -fpic" \
CXXFLAGS="-I/opt/dce/include -felide-constructors -fno-exceptions \
-fno-rtti" CXX=gcc ./configure --with-pthread \
--with-named-thread-libs='-ldce' --prefix=/usr/local/mysql --disable-shared

La ligne de configuration suivante devrait fonctionner avec gcc 3.1 :

CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc \
CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions \
-fno-rtti -O3 -fPIC" ./configure --prefix=/usr/local/mysql \
--with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile  --with-pthread \
--with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC
--disable-shared

2-8-5-2 - HP-UX Version 11.x Notes

Pour les versions 11.x de HP-UX nous recommandons MySQL 3.23.15 ou plus récent.

À cause de quelques bogues critiques dans les bibliothèques standard de HP-UX, vous devez installer les correctifs suivants avant d'essayer de faire fonctionner MySQL sous HP-UX 11.0 :

PHKL_22840 Streams cumulative
PHNE_22397 ARPA cumulative

Cela résoudra le problème de l'obtention de EWOULDBLOCK à partir de recv() et EBADF à partir de accept() dans les applications threadées.

Si vous utilisez gcc 2.95.1 sur un système HP-UX 11.x non corrigé, vous obtiendrez l'erreur :

In file included from /usr/include/unistd.h:11,
from ../include/global.h:125,
from mysql_priv.h:15,
from item.cc:19:
/usr/include/sys/unistd.h:184: declaration of C function ...
/usr/include/sys/pthread.h:440: previous declaration ...
In file included from item.h:306,
from mysql_priv.h:158,
from item.cc:19:

Le problème est que HP-UX ne définit pas pthreads_atfork() avec cohérence. Il possède des prototypes en conflit dans /usr/include/sys/unistd.h:184 et /usr/include/sys/pthread.h:440 (détails ci-dessous).

Une solution est de copier /usr/include/sys/unistd.h dans mysql/include et éditer unistd.h en le changeant pour qu'il corresponde à la définition dans pthread.h. Voici les modifications :

extern int pthread_atfork(void (*prepare)(), void (*parent)(),
void (*child)());

est remplacée par

extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
void (*child)(void));

Après cela, la ligne de configuration suivante devrait fonctionner :

CFLAGS="-fomit-frame-pointer -O3 -fpic" CXX=gcc \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O3" \
./configure --prefix=/usr/local/mysql --disable-shared

Si vous utilisez MySQL 4.0.5 avec le compilateur HP-UX, vous pouvez utiliser (testé avec cc B.11.11.04) :

CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure --with-extra-character-set=complex

Vous pouvez ignorer toutes les erreurs de ce type :

aCC: warning 901: unknown option: '-3': use +help for online documentation

Si vous obtenez l'erreur suivante de configure :

checking for cc option to accept ANSI C... no
configure: error: MySQL requires a ANSI C compiler (and a C++ compiler).
Try gcc. See the Installation chapter in the Reference Manual.

Vérifiez que le chemin vers le compilateur K&R ne précède pas le chemin vers le compilateur C et C++ HP-UX.

Une autre raison qui pourrait vous empêcher de compiler, et le fait de n'avoir pas défini l'option +DD64 ci-dessus.

2-8-5-3 - Notes relatives à IBM-AIX

La détection automatique de xlC est absente d'Autoconf, ce qui fait qu'une commande configure comme celle qui suit est requise lors de la compilation de MySQL (cet exemple utilise le compilateur IBM) :

export CC="xlc_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192 "
export CXX="xlC_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192"
export CFLAGS="-I /usr/local/include"
export LDFLAGS="-L /usr/local/lib"
export CPPFLAGS=$CFLAGS
export CXXFLAGS=$CFLAGS

./configure --prefix=/usr/local \
--localstatedir=/var/mysql \
--sysconfdir=/etc/mysql \
--sbindir='/usr/local/bin' \
--libexecdir='/usr/local/bin' \
--enable-thread-safe-client \
--enable-large-files

Ce sont les options utilisées pour compiler la distribution de MySQL qui peut être trouvée sur http://www-frec.bull.com/.

Si vous changez le -O3 en -O2 dans la ligne précédente, vous devez aussi enlever l'option -qstrict (c'est une limitation du compilateur IBM C).

Si vous utilisez gcc ou egcs pour compiler MySQL, vous devez utiliser l'option -fno-exceptions, vu que la gestion des exceptions de gcc/egcs n'est pas sûre pour les threads ! (Cela est testé avec egcs 1.1.) Il y a aussi quelques problèmes connus avec l'assembleur d'IBM, qui peuvent lui faire générer du mauvais code lors de son utilisation avec gcc.

Nous recommandons la ligne de configure suivante avec egcs et gcc 2.95 sur AIX :

CC="gcc -pipe -mcpu=power -Wa,-many" \
CXX="gcc -pipe -mcpu=power -Wa,-many" \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --with-low-memory

Le -Wa,-many est nécessaire pour que la compilation se passe sans problèmes. IBM est au courant de ce problème, mais n'est pas pressé de le corriger à cause de l'existence du palliatif. Nous ne savons pas si -fno-exceptions est requise avec gcc 2.95, mais comme MySQL n'utilise pas les exceptions et que l'option en question génère un code plus rapide, nous vous recommandons de toujours utiliser cette option avec egcs / gcc.

Si vous obtenez un problème avec le code de l'assembleur, essayez en changeant l'option -mcpu=xxx pour l'adapter à votre processeur. Le plus souvent, on a besoin de power2, power, ou powerpc, et sinon 604 ou 604e. Je ne suis pas positif, mais je pense que l'utilisation de "power" sera sûre la plupart du temps, même sur une machine power2.

Si vous ne savez pas quel est votre processeur, exécutez "uname -m", cela vous renverra une chaîne comme "000514676700", avec un format xxyyyyyymmss où xx et ss sont toujours des zéros, yyyyyy est un identifiant unique du système et mm est l'identifiant du CPU Planar. Une liste de ces valeurs peut être trouvée sur http://publib.boulder.ibm.com/doc_link/en_US/a_doc_lib/cmds/aixcmds5/uname.htm. Cela vous donnera un type et un modèle de machine que vous pouvez utiliser pour déterminer quel type de processeur vous avez.

Si vous avez des problèmes avec les signaux (MySQL se termine de manière imprévue lors des montées en charge), vous avez peut-être trouvé un bogue du système avec les threads et les signaux. Dans ce cas, vous pouvez demander à MySQL de ne pas utiliser les signaux en configuration avec :

shell> CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti \
-DDONT_USE_THR_ALARM" \
./configure --prefix=/usr/local/mysql --with-debug --with-low-memory

Cela n'affecte pas les performances de MySQL, mais comporte un effet secondaire faisant en sorte que vous ne pourrez tuer les clients en état « sleeping » sur une connexion avec mysqladmin kill ou mysqladmin shutdown. À la place, le client se terminera lorsqu'il émettra sa prochaine commande.

Sur quelques versions d'AIX, lier avec libbind.a fait vider son noyau à getservbyname (core dump). Il s'agit d'un bogue AIX et doit être remonté à IBM.

Pour AIX 4.2.1 et gcc vous devez apporter les modifications suivantes :

après la configuration, éditez config.h et include/my_config.h et changez la ligne qui comporte

#define HAVE_SNPRINTF 1

en

#undef HAVE_SNPRINTF

Et finalement, dans mysqld.cc vous devez ajouter un prototype pour initgroups.

#ifdef _AIX41
extern "C" int initgroups(const char *,int);
#endif

Si vous avez besoin d'allouer beaucoup de mémoire au processus mysqld, il ne suffit pas de configurer 'ulimit -d unlimited'. Vous aurez aussi à configurer dans mysqld_safe quelque chose comme :

export LDR_CNTRL='MAXDATA=0x80000000'

Vous trouverez plus d'informations sur l'utilisation d'une grande quantité de mémoire sur : http://publib16.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/lrg_prg_support.htm.

2-8-5-4 - Notes relatives à SunOS 4

Avec SunOS 4, les MIT-pthreads sont requis pour compiler MySQL, ce qui signifie que vous aurez besoin de GNU make.

Quelques systèmes SunOS 4 ont des problèmes avec les bibliothèques dynamiques et libtool. Vous pouvez utiliser la ligne suivante de configure pour éviter ce problème :

shell> ./configure --disable-shared --with-mysqld-ldflags=-all-static

Lors de la compilation de readline, vous pouvez obtenir des avertissements à propos de définitions dupliquées. Vous pouvez les ignorer.

Lors de la compilation de mysqld, il y aura quelques avertissements implicit declaration of function. Vous pouvez les ignorer.

2-8-5-5 - Notes pour Alpha-DEC-UNIX (Tru64)

Si vous utilisez egcs 1.1.2 sur Digital Unix, vous devez passer à gcc 2.95.2, car egcs connaît de sérieux bogues sur DEC !

Lorsque vous compilez des programmes threadés sous Digital Unix, la documentation recommande l'utilisation de l'option -pthread avec cc et cxx et les bibliothèques -lmach -lexc (en plus de -lpthread). Vous devriez exécuter le script configure comme ceci :

CC="cc -pthread" CXX="cxx -pthread -O" \
./configure --with-named-thread-libs="-lpthread -lmach -lexc -lc"

Lorsque vous compilez mysqld, vous pouvez voir apparaître des alertes comme celles-ci :

mysqld.cc: In function void handle_connections()':
mysqld.cc:626: passing long unsigned int *' as argument 3 of
accept(int,sockadddr *, int *)'

Vous pouvez les ignorer tranquillement. Elles apparaissent, car configure ne peut détecter que des erreurs, et pas des alertes.

Si vous démarrez le serveur directement en ligne de commande, vous pouvez rencontrer des problèmes d'interruption si vous vous déconnectez. Lorsque vous vous déconnectez, les processus en cours reçoivent le signal SIGHUP. Si c'est le cas, essayez de démarrer le serveur comme ceci :

shell> nohup mysqld [options] &

nohup fait que la commande suivante va ignorer les signaux SIGHUP envoyés par le terminal. Alternativement, vous pouvez démarrer le serveur avec le script safe_mysqld, qui appelle le démon mysqld avec l'option nohup pour vous. Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ».

Si vous avez des problèmes pour compiler mysys/get_opt.c, vous pouvez simplement supprimer la ligne #define _NO_PROTO au début du fichier !

Si vous utilisez le compilateur cc de Compaq, la ligne de configuration suivante devrait fonctionner :

CC="cc -pthread"
CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
CXX="cxx -pthread"
CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host \
-noexceptions -nortti"
export CC CFLAGS CXX CXXFLAGS
./configure \
--prefix=/usr/local/mysql \
--with-low-memory \
--enable-large-files \
--enable-shared=yes \
--with-named-thread-libs="-lpthread -lmach -lexc -lc"
gnumake

Si vous avez un problème avec libtool, lorsque vous compilez les bibliothèques partagées, ou lorsque vous compilez mysql, vous devriez pouvoir résoudre ce problème avec :

cd mysql
/bin/sh ../libtool --mode=link cxx -pthread  -O3 -DDBUG_OFF \
-O4 -ansi_alias -ansi_args -fast -inline speed \
-speculate all \ -arch host  -DUNDEF_HAVE_GETHOSTBYNAME_R \
-o mysql  mysql.o readline.o sql_string.o completion_hash.o \
../readline/libreadline.a -lcurses \
../libmysql/.libs/libmysqlclient.so  -lm
cd ..
gnumake
gnumake install
scripts/mysql_install_db

2-8-5-6 - Notes pour Alpha-DEC-OSF/1

Si vous avez des problèmes de compilation et que le CC de DEC et gcc sont installés, essayez d'utiliser le script configure comme ceci :

CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql

Si vous avez des problèmes avec le fichier c_asm.h, vous pouvez créer un fichier inerte c_asm.h avec :

touch include/c_asm.h
CC=gcc CFLAGS=-I./include \
CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql

Notez que les problèmes suivants avec le programme ld peuvent être corrigés en téléchargeant le dernier kit de patch de DEC (Compaq) à : http://ftp.support.compaq.com/public/unix/.

Su OSF/1 V4.0D et avec le compilateur DEC C V5.6-071 on Digital Unix V4.0 (Rev. 878) le compilateur présente un comportement étrange (undefined asm symbols). /bin/ld apparaît aussi comme incorrect (problèmes avec des erreurs _exit undefined survenant lors du link de mysqld). Sur ce système, nous avons réussi à compiler MySQL avec le script configure suivant, après avoir remplacé /bin/ld par la version de OSF 4.0C :

CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql

Avec le compilateur Digital C++ V6.1-029, la ligne suivante doit fonctionner :

CC=cc -pthread
CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all \
-arch host
CXX=cxx -pthread
CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all \
-arch host -noexceptions -nortti
export CC CFLAGS CXX CXXFLAGS
./configure --prefix=/usr/mysql/mysql --with-mysqld-ldflags=-all-static \
--disable-shared --with-named-thread-libs="-lmach -lexc -lc"

Avec certaines versions de OSF/1, la fonction alloca() est boguée. Corrigez cela en supprimant la ligne du fichier config.h qui définit 'HAVE_ALLOCA'.

La fonction alloca() a aussi un prototype incorrect dans /usr/include/alloca.h. L'alerte en résultant peut être ignorée.

Le script configure va utiliser automatiquement les bibliothèques de threads suivantes : --with-named-thread-libs="-lpthread -lmach -lexc -lc".

En utilisant gcc, vous pouvez aussi essayer le script configure avec ceci :

shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ...

Si vous avez des problèmes avec les signaux (MySQL s'arrête inopinément sous forte charge), vous pouvez avoir rencontré un bogue de l'OS avec les threads, et les signaux. Dans ce cas, vous pouvez indiquer à MySQL de ne pas utiliser les signaux avec la configuration suivante :

shell> CFLAGS=-DDONT_USE_THR_ALARM \
CXXFLAGS=-DDONT_USE_THR_ALARM \
./configure ...

Cela ne modifie pas les performances de MySQL, mais vous ne pourrez plus terminer les clients qui sont en mode « sleeping » sur une connexion avec la commande mysqladmin kill ou mysqladmin shutdown. Au lieu de cela, le client sera interrompu lorsqu'il émettra la prochaine commande.

Avec gcc 2.95.2, vous aurez probablement les problèmes de compilation suivants :

sql_acl.cc:1456: Internal compiler error in 'scan_region', at except.c:2566
Please submit a full bug report.

Pour corriger cela, vous devez aller dans le dossier sql et faire un « copier coller » de la dernière ligne gcc, tout en remplaçant le code -O3 par le code -O0 ou ajouter le code -O0 immédiatement après gcc si vous n'avez aucune option -O sur votre ligne de compilation). Après cela, vous pouvez retourner au niveau de la racine de MySQL, et tenter à nouveau un make.

2-8-5-7 - Notes relatives à SGI Irix

Si vous utilisez la version 6.5.3 d'Irix ou plus récente, mysqld ne pourra créer de threads que si vous l'exécutez en tant qu'utilisateur possédant le privilège CAP_SCHED_MGT (comme root) ou que vous donnez au serveur mysqld ce privilège avec la commande suivante :

shell> chcap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld

Vous devrez peut-être supprimer quelques définitions dans config.h après avoir exécuté configure et avant de compiler.

Sur quelques implémentations d'Irix, la fonction alloca() ne marche pas. Si le serveur mysqld se stoppe sur quelques requêtes SELECT, supprimez les lignes de config.h qui définissent HAVE_ALLOC et HAVE_ALLOCA_H. Si mysqladmin create ne fonctionne pas, supprimez la ligne qui définit HAVE_READDIR_R dans config.h. Vous devrez peut-être supprimer la ligne de HAVE_TERM_H aussi.

SGI recommande que vous installiez tous les patches de cette page : http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html

Vous devrez, au moins, installer la dernière version du noyau, de rld et de libc.

Vous avez besoin de tous les patches POSIX sur cette page, pour le support des pthreads :

http://support.sgi.com/surfzone/patches/patchset/6.2_posix.rps.html

Si vous obtenez une erreur se rapprochant de la suivante lors de la compilation de mysql.cc:

"/usr/include/curses.h", line 82: error(1084): invalid combination of type

Tapez ce qui suit dans le répertoire racine de votre source MySQL :

shell> extra/replace bool curses_bool < /usr/include/curses.h \
> include/curses.h
shell> make

Un problème de planification a aussi été signalé. Si seul un thread est en cours, les choses ralentissent. Évitez cela en démarrant un autre client. Cela pourra accélérer l'exécution de l'autre thread de 2 à 10 fois. Ceci est un problème pas encore très clair avec les threads Irix, vous devrez improviser pour trouver des solutions en attendant que cela soit corrigé.

Si vous compilez avec gcc, vous pouvez utiliser la commande configure suivante :

CC=gcc CXX=gcc CXXFLAGS=-O3 \
./configure --prefix=/usr/local/mysql --enable-thread-safe-client \
--with-named-thread-libs=-lpthread

Sous Irix 6.5.11 avec les compilateurs natifs Irix C et C++ versions 7.3.1.2, ce qui suit est connu pour fonctionner :

CC=cc CXX=CC CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \
-L/usr/local/lib' CXXFLAGS='-O3 -n32 -TARG:platform=IP22 \
-I/usr/local/include -L/usr/local/lib' ./configure \
--prefix=/usr/local/mysql --with-innodb --with-berkeley-db \
--with-libwrap=/usr/local \
--with-named-curses-libs=/usr/local/lib/libncurses.a

2-8-5-8 - Notes sur SCO

Le port actuel est testé uniquement sur les systèmes « sco3.2v5.0.5 », « sco3.2v5.0.6 » et « sco3.2v5.0.7 ». Il y a aussi eu des progrès sur le port vers « sco 3.2v4.2 ».

Pour le moment, le compilateur recommandé sur OpenServer est gcc 2.95.2. Avec lui, vous devriez être capable de compiler MySQL simplement avec :

CC=gcc CXX=gcc ./configure ... (options)

1. Pour OpenServer 5.0.x, vous avez besoin de gcc-2.95.2p1 ou plus récent, de Skunkware. http://www.sco.com/skunkware/ puis recherchez dans les paquets OpenServer ou par FTP sur ftp2.caldera.com, dans le dossier pub/skunkware/osr5/devtools/gcc.

2. Vous avez besoin de GCC 2.5.x pour ce produit, et du système de développement. Ils sont nécessaires sur cette version d'Unix SCO. Vous ne pouvez pas simplement utiliser GCC Dev.

3. Vous devriez installer le paquet FSU Pthreads et l'installer. Il peut être trouvé à l'adresse : http://moss.csc.ncsu.edu/~mueller/ftp/pub/PART/pthreads.tar.gz. Vous pouvez aussi obtenir un paquet précompilé sur http://www.mysql.com/Downloads/SCO/FSU-threads-3.5c.tar.gz.

4. Les FSU Pthreads peuvent être compilés sur SCO Unix 4.2 avec TCP/IP. Ou OpenServer 3.0 ou Open Desktop 3.0 (OS 3.0 ODT 3.0), avec le SCO Development System, installé avec le bon port de GCC 2.5.x ODT ou OS 3.0 avec le bon port de GCC 2.5.x Il y a beaucoup de problèmes si vous n'utilisez pas le bon port. Le port de ce produit requiert le SCO Unix Development. Sans cela, il vous manque des bibliothèques et le linker nécessaire.

5. Pour compiler FSU Pthreads sur votre système, faites ceci :

1. exécutez ./configure dans le dossier threads/src et sélectionnez l'option SCO OpenServer. Cette commande copie Makefile.SCO5 dans le fichier Makefile ;

2. exécutez make ;

3. pour installer le paquet dans le dossier par défaut /usr/include, identifiez-vous comme root, puis utilisez cd pour vous placer dans le dossier thread/src, et faites make install.

6. N'oubliez pas d'utiliser GNU make lors de la compilation de MySQL.

7. Si vous ne lancez pas mysqld_safe en tant que root, vous obtiendrez probablement un maximum de 110 fichiers ouverts par processus. mysqld vous le dira dans les logs.

8. Avec SCO 3.2V5.0.5, il est recommandé d'utiliser FSU Pthreads version 3.5c ou plus récente. Il est recommandé d'utiliser gcc 2.95.2 ou plus récent !

La commande configure devrait fonctionner :

shell> ./configure --prefix=/usr/local/mysql --disable-shared

9. Avec SCO 3.2V4.2, il est recommandé d'utiliser FSU Pthreads version 3.5c ou plus récent. La commande configure devrait fonctionner :

shell> CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \
./configure \
--prefix=/usr/local/mysql \
--with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \
--with-named-curses-libs="-lcurses"

Vous pourriez rencontrer des problèmes avec certains fichiers à inclure. Dans ce cas, vous pouvez trouver des fichiers spécifiques pour SCO à l'adresse http://www.mysql.com/Downloads/SCO/SCO-3.2v4.2-includes.tar.gz. Il suffit de décompresser le fichier dans le dossier include de votre dossier source MySQL.

Notes de développement SCO

- MySQL doit automatiquement détecter le paquet FSU Pthreads et l'utiliser pour compiler mysqld avec -lgthreads -lsocket -lgthreads.

- Les bibliothèques de développement SCO sont réentrantes avec les FSU Pthreads. SCO affirme que ses bibliothèques sont réentrantes, donc elles sont aussi réentrantes avec les FSU Pthreads. FSU Pthreads sur OpenServer essaie d'utiliser les concepts SCO pour rendre ses bibliothèques réentrantes.

- FSU Pthreads (tout au moins, la version de http://www.mysql.com/) est livré avec GNU malloc. Si vous rencontrez des problèmes avec l'utilisation de la mémoire, assurez-vous que le fichier gmalloc.o est inclus dans libgthreads.a et libgthreads.so.

- Avec les FSU Pthreads, les appels système suivants sont compatibles avec les pthreads : read(), write(), getmsg(), connect(), accept(), select() et wait().

- Le patch CSSA-2001-SCO.35.2 (le patch est nommé erg711905-dscr_remap security patch (version 2.0.0)) bloque les FSU Pthreads et rend mysqld instable. Vous devez le supprimer si vous voulez faire fonctionner mysqld sur une machine OpenServer 5.0.6.

- SCO fournit des patches pour son système d'exploitation à l'adresse ftp://ftp.sco.com/pub/openserver5 [ftp://ftp.sco.com/pub/openserver5] pour OpenServer 5.0.x

- SCO fournit des patches de sécurités et la bibliothèque libsocket.so.2 à l'adresse ftp://ftp.sco.com/pub/security/OpenServer [ftp://ftp.sco.com/pub/security/OpenServer] et ftp://ftp.sco.com/pub/security/sse [ftp://ftp.sco.com/pub/security/sse] pour OpenServer 5.0.x

- Patch de sécurité avant OSR506. De même, le patch telnetd de ftp://stage.caldera.com/pub/security/openserver/ [ftp://stage.caldera.com/pub/security/openserver/] ou ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/ [ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/] ainsi que libsocket.so.2 et libresolv.so.1 ont des instructions concernant leur installation sur un système pre-OSR506.

C'est probablement une bonne idée que d'installer les patches de sécurité ci-dessus avant de compiler et d'utiliser MySQL.

2-8-5-9 - Notes sur SCO UnixWare Version 7.1.x

Sur UnixWare 7.1.0, vous devez utiliser une version de MySQL au moins aussi récente que la 3.22.13 pour avoir les correctifs sur cet OS.

Nous avons réussi à compiler MySQL avec la commande de configuration suivante configure sur UnixWare Version 7.1.x :

CC=cc CXX=CC ./configure --prefix=/usr/local/mysql

Si vous voulez utiliser gcc, vous devez utiliser gcc 2.95.2 ou plus récent.

CC=gcc CXX=g++ ./configure --prefix=/usr/local/mysql

SCO fournit des patches pour son OS à ftp://ftp.sco.com/pub/unixware7 [ftp://ftp.sco.com/pub/unixware7] pour UnixWare 7.1.1 et 7.1.3 et à ftp://ftp.sco.com/pub/openunix8 [ftp://ftp.sco.com/pub/openunix8] pour OpenUNIX 8.0.0.

SCO fournit des informations sur les correctifs de sécurité à ftp://ftp.sco.com/pub/security/OpenUNIX [ftp://ftp.sco.com/pub/security/OpenUNIX] pour OpenUNIX et à ftp://ftp.sco.com/pub/security/UnixWare [ftp://ftp.sco.com/pub/security/UnixWare] pour UnixWare.

2-8-6 - Notes relatives à OS/2

MySQL utilise un certain nombre de fichiers ouverts. À cause de cela, vous devez ajouter une ligne se rapprochant de la suivante dans votre fichier CONFIG.SYS :

SET EMXOPT=-c -n -h1024

Si vous ne le faites pas, vous obtiendrez probablement l'erreur :

File 'xxxx' not found (Errcode: 24)

Lors de l'utilisation de MySQL avec OS/2 Warp 3, FixPack 29 ou plus est requis. Avec OS/2 Warp 4, FixPack 4 ou plus est requis. C'est un besoin de la bibliothèque des Pthreads. MySQL doit être installé sur une partition qui supporte les noms de fichiers longs, tel que HPFS, FAT32, etc.

Le script INSTALL.CMD doit être exécuté à partir du CMD.EXE d'OS/2 et ne fonctionnera probablement pas avec des substituts tels que 4OS2.EXE.

Le script scripts/mysql-install-db a été renommé. Il est maintenant nommé install.cmd et est un script REXX, qui mettra en place les configurations de sécurité par défaut de MySQL et créera les icônes WorkPlace Shell pour MySQL.

Le support des modules dynamiques est compilé, mais n'est pas assez testé. Les modules dynamiques doivent être compilés en utilisant la bibliothèque pthreads.

gcc -Zdll -Zmt -Zcrtdll=pthrdrtl -I../include -I../regex -I.. \
-o exemple udf_exemple.cc -L../lib -lmysqlclient udf_exemple.def
mv exemple.dll exemple.udf

Note : à cause des limitations d'OS/2, les noms des modules UDF ne doivent pas dépasser 8 caractères. Les modules sont stockés dans le répertoire /mysql2/udf; le script safe-mysqld.cmd placera ce répertoire dans la variable d'environnement BEGINLIBPATH. Lors de l'utilisation des modules UDF, les extensions spécifiées sont ignorées. Elle est supposée être .udf. Par exemple, sous Unix, le module partagé peut se nommer exemple.so et vous chargeriez une de ses fonctions de la façon suivante :

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "exemple.so";

Sous OS/2, le module s'appellera exemple.udf, mais vous n'aurez pas à spécifier son extension :

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "exemple";

2-8-7 - Notes relatives à BeOS

Nous sommes vraiment intéressés par le port de MySQL sur BeOS, mais malheureusement, nous n'avons personne qui s'y connait en BeOS ou qui a le temps de s'en occuper.

Nous sommes intéressés par quelqu'un qui serait prêt à faire le port, et nous l'aiderions pour toutes les questions techniques qu'il pourrait se poser durant le processus.

Nous avons déjà eu des contacts avec des développeurs BeOS qui ont dit que MySQL était porté à 80 % sur BeOS, mais nous n'avons plus entendu parler d'eux depuis.

2-9 - Commentaires sur l'installation de Perl

Le support MySQL par Perl est fourni grâce à l'interface DBI/DBD. Cette interface requiert Perl Version 5.6.0 ou plus récente. Elle ne fonctionnera pas si vous avez une autre version plus ancienne de Perl.

Si vous voulez utiliser les transactions avec Perl DBI, vous devez installer DBD::mysql version 1.2216 ou plus récente. La version 2.9003 ou plus récente est recommandée.

Notez que si vous utilisez la bibliothèque client MySQL 4.1, vous devrez utiliser DBD::mysql 2.9003 ou plus récent.

Depuis la version 3.22.8, le support de Perl n'est plus inclus dans les distributions de MySQL. Vous pouvez obtenir les modules requis sur le site http://search.cpan.org pour Unix, ou sur le site d'ActiveState (fichiers ppm) pour Windows. La section suivante décrit comment faire.

Le support de MySQL par Perl doit être installé si vous voulez exécuter les scripts de tests de performance. Voir Section 7.1.4, « La suite de tests MySQL ».

2-9-1 - Installer Perl sur Unix

Le support Perl de MySQL requiert que vous ayez installé le support de programmation de clients pour MySQL. Si vous avez installé MySQL à partir de fichiers RPM, les programmes clients sont dans le RPM client, mais le support de la programmation de clients est dans le RPM des développeurs. Assurez-vous d'avoir installé le dernier RPM.

Si vous voulez installer le support Perl, les fichiers dont vous avez besoin sont disponibles sur la bibliothèque CPAN (Comprehensive Perl Archive Network) à http://search.cpan.org.

Le moyen le plus facile pour installer le module Unix de Perl est d'utiliser le module CPAN. Par exemple :

shell> perl -MCPAN -e shell
cpan> install DBI
cpan> install DBD::mysql

L'installation de DBD::mysql effectue de nombreux tests. Ces tests requièrent une connexion locale au serveur MySQL, en tant qu'utilisateur anonyme, sans mot de passe. Si vous avez supprimé l'accès anonyme, ou assigné des mots de passe, les tests échoueront. Vous pouvez utiliser force install DBD::mysql pour ignorer ces tests.

DBI requiert le module Data::Dumper. Il peut être déjà installé. Sinon, vous devez l'installer avant d'installer DBI.

Il est aussi possible de télécharger la distribution module sous la forme d'une archive tar compressée, et de compiler manuellement les modules. Par exemple, pour décompresser et construire la distribution DBI, utilisez la procédure qui suit.

1. Décompressez la distribution dans le dossier courant :

shell> gunzip < Data-Dumper-VERSION.tar.gz | tar xvf -

Cette commande crée un dossier appelé Data-Dumper-VERSION.

2. Mettez-vous dans le répertoire racine de la distribution décompressée :

shell> cd DBI-VERSION

3. Construisez la distribution et compilez tout :

shell> perl Makefile.PL
shell> make
shell> make test
shell> make install

La commande make test est importante, car elle vérifie que le module fonctionne. Notez que quand vous exécutez cette commande durant l'installation de Msql-Mysql-modules pour tester le code de l'interface, le serveur MySQL doit être en marche sinon le test échouera.

Il est bon de reconstruire et réinstaller la distribution Msql-Mysql-modules à chaque fois que vous réinstallez une nouvelle version de MySQL, particulièrement si vous avez des problèmes avec vos scripts DBI après avoir mis à jour MySQL.

Si vous n'avez pas le droit d'installer des modules Perl dans le dossier système ou que vous voulez installer des modules locaux de Perl, la référence suivante pourra vous aider : http://www.iserver.com/support/contrib/perl5/modules.html

Regardez le paragraphe « Installing New Modules that Require Locally Installed Modules. »

2-9-2 - Installer ActiveState Perl sur Windows

Pour installer le module DBD MySQL avec ActiveState Perl sous Windows, vous devez faire ce qui suit.

- Obtenez ActiveState Perl à partir de http://www.activestate.com/Products/ActivePerl/ et installez-le.

- Ouvrez un terminal DOS.

- Si requis, définissez la variable HTTP_proxy. Par exemple, vous pouvez faire :

set HTTP_proxy=my.proxy.com:3128

- Démarrez le programme PPM :

C:\> c:\perl\bin\ppm.pl

- Installez DBI, si ce n'est pas déjà fait :

ppm> install DBI

- Si cela fonctionne, exécutez la commande suivante :

install \
ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd

Ce qui suit devrait fonctionner avec la version 5.6 d'ActiveState Perl.

Si ce qui précède ne veut pas fonctionner, vous devez à la place installer le pilote MyODBC et vous connecter au serveur MySQL via ODBC :

use DBI;
$dbh= DBI->connect("DBI:ODBC:$dsn","$utilisateur","$motdepasse") ||
die "Obtenu l'erreur $DBI::errstr lors de la connexion à $dsn\n";

2-9-3 - Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

Si Perl vous informe qu'il ne peut trouver le module ../mysql/mysql.so, il se trouve probablement que Perl n'arrive pas à trouver la bibliothèque partagée libmysqlclient.so.

Vous pouvez corriger cela en suivant l'une des méthodes suivantes :

- compilez la distribution Msql-Mysql-modules avec perl Makefile.PL -static -config au lieu de perl Makefile.PL ;

- copiez libmysqlclient.so dans le dossier où se situent vos autres bibliothèques partagées (souvent /usr/lib ou /lib) ;

- modifiez l'option -L utilisée pour compiler DBD::mysql pour refléter le chemin correct de libmysqlclient.so ;

- sous Linux vous pouvez ajouter le chemin vers le dossier dans lequel se trouve libmysqlclient.so au fichier /etc/ld.so.conf ;

- ajoutez le chemin complet vers le dossier où se situe libmysqlclient.so à la variable d'environnement LD_RUN_PATH.

Notez que vous aurez aussi besoin de modifier les options -L s'il y a d'autres bibliothèques que le linker ne peut trouver. Par exemple, si le linker ne peut trouver libc comme il est dans /lib et que la commande de link spécifie -L/usr/lib, modifiez l'option -L en -L/lib ou ajoutez l'option -L/lib à la commande de link existante.

Si vous obtenez l'erreur suivante de DBD-mysql, vous utilisez probablement gcc (ou un vieux binaire compilé avec gcc) :

/usr/bin/perl: can't resolve symbol '__moddi3'
/usr/bin/perl: can't resolve symbol '__divdi3'

Ajoutez -L/usr/lib/gcc-lib/... -lgcc à la commande de liaison lorsque la bibliothèque mysql.so est construite (vérifiez l'affichage de make concernant mysql.so quand vous compilez le client Perl). L'option -L doit spécifier le chemin vers le dossier où se situe libgcc.a sur votre système.

Une autre cause du problème peut être que Perl et MySQL ne sont pas tous deux compilés avec gcc. Dans ce cas-là, vous devrez faire en sorte qu'ils le soient.

Si vous obtenez les erreurs suivantes de la part de Msql-Mysql-modules quand vous exécutez ces tests :

t/00base............install_driver(mysql) failed:
Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql:
../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol:
uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.

cela signifie que vous avez besoin d'inclure la bibliothèque dynamique, -lz, dans la ligne de liaison. Cela peut se faire en changeant ce qui suit dans lib/DBD/mysql/Install.pm :

$sysliblist .= " -lm";

en

$sysliblist .= " -lm -lz";

Après cela, vous devez exécuter 'make realclean' et reprendre l'installation dès le début.

Si vous voulez installer DBI sur SCO, vous devez éditer le fichier Makefile de DBI-xxx et chaque sous-dossier.

Notez que gcc doit être en version 2.95.2 ou plus récente :

ANCIEN:                               NOUVEAU:
CC = cc                               CC = gcc
CCCDLFLAGS = -KPIC -W1,-Bexport       CCCDLFLAGS = -fpic
CCDLFLAGS = -wl,-Bexport              CCDLFLAGS =

LD = ld                               LD = gcc -G -fpic
LDDLFLAGS = -G -L/usr/local/lib       LDDLFLAGS = -L/usr/local/lib
LDFLAGS = -belf -L/usr/local/lib      LDFLAGS = -L/usr/local/lib

LD = ld                               LD = gcc -G -fpic
OPTIMISE = -Od                        OPTIMISE = -O1

OLD:
CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include

NEW:
CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include

Ceci est dû au fait que le chargeur dynamique de Perl ne va pas charger les modules DBI, s'ils sont compilés avec icc ou cc.

Si vous voulez utiliser le module de Perl sur un système qui ne supporte pas les liaisons dynamiques (comme Caldera/SCO) vous pouvez générer une version statique de Perl incluant DBI et DBD-mysql. L'approche est de générer une version de Perl avec le code de DBI lié et de l'installer au-dessus de votre Perl courant. Puis vous utilisez cette version pour en créer à nouveau une autre qui comporte le code de DBD lié et d'installer cette version-ci.

Sur Caldera (SCO), vous devez définir les variables d'environnement suivantes :

shell> LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib

ou :

shell> LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\
/usr/progressive/lib:/usr/skunk/lib
shell> LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\
/usr/progressive/lib:/usr/skunk/lib
shell> MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:\
/usr/skunk/man:

D'abord, créez un Perl incluant un DBI lié statiquement en exécutant des commandes dans le dossier où se situe votre distribution DBI :

shell> perl Makefile.PL -static -config
shell> make
shell> make install
shell> make perl

Ensuite, vous devez installer le nouveau Perl. Les affichages de make perl vous indiqueront les commandes make exactes que vous aurez besoin d'exécuter pour faire l'installation. Sur Caldera (SCO), il s'agit de make -f Makefile.aperl inst_perl MAP_TARGET=perl.

Puis, utilisez le Perl qui vient d'être créé pour en créer un nouveau qui inclut un DBD::mysql lié statiquement en exécutant ces commandes dans le dossier où votre distribution de Msql-Mysql-modules se situe :

shell> perl Makefile.PL -static -config
shell> make
shell> make install
shell> make perl

Finalement, vous devez installer ce nouveau Perl. Une fois de plus, l'affichage de make perl vous indiquera la commande à utiliser.

3 - Tutoriels d'introduction

Ce chapitre fournit un tutoriel d'introduction à MySQL en montrant comment utiliser le client mysql pour créer et utiliser une simple base de données. mysql (quelques fois nommé « moniteur terminal » ou juste « moniteur ») est un programme interactif qui vous permet de vous connecter à un serveur MySQL, exécuter des requêtes et voir les résultats. mysql peut aussi être utilisé en mode batch : vous placez vos requêtes dans un fichier, puis vous faites exécuter à mysql le contenu de ce fichier. Les deux manières d'utiliser mysql sont expliquées ici.

Pour voir une liste d'options fournies par mysql, invoquez-le avec l'option --help :

shell> mysql --help

Ce chapitre suppose que mysql est installé sur votre machine et qu'un serveur MySQL est disponible pour que vous vous y connectiez. Si ce n'est pas le cas, contactez votre administrateur MySQL. (Si vous êtes l'administrateur, vous aurez besoin de consulter d'autres sections de ce manuel.)

Ce chapitre décrit le processus d'installation et d'utilisation d'une base de données en entier. Si vous n'êtes intéressé que par l'accès à une base de données existante, vous pouvez sauter les sections décrivant la création de la base et des tables.

Ce chapitre n'est qu'un tutoriel, beaucoup de détails ne sont pas approfondis. Consultez les sections appropriées du manuel pour plus d'informations sur les sujets abordés.

3-1 - Connexion et déconnexion au serveur

Pour vous connecter au serveur, vous aurez dans la plupart des cas à fournir un nom d'utilisateur à MySQL, et, sûrement, un mot de passe. Si le serveur fonctionne sur une autre machine que la vôtre, vous devrez spécifier son adresse. Contactez votre administrateur pour connaître les paramètres à utiliser lors de la connexion (hôte, nom d'utilisateur, mot de passe à utiliser...). Une fois que vous aurez les bons paramètres, vous pourrez vous connecter de la façon suivante :

shell> mysql -h hote -u utilisateur -p
Enter password: ********

******** représente votre mot de passe, entrez-le lorsque mysql affiche Enter password:.

Si tout fonctionne, vous devrez voir quelques informations d'introduction suivies d'une invite de commande mysql> :

shell> mysql -h host -u user -p
Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 459 to server version: 3.22.20a-log

Type 'help' for help.

mysql>

L'invite vous dit que mysql attend que vous entriez des commandes.

Quelques installations de MySQL autorisent les connexions anonymes au serveur tournant sur l'hôte local. Si c'est le cas sur votre machine, vous devriez arriver à vous connecter à ce serveur en invoquant la commande mysql sans aucune option :

shell> mysql

Après vous être connecté avec succès, vous pouvez vous déconnecter à tout moment en entrant QUIT dans l'invite mysql> :

mysql> QUIT
Bye

Vous pouvez aussi le faire en appuyant sur Ctrl-D.

La plupart des exemples dans les sections suivantes supposent que vous êtes connecté au serveur. Cela se voit à l'invite mysql>.

3-2 - Entrer des requêtes

Assurez-vous d'être connecté au serveur, comme expliqué précédemment dans cette section. Faire ceci ne sélectionnera pas une base par lui-même, mais c'est normal. À ce stade, il est important de découvrir la façon dont sont publiées les requêtes, pour ensuite pouvoir créer des tables, y insérer et rechercher des données. Cette section décrit les principes de base pour entrer une commande, en utilisant plusieurs requêtes que vous pouvez essayer pour vous familiariser avec la façon dont mysql fonctionne.

Voilà une commande simple qui demande au serveur de vous donner son numéro de version et la date courante. Entrez-la comme suit, juste après l'invite mysql> puis pressez Enter :

mysql> SELECT VERSION(), CURRENT_DATE;
+--------------+--------------+
| VERSION()    | CURRENT_DATE |
+--------------+--------------+
| 3.22.20a-log | 1999-03-19   |
+--------------+--------------+
1 row in set (0.01 sec)
mysql>

La requête révèle plusieurs choses à propos de mysql.

- Une commande consiste normalement en une commande SQL suivie d'un point-virgule. (Il y a quelques cas ou le point-virgule n'est pas requis. QUIT, mentionnée plus tôt, en fait partie. Nous verrons les autres plus tard.)

- Lorsque vous entrez une commande, mysql l'envoie au serveur pour l'exécution et affiche le résultat, puis affiche un autre mysql> pour indiquer qu'il attend une autre commande.

- mysql affiche le résultat des requêtes dans une table (lignes et colonnes). La première ligne contient le nom des colonnes. Les lignes suivantes constituent le résultat de la requête. Normalement, les titres des colonnes sont les noms des champs des tables de la base de données que vous avez récupérées. Si vous récupérez la valeur d'une expression au lieu d'une colonne (comme dans l'exemple précédent), mysql nomme la colonne en utilisant l'expression elle-même.

- mysql vous indique combien de lignes ont été retournées et combien de temps d'exécution la requête a pris, ce qui vous donnera une approximation des performances du serveur. Ces valeurs sont imprécises, car elles représentent le temps logiciel (et non le temps processeur ou matériel), et qu'elles sont affectées par des facteurs tels que la charge du serveur ou l'accessibilité du réseau. (Dans un souci de brièveté, la ligne contenant « rows in set » n'est plus montrée dans les exemples suivants de ce chapitre.)

Les mots-clés peuvent être entrés sous n'importe quelle forme de casse. Les requêtes suivantes sont équivalentes :

mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;

Voilà une autre requête. Elle montre que vous pouvez utiliser mysql en tant que simple calculatrice :

mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
|    0.707107 |      25 |
+-------------+---------+

Les commandes vues jusqu'à présent ont été relativement courtes, et tenaient sur une seule ligne. Vous pouvez même entrer plusieurs requêtes sur une seule ligne. Il suffit de terminer chacune d'elles par un point-virgule :

mysql> SELECT VERSION(); SELECT NOW();
+--------------+
| VERSION()    |
+--------------+
| 3.22.20a-log |
+--------------+

+---------------------+
| NOW()               |
+---------------------+
| 1999-03-19 00:15:33 |
+---------------------+

Une commande ne doit pas être obligatoirement sur une seule ligne ; les commandes qui exigent plusieurs lignes ne sont pas un problème. mysql détermine où se situe la fin de votre commande en recherchant le point-virgule de terminaison, et pas l'extrémité de la commande entrée. (Dans d'autres termes, mysql accepte des formats libres d'entrée : il collecte les lignes entrées, mais ne les exécute qu'une fois le point-virgule trouvé.)

Voilà une seule requête sur plusieurs lignes :

mysql> SELECT
-> USER()
-> ,
-> CURRENT_DATE;
+--------------------+--------------+
| USER()             | CURRENT_DATE |
+--------------------+--------------+
| joesmith@localhost | 1999-03-18   |
+--------------------+--------------+

Dans cet exemple, notez comment l'invite change de mysql> à -> après avoir entré la première ligne d'une requête multiligne. C'est la façon dont mysql indique qu'il n'a pas vu de requête complète et qu'il attend la fin de celle-ci. L'invite est votre ami en vous fournissant la rétroactivité. Si vous utilisez cette rétroactivité, vous vous rendrez toujours compte de ce que mysql attend.

Si vous décidez d'annuler une commande que vous êtes en train de taper, faites-le en entrant \c :

mysql> SELECT
-> USER()
-> \c
mysql>

Ici aussi, portez votre attention sur l'invite. Elle se transforme à nouveau en mysql> après que vous avez entré \c, vous informant que mysql est prêt pour une nouvelle requête.

Le tableau suivant montre les différentes invites que vous pourrez voir et résume leur signification quant à l'état dans lequel se trouve mysql :

Invite

Signification

mysql>

Prêt pour une nouvelle commande.

->

En attente de la ou des lignes terminant la commande.

'>

En attente de la prochaine ligne collectant une chaîne commencée par un guillemet simple (''').

">

En attente de la prochaine ligne collectant une chaîne commencée par un guillemet double ('"').

`>

En attente de la prochaine ligne collectant une chaîne commencée par un guillemet oblique ('`').

Les commandes sur plusieurs lignes sont la plupart du temps des accidents, lorsque vous voulez faire une commande sur une seule ligne et que vous oubliez le point-virgule de fin. Dans ce cas, mysql attend la suite de votre saisie :

mysql> SELECT USER()
->

Si cela vous arrive (vous pensez que votre requête est complète, mais la seule réponse est l'invite ->), il est fort probable que mysql attende le point-virgule. Si vous ne notez pas ce que l'invite vous indique, vous pourriez patienter pendant longtemps avant de réaliser ce que vous devez faire. Entrez un point-virgule pour compléter la requête, et mysql devrait l'exécuter :

mysql> SELECT USER()
-> ;
+--------------------+
| USER()             |
+--------------------+
| joesmith@localhost |
+--------------------+

L'invite '> ainsi que "> apparaissent durant l'entrée de chaîne. Dans MySQL, vous pouvez écrire une chaîne entourée du caractère ''' ou bien '"' (par exemple, 'Bonjour' or "Au Revoir"), et mysql vous laisse entrer une chaîne qui peut être sur plusieurs lignes. Lorsque vous voyez une invite comme '> ou ">, cela signifie que vous avez entré une ligne contenant le caractère ''' ou '"', mais vous n'avez pas encore entré le caractère correspondant qui termine votre chaîne. C'est pratique si vous entrez réellement une chaîne à lignes multiples, mais est-ce probable ? Pas vraiment. Plus souvent, les invites '> et "> indiquent que vous avez, par inadvertance, oublié un caractère de fermeture. Par exemple :

mysql> SELECT * FROM ma_table WHERE nom = "Smith AND age < 30;
">

Si vous entrez cette requête SELECT, puis appuyez sur Enter et attendez le résultat, rien ne se passera. Au lieu de vous demander pourquoi la requête met si longtemps à s'exécuter, remarquez que l'invite de commande s'est transformée en ">. Cela indique que mysql attend de voir la fin d'une chaîne de caractères non terminée. (Voyez-vous l'erreur dans cette requête ? Il manque le second guillemet à la suite de "Smith.)

Que faire ? Le plus simple est d'annuler la commande. Toutefois, vous ne pouvez vous contenter de taper \c dans ce cas-là, car mysql l'interprète comme une partie de la chaîne qu'il est en train de collecter ! À la place, entrez le second guillemet (pour que mysql sache que vous avez fini la chaîne), puis entrez \c :

mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
"> "\c
mysql>

L'invite se change à nouveau en mysql>, indiquant que mysql est prêt pour une nouvelle requête.

Il est important de savoir ce que les invites '> et "> signifient, car si vous avez entré par erreur une chaîne non terminée, toutes les lignes suivantes que vous entrerez seront ignorées par mysql, même une ligne contenant QUIT ! Cela peut prêter à confusion, spécialement si vous ne savez pas que vous devez fournir le guillemet fermant avant de pouvoir annuler la commande courante.

3-3 - Création et utilisation d'une base de données

Maintenant que vous savez entrer des commandes, il est temps d'accéder à une base.

Supposons que vous avez plusieurs animaux chez vous (dans votre ménagerie) et que vous voulez garder diverses informations les concernant. Vous pouvez le faire en créant des tables pour stocker vos données et y charger vos informations. Vous pourrez alors répondre à différentes sortes de questions à propos de vos animaux en récupérant les données à partir des tables. Cette section vous montre comment :

- créer une base de données ;

- créer une table ;

- charger des données dans vos tables ;

- récupérer des données à partir des tables de différentes façons ;

- utiliser plusieurs tables.

La base de données de la ménagerie va être simple (délibérément), mais il n'est pas difficile de penser à des situations courantes de la vie où vous aurez à utiliser un tel type de base de données. Par exemple, une telle base pourrait être utilisée par un éleveur pour gérer sa boutique, ou par un vétérinaire pour garder des traces de ses patients. Une distribution de la ménagerie contenant quelques requêtes et des exemples de données utilisées dans la section suivante peut être trouvée sur le site web de MySQL. Les exemples sont disponibles au format compressé tar (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz) ou au format Zip (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip).

Utilisez la commande SHOW pour trouver quelles bases existent déjà sur le serveur :

mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql    |
| test     |
| tmp      |
+----------+

La liste des bases de données est probablement différente sur votre machine, mais les bases mysql et test y figurent sûrement. La base mysql est requise, car elle gère les accès et les privilèges. La base test est souvent fournie pour que les utilisateurs y effectuent leurs tests.

Notez que vous ne pourrez voir toutes les bases de données si vous n'avez pas le privilège SHOW DATABASES. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

Si la base de données test existe, essayez d'y accéder :

mysql> USE test
Database changed

Notez que USE, comme QUIT, ne requiert pas de point-virgule. (Vous pouvez terminer ces commandes avec un point-virgule ; cela ne posera pas de problème.) La commande USE est spéciale d'un autre point de vue : elle doit être donnée sur une seule ligne.

Vous pouvez utiliser la base de données test (si vous y avez accès) pour les exemples qui suivent, mais tout ce que vous créerez dans cette base pourra être effacé par quiconque y a accès. Pour cette raison, vous feriez mieux de demander à votre administrateur MySQL la permission d'utiliser une base de données rien que pour vous. Supposez que vous voulez nommer la vôtre menagerie. L'administrateur a besoin d'exécuter une commande telle que :

mysql> GRANT ALL ON menagerie.* TO votre_nom_mysql;

où votre_nom_mysql est le nom d'utilisateur MySQL qui vous est assigné.

3-3-1 - Créer et sélectionner une base de données

Si l'administrateur vous a créé une base de données lors du paramétrage de vos droits, vous pouvez commencer à l'utiliser. Sinon, vous aurez besoin de la créer par vous-même :

mysql> CREATE DATABASE menagerie;

Sous Unix, les noms des bases de données sont sensibles à la casse (ce qui diffère des mots réservés de SQL), ce qui fait que vous devez toujours vous référer à votre base de données avec menagerie, non avec Menagerie, MENAGERIE, ou d'autres variantes. Cela est aussi valable pour les noms de tables. (Sous Windows, cette restriction n'est pas appliquée, même si vous devez vous référer à une table ou une base de la même façon dans une même requête).

La création d'une base de données ne la sélectionne pas pour l'utilisation ; vous devez le faire explicitement. Pour rendre menagerie la base courante, utilisez cette commande :

mysql> USE menagerie
Database changed

Votre base a besoin d'être créée juste une fois, mais vous devez la sélectionner pour l'utiliser, chaque fois que vous débutez une session mysql. Vous pouvez le faire en publiant une requête USE comme ci-dessus. Sinon, vous pouvez sélectionner la base directement dans la ligne de commande lorsque vous invoquez mysql. Vous devez juste spécifier son nom après les paramètres de connexion dont vous avez besoin. Par exemple :

shell> mysql -h hote -u utilisateur -p menagerie
Enter password: ********

Notez que menagerie n'est pas votre mot de passe dans la commande que nous venons de montrer. Si vous voulez le fournir dans la ligne de commande après l'option -p, vous devez le faire sans espace entre les deux (par exemple, tapez -pmonmotdepasse, et non -p monmotdepasse). Toutefois, mettre le mot de passe en ligne de commande n'est pas recommandé, car le faire permettrait à d'autres utilisateurs connectés sur votre machine de l'obtenir.

3-3-2 - Création d'une table

Créer la base de données est la partie facile, mais jusque-là elle est vide, comme vous le montre SHOW TABLES :

mysql> SHOW TABLES;
Empty set (0.00 sec)

La partie la plus difficile est le choix de la structure de la base de données : de quelles tables aurez-vous besoin et quelles colonnes devront figurer dans chacune d'elles ?

Vous voudrez une table qui contient un enregistrement pour chaque animal. On peut l'appeler la table animal, et elle devra contenir, au minimum, le nom de chaque animal. Puisque le nom tout seul n'est pas intéressant, la table devra contenir d'autres informations. Par exemple, si plus d'une personne de votre famille possède un animal, vous voudrez lister le nom du maître de chaque animal. Vous voudrez peut-être aussi enregistrer une description basique comme l'espèce ou le sexe.

Et pour l'âge ? C'est intéressant, mais n'est pas bon pour un stockage en base de données. L'âge change chaque jour, vous devrez donc mettre à jour vos enregistrements assez souvent. Il est préférable de stocker une valeur fixe, comme la date de naissance. Dans ce cas-là, à chaque fois que vous aurez besoin de l'âge, vous pourrez l'obtenir en faisant la différence entre la date courante et la date enregistrée. MySQL fournit des fonctions de calcul sur les dates, cela ne sera donc pas difficile. Enregistrer la date de naissance, au lieu de l'âge a d'autres avantages :

- vous pouvez utiliser la base de données pour des tâches, comme la génération d'un rappel pour les prochains anniversaires d'animaux. (Si vous trouvez que ce type de requêtes est quelque peu idiot, notez que c'est la même question que vous vous poseriez dans le contexte d'une base de données d'affaires pour identifier les clients à qui vous aurez besoin d'envoyer un message de vœux, pour cette touche informatiquement assistée d'humanisme.) ;

- vous pouvez calculer l'âge à partir d'autres dates que la date du jour. Par exemple, si vous stockez la date de la mort dans la base de données, vous pourrez facilement calculer l'âge qu'avait un animal à sa mort.

Vous trouverez probablement d'autres informations qui pourront être utiles dans la table animal, mais celles identifiées jusqu'à maintenant sont largement suffisantes pour l'instant : nom, maître, espèce, sexe, naissance et mort.

Utilisez une requête CREATE TABLE pour spécifier la structure de votre table :

mysql> CREATE TABLE animal (nom VARCHAR(20), maitre VARCHAR(20),
-> espece VARCHAR(20), sexe CHAR(1), naissance DATE, mort DATE);

VARCHAR est un bon choix pour les colonnes nom, maitre, et espece, car leur valeur varie en longueur. La longueur de ces colonnes ne doit pas nécessairement être la même, et n'a pas besoin d'être forcément 20. Vous pouvez choisir une taille entre 1 et 255, celle qui vous semblera la plus raisonnable. (Si vous faites un mauvais choix et que vous vous apercevez plus tard que vous avez besoin d'un champ plus long, MySQL fournit la commande ALTER TABLE.)

Le sexe des animaux peut être représenté de plusieurs façons, par exemple, "m" et "f", ou bien "male" et "femelle". Il est plus simple d'utiliser les caractères simples "m" et "f".

L'utilisation du type de données DATE pour les colonnes naissance et mort est un choix plutôt judicieux.

Maintenant que vous avez créé une table, SHOW TABLES devrait produire de l'affichage :

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| animal              |
+---------------------+

Pour vérifier que la table a été créée de la façon que vous vouliez, utilisez la commande DESCRIBE :

mysql> DESCRIBE animal;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| nom       | varchar(20) | YES  |     | NULL    |       |
| maitre    | varchar(20) | YES  |     | NULL    |       |
| espece    | varchar(20) | YES  |     | NULL    |       |
| sexe      | char(1)     | YES  |     | NULL    |       |
| naissance | date        | YES  |     | NULL    |       |
| mort      | date        | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+

Vous pouvez utiliser DESCRIBE quand vous voulez, par exemple, si vous avez oublié le nom des colonnes dans votre table ou leur type.

3-3-3 - Charger des données dans une table

Après la création de votre table, vous aurez besoin de la remplir. Les commandes LOAD DATA et INSERT sont utiles pour cela.

Supposons que les enregistrements de vos animaux peuvent être décrits comme suit. (Observez que MySQL attend les dates au format YYYY-MM-DD; cela peut différer de ce à quoi vous êtes habitué.)

nom

maître

races

sexe

naissance

mort

Fluffy

Harold

chat

f

1993-02-04

Claws

Gwen

chat

m

1994-03-17

Buffy

Harold

chien

f

1989-05-13

Fang

Benny

chien

m

1990-08-27

Bowser

Diane

chien

m

1998-08-31

1995-07-29

Chirpy

Gwen

oiseau

f

1998-09-11

Whistler

Gwen

oiseau

1997-12-09

Slim

Benny

serpent

m

1996-04-29

Puisque vous commencez avec une table vide, il est facile de la remplir en créant un fichier texte contenant une ligne pour chaque animal que vous avez, puis charger son contenu à l'aide d'une seule commande.

Vous pouvez créer un fichier animal.txt contenant un enregistrement par ligne, avec les valeurs séparées par des tabulations, et ordonnées comme les champs l'étaient dans la requête CREATE TABLE. Pour les données manquantes (comme un sexe inconnu ou la date de mort d'un animal toujours en vie), vous pouvez utiliser les valeurs NULL. Pour les représenter dans votre fichier texte, utilisez \N. Par exemple, l'enregistrement de Whistler l'oiseau ressemblera à ça (l'espace entre les valeurs est une tabulation) :

nom

maître

race

sexe

naissance

mort

Whistler

Gwen

bird

\N

1997-12-09

\N

Pour charger le fichier animal.txt dans la table animal, utilisez cette commande :

mysql> LOAD DATA LOCAL INFILE "animal.txt" INTO TABLE animal;

Notez que si vous créez un fichier sur Windows, avec un éditeur qui utilise des caractères de lignes comme \r\n, vous devez utiliser :

mysql> LOAD DATA LOCAL INFILE "animal.txt" INTO TABLE animal;

Vous pouvez spécifier la valeur du séparateur de colonnes et le marqueur de fin de lignes explicitement dans la commande LOAD DATA si vous le voulez, mais les valeurs par défaut sont la tabulation et le retour à la ligne. Ceux-là sont suffisants pour que la commande lise le fichier animal.txt correctement.

Si la commande échoue, il est probable que votre installation MySQL n'a pas la possibilité d'accéder aux fichiers. Voyez Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL » pour plus d'informations sur comment modifier cela.

Lorsque vous voulez ajouter des enregistrements un par un, la commande INSERT est utile. Dans sa forme la plus simple, où vous spécifiez une valeur pour chaque colonne, dans l'ordre où les colonnes sont listées dans la requête CREATE TABLE. Supposons que Diane achète un nouveau hamster nommé Puffball. Vous pourriez ajouter ce nouvel enregistrement en utilisant un INSERT de la façon suivante :

mysql> INSERT INTO animal
-> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);

Notez que les chaînes de caractères et les valeurs de dates sont spécifiées en tant que chaînes protégées par des guillemets. De plus, avec INSERT vous pouvez insérer la valeur NULL directement pour représenter une valeur manquante. Vous n'utilisez pas \N comme vous le faites avec LOAD DATA.

À partir de cet exemple, vous devriez être capable de voir qu'il y a beaucoup plus de commandes à taper lorsque vous utilisez la commande INSERT au lieu de LOAD DATA.

3-3-4 - Récupérer des informations à partir d'une table

La commande SELECT est utilisée pour récupérer des informations à partir d'une table. La forme usuelle est :

SELECT quoi_selectionner
FROM quel_table
WHERE conditions_a_satisfaire

quoi_selectionner indique ce que vous voulez voir. Cela peut être une liste de colonnes, ou * pour indiquer « toutes les colonnes ». quel_table indique la table à partir de laquelle récupérer les données. La clause WHERE est optionnelle. Si elle est présente, conditions_a_satisfaire spécifie les conditions que les lignes doivent satisfaire pour être sélectionnées.

3-3-4-1 - Sélectionner toutes les données

La plus simple forme de SELECT récupère toutes les données d'une table :

mysql> SELECT * FROM animal;
+----------+--------+---------+------+------------+------------+
| nom      | maitre | espece  | sexe | naissance  | mort       |
+----------+--------+---------+------+------------+------------+
| Fluffy   | Harold | chat    | f    | 1993-02-04 | NULL       |
| Claws    | Gwen   | chat    | m    | 1994-03-17 | NULL       |
| Buffy    | Harold | chien   | f    | 1989-05-13 | NULL       |
| Fang     | Benny  | chien   | m    | 1990-08-27 | NULL       |
| Bowser   | Diane  | chien   | m    | 1998-08-31 | 1995-07-29 |
| Chirpy   | Gwen   | oiseau  | f    | 1998-09-11 | NULL       |
| Whistler | Gwen   | oiseau  | NULL | 1997-12-09 | NULL       |
| Slim     | Benny  | serpent | m    | 1996-04-29 | NULL       |
| Puffball | Diane  | hamster | f    | 1999-03-30 | NULL       |
+----------+--------+---------+------+------------+------------+

Cette forme de SELECT est utile si vous voulez récupérer la table entière. Par exemple, après l'avoir juste remplie avec vos données d'origine. Il apparaît alors qu'une erreur s'était glissée dans votre fichier de données : Bowser a l'air d'être né après sa mort ! En consultant le papier original de son pedigree, vous trouvez que la date correcte est 1989 et non pas 1998.

Il y a au moins deux façons de corriger cela :

- corriger le fichier animal.txt pour corriger l'erreur, puis vider et recharger à nouveau la table en utilisant DELETE et LOAD DATA :

mysql> SET AUTOCOMMIT=1;  # Utilisé pour une recréation rapide de la table
mysql> DELETE FROM animal;
mysql> LOAD DATA LOCAL INFILE "animal.txt" INTO TABLE animal;

Toutefois, si vous choisissez cette méthode, vous devrez aussi rentrer à nouveau l'enregistrement de Puffball ;

- corriger uniquement l'enregistrement erroné avec une requête UPDATE :

mysql> UPDATE animal SET naissance = "1989-08-31" WHERE nom = "Bowser";

Comme nous l'avons montré, il est facile de récupérer toutes les données d'une table. Toutefois, vous ne voudrez sûrement pas le faire, surtout si la table devient imposante. À la place, vous serez plus intéressé par répondre à une question particulière, dans ce cas-là, vous spécifiez quelques contraintes pour les informations que vous voulez. Regardons quelques requêtes de sélection qui répondent à des questions à propos de vos animaux.

3-3-4-2 - Sélectionner des lignes particulières

Vous pouvez sélectionner des lignes particulières de votre table. Par exemple, si vous voulez vérifier la modification que vous avez effectuée sur la date de naissance de Bowser, sélectionnez son enregistrement comme suit :

mysql> SELECT * FROM animal WHERE nom = "Bowser";
+--------+--------+--------+------+------------+------------+
| nom    | maitre | espece | sexe | naissance  | mort       |
+--------+--------+--------+------+------------+------------+
| Bowser | Diane  | chien  | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+--------+------+------------+------------+

L'affichage confirme que la date est correcte maintenant : 1989, et non 1998.

La comparaison des chaînes de caractères se fait normalement avec insensibilité à la casse, vous pouvez donc spécifier le nom "bowser", "BOWSER", etc. Le résultat de la requête sera le même.

Vous pouvez spécifier des conditions sur toutes les colonnes, pas seulement nom. Par exemple, si vous voulez savoir quels animaux sont nés après 1998, testez la colonne naissance :

mysql> SELECT * FROM animal WHERE naissance >= "1998-1-1";
+----------+--------+---------+------+------------+-------+
| nom      | maitre | espece  | sexe | naissance  | mort  |
+----------+--------+---------+------+------------+-------+
| Chirpy   | Gwen   | oiseau  | f    | 1998-09-11 | NULL  |
| Puffball | Diane  | hamster | f    | 1999-03-30 | NULL  |
+----------+--------+---------+------+------------+-------+

Vous pouvez combiner plusieurs conditions, par exemple, pour trouver les chiennes :

mysql> SELECT * FROM animal WHERE espece = "chien" AND sexe = "f";
+-------+--------+--------+------+------------+-------+
| nom   | maitre | espece | sexe | naissance  | mort  |
+-------+--------+--------+------+------------+-------+
| Buffy | Harold | chien  | f    | 1989-05-13 | NULL  |
+-------+--------+--------+------+------------+-------+

La requête précédente utilise l'opérateur logique AND. L'opérateur OR existe aussi :

mysql> SELECT * FROM animal WHERE espece = "serpent" OR espece = "oiseau";
+----------+--------+---------+------+------------+-------+
| nom      | maitre | espece  | sexe | naissance  | mort  |
+----------+--------+---------+------+------------+-------+
| Chirpy   | Gwen   | oiseau  | f    | 1998-09-11 | NULL  |
| Whistler | Gwen   | oiseau  | NULL | 1997-12-09 | NULL  |
| Slim     | Benny  | serpent | m    | 1996-04-29 | NULL  |
+----------+--------+---------+------+------------+-------+

AND et OR peuvent être utilisés ensemble. Si vous le faites, une bonne idée est d'utiliser les parenthèses pour indiquer comment les conditions doivent être regroupées :

mysql> SELECT * FROM animal WHERE (espece = "chat" AND sexe = "m")
-> OR (espece = "chien" AND sexe = "f");
+-------+--------+--------+------+------------+-------+
| nom   | maitre | espece | sexe | naissance  | mort  |
+-------+--------+--------+------+------------+-------+
| Claws | Gwen   | chat   | m    | 1994-03-17 | NULL  |
| Buffy | Harold | chien  | f    | 1989-05-13 | NULL  |
+-------+--------+--------+------+------------+-------+

3-3-4-3 - Sélectionner des colonnes particulières

Si vous ne voulez pas voir les lignes entières de votre table, nommez les colonnes qui vous intéressent, en les séparant par des virgules. Par exemple, si vous voulez savoir quand vos animaux sont nés, sélectionnez les colonnes nom et naissance :

mysql> SELECT nom, naissance FROM animal;
+----------+------------+
| nom      | naissance  |
+----------+------------+
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Buffy    | 1989-05-13 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+

Pour trouver qui possède les animaux, utilisez cette requête :

mysql> SELECT maitre FROM animal;
+--------+
| maitre |
+--------+
| Harold |
| Gwen   |
| Harold |
| Benny  |
| Diane  |
| Gwen   |
| Gwen   |
| Benny  |
| Diane  |
+--------+

Toutefois, remarquez que la requête récupère le champ maitre de chaque enregistrement, et certains apparaissent plus d'une fois. Pour minimiser l'affichage, récupérez chaque résultat unique une seule fois en ajoutant le mot-clé DISTINCT :

mysql> SELECT DISTINCT maitre FROM animal;
+--------+
| maitre |
+--------+
| Benny  |
| Diane  |
| Gwen   |
| Harold |
+--------+

Vous pouvez utiliser une clause WHERE pour combiner la sélection des lignes avec celle des colonnes. Par exemple, pour obtenir les dates de naissance des chiens et chats uniquement, utilisez cette requête :

mysql> SELECT nom, espece, naissance FROM animal
-> WHERE espece = "chien" OR espece = "chat";
+--------+--------+------------+
| nom    | espece | naissance  |
+--------+--------+------------+
| Fluffy | chat   | 1993-02-04 |
| Claws  | chat   | 1994-03-17 |
| Buffy  | chien  | 1989-05-13 |
| Fang   | chien  | 1990-08-27 |
| Bowser | chien  | 1989-08-31 |
+--------+--------+------------+

3-3-4-4 - Trier les enregistrements

Vous avez sûrement noté dans les exemples précédents que les lignes de résultat sont affichées sans ordre particulier. Cependant, il est souvent plus facile d'examiner les résultats lorsqu'ils sont triés d'une manière significative. Pour trier un résultat, vous devez utiliser une clause ORDER BY.

L'exemple suivant présente les dates d'anniversaire des animaux, triées par date :

mysql> SELECT nom, naissance FROM animal ORDER BY naissance;
+----------+------------+
| nom      | naissance  |
+----------+------------+
| Buffy    | 1989-05-13 |
| Bowser   | 1989-08-31 |
| Fang     | 1990-08-27 |
| Fluffy   | 1993-02-04 |
| Claws    | 1994-03-17 |
| Slim     | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy   | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+

Sur les noms de colonnes, le tri, comme toutes les opérations de comparaison, est normalement exécuté sans tenir compte de la casse. Cela signifie que l'ordre sera indéfini pour les colonnes qui sont identiques, excepté leur casse. Vous pouvez forcer le tri sensible à la casse en utilisant la clause BINARY : ORDER BY BINARY(champ).

Pour trier dans l'ordre inverse, ajoutez le mot-clé DESC (décroissant) au nom de la colonne à trier :

mysql> SELECT nom, naissance FROM animal ORDER BY naissance DESC;
+----------+------------+
| nom      | naissance  |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy   | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim     | 1996-04-29 |
| Claws    | 1994-03-17 |
| Fluffy   | 1993-02-04 |
| Fang     | 1990-08-27 |
| Bowser   | 1989-08-31 |
| Buffy    | 1989-05-13 |
+----------+------------+

Vous pouvez effectuer un tri sur plusieurs colonnes. Par exemple, pour trier par types d'animaux, puis par la date d'anniversaire des animaux, en plaçant les plus jeunes en premier, utilisez la requête suivante :

mysql> SELECT nom, espece, naissance FROM animal ORDER BY espece, naissance DESC;
+----------+---------+------------+
| nom      | espece  | naissance  |
+----------+---------+------------+
| Chirpy   | oiseau  | 1998-09-11 |
| Whistler | oiseau  | 1997-12-09 |
| Claws    | chat    | 1994-03-17 |
| Fluffy   | chat    | 1993-02-04 |
| Fang     | chien   | 1990-08-27 |
| Bowser   | chien   | 1989-08-31 |
| Buffy    | chien   | 1989-05-13 |
| Puffball | hamster | 1999-03-30 |
| Slim     | serpent | 1996-04-29 |
+----------+---------+------------+

Notez que le mot-clé DESC est appliqué uniquement au nom de la colonne qui le précède (naissance) ; les valeurs espece continuent à être triées dans l'ordre croissant.

3-3-4-5 - Calcul sur les dates

MySQL fournit plusieurs fonctions que vous pouvez utiliser pour effectuer des calculs sur les dates, par exemple, pour calculer l'âge ou pour extraire des parties de date.

Pour déterminer quel âge a chacun de vos animaux, vous devez calculer la différence entre l'année en cours et l'année de naissance, puis soustraire à la date courante si la date du jour se produit plus tôt dans l'année civile que la date de naissance. La requête suivante montre, pour chaque animal, la date de naissance, la date courante, ainsi que l'âge en années.

mysql> SELECT nom, naissance, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(naissance))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(naissance,5))
-> AS age
-> FROM animal;
+----------+------------+--------------+------+
| nom      |naissance   | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
+----------+------------+--------------+------+

Ici, YEAR() extrait l'année de la date et RIGHT() extrait les 5 caractères les plus à droite de la date qui représentent MM-DD (année civile). La partie de l'expression qui compare les valeurs de MM-DD évalue à 1 ou à 0, qui ajustent la différence d'année à la baisse, si CURRENT_DATE se produit plus au début de l'année que la naissance. L'expression complète est un peu plus fine en utilisant un alias (age) pour produire un nom de colonne un peu plus significatif.

La requête fonctionne, mais le résultat pourrait être lu plus facilement si les lignes étaient présentées dans le même ordre. Cela peut être obtenu en ajoutant une clause ORDER BY nom pour trier le résultat par nom :

mysql> SELECT nom, naissance, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(naissance))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(naissance,5))
-> AS age
-> FROM animal ORDER BY nom;
+----------+------------+--------------+------+
| nom      |naissance   | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
+----------+------------+--------------+------+

Pour trier le résultat par l'age plutôt que par le nom, utilisez simplement une clause ORDER BY différente :

mysql> SELECT nom, naissance, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(naissance))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(naissance,5))
-> AS age
-> FROM animal ORDER BY age;
+----------+------------+--------------+------+
| nom      |naissance   | CURRENT_DATE | age  |
+----------+------------+--------------+------+
| Chirpy   | 1998-09-11 | 2001-08-29   |    2 |
| Puffball | 1999-03-30 | 2001-08-29   |    2 |
| Whistler | 1997-12-09 | 2001-08-29   |    3 |
| Slim     | 1996-04-29 | 2001-08-29   |    5 |
| Claws    | 1994-03-17 | 2001-08-29   |    7 |
| Fluffy   | 1993-02-04 | 2001-08-29   |    8 |
| Fang     | 1990-08-27 | 2001-08-29   |   11 |
| Bowser   | 1989-08-31 | 2001-08-29   |   11 |
| Buffy    | 1989-05-13 | 2001-08-29   |   12 |
+----------+------------+--------------+------+

Une requête similaire peut être utilisée pour déterminer l'âge qu'avait un animal à sa mort. Vous déterminez les animaux qui le sont en regardant les valeurs mort qui ne valent pas NULL. Alors, pour ceux dont la valeur est non NULL, calculez la différence entre la mort et la naissance :

mysql> SELECT nom, naissance, mort,
-> (YEAR(mort)-YEAR(naissance)) - (RIGHT(mort,5)<RIGHT(naissance,5))
-> AS age
-> FROM animal WHERE mort IS NOT NULL ORDER BY age;
+--------+------------+------------+------+
| nom    |naissance   | mort       | age  |
+--------+------------+------------+------+
| Bowser | 1989-08-31 | 1995-07-29 |    5 |
+--------+------------+------------+------+

Cette requête utilise mort IS NOT NULL plutôt que mort <> NULL parce que NULL est une valeur spéciale. Cela sera expliqué plus tard. Voir Section 3.3.4.6, « Travailler avec la valeur NULL ».

Vous désirez savoir quels sont les animaux qui ont leur anniversaire le mois prochain ? Pour effectuer ce type de calculs, l'année et le jour ne sont pas utiles ; vous voulez simplement extraire le mois de la colonne naissance. MySQL fournit plusieurs fonctions d'extraction de parties de dates, comme YEAR(), MONTH(), et DAYOFMONTH(). MONTH() est la fonction appropriée dans notre cas. Pour voir comment cette fonction travaille, exécutez une requête simple qui retourne la naissance et le MONTH(naissance) :

mysql> SELECT nom, naissance, MONTH(naissance) FROM animal;
+----------+------------+------------------+
| nom      | naissance  | MONTH(naissance) |
+----------+------------+------------------+
| Fluffy   | 1993-02-04 |                2 |
| Claws    | 1994-03-17 |                3 |
| Buffy    | 1989-05-13 |                5 |
| Fang     | 1990-08-27 |                8 |
| Bowser   | 1989-08-31 |                8 |
| Chirpy   | 1998-09-11 |                9 |
| Whistler | 1997-12-09 |               12 |
| Slim     | 1996-04-29 |                4 |
| Puffball | 1999-03-30 |                3 |
+----------+------------+------------------+

Trouver les animaux qui ont leur anniversaire dans le mois suivant est aisé. Supposez que le mois courant est avril. Donc, la valeur du mois est 4 et vous cherchez les animaux nés en mai (mois 5) comme ceci :

mysql> SELECT nom, naissance FROM animal WHERE MONTH(naissance) = 5;
+-------+------------+
| nom   |naissance   |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+

Il y a une petite complication si le mois courant est décembre, bien sûr. Vous ne pouvez pas uniquement ajouter 1 au numéro du mois courant (12) et chercher les animaux qui sont nés le mois numéro 13, parce qu'il n'existe pas. À la place, vous cherchez les animaux nés en janvier (mois numéro 1).

Vous pouvez toujours écrire une requête qui fonctionne quel que soit le mois courant. Comme cela, vous n'avez pas à utiliser un numéro de mois particulier dans votre requête. DATE_ADD() vous permet d'ajouter un intervalle de temps à une date donnée. Si vous ajoutez un mois à la valeur de NOW(), et que vous extrayez le mois à l'aide de MONTH(), le résultat produit le mois dans lequel vous devez chercher un anniversaire :

mysql> SELECT nom, naissance FROM animal
-> WHERE MONTH(naissance) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));

Une manière différente d'arriver au même résultat est d'ajouter 1 pour trouver le mois prochain après le mois courant (après l'usage de la fonction (MOD) pour ajouter à la valeur du mois la valeur 0 s'il est de 12) :

mysql> SELECT nom, naissance FROM animal
-> WHERE MONTH(naissance) = MOD(MONTH(NOW()), 12) + 1;

Notez que MONTH retourne un nombre entre 1 et 12. MOD(quelquechose,12) retourne un nombre entre 0 et 11. Donc, l'addition doit être faite après l'utilisation de la fonction MOD(), sinon, nous aurions un intervalle entre novembre (11) et janvier (1).

3-3-4-6 - Travailler avec la valeur NULL

La valeur NULL peut être surprenante jusqu'à ce que vous vous y habituiez. Conceptuellement, NULL représente une valeur qui manque, ou une valeur inconnue, et elle est traitée différemment des autres valeurs. Pour tester la présence de la valeur NULL, vous ne pouvez pas utiliser les opérateurs arithmétiques habituels comme =, <, ou <>. Pour le voir, il suffit d'essayer ceci :

mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
|     NULL |      NULL |     NULL |     NULL |
+----------+-----------+----------+----------+

Clairement, vous n'obtiendrez aucun résultat valable pour ces comparaisons. Utilisez les opérateurs IS NULL et IS NOT NULL à la place :

mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
|         0 |             1 |
+-----------+---------------+

Notez que deux NULL sont considérés comme égaux lors que vous utilisez la clause GROUP BY.

Avec MySQL, 0 et NULL représentent le booléen faux, et tout le reste représente le booléen vrai. La valeur par défaut du booléen vrai issue d'une comparaison est 1.

Lorsque vous utilisez la clause ORDER BY, les valeurs NULL sont toujours triées en premier, même si vous utilisez l'attribut DESC.

Ce traitement particulier de NULL explique pourquoi, dans la section précédente, il était nécessaire de déterminer quel animal ne vivait plus en utilisant la fonction mort IS NOT NULL au lieu de mort <> NULL.

3-3-4-7 - Recherche de modèles

MySQL fournit le standard SQL des recherches de modèles, basé sur une extension des expressions régulières similaires à celles utilisées par les utilitaires Unix comme vi, grep, et sed.

La recherche de modèles SQL vous permet d'utiliser le caractère '_' pour trouver n'importe quel caractère et le caractère '%' pour trouver un nombre arbitraire de caractères (y compris aucun caractère). Dans MySQL, la recherche de modèles est insensible à la casse par défaut. Quelques exemples vous sont présentés ici.

Notez que vous n'utilisez ni = ni <> lorsque vous utilisez la recherche de modèles SQL ; utilisez les opérateurs de comparaison LIKE ou NOT LIKE à la place.

Pour trouver les noms commençant par la lettre 'b' :

mysql> SELECT * FROM animal WHERE nom LIKE "b%";
+--------+--------+--------+------+------------+------------+
| nom    | maitre | espece | sexe | naissance  | mort       |
+--------+--------+--------+------+------------+------------+
| Buffy  | Harold | chien  | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | chien  | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+--------+------+------------+------------+

Pour trouver les noms finissant par 'fy' :

mysql> SELECT * FROM animal WHERE nom LIKE "%fy";
+--------+--------+---------+------+------------+-------+
| nom    | maitre | espece  | sexe | naissance  | mort  |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | chat    | f    | 1993-02-04 | NULL  |
| Buffy  | Harold | chien   | f    | 1989-05-13 | NULL  |
+--------+--------+---------+------+------------+-------+

Pour trouver les noms contenant le caractère 'w' :

mysql> SELECT * FROM animal WHERE nom LIKE "%w%";
+----------+--------+---------+------+------------+------------+
| nom      | maitre | espece  | sexe | naissance  | mort       |
+----------+--------+---------+------+------------+------------+
| Claws    | Gwen   | chat    | m    | 1994-03-17 | NULL       |
| Bowser   | Diane  | chien   | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen   | oiseaux | NULL | 1997-12-09 | NULL       |
+----------+--------+---------+------+------------+------------+

Pour trouver les noms contenant exactement 5 caractères, utilisez le caractère de recherche '_' :

mysql> SELECT * FROM animal WHERE nom LIKE "_____";
+-------+--------+--------+------+------------+------+
| nom   | maitre | espece | sexe | naissance  | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen   | chat   | m    | 1994-03-17 | NULL |
| Buffy | Harold | chien  | f    | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

L'autre type de recherche de modèles fourni par MySQL utilise les expressions régulières étendues. Lorsque vous testez une recherche avec ce type de modèle, utilisez les opérateurs REGEXP et NOT REGEXP (ou RLIKE et NOT RLIKE qui sont des synonymes).

Quelques caractéristiques des expressions régulières étendues sont :

- le caractère '.' trouve n'importe quel caractère ;

- une classe de caractères '[...]' trouve n'importe quel caractère contenu entre les crochets. Par exemple, la classe de caractères '[abc]' trouve le caractère 'a', 'b', ou 'c'. Pour définir un intervalle de caractères, utilisez un trait d'union. La classe de caractères '[a-z]' trouvera n'importe quelle lettre minuscule, tout comme la classe '[0-9]' trouvera n'importe quel nombre ;

- le caractère '*' trouvera aucune ou plus d'instances du caractère qui le précède. Par exemple, 'x*' trouvera n'importe quel nombre de fois le caractère 'x', '[0-9]*' trouvera n'importe quel nombre et '.*' trouvera n'importe quel nombre de fois n'importe quel caractère ;

- le modèle est trouvé s'il se produit n'importe où dans la valeur testée. (Les modèles SQL ne sont trouvés que s'ils sont présents en valeur entière.) ;

- pour ancrer un modèle de sorte qu'il soit trouvé au début ou à la fin de valeur testée, utilisez '^' au début ou bien '$' à la fin du modèle.

Pour démontrer comment les expressions régulières fonctionnent, les requêtes LIKE vues précédemment ont été réécrites pour utiliser REGEXP.

Pour trouver les noms qui commencent par la lettre 'b', utilisez '^' pour trouver le début du nom :

mysql> SELECT * FROM animal WHERE nom REGEXP "^b";
+--------+--------+--------+------+------------+------------+
| nom    | maitre | espece | sexe | naissance  | mort       |
+--------+--------+--------+------+------------+------------+
| Buffy  | Harold | chien  | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | chien  | m    | 1989-08-31 | 1995-07-29 |
+--------+--------+--------+------+------------+------------+

Avant la version 3.23.4 de MySQL, REGEXP était sensible à la casse, et la requête précédente ne retournait aucune ligne. Pour trouver la lettre 'b' minuscule ou majuscule, utilisez cette requête à la place :

mysql> SELECT * FROM animal WHERE nom REGEXP "^[bB]";

Depuis MySQL 3.23.4, pour forcer REGEXP à être sensible à la casse, utilisez le mot-clé BINARY pour faire de la chaîne, une chaîne binaire. Cette requête trouvera uniquement la lettre minuscule 'b' au début du nom :

mysql> SELECT * FROM animal WHERE nom REGEXP BINARY "^b";

Pour trouver les noms finissant par 'fy', utilisez '$' pour trouver la fin du nom :

mysql> SELECT * FROM animal WHERE nom REGEXP "fy$";
+---------+--------+--------+-------+------------+------+
| nom     | maitre | espece | sexe  | naissance  | mort |
+---------+--------+--------+-------+------------+------+
| Fluffy  | Harold | chat   | f     | 1993-02-04 | NULL |
| Buffy   | Harold | chien  | f     | 1989-05-13 | NULL |
+---------+--------+--------+-------+------------+------+

Pour trouver les noms contenant la lettre 'w' minuscule ou majuscule, utilisez la requête suivante :

mysql> SELECT * FROM animal WHERE nom REGEXP "w";
+----------+--------+---------+------+------------+------------+
| nom      | maitre | espece  | sexe | naissance  | mort       |
+----------+--------+---------+------+------------+------------+
| Claws    | Gwen   | chat    | m    | 1994-03-17 | NULL       |
| Bowser   | Diane  | chien   | m    | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen   | oiseaux | NULL | 1997-12-09 | NULL       |
+----------+--------+---------+------+------------+------------+

Parce qu'une expression régulière est trouvée si le modèle se trouve n'importe où dans la valeur, il n'est pas nécessaire dans la requête précédente de mettre un joker de chaque côté du modèle recherché pour trouver la valeur entière comme cela aurait été le cas en utilisant les modèles de recherche SQL.

Pour trouver les noms contenant exactement 5 caractères, utilisez '^' et '$' pour trouver le début et la fin du nom, et 5 instances de '.' au milieu :

mysql> SELECT * FROM animal WHERE nom REGEXP "^.....$";
+-------+--------+--------+------+------------+------+
| nom   | maitre | espece | sexe | naissance  | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen   | chat   | m    | 1994-03-17 | NULL |
| Buffy | Harold | chien  | f    | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

Vous pouvez aussi écrire la requête suivante en utilisant l'opérateur '{n}' « répéter-n-fois » :

mysql> SELECT * FROM animal WHERE nom REGEXP "^.{5}$";
+-------+--------+--------+------+------------+------+
| nom   | maitre | espece | sexe | naissance  | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen   | chat   | m    | 1994-03-17 | NULL |
| Buffy | Harold | chien  | f    | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

3-3-4-8 - Compter les lignes

Les bases de données sont souvent employées pour répondre à la question : « Combien de fois un certain type de données se trouve dans la table ? » Par exemple, vous aimeriez savoir combien d'animaux vous avez, ou bien combien d'animaux chaque propriétaire possède, ou encore savoir différentes choses concernant vos animaux.

Savoir combien vous avez d'animaux revient à se poser la question : « Combien de lignes y a-t-il dans la table animal ? » parce qu'il y a un enregistrement par animal. La fonction COUNT() compte le nombre de résultats non NULL, donc, la requête pour compter les animaux ressemble à ceci :

mysql> SELECT COUNT(*) FROM animal;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+

Vous pouvez trouver également les noms des propriétaires des animaux. Vous pouvez utiliser COUNT() si vous voulez trouver combien d'animaux possède chaque propriétaire :

mysql> SELECT maitre, COUNT(*) FROM animal GROUP BY maitre;
+--------+----------+
| maitre | COUNT(*) |
+--------+----------+
| Benny  |        2 |
| Diane  |        2 |
| Gwen   |        3 |
| Harold |        2 |
+--------+----------+

Notez l'utilisation de la clause GROUP BY pour grouper tous les enregistrements par propriétaire. Sans cela, vous auriez le message d'erreur suivant :

mysql> SELECT maitre, COUNT(maitre) FROM animal;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause

COUNT() et GROUP BY sont utiles pour caractériser vos données de diverses façons. Les exemples suivants montrent différentes manières pour obtenir des statistiques sur les animaux.

Nombre d'animaux par espèce :

mysql> SELECT espece, COUNT(*) FROM animal GROUP BY espece;
+---------+----------+
| espece  | COUNT(*) |
+---------+----------+
| oiseau  |        2 |
| chat    |        2 |
| chien   |        3 |
| hamster |        1 |
| serpent |        1 |
+---------+----------+

Nombre d'animaux par sexe :

mysql> SELECT sexe, COUNT(*) FROM animal GROUP BY sexe;
+------+----------+
| sexe | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(Dans ce résultat, NULL indique les sexes inconnus.)

Nombre d'animaux par espèce et sexe :

mysql> SELECT espece, sexe, COUNT(*) FROM animal GROUP BY espece, sexe;
+---------+------+----------+
| espece  | sexe | COUNT(*) |
+---------+------+----------+
| oiseau  | NULL |        1 |
| oiseau  | f    |        1 |
| chat    | f    |        1 |
| chat    | m    |        1 |
| chien   | f    |        1 |
| chien   | m    |        2 |
| hamster | f    |        1 |
| serpent | m    |        1 |
+---------+------+----------+

Vous n'avez pas besoin de rechercher une table entière quand vous employez COUNT(). Par exemple, la requête précédente, si vous voulez trouver uniquement les chiens et les chats, ressemble à cela :

mysql> SELECT espece, sexe, COUNT(*) FROM animal
-> WHERE espece = "chien" OR espece = "chat"
-> GROUP BY espece, sexe;
+---------+------+----------+
| espece  | sexe | COUNT(*) |
+---------+------+----------+
| chat    | f    |        1 |
| chat    | m    |        1 |
| chien   | f    |        1 |
| chien   | m    |        2 |
+---------+------+----------+

Ou bien, si vous voulez trouver le nombre d'animaux par sexe, uniquement pour les animaux dont le sexe est connu :

mysql> SELECT espece, sexe, COUNT(*) FROM animal
-> WHERE sexe IS NOT NULL
-> GROUP BY espece, sexe;
+---------+------+----------+
| espece  | sexe | COUNT(*) |
+---------+------+----------+
| oiseau  | f    |        1 |
| chat    | f    |        1 |
| chat    | m    |        1 |
| chien   | f    |        1 |
| chien   | m    |        2 |
| hamster | f    |        1 |
| serpent | m    |        1 |
+---------+------+----------+

3-3-4-9 - Utiliser plus d'une table

La table animal garde les enregistrements de vos animaux. Si vous voulez enregistrer d'autres informations concernant vos animaux, comme les événements de leur vie, les visites chez le vétérinaire, ou encore lorsqu'ils ont mis bas, vous avez besoin d'une autre table. De quoi a besoin cette table ? Elle doit :

- contenir le nom de l'animal pour savoir à quel animal cet événement se rattache ;

- une date pour savoir quand a eu lieu l'événement ;

- un champ qui décrit l'événement ;

- un champ de type événement, si vous voulez être capable de cataloguer les événements.

En prenant cela en considération, le code CREATE TABLE pour la table evenement doit ressembler à ceci :

mysql> CREATE TABLE evenement (nom VARCHAR(20), date DATE,
-> type VARCHAR(15), remarque VARCHAR(255));

Tout comme la table animal, il est facile d'enregistrer les enregistrements initiaux en créant un fichier texte délimité par des tabulations, contenant l'information :

nom

date

type

remarque

Fluffy

1995-05-15

mise bas

4 chatons, 3 femelles, 1 mâle

Buffy

1993-06-23

mise bas

5 chiots, 2 femelles, 3 mâles

Buffy

1994-06-19

mise bas

3 chiots, 3 femelles

Chirpy

1999-03-21

vétérinaire

Redresser le bec

Slim

1997-08-03

vétérinaire

Côtes cassées

Bowser

1991-10-12

chenil

Fang

1991-10-12

chenil

Fang

1998-08-28

anniversaire

Don d'un nouvel objet de mastication

Claws

1998-03-17

anniversaire

Don d'un nouveau collier antipuces

Whistler

1998-12-09

anniversaire

Premier anniversaire

Chargez ces enregistrements comme cela :

mysql> LOAD DATA LOCAL INFILE "evenement.txt" INTO TABLE evenement;

En se basant sur ce que vous avez appris des requêtes effectuées sur la table animal, vous devriez être capable de faire des recherches sur les enregistrements de la table evenement ; le principe est le même. Quand devez-vous vous demander si la table evenement est seule suffisante pour répondre à votre question ?

Supposez que vous vouliez trouver l'âge de chaque animal lorsqu'il a mis bas. La table evenement indique quand cela s'est produit, mais pour le calcul de l'âge de la mère, vous avez besoin de sa date de naissance. Parce que ces informations sont stockées dans la table animal, vous avez besoin des deux tables pour cette requête :

mysql> SELECT animal.nom,
-> (TO_DAYS(date) - TO_DAYS(naissance))/365 AS age,
-> remarque
-> FROM animal, evenement
-> WHERE animal.nom = evenement.nom AND type = "mise bas";
+--------+------+--------------------------------+
| nom    | age  | remarque                       |
+--------+------+--------------------------------+
| Fluffy | 2.27 | 4 chatons, 3 femelles, 1 mâle  |
| Buffy  | 4.12 | 5 chiots, 2 femelles, 3 mâles  |
| Buffy  | 5.10 | 3 chiots, 3 femelles           |
+--------+------+--------------------------------+

Il y a plusieurs choses à noter concernant cette requête :

- la clause FROM liste les deux tables parce que la requête a besoin d'informations contenues dans ces deux tables ;

- lorsque vous combinez (joignez) des informations provenant de plusieurs tables, vous devez spécifier quels enregistrements d'une table peuvent être associés à quels enregistrements des autres tables. C'est aisé parce qu'elles ont toutes les deux une colonne nom. La requête utilise la clause WHERE pour faire correspondre les enregistrements des deux tables sur les valeurs de la colonne nom ;

- parce que la colonne nom apparaît dans les deux tables, vous devez être explicite concernant la table que vous utilisez lorsque vous vous référez à cette colonne. C'est fait en faisant précéder le nom de la colonne par le nom de la table.

Vous n'avez pas besoin de deux tables différentes pour effectuer une jointure. Quelquefois, c'est plus facile de joindre une table sur elle-même, si vous voulez comparer des enregistrements dans une table avec d'autres enregistrements de la même table. Par exemple, pour trouver des paires multiples parmi vos animaux, vous pouvez joindre la table animal sur elle-même pour trouver les paires mâles / femelles par rapport à l'espèce :

mysql> SELECT p1.nom, p1.sexe, p2.nom, p2.sexe, p1.espece
-> FROM animal AS p1, animal AS p2
-> WHERE p1.espece = p2.espece AND p1.sexe = "f" AND p2.sexe = "m";
+--------+------+--------+------+---------+
| nom    | sexe | nom    | sexe | espece  |
+--------+------+--------+------+---------+
| Fluffy | f    | Claws  | m    | chat    |
| Buffy  | f    | Fang   | m    | chien   |
| Buffy  | f    | Bowser | m    | chien   |
+--------+------+--------+------+---------+

Dans cette requête, nous avons spécifié des alias pour les noms de tables dans l'ordre de référence des colonnes et ainsi maintenir directement à quelle instance de la table chaque colonne est associée.

3-4 - Obtenir des informations à propos des bases de données et des tables

Que faire si vous oubliez le nom d'une base de données ou d'une table, ou bien encore la structure d'une table donnée (par exemple, comment se nomment ses colonnes) ?

MySQL répond à ce problème en fournissant plusieurs commandes qui renvoient des informations à propos des tables et des bases de données les contenant.

Vous avez déjà vu SHOW DATABASES qui liste les bases de données gérées par le serveur. Pour trouver quelle base de données est actuellement sélectionnée, utilisez la fonction DATABASE() :

mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+

Si vous n'avez encore sélectionné aucune base de données, le résultat est vide.

Pour trouver quelles sont les tables que la base contient (par exemple, quand vous n'êtes pas sûr du nom d'une table), utilisez cette commande :

mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| evenement           |
| animal              |
+---------------------+

Si vous voulez en savoir davantage sur la structure d'une table, la commande DESCRIBE est utile ; elle fournit des informations sur chaque colonne de la table :

mysql> DESCRIBE animal;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| nom       | varchar(20) | YES  |     | NULL    |       |
| maitre    | varchar(20) | YES  |     | NULL    |       |
| espece    | varchar(20) | YES  |     | NULL    |       |
| sexe      | char(1)     | YES  |     | NULL    |       |
| naissance | date        | YES  |     | NULL    |       |
| mort      | date        | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+

Field indique le nom de la colonne, Type est son type de données, NULL indique si la colonne peut contenir des valeurs NULL, Key indique si la colonne est indexée et Default spécifie la valeur par défaut de la colonne.

Si vous avez des index sur une table, SHOW INDEX FROM nom_de_table vous fournira des informations sur eux.

3-5 - Utilisation de mysql en mode batch

Dans les sections précédentes, vous avez utilisé mysql interactivement pour entrer vos requêtes et voir les résultats. Vous pouvez aussi utiliser mysql en mode batch. Pour ce faire, placez les commandes que vous voulez exécuter dans un fichier, puis dites à mysql de lire les entrées à partir de celui-ci :

shell> mysql < fichier-batch

Si vous utilisez mysql sous Windows et que vous avez des caractères spéciaux dans le fichier qui posent problème, vous pouvez faire :

dos> mysql -e "source fichier-batch"

Si vous devez spécifier les paramètres de connexion en ligne de commande, la commande ressemblera à ceci :

shell> mysql -h hôte -u utilisateur -p < fichier-batch
Enter password: ********

Lorsque vous utilisez mysql de cette façon, vous créez un fichier de script, puis vous l'exécutez.

Si vous voulez que le script continue, même s'il y a des erreurs, vous devez utiliser l'option --force de la ligne de commande.

Pourquoi utiliser un script ? Voici quelques raisons.

- Si vous utilisez une requête de façon répétitive (c'est-à-dire, chaque jour, ou chaque semaine), en faire un script vous évitera de la réécrire chaque fois.

- Vous pouvez générer de nouvelles requêtes à partir de requêtes existantes et similaires en copiant et éditant des fichiers de scripts.

- Ce mode peut aussi être utile lors du développement d'une requête, particulièrement pour les commandes sur plusieurs lignes ou plusieurs séquences de commandes. Si vous commettez une erreur, vous n'avez pas à tout récrire. Éditez juste votre script pour corriger l'erreur et dites à mysql de l'exécuter à nouveau.

- Si vous avez une requête qui produit beaucoup d'affichages, vous pouvez le rediriger vers un visualiseur plutôt que de le regarder défiler sur votre écran :

shell> mysql < fichier-batch | more

- Vous pouvez capturer l'affichage dans un fichier pour un traitement ultérieur :

shell> mysql < fichier_batch > mysql.out

- Vous pouvez distribuer votre script à d'autres personnes pour qu'elles l'exécutent.

- Quelques situations ne permettent pas une utilisation interactive, par exemple, quand vous exécutez une requête à partir d'une tâche cron. Dans ce cas, vous devez utiliser le mode batch.

Le format d'affichage par défaut est différent (plus concis) lorsque vous exécutez mysql en mode batch de celui utilisé interactivement. Par exemple, le résultat de SELECT DISTINCT espece FROM animal ressemble à ceci interactivement :

+---------+
| espece  |
+---------+
| oiseau  |
| chat    |
| chien   |
| hamster |
| serpent |
+---------+

Mais à ceci en mode batch :

espece
oiseau
chat
chien
hamster
serpent

Si vous voulez le format d'affichage interactif en mode batch, utilisez mysql -t. Pour écrire les commandes exécutées dans la sortie, utilisez mysql -vvv.

Vous pouvez aussi utiliser un script à partir de l'invite mysql en utilisant la commande source :

mysql> source nom_fichier;

3-6 - Exemples de requêtes usuelles

Voilà des exemples qui vous serviront à résoudre les problèmes communs avec MySQL.

Certains exemples utilisent la table shop pour sauvegarder le prix de chaque article (numéro de l'élément) pour certains vendeurs (dealers). En supposant que chaque vendeur a un prix fixe pour chaque article, le couple (article, dealer) est une clef primaire pour les enregistrements.

Démarrez le client en ligne de commande mysql et sélectionnez une base de données :

mysql nom-base-données

(Dans la plupart des installations de MySQL, vous pouvez utiliser la base de données test).

Vous pouvez créer la table d'exemple de la façon suivante :

CREATE TABLE shop (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer  CHAR(20)                 DEFAULT ''     NOT NULL,
price   DOUBLE(16,2)             DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));

INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),
(3,'D',1.25),(4,'D',19.95);

Les données d'exemple sont :

mysql> SELECT * FROM shop;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | A      |  3.45 |
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | B      |  1.45 |
|    0003 | C      |  1.69 |
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

3-6-1 - La valeur maximale d'une colonne

« Quel est le numéro du plus grand élément ? »

SELECT MAX(article) AS article FROM shop

+---------+
| article |
+---------+
|       4 |
+---------+

3-6-2 - La ligne contenant le maximum d'une certaine colonne

« Trouvez le numéro, vendeur et prix de l'article le plus cher. »

En SQL-99 (et MySQL version 4.1), cela est facilement fait avec une sous-requête :

SELECT article, dealer, price
FROM   shop
WHERE  price=(SELECT MAX(price) FROM shop);

En MySQL 4.0 ou plus ancien, vous devez le faire en deux temps :

1. Obtenir le plus grand prix de la table avec une requête SELECT.

mysql> SELECT MAX(price) FROM shop;
+------------+
| MAX(price) |
+------------+
|      19.95 |
+------------+

2. Utiliser la valeur 19.95 avec la requête suivante :

mysql> SELECT article, dealer, price
-> FROM   shop
-> WHERE  price=19.95;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0004 | D      | 19.95 |
+---------+--------+-------+

Une autre solution est de trier toutes les lignes en ordre décroissant, et de ne lire que la première ligne avec la clause LIMIT :

SELECT article, dealer, price
FROM   shop
ORDER BY price DESC
LIMIT 1;

Note : s'il y a beaucoup d'articles chers (par exemple, chaque 19.95) la solution avec LIMIT n'en montre qu'un !

3-6-3 - Maximum d'une colonne par groupe

« Quel est le plus grand prix par article ? »

SELECT article, MAX(price) AS price
FROM   shop
GROUP BY article

+---------+-------+
| article | price |
+---------+-------+
|    0001 |  3.99 |
|    0002 | 10.99 |
|    0003 |  1.69 |
|    0004 | 19.95 |
+---------+-------+

3-6-4 - La ligne contenant la plus grande valeur d'un certain champ par rapport à un groupe

« Pour chaque article, trouvez le ou les vendeurs ayant le plus haut prix. »

En ANSI SQL, je l'aurais fait de cette façon avec une sous-requête :

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);

En MySQL, il vaut mieux le faire en plusieurs étapes :

1. Récupérer la liste de couples article et plus grand prix ;

2. Pour chaque article, récupérer la ligne qui a le plus grand prix stocké.

Cela se fait facilement avec une table temporaire :

CREATE TEMPORARY TABLE tmp (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
price   DOUBLE(16,2)             DEFAULT '0.00' NOT NULL);

LOCK TABLES shop read;

INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;

SELECT shop.article, dealer, shop.price FROM shop, tmp
WHERE shop.article=tmp.article AND shop.price=tmp.price;

UNLOCK TABLES;

DROP TABLE tmp;

Si vous n'utilisez pas une table TEMPORARY, vous devez aussi verrouiller celle-ci.

« Peut-on le faire avec une seule requête ? »

Oui, mais en utilisant une astuce inefficace que j'appelle « astuce du MAX-CONCAT » :

SELECT article,
SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
0.00+LEFT(      MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM   shop
GROUP BY article;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | C      |  1.69 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

Le dernier exemple peut, bien sûr, être amélioré en découpant les colonnes concaténées dans le client.

3-6-5 - Utiliser les variables utilisateur

Vous pouvez utiliser les variables utilisateur de MySQL pour garder des résultats en mémoire sans avoir à les enregistrer dans des variables temporaires du client. Voir Section 9.3, « Variables utilisateur ».

Par exemple, pour trouver l'article avec le plus haut et le plus bas prix, vous pouvez faire :

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

3-6-6 - Utiliser les clefs étrangères

Depuis la version 3.23.44 de MySQL, les tables InnoDB supportent les contraintes des clefs étrangères. Voir Chapitre 15, Le moteur de tables InnoDB. Consultez aussi Section 1.5.5.5, « Les clés étrangères ».

Actuellement, vous n'avez pas besoin de clefs étrangères pour réaliser des jointures entre les tables. La seule chose que MySQL ne fait pas encore (avec les types autres que InnoDB), est CHECK pour s'assurer que la clef que vous utilisez existe bien dans la ou les tables que vous référencez et il n'efface pas automatiquement les lignes d'une table avec une définition de clef étrangère. Si vous utilisez vos clefs comme une clef normale, tout marchera parfaitement :

CREATE TABLE person (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE shirt (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),
PRIMARY KEY (id)
);

INSERT INTO person VALUES (NULL, 'Antonio Paz');

INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', LAST_INSERT_ID()),
(NULL, 'dress', 'white', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blue', LAST_INSERT_ID());

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');

INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'red', LAST_INSERT_ID()),
(NULL, 'dress', 'blue', LAST_INSERT_ID()),
(NULL, 't-shirt', 'white', LAST_INSERT_ID());

SELECT * FROM person;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | Antonio Paz         |
|  2 | Lilliana Angelovska |
+----+---------------------+

SELECT * FROM shirt;
+----+---------+--------+-------+
| id | style   | color  | owner |
+----+---------+--------+-------+
|  1 | polo    | blue   |     1 |
|  2 | dress   | white  |     1 |
|  3 | t-shirt | blue   |     1 |
|  4 | dress   | orange |     2 |
|  5 | polo    | red    |     2 |
|  6 | dress   | blue   |     2 |
|  7 | t-shirt | white  |     2 |
+----+---------+--------+-------+

SELECT s.* FROM person p, shirt s
WHERE p.name LIKE 'Lilliana%'
AND s.owner = p.id
AND s.color <> 'white';

+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange |     2 |
|  5 | polo  | red    |     2 |
|  6 | dress | blue   |     2 |
+----+-------+--------+-------+

3-6-7 - Recherche sur deux clefs

MySQL n'optimise pas encore quand vous effectuez des recherches sur deux clefs différentes combinées avec OR (la recherche sur une clef avec différentes parties OR est elle pas mal optimisée) :

SELECT champ1_index, champ2_index FROM test_table WHERE champ1_index = '1'
OR  champ2_index = '1'

La raison est que nous n'avons pas trouvé le temps suffisant pour parvenir à un moyen efficace de gérer cela dans un cas général. (En comparaison, la gestion de AND est maintenant complètement générale et fonctionne très bien.)

En MySQL 4.0, vous pouvez résoudre ce problème efficacement en utilisant une clause UNION qui combine le résultat de deux requêtes SELECT séparées. Voir Section 13.1.7.2, « Syntaxe de UNION ». Chaque requête SELECT ne recherche qu'avec une seule clé, et peut être optimisée :

SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'
UNION
SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';

Avant MYSQL 4.0, vous pouvez résoudre ce problème efficacement en utilisant une table temporaire (TEMPORARY). Ce type d'optimisation est très utile si vous utilisez des requêtes très complexes et que le serveur SQL fait une optimisation dans le mauvais ordre.

CREATE TEMPORARY TABLE tmp
SELECT champ1_index, champ2_index FROM test_table WHERE champ1_index = '1';
INSERT INTO tmp
SELECT champ1_index, champ2_index FROM test_table WHERE champ2_index = '1';
SELECT * from tmp;
DROP TABLE tmp;

La méthode ci-dessus pour résoudre cette requête est en effet une UNION de deux requêtes. Voir Section 13.1.7.2, « Syntaxe de UNION ».

3-6-8 - Calcul du nombre de visites par jour

Ce qui suit donne une idée d'une utilisation des fonctions de bits pour calculer le nombre de jours par mois où un utilisateur a visité une page web.

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,
day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),
(2000,2,23),(2000,2,23);

La table d'exemple contient des valeurs au format année-mois-jour, qui représentent des visites d'utilisateurs sur la page. Pour déterminer le nombre de jours entre deux visites, utilisez la requête suivante :

SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1
GROUP BY year,month;

Qui retourne :

+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 |    01 |    3 |
| 2000 |    02 |    2 |
+------+-------+------+

Ce qui précède calcule le nombre de jours différents qui a été utilisé pour une combinaison année/mois, avec suppression automatique des doublons.

3-6-9 - Utiliser AUTO_INCREMENT

L'attribut AUTO_INCREMENT peut être utilisé pour générer un identifiant unique pour les nouvelles lignes :

CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO animals (name) VALUES ("dog"),("cat"),("penguin"),
("lax"),("whale"),("ostrich");
SELECT * FROM animals;

Qui retourne :

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

Vous pouvez obtenir la valeur utilisée de la clef AUTO_INCREMENT avec la fonction SQL LAST_INSERT_ID() ou la fonction d'API mysql_insert_id().

Note@ : pour une insertion multiligne, LAST_INSERT_ID()/mysql_insert_id() retourneront la clef AUTO_INCREMENT de la première ligne insérée. Cela permet de reproduire les insertions multiligne sur d'autres services.

Pour les tables MyISAM et BDB vous pouvez spécifier AUTO_INCREMENT sur une colonne secondaire d'une clef multicolonne. Dans ce cas, la valeur générée pour la colonne auto-incrémentée est calculée de la façon suivante : MAX(auto_increment_column)+1) WHERE prefix=given-prefix. C'est utile lorsque vous voulez placer des données dans des groupes ordonnés.

CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
);
INSERT INTO animals (grp,name) VALUES("mammal","dog"),("mammal","cat"),
("bird","penguin"),("fish","lax"),("mammal","whale"),
("bird","ostrich");
SELECT * FROM animals ORDER BY grp,id;

Qui retourne :

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

Notez que dans ce cas, la valeur d'AUTO_INCREMENT sera réutilisée si vous effacez la ligne avec la plus grande valeur d'AUTO_INCREMENT tous groupes confondus. Cela n'arrive jamais avec les tables MyISAM, dont les valeurs AUTO_INCREMENT ne sont jamais réutilisées.

3-7 - Requêtes du projet Twin

À Analytikerna et Lentus, nous avons eu à mettre en place la partie système et base de données d'un grand projet de recherche. Ce projet est une collaboration entre l'institut de médecine environnementale de l'institut de Karolinska Stockholm et la section de recherche clinique d'âge et de psychologie à l'université de la Californie du sud.

Le projet nécessite une partie de récolte d'informations où tous les jumeaux en Suède de plus de 65 ans sont contactés par téléphone. Ceux qui répondent à certains critères sont admis à la seconde étape. Dans celle-ci, les jumeaux qui veulent participer rencontrent une équipe de médecins/infirmiers. Les examens incluent des examens physiques et neuropsychologiques, des tests en laboratoire, de la neuro-imagerie, des études psychologiques et de la collecte d'informations relatives à la famille. En plus de tout cela, les données à propos des facteurs de risques médicaux et environnementaux sont collectées.

Plus d'informations à propos de l'étude Twin peuvent être trouvées sur : http://www.imm.ki.se/TWIN/TWINUKW.HTM

La dernière partie de ce projet est administrée avec une interface web écrite en utilisant Perl et MySQL.

Chaque nuit, toutes les informations des interviews sont stockées dans une base de données MySQL.

3-7-1 - Trouver tous les jumeaux répondant aux critères

La requête suivante a été utilisée pour déterminer qui participerait à la seconde partie du projet :

SELECT
CONCAT(p1.id, p1.tvab) + 0 AS tvid,
CONCAT(p1.christian_name, " ", p1.surname) AS Name,
p1.postal_code AS Code,
p1.city AS City,
pg.abrev AS Area,
IF(td.participation = "Aborted", "A", " ") AS A,
p1.dead AS dead1,
l.event AS event1,
td.suspect AS tsuspect1,
id.suspect AS isuspect1,
td.severe AS tsevere1,
id.severe AS isevere1,
p2.dead AS dead2,
l2.event AS event2,
h2.nurse AS nurse2,
h2.doctor AS doctor2,
td2.suspect AS tsuspect2,
id2.suspect AS isuspect2,
td2.severe AS tsevere2,
id2.severe AS isevere2,
l.finish_date
FROM
twin_project AS tp
/* For Twin 1 */
LEFT JOIN twin_data AS td ON tp.id = td.id
AND tp.tvab = td.tvab
LEFT JOIN informant_data AS id ON tp.id = id.id
AND tp.tvab = id.tvab
LEFT JOIN harmony AS h ON tp.id = h.id
AND tp.tvab = h.tvab
LEFT JOIN lentus AS l ON tp.id = l.id
AND tp.tvab = l.tvab
/* For Twin 2 */
LEFT JOIN twin_data AS td2 ON p2.id = td2.id
AND p2.tvab = td2.tvab
LEFT JOIN informant_data AS id2 ON p2.id = id2.id
AND p2.tvab = id2.tvab
LEFT JOIN harmony AS h2 ON p2.id = h2.id
AND p2.tvab = h2.tvab
LEFT JOIN lentus AS l2 ON p2.id = l2.id
AND p2.tvab = l2.tvab,
person_data AS p1,
person_data AS p2,
postal_groups AS pg
WHERE
/* p1 gets main twin and p2 gets his/her twin. */
/* ptvab is a field inverted from tvab */
p1.id = tp.id AND p1.tvab = tp.tvab AND
p2.id = p1.id AND p2.ptvab = p1.tvab AND
/* Just the sceening survey */
tp.survey_no = 5 AND
/* Skip if partner died before 65 but allow emigration (dead=9) */
(p2.dead = 0 OR p2.dead = 9 OR
(p2.dead = 1 AND
(p2.death_date = 0 OR
(((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)
>= 65))))
AND
(
/* Twin is suspect */
(td.future_contact = 'Yes' AND td.suspect = 2) OR
/* Twin is suspect - Informant is Blessed */
(td.future_contact = 'Yes' AND td.suspect = 1
AND id.suspect = 1) OR
/* No twin - Informant is Blessed */
(ISNULL(td.suspect) AND id.suspect = 1
AND id.future_contact = 'Yes') OR
/* Twin broken off - Informant is Blessed */
(td.participation = 'Aborted'
AND id.suspect = 1 AND id.future_contact = 'Yes') OR
/* Twin broken off - No inform - Have partner */
(td.participation = 'Aborted' AND ISNULL(id.suspect)
AND p2.dead = 0))
AND
l.event = 'Finished'
/* Get at area code */
AND SUBSTRING(p1.postal_code, 1, 2) = pg.code
/* Not already distributed */
AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)
/* Has not refused or been aborted */
AND NOT (h.status = 'Refused' OR h.status = 'Aborted'
OR h.status = 'Died' OR h.status = 'Other')
ORDER BY
tvid;

Quelques explications :

- CONCAT(p1.id, p1.tvab) + 0 AS tvid

Nous voulons trier la concaténation d'id et tvab dans un ordre numérique. Ajouter 0 au résultat force MySQL à le considérer comme un nombre.

- colonne id

Identifie une paire de jumeaux. C'est un clef dans toutes les tables.

- colonne tvab

Identifie un jumeau dans une paire. Valeur 1 ou 2.

- colonne ptvab

Inverse de tvab. Si tvab est 1 c'est égal à 2, et vice versa. Elle existe pour diminuer la frappe et faciliter la tâche à MySQL lors de l'optimisation de la requête.

Cette requête montre, entre autres, comment faire pour consulter une table depuis cette même table en utilisant une jointure (p1 et p2). Dans cet exemple, est utilisé pour chercher quel partenaire du projet est décédé avant l'âge de 65 ans. Si c'est le cas, la ligne n'est pas retournée.

Tout ce qui précède existe dans toutes les tables avec des informations relatives aux jumeaux. Nous avons une clé sur les champs id,tvab (toutes les tables), et sur les champs id,ptvab (person_data) pour accélérer les requêtes.

Sur notre machine de production (un 200MHz UltraSPARC), cette requête retourne près de 150-200 lignes et prend moins d'une seconde.

Le nombre d'enregistrements dans les tables utilisées plus haut :

Table

Lignes

person_data

71074

lentus

5291

twin_project

5286

twin_data

2012

informant_data

663

harmony

381

postal_groups

100

3-7-2 - Afficher une table avec l'état des paires de jumeaux

Chaque entrevue se finit avec un code d'état, appelé event. La requête ci-dessous montre comment afficher une table avec toutes les paires, rassemblées par code d'état. Elle indique combien de paires ont terminé, combien de paires ont à moitié terminé et combien on refusé, etc.

SELECT
t1.event,
t2.event,
COUNT(*)
FROM
lentus AS t1,
lentus AS t2,
twin_project AS tp
WHERE
/* Nous recherchons une paire à la fois */
t1.id = tp.id
AND t1.tvab=tp.tvab
AND t1.id = t2.id
/* On étudie toutes les données */
AND tp.survey_no = 5
/* Cela évite qu'une paire devienne un doublon */
AND t1.tvab='1' AND t2.tvab='2'
GROUP BY
t1.event, t2.event;

3-8 - Utilisation de MySQL avec Apache

Il existe des programmes vous permettant d'identifier vos utilisateurs à l'aide d'une base MySQL et qui vous permettent aussi de créer des journaux de log dans vos tables MySQL.

Vous pouvez changer le format d'archivage d'Apache pour le rendre plus facilement lisible par MySQL en mettant ce qui suit dans le fichier de configuration d'Apache :

LogFormat \
"\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\",  \
\"%U\",\"%{Referer}i\",\"%{User-Agent}i\""

Avec MySQL, vous pouvez exécuter une requête de cette manière :

LOAD DATA INFILE '/local/access_log' INTO TABLE table_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'

4 - Utiliser les programmes MySQL

Ce chapitre présente les programmes fournis par MySQL AB et les options disponibles pour faire fonctionner ces programmes.

La plupart des programmes ont des options qui leur sont spécifiques, mais la syntaxe de spécification des options est similaire pour tous les programmes. Les derniers chapitres fournissent des détails sur chaque programme, y compris leurs options.

4-1 - Présentation des logiciels MySQL

MySQL AB fournit différents types de logiciels.

- Le serveur MYSQL et les scripts de démarrage :

- mysqld est le serveur MySQL.

- mysqld_safe, mysql.server et mysqld_multi sont les scripts de démarrage.

- mysql_install_db initialise le dossier de données et les premières bases.

Ces logiciels sont présentés en détail dans la section Chapitre 5, Administration du serveur.

- Logiciels clients pour accéder au serveur :

- mysql est un client en ligne de commande, pour exécuter des commandes SQL, interactivement, ou en mode batch.

- mysqlcc (MySQL Control Center) est un client interactif graphique, pour exécuter des commandes SQL, et administrer le serveur.

- mysqladmin est un client d'administration.

- mysqlcheck effectue les opérations de maintenance sur les tables.

- mysqldump et mysqlhotcopy font les sauvegardes de bases.

- mysqlimport importe des fichiers de données.

- mysqlshow affiche des informations sur les bases et les tables.

Ces logiciels sont présentés en détail dans la section Chapitre 8, MySQL Scripts clients et utilitaires.

- Utilitaires qui fonctionnent indépendamment du serveur :

- myisamchk effectue les opérations de maintenance des tables

- myisampack produit des tables compressées, en lecture seule

- mysqlbinlog est un outil pour traiter les fichiers de logs binaires

- perror affiche le message associé à un code d'erreur

myisamchk est présenté dans la section Chapitre 5, Administration du serveur. Les autres logiciels sont détaillés dans Chapitre 8, MySQL Scripts clients et utilitaires.

La plupart des distributions MySQL incluent tous ces programmes, hormis ceux qui sont spécifiques à une plate-forme. Par exemple, les scripts de démarrage du serveur ne sont pas utilisés sur Windows. L'exception est le format RPM, qui est plus spécialisé. Il y a des RPM pour le serveur, d'autres pour les clients. Si vous pensez qu'il vous en manque un, voyez la section Chapitre 2, Installer MySQL pour tout savoir sur les distributions et leur contenu. Il se peut alors que vous ayez un autre paquet à installer.

4-2 - Appeler des programmes MySQL

Pour appeler un logiciel MySQL en ligne de commande (c'est-à-dire depuis un terminal), il suffit d'entrer le nom du programme, suivi d'options, et d'autres arguments, pour indiquer au programme ce que vous voulez faire. Les commandes suivantes montrent quelques appels simples. « shell> » représente l'invite de commande de votre interpréteur : il ne fait pas partie de la commande elle-même. Les invites de commandes classiques sont $ pour sh et bash, % pour csh et tcsh, et C:\> pour Windows command.com ou cmd.exe.

shell> mysql test
shell> mysqladmin extended-status variables
shell> mysqlshow --help
shell> mysqldump --user=root personnel

Les arguments qui commencent par un tiret sont des options. Ils spécifient généralement le type de connexion que le serveur doit faire, ou lui donne un mode opératoire spécial. La syntaxe des options est décrite dans la section Section 4.3, « Spécifier des options aux programmes ».

Les arguments (ceux qui ne commencent pas par un tiret), fournissent davantage d'informations au programme. Par exemple, mysql utilise le premier argument comme un nom de base de données : la commande mysql test indique que vous voulez utiliser la base de données test.

Les sections ultérieures décriront les programmes individuellement, avec leurs options spécifiques, et l'interprétation qu'ils font des arguments.

Certaines options sont communes à un grand nombre de programmes. Les plus communes sont --host, --user et --password qui spécifient respectivement le nom d'hôte du serveur MySQL, le nom d'utilisateur et le mot de passe du compte. Tous les clients MySQL comprennent ces options : elles vous permettent d'indiquer sur quel serveur vous voulez travailler.

Vous pouvez avoir besoin d'appeler les logiciels MySQL en utilisant le chemin jusqu'au dossier bin dans lequel ils sont installés. Il est probable que dans ce cas, si vous rencontrez une erreur « program not found » lors de votre appel aux programmes hors du dossier bin. Pour rendre plus confortable l'utilisation de MySQL, vous pouvez ajouter le chemin vers bin dans votre variable d'environnement PATH. Puis, exécutez le programme en utilisant simplement son nom.

Consultez la documentation de votre interpréteur de ligne de commande pour savoir assigner la variable PATH. La syntaxe d'assignation des variables est spécifique à chaque terminal.

4-3 - Spécifier des options aux programmes

Vous pouvez fournir des options aux programmes MySQL de différentes façons :

- en ligne de commande, après le nom du programme. C'est le plus courant pour les appels ponctuels du programme ;

- dans un fichier d'options, que le programme lit au démarrage. C'est le plus courant pour les programmes que vous voulez utiliser fréquemment ;

- dans les variables d'environnement. Ce sont des options pratiques si vous voulez les appliquer à chaque fois que vous lancez le programme, même si les fichiers d'options sont plus utilisés en pratique. (La section Section 5.10.2, « Utiliser plusieurs serveurs sous Unix » présente une situation où les variables d'environnement peuvent être très utiles. Elle décrit une situation où vous pouvez utiliser les variables pour spécifier le numéro de port TCP/IP et le fichier de socket Unix pour le client et le serveur.)

Les programmes MySQL déterminent quelles options sont disponibles en examinant d'abord les variables d'environnement, puis le fichier d'options et enfin, la ligne de commande. Si une option est spécifiée plusieurs fois, la dernière occurrence sera utilisée. Cela signifie que les variables d'environnement ont la plus faible priorité, et que les options de ligne de commande ont la forte priorité.

La meilleure technique consiste à stocker les options dans un fichier d'options. Vous pourrez alors éviter de saisir les options en ligne de commande, mais vous pourrez les remplacer par d'autres valeurs ponctuellement, en utilisant la ligne de commande.

4-3-1 - Options de ligne de commande de mysqld

Les options des programmes spécifiées en ligne de commande suivent ces règles :

- les options sont données après la commande ;

- une option commence avec un ou deux tirets, suivant que c'est un nom court ou long. De nombreuses options ont les deux formats. Par exemple, -? et --help sont les formes courtes et longues de l'option qui demande à un programme d'afficher le message d'aide ;

- les noms des options sont sensibles à la casse. -v et -V sont valides tous les deux, mais ont des significations différentes. Elles correspondent aux formes courtes des options --verbose et --version ;

- certaines options prennent une valeur en argument, après le nom de l'option. Par exemple, -h localhost et --host=localhost indiquent au client MySQL le nom d'hôte du serveur à utiliser. La valeur de l'option est le nom de l'hôte à utiliser ;

- pour une option longue qui prend une valeur, séparez l'option de la valeur avec le signe égal ('='). Pour une option longue qui prend une valeur, séparez l'option de la valeur avec le signe espace. (-hlocalhost et -h localhost sont équivalents.) Une exception à cette règle est l'option qui permet de spécifier le mot de passe MySQL. Cette option peut être donnée en format long comme --password=pass_val ou bien --password. Dans le dernier cas (sans mot de passe indiqué), le programme vous demandera interactivement un mot de passe. Le mot de passe peut aussi être configuré avec la forme courte -ppass_val, ou encore -p. Cependant, en forme courte, si le mot de passe est fourni, il doit suivre immédiatement la lettre, sans espace. La raison à cela est que le programme ne saura pas si l'argument suivant est le paramètre de l'option ou un autre argument. Par conséquent, les deux commandes suivantes ont deux significations très différentes :

shell> mysql -ptest
shell> mysql -p test

La première commande demande à mysql d'utiliser la valeur test comme mot de passe, mais ne spécifie pas de base de données par défaut. La seconde commande demande à mysql de demander le mot de passe à l'écran, et d'utiliser la base test comme base par défaut.

MySQL 4.0 a introduit une souplesse supplémentaire dans la manière de saisir des options. Ces modifications ont été ajoutées en MySQL 4.0.2. Certaines se rapportent à la façon de spécifier qu'une option est « activée » ou « désactivée », et d'autres se rapportent aux options qui sont disponibles dans une version, mais pas dans l'autre. Ces fonctionnalités seront décrites ultérieurement dans cette section. Un autre changement se rapporte à la méthode de spécification des variables de programme. La section Section 4.3.4, « Utiliser les options pour configurer des variables de programme » présente en détail ce sujet.

Certaines options qui contrôlent le comportement du serveur peuvent être activées ou désactivées. Par exemple, le client mysql supporte l'option --column-names qui détermine s'il faut afficher ou pas le nom des colonnes. Par défaut, cette option est activée. Cependant, vous pouvez la désactiver dans certaines situations, comme lorsque vous voulez envoyer le résultat de mysql dans un autre programme qui s'attend à ne recevoir que des données, et pas les entêtes.

Pour désactiver le nom des colonnes, vous pouvez spécifier l'option de trois manières différentes :

--disable-column-names
--skip-column-names
--column-names=0

Les préfixes --disable et --skip et le suffixe =0 ont tous le même effet : ils désactivent l'option.

La forme « active » de l'option peut être spécifiée de ces trois manières :

--column-names
--enable-column-names
--column-names=1

Une autre modification au traitement des options, introduit en MySQL 4.0 est que vous pouvez utiliser le préfixe --loose pour les options de ligne de commande. Si une option est préfixée par --loose, le programme ne va pas se terminer avec une erreur, s'il ne reconnaît pas l'option, mais il va juste émettre une alerte :

shell> mysql --loose-no-such-option
mysql: WARNING: unknown option '--no-such-option'

Le préfixe --loose peut être utilisé lorsque vous exécutez des programmes depuis plusieurs installations de MySQL sur la même machine : tout au moins, des serveurs aussi récents que la version 4.0.2. Ce préfixe est particulièrement utilisé lorsque vous listez les options dans un fichier d'options. Une option peut ne pas être reconnue par une version du programme, avec le préfixe --loose, ou le préfixe loose dans un fichier d'options. Les versions du programme qui ne reconnaissent pas l'option émettront une alerte, mais ignoreront l'option. Cette stratégie requiert que les versions soient toutes en 4.0.2 ou plus récente, car les anciennes versions ne connaissent pas --loose.

4-3-2 - Fichier d'options my.cnf

Les programmes MySQL peuvent lire des options de démarrage depuis un fichier d'options (aussi appelé fichier de configuration). Les fichiers d'options fournissent un moyen pratique de spécifier les options les plus courantes pour éviter de les saisir à chaque lancement du programme. Cette fonctionnalité est fournie depuis MySQL version 3.22.

Les programmes suivants supportent les fichiers d'options : myisamchk, myisampack, mysql, mysql.server, mysqladmin, mysqlbinlog, mysqlcc, mysqlcheck, mysqld_safe, mysqldump, mysqld, mysqlhotcopy, mysqlimport et mysqlshow.

MySQL lit les fichiers d'options suivants sous Windows :

Fichier

Contenu

WINDIR\my.ini

Options globales

C:\my.cnf

Options globales

WINDIR représente votre dossier Windows. Il est généralement C:\Windows ou C:\WinNT. Vous pouvez déterminer sa localisation exacte à partir de la variable d'environnement WINDIR avec cette commande :

C:\> echo %WINDIR%

MySQL lit les options par défaut dans les fichiers suivants sous Unix :

Fichier

Objet

/etc/my.cnf

Options globales

DATADIR/my.cnf

Options spécifiques au serveur

defaults-extra-file

Le fichier spécifié par --defaults-extra-file=#

~/.my.cnf

Options spécifiques à l'utilisateur

DATADIR est le dossier de données de MySQL (typiquement /usr/local/mysql/data pour les installations binaires ou /usr/local/var pour une installation source). Notez que c'est ce dossier qui a été spécifié au moment de la configuration et non pas le dossier de l'option --datadir lorsque mysqld démarre ! (--datadir n'a aucun effet sur le serveur, car le serveur recherche les données avant de traiter les options de ligne de commande).

MySQL essaie de lire les fichiers d'options dans l'ordre dans lequel ils sont présentés ci-dessus. Si un fichier d'options n'existe pas, vous pouvez le créer avec un éditeur de texte. Si des options sont spécifiées plusieurs fois, la dernière occurrence utilisée prend la préséance sur les options spécifiées avant.

Toutes les options longues qui peuvent être données en ligne de commande, peuvent être mises dans un fichier d'options. Pour avoir la liste des options d'un programme, utilisez la commande --help.

La syntaxe de spécification dans un fichier d'options est similaire à celle de ligne de commande, hormis le fait que vous omettez les deux tirets initiaux. Par exemple, --quick et --host=localhost en ligne de commande deviennent quick et host=localhost dans un fichier d'options. Pour spécifier une option de la forme --loose-opt_name dans un fichier d'options, écrivez-la sous la forme loose-opt_name.

Les lignes vides du fichier d'options sont ignorées. Un fichier d'options contient des lignes ayant la forme suivante :

- #comment, ;comment

Les lignes de commentaires commencent avec '#' ou ';'. Depuis MySQL 4.0.14, un commentaire '#' peut être ouvert au milieu de la ligne ;

- [group]

group est le nom du programme ou du groupe pour lequel vous souhaitez configurer des options. Après une ligne de groupe, toutes les option et set-variable s'appliqueront au groupe nommé, jusqu'à la fin du fichier d'options ou du démarrage d'un autre groupe ;

- opt_name

Ceci est équivalent à --opt_name sur la ligne de commande ;

- opt_name=value

Ceci est équivalent à --opt_name=value sur la ligne de commande. Dans un fichier d'options, vous pouvez mettre des espaces autour du caractère '=', ce qui n'est pas vrai en ligne de commande. Depuis MySQL 4.0.16, vous pouvez mettre les valeurs des options entre guillemets simples ou doubles. C'est utile lorsqu'une valeur contient un début de commentaire '#' ou des espaces ;

- set-variable = variable=value

Donne à la variable programme var_name sa valeur. Ceci est équivalent à --set-variable variable=value sur la ligne de commande. Cette syntaxe doit être utilisée pour spécifier la valeur d'une variable mysqld. Les espaces sont autorisés autour du premier caractère '=' mais pas autour du second. Notez que --set-variable est obsolète depuis MySQL 4.0, utilisez simplement --variable=value comme tel. Voyez Section 4.3.4, « Utiliser les options pour configurer des variables de programme » pour plus d'informations sur la spécification des variables programme.

Les espaces initiaux et terminaux sont automatiquement effacés autour des noms d'options et de leur valeur. Vous pouvez utilisez les séquences spéciales '\b', '\t', '\n', '\r', '\\' et '\s' dans les valeurs des options pour représenter des effacement, tabulations, nouvelles lignes, retour chariot et espaces.

Sous Windows, si une valeur d'option représente un chemin de dossier, vous devez spécifier la valeur en utilisant '/' plutôt que '\' comme séparateur de dossiers. Si vous utilisez use '\', vous devez le doubler '\\', car '\' est le caractère de protection de MySQL.

Si un groupe d'options est le même que le nom d'un programme, les options de ce groupe seront réservées à ce programme.

Le groupe d'options [client] est lu par tous les programmes clients et pas par le serveur mysqld. Cela vous permet de spécifier les options qui s'appliqueront à tous les clients. Par exemple, [client] est le groupe parfait pour spécifier le mot de passe que vous utilisez pour vous connecter au serveur. Mais assurez-vous que le fichier est lisible et modifiable uniquement par vous-même pour que personne ne puisse découvrir votre mot de passe. Assurez-vous de n'utiliser que des options qui seront reconnues par tous les programmes clients. Les programmes qui ne comprennent pas une option vont afficher un message d'erreur lorsque vous les exécuterez.

Depuis MySQL 4.0.14, si vous voulez créer des groupes d'options qui ne doivent être lus que par une version spécifique du serveur mysqld, vous pouvez le faire en utilisant des groupes avec des noms du type [mysqld-4.0], [mysqld-4.1], etc. Le groupe suivant indique que l'option --new soit utilisée avec les serveurs de version 4.0.x :

[mysqld-4.0]
new

Voici un fichier d'options globales typique :

[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
port=3306
socket=/tmp/mysql.sock
key_buffer_size=16M
max_allowed_packet=8M

[mysqldump]
quick

Le fichier d'options ci-dessus utilise la syntaxe var_name=value pour les variables key_buffer_size et max_allowed_packet. Avant MySQL 4.0.2, vous auriez besoin d'utiliser la syntaxe set-variable à la place (comme présenté précédemment).

Voici un fichier d'options utilisateur classique :

[client]
# Le mot de passe suivant sera envoyé par tous les clients standard MySQL
password="my_password"

[mysql]
no-auto-rehash
set-variable = connect_timeout=2

[mysqlhotcopy]
interactive-timeout

Ce fichier d'options utilise la syntaxe set-variable pour spécifier la variable connect_timeout. Depuis MySQL 4.0.2, vous pouvez aussi configurer la variable avec connect_timeout=2.

Si vous avez une distribution source, vous trouverez des exemples de configuration dans les fichiers nommés my-xxxx.cnf dans le dossier support-files. Si vous avez une distribution binaire, regardez dans le dossier DIR/support-files, où DIR est le chemin de l'installation MySQL (typiquement /usr/local/mysql). Actuellement, il y a des exemples de configuration pour des systèmes petits, moyens, grands et très grands. Vous pouvez copier l'un des fichiers my-xxxx.cnf dans votre dossier utilisateur (renommez le fichier en .my.cnf) pour le tester.

Note : sous Windows, le fichier d'options .cnf peut ne pas afficher son extension.

Tous les programmes MySQL qui supportent les fichiers d'options gèrent les options suivantes de ligne de commande :

- --no-defaults

N'utilise aucun fichier d'options ;

- --print-defaults

Affiche le nom du programme et toutes les options qui seront lues dans les fichiers d'options ;

- --defaults-file=path_name

Utilise uniquement le fichier d'options indiqué. path_name est le chemin complet pour y accéder ;

- --defaults-extra-file=path_name

Lit ce fichier d'options après le fichier d'options globales, et avant le fichier d'options utilisateurs. path_name est le chemin complet pour y accéder.

Pour fonctionner correctement, toutes ces options doivent immédiatement suivre le nom de la commande en ligne, hormis --print-defaults qui peut être utilisée juste après --defaults-file et --defaults-extra-file.

Dans les scripts Shell, vous pouvez utiliser le programme my_print_defaults pour analyser les fichiers d'options. L'exemple suivant montre le résultat que my_print_defaults peut produire lorsqu'on lui demande d'afficher les options des groupes [client] et [mysql] :

shell> my_print_defaults client mysql
--port=3306
--socket=/tmp/mysql.sock
--no-auto-rehash

Note pour les développeurs : la gestion des fichiers est implémentée en C dans la bibliothèque cliente simplement en traitant les options qui sont trouvées, (c'est-à-dire, les options du groupe appropriée), et avant les options de ligne de commande. Cela fonctionne correctement avec les programmes qui utilisent la dernière option des options spécifiées plusieurs fois. Mais si vous avez un programme C ou C++ qui gère les options de cette manière, mais ne lit pas les fichiers d'options, vous aurez peut-être à ajouter seulement deux lignes pour lui donner cette fonctionnalité. Voyez le code source des clients MySQL standard pour voir comment faire.

De nombreux autres langages s'interfacent avec MySQL grâce à la bibliothèque C, et certains fournissent un moyen d'accéder aux fichiers d'options. Cela inclut les langages Perl et Python. Voyez la documentation de votre interface favorite pour plus de détails.

4-3-3 - Utiliser les variables d'environnement pour spécifier des options

Pour spécifier des options en utilisant des variables d'environnement, utilisez la commande d'affectation de votre système. Par exemple, sous Windows ou sous NetWare, vous pouvez utiliser la variable USER pour spécifier votre compte utilisateur. Utilisez cette syntaxe :

SET USER=your_name

La syntaxe sous Unix dépend de votre Shell. Supposons que vous voulez spécifier le numéro de port TCP/IP en utilisant la variable MYSQL_TCP_PORT. La syntaxe Bourne Shell et ses variantes sont (sh, bash, zsh, etc.) est :

MYSQL_TCP_PORT=3306

Pour csh et tcsh, utilisez cette syntaxe :

setenv MYSQL_TCP_PORT 3306

Les commandes pour spécifier les variables d'environnement peuvent être exécutées à l'invite de commande, et prennent effet immédiatement. Ces configurations persistent jusqu'à votre déconnexion. Pour que ces configurations soient effectives lors de votre reconnexion, ajoutez les commandes appropriées dans votre fichier de démarrage. Typiquement, les fichiers de démarrage sont AUTOEXEC.BAT sous Windows, .bash_profile pour bash, ou .tcshrc pour tcsh. Consultez la documentation de votre interpréteur de ligne de commande pour les détails spécifiques.

La section Annexe E, Variables d'environnement liste toutes les variables d'environnement qui affectent le fonctionnement de MySQL.

4-3-4 - Utiliser les options pour configurer des variables de programme

De nombreux programmes MySQL ont des variables internes, qui peuvent être modifiées durant l'exécution. Depuis MySQL version 4.0.2, les variables de programme peuvent être spécifiées de la même façon que toute autre option qui prend une valeur. Par exemple, le client mysql utilise la variable max_allowed_packet qui contrôle la taille maximale du buffer de communication. Pour spécifier la variable max_allowed_packet de mysql, à une valeur de 16 Mo, utilisez l'une de ces deux commandes :

shell> mysql --max_allowed_packet=16777216
shell> mysql --max_allowed_packet=16M

La première commande spécifie la valeur en octets. La seconde spécifie la valeur en mégaoctets. Les valeurs des variables peuvent être suffixées par K, M ou G (majuscule ou minuscule), pour indiquer une unité de kilooctets, mégaoctets ou gigaoctets.

Dans un fichier d'options, la configuration de la variable se fait sans les tirets initiaux :

[mysql]
max_allowed_packet=16777216

ou :

[mysql]
max_allowed_packet=16M

Si vous voulez, les soulignés d'un nom de variable peuvent être spécifiés comme des tirets.

Avant MySQL 4.0.2, les noms de variables de programmes n'étaient pas reconnus comme des noms d'options. Au lieu de cela, il faut utiliser l'option --set-variable pour assigner une valeur :

shell> mysql --set-variable=max_allowed_packet=16777216
shell> mysql --set-variable=max_allowed_packet=16M

Dans un fichier d'options, omettez les tirets initiaux :

[mysql]
set-variable = max_allowed_packet=16777216

ou :

[mysql]
set-variable = max_allowed_packet=16M

Avec --set-variable, les soulignés d'un nom de variable ne peuvent pas être spécifiés sous forme de tiret dans les versions de MySQL plus anciennes que la 4.0.2.

L'option --set-variable est toujours reconnue par MySQL versions 4.0.2 et plus récentes, mais elle est obsolète.

Certaines variables serveur peuvent être configurées durant l'exécution. Voyez la section Section 5.2.3.1, « Variables système dynamiques ».

5 - Administration du serveur

Ce chapitre couvre les problèmes d'administration de MySQL, comme la configuration des comptes et les sauvegardes.

5-1 - Scripts serveur MySQL et utilitaires

Le serveur MySQL, mysqld, est le programme principal qui effectue l'essentiel du travail. Le serveur est accompagné par différents scripts connexes qui effectuent des opérations de configuration lors de l'installation, ou fournissent de l'aide pour administrer le serveur.

Cette section fournit une introduction au serveur et ses utilitaires, et des informations sur les scripts de démarrage. Les informations sur la configuration du serveur lui-même sont données dans la section Section 5.2, « Configuration de MySQL ».

5-1-1 - Présentation des scripts serveur et des utilitaires

Tous les programmes MySQL prennent des options différentes. Toutefois, tous les programmes MySQL disposent de l'option --help qui vous aidera à connaître la liste complète des différentes options. Par exemple, essayez mysql --help.

Vous pouvez modifier toutes les valeurs par défaut des programmes en les plaçant dans le fichier de configuration. Section 4.3.2, « Fichier d'options my.cnf ».

Voici la liste des programmes côté serveur de MySQL.

- mysqld

Le démon SQL (c'est-à-dire, le serveur MySQL). Pour utiliser les programmes clients, ce programme doit fonctionner, car les clients viendront se connecter dessus. Voir Section 5.2, « Configuration de MySQL ».

- mysqld-max

Une version du serveur qui inclut des fonctionnalités supplémentaires. Voir Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld ».

- mysqld_safe

Un script de démarrage du serveur. mysqld_safe tente de démarrer mysqld-max s'il existe, et sinon mysqld. Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ».

- mysql.server

Un script de démarrage du serveur. Ce script est utilisé sur les systèmes qui ont un dossier contenant des services système. Il invoque mysqld_safe pour démarrer le serveur MySQL. Voir Section 5.1.4, « Le script de démarrage mysql.server ».

- mysqld_multi

Un script de démarrage qui peut lancer ou arrêter différentes instances du serveur, installées sur le système. Voir Section 5.1.5, « mysqld_multi, un programme pour gérer plusieurs serveurs MySQL ».

- mysql_install_db

Crée les tables de droits MySQL, avec les droits par défaut. Il est généralement exécuté une fois, lors de la première installation de MySQL.

- mysql_fix_privilege_tables

Ce script est utilisé après une mise à jour de MySQL, pour mettre à jour les tables de droits, et les adapter aux nouvelles versions de MySQL.

Il y a plusieurs autres utilitaires qui fonctionnent du côté du serveur.

- myisamchk

Un utilitaire pour décrire, vérifier, optimiser et réparer les tables MyISAM. myisamchk est décrit dans Section 5.7.3, « Utilisation de myisamchk pour la maintenance des tables et leur recouvrement ».

- make_binary_distribution

Ce programme crée une version compilée de MySQL. Le résultat peut être envoyé par FTP à /pub/mysql/Incoming sur support.mysql.com pour aider les autres utilisateurs MySQL.

- mysqlbug

Le script de rapport de bogues de MySQL. Il peut être utilisé pour envoyer un rapport de bogues à MySQL. Vous pouvez aussi aller sur http://bugs.mysql.com/ pour remplir un formulaire en ligne.

5-1-2 - mysqld-max, la version étendue du serveur mysqld

Le serveur MySQL-Max est une version du serveur mysqld qui a été compilée avec des fonctionnalités supplémentaires.

La distribution à utiliser dépend de votre plate-forme.

- Sous Windows, les distributions binaires MySQL incluent le serveur standard (mysqld.exe) et le serveur MySQL-Max (mysqld-max.exe), alors il n'y a pas de téléchargement spécial à faire. Utilisez simplement la distribution Windows habituelle, disponible sur http://dev.mysql.com/downloads/mysql-4.0.html. Voir Section 2.2.1, « Installer MySQL sous Windows ».

- Sous Linux, si vous installez une distribution RPM, utilisez le RPM MySQL-server standard pour installer le serveur mysqld. Puis, utilisez le RPM MySQL-Max pour installer le serveur mysqld-max. Le RPM MySQL-Max suppose que vous avez déjà installé le serveur régulier RPM. Voyez Section 2.2.12, « Installer MySQL sous Linux » pour plus d'informations sur les paquets Linux RPM.

- Toutes les autres distributions de MySQL-Max contiennent un serveur unique, appelé mysqld, mais qui inclut les fonctionnalités supplémentaires.

Vous pouvez trouver les distributions binaires sur le site web de MySQL AB, sur http://dev.mysql.com/downloads/mysql-4.0.html.

MySQL AB compile le serveur MySQL-Max avec les options de configure suivantes.

- --with-server-suffix=-max

Cette option ajoute le suffixe -max à la chaîne de version de mysqld.

- --with-innodb

Cette option active le support du moteur InnoDB. MySQL-Max inclut toujours le support d'InnoDB, mais cette option est nécessaire pour MySQL 3.23. Depuis MySQL 4, InnoDB est inclus par défaut dans les distributions binaires, alors il n'est pas nécessaire d'utiliser MySQL-Max pour ça.

- --with-bdb

Cette option active le support du moteur de table Berkeley DB (BDB).

- CFLAGS=-DUSE_SYMDIR

Cette option active le support des liens symboliques sous Windows.

Les distributions binaires de MySQL-Max sont disponibles pour ceux qui souhaitent installer une version précompilée. Si vous voulez compiler MySQL-Max depuis les sources, vous pouvez le faire et choisir les fonctionnalités que vous souhaitez au moment de la compilation.

Le serveur MySQL-Max inclut le moteur de stockage BerkeleyDB (BDB) lorsque c'est possible, mais toutes les plates-formes ne supportent pas BDB. La table suivante montre quelles plates-formes permettent à MySQL-Max d'inclure BDB :

Système

BDB Support

AIX 4.3

N

HP-UX 11.0

N

Linux-Alpha

N

Linux-IA-64

N

Linux-Intel

Y

Mac OS X

N

NetWare

N

SCO OSR5

Y

Solaris-Intel

N

Solaris-SPARC

Y

UnixWare

Y

Windows/NT

Y

Pour connaître les moteurs de stockage que votre serveur supporte, utilisez la commande suivante :

mysql> SHOW ENGINES;

Avant MySQL 4.1.2, SHOW ENGINES est indisponible. Utilisez la commande suivante et vérifiez la valeur de la variable pour le moteur de tables qui vous intéresse :

mysql> SHOW VARIABLES LIKE 'have_%';
+------------------+----------+
| Variable_name    | Value    |
+------------------+----------+
| have_bdb         | NO       |
| have_crypt       | YES      |
| have_innodb      | YES      |
| have_isam        | NO       |
| have_raid        | NO       |
| have_symlink     | DISABLED |
| have_openssl     | NO       |
| have_query_cache | YES      |
+------------------+----------+

La signification des valeurs est :

Valeur

Signification

YES

L'option est activée et utilisable.

NO

L'option n'est pas supportée.

DISABLED

L'option est supportée mais désactivée.

La valeur NO signifie que le serveur a été compilé sans le support, et que la fonctionnalité ne peut pas être activée durant l'exécution.

La valeur de DISABLED apparait soit parce que le serveur a été lancé sans l'option qui active cette fonctionnalité, soit si toutes les options nécessaires ne sont pas disponibles. Dans ce dernier cas, le fichier d'erreurs host_name.err devrait contenir la raison indiquant pourquoi l'option a été désactivée.

Une situation dans laquelle vous pouvez voir DISABLED survient en version MySQL 3.23, lorsque le moteur InnoDB est compilé. En MySQL 3.23, vous devez fournir au moins l'option innodb_data_file_path à l'exécution pour configurer l'espace de tables InnoDB. Sans cette option, InnoDB se désactive. Voir Section 15.3, « InnoDB avec MySQL version 3.23 ». Vous pouvez spécifier les options de configuration pour les tables BDB, mais BDB ne se désactivera pas de lui-même si vous les oubliez. Voir Section 14.4.3, « Options de démarrage BDB ».

Vous pouvez aussi rencontrer la valeur de DISABLED pour InnoDB, BDB, ou ISAM si le serveur a été compilé pour les supporter, mais également les options de démarrage --skip-innodb, --skip-bdb ou --skip-isam à l'exécution.

Depuis la version 3.23, tous les serveurs MySQL supportent les tables MyISAM, car le moteur MyISAM est le moteur par défaut.

5-1-3 - safe_mysqld, le script père de mysqld

safe_mysqld est la méthode recommandée pour démarrer un démon mysqld sous Unix. safe_mysqld ajoute des fonctionnalités de sécurité telles que le redémarrage automatique lorsqu'une erreur survient et l'enregistrement d'informations d'exécution dans un fichier de logs.

Note : avant MySQL 4.0, mysqld_safe s'appelait safe_mysqld. Pour préserver la compatibilité ascendante, la distribution binaire MySQL propose un lien symbolique de safe_mysqld vers mysqld_safe.

Par défaut, mysqld_safe essaie de lancer l'exécutable appelé mysqld-max s'il existe, ou mysqld sinon. Cela a des implications.

- Sous Linux, le RPM MySQL-Max dépend de mysqld_safe. Le RPM installe un exécutable appelé mysqld-max, qui fait que mysqld_safe va automatiquement utiliser l'exécutable installé.

- Si vous installez la distribution MySQL-Max qui inclut un serveur appelé mysqld-max, puis que vous le mettez à jour avec une version non max, mysqld_safe va essayer d'utiliser l'ancien serveur mysqld-max. Si vous faites une telle mise à jour, supprimez manuellement l'ancien serveur mysqld-max pour vous assurer que mysqld_safe utilise le nouveau mysqld.

Pour remplacer le comportement par défaut et spécifier explicitement le serveur que vous voulez utiliser, spécifiez l'option --mysqld ou --mysqld-version avec mysqld_safe.

De nombreuses options de mysqld_safe sont identiques aux options de mysqld. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Toutes les options spécifiées avec mysqld_safe en ligne de commande sont passées à mysqld. Si vous voulez utiliser des options qui sont spécifiques à mysqld_safe et que mysqld ne les supporte pas, ne les spécifiez pas en ligne de commande. Au lieu de cela, listez-les dans le groupe [mysqld_safe] du fichier d'options. Voir Section 4.3.2, « Fichier d'options my.cnf ».

mysqld_safe lit toutes les options des groupes [mysqld], [server] et [mysqld_safe] dans le fichier d'options. Pour assurer la compatibilité ascendante, il lit aussi le groupe [safe_mysqld]. Vous devriez renommer ces sections [mysqld_safe] lorsque vous passez à MySQL 4.0 ou plus récent.

safe_mysqld supporte les options suivantes.

- --basedir=path

Le chemin jusqu'à l'installation de MySQL.

- --core-file-size=#

Taille du fichier core que mysqld doit être capable de créer. Il est passé à ulimit -c.

- --datadir=path

Le chemin jusqu'au dossier de données.

- --defaults-extra-file=path

Le nom du fichier d'options à lire en plus des fichiers habituels.

- --defaults-file=path

Le nom d'un fichier d'options qui doit être lu à la place du fichier d'options habituel.

- --err-log=path

L'ancienne option --log-error, à utiliser avant MySQL 4.0.

- --ledir=path

Le chemin jusqu'au dossier contenant le dossier mysqld. Utilisez cette option pour indiquer explicitement le lieu du serveur.

- --log-error=path

Écrit le fichier d'erreurs dans le fichier ci-dessus. Voir Section 5.9.1, « Le log d'erreurs ».

- --mysqld=prog_name

Le nom du programme serveur (dans le dossier ledir) que vous voulez lancer. Cette option est nécessaire si vous utilisez une distribution binaire MySQL, mais que les données sont hors du dossier d'installation.

- --mysqld-version=suffix

Cette option est similaire à l'option --mysqld, mais vous spécifiez uniquement le suffixe du nom du programme. Le nom de base sera alors mysqld. Par exemple, si vous utilisez --mysqld-version=max, mysqld_safe va lancer le programme mysqld-max dans le dossier ledir. Si l'argument de --mysqld-version est vide, mysqld_safe utilise mysqld dans le dossier ledir.

- --nice=priority

Utilise le programme nice pour donner la priorité du serveur. Cette option a été ajoutée en MySQL 4.0.14.

- --no-defaults

Ne lit aucun fichier d'options.

- --open-files-limit=count

Le nombre de fichiers que mysqld ouvre au maximum. La valeur de l'option est passée à ulimit -n. Notez que vous devez lancer mysqld_safe en tant que root pour que cela fonctionne correctement.

- --pid-file=path

Le chemin jusqu'au fichier d'identifiant de processus.

- --port=port_num

Le numéro de port à utiliser pour attendre les connexions TCP/IP.

- --socket=path

Le fichier de socket Unix pour les connexions locales.

- --timezone=zone

Configure la variable d'environnement TZ. Consultez votre documentation système pour connaître le format légal des fuseaux horaires.

- --user={user_name | user_id}

Lance le serveur mysqld sous le nom d'utilisateur user_name ou avec l'utilisateur d'identifiant numérique ID user_id. (« Utilisateur » dans ce contexte représente le compte système, et non pas les utilisateurs des tables de droits MySQL).

Le script safe_mysqld a été écrit pour qu'il soit capable de démarrer le serveur qui a été installé à partir des sources ou de la version binaire, même si l'installation de MySQL est légèrement exotique. Voir Section 2.1.5, « Dispositions d'installation ». safe_mysqld suppose que les conditions suivantes sont remplies :

- le serveur et les bases de données sont placés dans un dossier relativement au dossier d'où safe_mysqld est appelé. safe_mysqld cherche dans les sous-dossiers bin et data (pour les distributions binaires) et, libexec et var (pour les distributions source). Cette condition doit être remplie si vous exécutez safe_mysqld depuis votre dossier d'installation MySQL (par exemple, /usr/local/mysql pour une distribution binaire) ;

- si le serveur et les bases de données ne peuvent être trouvés dans le dossier de travail, safe_mysqld essaie de les trouver en utilisant leur chemin absolu. Les chemins typiquement étudiés sont /usr/local/libexec et /usr/local/var. Les chemins réels sont déterminés lorsque la distribution est compilée, et safe_mysqld a alors aussi été généré. Ils doivent être corrects si MySQL a été installé dans un dossier standard.

Comme safe_mysqld essaie de trouver le serveur et les bases dans un dossier situé dans le dossier de travail, vous pouvez installer la version binaire de MySQL n'importe où, du moment que vous démarrez le script safe_mysqld dans le dossier d'installation de MySQL :

shell> cd mysql_installation_directory
shell> bin/safe_mysqld &

Si safe_mysqld échoue, même s'il est appelé depuis le dossier d'installation, vous pouvez le modifier pour qu'il reconnaisse le chemin que vous utilisez jusqu'à mysqld. Notez que si vous faites évoluer votre installation de MySQL, votre version de safe_mysqld sera écrasée, et vous devrez la rééditer.

Normalement, vous ne devez pas éditer le script mysqld_safe. Au lieu de cela, configurez mysqld_safe en utilisant les options de ligne de commande, ou les options de la section [mysqld_safe] du fichier d'options my.cnf. Dans de rares cas, il sera peut-être nécessaire d'éditer mysqld_safe pour faire fonctionner correctement le serveur. Cependant, si vous faites cela, mysqld_safe risque d'être écrasé lors de la prochaine mise à jour de MySQL : faites-en une sauvegarde avant d'installer.

Sous NetWare, mysqld_safe est un NetWare Loadable Module (NLM) qui est un port du script Unix original. Il fait ceci :

1. Effectue des vérifications système et des options ;

2. Lance la vérification des tables MyISAM et ISAM ;

3. Affiche un écran de présence de MySQL ;

4. Lance mysqld, le surveille et le relance s'il s'arrête sur une erreur ;

5. Envoie les messages de mysqld dans le fichier host_name.err dans le dossier de données ;

6. Envoie les affichages de mysqld_safe dans le fichier host_name.safe dans le dossier de données.

5-1-4 - Le script de démarrage mysql.server

Les distributions MySQL sous Unix incluent un script appelé mysql.server. Il peut être utilisé pour lancer et arrêter les services. Il est aussi utilisé par le script de démarrage de Max OS X.

mysql.server est placé dans le dossier support-files sous le dossier d'installation de MYSQL, ou dans le dossier de source.

Si vous utilisez le paquet RPM pour Linux (MySQL-server-VERSION.rpm), le script mysql.server sera déjà installé dans le dossier /etc/init.d sous le nom de mysql. Vous n'avez pas besoin de l'installer manuellement. Voyez Section 2.2.12, « Installer MySQL sous Linux » pour plus d'informations sur les paquets MySQL RPM Linux.

Certains éditeurs fournissent des paquets RPM qui installent un script de démarrage sous le nom de mysqld.

Si vous installez MySQL depuis une distribution source, ou en utilisant une distribution binaire qui n'installe pas automatiquement le fichier mysql.server, vous pouvez l'installer manuellement. Les instructions sont fournies dans la section Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ».

mysql.server lit les options dans les sections [mysql.server] et [mysqld] du fichier de configuration. Pour la compatibilité ascendante, il lit aussi la section [mysql_server], même si vous devrez la renommer en [mysql.server] lorsque vous commencerez à utiliser MySQL 4.0.

5-1-5 - mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

mysqld_multi sert à gérer plusieurs serveurs mysqld qui utilisent différentes sockets Unix et ports TCP/IP.

Le programme va rechercher les groupes nommés [mysqld#] dans le fichier my.cnf (ou le fichier appelé --config-file=...), où # peut être n'importe quel nombre positif, supérieur ou égal à 1. Ce nombre est appelé le numéro de groupe d'options. Les numéros de groupe permettent de distinguer un groupe d'options d'un autre, et sont utilisés comme argument du script mysqld_multi pour spécifier quel serveur vous voulez démarrer, arrêter ou examiner. Les options listées dans ces groupes doivent être les mêmes que celles que vous utiliseriez dans une section dédiée au démon [mysqld]. Voyez, par exemple, Section 2.5.2.2, « Lancer et arrêter MySQL automatiquement ». Cependant, pour mysqld_multi, vous devez vous assurer que chaque groupe contient des valeurs pour les options telles que port, socket, etc., qui seront utilisées par chaque processus mysqld. Pour plus d'informations sur les options de chaque serveur dans un environnement à serveurs multiples, voyez la section Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine ».

mysqld_multi est utilisé avec la syntaxe suivante :

shell> mysqld_multi [options] {start|stop|report} [GNR[,GNR]...]

start, stop et report indiquent le type d'opération que vous voulez faire. Vous pouvez faire une opération sur un serveur unique ou plusieurs serveurs, en fonction de la liste GNR qui suit le nom de l'opération. S'il n'y a pas de liste, mysqld_multi effectue l'opération sur tous les serveurs du fichier d'options.

Chaque GNR représente un numéro de groupe d'options. Vous pouvez démarrer, arrêter ou examiner n'importe quel numéro de groupe d'options, ou même plusieurs d'entre eux en même temps. Par exemple, le groupe GNR pour le groupe appelé [mysqld17] est 17. Pour spécifier un intervalle de nombres, séparez le premier et le dernier numéro par un tiret. La valeur GNR 10-13 représente les groupes de [mysqld10] à [mysqld13]. Les groupes multiples ou les intervalles de groupes peuvent être spécifiés en ligne de commande, séparés par des virgules. Il ne doit pas y avoir d'espace blanc entre deux éléments de la liste : tout ce qui sera après un espace sera ignoré.

Cette commande lance un serveur unique, avec le groupe d'options [mysqld17] :

shell> mysqld_multi start 17

Cette commande arrête plusieurs serveurs, en utilisant les groupes d'options [mysql8] et [mysqld10] à [mysqld13] :

shell> mysqld_multi start 8,10-13

Pour afficher un exemple de configurations, utilisez cette commande :

shell> mysqld_multi --example

Les valeurs de numéro de groupe d'options peuvent être une liste de valeurs séparées par une virgule ou un tiret. Dans ce dernier cas, tous les numéros de groupe d'options situés entre les deux numéros seront alors affectés. Sans numéro de groupe d'options spécifié, tous les numéros de groupes du fichier d'options sont affectés. Notez que vous ne devez pas avoir d'espace dans la liste des numéros de groupe d'options. Tout ce qui est placé au-delà de l'espace sera ignoré.

mysqld_multi supporte les options suivantes.

- --config-file=name

Un fichier de configuration alternatif. Note : cela ne va pas modifier les options de ce programme ([mysqld_multi]), mais uniquement les groupes [mysqld#]. Sans cette option, tout sera lu dans le fichier d'options traditionnel my.cnf. Cette option n'affecte pas la façon avec laquelle mysqld_multi lit ses options, qui sont toujours prises dans le groupe [mysqld_multi] du fichier my.cnf habituel.

- --example

Affiche un exemple de fichier de configuration.

- --help

Affiche l'aide et quitte.

- --log=name

Fichier de log. Le chemin complet et le nom du fichier sont nécessaires.

- --mysqladmin=prog_name

L'exécutable mysqladmin à utiliser lors de l'arrêt du serveur.

- --mysqld=prog_name

L'exécutable mysqld à utiliser. Notez que vous pouvez donner cette option à safe_mysqld. Ces options sont passées à mysqld. Assurez-vous que vous avez bien mysqld dans votre variable d'environnement PATH ou corrigez safe_mysqld.

- --no-log

Affiche les données d'historique à l'écran plutôt que dans le fichier de logs. Par défaut, le fichier de logs est activé.

- --password=password

Le mot de passe de l'utilisateur mysqladmin.

- --tcp-ip

Connexion au serveur MySQL via le port TCP/IP au lieu du socket Unix. Cela affecte l'arrêt et le rapport. Si le fichier de socket manque, le serveur peut continuer de tourner, mais il n'est plus accessible que par port TCP/IP. Par défaut, les connexions sont faites avec les sockets Unix.

- --user=user_name

L'utilisateur MySQL pour mysqladmin.

- --version

Affiche le numéro de version et quitte.

Quelques notes pour mysqld_multi.

- Assurez-vous que l'utilisateur MySQL, qui stoppe les services mysqld (e.g en utilisant la commande mysqladmin), a les mêmes nom d'utilisateur et mot de passe pour tous les dossiers de données utilisés. Et assurez-vous que cet utilisateur a bien les droits de SHUTDOWN ! Si vous avez de nombreux dossiers de données et de nombreuses bases mysql avec différents mots de passe pour le serveur root MySQL, vous souhaiterez peut-être créer un utilisateur commun multi_admin à chaque base, avec le même mot de passe (voir ci-dessous). Voici comment faire :

shell> mysql -u root -S /tmp/mysql.sock -proot_password -e
"GRANT SHUTDOWN ON *.* TO multi_admin@localhost IDENTIFIED BY 'multipass'"

Voir Section 5.5.2, « Comment fonctionne le système de droits ». Vous devrez utiliser la même commande pour chaque serveur mysqld qui fonctionne : changez simplement la socket, -S=...).

- pid-file est très important, si vous utilisez safe_mysqld pour démarrer mysqld (e.g., --mysqld=safe_mysqld). Chaque mysqld doit avoir son propre fichier pid-file. L'avantage d'utiliser safe_mysqld au lieu de mysqld est que safe_mysqld « surveille » tous les processus mysqld et les redémarrera si un processus mysqld s'arrête suite à la réception d'un signal kill -9, ou pour toute autre raison comme une erreur de segmentation (que MySQL ne devrait jamais faire, bien sûr !). Notez bien que le script safe_mysqld vous imposera peut-être d'être démarré depuis un dossier spécial. Cela signifie que vous devrez probablement utiliser la commande shell cd jusqu'à un certain dossier avant de pouvoir exécuter mysqld_multi. Si vous avez des problèmes pour démarrer, voyez le script safe_mysqld. Vérifiez notamment ces lignes :

----------------------------------------------------------------
MY_PWD=`pwd`
# Check if we are starting this relative (for the binary release)
if test -d $MY_PWD/data/mysql -a -f ./share/mysql/english/errmsg.sys -a \
-x ./bin/mysqld
----------------------------------------------------------------

Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ». Le test ci-dessus devrait fonctionner, ou bien vous rencontrerez probablement des problèmes.

- Le fichier de socket et le port TCP/IP doivent être différents pour chaque mysqld.

- Vous pouvez utiliser l'option --user de mysqld, mais afin de faire cela, vous devez exécuter le script mysqld_multi en tant que root Unix. Placer cette option dans le fichier de configuration ne changera rien : vous obtiendrez une alerte, si vous n'êtes pas le superutilisateur, et les démons mysqld seront démarrés avec vos droits Unix.

- Important : assurez-vous bien que le fichier de données et le fichier de pid-file sont accessibles en lecture et écriture (et exécution pour le dernier) à l'utilisateur Unix qui lance les processus mysqld. N'utilisez pas le compte root Unix pour cela, à moins que vous ne sachiez ce que vous faites.

- Très important : assurez-vous de bien comprendre la signification des options que vous passez à mysqlds et pourquoi vous avez besoin de plusieurs processus mysqld. Méfiez-vous des pièges des serveurs multiples mysqld dans le même dossier de données. Utilisez des dossiers de données à moins que vous ne sachiez ce que vous faites. Démarrer plusieurs serveurs mysqlds dans le même dossier ne vous donnera aucun gain de performance dans un système threadé. Voir Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine ».

Voici un exemple de fichier de configuration fourni par mysqld_multi.

# This file should probably be in your home dir (~/.my.cnf) or /etc/my.cnf
# Version 2.1 by Jani Tolonen

[mysqld_multi]
mysqld     = /usr/local/bin/safe_mysqld
mysqladmin = /usr/local/bin/mysqladmin
user       = multi_admin
password   = multipass

[mysqld2]
socket     = /tmp/mysql.sock2
port       = 3307
pid-file   = /usr/local/mysql/var2/hostname.pid2
datadir    = /usr/local/mysql/var2
language   = /usr/local/share/mysql/english
user       = john

[mysqld3]
socket     = /tmp/mysql.sock3
port       = 3308
pid-file   = /usr/local/mysql/var3/hostname.pid3
datadir    = /usr/local/mysql/var3
language   = /usr/local/share/mysql/swedish
user       = monty

[mysqld4]
socket     = /tmp/mysql.sock4
port       = 3309
pid-file   = /usr/local/mysql/var4/hostname.pid4
datadir    = /usr/local/mysql/var4
language   = /usr/local/share/mysql/estonia
user       = tonu

[mysqld6]
socket     = /tmp/mysql.sock6
port       = 3311
pid-file   = /usr/local/mysql/var6/hostname.pid6
datadir    = /usr/local/mysql/var6
language   = /usr/local/share/mysql/japanese
user       = jani

Voir Section 4.3.2, « Fichier d'options my.cnf ».

5-2 - Configuration de MySQL

Cette section présente la configuration du serveur MySQL :

- options de démarrage que le serveur supporte ;

- comment utiliser le mode SQL du serveur ;

- les variables serveur ;

- les variables de statut du serveur.

5-2-1 - Options de ligne de commande de mysqld

Lorsque vous démarrez le serveur mysqld, vous pouvez spécifier les options de programme en utilisant les méthodes décrites dans la section Section 4.3, « Spécifier des options aux programmes ». Les méthodes les plus courantes sont celles du fichier d'options et celles de la ligne de commande. Cependant, dans la plupart des cas, vous devrez vous assurer que le serveur utilise toujours les mêmes options à chaque redémarrage : il est recommandé de les mettre dans le fichier d'options. Voir Section 4.3.2, « Fichier d'options my.cnf ».

mysqld et mysqld.server lisent les options des groupes mysqld et server. mysqld_safe lit les options des groupes mysqld, server, mysqld_safe et safe_mysqld. Un serveur MySQL intégré lit généralement les options dans les groupes server, embedded et xxxxx_SERVER, où xxxxx est le nom de l'application.

mysqld accepte de nombreuses options de ligne de commande. Pour une liste complète, utilisez la commande mysqld --help. Avant MySQL 4.1.1, --help affiche un message d'aide complet. Depuis 4.1.1, il affiche un bref message. Pour voir la liste complète, utilisez mysqld --verbose --help.

La liste suivante montre les options de serveur les plus courantes. Les options supplémentaires sont détaillées ailleurs.

- Options qui affectent la sécurité : voir Section 5.4.3, « Options de démarrage qui concernent la sécurité ».

- Options liées à SSL : voir Section 5.6.7.5, « Options SSL en ligne de commande ».

- Options de contrôle des logs binaires : voir Section 5.9.4, « Le log binaire ».

- Options de réplication : voir Section 6.8, « Options de démarrage de la réplication ».

- Options spécifiques à un moteur de table particulier : voir Section 14.1.1, « Options de démarrage MyISAM », Section 14.4.3, « Options de démarrage BDB », Section 15.5, « Options de démarrage InnoDB ».

Vous pouvez aussi modifier les valeurs des variables système en utilisant le nom de l'option comme variable système, tel que décrit ultérieurement.

- --help, -?

Affiche l'aide courte et termine le programme. Avant MySQL 4.1.1, --help affiche un message d'aide complet. Depuis 4.1.1, il affiche un bref message. Pour voir la liste complète, utilisez mysqld --verbose --help.

- --allow-suspicious-udfs

Cette option contrôle le fait que les fonctions utilisateur qui disposent d'un seul symbole xxx puissent être chargées. Par défaut, cette option est désactivée, et seules les UDF qui ont au moins un symbole auxiliaire peuvent être chargées. Cela évite de charger des fonctions issues d'un objet partagé qui ne serait pas une fonction utilisateur légitime. Cette option a été ajoutée en MySQL 4.0.24, 4.1.10a et 5.0.3. Voir Section 27.2.3.6, « Précautions à prendre avec les fonctions utilisateur ».

- --ansi

Utilise la syntaxe ANSI SQL au lieu de la syntaxe MySQL. Voir Section 1.5.3, « Exécuter MySQL en mode ANSI ». Pour un contrôle plus précis sur le mode SQL serveur, utilisez l'option --sql-mode.

- --basedir=path, -b path

Chemin jusqu'au dossier d'installation. Tous les chemins sont généralement relatifs à celui-ci.

- --big-tables

Autorise la sauvegarde de grands résultats dans des fichiers temporaires. Cela résout le problème des erreurs « table full », mais ralentit les requêtes alors que des tables en mémoire suffiraient. Depuis la version 3.23.2, MySQL est capable de résoudre automatiquement ce problème en utilisant de la mémoire pour toutes les tables temporaires de petite taille, et en passant sur le disque au besoin.

- --bind-address=IP

L'adresse IP à utiliser.

- --console

Écrit les messages d'erreur du log d'erreur sur la sortie standard, même si --log-error est spécifiée. Sous Windows, mysqld ne ferme pas l'écran de console si cette option est utilisée.

- --character-sets-dir=path

Dossier contenant les jeux de caractères. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --chroot=path

Met le démon mysqld en environnement chroot au démarrage. Recommandé pour la sécurité depuis MySQL 4.0. (MySQL 3.23 n'est pas capable de fournir un encadrement chroot() qui soit 100 % étanche). Cela limite les commandes LOAD DATA INFILE et SELECT ... INTO OUTFILE.

- --core-file

Écrire le fichier core lorsque mysqld s'arrête inopinément. Pour certains fichiers, vous devez aussi spécifier --core-file-size à safe_mysqld. Voir Section 5.1.3, « safe_mysqld, le script père de mysqld ». Notez que sur certains systèmes, comme Solaris, vous n'aurez pas de fichier de core si vous avez aussi utilisé l'option --user.

- --datadir=path, -h path

Chemin jusqu'au dossier de données.

- --debug[=debug_options], -# [debug_options]

Si MySQL est configuré avec --with-debug, vous pouvez utiliser cette option pour obtenir un fichier de trace de ce que mysqld fait. Voir Section D.1.2, « Créer un fichier de traçage ».

- --default-character-set=charset

Spécifie le jeu de caractères par défaut. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --default-collation=collation

Spécifie la collation par défaut. Cette option est disponible depuis MySQL 4.1.1. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --default-storage-engine=type

Cette option est un synonyme de --default-table-type. Cette option est disponible depuis MySQL 4.1.2.

- --default-table-type=type

Spécifie le type de table par défaut. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- --delay-key-write[= OFF | ON | ALL]

Comment l'option DELAYED KEYS doit être utilisée. Les écritures différées font que les buffers de clés ne sont pas écrits entre deux écritures pour les tables MyISAM. OFF désactive les écritures différées. ON active les écritures différées pour les tables qui ont été créées avec l'option DELAYED KEYS. ALL active les écritures différées pour les tables MyISAM. Cette option est disponible depuis MySQL 4.0.3. Voir Section 7.5.2, « Réglage des paramètres du serveur ». Voir Section 14.1.1, « Options de démarrage MyISAM ».

Note : si vous avez donné la valeur de ALL à cette option, vous ne devez pas utiliser les tables MyISAM depuis un autre programme (comme myisamchk) lorsque la table est utilisée. En faisant cela, vous obtiendrez une corruption d'index.

- --delay-key-write-for-all-tables

Ancienne forme de --delay-key-write=ALL à utiliser sur les versions antérieures à la version 4.0.3. Depuis la version 4.0.3, utilisez --delay-key-write.

- --des-key-file=file_name

Lit les clés par défaut utilisées par DES_ENCRYPT() et DES_DECRYPT() dans ce fichier.

- --enable-named-pipe

Active le support des pipes nommés (seulement sur NT/Win2000/XP). Cette option ne s'applique qu'aux systèmes Windows NT, 2000 et XP, et peut être utilisée avec les serveurs mysqld-nt et mysqld-max-nt qui supportent les pipes nommés.

- --exit-info, -T

Cette option est la combinaison d'options que vous pouvez utiliser pour le débogage du serveur mysqld. Si vous ne savez pas ce que ça fait exactement, ne l'utilisez pas !

- --external-locking

Active le verrouillage système. Notez que si vous utilisez cette option sur un système pour lequel lockd ne fonctionne pas (comme Linux), vous allez bloquer rapidement mysqld avec les verrous. Anciennement appelée --enable-locking.

Note : si vous utilisez cette option pour activer des modifications de tables MyISAM depuis plusieurs processus MySQL, vous devez vous assurer de trois conditions :

- vous n'utilisez pas de cache de requêtes pour les requêtes qui utilisent les tables sont modifiées par un autre processus ;

- vous ne devez pas utiliser --delay-key-write=ALL ou DELAY_KEY_WRITE=1 sur des tables partagées.

Le plus simple pour s'assurer de cela est de toujours utiliser l'option --external-locking avec --delay-key-write=OFF --query-cache-size=0.

(Ceci n'est pas fait par défaut, car dans de nombreuses configurations, il est pratique de faire un mélange des options ci-dessus).

- --flush

Écrit toutes les données sur le disque après chaque requête SQL. Normalement, MySQL fait des écritures sur le disque après chaque requête, et laisse le système d'exploitation assurer la synchronisation avec le disque. Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

- --init-file=file

Lit les commandes SQL dans ce fichier au démarrage. Chaque commande doit être sur une ligne, et ne pas utiliser de commentaires.

- --language=lang_name, -L lang_name

Spécifie la langue utilisée pour les messages d'erreur du client. Le chemin complet doit être utilisé. Voir Section 5.8.2, « Langue des messages d'erreurs ».

- --log[=file], -l [file]

Enregistre les connexions et les requêtes dans ce fichier. Voir Section 5.9.2, « Le log général de requêtes ». Si vous ne le faites pas, MySQL va utiliser host_name.log comme nom de fichier.

- --log-bin=[file]

Enregistre toutes les requêtes qui modifient des données dans un log. Voir Section 5.9.4, « Le log binaire ». Ce log est utilisé pour la sauvegarde et la réplication. Si vous ne le faites pas, MySQL va utiliser host_name-bin comme nom de fichier.

- --log-bin-index[=file]

Fichier d'index pour les noms de fichiers de log binaire. Voir Section 5.9.4, « Le log binaire ». Si vous ne le faites pas, MySQL va utiliser host_name-bin.index comme nom de fichier.

- --log-error[=file]

Enregistre les messages d'erreur et les messages de démarrage dans ce fichier. Voir Section 5.9.1, « Le log d'erreurs ». Si vous ne le faites pas, MySQL va utiliser host_name.err comme nom de fichier.

- --log-isam[=file]

Enregistre toutes les modifications des tables ISAM/MyISAM dans ce fichier (uniquement nécessaire pour déboguer ISAM/MyISAM).

- --log-long-format

Enregistre des informations supplémentaires dans les fichiers de log (log de modifications, log binaire de modifications, log de requêtes lentes, n'importe quel log en fait). Par exemple, le nom d'utilisateur et un timestamp sont enregistrés avec la requête. Si vous utilisez --log-slow-queries et --log-long-format, alors les requêtes qui n'utilisent pas d'index seront aussi enregistrées. Notez que --log-long-format est obsolète depuis la version 4.1, où --log-short-format a été introduite (le format de log long est la configuration par défaut en version 4.1). Notez aussi que depuis la version MySQL 4.1 l'option --log-queries-not-using-indexes est disponible pour enregistrer spécifiquement les requêtes qui n'utilisent pas d'index, dans le log de requêtes lentes.

- --log-queries-not-using-indexes

Si vous utilisez cette option avec --log-slow-queries, alors les requêtes qui n'utilisent pas d'index seront aussi enregistrées dans le log de requêtes lentes. Cette option est disponible depuis MySQL 4.1. Voir Section 5.9.5, « Le log des requêtes lentes ».

- --log-short-format

Enregistre moins d'information dans les fichiers de log (log de modifications, log binaire de modifications, log de requêtes lentes, n'importe quel log en fait). Par exemple, les noms d'utilisateur et un timestamp ne seront pas enregistrés avec les requêtes. Cette option a été ajoutée en MySQL 4.1.

- --log-slow-queries[=file]

Enregistre toutes les requêtes qui prennent plus de long_query_time secondes à s'exécuter. Notez que la quantité d'informations enregistrées par défaut a changé en MySQL 4.1. Voyez les options --log-long-format et --log-long-format pour plus de détails. Voir Section 5.9.5, « Le log des requêtes lentes ».

- --log-update[=file]

Enregistre les modifications de données dans le fichier file.# où # est un nombre unique, s'il n'est pas fourni. Voir Section 5.9.3, « Le log de modification ». Le log de modification est obsolète et supprimé en MySQL 5.0.0; vous devriez utiliser le log binaire à la place. (--log-bin). Voir Section 5.9.4, « Le log binaire ». Depuis la version 5.0.0, utiliser --log-update va simplement activer le log binaire. (Voir Section C.1.7, « Changements de la version 5.0.0 (22 décembre 2003 : Alpha) »).

- --log-warnings, -W

Affiche les alertes comme Aborted connection... dans le fichier d'erreur .err. Activer cette option est recommandé, par exemple, si vous utilisez la réplication : vous obtiendrez plus d'informations sur ce qui se passe, comme les erreurs de connexion réseau, ou les reconnexions. Cette option est activée par défaut depuis MySQL 4.1.2; pour la désactiver, utilisez --skip-log-warnings. Voir Section A.2.10, « Erreurs de communication / Connexion annulée ».

Cette option s'appelait --warnings avant MySQL 4.0.

- --low-priority-updates

Les opérations de modification de table (INSERT/DELETE/UPDATE) auront une priorité inférieure aux sélections. Cela peut être aussi fait via l'attribut {INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ... pour baisser la priorité d'une requête, ou avec SET LOW_PRIORITY_UPDATES=1 pour changer la priorité dans plus d'un thread. Voir Section 7.3.2, « Problème de verrouillage de tables ».

- --memlock

Verrouille le processus mysqld en mémoire. Cela fonctionne si votre système supporte la fonction mlockall() (comme Solaris). Ceci peut être utile si vous avez des problèmes avec le système d'exploitation qui force mysqld à utiliser le swap sur le disque.

- --myisam-recover [=option[,option...]]]

Cette option est la combinaison de DEFAULT, BACKUP, FORCE et QUICK. Vous pouvez aussi lui donner la valeur explicite de "" si vous voulez désactiver cette option. Si cette option est utilisée, mysqld va vérifier si la table est marquée comme corrompue à l'ouverture de chaque table (cette dernière option ne fonctionne que si vous utilisez l'option --skip-external-locking). Si c'est le cas, mysqld va essayer de vérifier la table. Si la table était corrompue, mysqld essaie alors de la réparer.

L'option suivante va affecter la manière avec laquelle la réparation s'effectue.

Option

Description

DEFAULT

Identique à ne pas donner d'option à --myisam-recover.

BACKUP

Si la table a été modifiée durant la réparation, sauver une copie du fichier table_name.MYD, sous le nom de table_name-datetime.BAK.

FORCE

Exécute une réparation même si nous allons perdre une ou plusieurs lignes dans le fichier .MYD.

QUICK

Ne vérifie pas les lignes dans la table s'il n'y a pas eu d'effacement.

Avant que la table ne soit automatiquement réparée, MySQL va ajouter une note dans le fichier de logs d'erreurs. Si vous voulez être capable de restaurer la plupart des erreurs sans intervention de l'utilisateur, il vaut utiliser les options BACKUP,FORCE. Cela va forcer la réparation de la table, même si quelques lignes sont effacées, et conserve le vieux fichier de données comme sauvegarde, pour examen ultérieur.

Cette option est disponible depuis MySQL 3.23.25.

- --new

Depuis la version 4.0.12, l'option --new sert à dire au serveur d'adopter le comportement de la version 4.1 pour certains aspects, afin de simplifier la migration de 4.0 en 4.1.

- TIMESTAMP est retourné sous forme de chaîne avec le format 'YYYY-MM-DD HH:MM:SS'. Voir Chapitre 11, Types de colonnes.

Cette option peut vous aider à voir comment vos applications vont se comporter en MySQL 4.1, sans réellement changer de version.

- --pid-file=path

Le chemin jusqu'au fichier de PID utilisé par safe_mysqld.

- --port=port_num, -P port_num

Numéro de port utilisé pour attendre les connexions TCP/IP.

- --old-protocol, -o

Utilise le protocole 3.20, pour la compatibilité avec de très vieux clients. Voir Section 2.6.6, « Passer de la version 3.20 à la version 3.21 ».

- --one-thread

Utilise uniquement un thread (pour débogage sous Linux). Cette option est disponible uniquement si le serveur est compilé avec les options de débogage. Voir Section D.1, « Déboguer un serveur MySQL ».

- --open-files-limit=count

Pour changer le nombre de pointeurs de fichiers disponibles pour mysqld. Si cette option n'est pas configurée, ou qu'elle vaut 0, alors mysqld va utiliser cette valeur pour réserver ce nombre de pointeurs de fichiers, à utiliser avec setrlimit(). Si la valeur est 0 alors mysqld va réserver max_connections*5 ou max_connections + table_cache*2 (le plus grand des deux) pointeurs de fichiers. Il est recommandé d'augmenter cette valeur si mysqld émet des erreurs de type 'Too many open files'.

- --safe-mode

Ignore certaines étapes d'optimisation.

- --safe-show-database

Avec cette option, la commande SHOW DATABASES retourne uniquement les bases pour lesquelles l'utilisateur a des droits. Depuis la version 4.0.2, cette option est abandonnée, et ne fait plus rien (l'option est activée par défaut) car nous avons désormais le droit de SHOW DATABASES. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

- --safe-user-create

Si cette option est activée, un utilisateur ne peut pas créer de nouveaux utilisateurs avec la commande GRANT si l'utilisateur n'a pas les droits de INSERT dans la table mysql.user ou dans aucune colonne de cette table.

- --secure-auth

Interdit l'identification des comptes qui ont des mots de passe anciens (avant la version 4.1). Cette option est disponible depuis MySQL 4.1.1.

- --skip-bdb

Désactive l'utilisation des tables BDB. Cela va économiser de la mémoire et accélérer le serveur un peu. N'utilisez pas cette option si vous avez besoin des tables BDB.

- --skip-concurrent-insert

Désactive la possibilité de sélectionner et insérer en même temps dans les tables MyISAM (cela n'est utile que si vous pensez que vous avez trouvé un bogue dans cette fonctionnalité).

- --skip-delay-key-write

Ignore l'option DELAY_KEY_WRITE de toutes les tables. Depuis MySQL 4.0.3, vous devez utiliser --delay-key-write=OFF à la place. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

- --skip-external-locking

Ne pas utiliser le verrouillage du système. Pour utiliser les utilitaires isamchk ou myisamchk vous devez alors éteindre le système. Voir Section 1.2.3, « Jusqu'à quel point MySQL est il stable ? ». Notez qu'en MySQL version 3.23 vous pouvez utiliser la commande REPAIR et CHECK pour réparer ou vérifier des tables MyISAM. Cette option s'appelait auparavant --skip-locking.

- --skip-grant-tables

Cette option force le serveur à ne pas utiliser le système de privilège du tout. Cela donne à tous l'accès complet à toutes les bases de données ! Vous pouvez demander à un serveur en exécution d'utiliser à nouveau les tables de droits en exécutant la commande mysqladmin flush-privileges ou mysqladmin reload).

- --skip-host-cache

Ne pas utiliser le cache de noms de domaine pour une résolution des IP plus rapide, mais interroger le serveur DNS à chaque connexion. Voir Section 7.5.6, « Comment MySQL utilise le DNS ».

- --skip-innodb

Désactive l'utilisation des tables InnoDB. Cela va économiser de la mémoire et accélérer le serveur un peu. N'utilisez pas cette option si vous avez besoin des tables InnoDB.

- --skip-isam

Désactive l'utilisation des tables ISAM. Cela va économiser de la mémoire et accélérer le serveur un peu. Depuis MySQL 4.1, ISAM est désactivé par défaut, ce qui fait que cette option n'apparaît que si le serveur a été configuré avec le support N'utilisez pas cette option si vous avez besoin des tables ISAM.

- --skip-name-resolve

Les noms d'hôtes ne sont pas résolus. Toutes les colonnes Host dans vos tables de droits doivent être des IP numériques ou le mot localhost. Voir Section 7.5.6, « Comment MySQL utilise le DNS ».

- --skip-networking

Ne pas attendre les connexions TCP/IP du tout. Toutes les interactions du serveur mysqld seront faites avec les sockets Unix. Cette option est particulièrement recommandée pour les systèmes qui utilisent des requêtes locales. Voir Section 7.5.6, « Comment MySQL utilise le DNS ».

- --skip-new

Ne pas utiliser les nouvelles routines qui sont possiblement erronées.

- --skip-symlink

C'est l'ancienne forme de --skip-symbolic-links, à utiliser avant MySQL 4.0.13.

- --symbolic-links, --skip-symbolic-links

Active ou désactive le support des liens symboliques. Cette option a différents effets sur Windows et sur Unix.

- Sous Windows, activer les liens symboliques vous permet d'établir un lien symbolique vers une base de données, en créant un fichier directory.sym qui contient le chemin réel. Voir Section 7.6.1.3, « Utiliser des liens symboliques pour les bases de données sous Windows ».

- Sous Unix, activer les liens symboliques signifie que vous pouvez mettre un fichier d'index MyISAM ou un autre fichier de données dans un autre dossier, avec les options INDEX DIRECTORY ou DATA DIRECTORY de la commande CREATE TABLE. Si vous effacez ou renommez la table, les fichiers qui sont des liens symboliques seront aussi effacés ou renommés. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

Cette option est disponible depuis MySQL 4.0.13.

- --skip-show-database

Si MySQL est configuré avec --with-debug=full, tous les programmes vérifieront la mémoire pour rechercher les écrasements de zone lors des allocations et libérations de mémoire. Comme ce test est lent, vous pouvez l'éviter, si vous n'avez pas besoin de tester la mémoire, en utilisant cette option.

- --skip-show-database

Ne pas autoriser la commande SHOW DATABASES, à moins que l'utilisateur n'ait les droits de SHOW DATABASES. Depuis la version 4.0.2, vous n'avez plus besoin de cette option, car les droits pour ce faire sont distribués avec le droit de SHOW DATABASES.

- --skip-stack-trace

Ne pas écrire les piles de traces. Cette option est pratique lorsque vous utilisez mysqld avec un débogueur. Sur certains systèmes, vous devez aussi utiliser cette option pour obtenir un fichier de core. Voir Section D.1, « Déboguer un serveur MySQL ».

- --skip-thread-priority

Désactive les priorités des threads pour améliorer la vitesse de réponse.

- --socket=path

Sous Unix, le fichier de socket pour les connexions locales. (par défaut, /tmp/mysql.sock). Sous Windows, le nom du pipe à utiliser pour les connexions locales qui utilisent un pipe nommé (par défaut, MySQL).

- --sql-mode=value[,value[,value...]]

Spécifie le mode SQL. Voir Section 5.2.2, « Le mode SQL du serveur ». Cette option est disponible depuis 3.23.41.

- --temp-pool

En utilisant cette option, vous allez réduire le jeu de noms qui sont utilisés lors de la création de fichiers temporaires, plutôt qu'un nom unique à chaque fois. Ceci est un palliatif au noyau Linux qui crée plusieurs fichiers nouveaux avec des noms différents. Avec l'ancien comportement, Linux semble « perdre de la mémoire », car ils sont alloués au cache d'entrées du dossier au lieu de celui du disque.

- --transaction-isolation=level

Configure le niveau d'isolation des transactions. Le niveau peut être READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ ou SERIALIZABLE. Voir Section 13.4.6, « Syntaxe de SET TRANSACTION  ».

- --tmpdir=path, -t path

Chemin vers les fichiers temporaires. Il peut s'avérer pratique si votre dossier par défaut /tmp réside dans une partition qui est trop petite pour absorber les tables temporaires. Depuis MySQL MySQL 4.1, cette option accepte différents chemins, qui sont utilisés en alternance. Les chemins doivent être séparés par des deux-points (':') sous Unix et des points-virgules (';') sous Windows. Il est possible de dire à tmpdir de pointer sur un système de fichiers en mémoire, hormis si le serveur MySQL est un esclave. Si c'est un esclave, il faut un système de fichiers permanents (pour la réplication des tables temporaires et des commandes LOAD DATA INFILE) survive a un redémarrage de la machine : un système de fichiers en mémoire tmpdir, qui est effacé au lancement de la machine n'est pas acceptable. Un disque est nécessaire pour tmpdir, dans ce contexte.

- --user={user_name | user_id}, -u {user_name | user_id}

Exécute le démon mysqld avec l'utilisateur user_name ou userid (numérique). (« utilisateur » dans ce contexte fait référence à l'utilisateur du système d'exploitation, mais pas l'utilisateur MySQL, listé dans les tables de droits.)

Cette option est obligatoire lorsque vous démarrez mysqld en tant que root. Le serveur va changer d'ID durant le lancement du serveur, pour utiliser un autre utilisateur que root. Voir Section 5.4, « Sécurité générale du serveur ».

Depuis MySQL 3.23.56 et 4.0.12: Pour éviter des trous de sécurité si un utilisateur ajoute --user=root dans un fichier my.cnf (et donc, faisant que le serveur fonctionne en tant qu'utilisateur système root), mysqld utilise uniquement la première option --user spécifiée, et produit une alerte s'il rencontre d'autres options --user. Les options des fichiers /etc/my.cnf et datadir/my.cnf sont traités avant les options de ligne de commande, et il est recommandé que vous ajoutiez l'option --user dans le fichier /etc/my.cnf puis spécifiez une valeur autre que root. L'option de /etc/my.cnf peut être placée avant toute autre option --user, ce qui assure que le serveur fonctionnera avec l'utilisateur autre que root, et qu'une alerte apparaîtra si une autre option --user est découverte.

- --version, -V

Affiche les informations de version.

Vous pouvez assigner une valeur à une variable système en utilisant une option de la forme --nom_de_variable=valeur. Par exemple, --key_buffer_size=32M donne à la variable key_buffer_size la valeur de 32 Mo.

Notez que lorsque vous donnez une valeur à une variable, MySQL peut corriger automatiquement la valeur pour qu'elle reste dans un intervalle donné, ou peut ajuster la valeur à la valeur possible la plus proche.

Il est aussi possible de donner des valeurs aux variables avec la syntaxe --set-variable=var_name=value ou -O var_name=value. Notez que cette syntaxe est abandonnée depuis MySQL 4.0.

Vous pouvez trouver une description complète de toutes les variables dans la section Section 5.2.3, « Variables serveur système ». La section sur le paramétrage du serveur inclut des détails sur l'optimisation. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

Vous pouvez changer la valeur de la plupart des variables système sur un serveur en fonctionnement avec la commande SET. Voir Section 13.5.2.8, « Syntaxe de SET ».

Si vous voulez limiter la valeur maximale qu'une option recevra avec la commande SET, vous pouvez la définir en utilisant l'option --maximum-nom_de_variable en ligne de commande.

5-2-2 - Le mode SQL du serveur

Le serveur MySQL peut fonctionner avec différents modes SQL, et, depuis MySQL 4.1, il peut appliquer ces modes au niveau de la connexion du client. Cela permet aux applications d'adapter le comportement du serveur en fonction de leurs attentes.

Le mode définit quelle syntaxe SQL MySQL doit supporter, et quels types de vérification il doit faire. Cela rend plus facile l'utilisation de MySQL dans différents environnements, et la connexion avec les autres serveurs de bases de données.

Vous pouvez donner un mode SQL par défaut au démarrage de mysqld avec l'option --sql-mode="modes". La valeur peut aussi être vide (--sql-mode="") si vous voulez la remettre à 0.

Depuis MySQL 4.1, vous pouvez aussi changer le mode après le démarrage en modifiant la variable sql_mode avec la commande SET [SESSION|GLOBAL] sql_mode='modes'. Modifier la variable GLOBAL affecte les opérations de tous les clients qui se connecteront. En modifiant la variable SESSION, cela n'affectera que le client courant.

modes est une liste de modes différents, séparés par des virgules (','). Vous pouvez lire le mode courant avec la commande SELECT @@sql_mode. La valeur par défaut est vide (pas de mode configuré).

- ANSI

Change la syntaxe et le comportement pour être plus compatible avec le standard SQL. (Nouveau en MySQL 4.1.1.)

- STRICT_TRANS_TABLES

Si une valeur n'a pas pu être insérée dans une table transactionnelle sans modification, la commande est annulée. Pour une table non transactionnelle, la commande est annulée si cela survient dans une ligne unique ou dans la première ligne d'une insertion multiple. Plus de détails seront donnés ultérieurement dans cette section. (Nouveau en MySQL 5.0.2.)

- TRADITIONAL

MySQL se comporte comme un système SQL « traditionnel ». Une description simple est que ce mode « émet une erreur et non pas une alerte » lors de l'insertion d'une valeur incorrecte dans une colonne. Note : si vous utilisez un moteur de table non transactionnel, les commandes INSERT/UPDATE s'arrêteront dès que l'erreur est repérée, ce qui n'est pas forcément ce que vous voudrez. (Nouveau en MySQL 5.0.2.)

Lorsque cette documentation fait référence au mode strict, cela signifie qu'au moins un des modes STRICT_TRANS_TABLES ou STRICT_ALL_TABLES est activé.

La liste suivante présente les différents modes supportés :

- ALLOW_INVALID_DATES

N'autorise pas la vérification totale des dates. Vérifie simplement que le mois est dans l'intervalle de 1 à 12, et que le jour est dans l'intervalle de de 1 à 31. C'est très pratique pour les applications Web où la date est obtenue de 3 champs différents, et que vous voulez stocker exactement la date saisie sans validation. Ce mode s'applique aux colonnes de type DATE et DATETIME. Il ne s'applique pas aux colonnes TIMESTAMP, qui demandent toujours une date valide.

Ce mode est nouveau en MySQL 5.0.2. Avant 5.0.2, c'était le mode par défaut de gestion des dates. Depuis 5.0.2, activer le mode strict impose au serveur de vérifier la validité des dates, et non pas seulement les intervalles. Par exemple, '2004-04-31' est valide sans le mode strict, mais ne l'est plus avec le mode strict. Pour permettre ces valeurs malgré le mode strict, utilisez le mode ALLOW_INVALID_DATES.

- ANSI_QUOTES

Traite '"' comme un délimiteur d'identifiant (comme le caractère MySQL '`') et non comme un délimiteur de chaînes. Vous pouvez toujours utiliser '`' pour délimiter les identifiants en mode ANSI. Avec ANSI_QUOTES activée, vous ne pouvez pas utiliser les guillemets doubles pour délimiter une chaîne de caractères, car ce sera uniquement interprété comme un identifiant. (Nouveau en MySQL 4.0.0.)

- ERROR_FOR_DIVISION_BY_ZERO

Produit une erreur en mode strict et sinon une alerte, lorsque MySQL doit tenter une division par 0 ou un MOD(X,0)) durant une commande INSERT/ UPDATE. Si ce mode n'est pas activé, MySQL retourne simplement NULL pour les divisions par zéro. Si utilisé avec l'attribut IGNORE, MySQL génère une alerte pour les divisions par zéro, mais le résultat de l'opération sera NULL. (Nouveau en MySQL 5.0.2.)

- IGNORE_SPACE

Permet les espaces entre le nom de la fonction et le caractère '('. Cela force les noms de fonctions à être traités comme des mots réservés. En conséquence, si vous voulez accéder aux bases, tables et colonnes dont le nom est un mot réservé, vous devez le mettre entre délimiteurs. Par exemple, comme la fonction USER() existe, le nom de la table user de la base mysql et la colonne User de cette table doivent être protégés :

SELECT "User" FROM mysql."user";

(Nouveau en MySQL 4.0.0.)

- NO_AUTO_VALUE_ON_ZERO

NO_AUTO_VALUE_ON_ZERO affecte la gestion des colonnes de type AUTO_INCREMENT. Normalement, vous générez le prochain numéro de séquence dans la colonne en insérant soit NULL soit 0 dedans. NO_AUTO_VALUE_ON_ZERO supprime ce comportement pour 0 pour que seule la valeur NULL génère le prochain numéro de séquence. Ce mode est utile si vous avez stocké la valeur 0 dans la colonne AUTO_INCREMENT de la table. Ce n'est pas recommandé. Par exemple, si vous voulez exporter une table avec mysqldump et que vous la rechargez, normalement MySQL va générer de nouveaux identifiants pour les lignes avec la valeur 0, ce qui entraînera une différence avec la table originale. En activant NO_AUTO_VALUE_ON_ZERO avant de recharger le fichier exporté, vous évitez de problème. Depuis MySQL 4.1.1, mysqldump va automatiquement inclure les commandes nécessaires dans l'export, pour activer NO_AUTO_VALUE_ON_ZERO. (Nouveau en MySQL 4.1.1.)

- NO_DIR_IN_CREATE

Lors de la création d'une table, ignore les directives INDEX DIRECTORY et DATA DIRECTORY. Cette option est pratique sur un esclave de réplication. (Nouveau en MySQL 4.0.15.)

- NO_FIELD_OPTIONS

N'affiche pas les options spécifiques à MySQL dans le résultat de SHOW CREATE TABLE. Ce mode est utilisé par mysqldump dans un souci de portabilité. (Nouveau en MySQL 4.1.1.)

- NO_KEY_OPTIONS

N'affiche pas les options spécifiques à MySQL dans le résultat de SHOW CREATE TABLE. Ce mode est utilisé par mysqldump dans un souci de portabilité. (Nouveau en MySQL 4.1.1.)

- NO_TABLE_OPTIONS

N'affiche pas les options de tables spécifiques à MySQL (comme ENGINE) dans le résultat de SHOW CREATE TABLE. Ce mode est utilisé par mysqldump dans un souci de portabilité. (Nouveau en MySQL 4.1.1.)

- NO_ZERO_DATE

Ne permet pas l'utilisation de '0000-00-00' comme date valide. Vous pouvez toujours insérer des dates nulles avec l'option IGNORE. (Nouveau en MySQL 5.0.2.)

- NO_ZERO_IN_DATE

N'accepte pas les dates où le mois ou le jour vaut 0. Si utilisé avec l'option IGNORE, la date '0000-00-00' sera insérée pour chaque date invalide. (Nouveau en MySQL 5.0.2.)

- NO_UNSIGNED_SUBTRACTION

Dans les opérations de soustraction, ne marque pas le résultat UNSIGNED si un des opérandes est non signé. Notez que cela fait que UNSIGNED BIGINT n'est plus totalement utilisable dans tous les contextes. Voir Section 12.7, « Fonctions de transtypage ». (Nouveau en MySQL 4.0.2.)

- ONLY_FULL_GROUP_BY

N'autorise pas les requêtes dont la clause GROUP BY fait référence à une colonne qui n'est pas sélectionnée. (Nouveau en MySQL 4.0.0.)

- PIPES_AS_CONCAT

Traite || comme un opérateur de concaténation (identique à CONCAT()) au lieu d'être un synonyme de OR. (Nouveau en MySQL 4.0.0.)

- REAL_AS_FLOAT

Traite le type REAL comme un synonyme FLOAT plutôt que comme un synonyme de DOUBLE. (Nouveau en MySQL 4.0.0.)

- STRICT_ALL_TABLES

Active le mode strict pour tous les moteurs de stockage. Les valeurs invalides sont rejetées. Plus de détails suivent. (Nouveau en MySQL 5.0.2.)

- STRICT_TRANS_TABLES

Active le mode strict pour tous les moteurs de stockage transactionnels. Les valeurs invalides sont rejetées. Plus de détails suivent. (Nouveau en MySQL 5.0.2.)

Lorsque le mode strict est activé, MySQL retourne une erreur si une valeur est invalide ou manquante (aucune valeur fournie pour la colonne, et la colonne n'a pas de valeur DEFAULT explicite dans sa définition). Pour les tables transactionnelles, cela arrive lorsque les modes STRICT_ALL_TABLES et STRICT_TRANS_TABLES sont activés. La commande est alors annulée. Pour les tables non transactionnelles, MySQL gère les valeurs invalides comme ceci :

si la commande insère ou modifie une seule ligne, l'erreur survient si la valeur est invalide ou manquante. La commande est annulée et la table reste intacte. Si la commande insère ou modifie plusieurs lignes, l'effet dépend de l'option stricte activée :

- pour le mode STRICT_ALL_TABLES, si une valeur est invalide ou manquante dans la première ligne, MySQL retourne une erreur et aucune ligne n'est modifiée. Si une valeur est invalide ou manquante à partir de la seconde ligne, MySQL retourne une erreur et ignore le reste des lignes. Cependant, dans ce cas, les premières lignes restent modifiées ou insérées. Cela signifie que vous risquez d'obtenir une opération partielle, ce qui n'est pas forcément souhaitable. Pour éviter cela, il est alors recommandé d'utiliser des commandes unilignes ;

- pour le mode STRICT_TRANS_TABLES, si une valeur est invalide ou manquante pour la première ligne, MySQL retourne une erreur et aucune ligne n'est modifiée. Pour les lignes suivantes, si une valeur est invalide, MySQL insère la valeur valide la plus proche. Si une valeur manque, MySQL insère explicitement la valeur par défaut pour ce type de données. Dans ce cas, MySQL génère une alerte, et continue le traitement.

Le mode strict interdit l'utilisation de dates invalides comme '2004-04-31'. Il n'interdit pas les dates avec des 0 comme 2004-04-00' ou encore les dates « zéro ». Pour les interdire, il faut activer les modes NO_ZERO_IN_DATE et NO_ZERO_DATE.

Si vous n'utilisez pas de mode strict, c'est-à-dire ni STRICT_TRANS_TABLES ni STRICT_ALL_TABLES, MySQL génère une alerte pour toutes les valeurs qui sont adaptées pour être insérées. Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

Les modes suivants sont fournis comme raccourcis pour différentes combinaisons des valeurs précédentes. Tous les raccourcis sont disponibles depuis MySQL 4.1.1, hormisTRADITIONAL (5.0.2).

- ANSI

équivaut à REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY. Voir Section 1.5.3, « Exécuter MySQL en mode ANSI ».

- DB2

équivaut à PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

- MAXDB

équivaut à PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

- MSSQL

équivaut à PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

- MYSQL323

équivaut à NO_FIELD_OPTIONS.

- MYSQL40

équivaut à NO_FIELD_OPTIONS.

- ORACLE

équivaut à PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

- POSTGRESQL

équivaut à PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

- TRADITIONAL

équivaut à STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO.

5-2-3 - Variables serveur système

Le serveur entretient de nombreuses variables système qui indiquent comment il est configuré. Toutes les variables ont des valeurs par défaut. Elles peuvent être configurées au lancement du serveur, avec les options de ligne de commande, ou bien durant l'exécution, avec la commande SET.

Depuis MySQL version 4.0.3, le serveur mysqld entretient deux types de variables. Les variables globales, qui affectent les opérations générales du serveur. Et les variables de session qui affectent les comportements individuels des connexions.

Lorsque mysqld démarre, toutes les variables globales sont initialisées à partir des arguments passés en ligne de commande et des fichiers de configuration. Vous pouvez changer ces valeurs avec la commande SET GLOBAL. Lorsqu'un nouveau thread est créé, les variables spécifiques aux threads sont initialisées à partir des variables globales et ne changeront pas même si vous utilisez la commande SET GLOBAL var_name. Pour changer une variable globale, vous devez avoir les droits de SUPER.

Le serveur entretient aussi un jeu de variables de session pour chaque client qui se connecte. Les variables de session du serveur sont initialisées au moment de la connexion, en utilisant les valeurs correspondantes des variables globales. Pour les variables de session qui sont dynamiques, le client peut les changer avec la commande SET SESSION var_name. Modifier une variable de session ne requiert aucun droit spécifique, mais le client ne modifiera le comportement du serveur que pour sa connexion, et non pour les connexions des autres.

Une modification de variable globale est visible par tous les clients qui accèdent aux variables globales. Cependant, elle n'affectera les connexions des clients que pour les nouvelles connexions. Les variables de sessions déjà en cours continueront à fonctionner avec la même configuration, jusqu'à leur déconnexion. Même le client qui a émis la commande SET GLOBAL ne verra aucun changement.

Lorsque vous modifiez une variable avec une option de démarrage, les valeurs de variables peuvent être spécifiées avec le suffixe K, M ou G, pour indiquer des kilooctets, des mégaoctets ou des gigaoctets. Par exemple, pour lancer le serveur avec une taille de buffer de clé de 16 Mo, vous pouvez utiliser :

mysqld --key_buffer_size=16M

Avant MySQL 4.0, vous deviez utiliser la syntaxe suivante :

mysqld --set-variable=key_buffer_size=16M

La lettre de suffixe peut être en majuscule ou en minuscule : 16M et 16m sont équivalents.

Durant l'exécution, utilisez la commande SET pour donner de nouvelles valeurs aux variables système. Dans ce contexte, les lettres de suffixes ne pourront pas être utilisées. Leur valeur peut être calculée avec l'expression suivante :

mysql> SET sort_buffer_size = 10 * 1024 * 1024;

Pour spécifier explicitement si vous voulez modifier une variable globale ou une variable de session, utilisez les options GLOBAL et SESSION :

mysql> SET GLOBAL sort_buffer_size = 10 * 1024 * 1024;
mysql> SET SESSION sort_buffer_size = 10 * 1024 * 1024;

Si cette option est omise, la variable de session sera modifiée.

Les variables qui peuvent être modifiées durant l'exécution sont listées dans la section Section 5.2.3.1, « Variables système dynamiques ».

Si vous voulez restreindre le maximum possible d'une variable système, modifiée avec SET, vous pouvez spécifier ce maximum avec les options de la forme --maximum-var_name au lancement du serveur. Par exemple, pour éviter que la valeur de query_cache_size dépasse 32 Mo, utilisez l'option --maximum-query_cache_size=32M. Cette fonctionnalité est disponible depuis MySQL 4.0.2.

Vous pouvez découvrir les variables système et leur valeur avec la commande SHOW VARIABLES. Voyez Section 9.4, « Variables système » pour plus d'informations.

mysql> SHOW VARIABLES;
+---------------------------------+------------------------------+
| Variable_name                   | Value                        |
+---------------------------------+------------------------------|
| back_log                        | 50                           |
| basedir                         | /usr/local/mysql             |
| bdb_cache_size                  | 8388572                      |
| bdb_home                        | /usr/local/mysql             |
| bdb_log_buffer_size             | 32768                        |
| bdb_logdir                      |                              |
| bdb_max_lock                    | 10000                        |
| bdb_shared_data                 | OFF                          |
| bdb_tmpdir                      | /tmp/                        |
| bdb_version                     | Sleepycat Software: ...      |
| binlog_cache_size               | 32768                        |
| bulk_insert_buffer_size         | 8388608                      |
| character_set                   | latin1                       |
| character_sets                  | latin1 big5 czech euc_kr     |
| concurrent_insert               | ON                           |
| connect_timeout                 | 5                            |
| convert_character_set           |                              |
| datadir                         | /usr/local/mysql/data/       |
| default_week_format             | 0                            |
| delay_key_write                 | ON                           |
| delayed_insert_limit            | 100                          |
| delayed_insert_timeout          | 300                          |
| delayed_queue_size              | 1000                         |
| flush                           | OFF                          |
| flush_time                      | 0                            |
| ft_boolean_syntax               | + -><()~*:""&|               |
| ft_max_word_len                 | 84                           |
| ft_min_word_len                 | 4                            |
| ft_query_expansion_limit        | 20                           |
| ft_stopword_file                | (built-in)                   |
| have_bdb                        | YES                          |
| have_innodb                     | YES                          |
| have_isam                       | YES                          |
| have_openssl                    | YES                          |
| have_query_cache                | YES                          |
| have_raid                       | NO                           |
| have_symlink                    | DISABLED                     |
| init_file                       |                              |
| innodb_additional_mem_pool_size | 1048576                      |
| innodb_buffer_pool_size         | 8388608                      |
| innodb_data_file_path           | ibdata1:10M:autoextend       |
| innodb_data_home_dir            |                              |
| innodb_fast_shutdown            | ON                           |
| innodb_file_io_threads          | 4                            |
| innodb_flush_log_at_trx_commit  | 1                            |
| innodb_flush_method             |                              |
| innodb_force_recovery           | 0                            |
| innodb_lock_wait_timeout        | 50                           |
| innodb_log_arch_dir             |                              |
| innodb_log_archive              | OFF                          |
| innodb_log_buffer_size          | 1048576                      |
| innodb_log_file_size            | 5242880                      |
| innodb_log_files_in_group       | 2                            |
| innodb_log_group_home_dir       | ./                           |
| innodb_mirrored_log_groups      | 1                            |
| innodb_thread_concurrency       | 8                            |
| interactive_timeout             | 28800                        |
| join_buffer_size                | 131072                       |
| key_buffer_size                 | 16773120                     |
| key_cache_age_threshold         | 300                          |
| key_cache_block_size            | 1024                         |
| key_cache_division_limit        | 100                          |
| language                        | /usr/local/mysql/share/...   |
| large_files_support             | ON                           |
| local_infile                    | ON                           |
| locked_in_memory                | OFF                          |
| log                             | OFF                          |
| log_bin                         | OFF                          |
| log_slave_updates               | OFF                          |
| log_slow_queries                | OFF                          |
| log_update                      | OFF                          |
| log_warnings                    | OFF                          |
| long_query_time                 | 10                           |
| low_priority_updates            | OFF                          |
| lower_case_table_names          | 0                            |
| max_allowed_packet              | 1047552                      |
| max_binlog_cache_size           | 4294967295                   |
| max_binlog_size                 | 1073741824                   |
| max_connect_errors              | 10                           |
| max_connections                 | 100                          |
| max_delayed_threads             | 20                           |
| max_error_count                 | 64                           |
| max_heap_table_size             | 16777216                     |
| max_join_size                   | 4294967295                   |
| max_relay_log_size              | 0                            |
| max_sort_length                 | 1024                         |
| max_tmp_tables                  | 32                           |
| max_user_connections            | 0                            |
| max_write_lock_count            | 4294967295                   |
| myisam_max_extra_sort_file_size | 268435456                    |
| myisam_max_sort_file_size       | 2147483647                   |
| myisam_recover_options          | force                        |
| myisam_repair_threads           | 1                            |
| myisam_sort_buffer_size         | 8388608                      |
| net_buffer_length               | 16384                        |
| net_read_timeout                | 30                           |
| net_retry_count                 | 10                           |
| net_write_timeout               | 60                           |
| open_files_limit                | 1024                         |
| pid_file                        | /usr/local/mysql/name.pid    |
| port                            | 3306                         |
| protocol_version                | 10                           |
| query_cache_limit               | 1048576                      |
| query_cache_size                | 0                            |
| query_cache_type                | ON                           |
| read_buffer_size                | 131072                       |
| read_rnd_buffer_size            | 262144                       |
| rpl_recovery_rank               | 0                            |
| server_id                       | 0                            |
| skip_external_locking           | ON                           |
| skip_networking                 | OFF                          |
| skip_show_database              | OFF                          |
| slave_net_timeout               | 3600                         |
| slow_launch_time                | 2                            |
| socket                          | /tmp/mysql.sock              |
| sort_buffer_size                | 2097116                      |
| sql_mode                        |                              |
| table_cache                     | 64                           |
| table_type                      | MYISAM                       |
| thread_cache_size               | 3                            |
| thread_stack                    | 131072                       |
| timezone                        | EEST                         |
| tmp_table_size                  | 33554432                     |
| tmpdir                          | /tmp/:/mnt/hd2/tmp/          |
| tx_isolation                    | READ-COMMITTED               |
| version                         | 4.0.4-beta                   |
| wait_timeout                    | 28800                        |
+---------------------------------+------------------------------+

La plupart des variables système sont présentées ici. Les variables sans version sont présentes depuis MySQL 3.22. Les variables système InnoDB sont listées dans Section 15.5, « Options de démarrage InnoDB ».

Les valeurs pour les tailles de buffer, longueur et taille de pile sont données en octets, à moins que cela ne soit spécifié autrement.

Les informations sur le choix des valeurs de ces paramètres sont disponibles dans Section 7.5.2, « Réglage des paramètres du serveur ».

- ansi_mode

Vaut ON si mysqld a été démarré en mode --ansi. Voir Section 1.5.3, « Exécuter MySQL en mode ANSI ». Cette variable a été ajoutée en MySQL 3.23.6 et supprimée en 3.23.41. Voyez la description de sql_mode.

- back_log

Le nombre de connexions sortantes que MySQL peut supporter. Cette valeur entre en jeu lorsque le thread principal MySQL reçoit de très nombreuses requêtes de connexion en très peu de temps. MySQL prend un peu de temps (même si c'est très peu de temps), pour vérifier la connexion et démarrer un nouveau thread. La valeur de back_log indique combien de requêtes seront mises en attente durant ce temps. Vous devrez augmenter ce nombre si vous voulez mettre en attente plus de requêtes durant une courte période de temps.

En d'autres termes, cette valeur est la taille de la queue d'attente pour les connexions TCP/IP entrantes. Votre système d'exploitation a ses propres limites pour ce type de queue. La page du manuel Unix listen(2) doit contenir plus de détails. Vérifiez la documentation de votre OS pour connaître la valeur maximale de votre système. Si vous donnez une valeur à back_log qui est plus grande que celle que votre système supporte, cela restera sans effet.

- basedir

Le dossier d'installation de MySQL. La valeur de l'option --basedir.

- bdb_cache_size

Le buffer qui est alloué pour mettre en cache des lignes et des index pour les tables BDB. Si vous n'utilisez pas les tables BDB, vous devriez démarrer mysqld avec l'option --skip-bdb pour ne pas gaspiller de mémoire. Cette variable a été ajoutée en MySQL 3.23.14.

- bdb_home

Le dossier de base des tables BDB. Cette valeur doit être la même que celle de la variable datadir. Cette variable a été ajoutée en MySQL 3.23.14.

- bdb_log_buffer_size

Le buffer qui est alloué pour mettre en cache des lignes et des index pour les tables BDB. Si vous n'utilisez pas les tables BDB, vous devriez démarrer mysqld avec l'option --skip-bdb pour ne pas gaspiller de mémoire. Cette variable a été ajoutée en MySQL 3.23.31.

- bdb_logdir

Le dossier où le moteur BDB écrit les fichiers de log. C'est la valeur de l'option --bdb-logdir. Cette variable a été ajoutée en MySQL 3.23.14.

- bdb_max_lock

Le nombre maximum de verrous (par défaut 10 000) que vous pouvez activer simultanément dans une table BDB. Vous devriez augmenter cette valeur si vous obtenez des erreurs du type bdb: Lock table is out of available locks ou Got error 12 from ... lorsque vous avez de longues transactions ou que mysqld doit examiner de nombreuses lignes pour calculer la requête.

bdb: Lock table is out of available locks
Got error 12 from ...

Cette variable a été ajoutée en MySQL 3.23.29.

- bdb_shared_data

Vaut ON si vous utilisez l'option --bdb-shared-data. Cette variable a été ajoutée en MySQL 3.23.29.

- bdb_tmpdir

La valeur de l'option --bdb-tmpdir. Cette variable a été ajoutée en MySQL 3.23.14.

- bdb_version

La version du moteur BDB. Cette variable a été ajoutée en MySQL 3.23.31.

- binlog_cache_size

La taille du cache qui contient les requêtes SQL destinées au log binaire, durant une transaction. Un cache binaire est alloué à chaque client si le serveur supporte les moteurs transactionnels, et depuis MySQL 4.1.2, si le serveur a un log binaire activé (option --log-bin). Si vous utilisez souvent de grandes transactions multirequêtes, vous devez augmenter cette valeur pour améliorer les performances. Les variables Binlog_cache_use et Binlog_cache_disk_use sont aussi utiles pour optimiser la taille de cette variable. Cette variable a été ajoutée en MySQL 3.23.29. Voir Section 5.9.4, « Le log binaire ».

- bulk_insert_buffer_size

MyISAM utilise un cache hiérarchisé pour les insertions de masse (c'est-à-dire INSERT ... SELECT, INSERT ... VALUES (...), (...), ..., et LOAD DATA INFILE). Cette variable limite la taille du cache en octets, par threads. Utiliser la valeur de 0 va désactiver cette optimisation. Note : ce cache est uniquement utilisé lorsque vous ajoutez des données dans une table non vide. Par défaut, cette option vaut 8 Mo. Cette variable a été ajoutée en MySQL 4.0.3. Cette variable s'appelait myisam_bulk_insert_tree_size.

- character_set

Le jeu de caractères par défaut. Cette variable a été ajoutée en MySQL 3.23.3, puis retirée en MySQL 4.1.1 et remplacée par différentes variables character_set_xxx.

- character_set_client

Le jeu de caractères pour les commandes du client. Cette variable a été ajoutée en MySQL 4.1.1.

- character_set_connection

Le jeu de caractères utilisé pour les littéraux qui n'ont pas d'indication de jeu de caractères, pour certaines fonctions et pour les conversions de nombres vers une chaîne. Cette variable a été ajoutée en MySQL 4.1.1.

- character_set_database

Le jeu de caractères par défaut pour les bases de données. Le serveur modifie cette variable à chaque fois que la base de données par défaut change. S'il n'y a pas de base de données par défaut, cette variable prend la valeur de character_set_server. Cette variable a été ajoutée en MySQL 4.1.1.

- character_set_results

Le jeu de caractères utilisé pour retourner des résultats au client. Cette variable a été ajoutée en MySQL 4.1.1.

- character_set_server

Le jeu de caractères par défaut pour le serveur. Cette variable a été ajoutée en MySQL 4.1.1.

- character_set_system

Le jeu de caractères utilisé par le serveur pour stocker des identifiants. Cette valeur est toujours utf8. Cette variable a été ajoutée en MySQL 4.1.1.

- character_sets

Les jeux de caractères supportés. Cette variable a été ajoutée en MySQL 3.23.15.

- collation_connection

Cette variable a été ajoutée en MySQL 4.1.1.

- collation_database

La collation utilisée par la base de données par défaut. Le serveur modifie cette variable à chaque fois que la base de données par défaut change. S'il n'y a pas de base de données par défaut, cette variable prend la valeur de collation_server. Cette variable a été ajoutée en MySQL 4.1.1.

- collation_server

La collation par défaut du serveur. Cette variable a été ajoutée en MySQL 4.1.1.

- concurrent_insert

Si cette option vaut ON, MySQL va vous permettre de réaliser des commandes INSERT sur les tables MyISAM en même temps que d'autres commandes SELECT seront exécutées. Vous pouvez désactiver cette option en démarrant mysqld avec l'option --safe or --skip-new. Cette variable a été ajoutée en MySQL 3.23.7.

- connect_timeout

Le nombre de secondes d'attente d'un paquet de connexion avant de conclure avec une erreur Bad handshake.

- datadir

Le dossier de données de MySQL. C'est la valeur de l'option --datadir.

- default_week_format

Le mode par défaut pour la fonction WEEK(). Cette variable a été ajoutée en MySQL 4.0.14.

- delay_key_write

Les options pour les tables MyISAM. Elles peuvent prendre l'une des valeurs suivantes :

Option

Description

OFF

DELAYED_KEY_WRITE est ignoré.

ON

(Par défaut) MySQL va honorer l'option DELAY_KEY_WRITE de CREATE TABLE.

ALL

Toutes les nouvelles tables ouvertes sont traitées comme si elles étaient créées avec l'option DELAY_KEY_WRITE.

Si DELAY_KEY_WRITE est activé, cela signifie que le buffer de clés des tables ayant cette option ne sera pas écrit sur le disque dès la fin de la modification de la table, mais attendra que la table soit écrite. Cela accélère notablement les écritures des modifications, mais il faut penser à ajouter une vérification automatique des tables au démarrage avec --myisam-recover=BACKUP,FORCE. Voir aussi Section 5.2.1, « Options de ligne de commande de mysqld » et Section 14.1.1, « Options de démarrage MyISAM ».

Notez que --external-locking n'offre aucune protection contre les corruptions d'index pour les tables qui utilisent les écritures retardées de clés.

Cette variable a été ajoutée en MySQL 3.23.8.

- delayed_insert_limit

Après avoir inséré delayed_insert_limit lignes, le gestionnaire de INSERT DELAYED va vérifiez s'il n'y a pas de commande SELECT en attente. Si c'est le cas, il va autoriser ces commandes avant de continuer.

- delayed_insert_timeout

Combien de temps le thread INSERT DELAYED doit attendre les commandes INSERT avant de s'achever.

- delayed_queue_size

Quelle taille de file (en lignes) doit être allouée pour gérer les commandes INSERT DELAYED. Si la file se remplit, tous les clients qui émettent des commandes INSERT DELAYED devront attendre un peu de place avant de pouvoir continuer.

- flush

Cette option vaut ON si vous avez démarré MySQL avec l'option --flush. Cette variable a été ajoutée en MySQL 3.22.9.

- flush_time

Si cette option a une valeur non nulle, toutes les flush_time secondes, toutes les tables seront fermées (pour libérez des ressources et synchroniser les index sur le disque). Nous ne recommandons cette option que sur les systèmes Windows 9x/Me, ou les systèmes qui ont très peu de ressources. Cette variable a été ajoutée en MySQL 3.22.18.

- ft_boolean_syntax

Liste des opérateurs supportés par IN BOOLEAN MODE. Cette variable a été ajoutée en MySQL 4.0.1. Voir Section 12.6.1, « Booléens de recherches en texte intégral ».

La valeur par défaut de cette variable est '+ -><()~*:""&|'. Les règles pour modifier cette valeur sont les suivantes :

- la fonction de l'opérateur est déterminée par sa position dans la chaîne ;

- la chaîne de remplacement doit faire 14 caractères ;

- chaque caractère doit être ASCII, non alphanumérique ;

- le premier ou le deuxième caractère doit être un espace ;

- aucun doublon n'est autorisé, hormis les opérateurs guillemets aux positions 11 et 12. Ce deux caractères ne sont pas obligatoirement les mêmes, mais ce sont les deux seuls qui peuvent l'être ;

- les positions 10, 13 et 14 (qui sont par défaut ':', '&' et '|') sont réservées pour une utilisation ultérieure.

- ft_max_word_len

La taille maximale d'un mot à inclure dans un index FULLTEXT. Cette variable a été ajoutée en MySQL 4.0.0.

Note : les index FULLTEXT doivent être reconstruits après chaque modification de cette variable. Utilisez REPAIR TABLE tbl_name QUICK.

- ft_min_word_len

La taille minimale d'un mot à inclure dans un index FULLTEXT. Cette variable a été ajoutée en MySQL 4.0.0.

Note  : les index FULLTEXT doivent être reconstruits après chaque modification de cette variable. Utilisez REPAIR TABLE tbl_name QUICK.

- ft_query_expansion_limit

Le nombre de solutions générales à utiliser pour les extensions de recherche avec WITH QUERY EXPANSION. Cette variable a été ajoutée en MySQL 4.1.1.

- ft_stopword_file

Un fichier dans lequel lire une liste de mots interdits pour les recherches en texte plein. Tous les mots du fichier seront utilisés : les commentaires ne sont pas respectés. Par défaut, des listes de mots interdits internes sont utilisées, telles que définies dans myisam/ft_static.c). En donnant à cette option la valeur d'une chaîne vide "", vous désactivez le filtre de mots interdits.

Note  : les index FULLTEXT doivent être reconstruits après chaque modification de cette variable. Utilisez la commande REPAIR TABLE tbl_name QUICK. Cette variable a été ajoutée en MySQL 4.1.0.

- group_concat_max_len

La taille maximale de la chaîne résultat de GROUP_CONCAT(). Cette variable a été ajoutée en MySQL 4.1.0.

- have_bdb

YES si mysqld supporte les tables BDB. DISABLED si --skip-bdb a été utilisé. Cette variable a été ajoutée en MySQL 3.23.30.

- have_innodb

YES si mysqld supporte les tables InnoDB. DISABLED si --skip-innodb a été utilisé. Cette variable a été ajoutée en MySQL 3.23.37.

- have_isam

YES si mysqld supporte les tables ISAM. DISABLED si --skip-isam a été utilisé. Cette variable a été ajoutée en MySQL 3.23.30.

- have_raid

YES si mysqld supporte les tables RAID. Cette variable a été ajoutée en MySQL 3.23.30.

- have_openssl

YES si mysqld supporte le chiffrement SSL avec le protocole de communication client/serveur. Cette variable a été ajoutée en MySQL 3.23.43.

- init_connect

Une chaîne à exécuter sur le serveur lors de chaque connexion. La chaîne est constituée d'une ou plusieurs commandes SQL. Pour spécifier une commande multiple, séparez les requêtes individuelles par des points-virgules. Cette variable a été ajoutée en MySQL version 4.1.2.

Par exemple, chaque client commence par défaut avec le mode d'autovalidation activé. Il n'y a pas de variable globale à spécifier pour désactiver l'autovalidation, et init_connect peut servir à ça :

SET GLOBAL init_connect='SET AUTOCOMMIT=0';

Cette variable peut aussi être configurée en ligne de commande ou dans un fichier d'options. Pour assigner la variable comme montré dans le fichier d'options, ajoutez ces lignes-ci :

[mysqld]
init_connect='SET AUTOCOMMIT=0'

Cette variable a été ajoutée en MySQL 4.1.2.

- init_file

Le nom du fichier spécifié avec l'option --init-file lorsque vous démarrez le serveur. C'est un fichier qui contient les requêtes SQL que vous voulez voir exécutées dès le démarrage. Chaque commande doit être sur une seule ligne, et ne doit pas inclure de commentaires. Cette variable a été ajoutée en MySQL 3.23.2.

- init_slave

Cette variable est similaire à init_connect, mais la chaîne doit être exécutée par l'esclave, à chaque démarrage du thread SQL. Le format de la chaîne est le même que pour la variable init_connect. Cette variable a été ajoutée en MySQL 4.1.2.

- innodb_xxx

Les variables système de InnoDB sont listées dans Section 15.5, « Options de démarrage InnoDB ».

- interactive_timeout

Le nombre de secondes durant lequel le serveur attend une activité de la part de la connexion avant de la fermer. Un client interactif est un client qui utilise l'option CLIENT_INTERACTIVE avec mysql_real_connect(). Voir aussi wait_timeout.

- join_buffer_size

La taille du buffer qui est utilisée pour les jointures complètes (les jointures qui n'utilisent pas d'index). Ce buffer est alloué une fois pour chaque jointure entre deux tables. Augmentez cette valeur si vous voulez obtenir des jointures plus rapides, lorsque l'ajout d'index n'est pas possible. Normalement, le mieux est d'ajouter de bons index.

- key_buffer_size

Les blocs d'index des tables MyISAM et ISAM sont mis en buffer et partagés par tous les threads. key_buffer_size est la taille du buffer utilisé. Le buffer de clés est aussi appelé le cache de clés.

Augmentez cette valeur pour obtenir une meilleure gestion des index (pour les lectures et écritures multiples), autant que vous le pouvez : 64 Mo sur une machine de 256 Mo est une valeur répandue. Toutefois, si vous utilisez une valeur trop grande (par exemple, plus de 50 % de votre mémoire totale), votre système risque de commencer à utiliser sa mémoire swap, et devenir très lent. N'oubliez pas que MySQL ne met pas en cache les données lues, et il faut laisser le système d'exploitation respirer.

Pour obtenir encore plus de vitesse lors de l'écriture de plusieurs lignes en même temps, utilisez LOCK TABLES. Voir Section 13.4.5, « Syntaxe de LOCK TABLES/UNLOCK TABLES ».

Vous pouvez vérifier les performances du buffer de clés avec la commande SHOW STATUS et en examinant les variables Key_read_requests, Key_reads, Key_write_requests et Key_writes. Voir Section 13.5.3, « Syntaxe de SHOW ».

Le ratio Key_reads/Key_read_requests doit normalement être inférieur à 0.01. Le ratio Key_writes/Key_write_requests est généralement près de 1 si vous utilisez essentiellement des modifications et des effacements, mais il peut être plus petit si vous avez des modifications qui changent plusieurs lignes en même temps, ou si vous utilisez l'option DELAY_KEY_WRITE.

La fraction du buffer de clés utilisée est déterminée avec la variable key_buffer_size en conjonction avec la variable Key_blocks_used et la taille de bloc de buffer. Depuis MySQL 4.1.1, la taille de bloc de buffer est disponible dans la variable serveur key_cache_block_size. La fraction utilisée du buffer est :

(Key_blocks_used * key_cache_block_size) / key_buffer_size

Avant MySQL 4.1.1, les blocs du cache de clés étaient de 1024 octets, ce qui fait que la fraction utilisée était :

(Key_blocks_used * 1024) / key_buffer_size

Voir Section 7.4.6, « Le cache de clés des tables MyISAM ».

- key_cache_age_threshold

Cette valeur contrôle le transit des buffers d'une sous-chaîne de cache de clés vers une autre, moins prioritaire. Les valeurs les plus basses accroissent la vitesse de transit. La valeur minimale est de 100. La valeur par défaut est 300. Cette variable a été ajoutée en MySQL 4.1.1. Voir Section 7.4.6, « Le cache de clés des tables MyISAM ».

- key_cache_block_size

La taille du bloc de cache de clés, en octets. La valeur par défaut est 1024. Cette variable a été ajoutée en MySQL 4.1.1. Voir Section 7.4.6, « Le cache de clés des tables MyISAM ».

- key_cache_division_limit

Le point de division entre la sous-chaîne prioritaire et la seconde sous-chaîne. Cette valeur est le pourcentage du buffer à utiliser pour la sous-chaîne secondaire. Les valeurs possibles vont de 1 à 100. La valeur par défaut est 100. Cette variable a été ajoutée en MySQL 4.1.1. Voir Section 7.4.6, « Le cache de clés des tables MyISAM ».

- language

La langue utilisée pour les messages d'erreurs.

- large_file_support

Si mysqld a été compilé avec le support des grands fichiers. Cette variable a été ajoutée en MySQL 3.23.28.

- local_infile

Si mysqld a été configuré avec le support de LOCAL pour les commandes LOAD DATA INFILE. Cette variable a été ajoutée en MySQL 4.0.3.

- locked_in_memory

Si mysqld a été verrouillé en mémoire avec --memlock Cette variable a été ajoutée en MySQL 3.23.25.

- log

Si le log de toutes les requêtes est activé. Voir Section 5.9.2, « Le log général de requêtes ».

- log_bin

Si le log binaire est activé. Cette variable a été ajoutée en MySQL 3.23.14. Voir Section 5.9.4, « Le log binaire ».

- log_slave_updates

Si les modifications des esclaves doivent être enregistrées. Le log binaire doit être activé pour que cette option fonctionne. Cette variable a été ajoutée en MySQL 3.23.17. Voir Section 6.8, « Options de démarrage de la réplication ».

- log_slow_queries

Indique si les requêtes lentes doivent être enregistrées. « Lente » est déterminé par la valeur de long_query_time. Cette variable a été ajoutée en MySQL 4.0.2. Voir Section 5.9.5, « Le log des requêtes lentes ».

- log_update

Si le log de modifications est activé. Cette variable a été ajoutée en MySQL 3.22.18. Notez que le log binaire est préférable au log de modifications, qui n'est plus disponible en MySQL 5.0. Voir Section 5.9.3, « Le log de modification ».

- long_query_time

Si une requête prend plus de long_query_time secondes, le compteur de requêtes lentes Slow_queries sera incrémenté. Si vous utilisez l'option --log-slow-queries, ces requêtes seront enregistrées dans un historique de requêtes lentes. Cette durée est mesurée en temps réel, et non pas en temps processus, ce qui fait que les requêtes qui seraient juste sous la limite avec un système légèrement chargé, pourraient être au-dessus avec le même système, mais chargé. Voir Section 5.9.5, « Le log des requêtes lentes ».

- low_priority_updates

Si cette option vaut 1, toutes les requêtes INSERT, UPDATE, DELETE et LOCK TABLE WRITE attendent qu'il n'y ait plus de SELECT ou de LOCK TABLE READ en attente pour cette table. Cette variable s'appelait avant sql_low_priority_updates. Cette variable a été ajoutée en MySQL 3.22.5.

- lower_case_table_names

Si cette option vaut 1, les noms de tables sont stockés en minuscules sur le disque, et les comparaisons de nom de tables seront insensibles à la casse. Depuis la version 4.0.2, cette option s'applique aussi aux noms de bases. Depuis la version 4.1.1 cette option s'applique aussi aux alias de table. Voir Section 9.2.2, « Sensibilité à la casse pour les noms ».

Vous ne devez pas mettre cette variable à 0 si vous utilisez MySQL sur un serveur qui n'a pas de sensibilité à la casse au niveau du système de fichiers (comme Windows ou Mac OS X). Nouveau en 4.0.18 : si cette variable vaut 0 est que le système de fichiers n'est pas sensible à la casse, MySQL va automatiquement donner la valeur de 2 à lower_case_table_names.

- max_allowed_packet

La taille maximale d'un paquet.

Le buffer de messages est initialisé avec net_buffer_length octets, mais peut grandir jusqu'à max_allowed_packet octets lorsque nécessaire. Cette valeur est par défaut petite, pour intercepter les gros paquets, probablement erronés.

Vous devez augmenter cette valeur si vous utilisez de grandes colonnes BLOB. Cette valeur doit être aussi grande que le plus grand BLOB que vous utiliserez. Le protocole limite actuellement max_allowed_packet à 16 Mo en MySQL 3.23 et 1 Go en MySQL 4.0.

- max_binlog_cache_size

Si une transaction multirequête requiert plus que cette quantité de mémoire, vous obtiendrez une erreur "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage". Cette variable a été ajoutée en MySQL 3.23.29.

- max_binlog_size

Disponible depuis la version 3.23.33. Si vous écrivez dans le log binaire (de réplication) et que cela dépasse la taille de max_binlog_size, une erreur sera indiquée. Vous ne pouvez pas donner à max_binlog_size une valeur inférieure à 1024 octets, ou plus grande que 1 Go. Cette variable a été ajoutée en MySQL 3.23.33.

Notez bien si vous utilisez les transactions : une transaction est écrite en une seule fois dans le log binaire, et elle ne peut pas être répartie en plusieurs fichiers. Par conséquent, si vous avez de grandes transactions, vous verrez peut-être des fichiers de log plus grands que max_binlog_size.

Si max_relay_log_size vaut 0, la valeur de max_binlog_size s'applique aussi aux logs de relais. max_relay_log_size a été ajoutée en MySQL 4.0.14.

- max_connect_errors

S'il y a plus que max_connect_errors connexions interrompues depuis un même hôte, cet hôte sera bloqué dans ses prochaines tentatives de connexions. Vous pouvez débloquer un hôte avec la commande FLUSH HOSTS.

- max_connections

Le nombre maximal de clients simultanés accepté. En augmentant cette valeur, vous augmentez le nombre de pointeurs de fichier que requiert mysqld. Voyez la section Section 7.4.8, « Quand MySQL ouvre et ferme les tables » pour des commentaires sur les pointeurs de fichiers. Voyez aussi la section Section A.2.6, « Erreur Too many connections  ».

- max_delayed_threads

Ne pas lancer plus que max_delayed_threads threads pour gérer les insertions INSERT DELAYED. Si vous essayez d'insérer des données dans une nouvelle table alors que tous les gestionnaires INSERT DELAYED sont utilisés, la ligne sera insérée comme si l'option DELAYED n'avait pas été spécifiée. Cette variable a été ajoutée en MySQL 3.23.0.

- max_error_count

Le nombre maximum d'erreurs, alertes et messages de note à stocker pour afficher avec SHOW ERRORS ou SHOW WARNINGS. Cette variable a été ajoutée en MySQL 4.1.0.

- max_heap_table_size

Ne pas autoriser la création de tables de type MEMORY (HEAP) plus grande que max_heap_table_size. La valeur de la variable est utilisée pour calculer la valeur maximale de MAX_ROWS pour la table MEMORY. Modifier cette variable n'a pas d'effet sur les tables existantes, à moins que la table ne soit recréée, avec une commande comme CREATE TABLE ou TRUNCATE TABLE, ou encore modifiée avec ALTER TABLE. Cette variable a été ajoutée en MySQL 3.23.0.

- max_insert_delayed_threads

Cette variable est un synonyme de max_delayed_threads. Cette variable a été ajoutée en MySQL 4.0.19.

- max_join_size

Les jointures qui liront probablement plus de max_join_size lignes, retourneront une erreur. Utilisez cette valeur si vos utilisateurs font des jointures avec de mauvaises clauses WHERE, qui prennent trop de temps, et retournent des millions de lignes.

En donnant une valeur à cette variable qui est autre que DEFAULT remet la valeur de SQL_BIG_SELECTS à 0. Si vous modifiez à nouveau la valeur de SQL_BIG_SELECTS, la variable max_join_size sera ignorée.

Si un résultat de requête est déjà dans le cache de requêtes, aucune limite de taille n'est vérifiée, car le résultat a déjà été compilé, et cela ne posera aucun problème au serveur pour l'envoyer à nouveau.

Cette variable s'appelait précédemment sql_max_join_size.

- max_relay_log_size

Disponible depuis la version 4.0.14. Si vous écrivez des données dans un log de relais et que leur taille dépasse la valeur donnée, le log de relais passe au fichier suivant. Cette variable vous permet de placer différentes contraintes de taille sur les logs binaires et de relais. Cependant, en donnant la valeur de 0 à cette valeur, MySQL utilisera max_binlog_size pour les deux logs, binaire et de relais. Vous devez donner à max_relay_log_size la valeur de 0 ou plus de 4096, et moins que 1 Go. Par défaut, c'est 0. Cette variable a été ajoutée en MySQL 4.0.14. Voir Section 6.3, « Détails d'implémentation de la réplication ».

- max_seeks_for_key

La limite de recherches lors de recherches de lignes basées sur un index. L'optimiseur MySQL va supposer que lorsque vous recherchez des lignes dans une table en analysant les index, vous n'aller pas générer plus de ce nombre de recherches, indépendamment de la cardinalité de la clé. En donnant une valeur faible à cette variable (100 ?) vous pouvez forcer MySQL à préférer les scans d'index plutôt que les scans de tables. Cette variable a été ajoutée en MySQL 4.0.14.

- max_sort_length

Le nombre d'octets à utiliser lors du tri des colonnes de type BLOB et TEXT. Seuls les max_sort_length octets de chaque valeur seront utilisés pour le tri. Le reste est ignoré.

- max_tmp_tables

Cette option ne fait encore rien. Le nombre maximal de tables temporaires qu'un client peut garder ouvertes en même temps.

- max_user_connections

Le nombre maximum de connexions actives pour un utilisateur particulier (0 = pas de limite). Cette variable a été ajoutée en MySQL 3.23.34.

- max_write_lock_count

Après max_write_lock_count poses de verrou en écriture, autorise quelques verrous en lecture. Cette variable a été ajoutée en MySQL 3.23.7.

- myisam_data_pointer_size

La taille par défaut du pointeur à utiliser avec CREATE TABLE pour les tables MyISAM lorsque qu'aucune option MAX_ROWS n'est spécifiée. Cette variable ne peut pas être inférieure à 2 ni supérieure à 8. La valeur par défaut est de 4. Cette variable a été ajoutée en MySQL 4.1.2. Voir Section A.2.11, « Erreur The table is full ».

- myisam_max_extra_sort_file_size

Si un fichier temporaire est utilisé pour créer rapidement un fichier d'index pour une table MyISAM est plus grand que la valeur de cette variable, alors préfère la méthode du cache de clés. C'est surtout utilisé pour forcer les grands index à utiliser la méthode plus lente du cache de clés pour créer l'index. Cette variable a été ajoutée en MySQL 3.23.37. Note : la valeur donnée est en mégaoctets avant 4.0.3 et en octets après.

- myisam_max_sort_file_size

La taille maximale du fichier temporaire que MySQL est autorisé à utiliser durant la recréation des fichiers d'index (avec REPAIR, ALTER TABLE ou LOAD DATA INFILE). Si la taille du fichier dépasse myisam_max_sort_file_size, l'index sera créé avec un cache de clés (plus lent). Cette variable a été ajoutée en MySQL 3.23.37. Note : ce paramètre est spécifié en mégaoctets avant la version 4.0.3 et en octets depuis.

- myisam_recover_options

La valeur de l'option --myisam-recover. Cette variable a été ajoutée en MySQL 3.23.36.

- myisam_repair_threads

Si cette valeur est plus grande que 1, les index des tables MyISAM durant un processus de Repair by sorting seront créés en parallèle : chaque index avec son propre thread. Note : les réparations multithreadées sont encore en développement, et en qualité alpha. Cette variable a été ajoutée en MySQL 4.0.13.

- myisam_sort_buffer_size

Le buffer qui est alloué lors du tri d'index avec la commande REPAIR ou lors de la création d'index avec CREATE INDEX ou ALTER TABLE. Cette variable a été ajoutée en MySQL 3.23.16.

- named_pipe

Sous Windows, indique si le serveur supporte les connexions via les pipes nommés. Cette variable a été ajoutée en MySQL 3.23.50.

- net_buffer_length

Le buffer de communications est remis à zéro entre deux requêtes. Cela ne devrait pas être modifié, mais si vous avez très peu de mémoire, vous pouvez le remettre à la taille présumée de la requête (c'est-à-dire, la taille de la requête envoyée par le client. Si la requête dépasse cette taille, le buffer est automatiquement agrandi jusqu'à max_allowed_packet octets).

- net_read_timeout

Nombre de secondes d'attente des dernières données, avant d'annuler la lecture. Notez que lorsque nous n'attendons pas de données d'une connexion, le délai d'expiration est donné par write_timeout. Voir aussi slave_net_timeout. Cette variable a été ajoutée en MySQL 3.23.20.

- net_retry_count

Si une lecture sur un port de communication est interrompue, net_retry_count tentatives sont faites avant d'abandonner. Cette valeur doit être particulièrement grande pour FreeBSD, car les interruptions internes sont envoyées à tous les threads. Cette variable a été ajoutée en MySQL 3.23.7.

- net_write_timeout

Nombre de secondes d'attente pour qu'un bloc soit envoyé à une connexion, avant d'annuler l'écriture. Voir aussi net_read_timeout. Cette variable a été ajoutée en MySQL 3.23.20.

- open_files_limit

Si open_files_limit ne vaut pas 0, alors mysqld va utiliser cette valeur pour réserver des pointeurs de fichiers à utiliser avec setrlimit(). Si cette valeur est 0, alors mysqld va réserver max_connections*5 ou max_connections + table_cache*2 (le plus grand des deux) pointeurs de fichiers. Vous devriez augmenter cette valeur si mysqld vous donne des erreurs du type 'Too many open files'.

- pid_file

Le chemin vers le fichier de processus (PID). La valeur de l'option --pid-file. Cette variable a été ajoutée en MySQL 3.23.23.

- port

Le port de connexion sur lequel le serveur attend les connexions TCP/IP. Cette variable peut être spécifiée avec --port.

- protocol_version

La version du protocole utilisé par le serveur MySQL. Cette variable a été ajoutée en MySQL 3.23.18.

- query_alloc_block_size

Taille des blocs de mémoire alloués pour les objets durant l'analyse et la préparation des requêtes. Si vous avez un problème avec la fragmentation de la mémoire, cela peut être utile d'augmenter cette valeur. Cette variable a été ajoutée en MySQL 4.0.16.

- query_cache_limit

Ne met pas en cache les résultats qui sont plus grands que query_cache_limit. Par défaut, 1 Mo. Cette variable a été ajoutée en MySQL 4.0.1.

- query_cache_min_res_unit

La taille minimale pour les blocs alloués par le cache de requêtes. La valeur par défaut est de 4 ko. Des informations sur l'optimisation de cette variable sont données dans la section Section 5.11.3, « Configuration du cache de requêtes ». Cette variable a été ajoutée en MySQL 4.1.

- query_cache_size

La mémoire allouée pour stocker les résultats des vieilles requêtes. Si query_cache_size vaut 0, le cache de requêtes est désactivé (par défaut). Cette variable a été ajoutée en MySQL 4.0.1.

- query_cache_type

Choisit le type de cache de requêtes. Modifier la variable GLOBAL modifie le cache pour tous les clients. Les clients peuvent modifier la variable de SESSION pour l'adapter à leur utilisation.

query_cache_type peut prendre les valeurs numériques suivantes :

Option

Description

0 or OFF

Ne met pas en cache les résultats. Notez que cela ne va pas libérer le buffer de requête. Pour cela, il faut donner à query_cache_size la valeur de 0.

1 or ON

Met en cache tous les résultats exceptés les requêtes SELECT SQL_NO_CACHE ....

2 or DEMAND

Met en cache uniquement les requêtes SELECT SQL_CACHE ....

Cette variable a été ajoutée en MySQL 4.0.3.

- query_cache_wlock_invalidate

Normalement, lorsqu'un client pose un verrou WRITE sur une table MyISAM, les autres clients ne sont pas empêchés d'émettre des requêtes sur la table, si le résultat est déjà en cache. En donnant la valeur de 1 à cette variable, le verrou WRITE empêchera toutes les requêtes qui feront référence à cette table. Cela force les autres clients à attendre que le verrou se libère. Cette variable a été ajoutée en MySQL 4.0.19.

- query_prealloc_size

La taille du buffer persistant utilisé pour l'analyse des requêtes et leur exécution. Ce buffer n'est pas libéré entre deux requêtes. Si vous manipulez des requêtes complexes, une valeur plus grande pour query_prealloc_size sera plus utile pour améliorer les performances, car elle peut réduire les allocations complémentaires de mémoire durant l'exécution des requêtes.

Cette variable a été ajoutée en MySQL 4.0.16.

- range_alloc_block_size

La taille de bloc qui est alloué lors de l'optimisation d'intervalle. Cette variable a été ajoutée en MySQL 4.0.16.

- read_buffer_size

Chaque thread qui fait une recherche séquentielle alloue un buffer de cette taille pour son scan. Si vous faites de nombreux scans séquentiels, vous pourriez avoir besoin d'augmenter cette valeur. Cette variable a été ajoutée en MySQL 4.0.3. Auparavant, cette variable s'appelait record_buffer.

- read_only

Lorsque cette variable vaut ON pour un serveur de réplication esclave, cela fait que le serveur ne permet aucune modification, hormis celles de la réplication, ou des utilisateurs ayant le droit de SUPER. Cela peut être pratique pour s'assurer qu'un esclave n'accepte aucune modification des clients. Cette variable a été ajoutée en MySQL 4.0.14.

- read_rnd_buffer_size

Lors de la lecture des lignes triées, les lignes sont lues dans un buffer, pour éviter les accès disques. En donnant à cette variable une grande valeur, vous améliorerez les performances des clauses ORDER BY. Cependant, ce buffer est alloué pour chaque client : il est recommandé de ne pas donner une valeur globale trop importante. Au lieu de cela, modifiez cette valeur si votre client a besoin de faire de gros tris. Cette variable a été ajoutée en MySQL 4.0.3. Auparavant, cette variable s'appelait record_rnd_buffer.

- safe_show_database

Ne montre pas les bases pour lesquelles un utilisateur n'a pas des droits de bases ou de tables. Cela peut améliorer considérablement la sécurité si vous craignez de voir les utilisateurs découvrir ce que les autres ont mis en place. Voir aussi skip_show_database.

Cette variable a été supprimée en MySQL 4.0.5. À la place, utilisez le droit SHOW DATABASES pour contrôler les accès aux noms des bases de données.

- secure_auth

Si le serveur MySQL a été lancé avec l'option --secure-auth, il va empêcher les connexions des comptes qui ont un compte au format préversion 4.1. Dans ce cas, la valeur de cette variable vaut ON, sinon, c'est OFF.

Vous devriez activer cette option si vous voulez empêcher l'utilisation des mots de passe à l'ancien format (et donc, améliorer la sécurité de votre serveur). Cette variable a été ajoutée en MySQL 4.1.1.

Le démarrage du serveur échouera avec une erreur si cette option est activée, mais que la table de droits est toujours au format préversion 4.1.

Lorsqu'elle est utilisée comme une option du client, le client va refuser de se connecter au serveur si le serveur requiert un mot de passe à l'ancien format.

- server_id

La valeur de l'option --server-id. Elle sert à la réplication. Cette variable a été ajoutée en MySQL 3.23.26.

- skip_external_locking

skip_locking vaut OFF si mysqld utilise le verrouillage externe. Cette variable a été ajoutée en MySQL 4.0.3. Auparavant, cette variable s'appelait skip_locking.

- skip_networking

skip_networking vaut ON si seules les connexions locales (via socket) sont autorisées. Sous Unix, les connexions locales utilisent un fichier de socket Unix. Sous Windows, les connexions locales utilisent les pipes nommés. Sous NetWare, seules les connexions TCP/IP sont supportées, alors ne donnez pas la valeur de ON à cette variable. Cette variable a été ajoutée en MySQL 3.22.23.

- skip_show_database

skip_show_database empêche les utilisateurs d'exécuter des commandes SHOW DATABASES s'ils n'ont pas les droits de PROCESS. Cela peut améliorer la sécurité si vous craignez de voir les utilisateurs découvrir ce que les autres ont mis en place. Voir aussi safe_show_database. Cette variable a été ajoutée en MySQL 3.23.4. Depuis MySQL 4.0.2, son effet dépend aussi du droit SHOW DATABASES : si la variable vaut ON, la commande SHOW DATABASES n'est autorisée qu'aux comptes ayant le droit de SHOW DATABASES, et la commande affiche tous les noms de bases. Si la valeur est OFF, SHOW DATABASES est autorisé à tous les utilisateurs, mais il n'affichera que les noms de bases de données pour lesquelles l'utilisateur a le droit de SHOW DATABASES ou un droit quelconque dans la base.

- slave_net_timeout

Nombre de secondes d'attente de données en lecture ou écriture sur une connexion maître/esclave avant d'annuler. Cette variable a été ajoutée en MySQL 3.23.40.

- slow_launch_time

Si la création du thread prend plus de slow_launch_time secondes, le compteur de threads lents Slow_launch_threads sera incrémenté. Cette variable a été ajoutée en MySQL 3.23.15.

- socket

La socket Unix utilisé par le serveur. Sous Unix, c'est le fichier de socket Unix, pour les connexions locales. Sous Windows, c'est le nom du pipe nommé, pour les connexions locales.

- sort_buffer_size

Chaque thread qui doit faire un tri alloue un buffer de cette taille. Augmentez cette taille pour accélérer les clauses ORDER BY ou GROUP BY. Voir Section A.4.4, « Où MySQL stocke les fichiers temporaires ? ».

- sql_mode

Le mode SQL courant. Cette variable a été ajoutée en MySQL 3.23.41. Voir Section 5.2.2, « Le mode SQL du serveur ».

- storage_engine

Cette variable est un synonyme de table_type. Cette variable a été ajoutée en MySQL 4.1.2.

- table_cache

Le nombre de tables ouvertes pour tous les threads réunis. En augmentant cette valeur, vous augmentez le nombre de pointeurs de fichiers que mysqld utilise. Vous pouvez vérifier si vous avez besoin de plus de cache de tables en étudiant la valeur de la variable Opened_tables. Voir Section 5.2.4, « Variables de statut du serveur  ». Si cette variable est grande, c'est que vous ne faites pas souvent de commandes FLUSH TABLES (qui forcent les tables à se recharger), vous devrez alors augmenter cette valeur.

Pour plus d'informations sur le cache de tables, voyez Section 7.4.8, « Quand MySQL ouvre et ferme les tables ».

- table_type

Le type de table par défaut. Pour configurer le type de table par défaut au démarrage, utilisez --default-table-type. Cette variable a été ajoutée en MySQL 3.23.0. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

- thread_cache_size

Combien de threads nous allons conserver en cache pour réutilisation. Lorsqu'un client se déconnecte, les threads du client sont mis en cache s'il n'y en a pas déjà thread_cache_size de conservé. Tous les nouveaux threads sont d'abord prélevés dans le cache, et uniquement lorsque le cache est vide, un nouveau thread est créé. Cette variable peut vous permettre d'améliorer les performances si vous avez de nombreuses connexions. Normalement, thread_cache_size ne donne pas d'amélioration notable si vous avez une bonne implémentation des threads. En examinant la différence entre les variables de statut Connections et Threads_created vous pouvez voir comment votre système de cache de threads est efficace. (Voir Section 5.2.4, « Variables de statut du serveur  » pour plus de détails) Cette variable a été ajoutée en MySQL 3.23.16.

- thread_concurrency

Sous Solaris, mysqld va appeler thr_setconcurrency() avec cette valeur. thr_setconcurrency() permet à l'application de donner au système de threads une indication sur le nombre de threads qui seront exécutés en même temps. Cette variable a été ajoutée en MySQL 3.23.7.

- thread_stack

La taille de la pile pour chaque thread. De nombreuses limites détectées par crash-me sont dépendantes de cette valeur. La valeur par défaut est suffisamment grande pour des opérations normales. Voir Section 7.1.4, « La suite de tests MySQL ».

- timezone

Le fuseau horaire du serveur. Cette option prend la valeur de la variable d'environnement TZ lorsque mysqld est démarré. Elle peut aussi être modifiée avec l'argument --timezone de mysqld_safe. Cette variable a été ajoutée en MySQL 3.23.15. Voir Section A.4.6, « Problèmes de fuseaux horaires ».

- tmp_table_size

Si une table temporaire en mémoire excède cette taille, MySQL va automatiquement la convertir en une table MyISAM sur le disque. Augmentez la valeur de tmp_table_size si vous faites un usage intensif de la clause GROUP BY et que vous avez beaucoup de mémoire.

- tmpdir

Le dossier utilisé pour les fichiers temporaires et les tables temporaires. Depuis MySQL 4.1, cette variable peut prendre une liste de différents chemins, qui sont utilisés circulairement. Les chemins doivent être séparés par des deux-points (':') sous Unix et des points-virgules (';') sous Windows, NetWare et OS/2.

Cette fonctionnalité permet de répartir la charge en plusieurs disques. Si le serveur MySQL sert d'esclave de réplication, vous ne devez pas faire pointer tmpdir sur un dossier en mémoire, car il sera vidé si le serveur redémarre. Un esclave de réplication doit pouvoir reprendre ses fichiers temporaires pour que la réplication puisse redémarrer, en incluant les tables temporaires et les opérations de LOAD DATA INFILE. Si les fichiers du dossier temporaire sont perdus au redémarrage, la réplication s'arrêtera.

Cette variable a été ajoutée en MySQL 3.22.4.

- transaction_alloc_block_size

La taille de bloc d'allocation de mémoire pour le stockage des requêtes qui font partie d'une transaction, qui sera stockée dans le log binaire durant une validation. Cette variable a été ajoutée en MySQL 4.0.16.

- transaction_prealloc_size

Le buffer persistant pour transaction_alloc_blocks, qui n'est pas libéré entre deux requêtes. En rendant ce buffer « assez grand » pour accommoder toutes les requêtes dans une transaction classique, vous pouvez éviter de nombreux appels malloc(). Cette variable a été ajoutée en MySQL 4.0.16.

- tx_isolation

Le niveau par défaut d'isolation de transactions. Cette variable a été ajoutée en MySQL 4.0.3.

- version

Le numéro de version du serveur.

- wait_timeout

Le nombre de secondes d'attente du serveur sur une connexion non interactive avant de la refermer.

Lors du démarrage du thread, SESSION.WAIT_TIMEOUT est initialisé avec GLOBAL.WAIT_TIMEOUT ou GLOBAL.INTERACTIVE_TIMEOUT, suivant le type de client (tel que défini par l'option de connexion CLIENT_INTERACTIVE). Voir aussi interactive_timeout.

5-2-3-1 - Variables système dynamiques

Depuis MySQL version 4.0.3, de nombreuses variables système sont dynamiques, et peuvent être modifiées durant l'exécution avec les commandes SET GLOBAL ou SET SESSION. Vous pouvez aussi sélectionner leur valeur avec SELECT. Voir Section 9.4, « Variables système ».

La table suivante montre la liste complète de toutes les variables dynamiques. La dernière colonne indique si les options GLOBAL ou SESSION, ou les deux, s'appliquent.

Nom de la variable

Type de valeur

Application

autocommit

boolean

SESSION

big_tables

boolean

SESSION

binlog_cache_size

numeric

GLOBAL

bulk_insert_buffer_size

numeric

GLOBAL | SESSION

character_set_client

string

GLOBAL | SESSION

character_set_connection

string

GLOBAL | SESSION

character_set_results

string

GLOBAL | SESSION

character_set_server

string

GLOBAL | SESSION

collation_connection

string

GLOBAL | SESSION

collation_server

string

GLOBAL | SESSION

concurrent_insert

boolean

GLOBAL

connect_timeout

numeric

GLOBAL

convert_character_set

string

GLOBAL | SESSION

default_week_format

numeric

GLOBAL | SESSION

delay_key_write

OFF | ON | ALL

GLOBAL

delayed_insert_limit

numeric

GLOBAL

delayed_insert_timeout

numeric

GLOBAL

delayed_queue_size

numeric

GLOBAL

error_count

numeric

SESSION

flush

boolean

GLOBAL

flush_time

numeric

GLOBAL

foreign_key_checks

boolean

SESSION

ft_boolean_syntax

numeric

GLOBAL

group_concat_max_len

numeric

GLOBAL | SESSION

identity

numeric

SESSION

insert_id

boolean

SESSION

interactive_timeout

numeric

GLOBAL | SESSION

join_buffer_size

numeric

GLOBAL | SESSION

key_buffer_size

numeric

GLOBAL

last_insert_id

numeric

SESSION

local_infile

boolean

GLOBAL

log_warnings

boolean

GLOBAL

long_query_time

numeric

GLOBAL | SESSION

low_priority_updates

boolean

GLOBAL | SESSION

max_allowed_packet

numeric

GLOBAL | SESSION

max_binlog_cache_size

numeric

GLOBAL

max_binlog_size

numeric

GLOBAL

max_connect_errors

numeric

GLOBAL

max_connections

numeric

GLOBAL

max_delayed_threads

numeric

GLOBAL

max_error_count

numeric

GLOBAL | SESSION

max_heap_table_size

numeric

GLOBAL | SESSION

max_insert_delayed_threads

numeric

GLOBAL

max_join_size

numeric

GLOBAL | SESSION

max_relay_log_size

numeric

GLOBAL

max_seeks_for_key

numeric

GLOBAL | SESSION

max_sort_length

numeric

GLOBAL | SESSION

max_tmp_tables

numeric

GLOBAL

max_user_connections

numeric

GLOBAL

max_write_lock_count

numeric

GLOBAL

myisam_max_extra_sort_file_size

numeric

GLOBAL | SESSION

myisam_max_sort_file_size

numeric

GLOBAL | SESSION

myisam_repair_threads

numeric

GLOBAL | SESSION

myisam_sort_buffer_size

numeric

GLOBAL | SESSION

net_buffer_length

numeric

GLOBAL | SESSION

net_read_timeout

numeric

GLOBAL | SESSION

net_retry_count

numeric

GLOBAL | SESSION

net_write_timeout

numeric

GLOBAL | SESSION

query_alloc_block_size

numeric

GLOBAL | SESSION

query_cache_limit

numeric

GLOBAL

query_cache_size

numeric

GLOBAL

query_cache_type

enumeration

GLOBAL | SESSION

query_cache_wlock_invalidate

boolean

GLOBAL | SESSION

query_prealloc_size

numeric

GLOBAL | SESSION

range_alloc_block_size

numeric

GLOBAL | SESSION

read_buffer_size

numeric

GLOBAL | SESSION

read_only

numeric

GLOBAL

read_rnd_buffer_size

numeric

GLOBAL | SESSION

rpl_recovery_rank

numeric

GLOBAL

safe_show_database

boolean

GLOBAL

server_id

numeric

GLOBAL

slave_compressed_protocol

boolean

GLOBAL

slave_net_timeout

numeric

GLOBAL

slow_launch_time

numeric

GLOBAL

sort_buffer_size

numeric

GLOBAL | SESSION

sql_auto_is_null

boolean

SESSION

sql_big_selects

boolean

SESSION

sql_big_tables

boolean

SESSION

sql_buffer_result

boolean

SESSION

sql_log_bin

boolean

SESSION

sql_log_off

boolean

SESSION

sql_log_update

boolean

SESSION

sql_low_priority_updates

boolean

GLOBAL | SESSION

sql_max_join_size

numeric

GLOBAL | SESSION

sql_quote_show_create

boolean

SESSION

sql_safe_updates

boolean

SESSION

sql_select_limit

numeric

SESSION

sql_slave_skip_counter

numeric

GLOBAL

sql_warnings

boolean

SESSION

storage_engine

enumeration

GLOBAL | SESSION

table_cache

numeric

GLOBAL

table_type

enumeration

GLOBAL | SESSION

thread_cache_size

numeric

GLOBAL

timestamp

boolean

SESSION

tmp_table_size

enumeration

GLOBAL | SESSION

transaction_alloc_block_size

numeric

GLOBAL | SESSION

transaction_prealloc_size

numeric

GLOBAL | SESSION

tx_isolation

enumeration

GLOBAL | SESSION

unique_checks

boolean

SESSION

wait_timeout

numeric

GLOBAL | SESSION

warning_count

numeric

SESSION

Les variables qui sont marquées comme « string » prennent une valeur de chaîne de caractères. Les variables qui sont marquées comme « numeric » prennent un nombre. Les variables qui sont marquées comme « boolean » peuvent prendre 0 ou 1, ON ou OFF. Les variables qui sont marquées comme « enumeration » doivent normalement prendre l'une des valeurs possibles de cette variable, mais elles peuvent aussi prendre le numéro de l'élément dans l'énumération. Pour les systèmes à énumération, la première énumération est 0. Cela est différent des colonnes de type ENUM, pour qui la première valeur est la 1.

5-2-4 - Variables de statut du serveur

SHOW STATUS affiche des informations sur le statut du serveur (par exemple, mysqladmin extended-status). L'affichage ressemble à ce qui est affiché ci-dessous, mais les valeurs différeront sûrement de votre propre serveur.

mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_files        | 60         |
| Created_tmp_tables       | 8340       |
| Delayed_errors           | 0          |
| Delayed_insert_threads   | 0          |
| Delayed_writes           | 0          |
| Flush_commands           | 1          |
| Handler_delete           | 462604     |
| Handler_read_first       | 105881     |
| Handler_read_key         | 27820558   |
| Handler_read_next        | 390681754  |
| Handler_read_prev        | 6022500    |
| Handler_read_rnd         | 30546748   |
| Handler_read_rnd_next    | 246216530  |
| Handler_update           | 16945404   |
| Handler_write            | 60356676   |
| Key_blocks_used          | 14955      |
| Key_read_requests        | 96854827   |
| Key_reads                | 162040     |
| Key_write_requests       | 7589728    |
| Key_writes               | 3813196    |
| Max_used_connections     | 0          |
| Not_flushed_delayed_rows | 0          |
| Not_flushed_key_blocks   | 0          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Open_tables              | 1          |
| Opened_tables            | 44600      |
| Qcache_free_blocks       | 36         |
| Qcache_free_memory       | 138488     |
| Qcache_hits              | 79570      |
| Qcache_inserts           | 27087      |
| Qcache_lowmem_prunes     | 3114       |
| Qcache_not_cached        | 22989      |
| Qcache_queries_in_cache  | 415        |
| Qcache_total_blocks      | 912        |
| Questions                | 2026873    |
| Select_full_join         | 0          |
| Select_full_range_join   | 0          |
| Select_range             | 99646      |
| Select_range_check       | 0          |
| Select_scan              | 30802      |
| Slave_open_temp_tables   | 0          |
| Slave_running            | OFF        |
| Slow_launch_threads      | 0          |
| Slow_queries             | 0          |
| Sort_merge_passes        | 30         |
| Sort_range               | 500        |
| Sort_rows                | 30296250   |
| Sort_scan                | 4650       |
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_connected        | 1          |
| Threads_created          | 30022      |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

De nombreuses variables de statut sont remises à 0 par la commande FLUSH STATUS.

Les variables de statut ont les significations suivantes. Les variables compteur de commande Com_xxx ont été ajoutées en MySQL 3.23.47. Les variables de cache de requêtes Qcache_xxx ont été ajoutées en MySQL 4.0.1. Sinon, les variables sans versions sont présentes depuis MySQL 3.22.

- Aborted_clients

Nombre de connexions annulées parce que le client est mort sans se déconnecter correctement. Voir Section A.2.10, « Erreurs de communication / Connexion annulée ».

- Aborted_connects

Nombre de tentatives de connexions au serveur MySQL qui ont échoué. Voir Section A.2.10, « Erreurs de communication / Connexion annulée ».

- Binlog_cache_disk_use

Le nombre de transactions qui ont utilisé le cache de logs binaires, mais qui ont dépassé la taille de binlog_cache_size et ont finalement utilisé un fichier temporaire pour stocker les commandes de la transaction. Cette variable a été ajoutée en MySQL 4.1.2.

- Binlog_cache_use

Le nombre de transactions qui ont utilisé le cache de logs binaires temporaires. Cette variable a été ajoutée en MySQL 4.1.2.

- Bytes_received

Nombre d'octets reçu de tous les clients. Cette variable a été ajoutée en MySQL 3.23.7.

- Bytes_sent

Nombre d'octets envoyés à tous les clients. Cette variable a été ajoutée en MySQL 3.23.7.

- Com_xxx

Nombre d'exécutions de chaque commande xxx. Il y a une variable par type de commande. Par exemple, Com_delete et Com_insert comptent respectivement les commandes DELETE et INSERT.

- Connections

Nombre de tentatives de connexion au serveur MySQL, réussies ou pas.

- Created_tmp_disk_tables

Nombre de tables temporaires implicites créées sur le disque lors d'exécutions de commandes. Cette variable a été ajoutée en MySQL 3.23.24.

- Created_tmp_files

Combien de fichiers temporaires mysqld a créés. Si Created_tmp_disk_tables est grand, augmentez la taille de tmp_table_size pour que les tables temporaires restent plus souvent en mémoire.

- Created_tmp_tables

Nombre de tables temporaires implicites créées en mémoire lors d'exécutions de commandes. Cette variable a été ajoutée en MySQL 3.23.28.

- Delayed_errors

Nombre de lignes écrites avec INSERT DELAYED pour lesquelles des erreurs sont survenues (probablement une erreur de doublons (duplicate key)).

- Delayed_insert_threads

Nombre de gestionnaires d'insertions retardées sont en cours d'utilisation.

- Delayed_writes

Nombre de lignes écrites avec INSERT DELAYED.

- Flush_commands

Nombre de commandes FLUSH.

- Handler_commit

Nombre de commandes internes COMMIT. Cette variable a été ajoutée en MySQL 4.0.2.

- Handler_delete

Nombre de fois qu'une ligne a été effacée dans une table.

- Handler_read_first

Nombre de fois que la première ligne a été lue dans un index. Si ce chiffre est haut, c'est que le serveur fait de nombreuses recherches par analyse complète de la table, par exemple SELECT col1 FROM foo, en supposant que col1 est indexé.

- Handler_read_key

Nombre de requêtes de lecture de lignes basées sur une clé. Si ce chiffre est grand, c'est une bonne indication de l'indexation correcte de vos tables.

- Handler_read_next

Nombre de requêtes de lecture de la ligne suivante en ordre. Cela sera augmenté si vous listez une colonne avec une contrainte d'intervalle. Cette valeur sera aussi incrémentée si vous effectuez un scan d'index.

- Handler_read_prev

Nombre de requêtes de lecture de la clé précédente, dans l'ordre. C'est souvent utilisé pour optimiser les clauses ORDER BY ... DESC. Cette variable a été ajoutée en MySQL 3.23.6.

- Handler_read_rnd_next

Nombre de requêtes de lecture de la prochaine ligne dans le fichier de données. Ce chiffre sera grand si vous faites de nombreux scans de tables. Généralement, cela indique que vos requêtes ne sont pas écrites pour profiter des index que vous avez mis en place.

- Handler_read_rnd

Nombre de lectures d'une ligne basée sur une position fixe. Ce chiffre sera grand si vous effectuez de nombreuses requêtes qui réclament le tri du résultat.

- Handler_rollback

Nombre de commandes internes ROLLBACK.

- Handler_update

Nombre de requêtes de modification d'une ligne dans une table.

- Handler_write

Nombre de requêtes pour insérer une ligne dans une table.

- Key_blocks_used

Nombre de blocs utilisés dans un cache de clés. Vous pouvez utiliser cette valeur pour déterminer l'occupation du cache de clés : voyez la discussion de key_buffer_size dans Section 5.2.3, « Variables serveur système ».

- Key_read_requests

Nombre de requêtes de lecture d'un bloc de clés dans le cache.

- Key_reads

Nombre de lecture physique d'un bloc de clés sur le disque. Si Key_reads est grand, alors votre valeur pour key_buffer_size est probablement trop petite. Le ratio peut être calculé avec Key_reads/Key_read_requests.

- Key_write_requests

Nombre de requêtes d'écriture d'un bloc de clés dans le cache.

- Key_writes

Nombre d'écritures physiques de blocs de clés sur le disque.

- Max_used_connections

Nombre maximum de connexions utilisées simultanément.

- Not_flushed_delayed_rows

Nombre de lignes en attente d'écriture dans les listes INSERT DELAY.

- Not_flushed_key_blocks

Nombre de blocs de clés dans le cache de clés, qui ont été modifiées, mais pas encore écrites sur le disque.

- Open_files

Nombre de fichiers ouverts.

- Open_streams

Nombre de flux ouverts (utilisés généralement pour les logs).

- Open_tables

Nombre de tables ouvertes.

- Opened_tables

Nombre de tables qui ont été ouvertes. Si Opened_tables est grand, votre valeur pour table_cache est probablement trop petite.

- Qcache_free_blocks

Le nombre de blocs de mémoire libre dans le cache de requêtes.

- Qcache_free_memory

La quantité de mémoire libre dans le cache de requêtes.

- Qcache_hits

Le nombre de sollicitations du cache.

- Qcache_inserts

Le nombre de requêtes ajoutées dans le cache.

- Qcache_lowmem_prunes

Le nombre de requêtes qui ont été effacées du cache, pour libérer de la place.

- Qcache_not_cached

Le nombre de requêtes non cachées (elles ne peuvent pas être mises en cache, ou à cause de query_cache_type).

- Qcache_queries_in_cache

Le nombre de requêtes enregistrées dans le cache.

- Qcache_total_blocks

Le nombre total de blocs dans le cache de requêtes.

- Questions

Nombre de requêtes envoyées au serveur.

- Rpl_status

Statut de la réplication sans erreur (réservé pour utilisation ultérieure).

- Select_full_join

Nombre de jointures sans clé (si cette variable vaut 0, vous devriez vérifier soigneusement les index de vos tables). Cette variable a été ajoutée en MySQL 3.23.25.

- Select_full_range_join

Nombre de jointures où une recherche d'intervalle a été utilisée. Cette variable a été ajoutée en MySQL 3.23.25.

- Select_range_check

Nombre de jointures sans clé, où l'utilisation de clé a été vérifiée après chaque ligne (si cette variable vaut 0, vous devriez vérifier soigneusement les index de vos tables). Cette variable a été ajoutée en MySQL 3.23.25.

- Select_range

Nombre de jointures où une recherche d'intervalle a été utilisée sur la première table. (Ce n'est généralement pas important, même si cette valeur est importante.) Cette variable a été ajoutée en MySQL 3.23.25.

- Select_scan

Nombre de jointures où la première table a été totalement analysée. Cette variable a été ajoutée en MySQL 3.23.25.

- Slave_open_temp_tables

Nombre de tables temporaires actuellement utilisées par le thread esclave. Cette variable a été ajoutée en MySQL 3.23.29.

- Slave_running

Cette variable vaut ON si ce serveur est un esclave connecté au maître. Cette variable a été ajoutée en MySQL 3.23.16.

- Slow_launch_threads

Nombre de threads qui ont pris plus de slow_launch_time secondes pour être créés. Cette variable a été ajoutée en MySQL 3.23.15.

- Slow_queries

Nombre de requêtes qui ont pris plus de long_query_time pour s'exécuter. Voir Section 5.9.5, « Le log des requêtes lentes ».

- Sort_merge_passes

Nombre de passes que l'algorithme de tri a dû faire. Si cette valeur est grande, vous devriez vérifier la taille de sort_buffer.

- Sort_range

Nombre de tris qui ont été faits sur des intervalles.

- Sort_rows

Nombre de lignes triées.

- Sort_scan

Nombre de tris qui ont été faits en analysant la table.

- ssl_xxx

Variables utilisées par SSL. Réservée pour utilisation ultérieure. Ces variables ont été ajoutées en MySQL 4.0.0.

- Table_locks_immediate

Nombre de fois que la table a reçu immédiatement un verrou. Disponible depuis 3.23.33. Cette variable a été ajoutée en MySQL 3.23.33.

- Table_locks_waited

Nombre de fois qu'une table n'a pu recevoir de verrou immédiatement, et qu'il a fallu attendre. Si ce chiffre est haut, vous avez des problèmes de performance, et vous devriez optimiser vos requêtes, couper vos tables en deux, ou utiliser la réplication. Disponible depuis la version 3.23.33. Cette variable a été ajoutée en MySQL 3.23.33.

- Threads_cached

Nombre de threads dans le cache de threads. Cette variable a été ajoutée en MySQL 3.23.17.

- Threads_connected

Nombre de connexions actuellement ouvertes.

- Threads_created

Nombre de threads créés pour gérer les connexions. Si Threads_created est grand, vous pouvez augmenter la valeur de

- Threads_running

Nombre de threads qui ne dorment pas.

- Uptime

Durée de vie du serveur, en secondes depuis le redémarrage.

5-3 - Le processus d'extinction de MySQL

Le processus d'extinction du serveur peut se résumer comme ceci :

1. Le processus est activé ;

2. Le serveur crée un thread d'extinction, si nécessaire ;

3. Le serveur cesse d'accepter les nouvelles connexions ;

4. Le serveur conclut les activités en cours ;

5. Les moteurs de stockages se ferment ;

6. Le serveur se termine.

Voici une version plus détaillée de ce synopsis.

1. Le processus est activé

L'extinction du serveur peut être initiée par plusieurs méthodes. Par exemple, un utilisateur avec le droit de SHUTDOWN peut exécuter la commande mysqladmin shutdown. mysqladmin peut être utilisée sur n'importe quelle plate-forme supportée par MySQL. Les autres méthodes d'extinction spécifiques aux systèmes d'exploitation existent aussi : le serveur s'éteint lorsqu'il reçoit un signal SIGTERM sous Unix. Un serveur installé comme service Windows s'éteint sur ordre du gestionnaire.

2. Le serveur crée un thread d'extinction, si nécessaire

En fonction de l'origine de l'extinction, le serveur peut lancer un thread qui gèrera l'extinction. Si l'extinction a été demandée par un client, un thread d'extinction est créé. Si l'extinction est le résultat d'un signal SIGTERM, le thread signal pourra gérer l'extinction lui-même, ou alors lancer un autre thread. SI le serveur essaie de créer un thread et ne peut pas le faire (par exemple, plus de mémoire), il va émettre un message qui apparaitra comme ceci dans les logs :

Error: Can't create thread to kill server

3. Le serveur cesse d'accepter les nouvelles connexions

Pour éviter de voir de nouvelles opérations se lancer, le serveur commence par arrêter d'accepter les nouvelles connexions. Il fait cela en fermant les connexions au réseau qui attendent les connexions : le port TCP/IP, le socket Unix ou le Pipe Windows.

4. Le serveur conclut les activités en cours

Pour chaque thread associé à une connexion réseau, la connexion est interrompue, et le thread est marqué comme mort. Le thread s'arrête lorsqu'il remarque qu'il a été tué. Les threads qui sont inactifs meurent rapidement. Les threads qui traitent des requêtes vérifient périodiquement leur état, et prennent plus de temps pour s'arrêter. Pour plus d'informations sur la fin des threads, voyez Section 13.5.4.3, « Syntaxe de KILL », en particulier à propos des commandes REPAIR TABLE ou OPTIMIZE TABLE sur les tables MyISAM.

Pour les threads qui ont une transaction ouverte, la transaction est annulée. Notez que si un thread modifie une table non transactionnelle, une opération comme un UPDATE multiligne ou un INSERT peuvent laisser la table partiellement modifiée, car l'opération peut se terminer avant sa fin logique.

Si le serveur est un serveur de réplication, les threads associés avec les esclaves sont traités comme n'importe quel autre client. C'est-à-dire, ils sont marqués comme terminés, et se terminent à leur prochaine vérification d'état.

Si le serveur est un esclave de réplication, le thread d'entrée/sortie et le thread SQL sont arrêtés avant que le thread client ne soit tué. Le thread SQL est autorisé à terminer sa commande en cours (pour éviter des problèmes de réplication), puis cesse. Si le thread SQL était au milieu d'une transaction, elle sera annulée.

5. Les moteurs de stockages se ferment

À ce stade, les caches de tables sont envoyés sur le disque, et toutes les tables ouvertes sont fermées.

Chaque moteur de stockage effectue les opérations nécessaires pour fermer les tables qu'il gère. Par exemple, MyISAM envoie les dernières écritures pour la table. InnoDB vide ses buffers sur le disque, écrit le LSN courant dans l'espace de table, et termine ses propres threads.

6. Le serveur se termine

5-4 - Sécurité générale du serveur

Cette section décrit certaines règles générales de sécurité a bien connaître pour rendre votre installation MySQL plus sécuritaire contre des attaques ou des erreurs de manipulations. Pour des informations sur le contrôle d'accès à MySQL, voyez Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

5-4-1 - Guide de sécurité

Tous ceux qui utilisent MySQL avec un serveur connecté à Internet doivent lire cette section, pour éviter les erreurs les plus communes.

En parlant de sécurité, nous devons insister sur la nécessité de protéger tout le serveur, et non pas juste MySQL, contre tous les types d'attaques : surveillance des communications, usurpation, réexécution et dénis de service. Nous ne pouvons pas couvrir tous les aspects de tolérance aux fautes et de disponibilité ici.

MySQL dispose d'un système de sécurité basé sur des listes de contrôle d'accès (Access Control Lists, or ACL) pour toutes les connexions, requêtes et opérations que l'utilisateur peut faire. Il y a aussi le support des connexions SSL entre le client et le serveur MySQL. De nombreux concepts présentés ici ne sont pas spécifiques à MySQL : le même concept s'applique à de nombreuses applications.

Lorsque vous utilisez MySQL, suivez ces règles aussi souvent que possible.

- Ne donnez jamais à personne (sauf aux comptes MySQL root) accès à la table user de la base mysql ! C'est primordial. Le mot de passe chiffré est le vrai mot de passe de MySQL. Toute personne qui connaît le mot de passe de la table user et qui a accès à l'hôte associé peut facilement se connecter sous le nom de cet utilisateur.

- Apprenez à fond le système de droits MySQL. Les commandes GRANT et REVOKE sont utilisées pour contrôler les accès à MySQL. Ne donnez pas plus de droits que nécessaire. Ne donnez jamais de droits à tous les serveurs hôtes.

Liste de vérification :

- essayez la commande en ligne mysql -u root. Si vous pouvez vous connecter, sans donner de mot de passe, vous avez un problème. Toute personne peut se connecter au serveur comme utilisateur root avec le maximum de droits ! Passez en revue les instructions d'installation de MySQL, en insistant sur les passages où le mot de passe root est configuré. Voir Section 2.5.3, « Création des premiers droits MySQL » ;

- utilisez la commande SHOW GRANTS et vérifiez qui a accès à quoi. Puis, utilisez la commande REVOKE pour retirer les droits inutiles ;

- ne stockez jamais de mot de passe en clair dans votre base de données. Si votre serveur est compromis, le pirate aura alors la liste complète des mots de passe, et pourra les utiliser. À la place, utilisez MD5(), SHA1() ou une autre fonction de signature injective ;

- ne choisissez pas vos mots de passe dans un dictionnaire. Il y a des programmes spéciaux pour les rechercher. Même des mots de passe tels que « xfish98 » est très faible. Par contre, « duag98 » est bien mieux : il contient aussi le mot « fish », mais décalé d'une touche sur un clavier QWERTY. Une autre méthode de génération consiste à prendre la première lettre de chaque mot d'une phrase : « Maupa » est issu de « Marie a un petit agneau ». C'est facile à retenir, mais difficile à deviner pour un attaquant ;

- investissez dans un pare-feu. Cela protège de 50 % de tous les types d'attaque et vulnérabilité. Placez MySQL derrière le coupe-feu, ou dans une zone démilitarisée (DMZ).

Liste de vérification :

- essayez de scanner vos portes depuis l'Internet, avec des outils comme nmap. MySQL utilise le port 3306 par défaut. Ce port ne doit pas être accessible à tous les serveurs. Une autre méthode simple pour vérifier si le port MySQL est ouvert ou non, est d'essayer la commande suivante depuis une machine distante, où server_host est le serveur qui héberge MySQL :

shell> telnet server_host 3306

Si vous obtenez une connexion et des caractères binaires, le port est ouvert, et il devrait être fermé par votre routeur ou votre coupe-feu, à moins d'avoir une bonne raison pour le garder ouvert. Si telnet attend, ou que la connexion est refusée, tout va bien : le port est bloqué ;

- ne faites confiance à aucune donnée entrée par les utilisateurs de votre application. Ils peuvent déjouer vos filtres en entrant des séquences spéciales via les formulaires Web, les URL ou tout autre point d'entrée de l'application. Assurez-vous que votre application reste sûre si un utilisateur entre une chaîne telle que « ; DROP DATABASE mysql; ». C'est un exemple extrêmement simple, mais il dévoilera un trou de sécurité important. Il engendrera aussi des pertes de données si un pirate, utilisant cette technique, vous attaque.

Une erreur courante est de ne protéger que les chaînes de caractères. N'oubliez pas de protéger aussi les valeurs numériques. Si une application génère une requête telle que SELECT * FROM table WHERE ID=234 où l'utilisateur fournit le 234, alors ce dernier peut proposer la valeur 234 OR 1=1 pour conduire à la requête SELECT * FROM table WHERE ID=234 OR 1=1. Par conséquent, le serveur va lire toutes les lignes de la table. Cela va diffuser toutes les lignes de votre application, et générer un trafic excessif. Pour vous prémunir contre ce type d'attaque, ajoutez toujours des guillemets autour des constantes numériques : SELECT * FROM table WHERE ID='234'. Si un utilisateur entre des informations supplémentaires, elles seront intégrées dans la chaîne. Dans un contexte numérique, MySQL supprimera automatiquement les caractères incompréhensibles.

Parfois, les gens pensent que si une base de données contient des informations publiques, elle n'a pas besoin d'être défendue. C'est faux. Même si vous pouvez accéder à toutes les lignes de la table, il faut toujours se prémunir contre les dénis de service (par exemple, en utilisant la technique ci-dessus pour générer un trafic excessif). Sinon, votre serveur sera inutilisable.

Liste de vérification :

- essayez d'entrer des caractères ''' et '"' dans tous vos formulaires Web. Si vous obtenez une erreur MySQL, étudiez immédiatement le problème ;

- essayez de modifier une URL dynamique en ajoutant les séquences %22 ('"'), %23 ('#') et %27 (''') ;

- essayez de modifier les types de données des URL dynamiques de numériques en textuels, avec les caractères cités ci-dessus. Votre application doit être sécurisée contre ce type d'attaque ;

- essayez d'entrer des caractères, des espaces et d'autres symboles spéciaux, autres que des nombres, dans un champ numérique. Votre application devrait supprimer tous ces caractères avant de les passer à MySQL, ou générer une erreur. Passer à MySQL des valeurs non vérifiées est très dangereux ;

- vérifiez la taille des chaînes avant de les passer à MySQL ;

- essayez de faire connecter votre application en utilisant un autre nom que celui qui est utilisé pour les tâches d'administration. Ne donnez pas à votre application des droits dont elle n'a pas besoin ;

- de nombreuses interfaces de programmation disposent de moyens pour protéger les valeurs. Correctement utilisés, ils évitent aux utilisateurs de l'application de faire passer des caractères qui auront un effet différent de celui attendu.

- MySQL C API : Utilisez la fonction mysql_real_escape_string().

- MySQL++ : Utilisez les options escape et quote dans le flux de requête.

- PHP : Utilisez la fonction mysql_escape_string(), qui est basée sur la fonction C du même nom. Avant PHP 4.0.3, utilisez addslashes().

- Perl DBI : Utilisez la méthode quote() ou utilisez les variables de requête.

- Java JDBC : Utilisez un objet PreparedStatement ou utilisez les variables de requête.

Les autres interfaces ont des fonctionnalités similaires.

- Ne transmettez pas de données déchiffrées sur Internet. Cette information est accessible à tous ceux qui ont le temps et la capacité d'intercepter et d'utiliser ces mots de passe. Utilisez plutôt un protocole sécurisé comme SSL ou SSH. MySQL supporte les connexions SSL depuis la version 4.0.0. SSH peut être utilisé pour créer un tunnel chiffré et compressé de communication.

- Apprenez à utiliser les programmes tcpdump et strings. Dans la plupart des cas, vous pouvez vérifier si un flux MySQL est chiffré avec la commande suivante :

shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings

(Cette commande fonctionne sous Linux, et devrait être adaptée facilement dans les autres systèmes.) Attention : si vous ne voyez pas de données en clair, cela ne signifie pas toujours que les informations sont chiffrées. Si vous avez besoin de haute sécurité, consultez un expert.

5-4-2 - Protéger MySQL contre les attaques

Lorsque vous vous connectez à MySQL, vous devriez avoir besoin d'un mot de passe. Ce mot de passe n'est pas transmis en texte clair sur le réseau. La gestion des mots de passe durant l'identification des utilisateurs a été améliorée en MySQL 4.1.1 pour être très sécurisée. Si vous utilisez une vieille version de MySQL, ou si vous utilisez toujours les mots de passe de type pré-4.1.1, l'algorithme de chiffrement n'est pas très fort, quelques efforts permettront à un pirate d'obtenir votre mot de passe s'il est capable de surveiller le trafic entre le client et le serveur. (Voyez Section 5.5.9, « Hashage de mots de passe en MySQL 4.1 » pour une discussion des différentes méthodes de gestions des mots de passe). Si la connexion entre le client et le serveur utilise des réseaux non fiables, il est alors recommandé d'utiliser un tunnel SSH.

Toutes les autres informations sont transférées comme du texte clair, et quiconque qui surveille la connexion pourra les lire. Si vous souhaitez relever ce niveau de sécurité, il est recommandé d'utiliser le protocole compressé (avec les versions de MySQL 3.22 et plus récentes), pour compliquer considérablement le problème. Pour rendre la communication encore plus sûre, vous pouvez aussi utiliser ssh. Vous trouverez une version Open Source du client ssh sur le site http://www.openssh.org/, et une version commerciale du client ssh sur le site de http://www.ssh.com/. Avec eux, vous pouvez mettre en place une connexion TCP/IP chiffrée entre le serveur et le client MySQL.

Si vous utilisez MySQL 4.0, vous pouvez aussi utiliser le support OpenSSL interne. Voir Section 5.6.7, « Utilisation des connexions sécurisées ».

Pour rendre le système MySQL encore plus sûr, nous vous recommandons de suivre les suggestions suivantes.

- Utilisez des mots de passe pour tous les utilisateurs MySQL. N'oubliez pas que tout le monde peut se connecter avec un nom d'utilisateur quelconque, simplement avec l'option mysql -u autre_utilisateur nom_de_base, si autre_utilisateur n'a pas de mot de passe. C'est un comportement classique pour les applications client/serveur que le client spécifie son nom d'utilisateur. Il sera plus difficile à un attaquant de pénétrer dans votre serveur si tous les comptes ont un mot de passe.

Vous pouvez modifier les mots de passe de tous les utilisateurs en modifiant le script mysql_install_db avant de l'exécuter, ou vous pouvez modifier seulement le mot de passe du root MySQL comme ceci :

shell> mysql -u root
mysql> UPDATE mysql.user SET Password=PASSWORD('nouveau_mot_de_passe')
-> WHERE User='root';
mysql> FLUSH PRIVILEGES;

- N'exécutez jamais le démon MySQL avec l'utilisateur Unix root. C'est très dangereux, car toute personne ayant le droit de FILE pour créer des fichiers au nom du root (par exemple, ~root/.bashrc). Pour éviter cela, mysqld refusera de s'exécuter au nom de root à moins que soit précisé l'option --user=root.

mysqld peut être exécuté avec un utilisateur ordinaire sans droits particuliers. Vous pouvez aussi créer un utilisateur Unix mysql pour rendre cela encore plus sûr. Si vous exécutez mysqld sous un autre utilisateur Unix, vous n'avez pas à changer le mot de passe root dans la table user, car les noms d'utilisateurs MySQL n'ont rien à voir avec les noms d'utilisateurs Unix. Pour démarrer mysqld sous un autre nom d'utilisateur Unix, ajoutez la ligne user, qui spécifie le nom de l'utilisateur, dans le fichier d'options de [mysqld] /etc/my.cnf ou dans le fichier my.cnf présent dans le dossier de données du serveur. Par exemple :

[mysqld]
user=mysql

Cette ligne va forcer le serveur à démarrer en tant qu'utilisateur mysql, même si vous démarrez le serveur manuellement ou avec les scripts safe_mysqld, ou mysql.server. Pour plus de détails, voyez Section A.3.2, « Comment exécuter MySQL comme un utilisateur normal ».

Exécuter mysql sous un autre compte Unix que root ne signifie pas que vous devez changer le nom de root dans la table user. Les comptes d'utilisateurs de MySQL n'ont rien à voir avec ceux du compte Unix.

- N'autorisez pas l'utilisation de liens symboliques pour les tables. Cette fonctionnalité peut être désactivée avec l'option --skip-symbolic-links. C'est particulièrement important si vous utilisez mysqld comme root, car tout utilisateur a alors le droit d'écrire des données sur le disque, n'importe où sur le système !! Voir Section 7.6.1.2, « Utiliser les liens symboliques avec les tables sous Unix ».

- Vérifiez que l'utilisateur Unix qui exécute mysqld est le seul utilisateur avec les droits de lecture et écriture dans le dossier de base de données.

- Ne donnez pas le droit de PROCESS à tous les utilisateurs. La liste fournie par mysqladmin processlist affiche le texte des requêtes actuellement exécutées, ce qui permet à toute personne pouvant exécuter cette commande de lire des valeurs qui seraient en clair, comme : UPDATE user SET password=PASSWORD('not_secure').

mysqld réserve une connexion supplémentaire pour les utilisateurs qui ont le droit de PROCESS, afin que le root MySQL puisse toujours se connecter et vérifier que tout fonctionne bien, même s'il ne reste plus de connexion libre pour les autres utilisateurs.

Le droit SUPER peut être utilisé pour fermer des connexions clients, changer les variables système et contrôler la réplication.

- Ne donnez pas le droit de FILE à tous les utilisateurs. Tout utilisateur qui possède ce droit peut écrire un fichier n'importe où sur le serveur, avec les droits hérités du démon mysqld ! Pour rendre cela plus sécuritaire, tous les fichiers générés par SELECT ... INTO OUTFILE sont lisibles par tous, mais personne ne peut les modifier.

Le droit de FILE peut aussi être utilisé pour lire n'importe quel fichier accessible en lecture au démon qui fait tourner MySQL. Il devient donc possible, suivant les configurations, d'utiliser la commande LOAD DATA sur le fichier /etc/passwd pour tout mettre en table, et ensuite le relire avec la commande SELECT.

- Si vous ne faites pas confiance à votre DNS, vos pouvez simplement utiliser des adresses IP au lieu des noms d'hôtes. Dans ce cas, soyez très prudents lors de la création de droits qui utilisent des caractères joker.

- Si vous voulez restreindre le nombre de connexions d'un utilisateur, vous pouvez le faire en utilisant la variable max_user_connections de mysqld. La commande GRANT dispose aussi d'options de contrôle des ressources, pour limiter l'utilisation du serveur par un compte utilisateur.

5-4-3 - Options de démarrage qui concernent la sécurité

Les options suivantes de mysqld affectent la sécurité.

- --local-infile[=(0|1)]

Si vous utilisez --local-infile=0 alors vous ne pourrez pas utiliser LOAD DATA LOCAL INFILE. Voir Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL ».

- --safe-show-database

Avec cette option, la commande SHOW DATABASES ne retourne que les bases pour lesquelles l'utilisateur courant a des droits. Depuis la version 4.0.2, cette option est abandonnée, et ne sert plus à rien (elle est activée par défaut), car désormais, il y a le droit de SHOW DATABASES. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

- --safe-user-create

Si cette option est activée, tout utilisateur ne peut créer d'autres utilisateurs avec les droits de GRANT, s'il ne dispose pas des droits d'insertion dans la table mysql.user. Si vous voulez donner un accès à un utilisateur pour qu'il puisse créer des utilisateurs avec les droits dont il dispose, vous pouvez lui donner les droits suivants :

mysql> GRANT INSERT(user) ON mysql.user TO 'user'@'hostname';

Cela va s'assurer que l'utilisateur ne peut pas modifier une colonne directement, mais qu'il peut exécuter la commande GRANT sur d'autres utilisateurs.

- --secure-auth

Interdit l'identification pour les comptes qui ont d'anciens mots de passe (avant la version 4.1). Cette option est valable depuis MySQL 4.1.1.

- --skip-grant-tables

Cette option force le serveur à ne pas utiliser les tables de droits. Cette option donne donc tous les droits à tout le monde sur le serveur ! Vous pouvez forcer un serveur en fonctionnement à reprendre les tables de droits en exécutant la commande mysqladmin flush-privileges ou mysqladmin reload.)

- --skip-name-resolve

Les noms d'hôtes ne sont pas résolus. Toutes les valeurs de la colonne Host dans les tables de droits doivent être des adresses IP, ou bien localhost.

- --skip-networking

Ne pas accepter les connexions TCP/IP venant du réseau. Toutes les connexions au serveur mysqld doivent être faites avec les sockets Unix. Cette option n'existe pas pour les versions antérieures à la 3.23.27, avec les MIT-pthread, car les sockets Unix n'étaient pas supportés par les MIT-pthreads à cette époque.

- --skip-show-database

Ne pas autoriser la commande SHOW DATABASES, à moins que l'utilisateur n'ait les droits de SHOW DATABASES. Depuis la version 4.0.2, vous n'avez plus besoin de cette option, car les accès sont désormais donnés spécifiquement avec le droit SHOW DATABASES.

5-4-4 - Problèmes de sécurité avec LOAD DATA LOCAL

La commande LOAD DATA peut lire des données sur le serveur hôte, ou bien charger un fichier sur le client, avec l'option LOCAL.

Il existe deux problèmes particuliers pour le support de cette commande :

- comme la lecture du fichier est réalisée depuis le serveur, il est possible théoriquement de créer un serveur MySQL modifié qui pourrait lire n'importe quel fichier de la machine cliente, qui serait accessible à l'utilisateur ;

- dans un environnement web, où les clients se connectent depuis un serveur web, un utilisateur peut se servir de la commande LOAD DATA LOCAL pour lire les fichiers qui sont sur le serveur web, et auxquels ce dernier a accès (en supposant qu'un utilisateur peut exécuter n'importe quelle commande sur le serveur).

Pour traiter ces problèmes, nous avons changé la gestion des commandes LOAD DATA LOCAL depuis MySQL version 3.23.49 et MySQL version 4.0.2 (4.0.13 pour Windows) :

- par défaut, tous les clients MySQL et les bibliothèques des distributions binaires sont compilées avec l'option --enable-local-infile, pour être compatibles avec MySQL 3.23.48 et plus ancien ;

- si vous ne configurez pas MySQL avec l'option --enable-local-infile, alors LOAD DATA LOCAL sera désactivé pour tous les clients, à moins que l'option mysql_options(... MYSQL_OPT_LOCAL_INFILE, 0) soit activée dans le client. Voir Section 24.2.3.43, « mysql_options() » ;

- pour le client en ligne de commande mysql, LOAD DATA LOCAL peut être activé en spécifiant l'option --local-infile[=1], ou désactivé avec --local-infile=0 ;

- vous pouvez désactiver toutes les commandes LOAD DATA LOCAL du serveur MySQL en démarrant mysqld avec --local-infile=0. Similairement, pour mysqlimport, les options --local et -L active le chargement distant de fichiers. Dans ce cas, il faut que le serveur accepte aussi cette configuration pour que l'opération fonctionne ;

- au cas où LOAD DATA LOCAL INFILE est désactivé sur le serveur ou le client, vous obtiendrez le message d'erreur (1148) :

The used command is not allowed with this MySQL version

5-5 - Règles de sécurité et droits d'accès au serveur MySQL

MySQL est pourvu d'un système avancé, mais non standard de droits. Cette section décrit son fonctionnement.

5-5-1 - Rôle du système de privilèges

La fonction première du système de privilèges de MySQL est d'authentifier les utilisateurs se connectant à partir d'un hôte donné, et de leur associer des privilèges sur une base de données comme SELECT, INSERT, UPDATE et DELETE.

Les fonctionnalités additionnelles permettent d'avoir un utilisateur anonyme et de contrôler les privilèges pour les fonctions spécifiques à MySQL comme LOAD DATA INFILE et les opérations administratives.

5-5-2 - Comment fonctionne le système de droits

Le système de droits de MySQL s'assure que les utilisateurs font exactement ce qu'ils sont supposés pouvoir faire dans la base. Lorsque vous vous connectez au serveur, votre identité est déterminée par l'hôte d'où vous vous connectez et le nom d'utilisateur que vous spécifiez. Le système donne les droits en fonction de votre identité et de ce que vous voulez faire.

MySQL considère votre nom d'hôte et d'utilisateur pour vous identifier, car il n'y pas que peu de raisons de supposer que le même nom d'utilisateur appartient à la même personne, quel que soit son point de connexion sur Internet. Par exemple, l'utilisateur joe qui se connecte depuis office.com n'est pas forcément la même personne que joe qui se connecte depuis elsewhere.com. MySQL gère cela en vous aidant à distinguer les différents utilisateurs et hôtes qui ont le même nom : vous pourriez donner des droits à joe lorsqu'il utilise sa connexion depuis office.com, et un autre jeu de droits lorsqu'il se connecte depuis elsewhere.com.

Le contrôle d'accès de MySQL se fait en deux étapes :

- Étape 1 : le serveur vérifie que vous êtes autorisé à vous connecter ;

- Étape 2 : en supposant que vous pouvez vous connecter, le serveur vérifie chaque requête que vous soumettez, pour vérifier si vous avez les droits suffisants pour l'exécuter. Par exemple, si vous sélectionnez des droits dans une table, ou effacez une table, le serveur s'assure que vous avez les droits de SELECT pour cette table, ou les droits de DROP, respectivement.

Si vos droits ont changé (par vous-même ou bien par un administrateur), durant votre connexion, ces changements ne prendront peut-être effet qu'à la prochaine requête. Voyez la section Section 5.5.7, « Quand les modifications de privilèges prennent-elles effet ? » pour plus détails.

Le serveur stocker les droits dans des tables de droits, situées dans la base mysql. Le serveur lit le contenu de ces tables en mémoire lorsqu'il démarre, et les relit dans différentes circonstances, détaillées dans Section 5.5.7, « Quand les modifications de privilèges prennent-elles effet ? ». Le contrôle d'accès se fait par rapport aux tables en mémoire.

Normalement, vous manipulez le contenu des tables indirectement, via les commandes GRANT et REVOKE pour configurer des comptes et des droits. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ». La discussion de cette section décrit la structure des tables de droits, et comment elle interagit avec les clients.

Le serveur utilise les tables user, db et host dans la base mysql durant les deux étapes. Les champs de cette table sont les suivants :

Table name

utilisateur

base

hôte

Scope fields

Host

Host

Host

User

Db

Db

Password

User

Privilege fields

Select_priv

Select_priv

Select_priv

Insert_priv

Insert_priv

Insert_priv

Update_priv

Update_priv

Update_priv

Delete_priv

Delete_priv

Delete_priv

Index_priv

Index_priv

Index_priv

Alter_priv

Alter_priv

Alter_priv

Create_priv

Create_priv

Create_priv

Drop_priv

Drop_priv

Drop_priv

Grant_priv

Grant_priv

Grant_priv

References_priv

References_priv

References_priv

Reload_priv

Shutdown_priv

Process_priv

File_priv

Show_db_priv

Super_priv

Create_tmp_table_priv

Create_tmp_table_priv

Create_tmp_table_priv

Lock_tables_priv

Lock_tables_priv

Lock_tables_priv

Execute_priv

Repl_slave_priv

Repl_client_priv

ssl_type

ssl_cypher

x509_issuer

x509_cubject

max_questions

max_updates

max_connections

Lors de la seconde étape du contrôle d'accès (vérification de la requête), le serveur peut, suivant la requête, consulter aussi les tables tables_priv et columns_priv. Les champs de ces tables sont :

Nom de la table

tables_priv

columns_priv

Champ

Host

Host

Db

Db

User

User

Table_name

Table_name

Column_name

Droit

Table_priv

Column_priv

Column_priv

Autre champ

Timestamp

Timestamp

Grantor

Chaque table de droit contient des champs d'identification et des champs de droits.

- Les champs d'identification déterminent quels utilisateurs correspondent à cette ligne dans la table. Par exemple, une ligne dans la table user avec les valeurs dans les colonnes Host et User de 'thomas.loc.gov' et 'bob' servira à identifier les connexions qui sont faites par l'utilisateur bob depuis l'hôte thomas.loc.gov. De même, une ligne dans la table db avec les valeurs des colonnes Host, User et Db de 'thomas.loc.gov', 'bob' et 'reports' sera utilisée lorsque l'utilisateur bob se connecte depuis l'hôte thomas.loc.gov pour accéder à la base reports. Les tables tables_priv et columns_priv contiennent en plus des champs indiquant les tables et combinaisons tables et colonnes auxquelles les lignes s'appliquent.

- Les champs de droits indiquent si le droit est donné, c'est-à-dire si l'opération indiquée peut être exécutée. Le serveur combine les informations dans différentes tables pour former une description complète de l'utilisateur. Les règles utilisées sont décrites dans Section 5.5.6, « Contrôle d'accès, étape 2 : Vérification de la requête ».

Les champs d'identification sont des chaînes, déclarées comme suit. La valeur par défaut de chacun des champs est la chaîne vide.

Nom de la colonne

Type

Host

CHAR(60)

User

CHAR(16)

Password

CHAR(16)

Db

CHAR(64)

Table_name

CHAR(60)

Column_name

CHAR(60)

Avant MySQL 3.23, la colonne Db valait CHAR(32) dans certaines tables, et CHAR(60) dans d'autres.

Pour vérifier les accès, la comparaison sur les valeurs de la colonne Host sont sensibles à la casse. User, Password, Db et Table_name sont insensibles. Les valeurs de Column_name sont insensibles depuis MySQL 3.22.12.

Dans les tables user, db et host, tous les champs de droits sont déclarés avec le type ENUM('N','Y') : ils peuvent prendre tous les valeurs de 'N' (non) ou 'Y' (oui, YES), et la valeur par défaut est 'N'.

Dans les tables tables_priv et columns_priv, les champs de droits sont déclarés comme des champs de type SET :

Nom de la table

Nom du champ

Valeurs possibles

tables_priv

Table_priv

'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'

tables_priv

Column_priv

'Select', 'Insert', 'Update', 'References'

columns_priv

Column_priv

'Select', 'Insert', 'Update', 'References'

En bref, le serveur utilise les tables de droits comme ceci :

- la table user détermine si le serveur accepte ou rejette la connexion. Pour les connexions acceptées, tous les privilèges donnés dans la table user indiquent des privilèges globaux. Ces droits s'appliquent à toutes les bases du serveur ;

- les champs d'identification de la table db déterminent quels utilisateurs peuvent accéder à quelles bases, depuis quel hôte. Les champs de droits indiquent alors les opérations permises. Les droits s'appliquent alors à toutes les bases sur le serveur ;

- la table host est utilisée comme extension de la table db lorsque vous voulez qu'une ligne de la table db s'applique à plusieurs hôtes. Par exemple, si vous voulez qu'un utilisateur soit capable d'utiliser une base depuis plusieurs hôtes dans votre réseau, laissez la colonne Host vide dans la table db, Ce mécanisme est décrit en détail dans Section 5.5.6, « Contrôle d'accès, étape 2 : Vérification de la requête » ;

- les tables tables_priv et columns_priv sont similaires à la table db, mais sont plus atomiques : elles s'appliquent au niveau des tables et des colonnes, plutôt qu'au niveau des bases.

Notez que les droits d'administration tels que (RELOAD, SHUTDOWN, etc.) ne sont spécifiés que dans la table user. En effet, ces opérations sont des opérations au niveau serveur, et ne sont pas liées à une base de données, ce qui fait qu'il n'y a pas de raison de les lier avec les autres tables. En fait user doit être consulté pour déterminer les autorisations d'administration.

Le droit de FILE est spécifié par la table user. Ce n'est pas un droit d'administration, mais votre capacité à lire ou écrire des fichiers sur le serveur hôte et dépendant de la base à laquelle vous accédez.

Le serveur mysqld lit le contenu des tables de droits une fois, au démarrage. Lorsqu'il y a des modifications dans les tables, elles prennent effet tel qu'indiqué dans Section 5.5.7, « Quand les modifications de privilèges prennent-elles effet ? ».

Lorsque vous modifiez le contenu des tables de droits, c'est une bonne idée que de s'assurer que vous avez bien configuré les droits qui vous intéressent. Un moyen de vérifier les droits pour un compte est d'utiliser la commande SHOW GRANTS. Par exemple, pour déterminer les droits qui sont donnés à un compte avec les valeurs Host et User de pc84.example.com et bob, utilisez cette commande :

mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com';

Un outil de diagnostic pratique est le script mysqlaccess, que Yves Carlier a fourni à la distribution MySQL. Appelez mysqlaccess avec l'option the --help pour comprendre comment il fonctionne. Notez que mysqlaccess ne vérifie les accès que pour les tables user, db et host. Il n'utilise pas les tables de droits de niveau table ou colonne.

Pour plus d'aide au diagnostic pour les problèmes de droits, voyez la section Section 5.5.8, « Causes des erreurs Access denied ». Pour des conseils généraux sur la sécurité, voyez la section Section 5.4, « Sécurité générale du serveur ».

5-5-3 - Droits fournis par MySQL

Les droits des utilisateurs sont stockés dans les tables user, db, host, tables_priv et columns_priv de la base mysql (c'est-à-dire, la base nommée mysql). Le serveur MySQL lit ces tables au démarrage, et dans les circonstances indiquées dans la section Section 5.5.7, « Quand les modifications de privilèges prennent-elles effet ? ».

Les noms utilisés dans ce manuel font référence aux droits fournis par MySQL version 4.0.2, tels que présentés dans la table ci-dessous, avec le nom de la colonne associée au droit, dans la table de droits, et dans le contexte d'application. Plus d'informations sur la signification de chaque droit sont disponibles à Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

Droit

Colonne

Contexte

ALTER

Alter_priv

tables

DELETE

Delete_priv

tables

INDEX

Index_priv

tables

INSERT

Insert_priv

tables

SELECT

Select_priv

tables

UPDATE

Update_priv

tables

CREATE

Create_priv

bases de données, tables ou index

DROP

Drop_priv

bases de données ou tables

GRANT

Grant_priv

bases de données ou tables

REFERENCES

References_priv

bases de données ou tables

CREATE TEMPORARY TABLES

Create_tmp_table_priv

administration du serveur

EXECUTE

Execute_priv

administration du serveur

FILE

File_priv

accès aux fichiers du serveur

LOCK TABLES

Lock_tables_priv

administration du serveur

PROCESS

Process_priv

administration du serveur

RELOAD

Reload_priv

administration du serveur

REPLICATION CLIENT

Repl_client_priv

administration du serveur

REPLICATION SLAVE

Repl_slave_priv

administration du serveur

SHOW DATABASES

Show_db_priv

administration du serveur

SHUTDOWN

Shutdown_priv

administration du serveur

SUPER

Super_priv

administration du serveur

Les droits de SELECT, INSERT, UPDATE et DELETE vous permettent de faire des opérations sur les lignes qui existent, dans une table existante d'une base.

La commande SELECT requiert le droit de SELECT uniquement si des lignes sont lues dans une table. Vous pouvez exécuter une commande SELECT même sans aucun droit d'accès à une base de données dans le serveur. Par exemple, vous pourriez utiliser le client mysql comme une simple calculatrice :

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

Le droit de INDEX vous donne le droit de créer et détruire des index de table.

Le droit de ALTER vous donne le droit de modifier une table avec la commande ALTER TABLE.

Les droits de CREATE et DROP vous permettent de créer de nouvelles tables et bases de données, et de les supprimer.

Notez que si vous donnez le droit de DROP pour la base de données mysql à un utilisateur, cet utilisateur pourra détruire la base qui contient les droits d'accès du serveur !

Le droit de GRANT vous permet de donner les droits que vous possédez à d'autres utilisateurs.

Le droit de FILE vous donne la possibilité de lire et écrire des fichiers sur le serveur avec les commandes LOAD DATA INFILE et SELECT ... INTO OUTFILE. Tout utilisateur qui possède ce droit peut donc lire ou écrire dans n'importe quel fichier à l'intérieur duquel le serveur MySQL peut lire ou écrire.

Les autres droits sont utilisés pour les opérations administratives qui sont exécutées par l'utilitaire mysqladmin. La table ci-dessous montre quelle commande est associée à mysqladmin avec un de ces droits :

Droit

Commande autorisée

RELOAD

reload, refresh, flush-privileges, flush-hosts, flush-logs et flush-tables

SHUTDOWN

shutdown

PROCESS

processlist

SUPER

kill

La commande reload indique au serveur de relire les tables de droits. La commande refresh vide les tables de la mémoire, écrit les données et ferme le fichier de logs. flush-privileges est un synonyme de reload. Les autres commandes flush-* effectuent des fonctions similaires à la commande refresh mais sont plus limitées dans leur application, et sont préférables dans certains contextes. Par exemple, si vous souhaitez simplement vider les tampons dans le fichier de logs, utilisez flush-logs, qui est un meilleur choix que refresh.

La commande shutdown éteint le serveur.

La commande processlist affiche les informations sur les threads qui s'exécutent sur le serveur. La commande kill termine un des threads du serveur. Vous pouvez toujours afficher et terminer vos propres threads, mais vous aurez besoin des droits de PROCESS pour afficher les threads, et le droit de SUPER pour terminer ceux qui ont été démarrés par d'autres utilisateurs. Voir Section 13.5.4.3, « Syntaxe de KILL ».

C'est une bonne idée en général, de ne donner les droits de Grant qu'aux utilisateurs qui en ont besoin, et vous devriez être particulièrement vigilant pour donner certains droits.

- Le droit de GRANT permet aux utilisateurs de donner leurs droits à d'autres utilisateurs. Deux utilisateurs avec des droits différents et celui de GRANT pourront combiner leurs droits respectifs pour gagner un autre niveau d'utilisation du serveur.

- Le droit de ALTER peut être utilisé pour tromper le système en renommant les tables.

- Le droit de FILE peut servir à lire des fichiers accessibles à tous sur le serveur, et les placer dans une base de données. Le contenu pourra alors être lu et manipulé avec SELECT. Cela inclut le contenu de toutes les bases actuellement hébergées sur le serveur !

- Le droit de SHUTDOWN peut conduire au déni de service, en arrêtant le serveur.

- Le droit de PROCESS permet de voir en texte clair les commandes qui s'exécutent actuellement, et notamment les changements de mot de passe.

- Le droit de SUPER peut être utilisé pour terminer les connexions ou modifier le mode opératoire du serveur.

- Les droits sur la base de données mysql peuvent être utilisés pour changer des mots de passe ou des droits dans la table des droits. (Les mots de passe sont stockés chiffrés, ce qui évite que les intrus ne les lisent). S'ils accèdent à un mot de passe dans la table mysql.user, ils pourront l'utiliser pour se connecter au serveur avec cet utilisateur (avec des droits suffisants, le même utilisateur pourra alors remplacer un mot de passe par un autre).

Il y a des choses qui ne sont pas possibles avec le système de droits de MySQL :

- vous ne pouvez pas explicitement interdire l'accès à un utilisateur spécifique. C'est-à-dire, vous ne pouvez pas explicitement décrire un utilisateur et lui refuser la connexion ;

- vous ne pouvez pas spécifier qu'un utilisateur a les droits de créer et de supprimer des tables dans une base, mais qu'il n'a pas les droits pour créer et supprimer cette base.

5-5-4 - Se connecter au serveur MySQL

Les clients MySQL requièrent généralement que vous spécifiiez les paramètres de connexion pour vous connecter au serveur MySQL :

- l'hôte que vous voulez utiliser ;

- votre nom d'utilisateur ;

- votre mot de passe.

Par exemple, le client mysql peut être démarré comme ceci :

shell> mysql [-h nom_d_hote] [-u nom_d_utilisateur] [-pvotre_mot_de_passe]

Les formes alternatives des options -h, -u et -p sont --host=host_name, --user=user_name et --password=your_pass. Notez qu'il n'y a aucun espace entre l'option -p ou --password= et le mot de passe qui le suit.

Si vous utilisez les options -p et --password mais que vous ne spécifiez pas de mot de passe, le client vous le demandera interactivement. Le mot de passe ne sera alors pas affiché. C'est la méthode la plus sécuritaire. Sinon, n'importe quel utilisateur du système pourra voir le mot de passe de la ligne de commande en exécutant une commande telle que ps auxww. Voir Section 5.6.6, « Garder vos mots de passe en lieu sûr ».

mysql utilise des valeurs par défaut pour chacun des paramètres qui manquent en ligne de commande :

- le nom d'hôte par défaut est localhost ;

- le nom d'utilisateur par défaut est votre nom d'utilisateur de système Unix ;

- aucun mot de passe n'est transmis si -p manque.

Par exemple, pour un utilisateur Unix joe, les commandes suivantes sont équivalentes :

shell> mysql -h localhost -u joe
shell> mysql -h localhost
shell> mysql -u joe
shell> mysql

Les autres clients MySQL se comportent de manière similaire.

Sous Unix, vous pouvez spécifier différentes valeurs par défaut qui seront utilisées lorsque vous établirez la connexion, de manière à ce que vous n'ayez pas à entrer ces informations en ligne de commande lorsque vous invoquez un programme client. Cela peut se faire de plusieurs façons.

- Vous pouvez spécifier les informations de connexion dans la section [client] du fichier de configuration .my.cnf de votre dossier personnel. La section qui vous intéresse ressemble à ceci :

[client]
host=nom_d_hote
user=nom_d'utilisateur
password=votre_mot_de_passe

Les fichiers d'options sont présentés dans la section Section 4.3.2, « Fichier d'options my.cnf ».

- Vous pouvez spécifier les paramètres de connexion avec les variables d'environnement. L'hôte peut être spécifié à mysql avec la variable MYSQL_HOST. L'utilisateur MySQL peut être spécifié avec la variable USER (uniquement pour Windows). Le mot de passe peut être spécifié avec MYSQL_PWD : mais ceci est peu sécuritaire voyez Section 5.6.6, « Garder vos mots de passe en lieu sûr ». Voyez aussi la prochaine section Annexe E, Variables d'environnement.

5-5-5 - Contrôle d'accès, étape 1 : vérification de la connexion

Lorsque vous tentez de vous connecter au serveur MySQL, le serveur accepte ou rejette la connexion en fonction de votre identité et du mot de passe que vous fournissez. Si le mot de passe ne correspond pas à celui qui est en base, le serveur vous interdit complètement l'accès. Sinon, le serveur accepte votre connexion et passe à l'étape 2, et la gestion de commandes.

Votre identité est basée sur trois informations :

- l'hôte depuis lequel vous vous connectez ;

- votre nom d'utilisateur MySQL.

La vérification d'identité est réalisée avec les trois colonnes de la table user (Host, User et Password). Le serveur accepte la connexion uniquement si une entrée dans la table user correspond à votre hôte, et que vous fournissez le mot de passe qui correspond.

Les valeurs de la table user peuvent être paramétrées comme ceci :

- une valeur de la colonne Host peut être un nom d'hôte, une adresse IP numérique, ou encore 'localhost', qui représente l'hôte local ;

- vous pouvez utiliser les caractères joker '%' et '_' dans le champ Host. Ces caractères ont la même valeur que pour les opérations de recherches avec l'opérateur LIKE. Par exemple, une valeur Host de '%' remplace n'importe quel nom d'hôte, alors que la valeur '%.mysql.com' représente tous les hôtes du domaine mysql.com ;

- depuis MySQL version 3.23, les valeurs de Host spécifiées sous la forme d'IP numériques peuvent être complétées avec le masque de réseau qui indique combien de bits d'adresse sont utilisés. Par exemple :

mysql> GRANT ALL PRIVILEGES ON db.*
-> TO david@'192.58.197.0/255.255.255.0';

Cela permet à toute personne se connectant depuis une adresse IP qui satisfait la contrainte suivante :

user_ip & netmask = host_ip

C'est-à-dire, pour la commande GRANT ci-dessus :

client_ip & 255.255.255.0 = 192.58.197.0

Les adresses IP qui satisfont cette condition et qui peuvent se connecter au serveur MySQL sont dans l'intervalle 192.58.197.0 à 192.58.197.255 ;

- une valeur vide pour la colonne Host indique que les droits doivent être gérés avec les entrées de la table host qui correspond à l'hôte se connectant. Vous trouverez plus d'informations à ce sujet dans le chapitre Section 5.5.6, « Contrôle d'accès, étape 2 : Vérification de la requête ».

Une valeur vide dans la colonne Host des autres tables de droits revient à '%'.

Comme vous pouvez utiliser des jokers dans les valeurs IP de Host (par exemple, '144.155.166.%' pour tous les hôtes d'un sous-réseau), il est possible d'exploiter cette particularité en appelant un hôte 144.155.166.ailleurs.com. Pour contrer ce type d'attaque, MySQL bloque les noms de domaines qui commencent par des chiffres et des points. Par conséquent, si vous avez un hôte nommé 1.2.foo.com, il ne sera jamais accepté par la colonne Host des tables de droits. Un caractère joker d'adresse IP peut remplacer uniquement des nombres d'IP, et pas un nom d'hôte.

Dans la colonne User, les caractères joker ne sont pas autorisés, mais vous pouvez laisser cette valeur vide, qui acceptera tous les noms. Si la table user contient une connexion avec un nom d'utilisateur vide, l'utilisateur est considéré comme anonyme. Cela signifie que le nom d'utilisateur vide est utilisé pour les prochaines vérifications d'accès pour la durée de la connexion.

Le champ Password peut être vide. Cela ne signifie pas que n'importe quel mot de passe est valable, mais que l'utilisateur peut se connecter sans fournir de mot de passe.

Les valeurs non vides du champ Password représentent des valeurs du mot de passe chiffrées. MySQL ne stocke pas les mots de passe en clair, à la vue de tous. Au contraire, le mot de passe fourni par l'utilisateur qui tente de se connecter est chiffré (avec la fonction PASSWORD()). Le mot de passe ainsi chiffré est alors utilisé entre le client et le serveur pour vérifier s'il est valable. Cela évite que des mots de passe en clair circulent entre le client et le serveur, sur la connexion. Notez que du point de vue de MySQL, le mot de passe chiffré est le vrai mot de passe, ce qui fait que vous ne devez en aucun cas le donner à un tiers. En particulier, ne donnez pas accès en lecture aux utilisateurs normaux aux tables d'administration dans la base mysql ! À partir de sa version 4.1, MySQL utilise un mécanisme différent pour les logins, mots de passe qui est sécurisé même si les paquets TCP/IP sont sniffés et/ou que la base de données mysql est capturée.

Depuis la version 4.1, MySQL emploie une identification forte qui protège mieux les mots de passe durant le processus de connexion. Cette méthode est sécuritaire, même si les paquets TCP/IP sont surveillés pour que la base de données mysql soit capturée. Le chiffrement est présenté dans la section Section 5.5.9, « Hashage de mots de passe en MySQL 4.1 ».

Les exemples ci-dessous illustrent comment différentes variantes de Host et User dans la table user s'appliquent aux connexions entrantes :

Host value

User value

Connexions autorisées

'thomas.loc.gov'

'fred'

fred, se connectant depuis thomas.loc.gov

'thomas.loc.gov'

''

N'importe quel utilisateur, se connectant depuis thomas.loc.gov

'%'

'fred'

fred, se connectant depuis n'importe quel hôte

'%'

''

N'importe quel utilisateur, se connectant depuis n'importe quel hôte

'%.loc.gov'

'fred'

fred, se connectant depuis n'importe quel hôte dans le domaine loc.gov

'x.y.%'

'fred'

fred, se connectant depuis x.y.net, x.y.com,x.y.edu, etc. (Ceci n'est probablement pas très utilisé)

'144.155.166.177'

'fred'

fred, se connectant depuis l'hôte d'IP 144.155.166.177

'144.155.166.%'

'fred'

fred, se connectant depuis un hôte d'IP dans la classe C 144.155.166

'144.155.166.0/255.255.255.0'

'fred'

Identique à l'exemple précédent

Comme vous pouvez utiliser des caractères joker dans les adresses IP de la colonne Host (par exemple, '144.155.166.%' pour identifier tout un sous-réseau), il est possible d'exploiter cette fonctionnalité en nommant un hôte 144.155.166.kekpart.com. Pour contrer de telles tentatives, MySQL interdit les caractères joker avec les noms d'hôtes qui commencent par des chiffres ou des points. Par exemple, si vous avez un nom d'hôte tel que 1.2.foo.com, il ne sera jamais trouvé dans la colonne Host des tables de droits. Seule une adresse IP numérique peut être comparée avec un masque à caractère joker.

Une connexion entrante peut être identifiée par plusieurs entrées dans la table user. MySQL résout ce problème comme ceci :

- lorsque le serveur lit la table user en mémoire, il trie les lignes ;

- lorsqu'un client tente de se connecter, le serveur lit les lignes dans l'ordre ;

- le serveur utilise la première ligne qui correspond au nom du client et à son nom d'utilisateur.

Supposons que votre table user ressemble à ceci :

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

Lorsque le serveur lit cette table, il ordonne les lignes depuis les valeurs les plus spécialisées de la colonne Host jusqu'aux plus générales ('%' dans la colonne Host signifie « tous les hôtes » et elle est la moins spécifique). Les entrées identiques dans la colonne Host sont ordonnées en fonction de la spécificité des valeurs de la colonne User (une entrée vide dans la colonne User signifie « n'importe quel utilisateur » et est spécifique). Le résultat de ce tri donne quelque chose comme ceci :

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

Lorsqu'une connexion est en cours de mise en place, le serveur regarde dans cette liste, et utilisera la première entrée trouvée. Pour une connexion depuis l'hôte localhost avec le nom d'utilisateur jeffrey, les entrées 'localhost' dans la colonne Host sont trouvées en premier. Parmi celles-là, la ligne avec un utilisateur vide satisfait les deux contraintes sur le nom et l'hôte. '%'/'jeffrey' pourrait avoir fonctionné, mais comme ce n'est pas le premier rencontré, il n'est pas utilisé.

Voici un autre exemple. Supposons que la table user ressemble à ceci :

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| thomas.loc.gov |          | ...
+----------------+----------+-

La table triée ressemble à ceci :

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| thomas.loc.gov |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

Une connexion depuis l'hôte thomas.loc.gov avec jeffrey satisfait les conditions de la première ligne, tandis qu'une connexion depuis whitehouse.gov avec jeffrey satisfait la seconde ligne.

Une erreur commune est de penser que pour un utilisateur donné, toutes les entrées qui utilisent explicitement ce nom seront utilisées en premier lorsque la connexion est en cours d'établissement. Ceci est tout simplement faux. L'exemple précédent illustre cette situation, car la connexion depuis l'hôte thomas.loc.gov avec jeffrey est la première ligne qui est trouvée, alors que la ligne contenant 'jeffrey' dans la colonne User est ignorée, car il n'y a pas de nom d'utilisateur.

Si vous arrivez à vous connecter au serveur, mais que les droits ne sont pas ce que vous attendez, vous vous êtes probablement identifié avec un autre compte. Pour savoir quel compte le serveur utilise lors de votre identification, utilisez la fonction CURRENT_USER(). Elle retourne la valeur au format user_name@host_name qui indique les valeurs des colonnes User et Host de la table user qui vous est affectée. Supposons que jeffrey se connecte et utilise la requête suivante :

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost     |
+----------------+

Le résultat affiché ci-dessus indique que la ligne de la table user est l'utilisateur User vide. En d'autres termes, le serveur traite jeffrey comme un utilisateur anonyme.

La fonction CURRENT_USER() est disponible depuis MySQL 4.0.6. Voir Section 12.8.3, « Fonctions d'informations ». Une autre piste à explorer : imprimez le contenu de la table user et triez-la manuellement pour voir quelle est la première ligne qui est utilisée.

5-5-6 - Contrôle d'accès, étape 2 : vérification de la requête

Une fois que vous avez établi la connexion, le serveur passe à l'étape 2. Pour chaque requête qui est fournie avec la connexion, le serveur vérifie si vous avez les droits suffisants pour exécuter une commande, en fonction du type de commande. C'est à ce moment que les colonnes de droits des tables d'administration entrent en scène. Ces droits peuvent provenir de la table user, db, host, tables_priv ou columns_priv. Les tables d'administration sont manipulées avec les commandes GRANT et REVOKE. (Vous pouvez aussi vous reporter à la section Section 5.5.2, « Comment fonctionne le système de droits » qui liste les champs présents dans chaque table d'administration).

La table d'administration user donne les droits aux utilisateurs au niveau global, c'est-à-dire que ces droits s'appliquent quelle que soit la base de données courante. Par exemple, si la table user vous donne le droit d'effacement, DELETE, vous pouvez effacer des données dans n'importe quelle base de ce serveur. En d'autres termes, les droits stockés dans la table user sont des droits de super-utilisateur. Il est recommandé de ne donner des droits via la table user uniquement aux super-utilisateurs, ou aux administrateurs de bases. Pour les autres utilisateurs, il vaut mieux laisser les droits dans la table user à 'N' et donner des droits au niveau des bases uniquement, avec les tables db et host.

Les tables db et host donnent des droits au niveau des bases. Les droits peuvent être spécifiés dans ces tables comme ceci :

- les caractères '%' et '_' peuvent être utilisés dans la colonne Host et Db des deux tables. Si vous souhaitez utiliser le caractère '_' comme nom de base, utiliser la séquence '\_' dans la commande GRANT ;

- la valeur '%' dans la colonne Host de la table db signifie « tous les hôtes ». Une valeur vide dans la colonne Host de la table db signifie « consulte la table host pour plus de détails » ;

- la valeur '%' ou vide dans la colonne Host de la table host signifie « tous les hôtes » ;

- la valeur '%' ou vide dans la colonne Db des deux tables signifie « toutes les bases de données » ;

- un utilisateur vide dans la colonne User de l'une des deux tables identifie l'utilisateur anonyme.

Les tables db et host sont lues et triées par le serveur au démarrage (en même temps que la table user. La table db est triée suivant les valeurs des colonnes Host, Db et User, et la table host est triée en fonction des valeurs des colonnes Host et Db. Comme pour la table user, le tri place les entrées les plus spécifiques au début, et les plus générales à la fin. Lorsque le serveur recherche une ligne, il utilise la première qu'il trouve.

Les tables tables_priv et columns_priv spécifient les droits au niveau des tables et des colonnes. Les valeurs des droits dans ces tables peuvent être spécifiées avec les caractères spéciaux suivants :

- les caractères '%' et '_' peuvent être utilisés dans la colonne Host des deux tables ;

- la valeur '%' dans la colonne Host des deux tables signifie « tous les hôtes » ;

- les colonnes Db, Table_name et Column_name ne peuvent pas contenir de valeur vide ou de caractères joker, dans les deux tables.

Les tables tables_priv et columns_priv sont triées en fonction des colonnes Host, Db et User. Ce tri est similaire à celui du tri de la table db, même si le tri est bien plus simple, car seul le champ Host peut contenir des caractères joker.

Le processus de vérification est décrit ci-dessous. Si vous êtes familier avec le code source de contrôle d'accès, vous noterez que la description diffère légèrement de l'algorithme utilisé. La description est équivalente à ce que fait en réalité le code. La différence permet une meilleure approche pédagogique.

Pour les requêtes d'administration comme SHUTDOWN, RELOAD, etc., le serveur vérifie uniquement l'entrée dans la table user, car c'est la seule table qui spécifie des droits d'administration. Le droit est donné si la ligne utilisée dans la connexion courante dans la table user donne le droit, et sinon, ce droit est interdit. Par exemple, si vous souhaitez exécuter la commande mysqladmin shutdown, mais que votre ligne dans la table user ne vous en donne pas le droit (SHUTDOWN), vous n'aurez pas le droit sans même vérifier les tables db ou host : ces tables ne contiennent pas de colonne Shutdown_priv, ce qui évite qu'on en ait besoin.

Pour les requêtes exploitant une base de données, comme INSERT, UPDATE, etc., le serveur vérifie d'abord les droits globaux de l'utilisateur (droits de super-utilisateur), en regardant dans la table user. Si la ligne utilisée dans cette table donne droit à cette opération, le droit est donné. Si les droits globaux dans user sont insuffisants, le serveur déterminera les droits spécifiques à la base avec les tables db et host.

1. Le serveur recherche dans la table db des informations en se basant sur les colonnes Host, Db et User. Les champs Host et User sont comparés avec les valeurs de l'hôte et de l'utilisateur qui sont connectés. Le champ Db est comparé avec le nom de la base de données que l'utilisateur souhaite utiliser. S'il n'existe pas de ligne qui corresponde à Host et User, l'accès est interdit.

2. S'il existe une ligne dans la table db et que la valeur de la colonne Host n'est pas vide, cette ligne définit les droits de l'utilisateur.

3. Si dans la ligne de la table db, la colonne Host est vide, cela signifie que la table host spécifie quels hôtes doivent être autorisés dans la base. Dans ce cas, une autre recherche est faite dans la table host pour trouver une ligne avec les colonnes Host et Db. Si aucune ligne de la table host n'est trouvée, l'accès est interdit. S'il y a une ligne, les droits de l'utilisateur sont calculés comme l'intersection (NON PAS l'union !) des droits dans les tables db et host, c'est-à-dire que les droits doivent être marqués 'Y' dans les deux tables (de cette façon, vous pouvez donner des droits généraux dans la table db puis les restreindre sélectivement en fonction des hôtes, en utilisant la table host.

Après avoir déterminé les droits spécifiques à l'utilisateur pour une base grâce aux tables db et host, le serveur les ajoute aux droits globaux, donnés par la table user. Si le résultat autorise la commande demandée, l'accès est donné. Sinon, le serveur vérifie les droits au niveau de la table et de la colonne dans les tables tables_priv et columns_priv, et les ajoute aux droits déjà acquis. Les droits sont alors donnés ou révoqués en fonction de ces résultats.

Exprimée en termes booléens, la description précédente du calcul des droits peut être résumée comme ceci :

droits globaux
OR (droits de base AND droits d'hôte)
OR droits de table
OR droits de colonne

Il n'est peut-être pas évident pourquoi, si les droits globaux issus de la table user sont initialement insuffisants pour l'opération demandée, le serveur ajoute ces droits à ceux de base, table ou colonne ? La raison est que la requête peut demander l'application de plusieurs droits. Par exemple, si vous exécutez une commande INSERT ... SELECT, vous aurez besoin des droits de INSERT et de SELECT. Vos droits peuvent être tels que la table user donne un droit, mais que la table db en donne un autre. Dans ce cas, vous aurez les droits nécessaires pour faire une opération, mais le serveur ne peut le déduire d'une seule table : les droits de plusieurs tables doivent être combinés pour arriver à la bonne conclusion.

La table host sert à gérer une liste d'hôtes reconnus et sécuritaires.

Chez TcX, la table host contient une liste de toutes les machines du réseau local. Ces machines reçoivent tous les droits.

Vous pouvez aussi utiliser la table host pour spécifier les hôtes qui ne sont pas sécuritaires. Supposons que la machine public.votre.domaine t est placée dans une zone publique que vous considérez comme peu sûre. Vous pouvez autoriser l'accès de toutes les machines, hormis celle-ci, grâce à la table host configurée comme ceci :

+--------------------+----+-
| Host               | Db | ...
+--------------------+----+-
| public.your.domain | %  | ... (tous les droits à 'N')
| %.your.domain      | %  | ... (tous les droits à 'Y')
+--------------------+----+-

Naturellement, vous devriez toujours tester vos requêtes dans la table de droits, en utilisant l'utilitaire mysqlaccess pour vous assurer que vous disposez des droits nécessaires pour réaliser cette opération.

5-5-7 - Quand les modifications de privilèges prennent-elles effet ?

Lorsque mysqld est lancé, toutes les tables de droits sont lues, et sont utilisées.

Les modifications aux tables de droits que vous faites avec GRANT, REVOKE et SET PASSWORD sont immédiatement prises en compte par le serveur.

Si vous modifiez les tables de droits manuellement (avec INSERT, UPDATE, etc.), vous devez exécuter la commande FLUSH PRIVILEGES ou la commande mysqladmin flush-privileges, ou encore mysqladmin reload pour dire au serveur de relire les tables de droits. Sinon, vos modifications n'auront aucun effet jusqu'au redémarrage du serveur. Si vous modifiez les tables de droits manuellement, mais que vous oubliez de recharger les droits, vous vous demanderez sûrement pourquoi vos modifications n'ont pas d'effet.

Lorsque le serveur remarque que les tables de droits ont été modifiées, les connexions existantes avec les clients sont modifiées comme ceci :

- les droits de tables et colonnes prennent effet à la prochaine requête du client ;

- les droits de bases prennent effet à la prochaine commande USE nom_de_base ;

- les droits globaux et les modifications de droits prennent effet lors de la prochaine connexion.

5-5-8 - Causes des erreurs Access denied

Si vous rencontrez des erreurs Access denied quand vous essayez de vous connecter au serveur MySQL, la liste suivante indique quelques actions à entreprendre pour corriger le problème.

- Assurez-vous que le serveur fonctionne. S'il ne fonctionne pas, vous ne pourrez pas vous y connecter. Par exemple, si vous tentez de vous connecter au serveur, et que vous recevez un message comme celui-ci, c'est peut-être que le serveur ne fonctionne pas :

shell> mysql
ERROR 2003: Can't connect to MySQL server on 'host_name' (111)
shell> mysql
ERROR 2002: Can't connect to local MySQL server through socket
'/tmp/mysql.sock' (111)

Il se peut aussi que le serveur fonctionne, mais que vous essayez de vous connecter en utilisant un port TCP/IP, un pipe nommé ou un fichier de socket Unix qui n'est pas celui que le serveur utilise. Pour corriger cela, lorsque vous utilisez un client, spécifiez l'option --port pour indiquer le bon port, et l'option --socket pour indiquer le bon fichier de socket Unix ou le pipe nommé Windows. Pour connaître le port utilisé, et le chemin jusqu'à la socket, vous pouvez utiliser cette commande :

shell> netstat -l | grep mysql

- Les tables de droits doivent être correctement configurées pour que le serveur les utilise lors de l'identification. Les installations Windows qui utilisent une distribution binaire ou les installations binaires Unix RPM initialisent automatiquement la base mysql contenant les tables de droits. Pour les autres types d'installation, vous devez initialiser les tables de droits manuellement, avec le script mysql_install_db. Pour plus de détails, voyez Section 2.5.2, « Procédures de postinstallation sous Unix ».

Un moyen de déterminer si vous avez besoin d'initialiser les tables de droits est de regarder dans le dossier mysql dans le dossier de données. Le dossier de données s'appelle data ou var et est situé dans le dossier d'installation de MySQL. Assurez-vous que vous avez un fichier appelé user.MYD dans le dossier mysql. Si vous ne le trouvez pas, exécutez le script mysql_install_db. Après exécution de ce script, et redémarrage du serveur, testez les premiers droits avec la commande :

shell> mysql -u root test

Le serveur doit vous laisser vous connecter sans erreur.

- Après une installation toute fraîche, vous devez vous connecter au serveur et créer les utilisateurs en réglant leurs permissions d'accès :

shell> mysql -u root mysql

Le serveur devrait vous laisser vous connecter, car l'utilisateur root de MySQL n'a pas de mot de passe initial. Ceci est aussi une faille de sécurité, et donc, vous devez choisir un mot de passe pour l'utilisateur root en même tant que les autres utilisateurs MySQL. Pour des instructions sur la configuration des mots de passe initiaux, voyez la section Section 2.5.3, « Création des premiers droits MySQL ».

- Si vous avez mis à jour une version de MySQL avec une nouvelle version, avez-vous utilisé le script mysql_fix_privilege_tables ? Si ce n'est pas le cas, faites-le. La structure des tables de droits change occasionnellement, lorsque de nouvelles fonctionnalités sont ajoutées : après une mise à jour, assurez-vous que vos tables ont la bonne structure. Pour des instructions, voyez Section 2.6.7, « Mise à jour des tables de droits ».

- Si un programme client reçoit l'erreur suivante lorsqu'il essaie de se connecter, cela signifie que le serveur attend un mot de passe dans un nouveau format, alors que le client fournit un ancien format :

shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

Pour des informations sur comment traiter ce type de situations, voyez Section 5.5.9, « Hashage de mots de passe en MySQL 4.1 » et Section A.2.3, « Erreur Client does not support authentication protocol ».

- Si vous essayez de vous connecter en tant que root et que vous recevez l'erreur suivante, cela signifie que vous n'avez pas d'entrée dans la table user avec une valeur 'root' dans la colonne User et que mysqld ne peut pas résoudre le nom d'hôte du client :

Access denied for user: ''@'unknown' to database mysql

Dans ce cas, vous devez relancer le serveur avec l'option --skip-grant-tables, et éditer votre fichier /etc/hosts ou \windows\hosts pour ajouter une ligne vous votre hôte.

- N'oubliez pas que les clients utilisent les paramètres de connexions placés dans les fichiers d'options ou les variables d'environnement. Si un client semble envoyer des paramètres de connexions invalides, lorsque vous n'en spécifiez aucun, vérifiez votre environnement, et les options appropriées. Par exemple, si vous recevez l'erreur Access denied avec un client utilisé sans option, assurez-vous que vous n'avez pas spécifié un ancien mot de passe dans vos anciens fichiers d'options.

Vous pouvez supprimer l'utilisation des fichiers d'options d'un client en utilisant l'option --no-defaults. Par exemple :

shell> mysqladmin --no-defaults -u root version

Le fichier d'options que les clients utilisent est listé dans la section Section 4.3.2, « Fichier d'options my.cnf ». Les variables d'environnement sont listées dans Annexe E, Variables d'environnement.

- Si vous obtenez une erreur qui ressemble à celle-ci :

shell> mysqladmin -u root -pxxxx ver
Access denied for user: 'root'@'localhost' (Using password: YES)

Cela signifie que vous utilisez un mot de passe erroné.

Si l'erreur précédente survient lorsque vous n'avez pas spécifié de mot de passe, cela signifie que vous n'avez pas spécifié de mot de passe dans un fichier d'options. Essayez l'option --no-defaults telle que décrite ci-dessus.

Pour des informations sur les changements de mot de passe, voyez Section 5.6.5, « Configurer les mots de passe ».

Si vous avez oublié le mot de passe root, vous pouvez redémarrer mysqld avec --skip-grant-tables pour changer le mot de passe. Voir Section A.4.1, « Comment réinitialiser un mot de passe Root oublié ».

- Si vous n'arrivez pas à faire fonctionner votre mot de passe, souvenez-vous que vous devez utiliser la fonction PASSWORD() si vous le changez avec les commandes INSERT, UPDATE, ou SET PASSWORD. L'utilisation de la fonction PASSWORD() n'est pas nécessaire si vous spécifiez le mot de passe en utilisant la commande GRANT ... INDENTIFIED BY ou la commande mysqladmin password. Voir Section 5.6.5, « Configurer les mots de passe ».

mysql> SET PASSWORD FOR 'abe'@'host_name' = 'eagle';

À la place, utilisez cette commande :

mysql> SET PASSWORD FOR 'abe'@'host_name' = PASSWORD('eagle');

La fonction PASSWORD() n'est pas nécessaire si vous spécifiez un mot de passe avec la commande GRANT ou la commande en ligne mysqladmin password, qui utilise automatiquement PASSWORD() pour chiffrer le mot de passe.

- localhost est un synonyme de votre nom d'hôte local, et est aussi l'hôte par défaut auquel le client essaye de se connecter si vous n'en spécifiez pas un explicitement. Toutefois, les connexions à localhost ne fonctionnent pas si vous utilisez une version antérieure à la 3.23.27 qui utilise les MIT-pthreads.

Pour contourner ce problème sur de tels systèmes, vous devez utiliser l'option --host pour nommer l'hôte du serveur explicitement. Cela créera une connexion TCP/IP vers le serveur mysqld. Dans ce cas, vous devez avoir votre vrai nom d'hôte dans les entrées de la table user du serveur hôte. (Cela est vrai même si vous utilisez un programme client sur la même machine que le serveur.)

- Si vous obtenez une erreur Access denied lorsque vous essayez de vous connecter à la base de données avec mysql -u nom_utilisateur nom_base, vous pouvez avoir un problème dans la table user. Vérifiez-le en vous exécutant mysql -u root mysql et entrant la commande SQL suivante :

mysql> SELECT * FROM user;

Le résultat devrait comprendre une entrée avec les colonnes Host et User correspondante au nom d'hôte de votre ordinateur et votre nom d'utilisateur MySQL.

- Le message d'erreur Access denied vous dira en tant que qui vous essayez de vous identifier, l'hôte à partir duquel vous voulez le faire, et si vous utilisez ou pas un mot de passe. Normalement, vous devez avoir une entrée dans la table user qui correspond au nom d'hôte et nom d'utilisateur donnés dans le message d'erreur. Par exemple, si vous obtenez une erreur qui contient Using password: NO, cela signifie que vous avez essayé de vous connecter sans mot de passe.

- Si vous obtenez l'erreur suivante en essayant de vous connecter à partir d'un hôte différent de celui sur lequel est placé le serveur, c'est qu'il n'y a pas d'enregistrement dans la table user qui correspond à cet hôte :

Host ... is not allowed to connect to this MySQL server

Vous pouvez corriger ce problème en configurant un compte avec la combinaison hôte/nom d'utilisateur que vous utilisez lors de la connexion.

Si vous ne connaissez ni l'IP ni le nom d'hôte à partir duquel vous essayez de vous connecter, vous devez créer une entrée avec '%' dans la colonne Host dans la table user et redémarrer mysqld avec l'option --log sur la machine serveur. Après avoir essayé à nouveau de vous connecter à partir de la machine cliente, les informations contenues dans le log de MySQL vous apprendront comment vous vous êtes vraiment connecté. (Remplacez alors l'entrée de la table user contenant '%' avec le nom d'hôte qui apparaît dans le log. Sinon, vous aurez un système non sécurisé.)

Une autre raison pour cette erreur sous Linux est que vous utilisez une version binaire de MySQL qui est compilée avec une version de glibc différente de celle que vous utilisez. Dans ce cas, vous devez soit mettre à jour votre système d'exploitation et sa bibliothèque glibc, soit télécharger les sources de MySQL et les compiler vous-même. Un RPM de sources est normalement facile à compiler et installer, cela ne devrait donc pas vous poser de gros problèmes.

- Si vous obtenez une erreur où le nom d'hôte est absent ou que celui-ci est une adresse IP alors que vous avez bien entré le nom d'hôte :

shell> mysqladmin -u root -pxxxx -h some-hostname ver
Access denied for user: 'root@' (Using password: YES)

Cela signifie que MySQL a rencontré des erreurs lors de la résolution de l'IP du nom d'hôte. Dans ce cas, vous pouvez exécuter mysqladmin flush-hosts pour vider le cache interne des DNS. Voir Section 7.5.6, « Comment MySQL utilise le DNS ».

Les autres solutions sont :

- essayez de trouver le problème avec votre serveur DNS et corrigez-le ;

- spécifiez les IP à la place des noms d'hôtes dans les tables de droits de MySQL ;

- ajoutez une ligne pour le nom de votre machine dans /etc/hosts ;

- démarrez mysqld avec --skip-name-resolve ;

- démarrez mysqld avec --skip-host-cache ;

- sous Unix, si vous utilisez le serveur et le client sur la même machine, connectez-vous à localhost. Les connexions Unix à localhost utilisent un socket Unix plutôt que TCP/IP ;

- sous Windows, si vous exécutez le serveur et le client sur la même machine, et que le serveur supporte les pipes nommés, connectez-vous à l'hôte . (point). Les connexions à . utilisent les pipes nommés plutôt que TCP/IP ;

- si mysql -u root test fonctionne, mais que mysql -h votre_hote -u root test provoque une erreur Access denied, il se peut que vous ayez entré de mauvaises informations pour votre nom d'hôte dans la table user. Un problème commun ici est que la valeur Host dans la table user spécifie un nom d'hôte non qualifié, mais que vos routines système de résolution de noms retournent un nom de domaine pleinement qualifié (ou vice-versa). Par exemple, si vous avez une entrée avec l'hôte 'tcx' dans la table user, mais que vos DNS disent à MySQL que votre nom d'hôte est 'tcx.subnet.se', l'entrée ne fonctionnera pas. Essayez d'ajouter une entrée dans la table user qui contient votre adresse IP en tant que valeur de la colonne Host. (Une autre solution est d'ajouter une entrée dans la table user avec une valeur de Host qui contient un caractère spécial, par exemple, 'tcx.%'. Toutefois, l'utilisation des noms d'hôtes se terminant par '%' est non sécurisée et n'est pas recommandée !) ;

- si mysql -u utilisateur test fonctionne, mais que mysql -u utilisateur autre_base ne fonctionne pas, vous n'avez pas d'entrée pour autre_base listée dans la table db ;

- si mysql -u utilisateur nom_base fonctionne à partir du serveur, mais que mysql -h nom_hote -u utilisateur nom_base ne fonctionne pas à partir d'une autre machine, cette machine n'est pas listée dans la table user ou db ;

- si vous n'arrivez pas à trouver pourquoi vous obtenez l'erreur Access denied, effacez toutes les entrées de la table user dont la valeur du champ Host contiennent des caractères spéciaux (entrées contenant '%' ou '_'). Une erreur commune est d'insérer une nouvelle entrée avec Host='%' et User='un utilisateur', en pensant que cela vous permettra de spécifier localhost pour vous connecter à partir de la même machine. La raison pour laquelle cela ne fonctionnera pas est que les droits par défaut incluent une entrée avec Host='localhost' et User=''. Puisque cette entrée possède une valeur de Host égale à 'localhost', qui est plus spécifique que '%', elle est utilisée de préférence à la nouvelle entrée lors de la connexion à partir de localhost ! La procédure correcte est d'insérer une seconde entrée avec Host='localhost' et User='un_utilisateur', ou de supprimer l'entrée avec Host='localhost' et User='' ;

- si vous avez l'erreur suivante, vous avez peut-être un problème avec la table db ou host :

Access to database denied

Si l'entrée sélectionnée dans la table db possède un champ Host vide, assurez-vous qu'il y a au moins une entrée correspondante dans la table host spécifiant les hôtes auxquels l'entrée dans la table db s'applique ;

- si vous obtenez l'erreur lors de l'utilisation des commandes SQL SELECT ... INTO OUTFILE ou LOAD DATA INFILE, votre entrée dans la table user ne possède probablement pas les droits de FILE ;

- si vous apportez des modifications aux tables de droits directement (en utilisant une requête INSERT ou UPDATE) et que vos changements semblent ignorés, souvenez-vous que vous devez exécuter une requête FLUSH PRIVILEGES ou la commande mysqladmin flush-privileges pour demander au serveur de lire à nouveau les tables de droits. Sinon, vos changements ne seront pris en compte qu'au prochain démarrage du serveur. Souvenez-vous qu'après avoir choisi le mot de passe root avec une commande UPDATE, vous n'aurez pas à le spécifier avant de recharger les privilèges, car le serveur ne sait pas que vous l'avez modifié !

- si vos droits changent en milieu de session, c'est peut-être qu'un administrateur MySQL a changé les droits. En rechargeant les tables de droits, il a modifié aussi les connexions existantes, comme indiqué dans Section 5.5.7, « Quand les modifications de privilèges prennent-elles effet ? » ;

- si vous avez des problèmes d'accès avec un programme Perl, PHP, Python, ou ODBC, essayez de vous connecter au serveur avec mysql -u utilisateur nom_base ou mysql -u utilisateur -pvotre_passe nom_base. Si vous pouvez vous connecter en utilisant le client mysql, c'est que le problème vient de votre programme et non des droits MySQL. (Notez qu'il n'y a pas d'espace entre -p et le mot de passe, vous pouvez aussi utiliser la syntaxe --password=votre_passe pour spécifier le mot de passe. Si vous utilisez l'option -p toute seule, MySQL vous demandera le mot de passe.) ;

- pour les tests, démarrez le démon mysqld avec l'option --skip-grant-tables. Vous pourrez alors changer les tables de droits MySQL puis utiliser le script mysqlaccess pour vérifier si vos changements ont l'effet désiré. Lorsque vous êtes satisfait de vos modifications, exécutez mysqladmin flush-privileges pour dire au serveur mysqld de commencer à utiliser les nouvelles tables de droits. Recharger les tables de droits écrase l'option --skip-grant-tables. Cela vous permet de dire au serveur de commencer à prendre en considération les droits sans avoir à le couper et le redémarrer ;

- si rien ne fonctionne, démarrez le démon mysqld avec l'option de débogage (par exemple, --debug=d,general,query). Cela affichera l'hôte et les informations de l'utilisateur pour chaque tentative de connexion. Les informations à propos de chaque commande exécutée seront aussi affichées. Voir Section D.1.2, « Créer un fichier de traçage » ;

- si vous avez d'autres problèmes avec les tables de droits de MySQL et que vous sentez que vous devez envoyer le problème à la liste de diffusion, fournissez toujours le contenu de vos tables de droits. Vous pouvez obtenir les données avec la commande mysqldump mysql. Comme toujours, postez votre problème à l'aide du script mysqlbug. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ». Dans certains cas, vous aurez besoin de redémarrer mysqld avec --skip-grant-tables pour pouvoir exécuter mysqldump.

5-5-9 - Hashage de mots de passe en MySQL 4.1

Les comptes utilisateurs de MySQL sont stockés dans la table user de la base mysql. Chaque compte MySQL a un mot de passe, même si ce qui est stocké dans la colonne Password de la table user n'est pas la version texte du mot de passe, mais un hash calculé à partir du mot de passe. La transformation est faite avec la fonction PASSWORD().

MySQL utilise les mots de passe en deux phases, lors de la communication client/serveur :

- premièrement, lorsqu'un client tente de se connecter au serveur, il y a une identification initiale au cours de laquelle le client doit présenter un mot de passe dont la valeur hashée est la même que celle qui est présente dans la table d'utilisateur, pour le compte que le client veut utiliser ;

- ensuite, après la connexion du client, il peut modifier ou changer le mot de passe pour les utilisateurs du serveur (s'il a les droits nécessaires pour cela). Le client peut faire cela avec la fonction PASSWORD(), pour générer un autre mot de passe, ou en utilisant les commandes GRANT ou SET PASSWORD.

En d'autres termes, le serveur utilise les valeurs hashées durant la phase d'identification, lorsque le client tente de se connecter. Le serveur génère des valeurs hash, si un client appelle la fonction PASSWORD() ou utilise les commandes GRANT ou SET PASSWORD.

Le mécanisme de modifications des mots de passe a été modifié en MySQL 4.1, pour apporter une sécurité accrue et réduire le risque de vol de mots de passe. Cependant, ce nouveau mécanisme ne peut être compris que de la version 4.1, et des clients MySQL 4.1, ce qui pose des problèmes de compatibilité. Un client 4.1 peut se connecter sur un serveur pré-4.1, car le client comprend les deux méthodes de hashage, ancienne et nouvelle. Cependant, un client pré-4.1 qui tente se de connecter à un serveur 4.1 aura des problèmes. Par exemple, si un client mysql 4.0 essaie de se connecter au serveur 4.1, il va recevoir l'erreur suivante :

shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

La discussion suivante décrit les différences entre les mécanismes de mots de passe, et ce que vous devez faire pour mettre à jour votre serveur en version 4.1, tout en conservant la compatibilité avec les clients pre-4.1.

Note : cette discussion compare les comportements des versions 4.1 avec les versions d'avant (dites pré-4.1), mais le comportement 4.1 ne commence en réalité qu'avec la version 4.1.1. MySQL 4.1.0 est une version « marginale », car elle a un mécanisme légèrement différent de celui qui est implémenté en versions 4.1.1 et plus récentes. Les différences entre les versions 4.1.0 et les versions plus récentes sont décrites ultérieurement.

Avant MySQL 4.1, les hashs calculés par PASSWORD() étaient longs de 16 octets. Des hashs ressemblaient à ceci :

mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e   |
+--------------------+

La colonne Password de la table user, dans laquelle les hashs de mot de passe sont stockés, faisait 16 octets de long, avant MySQL 4.1.

Depuis MySQL 4.1, la fonction PASSWORD() a été modifiée, pour produire une valeur de 41 octets, comme ceci :

mysql> SELECT PASSWORD('mypass');
+-----------------------------------------------+
| PASSWORD('mypass')                            |
+-----------------------------------------------+
| *43c8aa34cdc98eddd3de1fe9a9c2c2a9f92bb2098d75 |
+-----------------------------------------------+

La colonne Password de la table user a été agrandie pour faire désormais 41 octets de long.

- Si vous faites une nouvelle installation de MySQL 4.1, la colonne Password fera automatiquement 41 octets.

- Si vous mettez à jour une ancienne installation, il est recommandé d'utiliser le script mysql_fix_privilege_tables pour mettre à jour la taille de la colonne Password, de 16 à 41 octets. Le script ne modifie pas les valeurs elles-mêmes, qui restent à 16 octets de long.

Une colonne Password élargie peut stocker les mots de passe dans les deux formats, ancien et nouveau. Le format d'un hash de mot de passe peut être déterminé de deux manières :

- la différence principale et évidente est la taille : 16 octets et 41 octets ;

- la seconde différence est que les hashs au nouveau format commencent par le caractère '*', alors que l'ancien format ne le fait pas.

Plus le hash du mot de passe est long, meilleures sont ses caractéristiques de chiffrement, et l'identification des clients, basée sur des hashs longs, est plus sécuritaire que l'ancienne méthode, dont les hashs sont plus courts.

La différence de taille entre les mots de passe est utile lors de l'utilisation des mots de passe, pour l'identification, et lors de la génération des hashs pour la modification des mots de passe, sur le client.

La façon de traiter le hash de mot de passe durant la phase d'identification diffère, en fonction de la taille de la colonne Password :

- si la colonne est étroite, l'identification par hash court sera utilisée ;

- si la colonne est large, elle peut contenir des hashs longs ou courts, et le serveur peut utiliser l'un ou l'autre des formats :

- les clients pré-4.1 peuvent se connecter, car ils connaissent l'ancien mécanisme de hashing, et ils peuvent s'identifier pour les comptes qui ont des mots de passe courts,

- les clients 4.1 peuvent s'identifier pour les comptes qui ont des hashs longs ou courts.

Pour les comptes à hash court, l'identification est un peu plus sécuritaire pour les clients 4.1 que pour les anciens clients. En termes de sécurité, le gradient de sécurité du plus faible au meilleur est :

- les clients pré-4.1 s'identifiant avec un hash court ;

- les clients 4.1 s'identifiant avec un hash court ;

- les clients 4.1 s'identifiant avec un hash long.

La méthode de génération des hashs de mots de passe pour les clients connectés est aussi affectée par la taille de la colonne Password, et par l'option --old-passwords. Un serveur 4.1 génère des hashs longs sous certaines conditions : La colonne Password doit être assez grande pour accueillir un hash de mot de passe long, et l'option --old-passwords doit être inactive. Ces conditions s'appliquent comme suit.

- La colonne Password doit être assez grande pour accueillir des hashs de mots de passe longs (41 octets). Si la colonne n'a pas été mise à jour, et qu'elle a toujours la taille de 16 octets, le serveur le remarque, et générera des hashs de mots de passe courts lorsque le client va modifier son mot de passe avec PASSWORD(), GRANT ou SET PASSWORD. Ce comportement survient si vous avez mis à jour le serveur en version 4.1, mais omis d'utiliser le script mysql_fix_privilege_tables pour élargir la colonne Password.

- Si la colonne Password est suffisamment grande, elle peut stocker un mot de passe long ou court. Dans ce cas, PASSWORD(), GRANT et SET PASSWORD vont générer des hashs longs, à moins que le serveur n'ait été lancé avec l'option --old-passwords. Cette option force le serveur à utiliser les hashs courts.

Le but de l'option --old-passwords est d'assurer la compatibilité ascendante avec les clients pré-4.1 clients dans certaines circonstances où le serveur aurait généré des hashs longs. Cela n'affecte pas l'identification, puisque les clients 4.1 peuvent continuer à utiliser les comptes avec des hashs longs, mais cela empêche la création de hashs longs dans la table user, lors de la modification de mots de passe. Si cela arrive, le compte me pourra plus être utilisé avec les clients pré-4.1. Sans l'option --old-passwords le scénario suivant est possible :

- un ancien client se connecter sur un compte, avec un hash court ;

- le client change le mot de passe. Sans l'option --old-passwords, cela conduit à la création d'un hash long ;

- lors de la prochaine connexion, le client pré-4.1 ne peut plus se connecter, car le compte requiert désormais le nouveau mécanisme d'identification. Une fois que le hash long est dans la table user, seuls les clients 4.1 peuvent l'utiliser, car les clients pré-4.1 ne le comprennent pas.

Ce scénario montre combien il est dangereux d'utiliser un serveur 4.1 sans l'option --old-passwords si vous devez supporter des clients pré-4.1. En utilisant l'option --old-passwords sur le serveur, les opérations de modification de mots de passe ne génèrent pas de hashs longs, et les utilisateurs ne se barreront pas l'accès par inadvertance.

L'inconvénient de l'option --old-passwords est que tous les hashs que vous allez créer seront des hashs courts, même pour les clients 4.1. Par conséquent, vous perdez la sécurité améliorée que les hashs longs apportent. Si vous voulez créer un compte avec un hash long (par exemple, pour un client 4.1), il faudra le faire avec un serveur qui n'utilise pas l'option --old-passwords.

Les scénarios suivants sont possibles avec un serveur 4.1.

Scénario 1 : colonne Password courte dans la table user

- Seuls, les hashs courts peuvent être stockés dans la colonne Password.

- Le serveur utilise uniquement les hashs courts pour les identifications.

- Pour les clients connectés, la génération de mot de passe avec PASSWORD(), GRANT ou SET PASSWORD utilise les mots de passe courts uniquement. Toute modification de compte entraine la création d'un hash court.

- L'option --old-passwords peut être utilisée, mais est superflue, car la colonne Password courte impose la manipulation de hashs courts de toute manière.

Scénario 2 : colonne Password longue dans la table user, serveur sans l'option --old-passwords

- les hashs courts et longs peuvent être stockés dans la colonne Password.

- Les clients 4.1 peuvent s'identifier sur leur compte avec des hashs courts ou longs.

- Les clients pré-4.1 peuvent s'identifier sur leur compte avec des hashs courts.

- Pour les clients connectés, la génération de mot de passe avec PASSWORD(), GRANT ou SET PASSWORD utilise les mots de passe longs uniquement. Toute modification de compte entraine la création d'un hash long.

Comme indiqué précédemment, le danger de ce scénario est qu'il est possible que les clients pré-4.1 se voient l'accès au serveur barré. Toutes les modifications du compte avec GRANT, SET PASSWORD et PASSWORD() conduisent à un hash long, qui empêchera les clients pré-4.1 d'utiliser ce compte.

Pour régler ce problème, vous pouvez modifier le mot de passe d'une manière spéciale. Par exemple, normalement, vous pouvez utiliser la commande SET PASSWORD comme ceci pour modifier un mot de passe :

mysql> SET PASSWORD FOR
-> 'some_user'@'some_host' = PASSWORD('mypass');

Pour changer le mot de passe avec un hash court, utilisez la fonction OLD_PASSWORD() :

mysql> SET PASSWORD FOR
-> 'some_user'@'some_host' = OLD_PASSWORD('mypass');

OLD_PASSWORD() est pratique pour les situations où vous voulez explicitement générer un hash court.

Scénario 3 : colonne Password longue dans la table user, serveur avec l'option --old-passwords

- les hashs courts et longs peuvent être stockés dans la colonne Password.

- Les clients 4.1 peuvent s'identifier sur leur compte avec des hashs courts ou longs. Notez qu'il n'est alors possible de créer des hashs longs si le serveur utilise --old-passwords).

- Les clients pré-4.1 peuvent s'identifier sur leur compte avec des hashs courts.

- Pour les clients connectés, la génération de mot de passe avec PASSWORD(), GRANT ou SET PASSWORD utilise les mots de passe courts uniquement. Toute modification de compte entraîne la création d'un hash long.

Dans ce scénario, vous ne pouvez plus créer de compte avec un hash long, car --old-passwords l'empêche. De même, si vous créez un compte avec un hash long sur un serveur qui utilise l'option --old-passwords, la modification du mot de passe tant que --old-passwords est active, aura pour effet de réduire la taille du hash, et vous perdrez en sécurité.

Les inconvénients de ces scénarios sont les suivants.

Scénario 1) vous ne pouvez pas tirer parti des hashs longs et de leur sécurité accrue.

Scénario 2) Les comptes avec des mots de passe courts sont inaccessibles aux clients pré-4.1 si vous modifiez leur mot de passe sans utiliser la fonction OLD_PASSWORD().

Scénario 3) --old-passwords empêche les comptes avec des hashs courts d'être barrés, mais les opérations de modifications de mots de passe créeront des hashs courts, et vous ne pourrez pas les modifier tant que à --old-passwords est effective.

5-5-9-1 - Implications des modifications de mot de passe pour les applications

Une mise à jour en version MySQL 4.1 peut se révéler un problème de compatibilité pour les applications qui utilisent PASSWORD() pour générer leurs propres mots de passe. Les applications ne devraient pas faire cela, car PASSWORD() doit être réservé pour gérer les mots de passe de MySQL. Mais certaines applications utilisent PASSWORD() pour leurs propres objectifs.

Si vous passez en version 4.1 et lancez le serveur dans certaines conditions, où il va générer des hashs de mots de passe longs, l'application qui utilise PASSWORD() va sûrement planter. Notre recommandation est d'utiliser les fonctions de chiffrement SHA1() ou MD5() pour produire des signatures. Si ce n'est pas possible, vous pouvez utiliser OLD_PASSWORD(), qui est fournie pour générer des hashs courts, dans l'ancien format (mais notez que OLD_PASSWORD() pourrait être abandonné un jour aussi.

Si le serveur fonctionne dans des conditions où il génère des hashs courts, OLD_PASSWORD() est disponible comme alias de PASSWORD().

5-5-9-2 - Gestion des mots de passe en MySQL 4.1.0

Le hashing de mot de passe de MySQL 4.1.0 diffère de celui de la version 4.1.1 et plus récentes. Les différences avec la version 4.1.0 sont :

- les mots de passe sont stockés sur 45 octets plutôt que 41 ;

- la fonction PASSWORD() n'est pas répétable. C'est-à-dire, à partir du même argument X, des appels successifs à PASSWORD(X) génèreront différents résultats.

Ces différences rendent l'identification de la version 4.1.0 incompatible avec les versions suivantes. Si vous avez mis à jour MySQL 4.1.0, il est recommandé de passer à une version plus récente aussi tôt que possible. Après cela, réassignez les mots de passe de la table user pour qu'ils soient compatibles avec le format 41 octets.

5-6 - Gestion des comptes utilisateur de MySQL

Cette section décrit comment configurer des comptes clients pour un serveur MySQL. Elle traite des points suivants :

- la signification des noms de compte et mots de passe, tels qu'utilisés par MySQL, et quelle différence il y a avec ceux de votre système d'exploitation ;

- comment configurer de nouveaux comptes ;

- comment modifier les mots de passe ;

- des conseils de gestion des mots de passe ;

- comment configurer des connexions sécurisées avec SSL

5-6-1 - Noms d'utilisateurs MySQL et mots de passe

Il y a de nombreuses différences entre les utilisations des noms et mots de passe sous MySQL, et celles qui sont faites sous Unix ou Windows.

- Les noms d'utilisateurs, tels qu'utilisés pour le processus d'identification sous MySQL, n'ont rien à voir avec les noms d'utilisateurs Unix ou Windows. La plupart des clients utilisent par défaut leur mot de passe Unix, mais c'est surtout parce que c'est pratique. Les programmes clients permettent d'utiliser des noms d'utilisateurs différents avec les options -u et --user. Cela signifie que vous ne pouvez pas rendre une base de données sécuritaire sans donner de mots de passe à tous les clients. Tout le monde peut essayer de se connecter au serveur sous n'importe quel nom, et il sera possible de se connecter si un nom d'utilisateur n'a pas de mot de passe.

- Les noms d'utilisateurs MySQL peuvent avoir jusqu'à 16 caractères ; les noms d'utilisateurs Unix sont généralement limités à 8 caractères.

- Les mots de passe MySQL n'ont aucun rapport avec le passeport Unix. Il n'y a pas nécessairement de connexion entre le mot de passe que vous utilisez pour vous connecter sur la machine Unix et celui que vous utilisez pour accéder au serveur MySQL.

- MySQL chiffre les mots de passe avec un algorithme différent de celui qui est utilisé par Unix. Reportez-vous aux descriptions des fonctions PASSWORD() et ENCRYPT() dans Section 12.8.2, « Fonctions de chiffrements ». Notez que même si le mot de passe est enregistré « brouillé », connaître votre mot de passe « brouillé » est suffisant pour se connecter au serveur MySQL.

Lorsque vous installez MySQL, la table de droits contient quelques comptes initiaux. Ces comptes ont des noms et droits qui sont décrits dans Section 2.5.3, « Création des premiers droits MySQL », qui montre aussi comment donner des mots de passe. Après cela, vous pouvez créer, modifier ou supprimer normalement des comptes MySQL avec les commandes GRANT et REVOKE. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

Lorsque vous vous connectez à un serveur MySQL avec un client en ligne de commande, vous devez spécifier le mot de passe avec l'option --password=mot-de-passe. Voir Section 5.5.4, « Se connecter au serveur MySQL ».

mysql --user=monty --password=devine nom_base

ou la version courte :

shell> mysql -u monty -pdevine nom_base

Il ne doit pas y avoir d'espace entre l'option -p et le mot de passe suivant.

Les commandes incluent la valeur d'un mot de passe en ligne de commande, ce qui n'est pas sécuritaire. Voir Section 5.6.6, « Garder vos mots de passe en lieu sûr ».

Pour éviter cela, spécifiez l'option --password ou -p sans aucune valeur :

shell> mysql --user=monty --password nom_base
shell> mysql -u monty -p nom_base

Le client va alors afficher une invite, et vous demander d'y saisir le mot de passe. Dans les exemples, nom_base n'est pas interprété comme un mot de passe, car il est séparé de l'option précédente par un espace.

Sur certains systèmes, l'appel que MySQL utilise pour demander le mot de passe va limiter automatiquement le mot de passe à 8 caractères. C'est un problème avec la bibliothèque système, et non pas avec MySQL. En interne, MySQL n'a pas de limite pour la taille du mot de passe. Pour contourner le problème, modifiez la taille du mot de passe pour qu'il fasse 8 caractères ou moins, ou placez votre mot de passe dans un fichier d'options.

5-6-2 - Ajouter de nouveaux utilisateurs à MySQL

Vous pouvez ajouter des utilisateurs de deux façons différentes :

- en utilisant la commande GRANT ;

- manipulant la table des droits de MySQL directement.

La méthode préférée consiste à utiliser la commande GRANT, car elle est plus concise et qu'il y a moins de risques d'erreur. Sa syntaxe est présentée dans la section Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

Il y a aussi beaucoup de programmes utilitaires comme phpmyadmin qui peuvent être utilisés pour créer et administrer les utilisateurs.

Les exemples suivants montrent comment utiliser le client mysql pour créer de nouveaux utilisateurs. Ces exemples supposent que les privilèges sont attribués en accord avec les valeurs par défaut discutées dans la section Section 2.5.3, « Création des premiers droits MySQL ». Cela signifie que pour effectuer des changements, vous devez être sur la même machine où mysqld tourne, vous devez vous connecter en tant qu'utilisateur MySQL root, et l'utilisateur root doit avoir le droit INSERT sur la base mysql et le droit d'administration RELOAD. Si vous avez changé le mot de passe de l'utilisateur root, vous devez le spécifier dans les commandes mysql ci-dessous.

D'abord, utilisez le programme client mysql pour vous connecter au serveur MySQL en tant qu'utilisateur root :

shell> mysql --user=root mysql

Vous pouvez ajouter de nouveaux utilisateurs en utilisant des commandes GRANT :

mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'
->     IDENTIFIED BY 'un_mot_de_passe' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
->     IDENTIFIED BY 'un_mot_de_passe' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';

Ces commandes GRANT ajoutent trois nouveaux utilisateurs :

- deux comptes de super-utilisateur qui utilisent le mot de passe 'un_mot_de_passe'. Les deux comptes ont tous les droits sur le serveur. Un des comptes, 'monty'@'localhost', peut être utilisé depuis la machine locale. L'autre depuis n'importe quel autre serveur : 'monty'@'%'. Notez que nous devons exécuter une commande GRANT pour 'monty'@'localhost' et 'monty'@'%'. Si nous n'ajoutons pas l'entrée avec localhost, l'entrée concernant l'utilisateur anonyme pour localhost qui est créée par mysql_install_db prendra précédence lors de la connexion à partir de l'hôte local, car elle a une entrée plus spécifique pour la valeur du champ Host et de plus, elle vient en premier dans l'ordre de tri de la table user. Les tris de la table user sont présentés dans la section Section 5.5.5, « Contrôle d'accès, étape 1 : Vérification de la connexion » ;

- un utilisateur admin qui peut se connecter depuis localhost sans mot de passe et qui a les droits administratifs RELOAD et PROCESS. Cela permet à cet utilisateur d'exécuter les commandes mysqladmin reload, mysqladmin refresh, et mysqladmin flush-*, ainsi que mysqladmin processlist. Aucun droit lié aux bases de données n'est donné. Ils peuvent l'être plus tard en utilisant d'autres instructions GRANT ;

- un utilisateur dummy qui peut se connecter sans mot de passe, mais seulement à partir de l'hôte local. Les droits globaux sont tous à 'N' : le type de droit USAGE vous permet de créer un utilisateur démuni de privilège. Il est supposé que vous lui assignerez les droits spécifiques aux bases de données plus tard.

Vous pouvez ajouter les mêmes droits d'accès aux utilisateurs en utilisant directement des requêtes INSERT puis en demandant au serveur de recharger les tables de droits :

shell> mysql --user=root mysql
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD('un_mot_de_passe'),
->          'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('un_mot_de_passe'),
->          'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user SET Host='localhost',User='admin',
->           Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
->                  VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

Selon votre version de MySQL, vous pouvez avoir un nombre différent de valeurs 'Y' plus haut (les versions antérieures à la 3.22.11 possèdent moins de colonnes de privilèges). Pour l'utilisateur admin, la syntaxe d'INSERT étendue la plus lisible disponible depuis la version 3.22.11 est utilisée.

Notez que pour ajouter un super-utilisateur, vous avez juste besoin de créer une entrée dans la table user avec tous les champs de droits à 'Y'. Aucune entrée n'est requise dans les tables db et host.

Les colonnes de privilèges de la table user n'étaient pas renseignées explicitement dans la dernière requête INSERT (pour l'utilisateur dummy), ses colonnes prennent donc la valeur par défaut, 'N'. C'est la même chose que ce que fait GRANT USAGE.

L'exemple suivant ajoute un utilisateur custom qui peut se connecter à partir des hôtes localhost, server.domain, et whitehouse.gov. Il ne pourra accéder à la base de données bankaccount qu'à partir de localhost, à la base expenses qu'à partir de whitehouse.gov, et à la base customer à partir des trois hôtes. Il utilisera le mot de passe stupid pour les trois hôtes.

Pour configurer les privilèges de cet utilisateur en utilisant des commandes GRANT, exécutez ce qui suit :

shell> mysql --user=root mysql
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->     ON bankaccount.*
->     TO custom@localhost
->     IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->     ON expenses.*
->     TO custom@whitehouse.gov
->     IDENTIFIED BY 'stupid';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->     ON customer.*
->     TO custom@'%'
->     IDENTIFIED BY 'stupid';

Les trois comptes peuvent être utilisés comme suit :

- le premier compte a accès à la base bankaccount, mais uniquement depuis l'hôte local ;

- le second compte peut accéder à la base expenses, mais uniquement depuis l'hôte whitehouse.gov ;

- le troisième compte peut accéder à la base customer, mais uniquement depuis l'hôte server.domain.

Pour régler les permissions d'accès en modifiant directement les tables de droits, exécutez ces commandes (notez l'appel à FLUSH PRIVILEGES à la fin) :

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('localhost','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('server.domain','custom',PASSWORD('stupid'));
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('whitehouse.gov','custom',PASSWORD('stupid'));
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
->  Create_priv,Drop_priv)
-> VALUES
-> ('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
->  Create_priv,Drop_priv)
-> VALUES
-> ('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
->  Create_priv,Drop_priv)
-> VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;

Les trois premières requêtes INSERT ajoutent les entrées dans la table user qui permettent l'utilisateur custom à se connecter à partir de plusieurs hôtes avec le mot de passe donné, mais ne lui donnent aucun droit (tous les droits sont mis à la valeur par défaut qui est 'N'). Les trois requêtes INSERT suivantes ajoutent des entrées dans la table db qui autorisent custom à utiliser les bases de données bankaccount, expenses, et customer, mais seulement s'il y accède à partir de l'hôte spécifié. Comme d'habitude, lorsque les tables de droits sont modifiées directement, on doit demander au serveur de les recharger (avec FLUSH PRIVILEGES) pour que les changements soient pris en compte.

Si vous voulez donner un accès spécifique à un utilisateur à partir de n'importe quelle machine d'un domaine donné, vous pouvez utiliser la commande GRANT, en utilisant '%' comme joker dans le nom de l'hôte :

mysql> GRANT ...
->     ON *.*
->     TO monutilisateur@"%.mondomaine.com"
->     IDENTIFIED BY 'monmotdepasse';

Pour faire la même chose en modifiant directement la table de droits, faites :

mysql> INSERT INTO user VALUES ('%.mondomaine.com', 'monutilisateur',
->             PASSWORD('monmotdepasse'),...);
mysql> FLUSH PRIVILEGES;

5-6-3 - Supprimer un compte utilisateur de MySQL

Pour supprimer un compte, utilisez la commande DROP USER, qui a été ajoutée en MySQL 4.1.1. Pour les anciennes versions de MySQL, utilisez la commande DELETE. La suppression de compte est décrite dans la section Section 13.5.1.2, « Effacer des utilisateurs MySQL ».

5-6-4 - Limiter les ressources utilisateur

Jusqu'à la version 4.0.2, la seule méthode possible pour limiter l'utilisation des ressources serveur MySQL était de configurer la variable de démarrage max_user_connections avec une valeur non nulle. De même, le nombre de connexions simultanées pouvait être limité pour un compte, mais pas les opérations réalisables, une fois l'utilisateur connecté. Ces deux types de contrôles sont importants pour les administrateurs système et les fournisseurs de services.

Depuis MySQL 4.0.2, il est possible de limiter certaines ressources accessibles à un utilisateur possible :

- nombre de requêtes par heure : toutes les commandes qu'un utilisateur peut exécuter ;

- nombre de modifications par heure : toute commande qui implique la modification d'une table ou d'une base ;

- nombre de connexions réalisées par heure : le nombre de nouvelles connexions par heure.

Toute commande que le client émet compte pour la limite de requêtes. Seules les commandes qui modifient les tables ou bases comptant pour la limite de modifications.

Pour utiliser cette fonctionnalité, la table user de la base mysql doit contenir les colonnes nécessaires pour stocker les limites. Les limites doivent être stockées dans les colonnes max_questions, max_updates et max_connections. Si votre table user ne dispose pas de ces colonnes, elle doit être mise à jour. Voyez Section 2.6.7, « Mise à jour des tables de droits ».

Par défaut, les utilisateurs ne sont pas limités dans l'utilisation des ressources ci-dessus, à moins que des limites ne leur soient imposées. Ces limites peuvent être configurées uniquement via la commande GRANT (*.*), avec cette syntaxe :

pour spécifier des limites de ressources avec la commande GRANT
utilisez la clause WITH pour chaque ressource que vous voulez limiter. Par exemple, pour créer un nouveau compte avec un accès à la base customer, mais sans abuser, utilisez ceci :

mysql> GRANT ALL ON customer.* TO 'francis'@'localhost'
->     IDENTIFIED BY 'frank'
->     WITH MAX_QUERIES_PER_HOUR 20
->          MAX_UPDATES_PER_HOUR 10
->          MAX_CONNECTIONS_PER_HOUR 5;

Les types de limites n'ont pas besoin d'être tous appelés avec WITH, mais ils peuvent être appelés dans n'importe quel ordre. La valeur de chaque limite doit être un entier représentant le nombre autorisé par heure. Si la commande GRANT n'a pas de clause WITH, les limites valent alors 0, c'est-à-dire qu'il n'y a pas de limite ;

pour configurer et changer les limites d'un compte existant
utilisez la commande GRANT USAGE au niveau global, avec ON *.*. La commande suivante modifie la limite de requêtes du compte francis à 100 :

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'
->     WITH MAX_QUERIES_PER_HOUR 100;

Cette commande ne touche pas aux droits du compte : elle ne modifie que les valeurs des limites ;

pour supprimer une limite existante
donnez-lui la valeur de 0. Par exemple, pour supprimer la limite de connexions de francis, utilisez cette commande :

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'
->     WITH MAX_CONNECTIONS_PER_HOUR 0;

Le compteur d'utilisation des ressources se met en marche dès que la limite n'est pas nulle.

Durant le fonctionnement du serveur, les ressources utilisées sont comptées. Si le compte atteint la limite de connexions dans un intervalle d'une heure, les connexions suivantes sont rejetées, jusqu'à la fin de l'heure. Similairement, si le compte atteint la limite de requête dans un intervalle d'une heure, les requêtes suivantes sont rejetées, jusqu'à la fin de l'heure. Dans tous les cas, un message approprié est affiché.

Le compte de ressource est fait par compte, et non pas client. Par exemple, si votre compte a une limite de requêtes de 50, vous ne pouvez pas augmenter votre limite à 100 en vous connectant deux fois. Les requêtes issues des deux connexions seront alors comptées ensemble.

Le compte courant d'utilisation peut être remis à zéro, globalement, ou individuellement.

- Pour remettre à zéro les compteurs pour tous les comptes, faites un FLUSH USER_RESOURCES. Les comptes sont remis à zéro au moment du rechargement des tables de droits : par exemple, avec la commande FLUSH PRIVILEGES ou la commande mysqladmin reload.

- Les comptes individuels peuvent être remis à zéro en donnant de nouvelles limites ou en changeant les droits. Pour cela, utilisez GRANT USAGE tel que décrit précédemment, en donnant la même limite que celle qui est configurée.

5-6-5 - Configurer les mots de passe

Les mots de passe peuvent être assignés en ligne de commande avec l'utilitaire mysqladmin :

shell> mysqladmin -u user_name -h host_name password "newpwd"

Le compte qui est remis à zéro par cette commande est celui pour lequel une ligne de la table user qui correspond à la valeur user_name dans la colonne User et l'hôte client d'où vous vous connectez dans la colonne Host.

Un autre moyen pour assigner un mot de passe à un compte est d'utiliser la commande SET PASSWORD :

mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');

Seuls les utilisateurs root ayant des accès en écriture à la base mysql peuvent changer les mots de passe des autres utilisateurs. Si vous n'êtes pas connectés en tant qu'utilisateur anonyme, vous pouvez modifier votre propre mot de passe en omettant la clause FOR :

mysql> SET PASSWORD = PASSWORD('biscuit');

Vous pouvez aussi utiliser la commande GRANT USAGE au niveau global (ON *.*) pour assigner un mot de passe sans affecter les droits du compte :

mysql> GRANT USAGE ON *.* TO 'jeffrey'@'%' IDENTIFIED BY 'biscuit';

Même s'il est généralement préférable d'assigner un mot de passe en utilisant une des méthodes précédentes, vous pouvez aussi modifier la table user directement.

- Pour établir un mot de passe lors de la création d'un compte, fournissez une valeur à la colonne Password :

shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('%','jeffrey','biscuit');
mysql> FLUSH PRIVILEGES;

- Pour changer le mot de passe d'un compte existant, utilisez la commande UPDATE pour modifier la valeur de la colonne Password :

shell> mysql -u root mysql
mysql> UPDATE user SET Password = PASSWORD('bagel')
-> WHERE Host = '%' AND User = 'francis';
mysql> FLUSH PRIVILEGES;

Lorsque vous assignez un mot de passe à un compte avec SET PASSWORD, INSERT, ou UPDATE, vous devez utiliser la fonction PASSWORD() pour le chiffrer. La seule exception est que vous n'avez pas besoin d'utiliser PASSWORD() si le mot de passe est vide. PASSWORD() est nécessaire, car la table user stocke les mots de passe sous forme chiffrée, et non en texte clair. Si vous oubliez cela, vous risquez d'avoir des mots de passe de la forme :

shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('%','jeffrey','biscuit');
mysql> FLUSH PRIVILEGES;

Le résultat est que la valeur 'biscuit' est stockée dans la colonne de mot de passe de la table user. Lorsque l'utilisateur jeffrey tente de se connecter au serveur avec ce mot de passe, le client mysql compare ce mot de passe chiffré avec sa version en clair stockée dans la table user. Cependant, la version stockée est la valeur littérale de 'biscuit', et la comparaison échoue, le serveur rejette la connexion :

shell> mysql -u jeffrey -pbiscuit test
Access denied

Si vous modifiez les mots de passe en utilisant la commande GRANT ... IDENTIFIED BY ou la commande mysqladmin password, la fonction PASSWORD() n'est pas nécessaire. Ces commandes assureront le chiffrement de votre mot de passe pour vous, ce qui vous permet de spécifier le mot de passe de 'biscuit' comme ceci :

Note : PASSWORD() n'effectue pas le chiffrement du mot de passe de la même façon qu'Unix. Voir Section 5.6.1, « Nom d'utilisateurs MySQL et mots de passe ».

5-6-6 - Garder vos mots de passe en lieu sûr

Il est recommandé de ne pas placer votre mot de passe là où il risque d'être découvert par d'autres personnes. Les méthodes que vous utiliserez pour spécifier votre mot de passe lors de la connexion avec le client sont listées ici, avec les risques liés à chaque méthode.

- Utilisez l'option -p ou --password (sans la valeur du mot de passe). Dans ce cas, le programme client va solliciter la saisie du mot de passe depuis le terminal :

shell> mysql -u user_name -p
Enter password: ********

Cette méthode est pratique, mais peu sûre, car le mot de passe est visible par les programmes système tels que ps qui peuvent être appelés par les autres utilisateurs. Les clients MySQL remplacent généralement les arguments de la ligne de commande par des zéros durant leur initialisation, mais il y a un court instant où la valeur est visible.

- Utilisez les options -p ou --password sans valeur de mot de passe. Dans ce cas, le client va solliciter explicitement le mot de passe du terminal :

shell> mysql -u francis
Enter password: ********

Les caractères '*' représentent votre mot de passe. Le mot de passe n'est pas affiché en clair lors de votre saisie.

Cette méthode est bien plus sûre pour saisir votre mot de passe qu'en le spécifiant directement en ligne de commande, car il n'est pas visible des autres utilisateurs. Cependant, cette méthode n'est possible qu'avec les programmes que vous utilisez en mode interactif. Si vous voulez invoquer le client depuis un script qui s'exécute de manière non interactive, il n'y aura pas d'opportunité pour saisir ce mot de passe dans le terminal. Sur certains systèmes, vous pourriez même voir la première ligne de votre script lue et interprétée comme votre mot de passe, incorrectement.

- Stockez votre mot de passe dans le fichier de configuration. Par exemple, vous pouvez lister votre mot de passe dans la section [client] du fichier .my.cnf dans votre dossier personnel :

[client]
password=mot_de_passe

Si vous stockez ce mot de passe dans le fichier .my.cnf, le fichier ne doit pas être lisible par le groupe ou par les autres utilisateurs, ou encore accessible en écriture : seul le propriétaire de ce fichier doit avoir ces droits. Assurez-vous que les droits d'accès au fichier soient 400 ou 600. Par exemple :

shell> chmod 600 .my.cnf

Section 4.3.2, « Fichier d'options my.cnf » présente les options pour plus de détails.

- Vous pouvez stocker votre mot de passe dans la variable d'environnement MYSQL_PWD, mais cette méthode doit être considérée comme extrêmement peu sûre, et doit être évitée autant que possible. Certaines versions de la commande en ligne ps incluent une option pour afficher les variables d'environnement des processus : votre mot de passe sera alors facilement accessible, et en texte clair, si vous configurez la commande MYSQL_PWD. Même sur les systèmes sans une telle version de la commande ps, il est peu recommandé de supposer que les variables d'environnement sont inaccessibles par une méthode quelconque. Voir Annexe E, Variables d'environnement.

En conclusion, la méthode la plus sûre est encore de laisser le client vous demander le mot de passe, ou de le spécifier dans le fichier de configuration.

5-6-7 - Utilisation des connexions sécurisées

5-6-7-1 - Introduction aux connexions sécurisées

Disponible depuis la version 4.0.0, MySQL supporte les connexions sécurisées. Pour comprendre comment MySQL utilise SSL, il est nécessaire de comprendre les concepts SSL et X509 de base. Ceux qui les connaissent peuvent aisément sauter ce chapitre.

Par défaut, MySQL utilise une connexion en clair entre le client et le serveur. Cela signifie qu'une personne peut surveiller votre trafic, et lire les données échangées. Cette personne pourrait aussi modifier les données qui transitent entre le client et le serveur. Parfois, vous aurez besoin d'échanger des informations sur un réseau public, mais en sécurisant ces informations. Dans ce cas, utiliser une connexion sans protection est inacceptable.

SSL est un protocole qui utilise différents algorithmes de chiffrement pour s'assurer que les données qui transitent par un réseau public peuvent être considérées comme fiables. Ce protocole dispose de méthodes pour s'assurer que les données n'ont pas été modifiées, que ce soit par une altération, une perte ou une répétition des données. SSL inclut aussi des algorithmes pour reconnaître et fournit des outils de vérifications d'identité, pris en charge par le standard X509.

Le chiffrement est une méthode pour rendre des données illisibles. En fait, les pratiques actuelles requièrent d'autres éléments de sécurité issus des algorithmes de chiffrement. Ils doivent savoir résister à de nombreux types d'attaques, comme la modification de l'ordre des messages ou les répétitions inopinées.

X509 est un standard qui rend possible l'identification d'une personne sur l'Internet. Il est particulièrement utilisé pour les applications e-commerce. En termes simples, il doit y avoir une entreprise (appelée l'« autorité de certification ») qui assigne un certificat électronique à toute personne qui en a besoin. Ces certificats utilisent un chiffrement asymétrique qui exploite deux clés de chiffrement, une clé publique et une clé privée. Le propriétaire d'un certificat peut prouver son identité en montrant son certificat à l'autre partie. Un certificat est constitué de la clé publique du propriétaire. Toute donnée qui est chiffrée avec cette clé publique doit être déchiffrée avec la clé secrète correspondante, qui est détenue par le propriétaire du certificat.

MySQL n'utilise pas les connexions chiffrées par défaut, car cela ralentit considérablement le protocole de communication. Toute fonctionnalité supplémentaire requiert du travail supplémentaire de la part du serveur, et chiffrer des données est une tâche particulièrement coûteuse, qui peut ralentir considérablement les tâches principales de MySQL. Par défaut, MySQL est paramétré pour être aussi rapide que possible.

Si vous avez besoin de plus d'informations sur SSL, X509 ou le chiffrement, utilisez votre moteur de recherche préféré sur Internet, et utilisez ces mots clés pour avoir plus de détails.

5-6-7-2 - Prérequis aux connexions sécurisées

Pour utiliser les connexions SSL entre le serveur MySQL et les clients, vous devez avoir le support de OpenSSL et votre version de MySQL doit être 4.0.0 ou plus récente.

Pour faire fonctionner les connexions sécurisées avec MySQL, vous devez disposer de ceci :

1. Installation de la bibliothèque d'OpenSSL. Nous avons testé MySQL avec OpenSSL 0.9.6. http://www.openssl.org/ ;

2. Lorsque vous configurez MySQL, utilisez le script configure avec les options --with-vio et --with-openssl ;

3. Assurez-vous que vous avez une version de la table mysql.user à jour. Ceci est nécessaire si vos tables de droits proviennent d'une version de MySQL antérieure à la version 4.0.0. La procédure de mise à jour est décrite dans Section 2.6.7, « Mise à jour des tables de droits » ;

4. Vous pouvez vérifier que vous possédez un serveur mysqld qui supporte OpenSSL en examinant le résultat de la commande SHOW VARIABLES LIKE 'have_openssl' :

mysql> SHOW VARIABLES LIKE 'have_openssl';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl  | YES   |
+---------------+-------+

elle doit retourner YES.

5-6-7-3 - Configurer les certificats SSL pour MySQL

Voici un exemple de configuration de certificats SSL pour MySQL :

DIR=`pwd`/openssl
PRIV=$DIR/private

mkdir $DIR $PRIV $DIR/newcerts
cp /usr/share/ssl/openssl.cnf $DIR
replace ./demoCA $DIR -- $DIR/openssl.cnf

# Créez les dossiers nécessaires : $database, $serial et $new_certs_dir
# optionnel

touch $DIR/index.txt
echo "01" > $DIR/serial

#
# Génération du certificat d'autorité (CA)
#

openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem \
-config $DIR/openssl.cnf

# Exemple de résultat :
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ................++++++
# .........++++++
# writing new private key to '/home/monty/openssl/private/cakey.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL admin
# Email Address []:

#
# Création des clés et requêtes serveur
#
openssl req -new -keyout $DIR/server-key.pem -out \
$DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf

# Exemple de résultat :
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ..++++++
# ..........++++++
# writing new private key to '/home/monty/openssl/server-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL server
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Supprimez la passe-phrase de la clé (optionnel)
#

openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem

#
# Signez le certificat serveur
#
openssl ca  -policy policy_anything -out $DIR/server-cert.pem \
-config $DIR/openssl.cnf -infiles $DIR/server-req.pem

# Exemple de résultat :
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL admin'
# Certificate is to be certified until Sep 13 14:22:46 2003 GMT (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Créez les clés et requêtes client
#
openssl req -new -keyout $DIR/client-key.pem -out \
$DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf

# Exemple de résultat :
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# .....................................++++++
# .............................................++++++
# writing new private key to '/home/monty/openssl/client-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be incorporated
# into your certificate request.
# What you are about to enter is what is called a Distinguished Name or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL user
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Supprimez la passe-phrase de la clé (optionnel)
#
openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem

#
# Signez le certificat client
#

openssl ca  -policy policy_anything -out $DIR/client-cert.pem \
-config $DIR/openssl.cnf -infiles $DIR/client-req.pem

# Exemple de résultat :
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL user'
# Certificate is to be certified until Sep 13 16:45:17 2003 GMT (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Créez le fichier my.cnf que vous pourrez utiliser pour tester les différents certificats
#

cnf=""
cnf="$cnf [client]"
cnf="$cnf ssl-ca=$DIR/cacert.pem"
cnf="$cnf ssl-cert=$DIR/client-cert.pem"
cnf="$cnf ssl-key=$DIR/client-key.pem"
cnf="$cnf [mysqld]"
cnf="$cnf ssl-ca=$DIR/cacert.pem"
cnf="$cnf ssl-cert=$DIR/server-cert.pem"
cnf="$cnf ssl-key=$DIR/server-key.pem"
echo $cnf | replace " " '
' > $DIR/my.cnf

#
# To test MySQL

mysqld --defaults-file=$DIR/my.cnf &

mysql --defaults-file=$DIR/my.cnf

Pour tester les connexions SSL, lancez le serveur comme ceci, où $DIR est le dossier où le fichier de configuration my.cnf est situé :

shell> mysqld --defaults-file=$DIR/my.cnf &

Puis, lancez le programme client en utilisant le même fichier d'options :

shell> mysql --defaults-file=$DIR/my.cnf

Si vous avez une distribution source MySQL, vous pouvez aussi tester votre configuration en modifiant le fichier my.cnf précédent, pour utiliser les certificats et fichiers de clés SSL de la distribution.

5-6-7-4 - Options de GRANT avec SSL

MySQL peut vérifier les certificats X509 en plus de la combinaison habituelle de nom d'utilisateur et mot de passe. Toutes les options habituelles sont toujours nécessaires (nom d'utilisateur, masque d'adresse IP, nom de base de données, nom de table). Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

Voici différentes possibilités pour limiter les connexions.

- Sans aucune option SSL ou X509, toutes les connexions chiffrées ou non chiffrées sont autorisées si le nom d'utilisateur et le mot de passe sont valides.

- L'option REQUIRE SSL requiert que les connexions soient chiffrées avec SSL. Notez que cette option peut être omise s'il n'y a pas de ligne ACL qui autorise une connexion sans SSL.

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret" REQUIRE SSL;

- REQUIRE X509 impose au client d'avoir un certificat valide, mais le certificat lui-même est de peu d'importance. La seule restriction est qu'il doit être possible de vérifier la signature avec une des autorités de certification.

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret" REQUIRE X509;

- REQUIRE ISSUER "issuer" restreint les tentatives de connexion : le client doit se présenter avec un certificat X509 valide, émis par l'autorité de certification "issuer". Utiliser un certificat X509 implique obligatoirement des chiffrements, donc l'option SSL est sous-entendue.

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret"
-> REQUIRE ISSUER "C=FI, ST=Some-State, L=Helsinki,
"> O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com";

- REQUIRE SUBJECT "subject" impose au client d'avoir un certificat X509 valide, avec le sujet "subject". Si le client présente un certificat valide, mais que le "subject" est différent, la connexion est refusée.

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret"
-> REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
"> O=MySQL demo client certificate,
"> CN=Tonu Samuel/Email=tonu@mysql.com";

- REQUIRE CIPHER "cipher" est utilisé pour s'assurer que les chiffrements sont suffisamment robustes, et que la bonne longueur de clé est utilisée. SSL lui-même peut être faible si des algorithmes sont utilisés avec des clés courtes. En utilisant cette option, il est possible d'imposer la méthode de chiffrement avec la connexion.

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret"
-> REQUIRE CIPHER "EDH-RSA-DES-CBC3-SHA";

Les options SUBJECT, ISSUER et CIPHER peuvent être combinées avec la clause REQUIRE comme ceci :

mysql> GRANT ALL PRIVILEGES ON test.* TO root@localhost
-> IDENTIFIED BY "goodsecret"
-> REQUIRE SUBJECT "C=EE, ST=Some-State, L=Tallinn,
"> O=MySQL demo client certificate,
"> CN=Tonu Samuel/Email=tonu@mysql.com"
-> AND ISSUER "C=FI, ST=Some-State, L=Helsinki,
"> O=MySQL Finland AB, CN=Tonu Samuel/Email=tonu@mysql.com"
-> AND CIPHER "EDH-RSA-DES-CBC3-SHA";

Depuis MySQL 4.0.4, le mot clé AND est optionnel, entre les options REQUIRE.

L'ordre de ces options n'a pas d'importance, mais aucune option ne peut être spécifiée deux fois.

5-6-7-5 - Options SSL en ligne de commande

La table suivante liste les différentes options que vous pouvez utiliser avec SSL, les fichiers de certificats et de clés. Ces options sont disponibles depuis MySQL 4.0. Elles peuvent être spécifiées en ligne de commande ou bien dans le fichier d'options.

- --ssl

Pour le serveur, indique que le serveur autorise les connexions SSL. Pour le client, permet au logiciel de se connecter au serveur en utilisant le protocole SSL. Cette option seule n'est pas suffisante pour que la connexion soit sécurisée par SSL. Vous devez aussi spécifier les options --ssl-ca, --ssl-cert et --ssl-key.

Cette option est plus souvent utilisée que sa forme contraire, pour indiquer que SSL ne doit pas être utilisé. Pour cela, spécifiez l'option sous la forme --skip-ssl ou --ssl=0.

Notez que cette option ne requiert pas de connexion SSL. Par exemple, si le serveur ou le client sont compilés sans le support SSL, une connexion sans chiffrement sera utilisée.

Une méthode pour s'assurer que la connexion sera bien sécurisée par SSL est de créer un compte sur le serveur, avec l'option REQUIRE SSL dans la commande GRANT. Utilisez alors ce compte pour vous connecter au serveur, avec le serveur et le client qui disposent du support SSL.

Vous pouvez utiliser cette option pour indiquer que la connexion ne doit pas être SSL. Pour faire cela, spécifiez l'option --skip-ssl ou --ssl=0.

- --ssl-ca=file_name

Le chemin jusqu'au fichier avec une liste des autorités de certifications SSL connues.

- --ssl-capath=directory_name

Le chemin jusqu'au dossier qui contient les certificats SSL au format PEM.

- --ssl-cert=file_name

Le nom du fichier de certificat SSL à utiliser pour établir une connexion sécurisée.

- --ssl-cipher=cipher_list

Une liste de chiffrements autorisés, à utiliser avec SSL. cipher_list a le même format que la commande openssl ciphers.

Exemple : --ssl-cipher=ALL:-AES:-EXP

- --ssl-key=file_name

Le nom du fichier de la clé SSL à utiliser pour établir une connexion sécurisée.

5-6-7-6 - Connexion à MySQL à distance avec Windows et SSH

Voici une note pour connecter un serveur MySQL avec une connexion sécurisée grâce à SSH (de David Carlson <dcarlson@mplcomm.com>).

- Installez un client SSH pour votre machine Windows. En tant qu'utilisateur, le meilleur que je connaisse est celui de SecureCRT de http://www.vandyke.com/. Une autre option est f-secure de http://www.f-secure.com/. Vous pouvez aussi en trouver d'autres gratuits avec Google à http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cryptography/SSH/Clients/Windows/.

- Démarrez votre client SSH Windows. Spécifiez Host_Name = yourmysqlserver_URL_or_IP. Spécifiez userid=your_userid pour vous loger dans votre serveur (probablement avec un mot de passe et un nom d'utilisateur différent).

- Configurez le forward de port. Faites soit un forward distant (spécifiez local_port: 3306, remote_host: yourmysqlservername_or_ip, remote_port: 3306 ) soit un forward local (spécifiez port: 3306, host: localhost, remote port: 3306).

- Sauvez le tout, sinon vous devrez le refaire la prochaine fois.

- Connectez-vous à votre serveur avec la session SSH que vous venez de créer.

- Sous votre machine Windows, démarrez une application ODBC (comme Access).

- Créez un nouveau fichier dans Windows et reliez-le avec MySQL en utilisant le pilote ODBC de la même façon que vous le feriez habituellement, hormis le fait que vous devrez taper localhost comme hôte serveur au lieu de yourmysqlservername.

Vous avez maintenant une connexion ODBC avec un serveur MySQL distant, et sécurisée avec SSH.

5-7 - Prévention des désastres et restauration

Cette section présente comment créer une sauvegarde de base de données, et comment assurer la maintenance des tables. La syntaxe des commandes SQL est décrite dans la section Section 13.5, « Référence de langage d'administration de la base de données ».

5-7-1 - Sauvegardes de base de données

Comme les tables MySQL sont stockées sous forme de fichiers, il est facile d'en faire une sauvegarde. Pour avoir une sauvegarde consistante, faites un LOCK TABLES sur les tables concernées suivi d'un FLUSH TABLES pour celles-ci. Voyez Section 13.4.5, « Syntaxe de LOCK TABLES/UNLOCK TABLES » et Section 13.5.4.2, « Syntaxe de FLUSH ». Vous n'avez besoin que d'un verrou en lecture, cela permet aux autres threads de continuer à effectuer des requêtes sur les tables dont vous faites la copie des fichiers dans le dossier des bases de données. FLUSH TABLE est requise pour s'assurer que toutes les pages d'index actifs soient écrits sur le disque avant de commencer la sauvegarde.

Si vous voulez faire une sauvegarde d'une table avec SQL, vous pouvez utiliser SELECT INTO OUTFILE ou BACKUP TABLE. Voyez Section 13.1.7, « Syntaxe de SELECT » et Section 13.5.2.2, « Syntaxe de BACKUP TABLE ».

Une autre façon de sauvegarder une base de données est d'utiliser l'utilitaire mysqldump ou le script mysqlhotcopy. Voyez Section 8.8, « mysqldump, sauvegarde des structures de tables et les données » et Section 8.9, « mysqlhotcopy, copier les bases et tables MySQL ».

1. Effectuez une sauvegarde complète de votre base de données :

shell> mysqldump --tab=/chemin/vers/un/dossier --opt --all

ou

shell> mysqlhotcopy base /chemin/vers/un/dossier

Vous pouvez aussi copier tout simplement tous les fichiers de tables (les fichiers *.frm, *.MYD, et *.MYI) du moment que le serveur ne met rien à jour. Le script mysqlhotcopy utilise cette méthode.

2. Arrêtez mysqld si il est en marche, puis démarrez-le avec l'option --log-update[=nom_fichier]. Voir Section 5.9.3, « Le log de modification ». Le ou les fichiers de log fournissent les informations dont vous avez besoin pour répliquer les modifications de la base de données qui sont subséquentes au moment où vous avez exécuté mysqldump.

Si votre serveur MySQL est un esclave, quelle que soit la sauvegarde que vous utilisez, lorsque vous sauvez vos données sur votre esclave, vous devez aussi sauver les fichiers master.info et relay-log.info, qui sont nécessaires pour relancer la réplication après la restauration des données de l'esclave. Si votre esclave doit traiter des commandes LOAD DATA INFILE, vous devez aussi sauver les fichiers nommés SQL_LOAD-*, qui sont dans le dossier spécifié par --slave-load-tmpdir. Ce dossier vaut par défaut la valeur de la variable tmpdir, si elle n'est pas spécifiée. L'esclave aura besoin de ces fichiers pour relancer la réplication d'une opération LOAD DATA INFILE interrompue.

Si vous avez besoin de restaurer quelque chose, essayez d'abord de restaurer vos tables avec REPAIR TABLE ou myisamchk -r en premier. Cela devrait fonctionner dans 99.9 % des cas. Si myisamchk ne réussit pas, essayez la procédure suivante (cela ne fonctionnera que si vous avez démarré MySQL avec --log-update, Section 5.9.4, « Le log binaire ») :

1. Restaurez la sauvegarde originale de mysqldump ;

2. Exécutez la commande suivante pour remettre en marche les mises à jour dans le log binaire :

shell> mysqlbinlog hostname-bin.[0-9]* | mysql

Dans votre cas, vous voudrez peut-être n'exécuter que certains logs binaires, depuis certaines positions : par exemple, depuis la date de la sauvegarde que vous avez restaurée, hormis quelques requêtes problématiques. Voyez Section 8.5, « mysqlbinlog, Exécuter des requêtes dans le log binaire » pour plus d'informations sur l'utilitaire mysqlbinlog, et comment l'utiliser.

Si vous utilisez le journal des mises à jour (qui a été supprimé en MySQL 5.0.0) vous pouvez utiliser :

shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql

ls est utilisée pour avoir tous les fichiers de mise à jour dans le bon ordre.

Vous pouvez aussi faire des sauvegardes sélectives de fichiers individuels :

- exportez la table avec SELECT * INTO OUTFILE 'nom_fichier' FROM nom_de_table ;

- restaurez avec LOAD DATA INFILE 'nom_fichier' REPLACE .... Pour éviter les lignes dupliquées, vous aurez besoin d'une PRIMARY KEY ou une clé UNIQUE dans la table. Le mot clé REPLACE fait que les anciens enregistrements sont remplacés par les nouveaux lorsque l'un d'eux duplique un ancien sur une valeur de clé unique.

Si vous obtenez des problèmes de performances sur votre système, vous pouvez les contourner en mettant en place une réplication et faisant les copies sur l'esclave au lieu du maître. Voir Section 6.1, « Introduction à la réplication ».

Si vous utilisez un système de fichiers Veritas, vous pourrez faire :

1. À partir d'un client (ou de Perl), exécutez : FLUSH TABLES WITH READ LOCK ;

2. À partir d'un autre Shell, exécutez : mount vxfs snapshot ;

3. Depuis le premier client, exécutez : UNLOCK TABLES ;

4. Copiez les fichiers à partir de la sauvegarde ;

5. Démontez snapshot.

5-7-2 - Exemples de stratégie de sauvegarde et restauration

Cette section présente une procédure pour effectuer des sauvegardes qui vous permettent de retrouver vos données après différents types de problèmes :

- arrêt du système d'exploitation ;

- problème d'alimentation électrique ;

- problème du système de fichiers ;

- problème matériel : disque dur, carte mère, etc.

Les instructions suivantes requièrent l'utilisation de la version minimale de MySQL 4.1.8, car certaines options de mysqldump utilisées ici ne sont pas disponibles dans les précédentes versions.

Les commandes d'exemples n'incluent pas les options telles que --user et --password avec les utilitaires mysqldump et mysql. Il vous faudra les ajouter en fonction des besoins, pour que MySQL puisse se connecter au serveur.

Nous considèrerons les données stockées dans une table de moteur InnoDB, qui supporte les transactions et la restauration automatique. Nous supposerons que le serveur MySQL est en charge au moment de la panne. Si ce n'est pas le cas, aucune restauration ne sera nécessaire.

Dans les cas de panne du système d'exploitation ou de l'alimentation électrique, on peut supposer que les disques de données MySQL sont toujours disponibles après un redémarrage. Les fichiers de données InnoDB sont analysés, et à partir des logs, on peut retrouver la liste des transactions archivées et non archivées, qui n'ont pas encore été écrites sur le disque. Le moteur de tables va alors annuler automatiquement les transactions qui n'ont pas été terminées. Le détail des opérations du processus de restauration est fourni à l'administrateur dans le fichier de logs d'erreurs de MySQL. Voici un extrait :

InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

Dans le cas d'une panne du système de fichiers ou du matériel, nous pouvons supposer que les données MySQL ne sont plus disponibles après le redémarrage. Cela signifie que MySQL ne pourra pas démarrer correctement, car certains blocs de données ne seront plus lisibles. Dans ce cas, il est nécessaire de formater le disque, d'en installer un nouveau ou bien de corriger le problème sous-jacent. Puis, il faut restaurer les données à partir des sauvegardes : cela signifie que nous devons avoir déjà fait des sauvegardes. Pour s'assurer que c'est le cas, voyons comment se déroule un processus de sauvegarde.

5-7-2-1 - Politique de sauvegarde

Nous savons tous que les sauvegardes doivent être programmées périodiquement. Les sauvegardes complètes, celles qui prélèvent toutes les données des bases, peuvent être réalisées avec plusieurs outils MySQL. Par exemple, InnoDB Hot Backup fournit un utilitaire de sauvegarde en ligne et non bloquant pour les fichiers InnoDB, et mysqldump fournit un outil de sauvegarde logique. Cette section utilise mysqldump.

Supposons que nous souhaitons réaliser une sauvegarde le dimanche, à une heure du matin, lorsque la charge sur le serveur est au plus bas. La commande suivante va faire une sauvegarde de toutes nos tables InnoDB, dans toutes les bases :

shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql

C'est un outil de sauvegarde en ligne, non bloquant, qui ne perturbe pas les opérations sur les tables. Nous avons supposé plus haut que nos tables utilisent le moteur InnoDB : l'option --single-transaction utilise une lecture cohérente, et garantit la stabilité des données prélevées par mysqldump. Les modifications peuvent être faites par d'autres clients sur les tables InnoDB sans que la commande mysqldump ne le perçoive. Si nous avons d'autres types de tables, nous devons aussi supposer qu'elles ne changeront pas durant la sauvegarde. Par exemple, pour une table MyISAM dans la base mysql, nous devons supposer qu'aucun administrateur ne fera de modification aux comptes MySQL durant la sauvegarde.

Le fichier .sql résultant, produit par mysqldump contient les commandes SQL INSERT qui peuvent être utilisées pour recharger les tables ultérieurement.

Les sauvegardes complètes sont nécessaires, mais elles ne sont pas toujours pratiques. Elles produisent de très grands fichiers de données, et prennent du temps à s'exécuter. Elles ne sont pas optimales, car chaque sauvegarde inclut toutes les données, même celles qui n'ont pas évolué entre deux sauvegardes. Une fois qu'une sauvegarde initiale a été faite, les sauvegardes incrémentales sont bien plus optimales : elles génèrent des fichiers plus petits, et sont plus rapides à réaliser. L'inconvénient est que cette sauvegarde ne vous permettra pas de restaurer toutes vos données à partir de la sauvegarde complète : il vous faudra utiliser les sauvegardes incrémentales pour restaurer totalement votre base.

Pour réaliser des sauvegardes incrémentales, vous devez sauver les modifications incrémentales. Le serveur MySQL doit être lancé avec l'option --log-bin pour qu'il puisse stocker ces modifications au fur et à mesure des modifications des données. Cette option active le log binaire, ce qui fait que chaque commande qui modifie les données est enregistrée dans un fichier appelé le log binaire. Voyons le dossier de données de MySQL, une fois qu'il a été lancé avec l'option --log-bin. Nous y trouverons les fichiers suivants :

-rw-rw---- 1 guilhem  guilhem   1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem  guilhem         4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem  guilhem        79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem  guilhem       508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem  guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem  guilhem    998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem  guilhem       361 Nov 14 10:07 gbichot2-bin.index

À chaque fois que le serveur redémarre, MySQL crée un nouveau fichier de logs binaire, en utilisant le numéro de séquence suivant. Lorsque le serveur fonctionne, vous pouvez aussi lui dire de clore le fichier de logs, et d'en ouvrir un nouveau avec la commande SQL FLUSH LOGS ou bien avec la commande en ligne mysqladmin flush-logs. La commande mysqldump dispose aussi d'une option pour clore les fichiers de logs. Le fichier .index contient la liste de tous les fichiers de logs binaire du dossier de données. Ce fichier est utilisé durant les opérations de réplication.

Les fichiers de log binaire MySQL sont importants lors de restauration, car ils représentent des sauvegardes incrémentales. Si vous vous assurez de bien refermer les fichiers de log binaire lorsque vous réalisez une sauvegarde complète, alors les fichiers de logs binaire qui ont été créés après votre sauvegarde représentent les modifications incrémentales de vos données. Maintenant, modifions la commande mysqldump pour qu'elle referme les logs binaires lors de sauvegarde complète, et que le fichier de sauvegarde contienne les noms des nouveaux fichiers de logs :

shell> mysqldump --single-transaction --flush-logs --master-data=2
--all-databases > backup_sunday_1_PM.sql

Après avoir exécuté cette commande, le dossier de données contient un nouveau fichier de logs binaire, gbichot2-bin.000007. Le fichier .sql résultant contient les lignes suivantes :

-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;

Comme la commande mysqldump a fait une sauvegarde complète, ces lignes signifient deux choses :

- le fichier .sql contient toutes les modifications effectuées sur les données avant le fichier appelé gbichot2-bin.000007, ou plus récent ;

- toutes les modifications des données effectuées après la sauvegarde ne sont pas enregistrées dans le fichier .sql, mais sont présentes dans le fichier de logs binaire gbichot2-bin.000007.

Le lundi, à une heure du matin, nous pouvons créer une sauvegarde incrémentale en refermant les fichiers de log binaire, et en créant un nouveau fichier de logs. Par exemple, la commande mysqladmin flush-logs crée un fichier gbichot2-bin.000008. Toutes les modifications qui ont eu lieu entre dimanche, 1 heure et lundi, 1 heure sont stockées dans le fichier gbichot2-bin.000007. Cette sauvegarde incrémentale est importante, et il est recommandé de la stocker dans un endroit sûr. Par exemple, copiez-la sur une cassette ou un DVD, ou même sur une autre machine. Le mardi, à 1 heure, vous pouvez exécuter à nouveau la commande mysqladmin flush-logs. Toutes les opérations effectuées entre lundi, 1 heure et mardi, 1 heure sont dans le fichier gbichot2-bin.000008, qui doit être mis en sécurité.

Les logs binaires MySQL occupent de l'espace disque sur le serveur. Pour récupérer cet espace, supprimez-le de temps en temps. Pour le faire en toute sécurité, supprimez simplement les fichiers qui ne servent plus à rien, c'est-à-dire ceux qui sont antérieurs à la dernière sauvegarde complète :

shell> mysqldump --single-transaction --flush-logs --master-data=2
--all-databases --delete-master-logs > backup_sunday_1_PM.sql

Note : effacer les logs binaires avec la commande mysqldump --delete-master-logs peut être dangereux, car si le serveur est un maître de réplication, les esclaves pourraient ne pas avoir traité en totalité le contenu des logs binaires.

La description de la commande PURGE MASTER LOGS explique ce qui doit être vérifié avant d'effacer un fichier de logs binaire. Voir Section 13.6.1.1, « PURGE MASTER LOGS ».

5-7-2-2 - Utiliser les sauvegardes pour la restauration

Supposons maintenant qu'un crash catastrophique survienne le mercredi à 8 heures du matin, et qu'il faille utiliser les sauvegardes pour restaurer la base de données. Pour cela, il faut commencer par utiliser la première sauvegarde complète que nous avons : c'est celle de samedi, à 1 heure. Cette sauvegarde est un ensemble de commandes SQL : la restauration est très simple :

shell> mysql < backup_sunday_1_PM.sql

Après cela, les données sont celles que nous avions dimanche, à 1 heure. Pour appliquer les modifications qui ont eu lieu depuis cette date, nous devons utiliser les sauvegardes incrémentales, c'est-à-dire les fichiers de log binaire gbichot2-bin.000007 et gbichot2-bin.000008. Retrouvez-les dans vos documents de sauvegarde, puis, exécutez-les de cette manière :

shell> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql

Nous avons maintenant retrouvé les données dans leur état de mardi, à 1 heure, mais il manque encore les données entre cette date et le crash. Pour ne pas les avoir perdues, il faut que les logs aient été sauvés dans un volume sécurisé (disque RAID, SAN...), sur un serveur différent de celui qui a crashé : tout cela pour que le serveur n'ait pas détruit les logs durant le crash. Pour cela, nous pouvons lancer le serveur avec l'option --log-bin, et spécifier un chemin sur un volume physique séparé. De cette manière, les logs ne seront pas perdus, même si le dossier contenant les données est perdu. Si nous pouvons retrouver ces fichiers de log, nous aurons un fichier appelé gbichot2-bin.000009 et nous pouvons l'appliquer aux données pour obtenir l'état le plus proche du moment du crash.

5-7-2-3 - Résumé des stratégies de sauvegarde

Dans le cas d'un arrêt du système d'exploitation ou d'une panne de courant, InnoDB se charge lui-même du travail de restauration des données. Mais pour vous assurer un sommeil sans cauchemar, nous vous recommandons de suivre ces instructions :

- utilisez toujours MySQL avec l'option --log-bin, ou même avec --log-bin=log_name, où le fichier est placé sur un média sécuritaire, différent de celui sur lequel fonctionne le dossier de données. SI vous avez un tel lieu de stockage, c'est aussi bon pour l'équilibrage de la charge du disque, ce qui conduit a des améliorations de performances ;

- faites des sauvegardes périodiques, en utilisant la commande mysqldump pour réaliser des sauvegardes non bloquantes ;

- faites des sauvegardes incrémentales périodiques, en vidant les logs sur le disque, avec la commande SQL FLUSH LOGS ou la commande en ligne mysqladmin flush-logs.

5-7-3 - Utilisation de myisamchk pour la maintenance des tables et leur recouvrement

La section suivante discute de l'utilisation de myisamchk pour vérifier et réparer les tables MyISAM (les tables avec les fichiers .MYI et .MYD). Les mêmes concepts s'appliquent à isamchk pour vérifier et réparer les tables ISAM (les tables avec les fichiers .ISM et .ISD). Voir Chapitre 14, Moteurs de tables MySQL et types de table.

Vous pouvez utiliser myisamchk pour obtenir des informations sur les tables de votre base de données, pour analyser, réparer ou optimiser ces tables. Les sections suivantes décrivent comment appeler myisamchk (y compris les options), comment mettre en place une politique d'entretien, et comment utiliser myisamchk pour effectuer différentes opérations.

Même si la réparation d'une table avec myisamchk est sécuritaire, il est toujours préférable de faire une sauvegarde avant la réparation, ou toute autre opération de maintenance qui pourrait faire de nombreuses modifications dans la table.

Les opérations myisamchk qui affectent les index peuvent causer la recompilation des index FULLTEXT avec des paramètres qui ne sont pas les paramètres courants du serveur. Pour éviter cela, voyez la section Section 5.7.3.2, « Options générales de myisamchk ».

Dans de nombreux cas, vous pouvez trouver plus simple de faire l'entretien des tables avec des requêtes SQL qu'avec myisamchk :

- pour vérifier ou réparer les tables MyISAM, utilisez CHECK TABLE ou REPAIR TABLE ;

- pour optimiser les tables MyISAM, utilisez OPTIMIZE TABLE ;

- pour analyser les tables MyISAM, utilisez ANALYZE TABLE.

Ces commandes ont été ajoutées dans différentes versions, mais sont toutes disponibles depuis MySQL 3.23.14. Voyez Section 13.5.2.1, « Syntaxe de ANALYZE TABLE », Section 13.5.2.3, « Syntaxe de CHECK TABLE », Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE », et Section 13.5.2.6, « Syntaxe de REPAIR TABLE ».

Les commandes peuvent être utilisées directement, ou via le client mysqlcheck, qui fournit une interface en ligne de commande.

Un avantage de ces commandes par rapport à myisamchk est que le serveur se charge de tout. Avec myisamchk, vous devez vous assurer que le serveur ne va pas utiliser les tables en même temps que vous. Sinon, il va y avoir des interférences entre myisamchk et le serveur.

5-7-3-1 - Syntaxe de l'utilitaire myisamchk

myisamchk s'exécute avec une commande de la forme :

shell> myisamchk [options] tbl_name

Les options spécifient ce que vous voulez que myisamchk fasse. Elles sont décrites dans ce chapitre. Vous pouvez aussi obtenir une liste d'options en invoquant le programme avec myisamchk --help. Sans option, myisamchk va simplement vérifier les tables. Pour obtenir plus d'informations ou pour demander à myisamchk de prendre des mesures correctives, il faut ajouter l'une des options listées ici.

tbl_name est la table que vous voulez réparer ou vérifier. Si vous exécutez myisamchk autre part que dans le dossier de données, vous devez spécifier le chemin jusqu'au fichier, car sinon, myisamchk n'aura aucune idée d'où chercher les données dans votre base. En fait, myisamchk ne se préoccupe pas du fait que le fichier que vous utilisez est dans le dossier de base ou pas : vous pouvez copier le fichier à réparer dans un autre dossier, et y faire les opérations d'entretien.

Vous pouvez spécifier plusieurs noms de tables à myisamchk si vous le voulez. Vous pouvez aussi spécifier un nom sous la forme d'un fichier d'index (avec l'option .MYI), qui vous permettra de spécifier toutes les tables dans un dossier en utilisant le schéma *.MYI. Par exemple, si vous êtes dans le dossier de données, vous pouvez spécifier toutes les tables dans le dossier comme ceci :

shell> myisamchk *.MYI

Si vous n'êtes pas dans le dossier de données, et que vous souhaitez vérifier toutes les tables, vous devez ajouter le chemin jusqu'au dossier :

shell> myisamchk /path/to/database_dir/*.MYI

Vous pouvez même vérifier toutes les tables de toutes les bases avec le chemin suivant :

shell> myisamchk /path/to/datadir/*/*.MYI

La méthode recommandée pour vérifier rapidement toutes les tables est :

myisamchk --silent --fast /path/to/datadir/*/*.MYI
isamchk --silent /path/to/datadir/*/*.ISM

Si vous voulez vérifier toutes les tables et réparer celles qui sont corrompues, vous pouvez utiliser la ligne suivante :

myisamchk --silent --force --fast --update-state -O key_buffer=64M \
-O sort_buffer=64M -O read_buffer=1M -O write_buffer=1M \
/path/to/datadir/*/*.MYI
isamchk --silent --force -O key_buffer=64M -O sort_buffer=64M \
-O read_buffer=1M -O write_buffer=1M /path/to/datadir/*/*.ISM

Ces commandes ci-dessus supposent que vous avez plus de 64 Mo de libres. Pour plus d'informations sur l'allocation de mémoire avec myisamchk, voyez la section Section 5.7.3.6, « Utilisation de la mémoire par myisamchk ».

Notez que si vous obtenez une erreur comme celle-ci :

myisamchk: warning: 1 clients is using or hasn't closed the table properly

Cela signifie que vous essayez de vérifier une table qui a été modifiée par un autre programme (comme le serveur mysqld) qui n'a pas encore refermé le fichier de table, ou que le fichier n'a pas été correctement refermé.

Si mysqld fonctionne, vous devez forcer la fermeture correcte des fichiers de tables avec la commande FLUSH TABLES, et vous assurer que personne n'utilise les tables durant vos opérations avec myisamchk. En MySQL version 3.23, la meilleure méthode pour éviter ce problème est d'utiliser la commande CHECK TABLE au lieu de myisamchk pour vérifier les tables.

5-7-3-2 - Options générales de myisamchk

Les options décrites dans cette section peuvent être utilisées pour toutes les maintenances de tables effectuées myisamchk. Les sections suivant celles-ci décrivent les options spécifiques à certaines opérations, comme la vérification et la réparation.

myisamchk supporte les options suivantes.

- --help, -?

Affiche le message d'aide, et termine le programme.

- --debug=debug_options, -# debug_options

Affiche le log de débogage. La chaîne debug_options vaut souvent : 'd:t:o,filename'.

- --silent, -s

Mode silencieux. Affiche uniquement les erreurs. Vous pouvez utiliser deux fois -s (-ss) pour que myisamchk soit très silencieux.

- --verbose, -v

Mode détaillé. Affiche plus d'informations. Vous pouvez combiner ce mode avec les options -d et -e. Utilisez -v plusieurs fois, (-vv, -vvv) pour plus de détails encore.

- --version, -V

Affiche la version et quitte.

- --wait, -w

Au lieu de s'arrêter avec une erreur si la table est verrouillée, le programme attend que la table soit libérée avant de continuer. Notez que si vous utilisez mysqld avec l'option --skip-external-locking, la table peut ne peut être verrouillée que par une autre commande myisamchk.

Vous pouvez aussi configurer les variables suivantes avec la syntaxe --var_name=value :

Variable

Valeur par défaut

decode_bits

9

ft_max_word_len

dépend de la version

ft_min_word_len

4

ft_stopword_file

liste par défaut

key_buffer_size

523264

myisam_block_size

1024

read_buffer_size

262136

sort_buffer_size

2097144

sort_key_blocks

16

write_buffer_size

262136

Il est aussi possible de configurer les variables avec les syntaxes --set-variable=var_name=value et -O var_name=value. Toutefois, cette syntaxe est obsolète depuis MySQL 4.0.

Les variables myisamchk possibles et leur valeur par défaut sont affichées par myisamchk --help :

sort_buffer_size sert lors de la réparation des index par tri des clés, qui est le mode utilisé par l'option --recover.

key_buffer_size sert lorsque vous vérifiez une table avec l'option --extend-check ou lorsque les clés sont réparées par insertion de lignes dans la table (comme lors des insertions normales). La réparation par buffer de clés est utilisée dans ces situations :

- vous utilisez l'option --safe-recover ;

- les fichiers temporaires utilisés pour trier les clés seraient deux fois plus gros que lors de la création directe du fichier. C'est souvent le cas lorsque vous avez de grandes clés pour les colonnes CHAR, VARCHAR et TEXT, car l'opération de tri a besoin de stocker la clé complète. Si vous avez beaucoup d'espace temporaire, vous pouvez forcer myisamchk à réparer en triant, en utilisant l'option --sort-recover.

La répartition par buffer de clés prend beaucoup moins d'espace disque, mais est bien plus lente.

Si vous voulez une réparation plus rapide, donnez à key_buffer_size et sort_buffer_size des valeurs représentant 25 % de votre mémoire. Vous pouvez leur donner de grandes valeurs, car une seule des deux variables est utilisée.

myisam_block_size est la taille des blocs d'index. Elle est disponible depuis MySQL 4.0.0.

Les variables ft_min_word_len et ft_max_word_len sont disponibles depuis MySQL 4.0.0. ft_stopword_file est disponible depuis MySQL 4.0.19.

ft_min_word_len et ft_max_word_len indiquent la taille minimum et maximum pour les index FULLTEXT. ft_stopword_file est le nom du fichier de mots ignorés. Ils doivent toujours être configurés.

Si vous utilisez myisamchk pour faire une opération qui modifie les index de tables (comme la répartition ou l'analyse), les index FULLTEXT sont reconstruits en utilisant les valeurs par défaut pour les tailles minimales et maximales, et pour le fichier de mots ignorés. Cela peut conduire à l'échec de requêtes.

Le problème survient lorsque ces paramètres ne sont connus que par le serveur. Elles ne sont pas stockées dans le fichier d'index MyISAM. Pour éviter ce problème si vous avez modifié la taille des mots ou le fichier de mots ignorés dans le serveur, pensez à spécifier les mêmes valeurs avec les options ft_min_word_len, ft_max_word_len et ft_stopword_file de myisamchk. Par exemple, si vous avez configuré une taille minimale de 3, vous pourrez réparer la table avec myisamchk comme ceci :

shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI

Pour vous assurer que myisamchk et le serveur utilisent les mêmes valeurs pour les paramètres des index en texte plein, vous pouvez placer ces valeurs dans les groupes [mysqld] et [myisamchk] du fichier d'options :

[mysqld]
ft_min_word_len=3

[myisamchk]
ft_min_word_len=3

Un substitut à l'utilisation de myisamchk est les commandes REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE et ALTER TABLE. Ces commandes sont effectuées par le serveur, qui sait comment traiter les paramétrages des index.

5-7-3-3 - Options de vérifications pour myisamchk

- -c, --check

Vérifie les erreurs d'une table. Ceci est l'opération par défaut de myisamchk si vous ne lui donnez aucune autre option.

- -e, --extend-check

Vérifie la table minutieusement (ce qui est un peu lent si vous avez des index). Cette option ne doit être utilisée que pour les cas extrêmes. Normalement, myisamchk ou myisamchk --medium-check devraient, dans la plupart des cas, être capables de trouver s'il y a des erreurs dans la table.

Si vous utilisez --extended-check et que vous avez beaucoup de mémoire, vous devez augmenter de beaucoup la valeur de key_buffer_size !

- -F, --fast

Ne vérifie que les tables qui n'ont pas été fermées proprement.

- -C, --check-only-changed

Ne vérifie que les tables qui ont changé depuis la dernière vérification.

- -f, --force

Redémarrez myisamchk avec -r (répare) sur la table, si myisamchk trouve une erreur dans la table.

- -i, --information

Affiche des statistiques à propos de la table vérifiée.

- -m, --medium-check

Plus rapide que --extended-check, mais ne trouve que 99.99 % des erreurs. Devrait, cependant, être bon pour la plupart des cas.

- -U, --update-state

Enregistre le fichier .MYI lorsque la table à été vérifiée ou a été corrompue. Cela devrait être utilisé pour tirer tous les avantages de l'option --check-only-changed, mais vous ne devez pas utiliser cette option si le serveur mysqld utilise cette table et que vous utilisez mysqld avec --skip-external-locking.

- -T, --read-only

Ne marque pas la table comme vérifiée. C'est pratique si vous utilisez myisamchk pour vérifier une table issue d'une autre application qui n'utilise pas les verrous. (Comme mysqld --skip-external-locking.)

5-7-3-4 - Options de réparation de myisamchk

Les options suivantes sont utilisées avec myisamchk et l'option de réparation -r ou -o.

- --backup, -B

Fait une sauvegarde du fichier .MYD, sous le nom filename-time.BAK.

- --character-sets-dir=path

Dossier qui contient les jeux de caractères. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --correct-checksum

Somme de contrôle correcte pour la table.

- --data-file-length=#, -D #

Taille maximale du fichier de données (lors de la recréation du fichier de données, et qu'il est complet).

- --extend-check, -e

Essaie de retrouver toutes les lignes possibles du fichier de données. Normalement, cette option va aussi découvrir beaucoup de lignes erronées. N'utilisez pas cette option si vous n'êtes pas totalement désespérés.

- --force, -f

Écrase les anciens fichiers temporaires (table_name.TMD) au lieu d'annuler.

- --keys-used=#, -k #

Si vous utilisez les tables ISAM, indique au gestionnaire de tables ISAM qu'il doit uniquement modifier les # premiers index. Si vous utilisez le gestionnaire de tables MyISAM, cette option indique quelles clés utiliser, et chaque bit binaire représente une clé (la première clé est le bit 0). Cela permet de réaliser des insertions plus rapides. Les index désactivés pourront être réactivés avec l'option myisamchk -r.

- --no-symlinks, -l

Ne pas suivre les lignes symboliques. Normalement, myisamchk répare les tables qu'un lien symbolique représente. Cette option n'existe pas en MySQL 4.0, car MySQL 4.0 ne va pas supprimer les liens symboliques durant la réparation.

- --parallel-recover, -p

Utilise la même technique que -r et -n, mais crée les clés avec des threads différents, en parallèle. Cette option a été ajoutée en MySQL 4.0.2. Ceci est du code alpha. Utilisez-le à vos risques et périls !

- --quick, -q

Réparation rapide, sans modifier le fichier de données. Il est possible d'ajouter l'option -q pour forcer myisamchk à modifier le fichier original en cas de clés doublons.

- --recover, -r

Peut réparer presque tout, sauf les clés uniques qui ne le sont plus (ce qui est extrêmement rare avec les tables ISAM/MyISAM). Si vous voulez restaurer une table, c'est l'option à utiliser en premier. Si myisamchk indique que la table ne peut pas être corrigée avec l'option -r, vous pouvez alors passer à l'option -o. Notez que dans le cas rarissime où -r, le fichier de données est toujours intact. Si vous avez beaucoup de mémoire, vous pouvez augmenter la taille du buffer sort_buffer_size !

- --safe-recover, -o

Utilise une ancienne méthode de restauration (lit toutes les lignes dans l'ordre, et modifie l'arbre d'index conformément pour les lignes trouvées). C'est une méthode qui est beaucoup plus lente que l'option -r, mais elle est capable de traiter certaines situations exceptionnelles que -r ne pourrait pas traiter. Cette méthode utilise aussi moins d'espace disque que -r. Normalement, vous devriez commencer à réparer avec l'option -r, et uniquement sur l'échec de cette option, passer à -o.

Si vous avez beaucoup de mémoire, vous devriez augmenter la taille du buffer de clés ! key_buffer_size !

- --set-character-set=name

Change le jeu de caractères utilisé par l'index.

- --sort-recover, -n

Force myisamchk à utiliser le tri pour résoudre les clés, même si le fichier temporaire doit être énorme.

- --tmpdir=path, -t path

Chemin pour stocker les fichiers temporaires. Si cette option n'est pas fournie, myisamchk va utiliser la variable d'environnement TMPDIR pour cela. Depuis MySQL 4.1, tmpdir peut prendre une liste de chemins différents, qui seront utilisés successivement, pour les fichiers temporaires. Le caractère de séparation des différents chemins est le deux-points sous Unix (':') et le point-virgule (';') sous Windows, NetWare et OS/2.

- --unpack, -u

Décompresse des données compressées avec myisampack.

5-7-3-5 - Autres options de myisamchk

Les autres actions que myisamchk peut réaliser, en dehors de vérifier et réparer une table sont mentionnées ci-après.

- -a, --analyze

Analyser la distribution des clés. Cela améliore les performances des jointures en permettant à l'optimiseur de jointures de mieux choisir l'ordre d'utilisation des clés. myisamchk --describe --verbose table_name' ou SHOW KEYS dans MySQL.

- -d, --description

Affiche des informations sur la table.

- -A, --set-auto-increment[=value]

Force AUTO_INCREMENT à commencer avec une valeur supérieure. Si aucune valeur n'est fournie, la prochaine valeur de la colonne AUTO_INCREMENT sera la plus grande valeur de la colonne +1.

- -S, --sort-index

Trie les blocs de l'arbre d'index dans l'ordre haut/bas. Cela va optimiser les recherches, et les scans de tables par clés.

- -R, --sort-records=#

Trie les lignes en fonction de l'index. Cela rassemble vos données, et peut accélérer les lectures de lignes par intervalle avec SELECT et ORDER BY sur cet index (ce tri peut être très lent la première fois). Pour connaître les numéros d'index de tables, utilisez la commande SHOW INDEX, qui affiche les index dans le même ordre que myisamchk ne les voit. Les index sont numérotés à partir de 1.

5-7-3-6 - Utilisation de la mémoire par myisamchk

L'espace mémoire est très important quand vous utilisez myisamchk. myisamchk n'utilise pas plus de mémoire que ce que vous spécifiez avec les options -O. Si vous pensez utiliser myisamchk sur des fichiers très grands, vous devez d'abord décider la quantité de mémoire que vous souhaitez utiliser. Avec des valeurs plus grandes, vous pouvez accélérer myisamchk. Par exemple, si vous avez plus de 32 Mo de RAM, vous pourriez utiliser les options suivantes (en plus des autres options que vous pourriez spécifier) :

shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...

Utiliser -O sort=16M sera probablement suffisant pour la plupart des cas.

Soyez conscient que myisamchk utilise des fichiers temporaires dans le dossier TMPDIR. Si TMPDIR est un fichier en mémoire, vous pourriez facilement rencontrer des erreurs de mémoire. Si cela arrive, choisissez une autre valeur pour TMPDIR, avec plus d'espace disque, et redémarrez myisamchk.

Lors de la réparation, myisamchk va aussi avoir besoin d'espace disque :

- doublez la taille du fichier de données (l'original plus une copie). Cet espace n'est pas nécessaire si vous faites des réparations de type --quick, car dans ce cas, seul le fichier d'index sera recréé. Cet espace est nécessaire sur le même disque que l'original !

- de l'espace pour le nouveau fichier d'index qui remplacera l'ancien. L'ancien fichier d'index est réduit dès le démarrage, ce qui vous permet généralement d'ignorer cet espace. Cet espace est nécessaire sur le même disque que l'original !

- lorsque vous utilisez les options --recover ou --sort-recover (mais pas lorsque vous utilisez --safe-recover), vous aurez besoin d'espace pour le buffer de tri :

(plus_grande_cle + taille_du_pointeur_de_ligne)*nombre_de_lignes * 2

Vous pouvez vérifier la taille des clés et la taille du pointeur de ligne avec la commande myisamchk -dv table. Cet espace est alloué sur le disque temporaire (spécifié par TMPDIR ou --tmpdir=#).

Si vous avez des problèmes avec l'espace disque durant la réparation, vous pouvez utiliser l'option --safe-recover au lieu de --recover.

5-7-3-7 - Utiliser myisamchk pour restaurer une table

Si vous utilisez mysqld avec l'option --skip-external-locking (qui est la configuration par défaut pour certains systèmes, comme Linux), vous ne pouvez pas utiliser myisamchk pour vérifier une table, lorsque mysqld utilise aussi la table. Si vous pouvez être sûr que personne n'utilise cette table via mysqld lorsque vous utilisez myisamchk, vous n'aurez qu'à utiliser la commande mysqladmin flush-tables avant de commencer à vérifier les tables. Si vous ne pouvez pas garantir cette condition, vous devez alors éteindre le serveur mysqld pour vérifier les tables. Si vous exécutez myisamchk alors que mysqld modifie la table, vous pourriez obtenir un diagnostic de corruption de la table, alors que ce n'est pas le cas.

Si vous n'utilisez pas l'option --skip-external-locking, vous pouvez vous servir de myisamchk pour vérifier les tables à tout moment. Pendant que vous le faites, les autres clients qui tentent de modifier la table devront attendre que myisamchk ait fini.

Si vous utilisez myisamchk pour réparer ou optimiser les tables, vous devez toujours vous assurer que mysqld n'utilise pas cette table (ce qui s'applique aussi si vous utilisez --skip-external-locking). Si vous n'éteignez pas le serveur mysqld, vous devez au moins utiliser mysqladmin flush-tables avant de lancer myisamchk. Vos tables peuvent être corrompues si le serveur et myisamchk travaillent dans une même table simultanément.

Ce chapitre décrit comment vérifier et gérer les corruptions de données dans les bases MySQL. Si vos tables sont fréquemment corrompues, vous devriez commencer par en rechercher la raison ! Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

La section sur les tables MyISAM contient différentes raisons pour lesquelles une table peut être corrompue. Voir Section 14.1.4, « Problèmes avec les tables MyISAM ».

Lorsque vous effectuez une restauration de table, il est important que chaque table tbl_name dans une base corresponde aux trois fichiers dans le dossier de base, du dossier de données :

Fichier

Utilisation

tbl_name.frm

Définition de la table

tbl_name.MYD

Fichier de données

tbl_name.MYI

Fichier d'index

Chacun de ces trois fichiers est sujet à des corruptions diverses, mais les problèmes surviennent généralement dans les fichiers de données ou d'index.

myisamchk fonctionne en créant une copie du fichier .MYD (les données), ligne par ligne. Il termine sa réparation en supprimant l'ancien fichier .MYD et en renommant le nouveau à la place de l'ancien. Si vous utilisez l'option --quick, myisamchk ne crée pas de fichier temporaire .MYD mais suppose plutôt que le fichier .MYD est correct et il génère simplement un nouveau fichier d'index sans toucher au fichier .MYD. C'est une méthode sécuritaire, car myisamchk va automatiquement détecter si le fichier .MYD est corrompu, et annulera alors la réparation si c'est le cas. Vous pouvez aussi ajouter deux options --quick à myisamchk. Dans ce cas, myisamchk ne s'interrompt pas sur certaines erreurs (comme des clés doublons), et essaie de résoudre ce problème en modifiant le fichier .MYD. Normalement, l'utilisation de deux options --quick n'est utile que si vous n'avez pas trop d'espace disque pour réaliser la réparation. Dans ce cas, vous devez au moins faire une copie de sauvegarde avant d'utiliser myisamchk.

5-7-3-8 - Comment vérifier la cohérence d'une table

Pour vérifier les tables de type MyISAM, utilisez les commandes suivantes.

- myisamchk nom_de_table

Cette commande trouvera 99.99 % de toutes les erreurs. Ce qu'elle ne peut pas découvrir comme erreurs sont celles qui impliquent uniquement le fichier de données (ce qui est très inhabituel). Si vous voulez vérifier une table, vous devriez utiliser l'utilitaire myisamchk sans les options ou avec les options -s ou --silent.

- myisamchk -m nom_de_table

Cette commande trouvera 99.999 % de toutes les erreurs. Elle vérifie toutes les entrées dans le fichier d'index, puis lit toutes les lignes. Elle calcule une somme de contrôle pour toutes les clés et les lignes, et vérifie que les deux se correspondent dans l'arbre d'index.

- myisamchk -e nom_de_table

Cette commande fait une vérification complète et exhaustive de toutes les données (-e signifie « extended check »). Elle fait une lecture de contrôle de chaque ligne, pour vérifier qu'elle correspond bien aux index. Cette commande va prendre un long moment sur les grosses tables. myisamchk va normalement s'arrêter dès qu'il trouve une erreur. Si vous voulez obtenir plus d'informations sur cette erreur, vous pouvez utiliser l'option --verbose (ou -v). Cela fera que myisamchk va continuer à travailler et accumuler jusqu'à 20 erreurs. En utilisation normale, l'utilisation de cet utilitaire sans options est suffisante.

- myisamchk -e -i nom_de_table

Comme les commandes précédentes, mais l'option -i indique à myisamchk qu'il doit afficher des informations statistiques.

5-7-3-9 - Comment réparer des tables

Dans la section présente, nous allons uniquement parler de l'utilitaire myisamchk sur les tables MyISAM (extensions .MYI et .MYD). Si vous utilisez les tables ISAM (extensions .ISM et .ISD), vous devriez vous servir de isamchk à la place.

Depuis MySQL version 3.23.14, vous pouvez réparer les tables MyISAM avec la commande SQL REPAIR TABLE. Voir Section 13.5.2.6, « Syntaxe de REPAIR TABLE ».

Les symptômes de corruption de tables sont des requêtes qui s'interrompent inopinément :

- tbl_name.frm locked against change : tbl_name.frm est verrouillée en écriture

- Can't find file tbl_name.MYI (Errcode: ###) : Impossible de trouver le fichier tbl_name.MYI (Errcode: ###)

- Unexpected end of file : Fin de fichier inattendue

- Record file is crashed : Fichier de données crashé

- Got error ### from table handler : Reception de l'erreur ### de la part du gestionnaire de tables

Pour obtenir plus d'informations sur l'erreur, vous pouvez exécuter la commande perror ###. Voici les erreurs les plus courantes :

shell> perror 126 127 132 134 135 136 141 144 145
126 = Index file is crashed / Wrong file format : le fichier d'index est corrompu / le format du fichier est incorrect.
127 = Record-file is crashed : le fichier de données est corrompu.
132 = Old database file / ce fichier provient d'une vieille base de données.
134 = Record was already deleted (or record file crashed) / La ligne était déjà effacée.
135 = No more room in record file / Plus de place dans le fichier de données.
136 = No more room in index file / Plus de place dans le fichier d'index.
141 = Duplicate unique key or constraint on write or update / Doublon pour une clé unique trouvé durant la lecture ou l'écriture.
144 = Table is crashed and last repair failed / la table est corrompue et la dernière réparation a échoué.
145 = Table was marked as crashed and should be repaired / La table a été marquée comme corrompue et doit être réparée.

Notez que l'erreur 135, « no more room in record file », n'est pas une erreur qui sera facile à corriger. Dans ce cas, vous devez utiliser la commande suivante :

ALTER TABLE table MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;

Dans d'autres cas, vous devrez réparer vos tables. myisamchk peut généralement détecter et corriger la plupart des erreurs.

Le processus de réparation se déroule en 4 étapes décrites ici. Avant de vous lancer, vous devriez vous placer dans le dossier de données et vérifier les permissions des fichiers de données. Assurez-vous qu'ils sont bien lisibles par l'utilisateur Unix que MySQL utilise (et à vous aussi, car vous aurez besoin d'accéder à ces fichiers durant la vérification. Si vous devez corriger ces fichiers, vous aurez aussi besoin des droits d'écriture.

Si vous utilisez MySQL version 3.23.16 et plus récent, vous pouvez (et vous devriez) utiliser les commandes CHECK et REPAIR pour réparer vos tables MyISAM. Voyez Section 13.5.2.3, « Syntaxe de CHECK TABLE » et Section 13.5.2.6, « Syntaxe de REPAIR TABLE ».

La section du manuel sur l'entretien des tables inclut la présentation des options des utilitaires isamchk/myisamchk : Section 5.7.3, « Utilisation de myisamchk pour la maintenance des tables et leur recouvrement ».

La section suivante est destinée aux cas où les commandes ci-dessus ont échoué ou que vous voulez exploiter les fonctionnalités avancées que isamchk/myisamchk proposent.

Si vous allez réparer une table en ligne de commande, il est recommandé d'arrêter le serveur mysqld. Notez que lorsque vous exécutez une commande mysqladmin shutdown sur un serveur distant, le serveur mysqld sera encore opérationnel pendant un instant après que mysqladmin ait terminé, jusqu'à ce que toutes les requêtes et toutes les clés aient été écrites sur le disque.

Étape 1 : vérifier vos tables

Exécutez la commande myisamchk *.MYI ou myisamchk -e *.MYI si vous avez plus de temps. Utilisez -s (silencieux) pour supprimer les informations peu pertinentes.

Si le serveur mysqld a terminé, vous devriez utiliser l'option --update pour indiquer à myisamchk d'enregistrer la vérification des tables ('checked').

Vous n'aurez à réparer que les tables pour lesquelles myisamchk vous annonce une erreur. Pour de telles tables, passez à l'étape 2.

Si vous obtenez des erreurs étranges lors de la vérification, (comme, l'erreur out of memory), ou si myisamchk crashe, passez à l'étape 3.

Étape 2 : réparations simples et faciles

Note : si vous voulez réparer très rapidement, vous devriez ajouter -O sort_buffer=# -O key_buffer=# (où # vaut environ le quart de la mémoire du serveur), à toutes les commandes isamchk/myisamchk.

Premièrement, essayez myisamchk -r -q tbl_name (-r -q signifie « mode de réparation rapide »). Cette commande va tenter de réparer le fichier d'index sans toucher au fichier de données. Si le fichier de données contient toutes les données qu'il est censé contenir, et que les points d'ancrage pour les effacements sont corrects, cette commande doit réussir, et la table sera alors réparée. Passez alors à la table suivante. Sinon, suivez la procédure suivante :

1. Faites une copie de sauvegarde de votre fichier de données ;

2. Utilisez la commande myisamchk -r tbl_name (-r signifie « mode de réparation »). Cette commande va supprimer les lignes invalides et effacer ces lignes du fichier de données, puis reconstruire le fichier d'index ;

3. Si l'instruction précédente a échoué, utilisez myisamchk --safe-recover tbl_name. Le mode restauration sécuritaire utilise une vieille méthode de réparation qui peut gérer certains cas rares, mais elle est bien plus lente.

Si vous obtenez des erreurs étranges lors de la réparation (comme des erreurs de type out of memory), ou si myisamchk crashe, passez à l'étape 3.

Étape 3 : réparations difficiles

Vous ne devriez atteindre cette étape que si les 16 premiers ko du fichier d'index sont détruits, qu'il contient des données erronées, ou si le fichier d'index manque. Dans ce cas, il est nécessaire de créer un nouveau fichier d'index. Faites ceci :

1. Déplacez le fichier de données dans une archive sûre ;

2. Utilisez le fichier description de la table pour créer de nouveaux fichiers de données et d'index vides.

shell> mysql db_name
mysql> SET AUTOCOMMIT=1;
mysql> TRUNCATE TABLE table_name;
mysql> quit

Si votre version SQL ne dispose pas de TRUNCATE TABLE, utilisez la commande DELETE FROM table_name.

3. Copiez l'ancien fichier de données à la place du nouveau fichier de données (ne faites pas un simple déplacement de fichier. Utilisez une copie, au cas où un problème surviendrait).

Retournez à l'étape 2. myisamchk -r -q doit alors fonctionner (et ceci ne doit pas être une boucle infinie).

Depuis MySQL 4.0.2, vous pouvez aussi utiliser REPAIR ... USE_FRM qui effectue toute cette opération automatiquement.

Étape 4 : réparations très difficiles

Vous ne devriez atteindre cette étape que si votre fichier de description .frm a aussi crashé. Cela ne devrait jamais arriver, car le fichier de description n'est jamais modifié une fois que la table est créée.

1. Restaurez le fichier de description avec une sauvegarde, et retournez à l'étape 3. Vous pouvez aussi restaurer le fichier d'index et retourner à l'étape 2. Dans ce dernier cas, vous pouvez démarrer avec l'option myisamchk -r.

2. Si vous n'avez pas de sauvegarde, mais que vous savez exactement comment la table a été créée, vous pouvez créer une telle table dans une autre base. Supprimez alors le nouveau fichier de données, puis déplacez les fichiers de description .frm et d'index .MYI dans votre base de données crashée. Cela vous donnera un nouveau fichier d'index et de description, mais laisse intact le fichier de données .MYD. Retournez à l'étape 2 et essayez de reconstruire le fichier d'index.

5-7-3-10 - Optimisation de table

Pour réorganiser les lignes fragmentées et éliminer l'espace perdu par les effacements et les modifications de lignes, vous pouvez exécuter l'utilitaire myisamchk en mode de restauration :

shell> myisamchk -r tbl_name

Vous pouvez optimiser une table de la même façon que vous le faites avec la commande SQL OPTIMIZE TABLE. OPTIMIZE TABLE effectue une réparation de la table, et une analyse des index, puis trie l'arbre d'index pour accélérer les recherches de clés. L'utilisation de la commande réduit aussi les interférences entre le serveur et l'utilitaire, car c'est le serveur lui-même qui fait le travail. Voir Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE ».

myisamchk dispose aussi d'un grand nombre d'options que vous pouvez utiliser pour améliorer les performances de la table :

- -S, --sort-index ;

- -R index_num, --sort-records=index_num ;

- -a, --analyze.

Pour une description complète de ces options, voyez Section 5.7.3.1, « Syntaxe de l'utilitaire myisamchk ».

5-7-4 - Mettre en place un régime d'entretien de MySQL

C'est une bonne idée que d'effectuer des vérifications des tables régulièrement, plutôt que d'attendre qu'un problème survienne. Pour faire ces vérifications, vous pouvez utiliser la commande myisamchk -s. L'option -s (raccourci pour --silent) fait que myisamchk s'exécute en mode silencieux, et n'affiche que les messages d'erreurs. Voyez les sections Section 13.5.2.3, « Syntaxe de CHECK TABLE » et Section 13.5.2.6, « Syntaxe de REPAIR TABLE ».

C'est aussi une bonne idée que de vérifier les tables lorsque le serveur démarre. Par exemple, à chaque fois qu'une machine redémarre au milieu d'une modification de table, vous devrez faire une vérification de toutes les tables qui pourraient être affectées : c'est une « table supposément corrompue ». Vous pouvez ajouter un test à safe_mysqld pour qu'il exécute myisamchk, afin de vérifier toutes les tables qui ont été modifiées dans les 24 dernières heures, s'il reste un vieux fichier .pid (identifiant de processus) après un redémarrage : le fichier .pid est créé par le serveur mysqld lorsqu'il démarre, et il est supprimé lorsque le serveur s'arrête dans des conditions normales. La présence d'un fichier .pid au démarrage indique que le serveur s'est arrêté anormalement.

Un test encore meilleur serait de vérifier toutes les tables dont la date de modification est plus récente que celle du fichier .pid.

Vous devriez aussi vérifier vos tables régulièrement durant les opérations normales. Chez MySQL AB, nous utilisons une tâche en cron pour vérifier toutes nos tables importantes au moins une fois par semaine, avec une ligne comme celle-ci dans le fichier crontab :

35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI

Cela nous affiche les informations sur les tables qui ont été corrompues, de façon à ce que nous puissions les examiner et les réparer.

Comme nous n'avons jamais eu de table qui se soit corrompue inopinément (des tables qui se corrompent pour d'autres raisons que des problèmes matériels) depuis quelques années (ce qui est véridique), une fois par semaine est un bon rythme pour nous.

Nous recommandons que vous commenciez par exécuter la commande myisamchk -s chaque nuit, sur toutes les tables qui ont été modifiées dans les 24 dernières heures, jusqu'à ce que vous preniez confiance en MySQL.

Normalement, vous n'avez pas à maintenir autant les tables MySQL. Si vous changez les tables avec un format de ligne dynamique (les tables avec des colonnes VARCHAR, BLOB ou TEXT) ou que vous avez des tables avec de nombreuses lignes effacées, vous pouvez envisager de faire des défragmentations du fichier, pour récupérer cet espace. Une fois par mois est un bon rythme.

Vous pouvez faire cela avec la commande SQL OPTIMIZE TABLE sur les tables en question, ou bien, si vous avez éteint le serveur mysqld, faites :

shell> myisamchk -r -s --sort-index -O sort_buffer_size=16M */*.MYI

Pour les tables ISAM, la commande est similaire à :

shell> isamchk -r -s --sort-index -O sort_buffer_size=16M */*.MYI

5-7-5 - Obtenir des informations sur une table

Pour obtenir la description d'une table ou des statistiques à son sujet, utiliser les commandes affichées ici. Nous allons expliquer certains de leurs détails ultérieurement.

- myisamchk -d nom_de_table Exécute myisamchk en « mode description » pour produire une description de votre table. Si vous démarrez le serveur MySQL en utilisant l'option --skip-external-locking, myisamchk va rapporter une erreur si la table est modifiée durant l'exécution de la commande. Cependant, comme myisamchk ne modifie pas les tables, durant le mode description, il n'y a pas de risque de perte de données.

- myisamchk -d -v nom_de_table Pour produire plus d'informations durant l'exécution de myisamchk, ajoutez l'option -v pour indiquer qu'elle doit fonctionner en mode détaillé.

- myisamchk -eis nom_de_table Affiche les informations les plus importantes pour une table. C'est une commande lente, car elle doit lire toute la table.

- myisamchk -eiv nom_de_table C'est l'équivalent de -eis, mais qui vous indique ce qui se passe.

Exemple d'affichage résultant de myisamchk -d :

MyISAM file:     company.MYI
Record format:   Fixed length
Data records:    1403698  Deleted blocks:         0
Recordlength:    226

table description:
Key Start Len Index   Type
1   2     8   unique  double
2   15    10  multip. text packed stripped
3   219   8   multip. double
4   63    10  multip. text packed stripped
5   167   2   multip. unsigned short
6   177   4   multip. unsigned long
7   155   4   multip. text
8   138   4   multip. unsigned long
9   177   4   multip. unsigned long
193   1           text

Exemple d'affichage résultant de myisamchk -d -v :

MyISAM file:         company
Record format:       Fixed length
File-version:        1
Creation time:       1999-10-30 12:12:51
Recover time:        1999-10-31 19:13:01
Status:              checked
Data records:           1403698  Deleted blocks:              0
Datafile parts:         1403698  Deleted data:                0
Datafilepointer (bytes):      3  Keyfile pointer (bytes):     3
Max datafile length: 3791650815  Max keyfile length: 4294967294
Recordlength:               226

table description:
Key Start Len Index   Type                  Rec/key     Root Blocksize
1   2     8   unique  double                      1 15845376      1024
2   15    10  multip. text packed stripped        2 25062400      1024
3   219   8   multip. double                     73 40907776      1024
4   63    10  multip. text packed stripped        5 48097280      1024
5   167   2   multip. unsigned short           4840 55200768      1024
6   177   4   multip. unsigned long            1346 65145856      1024
7   155   4   multip. text                     4995 75090944      1024
8   138   4   multip. unsigned long              87 85036032      1024
9   177   4   multip. unsigned long             178 96481280      1024
193   1           text

Exemple d'affichage résultant de myisamchk -eis :

Checking MyISAM file: company
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:  98%  Packed:   17%

Records:          1403698    M.recordlength:     226
Packed:             0%
Recordspace used:     100%   Empty space:          0%
Blocks/Record:   1.00
Record blocks:    1403698    Delete blocks:        0
Recorddata:     317235748    Deleted data:         0
Lost space:             0    Linkdata:             0

User time 1626.51, System time 232.36
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 627, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 639, Involuntary context switches 28966

Exemple d'affichage résultant de myisamchk -eiv :

Checking MyISAM file: company
Data records: 1403698   Deleted blocks:       0
- check file-size
- check delete-chain
block_size 1024:
index  1:
index  2:
index  3:
index  4:
index  5:
index  6:
index  7:
index  8:
index  9:
No recordlinks
- check index reference
- check data record references index: 1
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 2
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
- check data record references index: 3
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
- check data record references index: 5
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 6
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 7
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 8
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 9
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:   9%  Packed:   17%

- check records and index references
[LOTS OF ROW NUMBERS DELETED]

Records:          1403698    M.recordlength:     226   Packed:             0%
Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
Record blocks:    1403698    Delete blocks:        0
Recorddata:     317235748    Deleted data:         0
Lost space:             0    Linkdata:             0

User time 1639.63, System time 251.61
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
Blocks in 4 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 10604, Involuntary context switches 122798

Voici les tailles des fichiers de données et d'index utilisés dans les tables précédentes :

-rw-rw-r--   1 monty    tcx     317235748 Jan 12 17:30 company.MYD
-rw-rw-r--   1 davida   tcx      96482304 Jan 12 18:35 company.MYM

Des détails sur les types d'informations retournés par myisamchk sont listés ici. Le « keyfile » est le fichier d'index. « Record » et « row » sont synonymes de ligne :

- ISAM file Nom du fichier d'index ISAM ;

- Isam-version Version du format ISAM. Actuellement, c'est toujours 2 ;

- Creation time Date de création du fichier de données ;

- Recover time Date de dernière reconstruction du fichier de données ou d'index ;

- Data records Combien de lignes sont stockées dans la table ;

- Deleted blocks Combien de blocs effacés occupent toujours de l'espace. Vous pouvez optimiser la table pour récupérer cet espace. Voir Section 5.7.3.10, « Optimisation de table ».

- Data file: Parts Pour les tables au format de ligne dynamique, ceci indique combien de blocs de données sont présents. Pour une table optimisée sans ligne fragmentée, la valeur doit être égale à Data records ;

- Deleted data Combien d'octets de données effacées et non réutilisés sont présents dans la table. Vous pouvez optimiser la table pour récupérer cet espace. Voir Section 5.7.3.10, « Optimisation de table » ;

- Data file pointer La taille du pointeur de fichier de données, en octets. C'est généralement 2, 3, 4, ou 5 octets. La plupart des tables peuvent se gérer avec 2 octets, mais ceci ne peut être contrôlé par MySQL actuellement. Pour les tables à format de ligne fixe, c'est une adresse de ligne. Pour les tables dynamiques, c'est une adresse d'octet ;

- Keyfile pointer La taille du pointeur de fichier d'index, en octets. C'est généralement 1, 2 ou 3 octets. La plupart des tables supportent 2 octets, mais cela est calculé automatiquement par MySQL. C'est toujours une adresse de bloc ;

- Max datafile length Taille maximale du fichier de données, en octets ;

- Max keyfile length Taille maximale du fichier d'index, en octets ;

- Recordlength Taille occupée par chaque ligne, en octets ;

- Record format Le format utilisé pour stocker les lignes de la table. Les exemples ci-dessus utilisaient Fixed length. Les autres valeurs possibles sont Compressed et Packed ;

- table description Une liste de toutes les clés de la table. Pour chaque clé, des informations de bas niveau sont présentées :

- Key Le numéro d'index ;

- Start Où, dans la ligne, l'index débute ;

- Len Taille de cette partie d'index. Pour les nombres compactés, c'est toujours la taille maximale de la colonne. Pour les chaînes, c'est plus petit que la taille maximale de la colonne index, car vous pouvez indexer un préfixe de la chaîne ;

- Index unique et multip. (multiple). Indique si une valeur peut exister plusieurs fois dans cet index ;

- Type De quel type de données cet index est. C'est un type de données ISAM avec les options packed, stripped ou empty ;

- Root Adresse du premier bloc d'index ;

- Blocksize La taille de chaque bloc d'index. Par défaut, c'est 1024, mais cette valeur peut être modifiée lors de la compilation ;

- Rec/key C'est une valeur statistique, utilisée par l'optimiseur. Il indique combien de lignes sont disponibles par valeur de cette clé. Une clé unique aura toujours une valeur de 1. Cela peut être modifié une fois que la table est chargée (ou modifiée de façon majeure), avec la commande myisamchk -a. Si ce n'est pas mis à jour, une valeur par défaut de 30 est utilisée.

Dans le premier exemple ci-dessus, la neuvième clé est une clé multipartie, avec deux parties :

- Keyblocks used Quel pourcentage des blocs de clés est utilisé. Comme les tables utilisées dans les exemples ont tout juste été réorganisées avec myisamchk, ces valeurs sont très grandes (très proches du maximum théorique) ;

- Packed MySQL essaie de compacter les clés ayant un préfixe commun. Cela ne peut être utilisé que pour les colonnes de type CHAR/VARCHAR/DECIMAL. Pour les longues chaînes comme des noms, cette technique va significativement réduire l'espace utilisé. Dans le troisième exemple ci-dessus, la quatrième clé fait 10 caractères de long et a une réduction de 60 % dans l'espace utilisé effectivement ;

- Max levels La profondeur du B-tree. Les grandes tables avec de longues clés peuvent obtenir de grandes valeurs ;

- Records Combien de lignes sont enregistrées dans la table ;

- M.recordlength La taille moyenne d'une ligne. Pour les tables avec un format de ligne statique, c'est la taille de chaque ligne ;

- Packed MySQL efface les espaces à la fin des chaînes. Packed indique le pourcentage d'économie d'espace réalisé ;

- Recordspace used Quel est le pourcentage d'utilisation du fichier de données ;

- Empty space Quel est le pourcentage d'utilisation du fichier d'index ;

- Blocks/Record Le nombre moyen de blocs par enregistrements (c'est-à-dire, de combien de liens une ligne fragmentée est constituée). C'est toujours 1.0 pour les tables à format de ligne statique. Cette valeur doit être aussi proche que possible de 1.0. Si elle grossit trop, vous pouvez réorganiser la table avec myisamchk. Voir Section 5.7.3.10, « Optimisation de table » ;

- Recordblocks Combien de blocs sont utilisés. Pour les tables à format de ligne fixe, c'est le même nombre que le nombre de lignes ;

- Deleteblocks Combien de blocs (liens) sont effacés ;

- Recorddata Combien d'octets sont utilisés dans le fichier ;

- Deleted data Combien d'octets dans le fichier de données sont effacés (inutilisés) ;

- Lost space Si une ligne est modifiée, et réduite en taille, de l'espace est perdu. Ce chiffre est la somme de ces espaces perdus, en octets ;

- Linkdata Lorsque le format de ligne dynamique est utilisé, les fragments de lignes sont liés avec des pointeurs de (4 à 7 octets chacun). Linkdata est la somme du stockage utilisé par ces pointeurs.

Si une table a été compressée avec myisampack, myisamchk -d affiche des informations supplémentaires à propos de chaque colonne. Voir Section 8.2, « myisampack, le générateur de tables MySQL compressées en lecture seule », pour un exemple de ces informations, et une description de leur signification.

5-8 - Localisation MySQL et utilisation internationale

5-8-1 - Le jeu de caractères utilisé pour les données et le stockage

Par défaut, MySQL utilise le jeu de caractères ISO-8859-1 (Latin1) avec tri en accord au suédois/finnois. C'est le jeu de caractères le mieux adapté pour les USA et l'Europe de l'Ouest.

Tous les binaires standard MySQL sont compilés avec --with-extra-charsets=complex. Cela ajoutera du code à tous les programmes standard pour qu'ils puissent gérer latin1 et tous les jeux de caractères multioctets compris dans le binaire. Les autres jeux de caractères seront chargés à partir d'un fichier de définition de jeu si besoin.

Le jeu de caractères détermine quels caractères sont autorisés dans les noms et comment s'effectuent les tris dans les clauses ORDER BY et GROUP BY de la commande SELECT.

Vous pouvez changer le jeu de caractères avec l'option de démarrage du serveur --default-character-set. Les jeux de caractères disponibles dépendent des options --with-charset=charset et --with-extra-charsets= list-of-charset | complex | all de configure, et des fichiers de configuration de jeux de caractères situés dans SHAREDIR/charsets/Index. Voir Section 2.4.2, « Options habituelles de configure ».

Depuis MySQL 4.1.1, vous pouvez aussi changer la collation du jeu de caractères avec l'option --default-collation lorsque le serveur démarre. La collation doit être valide pour le jeu de caractères par défaut. Utilisez la commande SHOW COLLATION pour déterminer quelles collations sont disponibles pour chaque jeu de caractères. Voir Section 2.4.2, « Options habituelles de configure ».

Si vous changez le jeu de caractères lors de l'utilisation de MySQL (ce qui pourra aussi changer l'ordre de tri), vous devez exécuter myisamchk -r -q --set-character-set=charset sur toutes les tables. Sinon, vos index pourront ne pas être ordonnés correctement.

Lorsqu'un client se connecte à un serveur MySQL, le serveur envoie le jeu de caractères utilisé par défaut au client. Le client changera de jeu de caractères pour cette connexion.

Vous devez utiliser mysql_real_escape_string() pour protéger les chaînes pour une requête SQL. mysql_real_escape_string() est identique à l'ancienne fonction mysql_escape_string(), excepté qu'elle prend le gestionnaire de connexion MYSQL en tant que premier paramètre.

Si le client est compilé avec d'autres chemins que ceux où le serveur est installé et que la personne qui a configuré MySQL n'a pas inclus tous les jeux de caractères dans le binaire MySQL, vous devez indiquer au client où il peut trouver les jeux de caractères additionnels dont il aura besoin si le serveur utilise un autre jeu de caractères que le client.

On peut le spécifier en plaçant dans un fichier d'options MySQL :

[client]
character-sets-dir=/usr/local/mysql/share/mysql/charsets

où le chemin pointe vers le répertoire où les jeux de caractères dynamiques de MySQL sont stockés.

On peut forcer le client à utiliser un jeu de caractères spécifique en précisant :

[client]
default-character-set=character-set-name

mais on n'en a normalement jamais besoin.

5-8-1-1 - Jeu de caractères allemand

Pour obtenir l'ordre de tri allemand, vous devez démarrer mysqld avec --default-character-set=latin1_de. Cela vous donnera les caractéristiques différentes.

- Lors du tri et de la comparaison des chaînes, les remplacements suivants sont faits dans la chaîne avant d'effectuer la comparaison :

ä  ->  ae
ö  ->  oe
ü  ->  ue
ß  ->  ss

- Tous les caractères accentués sont convertis en leur majuscule non accentuée. Toutes les lettres sont transformées en majuscules.

- Lors de la comparaison des chaînes de caractères avec LIKE, la conversion un vers deux caractères n'est pas effectuée. Toutes les lettres sont transformées en majuscules. Les accents sont supprimés de toutes les lettres, à l'exception de : Ü, ü, Ö, ö, Ä et ä.

5-8-2 - Langue des messages d'erreurs

mysqld peut émettre des messages d'erreurs dans les langues suivantes : tchèque, danois, néerlandais, anglais (par défaut), estonien, français, allemand, grec, hongrois, italien, japonais, coréen, norvégien, norwegian-ny, polonais, portugais, roumain, russe, slovaque, espagnol et suédois.

Pour démarrer mysqld avec une langue particulière, utilisez soit l'option --language=lang, soit -L lang. Par exemple :

shell> mysqld --language=french

ou :

shell> mysqld --language=/usr/local/share/french

Notez que tous les noms de langue sont spécifiés en minuscules.

Les fichiers de langue sont situés (par défaut) dans share/LANGUAGE/.

Pour modifier le fichier de messages d'erreurs, vous devez éditer le fichier errmsg.txt et exécuter la commande suivante pour générer le fichier errmsg.sys :

shell> comp_err errmsg.txt errmsg.sys

Si vous changez de version de MySQL, pensez à modifier le nouveau fichier errmsg.txt.

5-8-3 - Ajouter un nouveau jeu de caractères

Cette section présente la procédure à suivre pour ajouter un autre jeu de caractères à MySQL. Vous devez avoir une distribution source pour suivre ces instructions.

Pour choisir la procédure adaptée, il faut savoir si le jeu de caractères est simple ou complexe :

- si le jeu de caractères n'a pas besoin d'utiliser des routines de collations de chaînes spéciales pour le tri et n'a pas besoin du support des jeux de caractères multioctets, il est simple ;

- s'il a besoin de l'une de ces deux fonctionnalités, il est complexe.

Par exemple, latin1 et danish sont des jeux de caractères simples tandis que big5 et czech sont complexes.

Dans la section suivante, nous supposons que vous nommez votre jeu de caractères MONJEU.

Pour un jeu de caractères simple, effectuez ce qui suit :

1. Ajoutez MONJEU à la fin du fichier sql/share/charsets/Index Assignez-lui un nombre unique ;

2. Créez le fichier sql/share/charsets/MONJEU.conf. (Vous pouvez vous inspirer de sql/share/charsets/latin1.conf.)

La syntaxe pour le fichier est très simple :

- les commentaires commencent avec le caractère '#' et se terminent à la fin de la ligne,

- les mots sont séparés par un nombre changeant d'espaces blancs,

- lors de la définition d'un jeu de caractères, chaque mot doit être un nombre au format hexadécimal,

- Le tableau ctype prend les 257 premiers mots. Les tableaux to_lower[], to_upper[] et sort_order[] prennent chacun 256 mots après cela.

Voir Section 5.8.4, « Le tableau de définition des caractères » ;

3. Ajoutez le nom du jeu de caractères aux listes CHARSETS_AVAILABLE et COMPILED_CHARSETS dans configure.in ;

4. Reconfigurez, recompilez et testez.

Pour un jeu de caractères complexe faites ce qui suit :

1. Créez le fichier strings/ctype-MONJEU.c dans la distribution des sources MySQL ;

2. Ajoutez MONJEU à la fin du fichier sql/share/charsets/Index. Assignez-lui un nombre unique ;

3. Regardez un des fichiers ctype-*.c existant pour voir ce qui doit être défini, par exemple, strings/ctype-big5.c. Notez que les tableaux dans votre fichier doivent avoir des noms tels que ctype_MONJEU, to_lower_MONJEU, etc. Cela correspond aux tableaux dans les jeux de caractères simples. Voir Section 5.8.4, « Le tableau de définition des caractères ». Pour un jeu de caractères complexes ;

4. Au début du fichier, placez un commentaire spécial comme celui-ci :

/*
* This comment is parsed by configure to create ctype.c,
* so don't change it unless you know what you are doing.
*
* .configure. number_MONJEU=MYNUMBER
* .configure. strxfrm_multiply_MONJEU=N
* .configure. mbmaxlen_MONJEU=N
*/

Le programme configure utilise ce commentaire pour inclure automatiquement le jeu de caractères dans la bibliothèque MySQL.

Les lignes strxfrm_multiply et mbmaxlen seront expliquées dans les sections suivantes. Ne les incluez que si vous avez besoin des fonctions d'assemblage des chaînes ou des fonctions de jeu de caractères multioctets, respectivement ;

5. Vous devez alors créer les fonctions suivantes :

- my_strncoll_MONJEU(),

- my_strcoll_MONJEU(),

- my_strxfrm_MONJEU(),

- my_like_range_MONJEU().

Voir Section 5.8.5, « Support d'assemblage des chaînes » ;

6. Ajoutez le nom du jeu de caractères aux listes CHARSETS_AVAILABLE et COMPILED_CHARSETS dans configure.in ;

7. Reconfigurez, recompilez et testez.

Le fichier sql/share/charsets/README fournit plus d'instructions.

Si vous voulez qu'un jeu de caractères soit ajouté dans la distribution MySQL, envoyez un patch aux listes internes. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

5-8-4 - Le tableau de définition des caractères

to_lower[] et to_upper[] sont de simples tableaux qui contiennent les caractères minuscules et majuscules correspondant à chaque membre du jeu de caractères. Par exemple :

to_lower['A'] doit contenir 'a'
to_upper['a'] doit contenir 'A'

sort_order[] est une carte indiquant comment les caractères doivent être ordonnés pour les comparaisons et les tris. Pour beaucoup de jeux de caractères, c'est la même chose que to_upper[] (ce qui signifie que le tri sera insensible à la casse). MySQL triera les caractères en se basant sur la valeur de sort_order[caractère]. Pour des règles de tri plus compliquées, voyez la discussion suivante sur l'assemblage des chaînes. Voir Section 5.8.5, « Support d'assemblage des chaînes ».

ctype[] est un tableau de valeurs de bit, avec un élément par caractère. (Notez que to_lower[], to_upper[], et sort_order[] sont indexés par la valeur du caractère, mais que ctype[] est indexé par la valeur du caractère + 1. C'est une vieille habitude pour pouvoir gérer EOF.)

Vous pouvez trouver les définitions de bitmask suivantes dans m_ctype.h :

#define _U      01      /* Majuscule */
#define _L      02      /* Minuscule */
#define _N      04      /* Numérique (nombre) */
#define _S      010     /* Caractère d'espacement */
#define _P      020     /* Ponctuation */
#define _C      040     /* Caractère de contrôle */
#define _B      0100    /* Blanc */
#define _X      0200    /* nombre hexadecimal */

L'entrée ctype[] de chaque caractère doit être l'union des valeurs de masque de bits qui décrivent le caractère. Par exemple, 'A' est un caractère majuscule (_U) autant qu'une valeur hexadécimale (_X), et donc ctype['A'+1] doit contenir la valeur :

_U + _X = 01 + 0200 = 0201

5-8-5 - Support d'assemblage des chaînes

Si les règles de tri de votre langue sont trop complexes pour être gérées par le simple tableau sort_order[], vous devez utiliser les fonctions d'assemblage de chaînes.

Jusqu'à présent, la meilleure documentation traitant de ce sujet est présente dans les jeux de caractères implémentés eux-mêmes. Regardez les jeux de caractères big5, czech, gbk, sjis, et tis160 pour des exemples.

Vous devez spécifier la valeur de strxfrm_multiply_MYSET=N dans le commentaire spécial au début du fichier. N doit être le rationnel maximal vers lequel la chaîne pourra croître durant my_strxfrm_MYSET (cela doit être un entier positif).

5-8-6 - Support des caractères multioctets

Si vous voulez ajouter le support de jeu de caractères incluant des caractères multioctets, vous devez utiliser les fonctions de caractères multioctets.

Jusqu'à présent, la meilleure documentation traitant de ce sujet est présente dans les jeux de caractères implémentés eux-mêmes. Regardez les jeux de caractères euc_kr, gb2312, gbk, sjis, et ujis pour des exemples. Ils sont implémentés dans les fichiers ctype-'charset'.c dans le dossier strings.

Vous devez spécifier la valeur de mbmaxlen_MYSET=N dans le commentaire spécial en haut du fichier source. N doit être la taille en octets du caractère le plus large dans le jeu.

5-8-7 - Problèmes avec les jeux de caractères

Si vous essayez d'utiliser un jeu de caractères qui n'est pas compilé dans votre exécutable, vous pouvez rencontrer différents problèmes.

- Votre programme a un chemin faux en ce qui concerne l'endroit où sont stockés les jeux de caractères. (Par défaut /usr/local/mysql/share/mysql/charsets). Cela peut être réparé en utilisant l'option --character-sets-dir du programme en question.

- Le jeu de caractères est un jeu de caractères multioctets qui ne peut être chargé dynamiquement. Dans ce cas, vous devez recompiler le programme en incluant le support du jeu de caractères.

- Le jeu de caractères est un jeu de caractères dynamique, mais vous n'avez pas de fichier de configuration lui étant associé. Dans ce cas, vous devez installer le fichier de configuration du jeu de caractères à partir d'une nouvelle distribution MySQL.

- Votre fichier Index ne contient pas le nom du jeu de caractères.

ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf' not found
(Errcode: 2)

Dans ce cas, vous devez soit obtenir un nouveau fichier Index ou ajouter à la main le nom du jeu de caractères manquant.

Pour les tables MyISAM, vous pouvez vérifier le nom du jeu de caractères et son nombre associé d'une table avec myisamchk -dvv nom_de_table.

5-8-8 - Support des fuseaux horaires avec MySQL

Avant MySQL version 4.1.3, vous pouviez modifier le fuseau horaire du serveur avec l'option --timezone=timezone_name de mysqld_safe. Vous pouvez aussi le modifier avec la variable d'environnement TZ avant de lancer mysqld.

Les valeurs autorisées pour --timezone et TZ dépendent du système d'exploitation. Consultez la documentation de votre système d'exploitation pour connaître ces valeurs.

Depuis MySQL 4.1.3, le serveur entretien différentes configurations de fuseau horaire.

- Le fuseau horaire du système. Lorsque le serveur se lance, il tente de déterminer le fuseau horaire de la machine serveur, et l'utilise dans la variable système system_time_zone.

- Le fuseau horaire courant. La variable système globale time_zone indique le fuseau horaire courant du serveur. La valeur initiale est 'SYSTEM', qui indique que le serveur est dans le même fuseau horaire que le serveur. La valeur initiale peut être spécifiée explicitement avec l'option --default-time-zone=timezone. Si vous avez les droits de SUPER, vous pouvez modifier la valeur de cette variable durant l'exécution du serveur, avec cette commande :

mysql> SET GLOBAL time_zone = timezone;

- Fuseau horaire de connexion. Chaque client qui se connecte peut disposer de sa propre configuration de fuseau horaire, grâce à la variable de session time_zone. Initialement, elle prend la valeur de time_zone, mais peut être redéfinie avec la commande suivante :

mysql> SET time_zone = timezone;

La valeur courante du fuseau horaire global et de session est accessible avec cette commande :

mysql> SELECT @@global.time_zone, @@session.time_zone;

Les valeurs de timezone peuvent être fournies sous forme de chaînes de caractères, indiquant un décalage par rapport au temps UTC, comme '+10:00' ou '-6:00'. Si la table de fuseau horaire de la base mysql a été créée et remplie, vous pouvez aussi utiliser les noms de fuseaux, comme 'Europe/Paris' ou 'Canada/Eastern', ou 'MET'. La valeur 'SYSTEM' indique le fuseau horaire du système. Les noms de fuseau horaire sont insensibles à la casse.

La procédure d'installation de MySQL crée la table des fuseaux horaires, mais ne la remplit pas. Vous devez le faire manuellement. Si vous passez en MySQL version 4.1.3 ou plus récent depuis une version plus récente, il est important de créer ces tables en mettant à jour la base mysql. Utilisez les instructions de Section 2.6.7, « Mise à jour des tables de droits ».)

Note : actuellement, la table des fuseaux horaires peut être remplie uniquement sous Unix. Le problème sera bientôt réglé pour Windows.

Le programme mysql_tzinfo_to_sql sert à charger la table des fuseaux horaires. Vous devez connaître le nom du dossier dans lequel votre système d'exploitation enregistre les fuseaux horaires. Typiquement, c'est /usr/share/zoneinfo. Indiquez cette valeur au programme en ligne de commande mysql_tzinfo_to_sql, et passez le résultat du programme au client mysql. Par exemple :

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

mysql_tzinfo_to_sql lit les fichiers de fuseaux horaires de votre système et génère des requêtes SQL. Le client mysql traite ces commandes et les charge dans la base de données.

mysql_tzinfo_to_sql peut aussi charger un fichier de fuseaux horaires, et générer les secondes additionnelles.

Pour charger un fichier de fuseaux horaires tz_file qui correspond au fuseau appelé tz_name, appelez le programme mysql_tzinfo_to_sql comme ceci :

shell> mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql

Si votre système doit prendre en compte les secondes additionnelles, initialisez les informations de secondes additionnelles comme ceci, où tz_file est le nom de votre fichier de fuseaux :

shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql

5-9 - Les fichiers de log de MySQL

MySQL a plusieurs fichiers de log qui peuvent vous aider à savoir ce qui se passe à l'intérieur de mysqld:

Fichier

Description

Le log d'erreurs

Problèmes rencontrés lors du démarrage, de l'exécution ou de l'arrêt de mysqld.

Le log ISAM

Garde une trace des changements liés aux tables ISAM. Utilisé uniquement pour déboguer le code ISAM.

Le log de requêtes

Connexions établies et requêtes exécutées.

Le log de mises à jour

Désapprouvé : enregistre toutes les commandes qui changent les données.

Le log binaire

Enregistre toutes les commandes qui changent quelque chose. Utilisé pour la réplication.

Le log des requêtes lentes

Enregistre toutes les requêtes qui ont pris plus de long_query_time à s'exécuter ou celles qui n'ont pas utilisé d'index.

Par défaut, tous les fichiers de log peuvent être trouvés dans le dossier de données de mysqld. Vous pouvez forcer mysqld à rouvrir les fichiers de log (ou dans quelques cas à passer à un nouveau log) en exécutant FLUSH LOGS. Voir Section 13.5.4.2, « Syntaxe de FLUSH ».

Si vous utilisez les fonctionnalités de réplication de MySQL, les serveurs esclaves entretiennent un fichier de logs supplémentaire, appelé log de relais. Chapitre 6, Réplication de MySQL.

5-9-1 - Le log d'erreurs

Le fichier d'erreurs contient les informations indiquant quand mysqld a été lancé et arrêté, ainsi que les erreurs critiques qui sont survenues lorsque le serveur fonctionnait.

Si mysqld s'arrête inopinément, et que mysqld_safe doit le relancer, mysqld_safe va écrire un message restarted mysqld dans le log d'erreurs. Si mysqld remarque qu'une table a besoin d'être réparée ou analysée, il écrit aussi un message dans le log d'erreurs.

Sur certains systèmes d'exploitation, le log d'erreurs contient automatiquement une pile de trace si mysqld. La trace peut être utilisée pour déterminer quand mysqld. Voir Section D.1.4, « Utilisation d'un traçage de pile mémoire ».

Depuis MySQL 4.0.10, vous pouvez spécifier où mysqld stocke le fichier d'erreurs avec l'option --log-error[=file_name]. Si aucune valeur file_name n'est donnée, mysqld utilise le nom host_name.err et écrit le fichier dans le dossier de données. (Avant MySQL 4.0.10, le nom de fichier d'erreurs Windows était mysql.err.) Si vous exécutez FLUSH LOGS, le log d'erreurs est renommé avec le suffixe -old et mysqld crée un nouveau fichier de logs vide.

Dans les anciennes versions de MySQL sous Unix, le log d'erreurs était géré par mysqld_safe qui redirigeait les erreurs vers host_name.err. Vous pouvez modifier le nom du fichier en spécifiant l'option --err-log=filename de mysqld_safe.

Si vous ne spécifiez pas --log-error, ou, sous Windows, si vous utilisez l'option --console, les erreurs sont écrites dans la sortie standard stderr. C'est généralement le terminal qui a lancé MySQL.

Sous Windows, les erreurs sont toujours écrites dans le fichier .err si --console n'est pas donné.

5-9-2 - Le log général de requêtes

Si vous voulez savoir ce qui se passe à l'intérieur de mysqld, vous devez le démarrer avec --log[=fichier]. Cela aura pour effet d'écrire toutes les connexions et les requêtes dans le fichier de logs (pas défaut nommé 'hostname'.log). Ce log peut être très utile quand vous suspectez une erreur dans un client et voulez savoir exactement ce que mysqld pense que le client lui a envoyé.

Les anciennes versions du script mysql.server (de MySQL 3.23.4 à 3.23.8) passent à safe_mysqld une option --log (active le log général de requêtes). Si vous avez besoin de meilleures performances lorsque vous démarrez MySQL dans un environnement de production, vous pouvez supprimer l'option --log de mysql.server ou la changer en --log-bin. Voir Section 5.9.4, « Le log binaire ».

mysqld écrit les commandes dans le log de requêtes, dans l'ordre où il les reçoit. Cela peut être différent de l'ordre dans lequel elles sont exécutées. Cela est différent du log de modifications et du log binaire, qui sont toujours écrits après exécution, mais avant la libération des verrous.

Les redémarrages de serveur et les écritures de logs ne génèrent pas un nouveau fichier de logs de requêtes (même si l'écriture des logs ferme puis ouvre à nouveau le fichier). Sous Unix, vous pouvez renommer le fichier et en créer un nouveau avec les commandes suivantes :

shell> mv hostname.log hostname-old.log
shell> mysqladmin flush-logs
shell> cp hostname-old.log to-backup-directory
shell> rm hostname-old.log

Sous Windows, vous ne pouvez pas renommer le fichier de logs, alors que le serveur l'a ouvert. Vous devez arrêter le serveur, puis renommer le log. Puis, redémarrez le serveur pour créer un nouveau log.

5-9-3 - Le log de modifications

Note : le log de modifications a été remplacé par le log binaire. Voir Section 5.9.4, « Le log binaire ». Avec ce nouveau log, vous pouvez faire tout ce que vous faisiez avec le log de modifications. Le log de modifications n'est plus disponible depuis MySQL 5.0.0.

Lors l'option --log-update[=file_name] est utilisée au démarrage, mysqld écrit un fichier de logs contenant toutes les commandes SQL qui modifient les données. Si aucun fichier n'est spécifié, il prendra la valeur par défaut du nom de l'hôte. Si un fichier est spécifié, mais qu'aucun chemin n'est indiqué, le fichier sera écrit dans le dossier de données. Si le fichier file_name n'a pas d'extension, mysqld va créer un fichier de logs avec ce nom : file_name.###, où ### est un nombre qui s'incrémente à chaque fois que vous exécutez la commande mysqladmin refresh, mysqladmin flush-logs, FLUSH LOGS ou que vous redémarrez le serveur.

Note : pour que la technique ci-dessus fonctionne, vous ne devez pas créer de fichiers avec le nom du fichier de logs + une extension, qui pourrait être considérée comme un nombre, dans le dossier qui contient les logs de modifications.

L'enregistrement dans le log de modification est fait juste après l'achèvement de la requête, mais avant la levée des verrous, et les validations. Cela garantit que la requête sera enregistrée.

Si vous voulez modifier une base grâce aux fichiers de log de modifications, vous pouvez utiliser la commande suivante (en supposant que vos fichiers de log de modifications portent le nom de file_name.###) :

shell> ls -1 -t -r file_name.[0-9]* | xargs cat | mysql

ls est utilisé pour obtenir toute la liste des fichiers de logs du dossier.

Ceci peut être utile si vous devez repartir d'un fichier de sauvegarde après un crash, et que vous souhaitez réexécuter les modifications qui ont eu lieu depuis la sauvegarde.

5-9-4 - Le log binaire

Le log binaire a remplacé l'ancien log de modifications, qui ne sera plus disponible à partir de MySQL version 5.0. Le log binaire contient toutes les informations du log de modifications, dans un format plus efficace, et compatible avec les transactions.

Le log binaire, comme le log de modifications, contient toutes les requêtes qui modifient les données. Ainsi, une commande UPDATE ou DELETE avec une clause WHERE qui ne trouve aucune ligne ne sera pas écrite dans le log. Les commandes UPDATE qui donnent à une colonne sa valeur courante sont même évitées.

Le log binaire contient aussi des informations sur le temps d'exécution de la requête dans la base. Il ne contient que des commandes qui modifient des données. Si vous voulez avoir toutes les commandes (par exemple, si vous identifiez un problème de requête, vous devez utiliser le log de requêtes général. Voir Section 5.9.2, « Le log général de requêtes ».

Le but principal de ce log est de pouvoir reprendre les modifications de la base durant les opérations de restaurations, car le log binaire contiendra les requêtes qui ont eu lieu après une sauvegarde.

Le log binaire est aussi utilisé lorsque de la réplication d'un maître par un esclave. Voir Chapitre 6, Réplication de MySQL.

L'utilisation du log binaire ralentit le serveur d'environ 1 %. Cependant, les avantages du log binaire durant les opérations de restauration et pour la réplication sont généralement plus intéressants.

Lorsque l'option de démarrage --log-bin[=file_name] est utilisée, mysqld écrit un fichier de logs contenant toutes les commandes SQL qui modifient les données. Si aucun nom de fichier n'est donné, le nom de la machine hôte est utilisé, suivi de -bin. Si un nom est donné, mais qu'il ne contient pas de chemin, le fichier sera écrit dans le dossier de données.

Si vous fournissez une extension à --log-bin=filename.extension, l'extension sera automatiquement supprimée.

mysqld va ajouter une extension au nom du fichier de logs binaire qui est un nombre automatiquement incrémenté chaque fois que vous exécutez mysqladmin refresh, mysqladmin flush-logs, FLUSH LOGS ou redémarrez le serveur. Un nouveau fichier de logs sera automatiquement créé lorsque le fichier en cours atteint la taille de max_binlog_size. Un fichier de logs binaire peut être plus grand que max_binlog_size si vous utilisez de grandes transactions : une transaction est écrite dans le log binaire d'un seul coup, et n'est jamais répartie entre plusieurs fichiers.

Pour être capable de faire la différence entre les fichiers de log binaire utilisés, mysqld crée aussi un fichier d'index de logs, qui porte le même nom que le fichier de logs, mais avec l'extension '.index'. Vous pouvez changer le nom du fichier de logs avec l'option --log-bin-index=[file_name]. N'éditez pas manuellement ce fichier durant l'exécution de mysqld ; cela va induire mysqld en erreur.

Vous pouvez effacer tous les fichiers de log avec la commande RESET MASTER, ou seulement certains d'entre eux avec PURGE MASTER LOGS. Voyez Section 13.5.4.5, « Syntaxe de la commande RESET » et Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication ».

Vous pouvez utiliser les options suivantes avec mysqld pour modifier ce qui est enregistré dans le fichier de logs :

- binlog-do-db=database_name

Indique au maître qu'il doit enregistrer les modifications si la base courante (c'est-à-dire, celle qui est sélectionnée par USE) est db_name. Toutes les autres bases de données qui ne sont pas explicitement mentionnées sont ignorées. Si vous utilisez cette option, assurez-vous que vous ne faites des modifications que dans la base courante.

Un exemple qui ne fonctionnera pas comme on pourrait l'attendre : si le serveur est lancé avec l'option binlog-do-db=sales, et que vous utilisez USE prices; UPDATE sales.january SET amount=amount+1000;, cette commande ne sera pas écrite dans le fichier de logs binaire.

- binlog-ignore-db=database_name

Indique au maître qu'il ne doit pas enregistrer les modifications si la base courante (c'est-à-dire, celle qui est sélectionnée par USE) est db_name. Si vous utilisez cette option, assurez-vous que vous ne faites des modifications que dans la base courante.

Un exemple qui ne fonctionnera pas comme on pourrait l'attendre : si le serveur est lancé avec l'option binlog-ignore-db=sales, et que vous utilisez USE prices; UPDATE sales.january SET amount=amount+1000;, cette commande sera écrite dans le fichier de logs binaire.

Pour ignorer ou forcer plusieurs bases, spécifiez l'option plusieurs fois, une fois par base.

Les règles suivantes sont utilisées dans l'ordre suivant, pour décider si la requête doit aller dans le log binaire ou pas.

1. Y a-t-il des règles binlog-do-db ou binlog-ignore-db ?

- Non : écrit la requête dans le log binaire, et quitte.

- Oui : aller à l'étape suivante.

2. Il y a des règles (binlog-do-db ou binlog-ignore-db ou les deux). Y a-t-il une base de données courante (une base sélectionnée avec la commande USE) ?

- Non : N'écrit pas la requête, et quitte.

- Oui : aller à l'étape suivante.

3. Il y a une base de données courante. Y a-t-il des règles binlog-do-db ?

- Oui : Est-ce que la base de données courante vérifie une des règles binlog-do-db ?

- Oui : écrit la requête dans le log binaire, et quitte.

- Non : n'écrit pas la requête, et quitte.

- Non : aller à l'étape suivante.

4. Il y a des règles binlog-ignore-db. Est-ce que la base de données courante vérifie une des règles binlog-ignore-db ?

- Oui : n'écrit pas la requête, et quitte.

- Non : écrit la requête dans le log binaire, et quitte.

Par exemple, un esclave qui fonctionne avec l'option binlog-do-db=sales ne va pas écrire dans le log binaire les commandes qui concernent d'autres bases que sales (en d'autres termes, l'option binlog-do-db peut être considéré comme « ignore les autres bases »).

Si vous utilisez la réplication, vous ne devez pas effacer les anciens logs binaires jusqu'à ce que vous soyez sûr que les esclaves n'en auront plus besoin. Une façon de faire cela est d'utiliser la commande mysqladmin flush-logs une fois par jour, et d'effacer les fichiers de log qui ont plus de trois jours. Vous pouvez les supprimer manuellement, ou utilisez de préférence la commande PURGE MASTER LOGS TO (Voir Section 13.6, « Commandes de réplication ») qui va aussi modifier le fichier de logs binaire pour vous depuis MySQL 4.1.

Un client avec le droit de SUPER peut désactiver le log binaire pour ses commandes avec SET SQL_LOG_BIN=0. Voir Section 13.5.2.8, « Syntaxe de SET ».

Vous pouvez examiner le fichier de logs binaire avec la commande mysqlbinlog. Par exemple, vous pouvez mettre à jour le serveur MySQL depuis la ligne de commande comme ceci :

shell> mysqlbinlog log-file | mysql -h server_name

Vous pouvez aussi utiliser le programme Section 8.5, « mysqlbinlog, Exécuter des requêtes dans le log binaire » pour lire le fichier de logs binaire directement dans le serveur MySQL.

Si vous utilisez les transactions, vous devez utiliser le fichier de logs binaire pour les sauvegardes, plutôt que le vieux fichier de logs de modifications.

L'enregistrement dans le fichier de logs binaire est fait immédiatement après l'achèvement de la requête, mais avant la libération des verrous ou la validation de la requête. Cela garantit que les requêtes seront enregistrées dans l'ordre d'exécution.

Les modifications dans les tables non transactionnelles sont enregistrées dans le fichier de logs binaire immédiatement après exécution. Pour les tables transactionnelles comme BDB ou InnoDB, toutes les modifications (UPDATE, DELETE ou INSERT) qui modifient les tables sont mises en cache jusqu'à ce qu'une commande COMMIT ne les envoie au serveur. À ce moment, mysqld écrit la totalité de la transaction dans le log binaire, avant d'appliquer la commande COMMIT. Tous les threads vont, au démarrage, allouer un buffer de la taille de binlog_cache_size octets pour enregistrer les requêtes. Si la requête est plus grande que ce buffer, le thread va ouvrir un fichier temporaire pour écrire la transaction. Le fichier temporaire sera supprimé dès que le thread se termine.

L'option max_binlog_cache_size (par défaut 4 Go) peut être utilisée pour limiter la taille utilisée pour mettre en cache une transaction multirequête. Si la transaction est plus grande que cette taille, elle sera annulée.

Si vous utilisez le log de modifications ou binaire, les insertions concurrentes seront converties en insertions normales lors de l'utilisation de CREATE ... SELECT ou INSERT ... SELECT. Cela garantit que vous pourrez recréer une copie exacte de la table en appliquant les mêmes commandes sauvegardées.

Le format de log binaire est différent entre les versions 3.23, 4.0 et 5.0.0. Ces changements de formats sont nécessaires pour améliorer la réplication. MySQL 4.1 a le même format de log binaire que 4.0. Voir Section 6.5, « Compatibilité de la réplication entre les versions de MySQL ».

5-9-5 - Le log des requêtes lentes

Lorsqu'il est démarré avec l'option --log-slow-queries[=file_name], mysqld va écrire dans un fichier les requêtes SQL qui vont mettre plus de long_query_time secondes à s'exécuter. Le temps d'acquisition d'un verrou n'est pas compté.

Les requêtes lentes sont enregistrées après l'achèvement de l'exécution de la requête, et libération du verrou. Cela peut être différent de l'ordre dans lequel les commandes sont exécutées.

Si aucun nom de fichier n'est donné, le fichier de logs prendra par défaut le nom de la machine, suffixé avec -slow.log. Si un nom de fichier est donné, mais qu'il manque le chemin, le fichier sera écrit dans le dossier de données.

Le log de requêtes lentes peut être utilisé pour repérer les requêtes qui prennent longtemps à s'exécuter, et donc, qui sont candidates à l'optimisation. Avec un grand fichier de logs, cela peut devenir difficile. Vous pouvez alors passer le fichier de logs à mysqldumpslow pour obtenir un sommaire des requêtes dans ce fichier.

Si vous utilisez l'option --log-long-format alors les requêtes qui n'utilisent pas d'index sont aussi enregistrées. Voir Section 4.3.1, « Options de ligne de commande de mysqld ».

5-9-6 - Entretien des fichiers de log

Le serveur MySQL peut créer un grand nombre de fichiers de log différents, qui permettent de suivre ce qui se passe. Voir Section 5.9, « Les fichiers de log de MySQL ». Vous devez toutefois nettoyer régulièrement ces fichiers, pour être sûr que les logs ne prennent pas tout le disque de la machine.

Lorsque vous utilisez MySQL avec des fichiers de log, vous voudrez, de temps en temps, supprimer ou sauvegarder les fichiers, et demander à MySQL d'utiliser de nouveaux fichiers. Voir Section 5.7.1, « Sauvegardes de base de données ».

Sous une installation Linux (Redhat), vous pouvez utiliser le script mysql-log-rotate pour cela. Si vous avez installé MySQL depuis une distribution RPM, le script doit avoir été installé automatiquement. Notez que vous devez être prudent avec cette commande si vous utilisez les logs pour la réplication.

Sur d'autres systèmes, vous devez installer un court script par vous-même, qui sera exécuté via le démon cron.

Vous pouvez forcer MySQL à utiliser de nouveaux fichiers de log en utilisant la commande mysqladmin flush-logs ou avec la commande SQL FLUSH LOGS. Si vous utilisez MySQL version 3.21, vous devez utiliser mysqladmin refresh.

Les commandes ci-dessus effectuent les tâches mentionnées ci-après :

- Si le log standard (--log) ou le log de requêtes lentes (--log-slow-queries) est utilisé, la commande ferme et rouvre le fichier de logs (mysql.log et `hostname`-slow.log par défaut).

- Si le log de modifications est utilisé (--log-update), la commande ferme le log de modifications et ouvre un nouveau fichier, avec un nouveau numéro de séquence plus grand.

Si vous utilisez uniquement le log de modifications, vous pouvez simplement vider les logs sur le disque, et sauver l'ancien fichier de modifications dans une sauvegarde. Si vous utilisez le log normal, vous pouvez faire ceci :

shell> cd mysql-data-directory
shell> mv mysql.log mysql.old
shell> mysqladmin flush-logs

puis faire une sauvegarde du fichier, et le supprimer (mysql.old).

5-10 - Faire fonctionner plusieurs serveurs MySQL sur la même machine

Il y a des situations où vous souhaiterez avoir plusieurs serveurs MySQL sur la même machine. Par exemple, si vous voulez tester une nouvelle version du serveur avec votre configuration de production sans perturber votre installation de production. Ou bien, vous êtes un fournisseur de services Internet, et vous voulez fournir des installations distinctes pour des clients différents.

Si vous voulez exécuter plusieurs serveurs MySQL, le plus simple et de compiler les serveurs avec différents ports TCP/IP et fichiers de sockets pour qu'ils ne soient pas tous à l'écoute du même port ou de la même socket. Voir Section 4.3.1, « Options de ligne de commande de mysqld » et Section 4.3.2, « Fichier d'options my.cnf ».

Au minimum, les options suivantes doivent être différentes sur chaque serveur.

- --port=port_num

--port contrôle le numéro de port des connexions TCP/IP.

- --socket=path

--socket contrôle le chemin de la socket sous Unix, et le nom du pipe nommé sous Windows. Sous Windows, il est nécessaire de spécifier un pipe distinct pour les serveurs qui supportent les connexions par pipes nommés.

- --shared-memory-base-name=name

Cette option ne sert actuellement que sous Windows. Elle désigne la portion de mémoire partagée, utilisée par Windows pour permettre aux clients de se connecter via la mémoire partagée. Cette option est nouvelle en MySQL 4.1.

- --pid-file=path

Cette option ne sert que sous Unix. Elle indique le nom du fichier dans lequel le serveur écrit l'identifiant de processus.

--port contrôle le numéro de port des connexions TCP/IP. --socket contrôle le chemin du fichier de socket sous Unix et le nom du pipe sous Windows. Il est nécessaire d'indiquer des noms de pipe différents sous Windows, uniquement si le serveur supporte les pipes nommés. --shared-memory-base-name désigne le nom du segment de mémoire partagée utilisé par un serveur Windows pour permettre à ses clients de se connecter via la mémoire partagée. --pid-file indique le nom du fichier sur lequel le serveur Unix écrit le numéro de processus.

Si vous utilisez les options suivantes, elles doivent être différentes sur chaque serveur :

- --log=path

- --log-bin=path

- --log-update=path

- --log-error=path

- --log-isam=path

- --bdb-logdir=path

Si vous voulez plus de performances, vous pouvez aussi spécifier les options suivantes différemment pour chaque serveur, pour répartir la charge entre plusieurs disques physiques :

- --tmpdir=path

- --bdb-tmpdir=path

Avoir plusieurs dossiers temporaires comme ci-dessus est aussi recommandé, car il est plus facile pour vous de savoir quel serveur MySQL aura créé quel fichier temporaire.

Généralement, chaque serveur doit aussi utiliser des options différentes pour les dossiers de données, qui est spécifié avec l'option --datadir=path.

Attention : normalement, vous ne devez pas avoir deux serveurs qui modifient en même temps les données dans les mêmes bases. Si votre OS ne supporte pas le verrouillage sans échec, cela peut vous mener à de déplaisantes surprises !

Cette mise en garde contre le partage de données entre deux serveurs s'applique aussi aux environnements NFS. Permettre à plusieurs serveurs MYSQL d'accéder aux mêmes données via NFS est une mauvaise idée !

- Le problème principal est que NFS devient rapidement une limitation en termes de vitesse. Il n'a pas été conçu pour cela.

- Un autre risque avec NFS est que vous devez vous assurer que deux serveurs n'interfèrent pas les uns avec les autres. Généralement, le verrouillage de fichier NFS est fait avec lockd, mais pour le moment, aucune plate-forme ne sera 100 % fiable avec cette technique.

Simplifiez-vous la vie : évitez de partager le même dossier de données entre plusieurs serveurs, via NFS. Une solution plus intelligente est d'avoir un serveur avec plusieurs processeurs, et un système d'exploitation bien optimisé pour les threads.

Si vous avez plusieurs installations de serveurs MySQL a plusieurs endroits, vous pouvez spécifier le dossier de données pour chaque serveur avec l'option --basedir=path, pour que chaque serveur utilise des données différentes, des fichiers de log différents et un PID différent. Les valeurs par défaut de ces options sont relatives au dossier d'installation. Dans ce cas, la seule chose qui reste à adapter est la socket --socket et le --port. Par exemple, supposons que vous installez différentes versions de MySQL en utilisant la distribution binaire .tar. Elles vont être installées en différents dossiers, et vous pouvez lancer le serveur à chaque fois, avec le script ./bin/mysqld_safe de chaque dossier respectif. mysqld_safe va déterminer la bonne option --basedir à passer à mysqld, et vous devrez spécifier --socket et --port à mysqld_safe.

Comme présenté dans les prochaines sections, il est possible de démarrer d'autres serveurs en modifiant des variables d'environnement ou en spécifiant les bonnes options de ligne de commande. Cependant, si vous devez lancer des serveurs de manière récurrente, il sera plus pratique de stocker ces valeurs dans le fichier de configuration.

5-10-1 - Utiliser plusieurs serveurs MySQL un serveur Windows

Vous pouvez utiliser plusieurs serveurs MySQL sur Windows, en lançant manuellement chacun d'entre eux en ligne de commande, avec ses paramètres de fonctionnement appropriés. Sur les systèmes Windows NT, vous pouvez aussi installer plusieurs serveurs comme services Windows, et les faire fonctionner de cette façon. Des instructions générales pour exécuter MySQL depuis la ligne de commande ou comme services sont données dans la section Section 2.2.1, « Installer MySQL sous Windows ». Cette section décrit comment lancer chaque serveur, avec différentes valeurs de démarrage, qui doivent être uniques pour chaque serveur, à commencer par le dossier de données. Ces options sont décrites dans la section Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine ».

5-10-1-1 - Lancer plusieurs serveurs depuis la console

Pour lancer plusieurs serveurs manuellement depuis la ligne de commande, vous pouvez spécifier les options appropriées en ligne de commande, ou dans un fichier d'options. Il est plus pratique de le faire dans un fichier d'options, mais il est nécessaire que chaque serveur utilise bien un fichier d'options différent. Pour cela, créez un fichier pour chaque serveur, et donnez le nom du fichier au serveur avec l'option --defaults-file.

Supposez que vous voulez utiliser mysqld sur le port 3307 avec un dossier de données situé dans C:\mydata1, et mysqld-max sur le port 3308 avec un dossier de données situé dans C:\mydata2. Pour cela, créez deux fichiers d'options. Par exemple créez un fichier appelé C:\my-opts1.cnf qui ressemble à celui-ci :

[mysqld]
datadir = C:/mydata1
port = 3307

Créez un fichier appelé C:\my-opts2.cnf qui ressemble à celui-ci :

[mysqld]
datadir = C:/mydata2
port = 3308

Puis, lancez chaque serveur avec ses propres options :

shell> mysqld --defaults-file=C:\my-opts1.cnf
shell> mysqld-max --defaults-file=C:\my-opts2.cnf

(Sur NT, les serveurs vont se lancer en tâche de fond, et vous devrez ouvrir deux consoles pour lancer les deux commandes séparées.)

Pour éteindre ces deux serveurs, vous devez vos connecter au bon numéro de port :

shell> mysqladmin --port=3307 shutdown
shell> mysqladmin --port=3308 shutdown

Les serveurs configurés comme décrits ci-dessus permettent aux clients de se connecter via un réseau TCP/IP. Si vous voulez aussi utiliser les pipes nommés, utilisez les serveurs mysqld-nt ou mysqld-max-nt et spécifiez les options qui permettent d'activer les pipes nommés et leur nom. Chaque serveur qui supporte les pipes nommés doit avoir un nom de pipe unique. Par exemple, le fichier C:\my-opts1.cnf peut être écrit comme ceci :

[mysqld]
datadir = C:/mydata1
port = 3307
enable-named-pipe
socket = mypipe1

Puis, lancez le serveur comme ceci :

shell> mysqld-nt --defaults-file=C:\my-opts1.cnf

C:\my-opts2.cnf doit être modifié similairement pour l'utiliser avec le second serveur.

5-10-1-2 - Lancer plusieurs serveurs comme services Windows

Sur les systèmes NT, MySQL peut fonctionner comme un service Windows. Les procédures pour installer, contrôler et supprimer un service MySQL sont décrites dans la section Section 2.2.9.1, « Lancer MySQL comme un service Windows ».

Depuis MySQL 4.0.2, vous pouvez installer plusieurs serveurs sous forme de plusieurs services. Dans ce cas, vous devez vous assurer que chaque serveur utilise un nom de service différent, en plus de tous les autres paramètres qui doivent être uniques pour chaque instance.

Pour les instructions suivantes, supposez que vous voulez utiliser le serveur mysqld-nt avec différentes versions de MySQL, qui sont installées dans les dossiers C:\mysql-4.0.8 et C:\mysql-4.0.17, respectivement. Cela peut être le cas si vous utilisez la version 4.0.8 comme serveur de production, mais que vous voulez tester la version 4.0.17 avant de l'utiliser.

Les règles suivantes sont applicables lors de l'installation d'un service MYSQL avec l'option --install.

- Si vous ne spécifiez aucun nom de service, le serveur utilise le nom de service par défaut de MySQL et le serveur lit les options dans le groupe [mysqld], du groupe de fichiers d'options standard.

- Si vous spécifiez un nom de service après l'option --install, le serveur va ignorer le group d'options [mysqld] et lire les options dans le groupe qui a le même nom que le service. Les options seront lues dans le fichier d'options standard.

- Si vous spécifiez --defaults-file après un nom de service, le serveur va ignorer le fichier d'options standard, et lire les options dans le groupe [mysqld] du fichier ainsi nommé.

Note : avant MySQL 4.0.17, seul le serveur utilisant le nom de service par défaut (MySQL) ou un service installé explicitement avec le nom de mysqld lira le groupe d'options [mysqld] dans le fichier d'options. Depuis 4.0.17, tous les serveurs lisent le groupe [mysqld] s'ils lisent dans le fichier d'options standard, même s'ils ont été installés avec un autre nom de service. Cela permet d'utiliser le groupe [mysqld] pour des options qui doivent être utilisées par tous les services MySQL, et un groupe d'options pour chaque service sera utilisé individuellement par chaque service.

En se basant sur les informations précédentes, vous avez plusieurs moyens pour installer des services Windows multiples. Les instructions suivantes décrivent certaines situations. Avant de toutes les essayer, assurez-vous de bien éteindre et supprimer tous les services MySQL existants.

- Approche 1 : spécifiez les options de tous les services dans un fichier d'options. Pour cela, utilisez différents noms de services pour chaque serveur. Supposons que vous vouliez utiliser mysqld-nt 4.0.8 sous le nom de mysqld1 et le mysqld-nt 4.0.17 sous le nom de mysqld2. Dans ce cas, vous pouvez utiliser le groupe [mysqld1] pour le serveur version 4.0.8 et le groupe [mysqld2] pour le serveur version 4.0.17. Par exemple, vous pourriez configurer votre fichier d'options C:\my.cnf ainsi :

# options for mysqld1 service
[mysqld1]
basedir = C:/mysql-4.0.8
port = 3307
enable-named-pipe
socket = mypipe1

# options for mysqld2 service
[mysqld2]
basedir = C:/mysql-4.0.17
port = 3308
enable-named-pipe
socket = mypipe2

Installez les services comme ceci, en utilisant les noms de chemin complet pour vous assurer que Windows trouve les bons programmes pour chaque service :

shell> C:\mysql-4.0.8\bin\mysqld-nt --install mysqld1
shell> C:\mysql-4.0.17\bin\mysqld-nt --install mysqld2

Pour lancer les services, utilisez le gestionnaire de services, ou bien utilisez la commande NET START avec les bons noms de services :

shell> NET START mysqld1
shell> NET START mysqld2

Pour lancer les services, utilisez le gestionnaire de services, ou bien utilisez la commande NET STOP avec les bons noms de services :

shell> NET STOP mysqld1
shell> NET STOP mysqld2

- Approche 2 : spécifiez les options de chaque serveur dans un fichier séparé, et utilisez l'option --defaults-file lorsque vous installez le service pour dire au serveur quel fichier utiliser. Dans ce cas, chaque fichier doit contenir les options du groupe [mysqld].

Avec cette approche, pour spécifier les options du serveur mysqld-nt 4.0.8, il faut créer un fichier C:\my-opts1.cnf qui ressemble à ceci :

[mysqld]
basedir = C:/mysql-4.0.8
port = 3307
enable-named-pipe
socket = mypipe1

Pour la version 4.0.17 de mysqld-nt, créez un fichier C:\my-opts2.cnf qui ressemble à ceci :

[mysqld]
basedir = C:/mysql-4.0.17
port = 3308
enable-named-pipe
socket = mypipe2

Installez les services comme suit (entrez chaque commande comme une seule ligne) :

shell> C:\mysql-4.0.8\bin\mysqld-nt --install mysqld1
--defaults-file=C:\my-opts1.cnf
shell> C:\mysql-4.0.17\bin\mysqld-nt --install mysqld2
--defaults-file=C:\my-opts2.cnf

Pour utiliser l'option --defaults-file lors de l'installation du serveur MySQL comme service, vous devez la faire précéder du nom de service.

Après avoir installé les services, lancez et arrêtez les services de la même façon que dans l'exemple précédent.

Pour supprimer plusieurs services, utilisez la commande mysqld --remove pour chacun d'entre eux, en spécifiant le nom du service, suivi de l'option --remove si le service a un nom qui n'est pas le nom par défaut.

5-10-2 - Utiliser plusieurs serveurs sous Unix

Le plus simple pour utiliser plusieurs serveurs sous Unix, est de le compiler avec différents ports TCP/IP et sockets pour que chacun puisse utiliser une interface réseau différente. De plus, en compilant le serveur dans différents dossiers de base, cela conduit automatiquement à la configuration de différents dossiers de données, fichiers de logs, et PID pour chaque serveur.

Supposons que le serveur existant est configuré avec le numéro de port (3306) et le fichier de sockets par défaut (/tmp/mysql.sock). Pour configurer un nouveau serveur en ayant des paramètres opératoires différents, vous pouvez utiliser le script de configuration configure avec les options suivantes :

shell> ./configure --with-tcp-port=port_number \
--with-unix-socket-path=file_name \
--prefix=/usr/local/mysql-4.0.17

Ici, port_number et file_name doivent être différents des valeurs par défaut de numéro de port et de chemin. La valeur --prefix doit spécifier un dossier d'installation différent de celui dans lequel le serveur existant est installé.

Si vous avez un serveur MySQL qui écoute sur un port donné, vous pouvez utiliser la commande suivante pour connaître ses caractéristiques, y compris son dossier de base et son fichier de sockets :

shell> mysqladmin --host=host_name --port=port_number variables

Avec les informations affichées par la commande, vous pouvez savoir quelles valeurs ne doivent pas être utilisées lors de la configuration du nouveau serveur.

Notez que si vous spécifiez « localhost » comme nom d'hôte, mysqladmin va utiliser par défaut une socket Unix plutôt que TCP/IP. En MySQL 4.1, vous pouvez explicitement spécifier le protocole de connexion avec l'option --protocol={TCP | SOCKET | PIPE | MEMORY}.

Vous n'avez pas à compiler un nouveau serveur MySQL pour le lancer avec un numéro de port et un socket différent. Il est aussi possible de spécifier ces valeurs au moment du démarrage. Une méthode pour faire cela est d'utiliser les options de ligne de commande :

shell> /path/to/mysqld_safe --socket=file_name --port=port_number

Pour utiliser un dossier de données différent, utilisez l'option --datadir=path à mysqld_safe.

Un autre moyen pour arriver au même résultat est d'utiliser les variables d'environnement pour spécifier le nom de la socket et le numéro de port.

shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
shell> MYSQL_TCP_PORT=3307
shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
shell> scripts/mysql_install_db
shell> bin/mysqld_safe &

C'est une méthode rapide pour lancer un second serveur pour le tester. Le plus agréable de cette méthode est que les variables d'environnement vont être adoptées par les logiciels clients que vous invoquerez avec le même Shell. Par conséquent, les connexions seront automatiquement dirigées vers le nouveau serveur.

Annexe E, Variables d'environnement inclut une liste des variables d'environnement que vous pouvez utiliser pour affecter mysqld.

Pour les scripts de lancement automatique, votre script de démarrage qui est exécuté au démarrage doit utiliser la commande suivante avec les options appropriées pour chaque serveur :

mysqld_safe --defaults-file=path-to-option-file

Chaque fichier d'options doit contenir les valeurs spécifiques du serveur.

Sous Unix, le script mysqld_multi est une autre méthode pour lancer plusieurs serveurs. Voir Section 5.1.5, « mysqld_multi, un programme pour gérer plusieurs serveurs MySQL ».

5-10-3 - Utiliser les clients dans un environnement multiserveur

Lorsque vous voulez connecter un client à un serveur MySQL qui écoute sur différentes interfaces réseau que celles que vous utilisez sur votre client, vous devez utiliser les méthodes suivantes.

- Lancez le client avec les options --host=host_name --port=port_number pour vous connecter via TCP/IP sur un hôte distant, ou avec --host=localhost --socket=file_name pour vous connecter localement, via les sockets Unix, ou un pipe nommé Windows.

- Depuis MySQL 4.1, lancez le programme avec l'option --protocol=tcp pour vous connecter via TCP/IP, --protocol=socket pour vous connecter via les sockets Unix, --protocol=pipe pour vous connecter via un pipe nommé, ou --protocol=memory pour vous connecter via la mémoire partagée. Pour TCP/IP, vous aurez peut-être besoin d'indiquer les options d'hôte --host et de port --port. Pour les autres types de connexion, vous aurez peut-être besoin de spécifier l'option --socket pour indiquer la socket ou le pipe nommé, ou encore --shared-memory-base-name pour spécifier la mémoire partagée.

- Sous Unix, configurez les variables d'environnement MYSQL_UNIX_PORT et MYSQL_TCP_PORT pour qu'elles pointent sur la socket Unix et le port TCP/IP que vous voulez, avant de lancer le client. Si vous utilisez normalement une socket ou un port spécifique, vous pouvez placer des commandes pour configurer ces variables dans votre script .login, afin que vous les ayez à chaque connexion. Voir Annexe E, Variables d'environnement.

- Spécifiez la socket par défaut et le port TCP/IP dans le groupe d'options [client] du fichier d'options. Par exemple, vous pouvez utiliser C:\my.cnf sur Windows, ou .my.cnf dans votre dossier racine sous Unix. Voir Section 4.3.2, « Fichier d'options my.cnf ».

- Dans un programme C, vous pouvez spécifier le port ou la socket dans l'appel à mysql_real_connect(). Vous pouvez aussi faire que le programme lise des fichiers d'options en utilisant la fonction mysql_options(). Voir Section 24.2.3, « Description des fonctions de l'API C ».

- Si vous utilisez le module DBD::mysql, vous pourrez lire les options dans les fichiers d'options MySQL. Par exemple :

$dsn = "DBI:mysql:test;mysql_read_default_group=client;"
. "mysql_read_default_file=/usr/local/mysql/data/my.cnf";
$dbh = DBI->connect($dsn, $user, $password);

Voir Section 24.4, « API Perl pour MySQL ».

5-11 - Cache de requêtes MySQL

Depuis la version 4.0.1, le MySQL server bénéficie d'un cache de requêtes. En fait, le cache sauvegarde le texte d'une requête SELECT avec le résultat qui a été envoyé au client. Si une requête identique est appelée par la suite, le serveur retournera le résultat à partir du cache plutôt que d'analyser puis exécuter la requête à nouveau.

Le cache de requêtes est extrêmement utile dans un environnement où les tables ne changent pas souvent, et que vous avez de nombreuses requêtes identiques. C'est la situation classique des serveurs Web, qui génèrent beaucoup de pages dynamiques à partir du même contenu.

Note : le cache de requêtes ne retourne pas de données périmées. À chaque fois que les données sont modifiées, les entrées correspondantes dans le cache sont effacées.

Voici quelques performances du cache de requêtes. (Ces résultats ont été générés en utilisant la suite benchmark MySQL sur un Linux Alpha 2 x 500 MHz avec 2 GB RAM et un cache de requêtes de 64 MB) :

- si toutes les requêtes que vous effectuez sont simples (comme sélectionner un champ d'une table n'en contenant qu'un) mais diffèrent d'une manière que toutes les requêtes ne peuvent être mises en cache, le gain lors de l'utilisation du cache est de 13 %. Cela peut être considéré comme le meilleur des cas. En réalité, les requêtes sont plus compliquées que notre exemple le gain est donc plus petit ;

- les recherches sur une colonne dans une table n'en contenant qu'une sont 238 % plus rapides. Cela peut être considéré comme le gain minimal à attendre pour une requête cachée.

Si vous ne voulez pas utiliser le cache de requêtes paramétrez query_cache_size à zéro. En désactivant le cache de requêtes, il n'y a aucune surcharge apparente. (Le cache de requêtes peut être désactivé à l'aide de l'option de configuration --without-query-cache.)

5-11-1 - Comment fonctionne le cache de requêtes

Cette section décrit le fonctionnement du cache de requêtes lorsque ce dernier est opérationnel. La section Section 5.11.3, « Configuration du cache de requêtes » décrit comment contrôler ce cache, qu'il soit opérationnel ou pas.

Les requêtes sont comparées avant analyse, alors les deux requêtes suivantes seront considérées comme différentes pour le cache de requêtes :

SELECT * FROM tbl_name
Select * from tbl_name

Les requêtes doivent être les mêmes (caractère à caractère) pour être considérées comme identiques. Les requêtes qui utilisent différentes bases de données, différents protocoles ou différents jeux de caractères sont alors considérées comme différentes, et mises en cache différemment.

Si un résultat de requête a été retourné depuis le cache de requêtes, alors la variable Com_select ne sera pas incrémentée, mais Qcache_hits le sera. Voir Section 5.11.4, « Statut du cache de requêtes et maintenance ».

Si une table change (INSERT, UPDATE, DELETE, TRUNCATE, ALTER ou DROP TABLE|DATABASE), alors toutes les requêtes mises en cache qui utilisaient cette table deviennent obsolètes et en sont retirées.

Les tables transactionnelles InnoDB qui ont été modifiées seront rendues obsolètes lorsqu'un COMMIT sera exécuté.

En MySQL 4.0, le cache de requêtes est désactivé dans les transactions : elles ne retournent pas le résultat. Depuis MySQL 4.1.1, le cache de requêtes fonctionne aussi dans les transactions avec les tables InnoDB : le serveur utilise le numéro de version de table pour détecter si le contenu est à jour ou non.

Avant MySQL 5.0, une requête qui commence avec un commentaire peut être mise en cache, mais ne sera jamais lue depuis le cache. Ce problème est résolu en MySQL 5.0.

Le cache de requêtes fonctionne pour les requêtes SELECT SQL_CALC_FOUND_ROWS ... et SELECT FOUND_ROWS(). Les requêtes FOUND_ROWS() retournent la valeur correcte même si la requête précédente a aussi été lue dans le cache, car le nombre de lignes lues est conservé dans le cache.

Une requête ne peut être mise en cache si elle contient l'une des fonctions suivantes :

BENCHMARK()

CONNECTION_ID()

CURDATE()

CURRENT_DATE()

CURRENT_TIME()

CURRENT_TIMESTAMP()

CURTIME()

DATABASE()

ENCRYPT() avec un paramètre

FOUND_ROWS()

GET_LOCK()

LAST_INSERT_ID()

LOAD_FILE()

MASTER_POS_WAIT()

NOW()

RAND()

RELEASE_LOCK()

SYSDATE()

UNIX_TIMESTAMP() sans paramètre

USER()

Une requête ne sera pas mise en cache dans ces conditions :

- elle contient des fonctions définies par l'utilisateur : UDF ;

- elle contient des variables utilisateur ;

- elle fait référence à des tables de la base mysql ;

- elle est de l'une des formes suivantes :

SELECT ... IN SHARE MODE
SELECT ... INTO OUTFILE ...
SELECT ... INTO DUMPFILE ...
SELECT * FROM ... WHERE autoincrement_col IS NULL

La dernière forme n'est pas mise en cache, car elle est utilisée comme palliatif pour ODBC, afin d'obtenir la dernière valeur insérée. Voir Section 25.1.14.1, « Comment obtenir la valeur d'une colonne AUTO_INCREMENT avec ODBC » ;

- Elle utilise une table TEMPORARY ;

- Elle n'utilise pas de table ;

- L'utilisateur a un droit de niveau colonne pour l'une des tables impliquées ;

- Avant la lecture de la requête dans le cache de requêtes, MySQL vérifie que l'utilisateur a les droits SELECT pour toutes les bases de données impliquées. Si ce n'est pas le cas, le résultat n'est pas utilisé.

5-11-2 - Options relatives au cache de requêtes dans un SELECT

Il y a deux options relatives au cache de requêtes qui peuvent être utilisées dans une requête SELECT.

- SQL_CACHE

Le résultat de la requête est en cache si la valeur de la variable système query_cache_type est à ON ou DEMAND.

- SQL_NO_CACHE

Le résultat de la requête n'est pas mis en cache.

Exemples :

SELECT SQL_CACHE id, name FROM customer;
SELECT SQL_NO_CACHE id, name FROM customer;

5-11-3 - Configuration du cache de requêtes

La variable système serveur have_query_cache indique si le cache est actif :

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+

Le cache de requêtes ajoute plusieurs variables système MySQL liées à mysqld qui peuvent être spécifiées dans un fichier de configuration, en ligne de commande lors du démarrage de mysqld. Les variables système liées au cache sont toutes préfixées avec query_cache_. Elles sont décrites brièvement dans la section Section 5.2.3, « Variables serveur système », avec des informations complémentaires.

Pour configurer la taille du cache de requêtes, modifiez la variable système query_cache_size. En lui donnant la valeur de 0, vous le désactivez. La taille par défaut du cache est de 0 : le cache est désactivé par défaut.

Si le cache de requêtes est actif, la variable query_cache_type modifie son comportement. Cette variable peut prendre les valeurs suivantes.

- La valeur de 0 ou OFF empêche la mise en cache ou la lecture de résultats en cache.

- La valeur de 1 ou ON permet le cache, sauf pour les commandes qui commencent par SELECT SQL_NO_CACHE.

- La valeur de 2 ou DEMAND impose la mise en cache de toutes les requêtes, même celles qui commencent par SELECT SQL_CACHE.

Modifier la valeur GLOBAL de query_cache_type détermine le comportement du cache pour tous les clients qui se connecteront après la modification. Les clients individuels peuvent modifier le comportement du cache pour leur connexion avec l'option SESSION de query_cache_type. Par exemple, un client peut désactiver le cache de requêtes pour ses propres requêtes avec :

mysql> SET SESSION query_cache_type = OFF;

Pour contrôler la taille maximale des résultats de requêtes qui peuvent être mis en cache, il faut modifier la valeur de la variable query_cache_limit. La valeur par défaut de 1 Mo.

Le résultat d'une requête (les données envoyées au client) est stocké dans le cache durant la lecture. Par conséquent, les données ne sont pas manipulées en un seul gros morceau. Le cache de requête  alloue des blocs à la demande, pour stocker les données, et dès qu'un bloc est rempli, un autre est alloué. Comme l'allocation de mémoire est une opération coûteuse (en temps), le cache de requêtes crée des blocs avec une taille minimale de query_cache_min_res_unit, jusqu'à la taille des données à mettre en cache. Suivant le type de requêtes exécutées, vous pourrez adapter la valeur de la variable query_cache_min_res_unit :

- la valeur par défaut de query_cache_min_res_unit est 4 Ko. Cela doit être adapté la plupart des situations ;

- si vous avez beaucoup de requêtes avec de petits résultats, la taille par défaut sera un peu grande, et conduit à une fragmentation inutile de la mémoire, indiquée par un grand nombre de blocs libres. La fragmentation va forcer le cache à effacer d'anciennes requêtes pour libérer de la place. Dans ce cas, réduisez la valeur de query_cache_min_res_unit. Le nombre de blocs libres et de requêtes supprimées pour libérer de la place est stocké dans les variables Qcache_free_blocks et Qcache_lowmem_prunes ;

- si la plupart de vos requêtes ont de grands résultats (vérifiez les variables Qcache_total_blocks et Qcache_queries_in_cache), vous pouvez augmenter la valeur de query_cache_min_res_unit. Cependant, soyez prudent de ne pas agrandir trop la valeur (voir point précédent).

query_cache_min_res_unit a été ajoutée en MySQL 4.1.

5-11-4 - Statut du cache de requêtes et maintenance

Vous pouvez vérifier que vous avez le cache de requêtes sur MySQL avec la commande suivante :

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

Avec la commande FLUSH QUERY CACHE, vous pouvez défragmenter le cache de requêtes pour mieux en utiliser la mémoire. Cette commande n'effacera aucune requête du cache.

La commande RESET QUERY CACHE efface tous les résultats de requêtes du cache. FLUSH TABLES aussi.

Vous pouvez visualiser les performances du cache de requêtes avec SHOW STATUS:

mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+--------+
| Variable_name           | Value  |
+-------------------------+--------+
| Qcache_free_blocks      | 36     |
| Qcache_free_memory      | 138488 |
| Qcache_hits             | 79570  |
| Qcache_inserts          | 27087  |
| Qcache_lowmem_prunes    | 3114   |
| Qcache_not_cached       | 22989  |
| Qcache_queries_in_cache | 415    |
| Qcache_total_blocks     | 912    |
+-------------------------+--------+

La description de chaque variable est présentée dans la section Section 5.2.4, « Variables de statut du serveur  ». Certaines utilisations sont présentées ici.

Le nombre total de commandes SELECT vaut :

Com_select
+ Qcache_hits
+ requêtes avec une erreur

La valeur de Com_select est :

Qcache_inserts
+ Qcache_not_cached
+ erreurs de droits d'accès ou de colonnes

Le cache de requêtes utilise des blocs de longueur variable, ce qui fait que Qcache_total_blocks et Qcache_free_blocks peuvent indiquer une fragmentation de la mémoire du cache. Après un appel à FLUSH QUERY CACHE un seul (grand) bloc libre subsiste.

Note : chaque requête a besoin au minimum de deux blocs (un pour le texte de la requête et un autre, ou plus, pour le résultat). De même, chaque table utilisée par une requête a besoin d'un bloc, mais si deux ou plusieurs requêtes utilisent la même table, seul un bloc a besoin d'être alloué.

Vous pouvez aussi utiliser la variable Qcache_lowmem_prunes pour ajuster la taille du cache de requêtes. Elle compte le nombre de requêtes qui ont été supprimées du cache pour libérer de la place pour les nouvelles requêtes. Le cache de requêtes utilise une stratégie du type la plus anciennement utilisée (least recently used ou LRU) pour décider de quelle requête doit être retirée. Des informations de paramétrage sont données dans la section Section 5.11.3, « Configuration du cache de requêtes ».

6 - Réplication de MySQL

Les possibilités de réplication, permettant à un serveur d'être recopié à l'identique sur un autre serveur, ont été introduites en MySQL 3.23.15. Cette section décrit les différentes fonctionnalités de la réplication MySQL. Elle sert de référence pour les options disponibles avec la réplication. Vous y trouverez une introduction à la réplication.

Vers la fin, vous y trouverez les questions et problèmes les plus fréquents, avec leur solution.

Pour une description de la syntaxe des commandes de réplication, voyez Section 13.6, « Commandes de réplication ».

Nous vous suggérons de visiter notre site web http://www.mysql.com/ souvent pour y lire les mises à jour de cette section. La réplication est constamment améliorée, et nous modifions souvent le manuel.

6-1 - Introduction à la réplication

Depuis la version 3.23.15, MySQL supporte la réplication unidirectionnelle interne. Un serveur sert de maître, et les autres serveurs servent d'esclaves. Le serveur entretient des logs binaires de toutes les modifications qui surviennent. Il entretient aussi un fichier d'index des fichiers de logs binaires, pour garder la trace de la rotation des logs. Chaque esclave, après connexion réussie au serveur maître, indique au maître le point qu'il avait atteint depuis la fin de la dernière réplication, puis rattrape les dernières modifications qui ont eu lieu, puis se met en attente des prochains événements en provenance du maître.

Un esclave peut aussi servir de maître à son tour, pour réaliser une chaîne de réplication.

Notez que lorsque vous utilisez la réplication, toutes les modifications de tables sont répliquées, et doivent intervenir sur le serveur maître. Sinon, vous devez être prudents dans vos interventions, pour ne pas créer de conflits entre les modifications de tables sur le maître et celles qui interviennent sur l'esclave.

La réplication unidirectionnelle permet de renforcer la robustesse, la vitesse et l'administration du serveur.

- La robustesse est augmentée par la configuration maître/esclave. Dans le cas où un problème survient sur le maître, vous pouvez utiliser un esclave comme serveur de secours.

- L'accélération provient de la répartition de la charge de traitement des requêtes clients entre le maître et les esclaves, permettant un meilleur temps de réponse. Les requêtes SELECT peuvent être envoyées aux esclaves pour réduire la charge du maître. Les requêtes de modifications des données sont envoyées au maître, qui les transmettra aux esclaves. Cette stratégie de répartition de charge est efficace si les lectures sont plus nombreuses que les écritures, ce qui est la situation la plus courante.

- Un autre avantage de la réplication est que vous pouvez faire des sauvegardes non bloquantes de vos données sur l'esclave et non plus sur le serveur principal : ce dernier n'est pas perturbé. Voir Section 5.7.1, « Sauvegardes de base de données ».

6-2 - Présentation de l'implémentation de la réplication

La réplication MySQL est basée sur le fait que le serveur va garder la trace de toutes les évolutions de vos bases (modifications, effacements, etc.) dans un fichier de logs binaire et les esclaves vont lire les requêtes du maître dans ce fichier de logs, pour pouvoir exécuter les mêmes requêtes sur leurs copies. Voir Section 5.9.4, « Le log binaire ».

Il est très important de comprendre que le fichier de logs binaire est simplement un enregistrement des modifications depuis un point fixe dans le temps (le moment où vous activez le log binaire). Tous les esclaves que vous activez auront besoin de la copie des données qui existaient au moment du démarrage du log. Si vous démarrez vos esclaves sans qu'ils ne disposent des données identiques à celles du maître au moment du démarrage du log binaire, votre réplication va échouer.

Depuis la version 4.0.0, vous pouvez utiliser la commande LOAD DATA FROM MASTER pour configurer un esclave. Soyez bien conscient qu'actuellement, LOAD DATA FROM MASTER ne fonctionne que si toutes les tables du maître sont du type MyISAM, et qu'il est possible d'obtenir un verrou de lecture global, pour qu'aucune lecture ne se fasse durant le transfert des tables depuis le maître. Cette limitation est de nature temporaire, et elle est due au fait que nous n'avons pas encore programmé un système de sauvegarde des tables sans verrou. La limitation sera supprimée dans la future version 4.0 une fois que nous aurons programmé le système de sauvegarde, qui permettra à LOAD DATA FROM MASTER de fonctionner sans bloquer le maître.

Étant donné la limitation ci-dessus, nous vous recommandons actuellement d'utiliser la commande LOAD DATA FROM MASTER uniquement si le jeu de données du maître est petit, ou si un verrou prolongé sur le maître est acceptable. Suivant la vitesse de lecture de LOAD DATA FROM MASTER en fonction des systèmes, une règle de base indique que le transfert se fera au rythme de 1 Mo par seconde. Vous pourrez ainsi obtenir une estimation du temps qu'il vous faudra pour transférer les données, si le maître et l'esclave sont connectés sur un réseau de 100 MBit/s, avec des configurations à base de Pentium 700 MHz. Bien sûr, votre cas particulier pourra varier en fonction de votre système : la règle ci-dessus vous donnera une première évaluation du temps à attendre.

Une fois que l'esclave est correctement configuré, et qu'il fonctionne, il va simplement se connecter au maître et attendre des requêtes de modifications. Si le maître est indisponible ou que l'esclave perd la connexion avec le maître, il va essayer de se reconnecter toutes les master-connect-retry secondes jusqu'à ce qu'il soit capable d'établir la communication, et de recommencer à appliquer les modifications.

Chaque esclave garde la trace du point où il en était rendu. Le serveur maître n'a pas de notions du nombre d'esclaves qui se connectent, ou qui sont à jour à un moment donné.

6-3 - Détails d'implémentation de la réplication

Les capacités de réplication de MySQL sont implémentées à l'aide de trois threads : un thread sur le maître et deux sur l'esclave. Lorsque la commande START SLAVE est envoyée, l'esclave crée un thread d'I/O (Entrée/Sortie). Le thread d'I/O se connecte au maître et lit les commandes qui ont été stockées dans le log binaire. Le maître crée un thread pour envoyer le contenu des logs binaire à l'esclave. Ce thread peut être identifié comme le thread Binlog Dump dans le résultat de la commande SHOW PROCESSLIST. Le thread esclave I/O lit ce que le thread maître Binlog Dump lui envoie, et le stocke dans un fichier local à l'esclave. Le troisième thread SQL lit ces commandes et les exécute.

Dans la description précédente, il y a trois threads par esclave. Pour un maître avec de nombreux esclaves, il crée un thread par esclave simultanément connecté, et chaque esclave a son propre thread I/O et SQL.

Pour les versions de MySQL avant 4.0.2, la réplication implique uniquement deux threads : un sur le maître et un sur l'esclave. Les threads I/O et SQL sont combinés en un seul thread, et il n'y a pas de log de relais.

L'avantage d'utiliser deux threads est que la lecture et l'exécution des requêtes sont découplées. La tâche de lecture n'est pas ralentie par l'exécution. Par exemple, si l'esclave n'a pas fonctionné depuis un bon moment, le thread d'I/O peut lire rapidement le contenu de toutes les commandes à appliquer, même si le thread SQL met du temps à les concrétiser. Si l'esclave s'arrête avant que toutes les commandes n'aient été exécutées, le thread d'I/O aura au moins lu les commandes, et elles sont désormais locales. Cela permettra au maître de purger ces lignes, si les autres esclaves n'en ont pas besoin non plus.

La commande SHOW PROCESSLIST affiche des informations qui vous indiquent ce qui se passe sur le maître et sur l'esclave, concernant la réplication.

L'exemple ci-dessous montre les trois threads dans le résultat de SHOW PROCESSLIST. Le format qui est présenté est celui de SHOW PROCESSLIST pour MySQL version 4.0.15, où le contenu de la colonne State a été changé pour être plus significatif.

Sur le serveur maître, le résultat de SHOW PROCESSLIST ressemble à ceci :

mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL

Ici, le thread 2 est le thread de réplication pour un esclave connecté. L'information indique que toutes les requêtes ont été envoyées à l'esclave, et que le maître attend de nouvelles instructions.

Sur le serveur esclave, le résultat de SHOW PROCESSLIST ressemble à ceci :

mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 10
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 11
User: system user
Host:
db: NULL
Command: Connect
Time: 11
State: Has read all relay log; waiting for the slave I/O
thread to update it
Info: NULL

Cette information indique que le thread 10 est le thread d'I/O, en communication avec le serveur, et le thread 11 est le thread SQL, qui traite les commandes stockées dans le log de relais. Actuellement, les deux threads sont oisifs, et attendent des instructions.

Notez que la valeur de la colonne Time vous indique le retard de l'esclave par rapport au maître. Voir Section 6.9, « FAQ de la réplication ».

6-3-1 - État de réplication du maître

La liste suivante montre les états les plus courants que vous verrez dans la colonne State pour le thread maître Binlog Dump. Si vous ne voyez pas le thread Binlog Dump sur le maître, la réplication ne fonctionne pas. C'est-à-dire qu'aucun esclave n'est connecté.

- Envoi de log binaire à l'esclave (Sending binlog event to slave)

Le log binaire contient les événements, qui sont les commandes de modifications des tables, ainsi que d'autres informations supplémentaires. Le thread a lu un événement dans le log binaire, et il l'envoie à l'esclave.

- Fini de lire le log binaire. Passe au fichier de logs suivant (Finished reading one binlog; switching to next binlog)

Le thread a fini de lire le fichier de logs binaire, et il en ouvre un nouveau, pour l'envoyer à l'esclave.

- A envoyé tous les logs binaires à l'esclave ; attente de nouveaux événements dans le log binaire (Has sent all binlog to slave; waiting for binlog to be updated)

Le thread a lu toutes les commandes de modification dans le log binaire, et les a envoyées à l'esclave. Il est inactif, attend de nouveaux événements dans le log binaire pour reprendre ses activités.

- Attente de la finalisation (Waiting to finalize termination)

Un état très bref qui survient lorsque le thread s'arrête.

6-3-2 - États du thread esclave d'E/S

La liste suivante montre les états les plus courants que vous verrez dans la colonne State pour le thread esclave d'entrée/sortie. Depuis 4.1.1, cette information apparaît aussi dans la colonne Slave_IO_State affichée par la commande SHOW SLAVE STATUS. Cela signifie que vous pouvez avoir une bonne idée de ce qui se passe juste avec SHOW SLAVE STATUS.

- Connexion au maître (Connecting to master)

Le thread tente de se connecter au maître

- Vérification de la version du maître (Checking master version)

Un état très bref qui survient juste après la connexion au maître.

- Enregistrement de l'esclave auprès du maître (Registering slave on master)

Un état très bref qui survient juste après la connexion au maître.

- Demande de l'export du log binaire (Requesting binlog dump)

Un état très bref qui survient juste après la connexion au maître. Le thread envoie une requête au maître pour obtenir le contenu des logs binaires, en indiquant le fichier de logs et la position de démarrage.

- Attente de reconnexion avec un échec de demande de log binaire (Waiting to reconnect after a failed binlog dump request)

Si la demande de log binaire a échoué (à cause d'une déconnexion), le thread passe dans cet état durant sa mise en sommeil, et essaie de se reconnecter périodiquement. L'intervalle entre deux tentative est spécifié avec l'option --master-connect-retry.

- Reconnexion avec un échec de demande de log binaire (Reconnecting after a failed binlog dump request)

Le thread tente de se reconnecter au maître.

- Attente d'informations de la part du maître (Waiting for master to send event)

Le thread est connecté au maître, et il attend les événements du log binaire. Cela peut durer longtemps si le maître est inactif. Si l'attente de prolonge au-delà de slave_read_timeout secondes, un dépassement de délai survient. À ce moment, le thread considère que la connexion est perdue, et il va se reconnecter.

- Ajoute un événement au log de relais (Queueing master event to the relay log)

Le thread a lu un événement, et il le copie dans le log de relais, pour que le thread SQL puisse le lire.

- Attente de reconnexion après un échec de lecture d'événement (Waiting to reconnect after a failed master event read)

Une erreur est survenue durant la lecture, à cause d'une déconnexion. Le thread est en sommeil pour master-connect-retry secondes avant de tenter de se reconnecter.

- Reconnexion après un échec de lecture d'événement (Reconnecting after a failed master event read)

Le thread tente de se reconnecter au maître. Lorsque la reconnexion est faite, l'état deviendra Waiting for master to send event.

- Attente d'espace pour le log de relais auprès du thread SQL (Waiting for the slave SQL thread to free enough relay log space)

Si vous utilisez une valeur relay_log_space_limit non nulle, et que le log de relais a atteint sa taille maximale, le thread d'E/S va attendre que le thread SQL ait libéré suffisamment d'espace en traitant les requêtes pour qu'il puisse effacer un des fichiers de logs.

- Attente du mutex de l'esclave (Waiting for slave mutex on exit)

Un état très bref qui survient juste à l'extinction.

6-3-3 - États des esclaves de réplication

La liste suivante présente les différents types les plus courants de valeurs de la colonne State pour un esclave SQL.

- Lecture d'un événement dans le log de relais (Reading event from the relay log)

Le thread a lu un événement dans le log de relais, et il le traite.

- A lu tous les logs de relais ; attente de l'esclave d'E/S (Has read all relay log; waiting for the slave I/O thread to update it)

Le thread a traité tous les événements dans le log de relais et attend que le thread écrive de nouveaux événements dans le log de relais.

- Attente du mutex de l'esclave pour terminer (Waiting for slave mutex on exit)

Un état très bref qui survient lorsque le thread s'arrête.

La colonne State du thread d'E/S peut aussi afficher une commande. Cela indique que le thread a lu un événement dans le log de relais, a extrait la commande et est en train de l'exécuter.

6-3-4 - Fichiers de relais et de statut de la réplication

Par défaut, les logs de relais sont nommés en utilisant des noms de la forme host_name-relay-bin.nnn, où host_name est le nom de l'hôte serveur esclave, et nnn est un numéro de séquence. Les fichiers de logs de relais successifs sont créés en utilisant une séquence de nombre commençant à 001. L'esclave garde la trace des logs avec un fichier d'index. Le nom du fichier d'index des logs de relais est host_name-relay-bin.index. Par défaut, ces fichiers sont créés dans le dossier de données de l'esclave. Les noms par défaut peuvent être remplacés grâce aux options --relay-log et --relay-log-index du serveur. Voir Section 6.8, « Options de démarrage de la réplication ».

Les logs de relais ont le même format que les logs binaires, et ils peuvent être lus avec mysqlbinlog. Un log de relais est automatiquement effacé par le thread SQL aussitôt qu'il n'en a plus besoin : c'est-à-dire aussitôt qu'il en a exécuté les commandes. Il n'y a pas de commande pour effacer les logs de relais, car le thread SQL se charge de le faire. Toutefois, depuis MySQL 4.0.14, la commande FLUSH LOGS effectue la rotation des logs de relais, qui influence leur effacement par le thread SQL.

Un nouveau log de relais est créé dans les conditions suivantes.

- La première fois qu'un thread d'I/O démarre après le démarrage du serveur. Avec MySQL 5.0, un nouveau log de relais sera créé chaque fois que le thread d'I/O démarre, et pas seulement la première fois.

- Une commande FLUSH LOGS ou mysqladmin flush-logs est émise (MySQL 4.0.14 et plus récent uniquement).

- La taille du log de relais courant est trop grosse. « trop grosse » signifie :

- max_relay_log_size, si max_relay_log_size > 0

- max_binlog_size, si max_relay_log_size = 0 ou si MySQL est plus ancien que la version 4.0.14.

Un serveur de réplication esclave crée deux autres petits fichiers dans le dossier de données. Ces fichiers sont appelés master.info et relay-log.info par défaut. Ils contiennent des informations comme celles affichées par la commande SHOW SLAVE STATUS (voir Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication » pour une description de cette commande). En tant que fichiers disque, ils survivent à l'extinction de l'esclave. Au prochain démarrage de l'esclave, ce dernier peut lire ces fichiers pour savoir où il en était du traitement des événements du maître et de leur lecture.

Le fichier master.info est modifié par le thread d'I/O. Avant la version 4.1, la correspondance entre les lignes du fichier et les colonnes affichées par SHOW SLAVE STATUS est la suivante :

Ligne

Description

1

Master_Log_File

2

Read_Master_Log_Pos

3

Master_Host

4

Master_User

5

Mot de passe (pas affiché par SHOW SLAVE STATUS)

6

Master_Port

7

Connect_Retry

Depuis MySQL 4.1, le fichier inclut un compteur de lignes et des informations sur les options SSL :

Line

Description

1

Nombre de lignes dans le fichier

2

Master_Log_File

3

Read_Master_Log_Pos

4

Master_Host

5

Master_User

5

Mot de passe (pas affiché par SHOW SLAVE STATUS)

7

Master_Port

8

Connect_Retry

9

Master_SSL_Allowed

10

Master_SSL_CA_File

11

Master_SSL_CA_Path

12

Master_SSL_Cert

13

Master_SSL_Cipher

14

Master_SSL_Key

Le fichier relay-log.info est modifié par le thread SQL. La correspondance entre les lignes du fichier et les colonnes affichées par SHOW SLAVE STATUS est la suivante :

Ligne

Description

1

Relay_Log_File

2

Relay_Log_Pos

3

Relay_Master_Log_File

4

Exec_Master_Log_Pos

Lorsque vous sauvegardez les données de votre esclave, vous devriez aussi sauver ces deux fichiers, ainsi que les logs de relais. Ils sont nécessaires pour reprendre la réplication après une restauration de la base. Si vous perdez les logs de relais, mais avez encore le fichier relay-log.info, vous pouvez l'étudier pour déterminer ce que le thread SQL a traité des logs binaires du maître. Puis, vous pouvez utiliser CHANGE MASTER TO avec les options MASTER_RELAY_LOG et MASTER_RELAY_POS pour dire au thread d'I/O de relire les logs depuis ce point. Cela impose que ces logs sont toujours disponibles sur le serveur.

Si votre esclave doit répliquer une commande LOAD DATA INFILE, vous devriez aussi sauver les fichiers SQL_LOAD-* qui existent dans le dossier que l'esclave utilise à cette fin. L'esclave aura besoin de ces fichiers pour reprendre la réplication des commandes LOAD DATA INFILE. Le chemin du dossier est spécifié avec l'option --slave-load-tmpdir. Sa valeur par défaut est tmpdir.

6-4 - Comment mettre en place la réplication

Voici les instructions pour mettre en place la réplication sur votre serveur MySQL. Nous supposons que vous voulez répliquer toutes vos bases, et que vous ne l'avez jamais configuré auparavant. Vous aurez besoin d'éteindre brièvement le serveur principal pour suivre toutes les instructions.

La procédure est écrite pour configurer un esclave seul, mais elle peut être répétée pour configurer plusieurs esclaves.

Si cette méthode n'est pas la plus simple pour configurer un esclave, ce n'est pas la seule. Par exemple, si vous avez déjà une sauvegarde des données du maître, et que le maître a déjà un identifiant de serveur, et le log binaire activé, vous pouvez configurer l'esclave sans éteindre le serveur et sans bloquer les mises à jour. Pour plus de détails, voyez Section 6.9, « FAQ de la réplication ».

Si vous voulez administrer une architecture de réplication MySQL, nous vous suggérons de commencer par étudier, tester et expérimenter toutes les commandes mentionnées dans les chapitres Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication » et Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication ». Vous devriez aussi vous familiariser avec les options de démarrage décrites dans la section Section 6.8, « Options de démarrage de la réplication ».

1. Assurez-vous que vous avez une version récente de MySQL installée comme maître et comme esclave. Assurez-vous que ces versions sont compatibles entre elles, conformément à la table présentée dans la section Section 6.6, « Changer de version de réplication ».

Ne nous rapportez pas de bogues tant que vous n'avez pas vérifié que le problème persiste dans la dernière version de MySQL.

2. Créez un utilisateur MySQL spécial pour la réplication sur le maître, avec les droits de FILE (dans les versions plus anciennes que la versions 4.0.2) ou le droit de REPLICATION SLAVE pour les nouvelles versions. Vous devez aussi lui donner les droits de connexion depuis tous les esclaves. Si l'utilisateur ne fait que de la réplication (ce qui est recommandé), vous n'avez pas à lui donner d'autres droits.

Le nom d'hôte du compte doit être tel que chaque serveur esclave peut l'utiliser pour se connecter au maître. Par exemple, pour créer un utilisateur appelé repl qui peut accéder au maître, vous pourriez utiliser une commande comme :

mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%' IDENTIFIED BY '<password>';

Pour les versions de MySQL antérieures à la 4.0.2, utilisez cette commande :

mysql> GRANT FILE ON *.* TO repl@'%' IDENTIFIED BY '<password>';

Si vous envisagez d'utiliser LOAD TABLE FROM MASTER ou LOAD DATA FROM MASTER sur l'esclave, vous devez donner les droits supplémentaires suivants :

- Donnez le droit de SUPER et RELOAD.

- Donnez le droit de SELECT pour toutes les tables que vous voulez charger. Toutes les tables maîtres dans lesquelles l'esclave ne pourra pas utiliser SELECT seront ignorées par LOAD DATA FROM MASTER.

3. Si vous utilisez des tables MyISAM, déchargez toutes les tables et blocs en utilisant la commande FLUSH TABLES WITH READ LOCK.

mysql> FLUSH TABLES WITH READ LOCK;

puis faire une sauvegarde des données de votre maître.

Le plus simple pour cela (sous Unix) et d'utiliser la commande tar pour produire une archive de votre dossier de données total. Le dossier de données dépend de votre installation.

shell> tar -cvf /tmp/mysql-snapshot.tar .

Si vous voulez que vos archives incluent seulement une base de données appelée cette_base, utilisez cette commande :

shell> tar -cvf /tmp/mysql-snapshot.tar ./cette_base

Puis copiez le fichier d'archive dans le dossier /tmp sur le serveur esclave. Sur cette machine, placez-vous dans le dossier de données du serveur et décompressez l'archive locale avec cette commande :

shell> tar -xvf /tmp/mysql-snapshot.tar

Il n'est pas besoin de répliquer la base mysql. Si c'est le cas, vous pouvez l'exclure de votre archive. Vous n'avez pas besoin d'inclure les fichiers de logs dans l'archive, ou les fichiers master.info ou relay-log.info.

Lorsque le verrou de lecture a été posé par FLUSH TABLES WITH READ LOCK et est en action, lisez les valeurs courantes du fichier de logs et de son offset sur le maître :

mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73       | test,bar     | foo,manual,mysql |
+---------------+----------+--------------+------------------+
1 row in set (0.06 sec)

La colonne File montre le nom du fichier de logs, et la colonne Position affiche l'offset. Dans l'exemple ci-dessus, le nom du fichier de logs est mysql-bin.003 et son offset est 73. Notez ces valeurs. Vous en aurez besoin pour configurer l'esclave.

Une fois que vous avez pris une sauvegarde et enregistré le nom de fichier, et son offset, vous pouvez réactiver l'activité sur votre maître :

mysql> UNLOCK TABLES;

Si vous utilisez des tables InnoDB, l'outil idéal est InnoDB Hot Backup, qui est disponible pour ceux qui achètent des licences commerciales MySQL, du support ou l'outil lui-même. Il fait une sauvegarde cohérente du maître, enregistre le nom du fichier de logs binaire et son offset, pour que cette archive soit directement utilisée par l'esclave plus tard. Pour plus d'informations sur cet outil, voyez http://www.innodb.com/order.php.

Sans Hot Backup, le mieux pour faire une sauvegarde rapide d'une base InnoDB est d'arrêter le serveur, puis de copier les fichiers de données InnoDB, leurs logs, et leur fichier de définitions (.frm). Pour enregistrer le fichier de logs courant et son offset, vous devez utiliser les commandes suivantes lors de l'extinction du serveur :

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

Ensuite, enregistrer le nom du fichier et son offset, lu dans le résultat de la commande SHOW MASTER STATUS présentée précédemment. Une fois que vous avez ces informations, éteignez le serveur sans déverrouiller les tables, pour vous assurer qu'il va bien s'arrêter dans l'état que vous avez noté :

shell> mysqladmin -uroot shutdown

Une autre solution, valable pour les deux types de tables MyISAM et InnoDB, est de prendre un export SQL du maître, au lieu d'une copie binaire. Pour cela, vous pouvez utiliser l'utilitaire mysqldump --master-data sur votre maître, puis exécuter les commandes SQL sur votre esclave. Toutefois, c'est plus lent que de faire une copie binaire.

Si le maître fonctionnait sans l'option --log-bin, le nom du fichier de logs et l'offset seront vides, lorsqu'ils sont demandés à SHOW MASTER STATUS et mysqldump sera vide aussi. Dans ce cas, utilisez la chaîne vide ('') comme nom de fichier de logs, et la valeur 4 comme offset.

4. Dans le fichier my.cnf du maître, ajoutez les options log-bin et server-id=unique number, où master_id doit être un entier positif entre 1 et 2^32 - 1, à la section [mysqld] et redémarrez le serveur. Il est très important que l'identifiant des esclaves soit différent de celui du maître. Pensez à server-id comme à une valeur comparable à une adresse IP : elle identifie de manière unique un serveur dans la communauté des réplicateurs.

[mysqld]
log-bin
server-id=1

Si ces options ne sont pas présentes, ajoutez-les, et redémarrez le serveur.

5. Arrêtez le serveur qui va servir d'esclave, et ajoutez les lignes suivantes dans son fichier my.cnf :

[mysqld]
server-id=slave_id

La valeur de slave_id, comme la valeur de master_id, doit être un entier, entre 1 et 2^32 - 1. De plus, il est très important que l'identifiant de l'esclave soit différent de celui du maître. Par exemple :

[mysqld]
server-id=2

Si vous configurez plusieurs esclaves, chacun d'entre eux doit avoir une valeur server-id distincte de celle du maître et des autres esclaves. Pensez aux server-id comme étant des adresses IP : ces identifiants repèrent de manière unique un esclave dans la communauté de réplication.

Si vous ne spécifiez pas de valeur pour server-id, il prendra la valeur de 1 si vous n'avez pas défini de valeur pour master-host, sinon, il prendra la valeur de 2. Notez que dans le cas où vous omettez server-id, un maître refusera la connexion à tous les esclaves. Par conséquent, omettre server-id est uniquement valable pour des opérations de sauvegarde avec log binaire.

6. Copiez la sauvegarde des données dans vos esclaves. Assurez-vous que les droits sur ces données sont corrects. L'utilisateur qui fait fonctionner MySQL doit avoir les droits d'écriture et de lecture sur ces fichiers, tout comme le maître l'avait.

Si vous avez fait une sauvegarde avec mysqldump, lancez d'abord les esclaves (voir prochaine étape).

7. Redémarrez les esclaves. S'ils étaient déjà configurés pour la réplication, lancez les esclaves avec l'option --skip-slave-start. Vous pouvez aussi les lancer avec l'option --log-warnings. De cette manière, vous aurez plus de détails sur les problèmes que les esclaves rencontreront (problèmes réseau, d'identification, etc.)

8. Si vous avez fait une sauvegarde du maître avec l'utilitaire mysqldump, chargez l'export avec la commande suivante :

shell> mysql -u root -p < dump_file.sql

9. Exécutez la commande sur l'esclave, en remplaçant les valeurs entre crochets <> par les valeurs que vous aviez lues sur le maître, ou qui sont valables pour votre système :

mysql> CHANGE MASTER TO
->     MASTER_HOST='<master host name>',
->     MASTER_USER='<replication user name>',
->     MASTER_PASSWORD='<replication password>',
->     MASTER_LOG_FILE='<recorded log file name>',
->     MASTER_LOG_POS=<recorded log offset>;

La table suivante vous donne les tailles maximales de ces variables :

MASTER_HOST

60

MASTER_USER

16

MASTER_PASSWORD

32

MASTER_LOG_FILE

255

10. Lancez les threads esclaves.

mysql> START SLAVE;

Après avoir suivi les instructions ci-dessus, les esclaves doivent se connecter au maître, et rattraper les modifications qui ont eu lieu depuis la sauvegarde des données.

Si vous avez oublié de spécifier un server-id pour un esclave, vous allez obtenir l'erreur suivante dans le fichier d'erreurs :

Warning: one should set server_id to a non-0 value if master_host is set.
The server will not act as a slave.

Si vous avez oublié de le faire pour le maître, les esclaves ne pourront pas se connecter avec le maître.

Si un esclave n'est pas capable de faire la réplication pour une raison quelconque, vous allez trouver le message d'erreur dans le fichier de logs d'erreurs de l'esclave.

Une fois qu'un esclave a activé la réplication, vous trouverez deux fichiers dans son dossier de données : master.info et relay-log.info. L'esclave utilise ces deux fichiers pour savoir où il en est des logs du maître. Ne supprimer pas et n'éditez pas ces fichiers, à moins que vous ne sachiez bien ce que vous faites. Même dans ce cas, il est préférable d'utiliser la commande CHANGE MASTER TO.

NOTE : le contenu du fichier master.info est prioritaire par rapport à certaines versions spécifiées en ligne de commande, ou dans le fichier my.cnf. Voyez Section 6.8, « Options de démarrage de la réplication » pour plus de détails.

Une fois que vous avez une sauvegarde, vous pouvez l'utiliser pour configurer d'autres esclaves, en suivant la procédure concernant l'esclave, ci-dessus. Vous n'aurez pas besoin d'une autre sauvegarde du maître.

6-5 - Compatibilité de la réplication entre les versions de MySQL

Le format de log binaire original de la réplication a été développé en MySQL 3.23. Il a changé en MySQL 4.0, et encore en MySQL 5.0. Cela a des conséquences lorsque vous mettez à jour votre architecture de réplication, tel que décrit dans la section Section 6.6, « Changer de version de réplication ».

Au niveau de la réplication, toutes les versions MySQL 4.1.x et 4.0.x sont identiques, car elles utilisent le même format de log binaire. Par conséquent, les serveurs dans cet intervalle de versions seront compatibles, et la réplication devrait fonctionner sans problèmes entre eux. Les exceptions à cette compatibilité sont que les versions de MySQL 4.0.0 à 4.0.2 étaient des versions de développement très récentes, et qu'elles ne doivent plus être utilisées. Elles représentent des versions alpha dans la série des 4.0. La compatibilité avec ces versions est toujours documentée dans le manuel, avec ces distributions.

La table suivante indique les compatibilités entre les esclaves et maîtres, pour différentes versions de MySQL.

Maître

Maître

Maître

3.23.33 et plus récent

4.0.3 et plus récent ou 4.1.x

5.0.0

Esclave

3.23.33 et plus récent

oui

non

non

Esclave

4.0.3 et plus récent

oui

oui

non

Esclave

5.0.0

oui

oui

oui

En général, nous recommandons d'utiliser des versions récentes de MySQL, car la réplication s'améliore continuellement. Nous recommandons aussi d'utiliser la même version pour le maître et les esclaves.

6-6 - Changer de version de réplication

Lorsque vous mettez à jour vos serveurs dans une architecture de réplication, la procédure pour changer les versions dépend des versions que vous abandonnez et de celle vers laquelle vous allez.

6-6-1 - Passer à la réplication version 4.0

Cette section s'applique aux situations de mises à jour depuis une architecture MySQL 3.23 vers 4.0 ou 4.1. Un serveur 4.0 doit être en version 4.0.3 ou plus récent, tel que mentionné dans la section Section 6.5, « Compatibilité de la réplication entre les versions de MySQL ».

Lorsque vous mettez à jour un maître depuis MySQL 3.23 vers MySQL 4.0 ou 4.1, assurez-vous d'abord que tous les esclaves et tous les maîtres sont déjà en versions 4.0 ou 4.1 (si ce n'est pas le cas, commencez par mettre à jour les esclaves comme indiqué ci-dessous). Une fois le maître mis à jour, vous ne devez pas relancer la réplication avec les vieux logs binaires 3.23, car cela va perturber les esclaves 4.0 et 4.1. La mise à jour peut être faite comme ceci, en supposant que vous avez un maître 3.23 à modifier, et des esclaves 4.0 ou 4.1 :

1. Bloquez toutes les modifications sur le maître avec FLUSH TABLES WITH READ LOCK ;

2. Attendez que les esclaves aient rattrapé toutes les modifications du maître (utilisez SHOW MASTER STATUS sur le maître, et SELECT MASTER_POS_WAIT() sur les esclaves. Puis lancez STOP SLAVE sur les esclaves ;

3. Éteignez le serveur maître et passez-le en MySQL 4.0 or 4.1 ;

4. Relancez le serveur MySQL maître. Enregistrez le nom du nouveau log binaire du maître. Vous pouvez obtenir ce nom avec la commande SHOW MASTER STATUS sur le maître. Puis, lancez cette commande sur les esclaves :

mysql> CHANGE MASTER TO MASTER_LOG_FILE='<name>', MASTER_LOG_POS=4;
mysql> START SLAVE;

6-6-2 - Passer à la réplication version 5.0

Cette section s'applique aux situations de mises à jour depuis une architecture MySQL 3.23, 4.0 ou 4.1 vers une version 5.0.0. Un serveur 4.0 doit être en version 4.0.3 ou plus récent, tel que mentionné dans la section Section 6.5, « Compatibilité de la réplication entre les versions de MySQL ».

D'abord, notez bien que MySQL 5.0.0 est actuellement en phase alpha, même s'il est supposé utilisable et meilleur que les vieilles versions (meilleure mise à jour, réplication de certaines variables de sessions importantes comme SQL_MODE; voyez Section C.1.7, « Changements de la version 5.0.0 (22 décembre 2003 : Alpha) »), il n'est pas encore totalement testé. Nous vous recommandons donc de ne pas l'utiliser pour des environnements de production.

Lorsque vous passez de MySQL 3.23 ou 4.0 en 4.1 ou 5.0.0, vous devriez vous assurer que tous les esclaves de ce maître sont déjà en version 5.0.0 (si ce n'est pas le cas, vous devriez commencer par mettre à jour vos esclaves, comme expliqué ci-dessous.

Alors, éteignez le maître, passez-le en version 5.0.0 et relancez-le. Le maître version 5.0.0 sera capable de relire les anciens logs binaires (d'avant la mise à jour), et de les envoyer aux esclaves 5.0.0 qui reconnaîtront le vieux format, et le comprendront. Les nouveaux logs binaires créés par le maître seront au format 5.0.0, et seront reconnus par les esclaves.

Pour mettre à jour les esclaves, commencez par les éteindre, puis passez-les en version 5.0.0, et relancez-les, ou relancez la réplication. Les esclaves de version 5.0.0 seront capables de relire les vieux fichiers de logs binaires (ceux d'avant la mise à jour), et exécuter les commandes qu'ils contiennent. Les logs de relais créés après la mise à jour seront au format 5.0.0.

En d'autres termes, il n'y a pas de mesure à prendre lorsque vous passez en version 5.0.0, sauf que les esclaves doivent être mis à jour avant le maître. Notez que si vous descendez de version, cela ne fonctionnera pas automatiquement : vous devez commencer par effacer les logs binaires et de relais au format 5.0.0 avant de procéder.

6-7 - Fonctionnalités de la réplication et problèmes connus

La liste suivante explique ce qui est supporté ou pas. Des informations spécifiques InnoDB sur la réplication sont disponibles dans la section Section 15.7.5, « InnoDB et la réplication MySQL ».

- La réplication s'effectue correctement sur les valeurs AUTO_INCREMENT, LAST_INSERT_ID() et TIMESTAMP.

- Les fonctions USER() et LOAD_FILE() sont répliquées dans modifications, et ne seront pas fiables une fois rendues sur le serveur esclave. C'est aussi vrai pour CONNECTION_ID() pour les esclaves de versions antérieures à la 4.1.1. La nouvelle fonction PASSWORD() de MySQL 4.1, est bien répliquée depuis les maîtres version 4.1.1; vos esclaves doivent être en version 4.1.0 ou plus récent pour la répliquer. Si vous avez d'anciens esclaves, et que vous devez répliquer la fonction PASSWORD() depuis un maître 4.1, vous devez lancer le maître avec l'option --old-password.

- Les variables SQL_MODE, UNIQUE_CHECKS, SQL_AUTO_IS_NULL sont répliquées depuis la version 5.0.0. Les variables SQL_SELECT_LIMIT et TABLE_TYPE ne sont pas répliquées pour le moment. FOREIGN_KEY_CHECKS est répliquée depuis la version 4.0.14.

- Vous devez utiliser le même jeu de caractères (--default-character-set) sur le maître et sur l'esclave. Sinon, vous risquez de rencontrer des erreurs de clés dupliquées, sur l'esclave, car une clé considérée comme unique sur le serveur pourrait ne pas l'être dans le jeu de caractères de l'esclave. Les jeux de caractères seront répliqués en version 5.0.

- Si vous utilisez des tables transactionnelles sur le maître et non transactionnelles sur l'esclave, pour les mêmes tables, vous rencontrerez des problèmes si l'esclave est interrompu au milieu d'un bloc BEGIN/COMMIT, car l'esclave reprendra ultérieurement au début du bloc BEGIN. Ce problème est sur notre liste de tâches, et sera corrigé prochainement.

- Les requêtes d'UPDATE qui utilisent des variables utilisateur ne sont pas correctement répliquées sur les serveurs 3.23 et 4.0. C'est corrigé en 4.1. Notez que les noms de variables utilisateur sont insensibles à la casse depuis la version 5.0, alors il est recommandé de prendre cela en compte lors de la configuration de la réplication entre un serveur version 5.0 et une version précédente.

- L'esclave peut se connecter au maître avec la sécurisation SSL, si le maître et l'esclave sont tous les deux en versions 4.1.1 ou plus récentes.

- Si la clause DATA DIRECTORY ou INDEX DIRECTORY est utilisée dans la commande CREATE TABLE sur le maître, la clause est aussi utilisée sur l'esclave. Cela peut causer des problèmes s'il n'existe pas de dossier correspondant sur le système de fichiers de l'esclave. Depuis MySQL 4.0.15, il y a une option de mode SQL sql_mode appelée NO_DIR_IN_CREATE. Si le serveur esclave fonctionne avec ce mode SQL, il va simplement ignorer ces clauses avant de répliquer les commandes CREATE TABLE. Le résultat est que les données MyISAM et les fichiers d'index seront créés dans le dossier de la base.

- Même si nous n'avons jamais vu d'occurrence de ce problème, il est théoriquement possible pour les données du maître et de l'esclave de différer si une requête non déterministe est utilisée pour modifier les données, c'est-à-dire si elle est laissée au bon vouloir de l'optimiseur, ce qui n'est pas une bonne pratique même sans la réplication. Pour plus d'informations, voyez Section 1.5.7.4, « Bogues connus / limitations de MySQL ».

- Avant MySQL 4.1.1, les commandes FLUSH, ANALYZE, OPTIMIZE, REPAIR n'étaient pas stockées dans le log binaire, et donc, elles n'étaient pas répliquées avec les esclaves. Ce n'est pas normalement un problème, car FLUSH ne modifie pas les tables. Cela peut signifier que vous avez modifié des droits dans les tables MySQL directement sans la commande GRANT et que vous avez répliqué les droits de mysql sans pouvoir faire de commande FLUSH PRIVILEGES sur vos esclaves pour les prendre en compte. Depuis MySQL version 4.1.1, ces commandes sont écrites dans le log binaire, (hormis FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, FLUSH TABLES WITH READ LOCK) à moins que vous ne spécifiez NO_WRITE_TO_BINLOG ou son alias LOCAL). Pour un exemple d'utilisation de la syntaxe, voyez Section 13.5.4.2, « Syntaxe de FLUSH ».

- MySQL supporte uniquement un maître et plusieurs esclaves. Ultérieurement, nous allons ajouter un algorithme de choix automatique du maître. Nous allons aussi introduire une notion d'agent, qui aidera à équilibrer la charge en envoyant les commandes SELECT aux différents esclaves.

- Lorsqu'un serveur s'arrête et repart, les tables MEMORY (HEAP) sont vidées. Depuis MySQL 4.0.18, le maître réplique cet effet comme ceci : la première fois que le maître utilise une table MEMORY après le démarrage, il indique aux esclaves que la table doit être vidée en ajoutant une commande DELETE FROM pour la table en question, dans son log binaire. Voyez Section 14.3, « Le moteur de table MEMORY (HEAP) » pour plus de détails.

- Les tables temporaires sont répliquées depuis la version 3.23.29, à l'exception des cas où vous éteignez le serveur esclave (et pas juste le thread esclave), que vous avez des tables temporaires ouvertes et qu'elles sont utilisées dans des modifications ultérieures. (Si vous éteignez l'esclave, les tables temporaires utilisées par ces commandes ne sont plus disponibles au redémarrage de l'esclave.) Pour éviter ce problème, n'éteignez jamais un esclave qui a des tables temporaires actives. Utilisez cette procédure :

1. Utilisez la commande SLAVE STOP ;

2. Vérifiez la variable de statut Slave_open_temp_tables pour vérifier si elle vaut bien 0 ;

3. Si elle vaut bien 0, exécutez mysqladmin shutdown ;

4. Si le nombre n'est pas 0, redémarrez l'esclave avec la commande SLAVE START ;

5. Répétez la procédure et voyez si vous avez plus de chance la prochaine fois.

Nous envisageons de corriger ce problème prochainement.

- Il est possible de connecter les serveurs MySQL en chaîne bouclée (chaque serveur est le maître du précédent et l'esclave du suivant, en boucle), avec l'activation de l'option log-slave-updates. Notez que de nombreuses requêtes ne vont pas fonctionner dans ce type de configuration à moins que votre code client ne soit écrit avec beaucoup de soin, pour qu'il se charge des problèmes qui pourraient arriver dans différentes séquences de modifications sur différents serveurs.

Cela signifie que vous pouvez réaliser une configuration comme ceci :

A -> B -> C -> A

Les identifiants de serveurs sont inscrits dans les événements. A saura qu'un événement qu'il a déjà exécuté lui est revenu, et il ne l'exécutera pas deux fois : il n'y a pas de risque de boucle infinie. Mais dans une configuration circulaire, vous devez vous assurer que le code client n'effectue pas de modifications conflictuelles. En d'autres termes, si vous insérez des données dans A et C, vous devez vous assurez qu'il n'y a pas de conflit de clé unique. Ne modifiez pas non plus deux lignes simultanément sur deux serveurs, si l'ordre des modifications a une importance pour vous.

- Si la requête sur l'esclave génère une erreur, le thread esclave s'arrêtera, et un message sera ajouté dans le fichier d'erreurs. Vous devrez vous connecter pour corriger manuellement les données de l'esclave, puis relancer l'esclave avec la commande SLAVE START (disponible depuis la version 3.23.16. En version 3.23.15, vous devrez redémarrer le serveur.

- Si la connexion au maître est perdue, l'esclave tente de se reconnecter immédiatement, et en cas d'échec, il va retenter toutes les master-connect-retry (par défaut, 60) secondes. À cause de cela, il est sage d'éteindre le serveur maître et de le redémarrer régulièrement. L'esclave sera capable de gérer les problèmes réseau. Voir Section 5.2.3, « Variables serveur système ».

- Éteindre l'esclave proprement est sûr, car il garde la trace du point où il en est rendu. Les extinctions sauvages vont produire des problèmes, surtout si le cache disque n'a pas été écrit sur le disque avant que le système ne s'arrête. Votre niveau de tolérance aux pannes sera grandement amélioré si vous avez de bons onduleurs.

- Étant donné la nature non transactionnelle des tables MySQL, il est possible de ne faire qu'une partie de la modification, et retourner une erreur. Cela peut arriver, par exemple, dans une insertion multiple dont une des lignes viole une contrainte d'unicité, ou si un très long UPDATE est interrompu au milieu du stock de ligne. Si cela arrive sur le maître, l'esclave va s'arrêter et attendre que l'administrateur décide quoi faire, à moins que l'erreur soit légitime, et que la requête arrive à la même conclusion. Si le code d'erreur n'est pas désirable, certaines erreurs (voire toutes), peuvent être masquées avec l'option slave-skip-errors, depuis la version 3.23.47.

- Si vous modifiez une table transactionnelle depuis une table transactionnelle, dans un bloc de transaction BEGIN/COMMIT, les modifications du log binaire peut être déphasées si un thread a fait une modification dans la table non transactionnelle, avant la validation de la transaction. Les transactions sont écrites dans le log binaire au moment de leur validation.

- Avant la version 4.0.15, les modifications sur des tables non transactionnelles sont écrites dans le log binaire immédiatement, alors que les modifications d'une transaction sont écrites au moment du COMMIT ou ignorées si vous utilisez un ROLLBACK; vous devez prendre cela en compte lors de la modification de tables transactionnelles et non transactionnelles dans la même transaction, si vous utilisez le log binaire pour les sauvegardes ou la réplication. En version 4.0.15, nous avons modifié le comportement du log pour les transactions, qui mêlent les modifications de tables transactionnelles et non transactionnelles dans la même transaction, pour résoudre ce problème. L'ordre des requêtes est maintenant maintenu, et toutes les requêtes sont écrites, même en cas d'annulation ROLLBACK. Le problème qui reste est que lorsqu'une seconde connexion modifie une table non transactionnelle durant la transaction de la première connexion, une erreur d'ordre dans les requêtes peut survenir, car la seconde transaction sera écrite immédiatement après sa réalisation.

- Lorsque l'esclave 4.x réplique une commande LOAD DATA INFILE depuis un maître 3.23, les valeurs des colonnes Exec_Master_Log_Pos et Relay_Log_Space pour SHOW SLAVE STATUS sont incorrectes. L'erreur de Exec_Master_Log_Pos va causer un problème lorsque vous stopperez et relancerez la réplication. Il est donc bon de corriger cela avec la commande FLUSH LOGS sur le maître. Ces bogues sont corrigés pour les esclaves en MySQL 5.0.0.

La table suivante liste les problèmes de MySQL 3.23 qui sont corrigés en MySQL 4.0.

- LOAD DATA INFILE est correctement géré, tant que les données résident toujours sur le serveur maître au moment de la propagation.

- LOAD LOCAL DATA INFILE sera ignoré.

- En version 3.23 RAND() dans les modifications de lignes ne se propage pas correctement. Utilisez RAND(some_non_rand_expr) si vous répliquez des modifications qui incluent RAND(). Vous pouvez, par exemple, utiliser UNIX_TIMESTAMP() comme argument de RAND(). Ceci est corrigé en version 4.0.

6-8 - Options de démarrage de la réplication

Sur le maître comme sur l'esclave, vous devez utiliser l'option server-id pour donner un identifiant unique ID à chaque serveur. Vous pouvez choisir un entier dans l'intervalle de 1 à 2^32 - 1 pour chaque maître et esclave. Exemple : server-id=3

Les options que vous pouvez utiliser sur le maître pour contrôler les logs sont décrites dans la section Section 5.9.4, « Le log binaire ».

La table suivante décrit les options que vous pouvez utiliser sur les serveurs esclaves. Vous pouvez les spécifier en ligne de commande, ou dans le fichier d'options.

Les gestionnaires de réplication gèrent les options de manière spéciale, sans le sens où elles sont ignorées si un fichier master.info existe lorsque l'esclave est lancé, et qu'il contient des valeurs pour les options. Les options suivantes sont gérées de cette manière :

- --master-host

- --master-user

- --master-password

- --master-port

- --master-connect-retry

Depuis MySQL 4.1.1, les options suivantes sont gérées de manière particulière :

- --master-ssl

- --master-ssl-ca

- --master-ssl-capath

- --master-ssl-cert

- --master-ssl-cipher

- --master-ssl-key

Le format du fichier master.info de version 4.1.1 a changé pour inclure les options SSL. De plus, en version 4.1.1, le fichier inclut le nombre de lignes comme première ligne. Si vous passez d'une ancienne version vers un serveur 4.1.1, le nouveau serveur va mettre à jour le fichier master.info avec le nouveau format au démarrage. Toutefois, si vous rétrogradez en version 4.1.1, vous devrez supprimer la première ligne avant de relancer votre vieux serveur. Notez que dans ce cas, le serveur ancien ne pourra pas utiliser les connexions sécurisées pour communiquer avec le maître.

Si aucun fichier master.info n'existe lors du lancement de l'esclave, il utilise les valeurs de ces options. Cela arrivera lorsque vous lancez un serveur de réplication en tant qu'esclave, pour la première fois, ou si vous avez utilisé la commande RESET SLAVE et arrêté puis relancé le serveur.

Cependant, si master.info existe lorsque l'esclave démarre, il utilisera les valeurs dans le fichier et ignorera les valeurs spécifiées en ligne de commande, ou dans le fichier d'options master.info.

Si vous redémarrez le serveur avec différentes options de démarrage que les valeurs qui sont dans le master.info, ces nouvelles valeurs n'auront pas d'effet, car le serveur continuera d'utiliser master.info. Pour utiliser différentes valeurs, vous devez relancer le serveur après avoir supprimé master.info, ou, de préférence, utilise la commande CHANGE MASTER TO pour remettre à zéro les valeurs durant l'exécution.

Supposez que vous spécifiez cette option dans votre fichier my.cnf :

[mysqld]
master-host=un_hote

La première fois que vous démarrez le serveur en tant qu'esclave de réplication, il va lire et utiliser cette option dans le fichier my.cnf. Le serveur va ensuite enregistrer les valeurs courantes dans le fichier master.info. Au prochain démarrage du serveur, il va lire les valeurs dans le fichier master.info. Si vous modifiez my.cnf pour spécifier un nouvel hôte, cela n'aura pas d'effet. Vous devez utiliser la commande CHANGE MASTER TO.

Comme le serveur donne la priorité au fichier master.info sur les options de démarrage décrites, vous pourriez ne pas souhaiter utiliser les options de démarrage pour ces valeurs, et plutôt, les spécifier avec la commande CHANGE MASTER TO. Voir Section 13.6.2.1, « CHANGE MASTER TO ».

Cet exemple illustre une utilisation plus complète des options de démarrage pour configurer un serveur esclave :

[mysqld]
server-id=2
master-host=db-master.mycompany.com
master-port=3306
master-user=pertinax
master-password=freitag
master-connect-retry=60
report-host=db-slave.mycompany.com

La liste suivante décrit les options de démarrage qui contrôlent la réplication. De nombreuses options peuvent être remises à zéro pendant que le serveur fonctionne, en utilisant la commande CHANGE MASTER TO. Sinon, des options comme --replicate-* peuvent être utilisées lorsque le serveur esclave démarre. Nous envisageons de corriger cela.

- --log-slave-updates

Dit à l'esclave d'enregistrer les modifications effectuées par son thread SQL dans son propre log binaire. Par défaut, cette option est à Off. Pour que cette option ait un effet, l'esclave doit être lancé avec le log binaire activé : c'est l'option --log-bin option. --log-slave-updates sert lorsque vous voulez faire une chaîne de serveurs de réplication. Par exemple :

A -> B -> C

C'est-à-dire, A sert de maître à l'esclave B, et B sert de maître à l'esclave C. Pour que cela fonctionne, avec B qui sert d'esclave et de maître simultanément, vous devez lancer B avec l'option --log-slave-updates. A et B doivent être lancés avec le log binaire activé.

- --log-warnings

Fait que l'esclave affiche plus de messages sur ses activités. Par exemple, il vous alertera s'il réussit à se reconnecter après un problème de connexion, ou le démarrage de thread esclaves.

Cette option n'est pas limitée à la réplication. Elle produit des alertes sur toute la gamme des activités du serveur.

- --master-connect-retry=seconds

Le nombre de secondes qu'un esclave attend avant de tenter de se reconnecter au maître, dans le cas où le maître et l'esclave perdent la connexion. La valeur du fichier master.info a priorité, si elle est disponible. Par défaut, elle vaut 60.

- --master-host=host

Spécifie l'hôte ou l'IP du maître de réplication. Si cette option n'est pas fournie, le thread esclave ne sera pas lancé. La valeur inscrite dans le fichier master.info a priorité, si elle peut être lue. Un meilleur nom pour cette option aurait été --bootstrap-master-host, mais il est trop tard.

- --master-info-file=file_name

Le nom à utiliser pour le fichier dans lequel l'esclave stocke les informations sur le maître. Par défaut, c'est mysql.info, dans le dossier de données.

- --master-password=password

Le mot de passe que l'esclave utilise lors de l'identification auprès du maître. Si le mot de passe n'est pas configuré, la chaîne vide est utilisée. La valeur inscrite dans le fichier master.info a priorité, si elle peut être lue.

- --master-port=port_number

Le port du maître que l'esclave utilise lors de l'identification auprès du maître. Si le port n'est pas configuré, la valeur de la variable MYSQL_PORT est utilisée. Si vous n'y avez pas touché lors de la compilation avec configure, ce doit être 3306. La valeur inscrite dans le fichier master.info a priorité, si elle peut être lue.

- --master-ssl, --master-ssl-ca=file_name, --master-ssl-capath=directory_name, --master-ssl-cert=file_name, --master-ssl-cipher=cipher_list, --master-ssl-key=file_name

Ces options servent à configurer la réplication chiffrée, lorsque la connexion avec le maître utilise SSL. Leur signification respective est la même que les options --ssl, --ssl-ca, --ssl-capath, --ssl-cert, --ssl-cipher, --ssl-key décrites dans Section 5.6.7.5, « Options SSL en ligne de commande ».

Ces options sont disponibles depuis MySQL 4.1.1.

- --master-user=username

Le nom d'utilisateur que l'esclave utilise lors de l'identification auprès du maître. Le compte doit avoir les droits de REPLICATION SLAVE (avant MySQL 4.0.2, il devait avoir les droits de FILE). Si l'utilisateur maître n'est pas configuré, l'utilisateur test est utilisé. La valeur inscrite dans le fichier master.info a priorité, si elle peut être lue. Si l'utilisateur maître n'est pas configuré, la valeur test est utilisée.

- --max-relay-log-size=#

Pour faire la rotation automatique des logs. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ».

Cette option est disponible depuis MySQL 4.0.14.

- --read-only

Cette option fait que le serveur n'autorise aucune modification, hormis celles du thread esclave, ou celles des utilisateurs ayant les droits de SUPER. Cela peut être utile si vous voulez vous assurer que l'esclave ne reçoit aucune modification des clients.

Cette option est disponible depuis MySQL 4.0.14.

- --relay-log=filename

Pour spécifier la localisation et le nom qui doivent être utilisés pour les logs de relais. Les noms par défaut sont de la forme host_name-relay-bin.nnn, où host_name est le nom du serveur esclave et nnn indique le numéro de séquence du log de relais. Vous pouvez utiliser ces options pour avoir des noms de fichiers de logs de relais indépendants du nom d'hôte, ou si vos logs ont tendance à devenir très grands (et que vous ne voulez pas réduire la valeur de max_relay_log_size) et que vous devez les mettre dans un autre dossier, ou simplement pour accélérer la vitesse d'équilibrage entre deux disques.

- --relay-log-index=filename

Pour spécifier la localisation et le nom qui doivent être utilisés pour le fichier d'index du log de relais. Le nom par défaut est host_name-relay-bin.index, où host_name est le nom du serveur esclave.

- --relay-log-info-file=filename

Pour donner au fichier relay-log.info un autre nom ou pour le placer dans un autre dossier. Le nom par défaut est relay-log.info dans le dossier de données.

- --relay-log-purge={0|1}

Active ou désactive la vidange automatique des logs de relais, dès qu'ils ne sont plus utiles. C'est une variable globale, qui peut être dynamiquement modifiée avec SET GLOBAL RELAY_LOG_PURGE=0|1. Sa valeur par défaut est 1.

Cette option est disponible depuis MySQL 4.1.1.

- --relay-log-space-limit=#

Limite la taille maximale de tous les fichiers de logs de relais sur l'esclave (une valeur de 0 signifie « sans limite »). C'est utile lorsque vous avez un petit disque sur votre machine esclave. Lorsque la limite est atteinte, le thread d'I/O fait une pause : il ne lit plus rien dans le log binaire du maître, jusqu'à ce que le thread SQL ait avancé, et effacé des fichiers de logs. Notez que cette limite n'est pas absolue : il se peut que le thread SQL requiert plusieurs événements pour être capable d'effacer les fichiers de logs de relais. Dans ce cas, le thread d'I/O va dépasser la limite, jusqu'à ce que l'effacement devienne possible. Sans cela, des blocages pourraient survenir, ce qui arrivait sur les versions antérieures à la 4.0.13). Avec --relay-log-space-limit, il ne faut pas utiliser de valeur inférieure à deux fois la taille de --max-relay-log-size (ou --max-binlog-size si --max-relay-log-size vaut 0), car dans ce cas, il y a des chances que le thread d'I/O attende de l'espace libre parce que --relay-log-space-limit est dépassée, mais que le thread SQL n'ait pas de logs à effacer, et ne peut donc libérer le thread d'I/O, forçant le thread d'I/O à ignorer temporairement --relay-log-space-limit.

- --replicate-do-db=db_name

Indique à l'esclave qu'il doit restreindre la réplication aux commandes qui utilisent la base de données db_name par défaut (c'est-à-dire celle qui est sélectionnée avec la commande USE). Pour spécifier plusieurs bases de données, utilisez cette option aussi souvent que nécessaire. Note que cela ne va pas autoriser les commandes multibases, comme UPDATE some_db.some_table SET foo='bar' si une base de données différente ou qu'aucune base de données n'est sélectionnée. Si vous avez besoin que les commandes multibases fonctionnent, assurez-vous que vous avez MySQL 3.23.28 ou plus récent, et utilisez --replicate-wild-do-table=db_name.%. Lisez les notes qui suivent cette liste d'options.

Un exemple qui pourrait ne pas fonctionner comme vous l'attendez : si l'esclave est lancé avec --replicate-do-db=sales et que vous émettez une commande sur le maître, la commande UPDATE suivante ne sera pas répliquée :

USE prices;
UPDATE sales.january SET amount=amount+1000;

Si vous avez besoin de répliquer des commandes multibases, utilisez l'option --replicate-wild-do-table=db_name.% à la place.

La raison principale de ce comportement « vérifie juste la base par défaut » est qu'il est difficile de savoir si une requête doit être répliquée, uniquement à partir de la requête. Par exemple, si vous utilisez une requête multitable DELETE oui multitable UPDATE, qui a des conséquences dans d'autres bases. La vérification de la base courante est aussi très rapide.

- --replicate-do-table=db_name.table_name

Dit à l'esclave qu'il doit restreindre la réplication à une table spécifiée. Pour spécifier plusieurs tables, il faut utiliser cette directive plusieurs fois, une fois par table. Cela fonctionnera pour les mises à jour multibases, au contraire de --replicate-do-db. Lisez les notes qui suivent cette liste d'options.

- --replicate-ignore-db=db_name

Indique à l'esclave qu'il ne doit pas assurer la réplication avec les commandes qui utilisent la base de données db_name par défaut (c'est-à-dire celle qui est sélectionnée avec la commande USE). Pour spécifier plusieurs bases de données, utilisez cette option aussi souvent que nécessaire. Notez que cela ne va pas autoriser les commandes multibases, comme UPDATE some_db.some_table SET foo='bar' si une base de données différente ou qu'aucune base de données n'est sélectionnée. Si vous avez besoin que les commandes multibases fonctionnent, assurez-vous que vous avez MySQL 3.23.28 ou plus récent, et utilisez --replicate-wild-do-table=db_name.%. Lisez les notes qui suivent cette liste d'options.

Un exemple qui pourrait ne pas fonctionner comme vous l'attendez : si l'esclave est lancé avec --replicate-ignore-db=sales et que vous émettez une commande sur le maître, la commande UPDATE suivante ne sera pas répliquée :

USE prices;
UPDATE sales.january SET amount=amount+1000;

Si vous avez besoin de répliquer des commandes multibases, utilisez l'option --replicate-wild-ignore-table=db_name.% à la place.

- --replicate-ignore-table=db_name.table_name

Dit à l'esclave qu'il ne doit pas répliquer les commandes qui touche à la table spécifiée, même si d'autres tables sont modifiées dans la même commande. Pour spécifier plusieurs tables, il faut utiliser cette directive plusieurs fois, une fois par table. Cela fonctionnera pour les mises à jour multibases, au contraire de --replicate-ignore-db. Lisez les notes qui suivent cette liste d'options.

- --replicate-wild-do-table=db_name.table_name

Dit à l'esclave qu'il doit restreindre la réplication aux tables dont le nom vérifie le masque spécifié. Le masque peut contenir les caractères '%' et '_', qui ont la même signification que dans les expressions régulières de la clause LIKE. Pour spécifier plusieurs tables, il faut utiliser cette directive plusieurs fois, une fois par table. Cela fonctionnera pour les mises à jour multibases, au contraire de --replicate-do-db. Lisez les notes qui suivent cette liste d'options.

Exemple : --replicate-wild-do-table=foo%.bar% va répliquer les mises à jour qui surviennent sur toutes les tables de toutes les bases qui commencent par foo, et dont le nom de table commence par bar.

Notez que si vous utilisez --replicate-wild-do-table=foo%.%, alors la règle sera propagée à CREATE DATABASE et DROP DATABASE, c'est-à-dire que ces deux commandes seront répliquées si le nom de la base correspond au masque (foo% ici) (la magie est ici déclenchée par % comme masque de table).

Si le masque de noms de tables est %, il accepte tous les noms de tables et les options s'appliquent aux commandes de niveau base de données (comme CREATE DATABASE, DROP DATABASE et ALTER DATABASE). Par exemple, si vous utilisez --replicate-wild-do-table=foo%.%, les commandes de niveau de base de données seront répliquées si le nom de la base de données est accepté par le masque foo%.

Si vous voulez faire la réplication des tables du type ma_petite%base (ceci est le nom exact de la base), mais que vous ne voulez pas répliquer la base ma1petiteAABCbase, vous devez protéger les caractères '_' et '%' : il faut utiliser une syntaxe équivalant à : replicate-wild-do-table=my\_own\%db. Et si vous spécifiez cette option en ligne de commande, suivant votre système, vous devrez protéger aussi le caractère \ (par exemple, en Shell bash, vous devez émettre une option sous la forme --replicate-wild-do-table=my\\_own\\%db).

- --replicate-wild-ignore-table=db_name.table_name

Dit à l'esclave qu'il ne doit pas répliquer les tables dont le nom vérifie le masque spécifié. Pour spécifier plusieurs tables, il faut utiliser cette directive plusieurs fois, une fois par table. Cela fonctionnera pour les mises à jour multibases, au contraire de --replicate-do-db. Lisez les notes qui suivent cette liste d'options.

Exemple : --replicate-wild-ignore-table=foo%.bar% n'autorisera pas de modifications dans les tables des bases dont le nom commence par foo et dont le nom de table commence par bar.

Pour des informations sur le fonctionnement du filtre, voyez l'option --replicate-wild-ignore-table. La règle pour inclure des caractères littéraux est la même que pour --replicate-wild-ignore-table.

- --replicate-rewrite-db=from_name->to_name

Dit à l'esclave de remplacer la base courante (celle qui est sélectionnée avec USE) par to_name si elle était from_name sur le maître. Seules les commandes impliquant des tables peuvent être affectées. (CREATE DATABASE, DROP DATABASE ne le seront pas), et uniquement si from_name était la base de données courante sur le maître. Cela ne fonctionnera pas pour les commandes multibases de données. Notez que la traduction est faite avant que les règles --replicate-* ne soient testées.

Si vous utilisez cette option en ligne de commande, et que vous utilisez le caractère '>', qui peut être spécial pour votre interpréteur Shell, protégez-le comme ceci :

shell> mysqld --replicate-rewrite-db="olddb->newdb"

- --replicate-same-server-id

À utiliser sur les serveurs esclaves. Généralement, vous pouvez spécifier la valeur 0 pour éviter les réplications infinies. Si cette option vaut 1, l'esclave n'ignorera pas les événements de réplication, même s'ils portent son propre numéro d'identification. Normalement, cela n'est utile que pour de très rares configurations. Vous ne pouvez pas mettre cette option à 1 si --log-slave-updates est utilisé. Faites attention en démarrant MySQL 4.1, par défaut le thread d'E/S n'écrit pas les événements dans le log de relais s'ils portent l'identification du serveur esclave (c'est une optimisation pour économiser l'espace disque, par rapport à la version 4.0). Si vous voulez utiliser --replicate-same-server-id avec les versions 4.1, assurez-vous de démarrer l'esclave avec cette option avant que l'esclave ne lise ses propres événements et qu'il les fasse exécuter au thread SQL.

- --report-host=host

Le nom d'hôte ou l'adresse IP de l'esclave, qui doit être indiquée lors de l'enregistrement de l'esclave chez le maître. Cela apparaîtra dans l'affichage de la commande SHOW SLAVE HOSTS. Laissez cette option vide pour que l'esclave ne s'enregistre pas sur le maître. Notez qu'il n'est pas suffisant pour que le maître lise l'adresse IP de l'esclave sur la socket, une fois que l'esclave se connecte. À cause du NAT et des problèmes de routages, cette IP peut être invalide pour se connecter au maître depuis l'hôte ou les autres esclaves.

Cette option est disponible depuis MySQL 4.0.0.

- --report-port=port_number

Le port de connexion indiqué par l'esclave lors de son enregistrement chez le maître. Configurez cette option si l'esclave utilise un port autre que le port par défaut, ou si vous avez installé un tunnel spécial pour le maître ou les autres esclaves. Dans le doute, laissez cette option vide.

Cette option est disponible depuis MySQL 4.0.0.

- --skip-slave-start

Dit à l'esclave de ne pas lancer les threads esclaves au démarrage du serveur. L'utilisateur pourra les lancer manuellement, avec START SLAVE.

- --slave_compressed_protocol=#

Si cette option vaut 1, alors le protocole client/serveur compressé sera utilisé, si l'esclave et le maître le supportent.

- --slave-load-tmpdir=filename

Cette option vaut par défaut la variable tmpdir. Lorsque le thread SQL réplique des commandes LOAD DATA INFILE, il extrait les fichiers à charger du log de relais dans un fichier temporaire, puis charge ce fichier dans la table. Si le fichier chargé sur le maître est immense, le fichier temporaire sera aussi grand. Il faudra donc dire à l'esclave de placer ces fichiers temporaires sur un grand disque, qui sera différent de tmpdir : utilisez cette option. Dans ce cas, vous pouvez aussi utiliser l'option --relay-log, car les fichiers de logs de relais seront aussi grands. --slave-load-tmpdir doit pointer sur un système de fichiers basés sur un disque, et non pas sur une portion de mémoire : l'esclave doit pouvoir accéder à ce fichier pour répliquer la commande LOAD DATA INFILE, même après un redémarrage.

- --slave-net-timeout=#

Le nombre de secondes à attendre des données du maître, avant d'annuler la lecture en considérant que la connexion est rompue, et de tenter de se reconnecter. La première reconnexion intervient immédiatement après l'expiration du délai. L'intervalle entre deux tentatives de connexion est contrôlé par l'option --master-connect-retry.

- --slave-skip-errors= [err_code1,err_code2,... | all]

Normalement, la réplication s'arrête lorsqu'une erreur survient, ce qui vous donne l'opportunité de résoudre les incohérences manuellement. Cette option Indique au thread SQL les erreurs qu'il doit ignorer durant la réplication.

N'utilisez pas cette option si vous ne connaissez pas la raison des erreurs que vous rencontrez. S'il n'y a pas de bogues dans votre réplication, et qu'il n'y a pas de bogue dans MySQL, vous ne devriez pas rencontrer d'erreurs, ni utiliser cette option. L'utilisation abusive de cette option conduit irrémédiablement l'esclave à être désynchronisé avec le maître sans que vous ne sachiez d'où vient l'erreur.

Pour les codes d'erreur, il faut utiliser les numéros d'erreurs fournis par l'esclave dans le log d'erreur, et dans le résultat de SHOW SLAVE STATUS. La liste complète des messages d'erreur est disponible dans la distribution source, dans le fichier Docs/mysqld_error.txt. Les codes d'erreur du serveur sont aussi disponibles sur Chapitre 26, Gestion des erreurs avec MySQL.

Vous pouvez (mais ne devez pas) utiliser la valeur très déconseillée de all, qui va ignorer tous les messages d'erreur, et continuer à touiller les données sans se préoccuper de cohérence. Inutile d'insister sur le fait que l'intégrité de vos données n'est plus du tout garantie. Ne vous plaignez pas si les données de votre esclave ne ressemblent même pas du tout à celles de votre maître : vous aurez été prévenu.

Exemples :

--slave-skip-errors=1062,1053
--slave-skip-errors=all

Voici l'ordre d'étude des règles r--eplicate-*, pour décider si une requête doit être exécutée par l'esclave ou ignorée.

1. Existe-t-il des règles --replicate-do-db ou --replicate-ignore-db ?

- Oui : les tester pour --binlog-do-db et --binlog-ignore-db (voir Section 5.9.4, « Le log binaire »). Quel est le résultat ?

- Ignorer la requête : ignore la requête et quitte.

- Exécute la requête : n'exécute pas la requête immédiatement, reporte la décision, et passe à l'étape d'après.

- Non : passe à l'étape d'après.

2. Y a-t-il des règles --replicate-*-table ?

- Non : exécute la requête et quitte.

- Oui : passe à l'étape d'après. Seules les tables qui doivent être modifiées seront utilisées dans les règles : (INSERT INTO sales SELECT * from prices: seule sales sera utilisée pour évaluer les règles. Si plusieurs tables doivent être modifiées (modifications multitables), la première table (qui correspond à un « do » ou « ignore ») gagne. C'est-à-dire que la première table est utilisée dans les règles de comparaison, et si aucune décision ne peut être prise, la seconde table est utilisée...

3. Y a-t-il des règles --replicate-do-table ?

- Oui : est-ce qu'une table entre dans cette liste ?

- Oui : exécute la requête et quitte.

- Non : passe à l'étape d'après.

- Non : passe à l'étape d'après.

4. Y a-t-il des règles --replicate-ignore-table ?

- Oui : est-ce qu'une table entre dans cette liste ?

- Oui : ignore la requête et quitte.

- Non : passe à l'étape d'après.

- Non : passe à l'étape d'après.

5. Y a-t-il des règles --replicate-wild-do-table ?

- Oui : est-ce qu'une table entre dans cette liste ?

- Oui : exécute la requête et quitte.

- Non : passe à l'étape d'après.

- Non : passe à l'étape d'après.

6. Y a-t-il des règles --replicate-wild-ignore-table ?

- Oui : est-ce qu'une table entre dans cette liste ?

- Oui : ignore la requête et quitte.

- Non : passe à l'étape d'après.

- Non : passe à l'étape d'après.

7. Aucune règle n'a fonctionné avec --replicate-*-table. Y a-t-il d'autres tables à tester ?

- Oui : boucle.

- Non : nous avons testé toutes les tables à mettre à jour, et nous n'avons pas trouvé de règle les concernant. Y a-t-il des règles --replicate-do-table ou --replicate-wild-do-table ?

- Oui : ignore la requête et quitte.

- Non : exécute la requête et quitte.

6-9 - FAQ de la réplication

Q : Comment puis-je configurer un esclave si le maître fonctionne déjà, et que je ne veux pas le stopper ?

R : Il y a plusieurs solutions. Si vous avez effectué une sauvegarde du maître à un moment et enregistré le nom et l'offset du binlog (issu du résultat de la commande SHOW MASTER STATUS) correspondant à la sauvegarde, faites ceci :

1. Assurez-vous qu'un identifiant unique est assigné à l'esclave ;

2. Exécutez la commande pour chaque valeur appropriée :

mysql> CHANGE MASTER TO
->     MASTER_HOST='master_host-name',
->     MASTER_USER='master_user_name',
->     MASTER_PASSWORD='master_pass',
->     MASTER_LOG_FILE='recorded_log_name',
->     MASTER_LOG_POS=recorded_log_pos;

3. Exécutez la commande SLAVE START.

Si vous n'avez pas de copie de sauvegarde, voici un moyen rapide d'en faire une :

1. Exécutez cette commande MySQL :

mysql> FLUSH TABLES WITH READ LOCK;

2. Exécutez cette commande Shell, ou toute variation de cette commande :

shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql

3. Utilisez cette commande pour vous assurer de bien noter les informations de réplication. Vous en aurez besoin ultérieurement.

mysql> SHOW MASTER STATUS;

4. Libérez les tables :

mysql> UNLOCK TABLES;

Un autre moyen est de faire un export SQL du maître, au lieu de faire une copie comme indiqué ci-dessus : pour cela, vous pouvez utiliser l'utilitaire mysqldump --master-data sur votre maître, et exécuter ce script ultérieurement sur votre esclave. Cependant, c'est une méthode plus lente que de faire une copie binaire.

Quelle que soit la méthode que vous adoptez, après cela, suivez les instructions comme pour le cas où vous avez déjà votre sauvegarde, et que vous avez enregistré le nom et l'offset du point de contrôle du log binaire. Tant que les logs binaires du serveur sont toujours là, vous allez pouvoir rattraper tout ce qui se fait sur le serveur principal. Vous pourriez même attendre plusieurs jours ou mois avant de mettre en place votre esclave. En théorie, le temps d'attente peut être infini. En pratique, les limitations sont l'espace disque du maître, et le temps que cela prendra à l'esclave pour rattraper le temps.

Vous pouvez aussi utiliser LOAD DATA FROM MASTER. C'est une commande pratique pour faire une copie de la base, l'envoyer à l'esclave, et ajuster le point de contrôle du log binaire, tout en une seule commande. Dans le futur, LOAD DATA FROM MASTER sera la méthode recommandée pour configurer un esclave. Soyez prévenu, que le verrou de lecture posé par la commande sur le serveur peut rester en place un très long moment, si vous utilisez cette commande : elle n'est pas encore implémentée de manière efficace. Si vous avez de grandes tables, préférez donc la méthode qui utilise la sauvegarde via l'utilitaire tar après avoir exécuté la commande FLUSH TABLES WITH READ LOCK.

Q : Est-ce que l'esclave doit être connecté en permanence au serveur ?

R : Non, il n'est pas obligé. Vous pouvez éteindre l'esclave et le laisser déconnecter plusieurs heures ou jours, puis le reconnecter pour le voir récupérer les modifications et rattraper le temps. Puis, se déconnecter à nouveau. De cette façon, vous pouvez, par exemple, configurer un esclave via une connexion modem, qui n'utilise que de brèves périodes de connexion. L'implication de cela est qu'il n'est jamais garanti que l'esclave soit synchronisé avec le maître, à moins que vous ne preniez des mesures pour cela. Dans le futur, nous allons avoir l'option de bloquer le maître jusqu'à ce que au moins un des esclaves soit synchronisé.

Q : Comment puis-je mesurer le retard d'un esclave sur son maître ? En d'autres termes, comme savoir quelle est la date de la dernière requête répliquée par l'esclave ?

R : Si l'esclave est en version 4.1.1 et plus récent, lisez la colonne Seconds_Behind_Master dans la commande SHOW SLAVE STATUS. Pour les versions plus anciennes, suivez cette procédure. Cela n'est possible que si un thread SQL existe, c'est-à-dire s'il existe dans la commande SHOW PROCESSLIST, Voir Section 6.3, « Détails d'implémentation de la réplication ».

En MySQL version 3.23, si le thread SQL esclave existe, c'est-à-dire, s'il apparaît dans la commande SHOW PROCESSLIST, et s'il a exécuté au moins un événement lu auprès du maître, the thread modifie sa propre horloge pour prendre l'horaire du dernier événement répliqué (c'est pour cela que les colonnes TIMESTAMP sont bien répliquées. Dans la colonne Time du résultat de SHOW PROCESSLIST, le nombre de secondes affichées est le nombre de secondes entre la dernière commande exécutée sur le serveur maître et celle exécutée sur l'esclave. Notez que si votre esclave a été déconnecté du maître durant une heure, lorsqu'il se reconnecte, vous pouvez voir immédiatement la valeur 3600 dans la colonne Time, pour le thread esclave dans SHOW PROCESSLIST... Ceci est dû au fait que la dernière requête exécutée date d'une heure.

Q : Comment puis-je forcer le maître à bloquer les modifications jusqu'à ce que l'esclave ait tout rattrapé ?

R : Exécutez les commandes suivantes :

1. Sur le maître, exécutez ces commandes :

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

Enregistrez le nom du fichier de logs et l'offset, dans la commande SHOW.

2. Sur l'esclave, utilisez la commande ci-dessous, où vous aurez reporté les arguments de coordonnées de réplication données par MASTER_POS_WAIT() :

mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);

La commande SELECT va s'arrêter jusqu'à ce que l'esclave atteigne le fichier de logs et l'offset. À ce point, l'esclave sera synchronisé avec le maître, et la commande se terminera.

3. Sur le maître, utilisez la commande suivante pour permettre au maître de recommencer à traiter les modifications :

mysql> UNLOCK TABLES;

Q : Quels sont vos conseils concernant la réplication bidirectionnelle ?

R : La réplication MySQL ne supporte aucun protocole de verrouillage entre le maître et l'esclave pour garantir l'atomicité d'une modification entre les serveurs. En d'autres termes, il est possible pour un client A de faire une modification sur le serveur 1 et que dans le même temps, avant que cela ne se soit propagé au serveur 2, un client B se connecte au serveur 2, et fasse une modification sur le serveur 2 qui ne débouchera pas sur le même état que celui dans lequel le serveur 1 est. C'est ainsi qu'il ne faut pas lier de cette façon deux serveurs, à moins que les modifications ne puissent se faire dans n'importe quel ordre, ou que vous sachiez prendre en charge des modifications anarchiques.

Vous devez aussi réaliser que la réplication bidirectionnelle n'améliore pas beaucoup les performances, tout au moins au niveau des modifications. Les deux serveurs doivent faire la même quantité de modifications, ainsi qu'un serveur seul le ferait. La seule différence est qu'il va y avoir moins de verrous, car les modifications qui proviennent d'un autre serveur seront optimisées par l'esclave. Cet avantage peut aussi être annulé par les délais réseau.

Q : Comment puis-je utiliser la réplication pour améliorer les performances de mon système ?

R : Vous devez configurer un serveur en maître et y diriger toutes les écritures, puis configurer les autres en esclaves dans la limite de vos moyens, et y distribuer les lectures. Vous pouvez aussi démarrer les esclaves en mode --skip-bdb, --low-priority-updates et --delay-key-write=ALL pour accélérer les esclaves. Dans ce cas, l'esclave va utiliser les tables non transactionnelles MyISAM au lieu des tables BDB pour obtenir plus de vitesse.

Q : Que dois-je faire pour préparer mon code client à la réplication ?

R : Si la partie de votre code qui réalise les accès aux bases de données a été proprement modularisée, la convertir en une configuration qui supporte la réplication ne sera pas un problème : modifiez simplement votre base pour qu'elle aille lire sur les esclaves et le maître, mais ne fasse que des modifications avec le maître. Si votre code n'a pas ce niveau d'abstraction, l'installation du système de réplication vous donnera alors la motivation ou la raison pour le faire. Vous devriez commencer par créer une couche d'abstraction ou un module avec les fonctions suivantes :

- safe_writer_connect()

- safe_reader_connect()

- safe_reader_query()

- safe_writer_query()

safe_ signifie que la fonction devra prendre en charge toutes les conditions d'erreurs. Naturellement, vous pouvez utiliser des noms différents pour les fonctions. L'important est de savoir clairement laquelle se connecte en écriture et laquelle se connecte en lecture, et laquelle lit et laquelle écrit.

Vous devriez alors convertir votre code client pour qu'il utilise cette bibliothèque. Cela peut être un processus laborieux et déroutant, mais il va s'avérer payant dans le long terme. Toutes les applications qui suivent la technique ci-dessus pourront alors prendre avantage des solutions de réplication. Le code sera aussi bien plus facilement entretenu, et ajouter des options sera trivial. Vous devrez modifier une ou deux fonctions, comme pour enregistrer le temps de calcul de certaines requêtes, ou les requêtes qui vous retournent des erreurs.

Si vous avez écrit beaucoup de code jusqu'ici, vous pourriez vouloir automatiser la conversion en utilisant l'utilitaire de Monty, replace, qui est distribué avec la distribution standard de MySQL, ou bien simplement en écrivant un script Perl. Avec un peu de chance, votre code suit des conventions connues. Si ce n'est pas le cas, alors vous serez peut être conduit à réécrire votre application de toutes manières, ou bien, à lui appliquer des méthodes à la main.

Q : Quand et combien de réplications de MySQL permettent d'améliorer les performances de mon système ?

R : La réplication MySQL est particulièrement avantageuse pour les systèmes qui gèrent des lectures fréquentes, et des écritures plus rares. En théorie, en utilisant uniquement un maître et beaucoup d'esclaves, vous pouvez augmenter les performances de votre système jusqu'à saturation de la bande passante ou du maître, pour les modifications.

Afin de déterminer le nombre d'esclaves que vous pouvez obtenir et voir les performances de votre système s'améliorer, vous devez bien connaître les types de requêtes que vous utilisez, et empiriquement déterminer la relation entre le nombre de lectures et d'écritures (par secondes, ou maximum absolu), pour un maître et un esclave. L'exemple ci-dessous va vous montrer comment faire des calculs simples.

Imaginons que votre charge système soit constituée de 10 % d'écriture et de 90 % de lectures. Nous avons aussi déterminé que le maximum de lectures max_reads = 1200 - 2 * max_writes, ou, en d'autres mots, notre système peut voir des pics de 1200 lectures par secondes sans aucune écritures, notre temps d'écriture moyen est deux fois plus lent qu'une lecture, et la relation est linéaire. Supposons que notre maître et notre esclave sont de la même capacité, et que nous avons N esclaves et un maître. Nous avons alors pour chaque serveur (maître ou esclave) :

lectures = 1200 - 2 * écriture (issue des tests)

lectures = 9* écriture / (N + 1) (lectures réparties, mais toutes les écritures vont à tous les serveurs)

9*écriture/(N+1) + 2 * écriture = 1200

écriture = 1200/(2 + 9/(N+1)

- Si N = 0, ce qui signifie que nous n'avons pas de réplication, notre système peut gérer 1200/11, environ 109 écritures par seconde, ce qui signifie (que nous aurons 9 fois plus de lectures que d'écritures, étant donné la nature de notre application).

- Si N = 1, nous pouvons monter à 184 écritures par seconde.

- Si N = 8, nous pouvons monter à 400 écritures par seconde.

- Si N = 17, nous pouvons monter à 480 écritures par seconde.

- Éventuellement, si N se rapproche de l'infini (et notre budget de l'infini négatif), nous pourrons nous rapprocher de 600 écritures par seconde, en améliorant le système 5,5 fois. Toutefois, avec 8 serveurs, nous avons pu améliorer le système de 4 fois.

Notez que nos calculs ont supposé une bande passante infinie, et que nous avons négligé des facteurs qui pourraient être significatifs pour notre système. Dans de nombreux cas, nous ne pourrions pas faire de calculs précis pour prédire l'état de notre système avec N esclaves de réplication. Toutefois, répondre aux questions ci-dessus vous permettra de décider si la réplication est une solution à votre problème ou pas.

- Quel est le ratio d'écriture/lecture de votre système ?

- Quelle est la charge maximale d'un serveur en écriture, si vous pouvez limiter les lectures ?

- Combien d'esclaves votre réseau peut-il supporter ?

Q : Comment puis-je utiliser la réplication pour fournir un système à haute tolérance de panne ?

R : Avec les fonctionnalités actuellement disponibles, vous devez configurer un serveur et un esclave (ou plusieurs esclaves), et écrire un script qui va surveiller le maître pour voir s'il fonctionne, et instruire votre application et les esclaves d'un changement de maître en cas d'échec. Voici des suggestions.

- Utilisez la commande CHANGE MASTER TO pour changer un esclave en maître.

- Un bon moyen de garder votre application informée du maître courant est d'utiliser les DNS dynamiques, vous pouvez attribuer au maître. Avec bind, vous pouvez utiliser nsupdate pour modifier dynamiquement votre DNS.

- Vous devez faire fonctionner vos esclaves avec l'option log-bin et sans l'option log-slave-updates. De cette façon, l'esclave sera prêt à prendre le relais dès que vous lui enverrez la commande STOP SLAVE; envoyez RESET MASTER et CHANGE MASTER TO aux autres esclaves.

Par exemple, considérez l'architecture suivante (« M » représente le maître, « S » les esclaves, « WC » les clients qui émettent des commandes de lecture et écriture. Les clients qui ne font que des lectures ne sont pas représentés, car ils n'ont pas à changer quoi que ce soit.

WC
\
v
WC----> M
/ | \
/  |  \
v   v   v
S1   S2  S3

S1 (comme S2 et S3) est un esclave qui fonctionne avec les options --log-bin et sans --log-slave-updates. Comme les seules écritures faites sur S1 sont celles qui sont répliquées depuis M, le log binaire de S1 est vide : n'oubliez pas que S1 fonctionne sans --log-slave-updates. Puis, pour une raison quelconque, M devient inaccessible, et vous voulez que S1 devienne le nouveau maître (c'est-à-dire, les WC sont dirigées vers S1, et S2 et S3 répliquent S1.

Assurez-vous que tous les esclaves ont fini de traiter les requêtes de leur log de relais. Sur chaque esclave, faites STOP SLAVE IO_THREAD, puis vérifiez le résultat de la commande SHOW PROCESSLIST jusqu'à ce que vous lisiez Has read all relay log. Lorsque cela est vrai pour tous les esclaves, ils peuvent être reconfigurés vers un nouveau maître. Faites STOP SLAVE sur chaque esclave, et RESET MASTER sur celui qui devient le maître, puis CHANGE MASTER sur les autres.

Aucun WC n'accède à M. Reconfigurez les WC pour qu'ils dirigent leurs requêtes sur S1. À partir de maintenant, les requêtes envoyées par WC à S1 sont écrites dans le log binaire. Le log binaire de S1 contient maintenant exactement chaque requête envoyée à S1 depuis que M est mort. Sur S2 (et S3), faites STOP SLAVE, CHANGE MASTER TO MASTER_HOST='S1' (où 'S1' est remplacé par le vrai nom d'hôte de S1). Pour changer le maître, utilisez la commande CHANGE MASTER, et ajoutez les informations de connexion à S1 depuis S2 et S3 (utilisateur, mot de passe, port). Dans CHANGE MASTER, il n'y a pas besoin de spécifier le nom du fichier de logs binaire de S1, ou la position dans le log : nous savons que c'est le premier fichier et le premier offset (position 4), car ce sont les coordonnées par défaut utilisées par CHANGE MASTER. Finalement, lancez START SLAVE sur S2 et S3, et maintenant, vous avez ceci :

WC
/
|
WC   |  M(indisponible)
\   |
\  |
v v
S1<--S2  S3
^       |
+-------+

Lorsque M est de nouveau disponible, vous devez utiliser la commande CHANGE MASTER comme vous l'avez fait avec S2 et S3, pour que M devienne l'esclave de S1 et rattrape toutes les modifications que les WC ont émises, et qu'il a manquées. Puis, pour refaire de M le maître, suivez la même procédure que précédemment, comme si S1 était indisponible et que M prenait le relais. Durant la procédure, n'oubliez pas d'utiliser la commande RESET MASTER sur M avant de faire de S1, S2 et S3 des esclaves de M, car ils risquent de reprendre les anciennes requêtes des WC, qui datent d'avant l'indisponibilité de M.

Nous travaillons actuellement à l'intégration automatique de l'élection d'un nouveau maître, mais jusqu'à ce que ce soit près, vous devez créer votre propre outil de surveillance.

6-10 - Correction de problèmes courants

Si vous avez suivi les instructions, et que votre configuration de réplication ne fonctionne pas, commencez par supprimer les problèmes liés à l'utilisateur comme ceci.

- Vérifiez les messages d'erreur dans les logs. De nombreux utilisateurs ont perdu du temps en ne faisant pas cela en premier.

- Est-ce que le maître enregistre dans le log binaire ? Vérifiez avec la commande SHOW MASTER STATUS. S'il le fait, la variable Position doit être non nulle. Si ce n'est pas le cas, vérifiez que vous avez donné au serveur l'option log-bin et que vous lui avez donné un server-id.

- Est-ce que l'esclave fonctionne ? Vérifiez-le avec SHOW SLAVE STATUS. La réponse se trouve dans la colonne Slave_running. Si ce n'est pas le cas, vérifiez les options de l'esclave, et vérifiez le fichier de logs d'erreurs.

- Si l'esclave fonctionne, a-t-il établi une connexion avec le maître ? Exécutez la commande SHOW PROCESSLIST, et recherchez un utilisateur avec la valeur system user dans la colonne User et none dans la colonne Host, et vérifiez la colonne State. Si elle indique connecting to master, vérifiez les droits de connexion pour l'utilisateur de réplication sur le serveur, ainsi que le nom de l'hôte, votre configuration DNS, le fonctionnement du maître, et si tout est OK, vérifiez le fichier de logs d'erreurs.

- Si l'esclave fonctionnait, mais s'est arrêté, vérifiez le résultat de la commande SHOW SLAVE STATUS, et vérifiez le fichier de logs d'erreurs. Il arrive que certaines requêtes réussissent sur le maître, mais échouent sur l'esclave. Cela ne devrait pas arriver si vous avez pris la bonne sauvegarde du maître, et que vous n'avez jamais modifié les données sur le serveur esclave, autrement que par le truchement de l'esclave de réplication. Si c'est le cas, c'est un bogue, et vous devez le rapporter. Voyez plus loin pour savoir comment rapporter un bogue.

- Si une requête qui a réussi sur le maître, refuse de s'exécuter sur l'esclave, et qu'une synchronisation complète de la base ne semble pas possible, essayez ceci.

1. Commencez par voir s'il n'y a pas de lignes différentes de celles du maître. Essayez de comprendre comment elle a pu se trouver là, effacez-la, et essayez de redémarrer l'esclave avec SLAVE START. (Cela peut être un bogue : lisez les logs sur le manuel MySQL, http://www.mysql.com/documentation, pour savoir si c'est un bogue et s'il est corrigé.)

2. Si la solution ci-dessus ne fonctionne pas ou ne s'applique pas, essayez de comprendre si c'est risqué de faire une correction à la main (au besoin) puis, ignorez la prochaine requête du maître.

3. Si vous avez décidé que vous pouviez vous passer de la prochaine requête, utilisez la commande suivante :

mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n;
mysql> START SLAVE;

La valeur de n doit être de 1 si la requête n'utilise pas de valeur AUTO_INCREMENT ou LAST_INSERT_ID(). Sinon, la valeur doit être de 2. La raison pour utiliser la valeur 2 pour les requêtes qui utilisent AUTO_INCREMENT ou LAST_INSERT_ID() est qu'elles requièrent deux lignes dans le log binaire.

4. Si vous êtes sûr que l'esclave est parfaitement synchronisé avec le maître, et que personne n'a mis à jour les tables impliquées, rapportez-nous un bogue.

6-11 - Rapporter des bogues de réplication

Lorsque vous avez bien vérifié qu'il n'y a pas de problèmes avec les utilisateurs impliqués, et que la réplication ne fonctionne pas ou qu'elle est instable, il est temps d'envoyer un rapport de bogue. Nous avons besoin d'autant d'informations que possible pour rechercher le bogue. N'hésitez pas à investir quelques efforts lors de la préparation d'un rapport de bogue.

Si vous avez un moyen de reproduire le bogue, alors indiquez-le dans notre base de bogues à l'adresse http://bugs.mysql.com/. Si vous avez un problème fantôme (un qui ne peut être reproduit « à souhait »), utilisez la procédure suivante.

1. Vérifiez qu'il n'y a pas d'erreur utilisateur impliquée. Par exemple, si vous modifiez l'esclave sans passer par le thread esclave, les données seront désynchronisées et vous pourrez alors rencontrer des problèmes de contraintes de clés uniques durant les modifications. Dans ce cas, l'esclave doit être arrêté et nettoyé manuellement pour être synchronisé avec le maître. Ce n'est pas un problème de réplication : c'est un problème d'interférence extérieure, qui conduit à l'échec de la réplication.

2. Exécutez l'esclave avec les options --log-slave-updates et --log-bin. Elles font que l'esclave va enregistrer les modifications qu'il reçoit dans ses propres logs binaires.

3. Sauvez toutes les preuves avant de remettre à zéro l'état de la réplication. Si vous n'avez aucune information, ou seulement des informations partielles, cela nous prendra plus de temps pour rechercher le problème. Les preuves que vous devez rassembler sont :

- tous les logs binaires du maître ;

- tous les logs binaires de l'esclave ;

- le résultat de la commande SHOW MASTER STATUS sur le maître au moment du problème ;

- le résultat de la commande SHOW SLAVE STATUS sur l'esclave au moment du problème ;

- les logs d'erreurs du maître et de l'esclave.

4. Utilisez mysqlbinlog pour examiner les logs binaires. La commande suivante doit permettre d'identifier la requête coupable :

mysqlbinlog -j pos_from_slave_status /path/to/log_from_slave_status | head

Une fois que vous avez rassemblé toutes ces preuves du problème fantôme, essayez de l'isoler dans des cas de tests indépendants. Puis, soumettez le problème dans notre base de bogues à l'adresse http://bugs.mysql.com/ avec toute autre information importante.

7 - Optimisation de MySQL

L'optimisation est une tâche complexe, car elle nécessite une parfaite compréhension du système en entier. Alors qu'il serait possible de faire quelques optimisations localement avec une faible connaissance de votre système ou de votre application, plus vous voulez un système optimal, plus il est nécessaire de le connaître.

Ce chapitre va tenter d'expliquer et de donner des exemples de différentes manières d'optimiser MySQL. Souvenez-vous, malgré tout, qu'il existe toujours d'autres moyens (de plus en plus difficiles) de rendre le système plus véloce.

7-1 - Présentation de l'optimisation

Le facteur le plus important pour optimiser un système est la conception de base. Vous devez aussi savoir quel type de ralentissement votre système peut rencontrer, et ce qu'il doit faire.

Les ralentissements les plus fréquents sont :

- recherches sur le disque : il faut du temps pour trouver une donnée sur un disque. Avec les disques modernes, le temps moyen d'accès est de 10 ms, ce qui donne environ 100 recherches par seconde. Ce temps s'améliore lentement avec les nouveaux disques, et il est très difficile d'optimiser cette valeur pour une table unique. Pour optimiser les accès disques, il faut distribuer les données sur plusieurs disques ;

- lectures et écritures sur le disque : lorsque le disque a atteint la bonne position, nous devons y lire des données. Les disques modernes délivrent environ 10 à 20 Mo de données par seconde. Cela est facile à optimiser, car vous pouvez lire en parallèle sur plusieurs disques ;

- cycles processeurs : lorsque les données sont en mémoire centrale (ou si elles y étaient déjà), nous devons traiter les données pour obtenir le résultat. La taille des tables par rapport à la mémoire disponible est le principal facteur limitant. Avec des tables de petite taille, ce n'est jamais un problème ;

- accès mémoire : lorsque le processeur doit traiter plus de données que ce qui peut être contenu dans les caches du processeur, alors la vitesse de transfert avec la mémoire devient limitante. C'est un facteur assez extraordinaire, mais il faut en être conscient.

7-1-1 - Limitations et inconvénients des choix conceptuels de MySQL

Avec les tables de type MyISAM, MySQL utilise un verrouillage extrêmement rapide (plusieurs lectures/une seule écriture). Le plus gros problème avec ce type de table survient quand vous avez un mélange de flux de modifications et des sélections lentes sur la même table. Si c'est un problème sur plusieurs tables, vous pouvez utiliser un autre type de table pour celles-ci. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

MySQL peut utiliser à la fois des tables transactionnelles et des tables non transactionnelles. Pour pouvoir travailler tranquillement avec des tables non transactionnelles (qui n'ont pas la possibilité de revenir en arrière si quelque chose se passe mal) MySQL suit les règles suivantes.

- Toutes les colonnes ont une valeur par défaut.

- Si vous insérez une mauvaise valeur dans une colonne (par exemple NULL dans une colonne NOT NULL, ou encore une valeur numérique trop grande dans une colonne numérique), MySQL prendra en compte « la meilleure valeur possible » plutôt que de sortir une erreur. Pour les valeurs numériques, il s'agit de 0, de la valeur la plus petite possible, ou de la valeur la plus grande possible. Pour les chaînes, il s'agit soit d'une chaîne vide, soit de la chaîne la plus longue que peut contenir la colonne.

- Toutes les expressions calculées retournent une valeur qui peut être utilisée à la place d'afficher un message d'erreur. Par exemple, 1/0 retourne NULL.

Pour plus d'informations, voyez Section 1.5.6, « Comment MySQL gère les contraintes ».

Ce qui précède signifie qu'il ne faut pas que le contrôle du contenu des champs soit fait au niveau de MySQL, mais au niveau de l'application.

7-1-2 - Portabilité

Comme tous les serveurs SQL implémentent différemment le langage SQL, cela prend de solides connaissances pour écrire des applications SQL portables. Pour les insertions et sélections simples, c'est très simple, mais plus vos besoins se complexifient, plus c'est abscons. Si vous voulez une application qui fonctionne rapidement sur de nombreuses bases de données, c'est même encore plus difficile.

Pour rendre une application complexe portable, vous pouvez commencer par choisir une panoplie de serveurs SQL avec lesquels travailler.

Vous pouvez utiliser le programme/page web de MySQL appelé crash-me http://www.mysql.com/information/crash-me.php pour trouver les fonctions, types et limites que vous pouvez utiliser avec un panel de serveurs de bases de données. Les tests de crash-me ne vérifient pas tout, mais il est déjà très exhaustif avec plus de 450 points de tests.

Par exemple, vous ne devriez pas avoir de nom de colonne supérieur à 18 caractères, si vous voulez pouvoir utiliser Informix ou DB2.

Les programmes de tests crash-me et de performance de MySQL sont très indépendants du serveur. En regardant comment nous avons géré ces situations, vous pouvez comprendre comment rendre votre propre code indépendant du serveur. Les tests de performance sont situés dans le dossier sql-bench de la distribution source de MySQL. Ils sont écrits en Perl avec l'interface DBI, ce qui résout les problèmes de connexion.

Voyez http://www.mysql.com/information/benchmarks.html pour connaître les résultats de ces benchmarks.

Comme vous pouvez le voir avec ces résultats, toutes les bases de données ont leur point faible. En réalité, elles ont toutes une approche différente du même problème, et cela conduit à des comportements spécifiques.

Si vous avez besoin de l'indépendance aux serveurs de bases de données, vous devez bien connaître les faiblesses de chaque serveur. MySQL est très rapide pour lire et modifier les données, mais peine lorsque les lectures et écritures sont lentes sur la même table. Oracle, d'un autre côté, a de gros problèmes lorsque vous essayez d'accéder aux données que vous avez modifiées récemment (jusqu'à ce qu'elles soient écrites sur le disque). Les bases de données transactionnelles en général ne sont pas très douées pour générer des tables résumées à partir des tables de log, car dans ce cas, le verrouillage de ligne est inutile.

Pour rendre votre application réellement indépendante de la base de données, vous devez définir une classe très souple à travers laquelle vous allez vous interfacer pour manipuler vos données. Comme le langage C++ est disponible sur la plupart des systèmes, cela rend les classes C++ très pratiques pour cette tâche.

Si vous utilisez une fonctionnalité spécifique d'une base de données (comme la commande REPLACE de MySQL), il vous faut aussi coder la même commande pour les autres serveurs (qui sera alors plus lente). Avec MySQL, vous pouvez aussi utiliser la syntaxe /*! */ pour utiliser des mots clés spécifiques de MySQL dans une requête. Le code entre /* */ sera alors traité comme un commentaire et ignoré par la plupart des autres serveurs SQL.

Si les hautes performances sont plus importantes que l'exactitude, comme pour les applications web, il est possible de créer une couche application qui met en cache les résultats et vous donne de meilleures performances. En laissant les anciens résultats se périmer, vous pouvez garder un cache à jour. Cela vous donne une méthode pour gérer les grandes charges, durant lesquelles vous pouvez augmenter la taille du cache, et augmenter la durée de vie.

Dans ce cas, les informations de création de tables doivent contenir les informations de taille initiale du cache, et la fréquence de rafraîchissement des tables. Voir Section 5.11, « Cache de requêtes MySQL ».

7-1-3 - Pourquoi avons-nous utilisé MySQL ?

Pendant le développement initial de MySQL, les fonctions de MySQL ont été créées pour convenir à un maximum de clients. Celles-ci supportent des entrepôts de données pour deux des plus gros revendeurs suédois.

Nous recevons chaque semaine le résumé de toutes les transactions par carte de toutes les boutiques, et nous sommes chargés de fournir des informations utiles aux gérants des boutiques pour les aider à comprendre comment leurs propres campagnes publicitaires touchent leurs clients.

Les données sont assez énormes (près de 7 millions de résumés de transactions par mois), et nous avions 4-10 ans de données à présenter aux utilisateurs. Nous avons chaque semaine des requêtes des clients qui veulent un accès 'instantané' aux nouveaux rapports sur ces données.

Nous avons réussi en stockant toutes les informations dans des tables de 'transactions' compressées. Nous avons une série de macros (scripts) qui génèrent des tables de résumés groupés par différents critères (groupe de produits, identifiant de client, boutique...). Ces rapports sont des pages Web générées dynamiquement par un petit script Perl qui parcourt une page web, exécute les requêtes SQL, et insère les résultats. Nous aurions bien utilisé PHP ou mod_perl à la place, mais ils n'étaient pas disponibles à cette époque.

Nous avons écrit un outil en C pour la représentation graphique des données qui génère des GIF à partir du résultat de requêtes SQL (avec quelques traitements sur le résultat). Ceci est également effectué dynamiquement par le script Perl qui parcourt les fichiers HTML.

Pour la plupart des cas, un nouveau rapport peut simplement être fait en copiant un script existant, et en modifiant la requête SQL qu'il exécute. Dans certains cas, nous aurons besoin d'ajouter des champs à une table de résumé existante ou d'en générer une nouvelle, mais c'est tout de même toujours assez simple, car nous gardons toutes les tables de transactions sur disque. (Actuellement, nous avons au moins 50 Go de tables de transactions et 200 Go d'autres données sur les clients.)

Nous donnons également accès aux tables de résumés à nos clients directement avec ODBC, de sorte que les utilisateurs avancés puissent traiter les données eux-mêmes.

Nous n'avons eu aucun problème à supporter tout cela avec une relativement modeste Sun Ultra SPARCStation (2x200 MHz). Nous avons récemment amélioré l'un de nos serveurs en un bi-CPU 400 MHz UltraSPARC, et nous projetons actuellement de supporter les transactions au niveau du produit, ce qui signifie un décuplement des données. Nous pensons pouvoir y arriver uniquement en ajoutant des disques supplémentaires à nos systèmes.

Nous expérimentons aussi Intel-Linux, pour pouvoir avoir plus de puissance CPU pour moins cher. Comme nous utilisons désormais le format binaire portable pour les bases de données (nouveauté de la version 3.23), nous utiliserons cela pour quelques parties de l'application.

Nous avons au départ le sentiment que Linux s'acquittera mieux des faibles et moyennes charges tandis que Solaris fonctionnera mieux sur les grosses charges à cause des I/O disques extrêmes, mais nous n'avons actuellement aucune conclusion à ce propos. Après quelques discussions avec un développeur du noyau Linux, un effet de bord de Linux est d'allouer trop de ressources aux travaux de traitement, ainsi les performances de l'interface interactive peuvent devenir vraiment lentes. Cela fait apparaître la machine très lente et sans réponse lorsque de gros traitements sont en cours. Heureusement, cela sera mieux géré dans les futurs noyaux de Linux.

7-1-4 - La suite de tests MySQL

Ceci devrait comprendre une description technique de la suite de tests de performance de MySQL (et crash-me), mais cette description n'est pas encore écrite. Actuellement, vous pouvez vous faire une idée des tests en regardant le code et les résultats dans le répertoire sql-bench dans toutes les distributions de sources de MySQL.

Cette suite de tests est censée permettre à utilisateur de comparer ce qu'une implémentation SQL donnée réussit bien ou mal.

Sachez que ces tests de performance lancent en un seul thread, donc il mesure le temps minimum pour chaque opération. Nous projetons pour le futur d'ajouter de nombreux tests multithreads à cette suite de tests.

Par exemple, (tous ont été lancés sur une même machine NT 4.0)

Lecture de 2 000 000 lignes indexées

Secondes

Secondes

mysql

367

249

mysql_odbc

464

db2_odbc

1206

informix_odbc

121126

ms-sql_odbc

1634

oracle_odbc

20800

solid_odbc

877

sybase_odbc

17614

Insertion de lignes (350768)

Secondes

Secondes

mysql

381

206

mysql_odbc

619

db2_odbc

3460

informix_odbc

2692

ms-sql_odbc

4012

oracle_odbc

11291

solid_odbc

1801

sybase_odbc

4802

Le test ci-dessus a été exécuté avec un index de cache de 8 Mo.

Nous avons rassemblé d'autres résultats de tests à http://www.mysql.com/information/benchmarks.html.

Notez que Oracle n'est pas inclus dans ces tests, car ils ont demandé à être retirés. Tous les tests d'Oracle doivent être faits par Oracle ! Nous croyons que cette politique va biaiser fortement les tests en faveur de Oracle, car les tests ci-dessus sont supposés montrer ce qu'une installation simple peut faire pour un client simple.

Pour utiliser la suite de tests, les prérequis suivants doivent être vérifiés.

- La suite de tests est disponible dans la distribution source de MySQL, et vous devez avoir téléchargé cette distribution. Vous pouvez télécharger la version publiée sur le site de http://www.mysql.com/downloads/, ou utiliser celle du serveur de développement (voir Section 2.4.3, « Installer à partir de l'arbre source de développement »).

- Les scripts de tests ont été écrits en Perl, et utilisent le module Perl DBI pour accéder aux serveurs, donc DBI doit être installée. Vous aurez aussi besoin des pilotes spécifiques DBD de chaque serveur que vous voulez tester. Par exemple, pour tester MySQL, PostgreSQL et DB2, les modules DBD::mysql, DBD::Pg et DBD::DB2 doivent être installés. Voir Section 2.9, « Commentaires sur l'installation de Perl ».

La suite de tests est située dans le dossier sql-bench de la distribution source de MySQL. Pour exécuter la suite de tests, compilez MySQL, puis allez dans le dossier sql-bench et exécutez le script run-all-tests :

shell> cd sql-bench
shell> perl run-all-tests --server=server_name

server_name est un des serveurs supportés. Pour avoir la liste de toutes les options et serveurs supportés. Utilisez cette commande :

shell> perl run-all-tests --help

Le script crash-me est aussi situé dans le dossier sql-bench. crash-me essaie de déterminer quelles fonctionnalités un serveur supporte, et quelles sont ses limitations. Par exemple, le test détermine :

- les types de colonnes supportés ;

- le nombre d'index supportés ;

- les fonctions supportées ;

- la taille maximale d'une requête ;

- la taille maximale d'une colonne VARCHAR.

Vous pouvez retrouver les résultats de crash-me sur de nombreuses bases de données à http://www.mysql.com/information/crash-me.php.

7-1-5 - Utiliser vos propres tests de performance

Vous devriez vraiment penser à préparer des tests de performance pour votre application et base, afin d'identifier les opérations les plus lentes. En les corrigeant (ou en remplaçant ces opérations des « modules simples ») vous pouvez facilement identifier les autres opérations lentes (et ainsi de suite...). Même si la performance générale de votre application est suffisante, vous devriez prévoir où seront les prochains freins, et décider d'anticiper leur résolution, avant que vous n'ayez vraiment besoin de ces performances.

Pour avoir un exemple de programme de tests portables, voyez la suite de tests MySQL. Voir Section 7.1.4, « La suite de tests MySQL ». Vous pouvez prendre n'importe quel programme de cette suite, le modifier pour l'adapter à vos besoins, et essayer différentes solutions à votre problème : il suffit de tester et d'identifier la solution la plus rapide pour vous.

Une autre suite de tests est la « Open Source Database Benchmark », disponible sur le site de http://osdb.sourceforge.net/.

Il est très fréquent que des problèmes surviennent lorsque le système subit une forte charge. Nous avons de nombreux clients qui nous contactent lorsqu'ils ont mis leur système en production, et rencontré des problèmes de charge. Pour chacun d'entre eux, les problèmes étaient des problèmes simples de conceptions (les scans de tables ne sont pas bons sous forte charge) ou des problèmes liés au système d'exploitation ou les bibliothèques. La plupart auraient été vraiment plus simples à tester si le système n'était pas déjà en production.

Pour éviter des problèmes comme ceux-là, vous devriez mettre quelques efforts dans les tests de votre application dans son ensemble, avant de la mettre dans les pires conditions. Vous pouvez utiliser le programme Super Smack pour cela, qui est disponible à http://www.mysql.com/Downloads/super-smack/super-smack-1.0.tar.gz. Comme son nom le suggère, il va mettre votre système à genoux si vous lui demandez, alors assurez-vous de ne l'utiliser qu'avec votre système de développement.

7-2 - Optimisation des commandes SELECT et autres requêtes

Premièrement, ce qui affecte toutes les requêtes : plus votre système de droits est compliqué, plus vous aurez des baisses de performances.

Si vous n'avez aucun GRANT effectué, MySQL optimisera les vérifications de droits. Donc, si vous avez un système volumineux, il serait bénéfique d'éviter les grants. Sinon les performances seront réduites. Par exemple, si vous n'avez pas de droits de niveau table ou colonne, le serveur n'a pas à vérifier le contenu des tables tables_priv et columns_priv. Similairement, si vous n'avez pas de limites de ressources, le serveur n'a pas de comptes de ressources à faire. Si vous avez un très haut niveau de requêtes, il peut se révéler bénéfique d'utiliser une structure de droits simplifiée, pour réduire le temps de vérification.

Si votre problème est spécifique à une expression MySQL ou une fonction, vous pouvez utiliser la fonction BENCHMARK() du client mysql pour effectuer un test de performance. La syntaxe est BENCHMARK(loop_count,expression). Par exemple :

mysql> SELECT BENCHMARK(1000000,1+1);
+------------------------+
| BENCHMARK(1000000,1+1) |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.32 sec)

Ce qui précède montre que MySQL peut exécuter 1 000 000 d'additions en 0.32 seconde sur un PentiumII 400 MHz.

Toutes les fonctions MySQL sont censées être optimisées, mais il peut y avoir quelques exceptions et la fonction BENCHMARK(nombre_de_fois,expression) est un très bon moyen de trouver ce qui cloche dans vos requêtes.

7-2-1 - Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

EXPLAIN tbl_name

ou :

EXPLAIN SELECT select_options

EXPLAIN nom_de_table est un synonyme de DESCRIBE nom_de_table ou SHOW COLUMNS FROM nom_de_table.

- La syntaxe EXPLAIN tbl_name est synonyme de DESCRIBE tbl_name ou SHOW COLUMNS FROM tbl_name.

- Lorsque vous faites précéder une commande SELECT avec le mot-clé EXPLAIN, MySQL vous explique comment il va traiter la commande SELECT, choisir les tables et index pour les jointures.

Cette section fournit des informations sur comment utiliser EXPLAIN.

Avec l'aide de EXPLAIN, vous pouvez identifier les index à ajouter pour accélérer les commandes SELECT.

Vous devriez souvent utiliser la commande ANALYZE TABLE pour mettre à jour les statistiques de cardinalité de vos tables, qui affectent les choix de l'optimiseur. Voir Section 13.5.2.1, « Syntaxe de ANALYZE TABLE ».

Vous pouvez aussi voir si l'optimiseur fait les jointures dans un ordre vraiment optimal. Pour forcer l'optimiseur à utiliser un ordre spécifique de jointure dans une commande SELECT, ajoutez l'attribut STRAIGHT_JOIN à la clause.

Pour les jointures complexes, EXPLAIN retourne une ligne d'information pour chaque table utilisée dans la commande SELECT. Les tables sont listées dans l'ordre dans lequel elles seront lues. MySQL résout toutes les jointures avec une seule passe multijointure. Cela signifie que MySQL lit une ligne dans la première table, puis recherche les lignes qui correspondent dans la seconde, puis dans la troisième, etc. Lorsque toutes les tables ont été traitées, MySQL affiche les colonnes demandées, et il remonte dans les tables jusqu'à la dernière qui avait encore des lignes à traiter. La prochaine ligne est alors traitée de la même façon.

Avec MySQL version 4.1 l'affichage de EXPLAIN a été modifié pour mieux fonctionner avec les structures comme UNION, sous-requêtes, et tables dérivées. La plus importante évolution est l'addition de deux nouvelles colonnes : id et select_type.

Le résultat de la commande EXPLAIN est constitué des colonnes suivantes.

- id

identifiant de SELECT, le numéro séquentiel de cette commande SELECT dans la requête.

- select_type

Type de clause SELECT, qui peut être :

- SIMPLE

SELECT simple (sans utiliser de clause UNION ou de sous-requêtes) ;

- PRIMARY

SELECT extérieur ;

- UNION

Second et autres UNION SELECT ;

- DEPENDENT UNION

Second et autres UNION SELECT, dépend de la commande extérieure ;

- SUBQUERY

Premier SELECT de la sous-requête ;

- DEPENDENT SUBSELECT

Premier SELECT, dépendant de la requête extérieure ;

- DERIVED

Table dérivée SELECT ;

- table

La table à laquelle la ligne fait référence.

- type

Le type de jointure. Les différents types de jointures sont les suivants, dans l'ordre du plus efficace au plus lent :

- system

La table a une seule ligne (c'est une table système). C'est un cas spécial du type de jointure const ;

- const

La table a au plus une ligne correspondante, qui sera lue dès le début de la requête. Comme il n'y a qu'une seule ligne, les valeurs des colonnes de cette ligne peuvent être considérées comme des constantes pour le reste de l'optimiseur. Les tables const sont très rapides, car elles ne sont lues qu'une fois.

const est utilisé lorsque vous comparez toutes les parties d'une clé PRIMARY/UNIQUE avec des constantes :

SELECT * FROM const_table WHERE primary_key=1;

SELECT * FROM const_table
WHERE primary_key_part1=1 AND primary_key_part2=2;

- eq_ref

Une ligne de cette table sera lue pour chaque combinaison de ligne des tables précédentes. C'est le meilleur type de jointure possible, à l'exception des précédents. Il est utilisé lorsque toutes les parties d'un index sont utilisées par la jointure, et que l'index est UNIQUE ou PRIMARY KEY.

eq_ref peut être utilisé pour les colonnes indexées, qui sont comparées avec l'opérateur =. L'élément comparé doit être une constante ou une expression qui utilise les colonnes de la table qui est avant cette table.

Dans l'exemple suivant, ref_table sera capable d'utiliser eq_ref :

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

- ref

Toutes les lignes avec des valeurs d'index correspondantes seront lues dans cette table, pour chaque combinaison des lignes précédentes. ref est utilisé si la jointure n'utilise que le préfixe de gauche de la clé, ou si la clé n'est pas UNIQUE ou PRIMARY KEY (en d'autres termes, si la jointure ne peut pas sélectionner qu'une seule ligne en fonction de la clé). Si la clé qui est utilisée n'identifie que quelques lignes à chaque fois, la jointure est bonne.

ref peut être utilisé pour les colonnes indexées, qui sont comparées avec l'opérateur =.

Dans les exemples suivants, ref_table sera capable d'utiliser ref.

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

- ref_or_null

Comme ref, mais avec le coût supplémentaire pour les recherches couvrant les valeurs NULL. Ce type de jointure est nouveau en MySQL 4.1.1 sert essentiellement à la résolution des sous-requêtes.

Dans les exemples suivants, MySQL peut utiliser une jointure ref_or_null pour traiter ref_table :

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

Voir Section 7.2.7, « Comment MySQL optimise IS NULL ».

- index_merge

Ce type de jointure indique que l'optimisation de type Index Merge est utilisée. Dans ce cas, la colonne key contient une liste d'index utilisés, et key_len contient la liste des plus longues parties de clés utilisées. Pour plus d'informations, voyez Section 7.2.6, « Optimisation de combinaison d'index ».

- unique_subquery

Ce type remplace le type ref dans certaines sous-requêtes IN de la forme suivante :

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery est simplement une analyse d'index, qui remplace complètement la sous-requête pour une meilleure efficacité.

- index_subquery

Ce type de jointure est similaire à unique_subquery. Elle remplace des sous-requêtes IN, mais elle fonctionne pour les index non uniques dans les sous-requêtes de la forme suivante :

value IN (SELECT key_column FROM single_table WHERE some_expr)

- range

Seules les lignes qui sont dans un intervalle donné seront lues, en utilisant l'index pour sélectionner les lignes. La colonne key indique quel est l'index utilisé. key_len contient la taille de la partie de la clé qui est utilisée. La colonne ref contiendra la valeur NULL pour ce type.

range peut être utilisé lorsqu'une colonne indexée est comparée avec une constante comme =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN ou IN.

SELECT * FROM tbl_name
WHERE key_column = 10;

SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);

SELECT * FROM tbl_name
WHERE key_part1= 10 AND key_part2 IN (10,20,30);

- index

C'est la même chose que ALL, hormis le fait que seul l'arbre d'index est étudié. C'est généralement plus rapide que ALL, car le fichier d'index est plus petit que le fichier de données.

Cette méthode peut être utilisée lorsque la requête utilise une colonne qui fait partie d'un index.

- ALL

Une analyse complète de la table sera faite pour chaque combinaison de lignes issue des premières tables. Ce n'est pas bon si la première table n'est pas une jointure de type const et c'est très mauvais dans les autres cas. Normalement vous pouvez éviter ces situations de ALL en ajoutant des index basés sur des parties de colonnes.

- possible_keys

La colonne possible_keys indique quels index MySQL va pouvoir utiliser pour trouver les lignes dans cette table. Notez que cette colonne est totalement dépendante de l'ordre des tables. Cela signifie que certaines clés de la colonne possible_keys pourraient ne pas être utilisées dans d'autres cas d'ordre de tables.

Si cette colonne est vide, il n'y a pas d'index pertinent. Dans ce cas, vous pourrez améliorer les performances en examinant votre clause WHERE pour voir si des colonnes sont susceptibles d'être indexées. Si c'est le cas, créez un index approprié, et examinez le résultat avec la commande EXPLAIN. Voir Section 13.2.2, « Syntaxe de ALTER TABLE ».

Pour connaître tous les index d'une table, utilisez le code SHOW INDEX FROM nom_de_table.

- key

La colonne key indique l'index que MySQL va décider d'utiliser. Si la clé vaut NULL, aucun index n'a été choisi. Pour forcer MySQL à utiliser un index listé dans la colonne possible_keys, utilisez USE KEY/IGNORE KEY dans votre requête. Voir Section 13.1.7, « Syntaxe de SELECT ».

Pour les tables MyISAM et BDB, la commande ANALYZE TABLE va aider l'optimiseur à choisir les meilleurs index. Pour les tables MyISAM, myisamchk --analyze fera la même chose. Voyez Section 13.5.2.1, « Syntaxe de ANALYZE TABLE » et Section 5.7.3, « Utilisation de myisamchk pour la maintenance des tables et leur recouvrement ».

- key_len

La colonne key_len indique la taille de la clé que MySQL a décidé d'utiliser. La taille est NULL si la colonne key vaut NULL. Notez que cela vous indique combien de parties d'une clé multiple MySQL va réellement utiliser.

- ref

La colonne ref indique quelle colonne ou quelles constantes sont utilisées avec la clé key, pour sélectionner les lignes de la table.

- rows

La colonne rows indique le nombre de lignes que MySQL estime devoir examiner pour exécuter la requête.

- Extra

Cette colonne contient des informations additionnelles sur comment MySQL va résoudre la requête. Voici une explication des différentes chaînes que vous pourriez trouver dans cette colonne :

- Distinct

MySQL ne va pas continuer à chercher d'autres lignes que la ligne courante, après en avoir trouvé une ;

- Not exists

MySQL a été capable d'appliquer une optimisation de type LEFT JOIN sur la requête, et ne va pas examiner d'autres lignes de cette table pour la combinaison de lignes précédentes, une fois qu'il a trouvé une ligne qui satisfait le critère de LEFT JOIN.

Voici un exemple de cela :

SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id
WHERE t2.id IS NULL;

Supposons que t2.id est défini comme NOT NULL. Dans ce cas, MySQL va scanner t1 et rechercher des lignes dans t2 via t1.id. Si MySQL trouve une ligne dans t2, il sait que t2.id ne peut pas être NULL, et il ne va pas scanner le reste des lignes de t2 qui ont le même id. En d'autres termes, pour chaque ligne de t1, MySQL n'a besoin que de faire une recherche dans t2, indépendamment du nombre de lignes qui sont trouvées dans t2.

- range checked for each record (index map: #)

MySQL n'a pas trouvé d'index satisfaisant à utiliser. Il va, à la place, pour chaque combinaison de lignes des tables précédentes, faire une vérification de quel index utiliser (s'il en existe), et utiliser cet index pour continuer la recherche. Ce n'est pas très rapide, mais c'est plus rapide que de faire une recherche sans aucun index.

- Using filesort

MySQL va avoir besoin d'un autre passage pour lire les lignes dans l'ordre. Le tri est fait en passant en revue toutes les lignes, suivant le type de jointure et stockant la clé et le pointeur de chaque ligne qui satisfait la clause WHERE. Alors, les clés sont triées. Finalement, les lignes sont triées dans l'ordre.

- Using index

Les informations de la colonne sont lues de la table, en utilisant uniquement les informations contenues dans l'index, sans avoir à faire d'autres lectures. Cela peut arriver lorsque toutes les colonnes utilisées dans une table font partie de l'index.

- Using temporary

Pour résoudre la requête, MySQL va avoir besoin de créer une table temporaire pour contenir le résultat. C'est typiquement ce qui arrive si vous utilisez une clause ORDER BY sur une colonne différente de celles qui font partie de GROUP BY.

- Using where

Une clause WHERE sera utilisée pour restreindre les lignes qui seront trouvées dans la table suivante, ou envoyée au client. Si vous n'avez pas cette information, et que la table est de type ALL ou index, vous avez un problème dans votre requête (si vous ne vous attendiez pas à tester toutes les lignes de la table).

Si vous voulez rendre vos requêtes aussi rapides que possible, vous devriez examiner les lignes qui utilisent Using filesort et Using temporary.

Vous pouvez obtenir une bonne indication de la qualité de votre jointure en multipliant toutes les valeurs de la colonne rows dans la table de la commande EXPLAIN. Cela est une estimation du nombre de lignes que MySQL va examiner pour exécuter cette requête. C'est aussi ce nombre qui sera utilisé pour interrompre votre requête, grâce à la variable max_join_size. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

L'exemple ci-dessous illustre comment une requête JOIN peut être optimisée avec les résultats de la commande EXPLAIN.

Supposons que vous avez la requête SELECT suivante, et que vous l'examinez avec EXPLAIN:

EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
tt.ProjectReference, tt.EstimatedShipDate,
tt.ActualShipDate, tt.ClientID,
tt.ServiceCodes, tt.RepetitiveID,
tt.CurrentProcess, tt.CurrentDPPerson,
tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
et_1.COUNTRY, do.CUSTNAME
FROM tt, et, et AS et_1, do
WHERE tt.SubmitTime IS NULL
AND tt.ActualPC = et.EMPLOYID
AND tt.AssignedPC = et_1.EMPLOYID
AND tt.ClientID = do.CUSTNMBR;

Pour cet exemple, nous supposons que :

- les colonnes utilisées sont déclarées comme ceci :

Table

Colonne

Type de colonne

tt

ActualPC

CHAR(10)

tt

AssignedPC

CHAR(10)

tt

ClientID

CHAR(10)

et

EMPLOYID

CHAR(15)

do

CUSTNMBR

CHAR(15)

- les tables ont les index suivants :

Table

Index

tt

ActualPC

tt

AssignedPC

tt

ClientID

et

EMPLOYID (clé primaire)

do

CUSTNMBR (clé primaire)

- les valeurs de tt.ActualPC ne sont pas réparties également.

Initialement, avant toute optimisation, la commande EXPLAIN produit les informations suivantes :

table type possible_keys key  key_len ref  rows  Extra
et    ALL  PRIMARY       NULL NULL    NULL 74
do    ALL  PRIMARY       NULL NULL    NULL 2135
et_1  ALL  PRIMARY       NULL NULL    NULL 74
tt    ALL  AssignedPC,   NULL NULL    NULL 3872
ClientID,
ActualPC
range checked for each record (key map: 35)

Comme le type type vaut ALL pour chaque table, le résultat indique que MySQL fait une analyse complète de toutes les tables. Cela va prendre un très long temps de calcul, car le nombre de lignes à examiner de cette façon est le produit du nombre de lignes de toutes les tables : dans notre cas, cela vaut 74 * 2135 * 74 * 3872 = 45 268 558 720 lignes. Si les tables étaient plus grandes, cela serait encore pire.

Le premier problème que vous avons ici, est que MySQL ne peut pas (encore) utiliser d'index sur les colonnes, si elles sont déclarées différemment. Dans ce contexte, les colonnes VARCHAR et CHAR sont les mêmes, mais elles ont été déclarées avec des tailles différentes. Comme tt.ActualPC est déclarée comme CHAR(10) et que et.EMPLOYID est déclaré comme CHAR(15), il y a un problème de taille.

Pour corriger cette disparité, utilisez la commande ALTER TABLE pour agrandir la colonne ActualPC de 10 caractères à 15 :

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

Maintenant, tt.ActualPC et et.EMPLOYID sont tous les deux des colonnes de type VARCHAR(15). Exécuter la commande EXPLAIN produit maintenant le résultat suivant :

table type   possible_keys key     key_len ref         rows    Extra
tt    ALL    AssignedPC,   NULL    NULL    NULL        3872    Using
ClientID,                                         where
ActualPC
do    ALL    PRIMARY       NULL    NULL    NULL        2135
range checked for each record (key map: 1)
et_1  ALL    PRIMARY       NULL    NULL    NULL        74
range checked for each record (key map: 1)
et    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC 1

Ce n'est pas parfait, mais c'est bien mieux. Le produit de toutes les lignes a été divisé par 74. Cette version s'exécute en quelques secondes.

Une autre modification peut être faite pour éliminer les problèmes de taille de colonne pour tt.AssignedPC = et_1.EMPLOYID et tt.ClientID = do.CUSTNMBR :

mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
->                MODIFY ClientID   VARCHAR(15);

Maintenant, EXPLAIN produit le résultat suivant :

table type   possible_keys key      key_len ref           rows Extra
et    ALL    PRIMARY       NULL     NULL    NULL          74
tt    ref    AssignedPC,   ActualPC 15      et.EMPLOYID   52   Using
ClientID,                                         where
ActualPC
et_1  eq_ref PRIMARY       PRIMARY  15      tt.AssignedPC 1
do    eq_ref PRIMARY       PRIMARY  15      tt.ClientID   1

C'est presque aussi bon que cela pourrait l'être.

Le problème final est que, par défaut, MySQL suppose que les valeurs de la colonne tt.ActualPC sont uniformément réparties, et que ce n'est pas le cas pour la table tt. Mais il est facile de le dire à MySQL :

mysql> <userinput>ANALYZE TABLE tt;</userinput>

Maintenant, la jointure est parfaite, et la commande EXPLAIN produit ce résultat :

table type   possible_keys key     key_len ref           rows Extra
tt    ALL    AssignedPC    NULL    NULL    NULL          3872 Using
ClientID,                                        where
ActualPC
et    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC   1
et_1  eq_ref PRIMARY       PRIMARY 15      tt.AssignedPC 1
do    eq_ref PRIMARY       PRIMARY 15      tt.ClientID   1

Notez que la colonne rows dans le résultat de EXPLAIN est une prédiction éclairée de l'optimiseur de jointure MySQL. Pour optimiser une requête, vous devriez vérifier si ces nombres sont proches de la réalité. Si ce n'est pas le cas, vous pourriez obtenir de meilleures performances avec l'attribut STRAIGHT_JOIN dans votre commande SELECT, et en choisissant vous-même l'ordre de jointure des tables dans la clause FROM.

7-2-2 - Mesurer les performances d'une requête

Dans la plupart des cas, vous pouvez mesurer la performance d'une requête en comptant le nombre d'accès disques. Pour les tables de petite taille, vous pouvez généralement obtenir une seule lecture (car l'index est probablement en cache). Pour les tables plus grandes, vous pouvez estimer que vous aurez besoin de (en utilisant les index B-tree) : log(row_count) / log(index_block_length / 3 * 2 / (index_length + data_pointer_length)) + 1 lectures pour trouver une ligne.

Pour MySQL, un bloc d'index vaut généralement 1024 octets, et le pointeur de données vaut 4 octets. Une table de 500 000 avec un index de taille 3 (entier moyen) vous donnera log(500,000)/log(1024/3*2/(3+4)) + 1 = 4 lectures.

Comme l'index ci-dessus serait de taille 500 000 * 7 * 3/2 = 5.2 Mo, (en supposant que les index des tampons sont remplis aux 2/3, ce qui est typique), vous aurez probablement l'essentiel de l'index en mémoire, et vous n'aurez alors besoin que d'une ou deux lectures pour lire le reste des lignes.

Pour les écritures, toutefois, vous aurez besoin de quatre lectures (comme ci-dessus), pour trouver la place du nouvel index, et normalement, deux autres lectures pour modifier l'index et la ligne.

Notez que le raisonnement ci-dessus n'indique pas que votre application va dégénérer en fonction du logarithme népérien ! Tant que tout est mis en cache par l'OS ou le serveur SQL, les performances ne vont se réduire que marginalement, même si la table grossit beaucoup. Une fois que les données seront trop importantes pour être en cache, votre application va ralentir, car le serveur devra faire des lectures sur le disque (ce qui va accroître le log). Pour éviter cela, augmentez le cache d'index au fur et à mesure que votre index grossit. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

7-2-3 - Vitesse des requêtes SELECT

En général, lorsque vous voulez rendre un SELECT ... WHERE plus rapide, la première chose à faire est de voir si vous pouvez ajouter des index. Toutes les références entre les tables doivent normalement être faites avec des index. Vous pouvez utiliser la commande EXPLAIN pour déterminer les index utilisés pour le SELECT. Voyez aussi Section 7.4.5, « Comment MySQL utilise les index » et Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) ».

Quelques conseils généraux

- Pour aider MySQL à mieux optimiser les requêtes, exécutez myisamchk --analyze sur une table après l'avoir remplie avec quelques données consistantes. Cela met à jour une valeur pour chaque partie de l'index qui indique le nombre moyen de lignes qui ont la même valeur. (Pour les index uniques, c'est toujours 1, bien sûr.) MySQL utilisera cela pour décider quel index choisir pour connecter deux tables avec une « expression non constante ». Vous pouvez vérifier le retour de l'exécution d'analyze en faisant SHOW INDEX FROM nom_de_table et examiner la colonne Cardinality.

- Pour trier un index et des données par rapport à un index, utilisez myisamchk --sort-index --sort-records=1 (si vous voulez trier selon le premier index). Si vous avec un index unique à partir duquel vous voulez lire toutes les lignes en prenant comme ordre cet index, c'est un bon moyen de rendre les traitements plus rapides. Notez, toutefois, que ce tri n'est pas le plus optimal et prendra beaucoup de temps pour une grosse table !

7-2-4 - Comment MySQL optimise les clauses WHERE

Les optimisations de la clause WHERE sont présentées avec la commande SELECT, car elles sont généralement utilisées avec la commande SELECT, mais les mêmes optimisations peuvent s'appliquer aux clauses WHERE des commandes DELETE et UPDATE.

Notez aussi que cette section est incomplète. MySQL fait de très nombreuses optimisations, et nous n'avons pas eu le temps de toutes les documenter.

Certaines des optimisations effectuées par MYSQL sont présentées ici.

- Suppression des parenthèses inutiles :

((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)

- Remplacement des constantes :

(a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5

- Suppression des conditions constantes (nécessaire pour le remplacement des constantes) :

(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6

- Les expressions constantes utilisées par les index sont évaluées une fois.

- COUNT(*) sur une table simple, sans clause WHERE est lu directement dans les informations de la table pour les tables MyISAM et HEAP. Cela peut aussi être fait avec les expressions NOT NULL lorsqu'elles sont utilisées sur une seule table.

- Détection précoce des expressions constantes invalides. MySQL détecte rapidement les commandes SELECT qui sont impossibles, et ne retourne aucune ligne.

- HAVING est combiné avec la clause WHERE si vous n'utilisez pas la clause GROUP BY ou les fonctions de groupe (COUNT(), MIN()...).

- Pour chaque sous-jointure, une clause WHERE simplifiée est construite pour accélérer l'évaluation de WHERE pour chaque sous-jointure, et aussi essayer d'ignorer les lignes le plus tôt possible.

- Toutes les tables constantes sont lues en premier, avant toute autre table de la requête. Une table constante est :

- une table vide ou une table d'une ligne ;

- une table qui est utilisée avec la clause WHERE sur un index de type UNIQUE, ou avec une clé primaire PRIMARY KEY, dont toutes les parties sont des expressions constantes, et les parties de l'index sont identifiées comme NOT NULL.

Toutes les tables suivantes sont considérées comme constantes :

mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2
->          WHERE t1.primary_key=1 AND t2.primary_key=t1.id;

- La meilleure combinaison de jointures est obtenue en testant toutes les possibilités. Si toutes les colonnes des clauses ORDER BY et GROUP BY proviennent de la même table, cette table sera utilisée de préférence comme première table dans la jointure.

- S'il y a une clause ORDER BY et une clause GROUP BY différente, ou si la clause ORDER BY ou GROUP BY contient des colonnes issues des tables autres que la première, une table temporaire est créée.

- Si vous utilisez SQL_SMALL_RESULT, MySQL va utiliser une table temporaire en mémoire.

- Chaque index de table est interrogé, et le meilleur index qui représente moins de 30 % des lignes est utilisé. Si un tel index ne peut être identifié, un scan rapide de la table est fait.

- Dans certains cas, MySQL peut lire des lignes depuis l'index sans même consulter le fichier de données. Si toutes les colonnes de l'index sont des nombres, alors seul l'arbre d'index sera utilisé pour résoudre la requête.

- Avant chaque affichage de ligne, celles qui ne satisfont pas les critères de la clause HAVING sont ignorées.

Quelques exemples de requêtes très rapides :

mysql> SELECT COUNT(*) FROM tbl_name;
mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql> SELECT MAX(key_part2) FROM tbl_name
->        WHERE key_part_1=constant;
mysql> SELECT ... FROM tbl_name
->        ORDER BY key_part1,key_part2,... LIMIT 10;
mysql> SELECT ... FROM tbl_name
->        ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;

Les requêtes suivantes ne sont résolues qu'avec l'arbre d'index (en supposant que les colonnes sont numériques) :

mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql> SELECT COUNT(*) FROM tbl_name
->        WHERE key_part1=val1 AND key_part2=val2;
mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;

Les requêtes suivantes utilisent l'indexation pour lire les lignes dans un ordre donné, sans faire de tri supplémentaire :

mysql> SELECT ... FROM tbl_name
->            ORDER BY key_part1,key_part2,... ;
mysql> SELECT ... FROM tbl_name
->            ORDER BY key_part1 DESC,key_part2 DESC,... ;

7-2-5 - Optimisation d'intervalle

La méthode d'accès range utilise un seul index pour obtenir une sous-partie de table, dont les lignes font partie d'un intervalle de valeurs d'index. La description détaillée de l'extraction des index de la clause WHERE est présentée dans les sections suivantes.

7-2-5-1 - Méthode d'accès par intervalle pour les index multicolonnes

Pour un index à une colonne, les intervalles peuvent être représentés en pratique par les conditions correspondant à la clause WHERE, et cela donne des « conditions d'intervalle » au lieu d'intervalle.

La définition d'une condition d'intervalle pour un index monocolonne est la suivante :

- pour les index BTREE et HASH, la comparaison d'une partie de clé avec une valeur constante est une condition d'intervalle lorsqu'on l'utilise avec =, <=>, IN, IS NULL ou IS NOT NULL ;

- pour les index BTREE, la comparaison d'une partie de clé avec une constante est une condition d'intervalle avec les opérateurs >, <, >=, <=, BETWEEN, != et <>, ou LIKE 'pattern' (où 'pattern' ne commence pas avec un joker) ;

- pour tous les types d'index, plusieurs conditions d'intervalle combinées avec des opérateurs OR ou AND forment une condition d'intervalle.

« Valeur constante », dans les descriptions précédentes, signifie l'un des objets suivants.

- Une constante dans une chaîne de requêtes.

- Une colonne dans une table const ou system dans une jointure.

- Le résultat d'une sous-requête non corrélée.

- Une expression composée entièrement de sous-expressions de l'un des types précédents.

Voici des exemples de requêtes avec des conditions d'intervalle dans la clause WHERE :

SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10;

SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20);

SELECT * FROM t1 WHERE key_col LIKE 'ab%' OR key_col BETWEEN
'bar' AND 'foo';

Notez que certaines valeurs non constantes sont converties en constantes durant la phase de propagation des constantes.

MySQL essaie d'extraire les conditions d'intervalle de la clause WHERE pour chaque index possible. Durant le processus d'extraction, les conditions qui ne peuvent pas être utilisées sont ignorées, les conditions qui produisent des intervalles qui se recoupent sont combinées, et les conditions qui produisent des intervalles vides sont supprimées.

Par exemple, observez la commande suivante, où key1 est une colonne indexée et nonkey n'est pas indexée :

SELECT * FROM t1 WHERE
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR
(key1 < 'bar' AND nonkey = 4) OR
(key1 < 'uux' AND key1 > 'z');

Le processus d'extraction de la clé key1 est la suivante.

1. Début avec la clause WHERE originale :

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR
(key1 < 'bar' AND nonkey = 4) OR
(key1 < 'uux' AND key1 > 'z')

2. Suppression de nonkey = 4 et key1 LIKE '%b', car elles ne peuvent pas être utilisées pour des conditions d'intervalle. La bonne méthode pour les supprimer est de les remplacer par une valeur TRUE, pour qu'elles n'ignorent aucune ligne lors de la recherche. Cela donne :

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR
(key1 < 'bar' AND TRUE) OR
(key1 < 'uux' AND key1 > 'z')

3. Suppression des conditions qui sont toujours vraies ou fausses :

- (key1 LIKE 'abcde%' OR TRUE) est toujours vraie

- (key1 < 'uux' AND key1 > 'z') est toujours fausse

Remplacement de ces conditions avec des constantes, nous obtenons :

(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)

Suppression des constantes TRUE et FALSE inutiles, nous obtenons :

(key1 < 'abc') OR (key1 < 'bar')

4. Combinaison des intervalles communs conduit à une seule condition finale, à utiliser pour l'intervalle :

(key1 < 'bar')

En général (et tel que démontré dans notre exemple), les conditions utilisées pour une condition d'intervalle sont moins restrictives que la clause WHERE. MySQL va compléter la recherche par des filtres appliqués aux lignes trouvées pour supprimer celles qui ne satisfont pas les clauses WHERE.

L'algorithme d'extraction d'intervalles peut gérer des conditions AND/OR de profondeur arbitraire, et son résultat ne dépend pas de l'ordre des conditions dans la clause WHERE.

7-2-5-2 - Méthode d'accès par intervalle pour les index multicolonnes

Les conditions d'intervalle sur un index à plusieurs parties sont une extension de la version pour index monocolonne. Une condition d'intervalle pour un index multicolonne restreint les lignes à un ou plusieurs intervalles dans l'index. Les intervalles sont définis comme un jeu d'index, en utilisant l'ordre de l'index existant.

Par exemple, considérez l'index multicolonne suivant, défini par key1(key_part1, key_part2, key_part3) et leur ordre :

key_part1  key_part2  key_part3
NULL       1          'abc'
NULL       1          'xyz'
NULL       2          'foo'
1         1          'abc'
1         1          'xyz'
1         2          'abc'
2         1          'aaa'

La condition key_part1 = 1 définit cet intervalle :

(1, -inf, -inf) <= (key_part1, key_part2, key_part3) < (1, +inf, +inf)

L'intervalle couvre les 4e, 5e et 6e lignes dans la table précédente, et peut être utilisé par la méthode d'accès par intervalle.

Par contraste, la condition key_part3 = 'abc' ne définit aucun intervalle et ne peut pas être utilisée par la méthode d'accès par intervalle.

La description suivante montre comment les conditions d'intervalle fonctionnent avec un index multicolonne.

- Pour les index HASH, chaque intervalle contient des valeurs identiques qui peuvent être utilisées. Cela signifie que l'intervalle peut produire des conditions d'intervalle uniquement pour les conditions suivantes :

key_part1 cmp const1
AND key_part2 cmp const2
AND ...
AND key_partN cmp constN;

Ici, const1, const2... sont constantes, cmp est un des opérateurs de comparaison =, <=> ou IS NULL et les conditions couvrent toutes les parties de l'index. C'est-à-dire qu'il y a N conditions, une pour chaque partie de l'index.

Voyez Section 7.2.5.1, « Méthode d'accès par intervalle pour les index multicolonnes » pour avoir la définition d'une constante dans ce contexte.

Par exemple, la condition suivante est une condition d'intervalle pour un index HASH :

key_part1 = 1 AND key_part2 IS NULL AND key_part3 = 'foo'

- Pour in index BTREE, un intervalle peut être utilisable pour des conditions AND combinées, où chaque condition compare une partie de la clé avec une valeur constante et un opérateur de comparaison =, <=>, IS NULL, >, <, >=, <=, !=, <>, BETWEEN ou LIKE 'pattern' (où 'pattern' ne commence pas par un joker). Un intervalle peut être utilisé tant qu'il est possible de déterminer une ligne qui vérifie la condition, ou deux intervalles si <> ou != est utilisé. Par exemple :

key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10

L'intervalle sera :

('foo', 10, 10)
< (key_part1, key_part2, key_part3)
< ('foo', +inf, +inf)

Il est possible que l'intervalle créé contienne plus de lignes que la condition initiale. Par exemple, l'intervalle précédent inclut la valeur ('foo', 11, 0), qui ne satisfait pas les conditions initiales.

- Si les conditions qui génèrent les conditions d'intervalle sont combinées avec OR, elles forment une condition qui couvre un jeu de lignes contenues dans l'union des intervalles. Si les conditions sont combinées avec AND, elles forment une condition qui couvre un jeu de lignes contenues dans l'intersection des intervalles. Par exemple, pour cette condition bâtie sur un index à 2 colonnes :

(key_part1 = 1 AND key_part2 < 2)
OR (key_part1 > 5)

Les intervalles seront :

(1, -inf) < (key_part1, key_part2) < (1, 2)
(5, -inf) < (key_part1, key_part2)

Dans cet exemple, l'intervalle de la première ligne utilise une partie de la clé pour l'opérande de gauche, et deux parties de clé pour l'opérande de droite. La colonne key_len dans le résultat de EXPLAIN indique la taille maximale du préfixe de clé utilisé.

Dans certains cas, key_len peut indiquer qu'une clé a été utilisée, mais ce n'est pas ce que vous attendiez. Par exemple, supposez que key_part1 et key_part2 soient NULL. Alors, la colonne key_len va afficher deux clés de tailles différentes pour les conditions suivantes :

key_part1 >= 1 AND key_part2 < 2

Mais en fait, les conditions seront converties en :

key_part1 >= 1 AND key_part2 IS NOT NULL

Section 7.2.5.1, « Méthode d'accès par intervalle pour les index multicolonnes » décrit comment les optimisations sont appliquées pour combiner ou éliminer les intervalles basés sur des index monocultures. Des étapes analogues sont effectuées pour les conditions sur des index multicolonnes.

7-2-6 - Optimisation de combinaison d'index

La méthode de combinaison d'index (Index Merge, index_merge) est utilisée pour lire des lignes avec plusieurs scans ref, ref_or_null et range et les combiner en un seul résultat. Cette méthode est employée lorsque les conditions sur la table sont un groupe de conditions disjointes pour lesquelles ref, ref_or_null, ou range peuvent être utilisées avec différentes clés.

Ce type d'optimisation « join » est nouveau en MySQL 5.0.0, et représente un changement significatif dans le comportement de MySQL avec les index, car l'ancienne règle était que le serveur n'utilisait qu'un seul index au plus pour chaque table référencée.

Dans le résultat de EXPLAIN, cette méthode apparaît sous le nom de index_merge dans la colonne de type type. Dans ce cas, la colonne key contient la liste des index utilisés, et key_len contient la liste des tailles maximales de clé pour chaque index.

Exemples :

SELECT * FROM tbl_name WHERE key_part1 = 10 OR key_part2 = 20;

SELECT * FROM tbl_name
WHERE (key_part1 = 10 OR key_part2 = 20) AND non_key_part=30;

SELECT * FROM t1, t2
WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')
AND t2.key1=t1.some_col;

SELECT * FROM t1, t2
WHERE t1.key1=1
AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);

La méthode de combinaison d'index a différentes méthodes d'accès aux index, telles que présentées dans le champ Extra du résultat de la commande EXPLAIN :

- intersection ;

- union ;

- sort-union.

Les sections suivantes décrivent ces méthodes avec plus de détails.

Note : l'algorithme d'optimisation des combinaisons d'index a les limitations suivantes.

- Si un scan d'intervalle est possible avec une clé, la combinaison d'index sera omise. Par exemple :

SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;

Pour cette requête, deux solutions sont possibles :

1. Une combinaison d'index avec la condition (goodkey1 < 10 OR goodkey2 < 20) ;

2. Un scan d'intervalle avec la condition badkey < 30.

Mais ici, l'optimiseur ne considérera que la seconde méthode. Si ce n'est pas ce que vous souhaitez, vous pouvez forcer l'optimiseur à utiliser index_merge en utilisant les clauses IGNORE INDEX et FORCE INDEX. Les requêtes suivantes seront exécutées avec une combinaison d'index :

SELECT * FROM t1 FORCE INDEX(goodkey1,goodkey2)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;

SELECT * FROM t1 IGNORE INDEX(badkey)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;

- Si votre requête a une clause WHERE complexe avec des conditions AND/OR imbriquées, et que MySQL n'a pas identifié la méthode optimale, essayez de répartir les conditions en utilisant les lois d'identité :

(x AND y) OR z = (x OR z) AND (y OR z)
(x OR y) AND z = (x AND z) OR (y AND z)

Le choix entre les méthodes de index_merge est basé sur le calcul de coûts.

7-2-6-1 - Algorithme d'accès aux intersections de combinaisons d'index

Cet algorithme peut être employé lorsque la clause WHERE a été convertie en plusieurs conditions d'intervalle sur différentes clés combinées avec AND, et que chaque condition vérifie :

- sous cette forme, où l'index a exactement N parties (c'est-à-dire que toutes les parties de l'index sont couvertes) :

key_part1=const1 AND key_part2=const2 ... AND key_partN=constN

- toute condition d'intervalle sur une clé primaire de table InnoDB ou BDB.

Voici quelques exemples :

SELECT * FROM innodb_table WHERE primary_key < 10 AND key_col1=20;

SELECT * FROM tbl_name
WHERE (key1_part1=1 AND key1_part2=2) AND key2=2;

L'algorithme d'intersection effectue des scans simultanés sur tous les index utilisés, et produit la séquence de lignes qu'il reçoit des analyses d'index combinés.

Si toutes les colonnes utilisées dans la requête sont couvertes par les index utilisés, toutes les lignes de la table ne seront pas lues : EXPLAIN indiquera Using index dans la colonne Extra. Voici un exemple de cette requête :

SELECT COUNT(*) FROM t1 WHERE key1=1 AND key2=1;

Si les index utilisés ne couvrent pas toutes les colonnes, les lignes complètes seront lues uniquement lorsque les conditions d'intervalle seront toutes satisfaites.

Si une des conditions est une condition sur une clé primaire d'une table InnoDB ou BDB, elle n'est pas utilisée pour lire les lignes, mais pour filtrer les lignes lues par les autres conditions.

7-2-6-2 - Algorithme d'accès aux unions de combinaison d'index

Le critère applicable pour cet algorithme est similaire à ceux de la méthode des intersections de combinaisons d'index. L'algorithme peut être employé lorsque la clause WHERE a été convertie en plusieurs conditions d'intervalle combinées avec l'opérateur OR, et que chaque condition est une des suivantes.

- Sous cette forme, où l'index a exactement N parties, c'est-à-dire que toutes les parties de l'index sont couvertes :

key_part1=const1 AND key_part2=const2 ... AND key_partN=constN

- Toute condition d'intervalle sur une clé primaire d'une table InnoDB ou BDB.

- Une condition pour laquelle l'algorithme d'intersection de combinaisons d'index est applicable.

Voici quelques exemples :

SELECT * FROM t1 WHERE key1=1 OR key2=2 OR key3=3;

SELECT * FROM innodb_table WHERE (key1=1 AND key2=2) OR
(key3='foo' AND key4='bar') AND key5=5;

7-2-6-3 - Algorithme d'accès aux unions triées de combinaison d'index

Cet algorithme d'accès est employé lorsque la clause WHERE a été convertie en plusieurs conditions d'intervalle par l'opérateur OR, mais que l'algorithme d'union de combinaison d'index n'est pas utilisable.

Voici quelques exemples :

SELECT * FROM tbl_name WHERE key_col1 < 10 OR key_col2 < 20;

SELECT * FROM tbl_name
WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col=30;

La différence entre l'algorithme d'union triée et l'algorithme d'union est que l'algorithme d'union triée doit commencer par lire les identifiants de toutes les lignes, et les trier avant de retourner un résultat.

7-2-7 - Comment MySQL optimise IS NULL

MySQL peut exploiter certaines optimisations sur les conditions column IS NULL, comme il peut le faire avec les conditions column = constant_value. Par exemple, MySQL peut utiliser des index et des intervalles pour rechercher des valeurs NULL avecIS NULL.

SELECT * FROM table_name WHERE key_col IS NULL;

SELECT * FROM table_name WHERE key_col <=> NULL;

SELECT * FROM table_name WHERE key_col=# OR key_col=# OR key_col IS NULL

Si vous utilisez column_name IS NULL sur une colonne NOT NULL dans une clause WHERE, sur une table qui ne fait pas partie d'une jointure OUTER JOIN, l'expression sera optimisée immédiatement.

MySQL 4.1.1 peut aussi optimiser des combinaisons column = expr AND column IS NULL, une forme qui est fréquente avec les sous-requêtes. EXPLAIN vous indiquera ref_or_null lorsque cette optimisation est utilisée.

Cette optimisation peut gérer une condition IS NULL avec toute partie de clé.

Quelques exemples de requêtes qui sont optimisées (en supposant qu'il existe une clé sur t2 (a,b) :

SELECT * FROM t1 WHERE t1.a=expr OR t1.a IS NULL;

SELECT * FROM t1,t2 WHERE t1.a=t2.a OR t2.a IS NULL;

SELECT * FROM t1,t2 WHERE (t1.a=t2.a OR t2.a IS NULL) AND t2.b=t1.b;

SELECT * FROM t1,t2 WHERE t1.a=t2.a AND (t2.b=t1.b OR t2.b IS NULL);

SELECT * FROM t1,t2 WHERE (t1.a=t2.a AND t2.a IS NULL AND ...) OR (t1.a=t2.a AND t2.a IS NULL AND ...);

ref_or_null fonctionne en lisant la clé de référence, et après ça, fait une recherche différente pour les valeurs NULL.

Notez que l'optimisation ne peut gérer qu'un seul niveau de conditions IS NULL.

SELECT * FROM t1,t2 where (t1.a=t2.a AND t2.a IS NULL) OR (t1.b=t2.b AND t2.b IS NULL);

Dans le cas ci-dessus, MySQL va uniquement utiliser une recherche de clé pour la partie (t1.a=t2.a AND t2.a IS NULL) et ne sera pas capable d'utiliser la clé pour b.

7-2-8 - Comment MySQL optimise DISTINCT

DISTINCT combiné avec un ORDER BY aura dans la plupart des cas recours à une table temporaire.

Notez que comme DISTINCT peut utiliser GROUP BY, apprenez comment MySQL fonctionne avec les champs de ORDER BY et HAVING qui ne sont pas dans la liste des colonnes sélectionnées. Voir Section 12.9.3, « GROUP BY avec les champs cachés ».

Quand vous combinerez LIMIT # avec DISTINCT, MySQL stoppera dès qu'il trouvera # lignes uniques.

Si vous n'utilisez pas de colonnes de toutes les tables utilisées, MySQL arrête de scanner la table non utilisée dès qu'il trouve la première correspondance.

SELECT DISTINCT t1.a FROM t1,t2 where t1.a=t2.a;

Dans ce cas, en supposant que t1 est utilisée avant t2 (vérifiez avec EXPLAIN), MySQL arrêtera de lire à partir de t2 (pour cette ligne particulière de t1) lorsque la première ligne de t2 est trouvée.

7-2-9 - Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN

A LEFT JOIN B est implémenté dans MySQL comme suit :

- La table B est censée être dépendante de la table A et de toutes les tables dont dépend A.

- La table A est censée être dépendante de toutes les tables (à part B) qui sont utilisées dans la condition du LEFT JOIN.

- Toutes les conditions du LEFT JOIN sont transmises à la clause WHERE.

- Toutes les optimisations standard de jointures sont effectuées, à l'exception qu'une table est toujours lue après celles dont elle dépend. S'il y a une dépendance circulaire, MySQL retournera une erreur.

- Toutes les optimisations standard de WHERE sont effectuées.

- S'il y a une ligne dans A qui répond à la clause WHERE, mais qu'il n'y avait aucune ligne dans B qui répondait à la condition du LEFT JOIN, alors une ligne supplémentaire de B est générée avec toutes les colonnes mises à NULL.

- Si vous utilisez LEFT JOIN pour trouver les enregistrements qui n'existent pas dans d'autres tables et que vous effectuez le test suivant : nom_colonne IS NULL dans la partie WHERE, où nom_colonne est une colonne qui est déclarée en tant que NOT NULL, alors MySQL arrêtera de chercher d'autres lignes (pour une combinaison de clés particulière) après avoir trouvé une ligne qui répond à la condition du LEFT JOIN.

RIGHT JOIN est implémenté de manière analogue à LEFT JOIN.

L'ordre de lecture de tables forcé par LEFT JOIN et STRAIGHT JOIN aidera l'optimiseur de jointures (qui calcule l'ordre dans lequel les tables doivent être jointes) à faire son travail plus rapidement, puisqu'il y aura moins de permutations de tables à vérifier.

Notez que ce qui précède signifie que si vous faites une requête de la sorte :

SELECT *
FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.key;

Un palliatif est de changer la requête en :

SELECT *
FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.key;

Depuis la version 4.0.14, MySQL effectue l'optimisation LEFT JOIN suivante : si la condition WHERE est toujours fausse pour la ligne NULL générée, la jointure LEFT JOIN est transformée en jointure normale.

Par exemple, dans la requête suivante, la clause WHERE sera fausse si t2.column est NULL : il est donc valide de convertir la jointure en une jointure normale.

SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;

Par conséquent, il est possible de convertir la requête en jointure normale :

SELECT * FROM t1,t2 WHERE t2.column2=5 AND t1.column1=t2.column1;

Cela peut se faire plus rapidement, car MySQL peut maintenant utiliser la table t2 avant la table t1 si les relations sont plus favorables. Pour forcer l'utilisation spécifique d'un ordre de table, utilisez STRAIGHT JOIN.

7-2-10 - Comment MySQL optimise ORDER BY

Dans certains cas, MySQL peut utiliser un index pour répondre à une requête ORDER BY ou GROUP BY sans faire aucun tri.

L'index peut être utilisé même si le ORDER BY ne correspond pas exactement à l'index, tant que toutes les parties inutilisées de l'index et les colonnes du ORDER BY sont constantes dans la clause WHERE. Les requêtes suivantes utilisent l'index pour répondre aux parties ORDER BY / GROUP BY :

SELECT * FROM t1 ORDER BY partie_clef1,partie_clef2,...
SELECT * FROM t1 WHERE partie_clef1=constante ORDER BY partie_clef2
SELECT * FROM t1 WHERE partie_clef1=constante GROUP BY partie_clef2
SELECT * FROM t1 ORDER BY partie_clef1 DESC,partie_clef2 DESC
SELECT * FROM t1 WHERE partie_clef1=1 ORDER BY partie_clef1 DESC,partie_clef2 DESC

Quelques cas où MySQL ne peut pas utiliser les index pour répondre à ORDER BY (notez que MySQL utilisera quand même les index pour trouver les lignes qui correspondent à la clause WHERE).

- Vous effectuez un ORDER BY sur des clés différentes :

SELECT * FROM t1 ORDER BY key1, key2;

- Vous effectuez un ORDER BY en utilisant des parties de clé non consécutives.

SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;

- Vous mélangez ASC et DESC.

SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;

- La clé utilisée pour extraire les résultats n'est pas la même que celle utilisée lors du groupement ORDER BY :

SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

- Vous faites une jointure entre plusieurs tables et les colonnes sur lesquelles vous faites un ORDER BY ne font pas toutes partie de la première table non const qui est utilisée pour récupérer les lignes (c'est la première table dans l'affichage d'EXPLAIN qui n'utilise pas une méthode de récupération sur une ligne constante).

- Vous avez plusieurs expressions ORDER BY et GROUP BY.

- L'index de table utilisé est un type d'index qui n'enregistre pas les lignes dans l'ordre. (comme le type d'index HASH dans les tables HEAP).

Dans les cas où MySQL doit trier les résultats, il utilisera l'algorithme suivant :

1. Lit toutes les lignes en fonction d'un index ou par scan de la table. Les lignes qui ne vérifient pas la condition WHERE sont ignorées ;

2. Stocke les valeurs des clés de tri dans un buffer. La taille du buffer est la valeur de la variable système sort_buffer_size ;

3. Lorsque le buffer se remplit, fait un tri rapide et stocke le résultat dans un fichier temporaire. Sauve le pointeur dans un bloc trié. Si toutes les lignes tiennent dans le buffer de tri, aucun fichier temporaire n'est créé ;

4. Répète les étapes précédentes jusqu'à ce que toutes les lignes aient été lues ;

5. Fait une combinaison multiple jusqu'à MERGEBUFF (7) régions en un bloc, dans un autre fichier temporaire. Répète l'opération jusqu'à ce que le premier fichier soit dans le second ;

6. Répète la suite jusqu'à ce qu'il y ait moins de MERGEBUFF2 (15) blocs libres ;

7. Dans la dernière combinaison multiple, seul le pointeur de ligne (la dernière partie de la clé de tri) est écrit dans le fichier de résultat ;

8. Lit les lignes triées en utilisant les pointeurs de lignes du fichier de résultat. Pour optimiser cela, on lit un gros bloc de pointeurs, on les trie, et on les utilise pour lire les lignes en ordre dans un buffer. La taille du buffer est la valeur de la variable système read_rnd_buffer_size. Le code de cette étape est dans le fichier source sql/records.cc.

Vous pouvez vérifier avec EXPLAIN SELECT ... ORDER BY si MySQL peut utiliser des index pour répondre à cette requête. Si vous obtenez un Using filesort dans la colonne extra, c'est que MySQL ne peut utiliser d'index pour résoudre cet ORDER BY. Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) ».

Si vous voulez plus de rapidité avec les ORDER BY, vous devez d'abord voir si vous pouvez faire en sorte que MySQL utilise des index au lieu de passer par des phases de tri en plus. Si cela se révèle impossible, vous pouvez :

- augmenter la taille de la variable sort_buffer ;

- augmenter la taille de la variable record_rnd_buffer ;

- changer tmpdir pour qu'il pointe vers un disque dédié avec beaucoup d'espace libre. Si vous utilisez MySQL version 4.1 ou plus récent, vous pouvez répartir la charge entre plusieurs disques physiques en donnant à l'option tmpdir une liste de chemins, séparés par des deux-points (':') ou des points-virgules ';' sous Windows). Ils seront utilisés circulairement. Note : ces chemins doivent aboutir à différents disques physiques, et non pas différentes partitions du même disque.

Par défaut, MySQL trie les requêtes GROUP BY x,y[,...] comme si vous aviez spécifié l'ordre ORDER BY x,y[,...]. Si vous ajoutez une clause ORDER BY explicite, MySQL l'optimise aussi sans perte de vitesse, même si un tri a lieu. Si la requête inclut une clause GROUP BY, mais que vous voulez éviter le surcoût du tri, vous pouvez supprimer le tri en spécifiant ORDER BY NULL :

INSERT INTO foo SELECT a,COUNT(*) FROM bar GROUP BY a ORDER BY NULL;

7-2-11 - Comment MySQL optimise les clauses GROUP BY

La méthode la plus générale pour satisfaire une clause GROUP BY est de scanner toute la table et de créer une table temporaire où toutes les lignes de chaque groupe sont rangées consécutivement, puis d'utiliser cette table temporaire pour trouver les groupes, et leur appliquer les fonctions d'agrégation s'il y en a. Dans certains cas, MySQL est capable de faire encore mieux, et d'éviter la création de la table temporaire grâce aux index.

La plus importante condition à l'utilisation des index pour GROUP BY est que toutes les colonnes du GROUP BY soient dans le même index, et que l'index stocke les clés dans le même ordre (par exemple, un B-Tree et non pas un HASH). L'utilisation de cette technique dépend aussi des parties de l'index qui sont utilisées dans la requête, les conditions posées sur ces index, et les différentes fonctions d'agrégation.

Il y a deux méthodes pour exécuter une requête GROUP BY via un accès aux index, tel que présenté dans les sections suivantes. Dans la première méthode, les opérations de regroupement sont appliquées ensemble avec les prédicats d'intervalle. La seconde méthode commence par faire une analyse d'intervalle, puis regroupe les lignes trouvées.

7-2-11-1 - Scan restreint d'index

Le plus efficace est lorsque l'index sert à lire directement un groupe de champs. Avec cette méthode d'accès, MySQL exploite la propriété de certains types d'index comme les B-Tree, pour lesquels les clés sont triées. Cette propriété permet la recherche de groupe dans un index en omettant d'autres clés pour satisfaire toutes les conditions de la clause WHERE. Comme cette méthode d'accès ne prend en compte qu'une fraction de toutes les clés d'un index, elle est appelée « scan restreint d'index », ou loose index scan. Lorsqu'il n'y a pas de clause WHERE, un scan restreint va lire autant de clés que de groupes, ce qui peut être un nombre inférieur au nombre de clés. Si la clause WHERE contient des prédicats d'intervalle (indiqués dans Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) », dans la colonne range), un scan restreint d'index analysera la première clé de chaque groupe qui satisfait les conditions d'intervalle, et lira ainsi le minimum possible de clés. Cela est rendu possible dans les conditions suivantes.

- La requête utilise une seule table.

- La clause GROUP BY inclut les premières parties consécutives de l'index, et si la requête utilise une clause DISTINCT à la place d'une clause GROUP BY, tous les attributs distincts se rapportent au début de l'index.

- Les seules fonctions d'agrégation utilisées sont MIN() et MAX(), et toutes font référence à la même colonne.

- Toutes les autres parties de l'index de GROUP BY doivent être des constantes (c'est-à-dire qu'elles doivent être référencées avec des constantes), hormis pour les arguments des fonctions MIN() et MAX().

Le résultat de EXPLAIN pour ces requêtes affiche la valeur Using index for group-by dans la colonne Extra.

Les requêtes suivantes sont autant d'exemples qui sont éligibles, en supposant qu'il existe un index idx(c1, c2, c3) sur la table t1(c1,c2,c3,c4):

SELECT c1, c2 FROM t1 GROUP BY c1, c2;
SELECT DISTINCT(c1, c2) FROM t1;
SELECT c1, MIN(c2) FROM t1 GROUP BY c1;
SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2;
SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2;

Les requêtes suivantes ne peuvent pas être exécutées avec les méthodes de sélection rapide, pour les raisons citées.

- Il y a d'autres fonctions d'agrégation que MIN() ou MAX() :

SELECT c1, SUM(c2) FROM t1 GROUP BY c1;

- Les champs de GROUP BY ne font pas référence au début de l'index :

SELECT c1,c2 FROM t1 GROUP BY c2, c3;

- La requête fait référence à une partie de clé qui est placée après la partie GROUP BY, et pour lesquelles l'égalité ne se fait pas avec une constante :

SELECT c1,c3 FROM t1 GROUP BY c1, c2;

7-2-11-2 - Scan d'index systématique

Un scan d'index systématique peut être un scan d'index total, un scan d'intervalle, suivant les conditions.

Lorsque les conditions pour faire un scan d'index restreint ne sont pas là, il est toujours possible d'éviter la constitution de tables temporaires pour les requêtes GROUP BY. S'il y a des conditions d'intervalle dans la clause WHERE, cette méthode ne va lire que les clés qui satisfont les conditions. Sinon, elle appliquera un scan d'index. Comme cette méthode lit toutes les clés de chaque intervalle défini par WHERE, ou scanne tout l'index s'il n'y a pas de condition d'intervalle, nous l'appelons un « scan d'index systématique ». Notez qu'avec un scan d'index systématique, les opérations de regroupement sont faites après la lecture des clés qui satisfont les conditions.

Pour que cette méthode fonctionne, il suffit que toutes les colonnes d'une requête qui font référence à une partie de clé avant ou entre les conditions de la clause GROUP BY, soient des conditions constantes. Ces constantes remplissent les « trous » dans les clés de recherche, pour qu'il soit possible de former des préfixes complets d'index. Ensuite, ces préfixes seront utilisés pour les recherches. Si vous avez besoin de tri avec GROUP BY, et qu'il est possible de former des clés de recherche avec des préfixes d'index, MySQL pourra aussi éviter le tri, car la recherche avec préfixe dans un index ordonné lit les clés dans l'ordre.

Les requêtes suivantes ne fonctionneront pas avec la première méthode, mais fonctionneront toujours avec la deuxième méthode d'accès aux index (en supposant que nous avons l'index idx sur la table t1).

- Il y a un « trou » dans le GROUP BY, mais il est couvert par la condition (c2 = 'a').

SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;

- GROUP BY ne commence pas par la première clé, mais il y a une condition qui fournit une constante pour cette partie de clé :

SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;

7-2-12 - Comment MySQL optimise LIMIT

Dans certains cas, MySQL va gérer la requête différemment avec la clause LIMIT #, si la clause HAVING n'est pas utilisée.

- Si vous ne sélectionnez que quelques lignes avec LIMIT, MySQL va utiliser les index dans certains cas, où il aurait préféré utiliser un scan de table complet.

- Si vous utilisez LIMIT # avec la clause ORDER BY, MySQL va arrêter de trier dès qu'il a trouvé la première # au lieu de trier toute la table.

- Lorsque vous combinez LIMIT # avec DISTINCT, MySQL va s'arrêter dès qu'il a trouvé # lignes distinctes.

- Dans certains cas, la clause GROUP BY peut être appliquée en lisant les clés dans l'ordre (ou en faisant un tri sur la clé), puis en calculant un sommaire, jusqu'à ce que la clé soit modifiée. Dans ce cas, LIMIT # ne va pas appliquer les éléments non nécessaires de la clause GROUP BY.

- Aussitôt que MySQL a envoyé les premières # lignes au client, il annule le reste de la requête (si vous n'utilisez pas la fonction SQL_CALC_FOUND_ROWS).

- LIMIT 0 va toujours retourner rapidement un résultat vide. C'est pratique pour vérifier une requête et lire les types de colonnes du résultat, sans exécuter réellement la requête.

- Lorsque le serveur utilise des tables temporaires pour résoudre les requêtes, la clause LIMIT # est utilisée pour calculer l'espace nécessaire.

7-2-13 - Comment éviter les analyses de tables

EXPLAIN affiche la valeur ALL dans la colonne type lorsque MySQL utilise un scan de table pour résoudre une requête. Cela arrive lorsque :

- la table est si petite qu'il est plus rapide d'analyser la table que d'utiliser les index. C'est un cas courant pour les tables de moins de 10 lignes, et de taille de ligne faible ;

- il n'y a pas de restriction exploitable sur les conditions ON et WHERE, avec les colonnes indexées ;

- vous comparez des colonnes indexées avec des constantes, et MySQL a calculé, en se basant sur l'arbre d'index, que les constantes couvrent une trop grande partie de la table : un scan devrait être plus rapide. Voir Section 7.2.4, « Comment MySQL optimise les clauses WHERE » ;

- vous utilisez une clé avec une cardinalité faible (c'est-à-dire, beaucoup de lignes sont trouvées). MySQL va alors supposer que l'utilisation de l'index va lui imposer beaucoup de recherches, et qu'un scan de table sera plus rapide.

Ce que vous pouvez faire pour éviter les scans de grosses tables :

- utilisez ANALYZE TABLE sur les tables pour optimiser la distribution des clés. Voir Section 13.5.2.1, « Syntaxe de ANALYZE TABLE » ;

- utilisez FORCE INDEX sur les tables, pour dire à MYSQL que les scans de tables sont trop coûteux, comparés à l'utilisation de l'index. Voir Section 13.1.7, « Syntaxe de SELECT ».

SELECT * FROM t1,t2 force index(index_for_column) WHERE t1.column=t2.column;

- lancez mysqld avec --max-seeks-for-key=1000 ou faites SET MAX_SEEKS_FOR_KEY=1000 pour dire à l'optimiseur que les scans sans index ne généreront pas plus de 1000 recherches dans les index. Voir Section 5.2.3, « Variables serveur système ».

7-2-14 - Vitesse des requêtes INSERT

Le temps d'insertion d'une ligne est constitué comme ceci :

- connexion : (3) ;

- envoi au serveur : (2) ;

- analyse de la requête : (2) ;

- insertion de la ligne : (1 x taille de la ligne) ;

- insertion des index  : (1 x nombre d'index) ;

- fermeture : (1)

Où les nombres représentent une partie proportionnelle du temps total. Le calcul ne prend pas en compte les coûts d'administration initiaux de l'ouverture des tables (qui est fait une fois pour chaque requête simultanée).

La taille de la table ralentit les opérations d'insertion des index par un facteur de log N (B-trees).

Quelques méthodes pour accélérer les insertions.

- Si vous insérez plusieurs lignes depuis le même client, en même temps, utilisez les valeurs multiples de la commande INSERT. C'est bien plus rapide (et parfois beaucoup plus rapide) que d'utiliser des commandes INSERT distinctes. Si vous ajoutez des données dans une table non vide, vous pouvez ajuster la variable bulk_insert_buffer_size pour l'accélérer encore plus. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ».

- Si vous insérez de nombreuses lignes depuis différents clients, vous pouvez accélérer les insertions en utilisant la commande INSERT DELAYED. Voir Section 13.1.4, « Syntaxe de INSERT ».

- Avec les tables MyISAM, vous pouvez insérer des lignes en même temps que vous utilisez des commandes SELECT, du moment qu'il n'y a pas d'effacement de ligne dans la table.

- Lorsque vous chargez une table depuis un fichier texte, utilisez la commande LOAD DATA INFILE. Elle est généralement 20 fois plus rapide que l'équivalent en commandes INSERT. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

- Il est possible, avec un peu de travail supplémentaire, d'accélérer encore la vitesse des commandes LOAD DATA INFILE. Utilisez la procédure standard :

1. Créez optionnellement une table avec CREATE TABLE. Par exemple, en utilisant mysql ou Perl DBI ;

2. Exécutez une commande FLUSH TABLES ou la commande en ligne shell mysqladmin flush-tables ;

3. Utilisez myisamchk --keys-used=0 -rq /path/to/db/tbl_name. Cela va supprimer l'utilisation des index dans la table ;

4. Insérez vos données dans la table, avec LOAD DATA INFILE. Les index ne seront pas modifiés, et donc, très rapides ;

5. Si vous allez uniquement lire la table dans le futur, utilisez myisampack pour la réduire de taille. Voir Section 14.1.3.3, « Caractéristiques des tables compressées » ;

6. Recréez les index avec myisamchk -r -q /path/to/db/tbl_name. Cette commande va créer l'arbre d'index en mémoire, avant de l'écrire sur le disque, ce qui est bien plus rapide, car il n'y a que peu d'accès disques. L'arbre final sera aussi parfaitement équilibré ;

7. Exécutez une commande FLUSH TABLES ou utilisez la commande en ligne shell mysqladmin flush-tables.

Notez que la commande LOAD DATA INFILE fait aussi les optimisations ci-dessus, si vous faites les insertions dans une table vide. La différence principale avec la procédure ci-dessus est que vous pouvez laisser myisamchk allouer plus de mémoire temporaire pour la création d'index, que vous ne pourriez le faire pour chaque recréation.

Depuis MySQL 4.0 vous pouvez aussi utiliser ALTER TABLE tbl_name DISABLE KEYS au lieu de myisamchk --keys-used=0 -rq /path/to/db/tbl_name et ALTER TABLE tbl_name ENABLE KEYS au lieu de myisamchk -r -q /path/to/db/tbl_name. De cette façon, vous pouvez aussi éviter l'étape FLUSH TABLES.

- Vous pouvez accélérer les insertions qui sont faites avec plusieurs requêtes en verrouillant vos tables :

mysql> LOCK TABLES a WRITE;
mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
mysql> INSERT INTO a VALUES (8,26),(6,29);
mysql> UNLOCK TABLES;

La principale différence de vitesse est que l'index de buffer est écrit sur le disque une fois, après toutes les insertions INSERT terminées. Normalement, il aurait dû y avoir de nombreuses écritures, une pour chaque commande INSERT. Le verrouillage n'est pas nécessaire si vous pouvez insérer toutes les lignes d'une seule commande.

Pour les tables transactionnelles, vous devriez utiliser BEGIN/COMMIT au lieu de LOCK TABLES pour accélérer les opérations.

Le verrouillage va aussi réduire le nombre total de tests de connexion, mais le temps d'attente maximum de certains threads va augmenter (car il va y avoir la queue pour les verrous). Par exemple :

thread 1 fait 1000 insertions
thread 2, 3, et 4 font 1 insertion
thread 5 fait 1000 insertions

Si vous ne voulez pas utiliser le verrouillage, les threads 2, 3 et 4 auront fini avant les 1 et 5. Si vous utilisez le verrouillage, 2, 3 et 4 ne finiront probablement pas avant 1 ou 5, mais la durée globale de l'opération sera 40 % plus courte.

Comme les commandes INSERT, UPDATE et DELETE sont très rapides avec MySQL, vous obtiendrez de meilleures performances générales en ajoutant des verrous autour de toutes vos opérations de 5 insertions ou modifications simultanées. Si vous faites de très nombreuses insertions dans une ligne, vous pouvez utiliser LOCK TABLES suivi de UNLOCK TABLES une fois de temps en temps (par exemple, toutes les 1000) pour permettre aux autres threads d'accéder à la table. Cela vous donnera quand même une bonne accélération.

Bien sûr, LOAD DATA INFILE reste bien plus rapide pour charger les données.

- Pour accélérer LOAD DATA INFILE et INSERT, agrandissez le buffer de clés. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

7-2-15 - Vitesses des commandes UPDATE

Les requêtes de modification sont optimisées comme les requêtes de SELECT avec le coût supplémentaire de l'écriture. La vitesse d'écriture dépend de la taille des données qui sont modifiées, et du nombre d'index que cela va impacter. Les index ne sont pas modifiés tant que la ligne n'est pas écrite. Les index qui ne sont pas modifiés ne seront pas réécrits.

De plus, une autre méthode pour obtenir des accélérations avec les modifications est de retarder les modifications, et d'en faire plusieurs d'un coup. Faire plusieurs modifications d'un coup est bien plus rapide que d'en faire une à chaque fois.

Notez que, avec le format de ligne dynamique, la modification d'une ligne peut déboucher sur la fragmentation de la ligne. Si vous le faites souvent, il est très important d'appliquer OPTIMIZE TABLE sur ces tables, pour les optimiser. Voir Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE ».

7-2-16 - Rapidité des requêtes DELETE

Si vous voulez effacer toutes les lignes d'une table, vous devez utiliser TRUNCATE TABLE nom_de_table. Voir Section 13.1.9, « Syntaxe de TRUNCATE ».

Le temps de suppression d'une ligne est exactement proportionnel au nombre d'index. Pour effacer les enregistrements plus rapidement, vous pouvez augmenter la taille du cache d'index. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

7-2-17 - Autres conseils d'optimisation

Quelques conseils en vrac pour accélérer le serveur.

- Utilisez les connexions persistantes à la base, pour éviter les coûts récurrents de connexion. Si vous ne pouvez pas utiliser de connexions persistantes, et que vous faites de nombreuses connexions à la base, essayez de modifier la valeur de la variable thread_cache_size. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

- Vérifiez toujours que vos requêtes utilisent vraiment les index que vous avez créés dans les tables. Avec MySQL, vous pouvez utiliser la commande EXPLAIN. See Explain: (manual) Explain.

- Essayez d'éviter les requêtes SELECT complexes sur les tables MyISAM qui sont souvent modifiées. Cela évitera des problèmes de verrouillage.

- Les nouvelles tables MyISAM peuvent insérer des lignes sans en effacer d'autres, tout en lisant dans cette table. Si c'est important pour vous, vous pouvez considérer d'autres méthodes où vous n'avez pas à effacer de lignes, ou bien utilisez OPTIMIZE TABLE après avoir effacé beaucoup de lignes.

- Utilisez ALTER TABLE ... ORDER BY expr1,expr2... si vous lisez les colonnes dans l'ordre expr1,expr2.... Avec cette option, après de grosses modifications dans la table, vous pourriez obtenir de meilleures performances.

- Dans certains cas, cela vaut la peine d'ajouter une colonne qui est une combinaison (« hashed ») des informations des autres colonnes. Si cette colonne est courte, et plutôt exempte de doublons, elle peut se révéler plus rapide qu'un gros index sur plusieurs colonnes. Avec MySQL, il est très facile d'utiliser une telle colonne :

SELECT * FROM tbl_name
WHERE hash_col=MD5(CONCAT(col1,col2))
AND col1='constant' AND col2='constant';

- Pour les tables qui sont souvent modifiées, vous devriez essayer d'éviter les colonnes VARCHAR et BLOB. Vous obtiendrez des lignes à format dynamique si vous utilisez ne serait-ce qu'une seule colonne VARCHAR ou BLOB. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- Normalement, cela ne sert à rien de séparer une table en différentes tables plus petites, juste parce que vos lignes deviennent grosses. Pour accéder à une ligne, le plus long est le temps d'accès aux premiers octets de la ligne. Après cela, les disques modernes vont lire très rapidement la ligne, et suffisamment pour la plupart des applications. Le seul cas où cela peut être important est si vous êtes capable de dégager une table à format de ligne fixe (voir ci-dessus), ou si vous avez besoin de scanner régulièrement la table, mais que vous n'avez pas besoin de toutes les colonnes. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- Si vous avez besoin de calculer souvent des expressions en fonction des informations placées dans de nombreuses lignes (comme compter des lignes), il est probablement plus efficace d'introduire une nouvelle table qui va mettre à jour ce compteur en temps réel. Une modification du type présenté ci-dessous est très rapide !

UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;

C'est très important lorsque vous utilisez les types de tables MyISAM et ISAM, qui ne disposent que d'un verrouillage de table (plusieurs lecteurs, un seul qui écrit). Cela va aussi améliorer les performances avec la plupart des bases, car le gestionnaire de verrouillage de ligne aura moins de tâches à faire.

- Si vous devez rassembler des statistiques issues de grosses tables de logs, utiliser les tables de sommaires plutôt que la table complète. Entretenir un sommaire est bien plus rapide que de régénérer des tables à partir des logs à chaque modification (suivant l'importance de vos informations), plutôt que de modifier l'application qui fonctionne.

- Si possible, essayez de marquer les rapports comme « direct » ou « statistique », où les données nécessaires pour les rapports statistiques ne sont générées qu'à partir de tables de sommaires, calculées depuis les données réelles.

- Utilisez les valeurs par défaut des colonnes. N'insérez des valeurs explicitement que lorsque la valeur diffère de la valeur par défaut. Cela réduit le temps d'analyse de MySQL, et améliore les insertions.

- Dans certains cas, il est pratique de compacter et stocker les données dans un BLOB. Dans ce cas, vous devez ajouter du code supplémentaire pour compacter et décompacter les données dans le BLOB, mais cela pourra vous faire économiser de nombreux accès. C'est pratique lorsque vous avez des données qui ne peuvent s'adapter facilement à une structure de base de données.

- Normalement, vous devriez essayer de garder vos données non redondantes (ce qui s'appelle la troisième forme normale dans les théories de bases de données), mais ne vous empêchez pas de dupliquer des données ou de créer des tables de sommaire, pour gagner de la vitesse.

- Les procédures stockées ou UDF (fonctions utilisateur) peuvent être une bonne façon de gagner en performance. Dans ce cas, vous devriez avoir une méthode pour appliquer les mêmes fonctions d'une autre manière, si votre base ne supporte les procédures stockées.

- Vous pouvez aussi gagner de la vitesse en utilisant des caches de requêtes dans vos applications, et en essayant de rassembler les nombreuses insertions ou modifications. Si votre base de données supporte le verrouillage de table (comme MySQL et Oracle), cela vous aidera à vous assurer que le cache d'index est vidé après chaque modification.

- Utilisez INSERT /*! DELAYED */ lorsque vous n'avez pas besoin d'être assuré que vos données sont écrites. Cela accélère les insertions, car de nombreuses lignes seront écrites en une seule fois.

- Utilisez INSERT /*! LOW_PRIORITY */ lorsque vous voulez que vos sélections soient prioritaires.

- Utilisez SELECT /*! HIGH_PRIORITY */ pour rendre les sélections prioritaires. C'est-à-dire, les sélections seront désormais faites même si un autre programme attend pour écrire.

- Utilisez la commande INSERT multiple pour insérer plusieurs lignes en une seule commande SQL (plusieurs serveurs SQL le supportent).

- Utilisez LOAD DATA INFILE pour charger de grande quantité de données dans une table. C'est généralement plus rapide que des insertions, et sera même encore plus rapide une fois que myisamchk sera intégré dans mysqld.

- Utilisez les colonnes AUTO_INCREMENT pour avoir des valeurs uniques.

- Utilisez OPTIMIZE TABLE une fois de temps en temps, pour éviter la fragmentation lors de l'utilisation de tables avec un format de ligne dynamique. Voir Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE ».

- Utilisez les tables de type HEAP pour accélérer les traitements au maximum. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- Avec un serveur web normal, les images doivent être stockées dans des fichiers. C'est-à-dire, ne stockez qu'une référence au fichier d'images dans la base. La raison principale à cela est qu'un serveur web est bien meilleur pour mettre en cache des fichiers que le contenu d'une base de données. Il est donc plus rapide si vous utilisez des fichiers.

- Utilisez des tables en mémoire pour les données non critiques, qui ont besoin d'être lues souvent (comme des informations sur la dernière bannière affichée pour les utilisateurs sans cookies).

- Les colonnes contenant des informations identiques dans différentes tables doivent être déclarées identiquement lors de la création des tables, et porter des noms identiques. Avant la version 3.23, vous pouviez ralentir les jointures.

Essayez de garder des noms simples (utilisez nom au lieu de nom_du_client dans la table de clients). Pour rendre vos noms de colonnes portables vers les autres serveurs SQL, vous devriez essayer de les garder plus petits que 18 caractères.

- Si vous avez vraiment besoin de très haute vitesse, vous devriez considérer les interfaces de bas niveau pour le stockage des données que les différents serveurs SQL supportent. Par exemple, en accédant directement aux tables MySQL MyISAM, vous pourriez obtenir un gain de vitesse de l'ordre de 2 à 5 fois, en comparaison avec l'interface SQL. Pour cela, les données doivent être sur le même serveur que l'application, et généralement, elles ne doivent être manipulées que par un seul programme à la fois (car le verrouillage externe de fichiers est très lent). Vous pouvez éliminer ces problèmes en créant des commandes MyISAM de bas niveau dans le serveur MySQL (cela peut se faire facilement pour améliorer les performances). Soyez très prudent dans la conception de votre interface, mais il est très facile de supporter ce type d'optimisation.

- Dans de nombreux cas, il est plus rapide d'accéder aux données depuis une base (en utilisant une connexion ouverte) que d'accéder à un fichier texte, car la base de données est plus compacte que le fichier texte (si vous utilisez des données numériques), et cela entraîne moins d'accès disques. Vous allez aussi économiser du code, car vous n'aurez pas à analyser le fichier texte pour repérer les limites de lignes.

- Vous pouvez aussi utiliser la réplication pour accélérer le serveur. Voir Chapitre 6, Réplication de MySQL.

- Déclarer une table avec DELAY_KEY_WRITE=1 va accélérer la mise à jour des index, car ils ne seront pas écrits sur le disque jusqu'à ce que le fichier de données soit refermé. L'inconvénient est que vous devez exécuter l'utilitaire myisamchk sur ces tables avant de lancer mysqld pour vous assurer que les index sont bien à jour, au cas où le processus aurait été interrompu avant d'enregistrer les données. Comme les informations d'index peuvent toujours être régénérées, vous ne perdrez pas de données avec DELAY_KEY_WRITE.

7-3 - Verrouillage de tables

7-3-1 - Méthodes de verrouillage

Actuellement, MySQL ne supporte que le verrouillage de table pour les tables ISAM/MyISAM et MEMORY (HEAP), le verrouillage de page pour les tables BDB et le verrouillage de ligne pour InnoDB.

Dans de nombreux cas, vous pouvez faire prévoir le type de verrouillage qui sera le plus efficace pour une application, mais il est très difficile de savoir si un type de verrou est meilleur que l'autre. Tout dépend de l'application, et des différents composants qui utilisent les verrous.

Pour décider si vous voulez utiliser un type de table avec verrouillage de ligne, vous devez commencer par étudier ce que votre application fait, et quel est le schéma d'utilisation des sélections et modifications. Par exemple, la plupart des applications Web font de nombreuses sélections, peu d'effacements, des modifications basées sur des clés, et des insertions dans des tables spécifiques. Le moteur de base MySQL MyISAM est très bien optimisé pour cette application.

Toutes les méthodes de verrouillage de MySQL sont exemptes de blocage, sauf pour les tables InnoDB et BDB. Ceci fonctionne en demandant tous les verrous d'un seul coup, au début de la requête, et en verrouillant les tables toujours dans le même ordre.

Les tables InnoDB obtiennent automatiquement leur verrou de ligne et les tables BDB leur verrou de page, durant le traitement de la requête SQL, et non pas au démarrage de la transaction.

La méthode de verrouillage des tables de MySQL en écriture (WRITE) fonctionne comme ceci :

- s'il n'y a pas de verrou sur la table, pose un verrou en écriture dessus ;

- sinon, soumet une requête de verrouillage dans la queue de verrous d'écriture.

La méthode de verrouillage des tables de MySQL en lecture (READ) fonctionne comme ceci :

- s'il n'y a pas de verrou sur la table, pose un verrou en écriture dessus ;

- sinon, soumet une requête de verrouillage dans la queue de verrou de lecture.

Lorsqu'un verrou est libéré, le verrou est donné aux threads de la queue de verrous en écriture, puis à ceux de la queue de verrous en lecture.

Cela signifie que si vous avez de nombreuses modifications dans une table, la commande SELECT va attendre qu'il n'y ait plus d'écriture avant de lire.

Depuis MySQL 3.23.33, vous pouvez analyser le comportement des verrous sur une table avec les variables de statut Table_locks_waited et Table_locks_immediate :

mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name         | Value   |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited    | 15324   |
+-----------------------+---------+

Depuis MySQL 3.23.7 (3.23.25 pour Windows), vous pouvez librement mélanger des commandes INSERT et SELECT sur une table MyISAM sans verrou, si les commandes INSERT sont sans conflit. C'est-à-dire, vous pouvez insérer des lignes dans une table MyISAM en même temps que d'autres clients lisent la même table. Aucun conflit ne survient si la table ne contient aucun bloc libre dans les données, et que les lignes sont insérées à la fin de la table. Les trous sont des lignes qui ont été effacées. S'il y a des trouvés, les insertions concurrentes sont réactivées automatiquement, lorsque les trous sont bouchés par de nouvelles données.

Pour contourner ce problème dans les cas où vous voulez faire de nombreux INSERT et SELECT sur la même table, vous pouvez insérer les lignes dans une table temporaire, et ne modifier la table réelle que de temps en temps, à partir de la table temporaire.

Ceci peut être fait comme ceci :

mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;

InnoDB utilise un verrouillage de ligne, et BDB utilise un verrouillage de page. Pour les moteurs InnoDB et BDB, un blocage de verrou est possible. Cela est dû au fait que InnoDB obtient automatiquement un verrou de ligne, et BDB pose le verrou de page durant le traitement SQL, et non pas au démarrage de la transaction.

Avantages du verrouillage de ligne

- Moins de conflits de lignes, lorsque les mêmes lignes sont utilisées par différents threads.

- Moins de modifications pour les annulations (ROLLBACK)

- Rend possible le verrouillage d'une ligne pour une longue durée.

Inconvénients du verrouillage de ligne

- Prend plus de mémoire que les verrous de page ou de table.

- Est plus lent que les verrous de page ou de table, lorsqu'il est utilisé sur une grande partie de la table, car il faut alors poser plusieurs verrous.

- Est vraiment bien pire que les autres verrous si vous utilisez souvent la requête GROUP BY sur la majeure partie des données, ou si vous avez à scanner toute la table.

- Avec des verrous de plus haut niveau, vous pouvez aussi supporter des verrous d'autres types, pour optimiser l'application, car le coût de l'administration est moindre que pour le verrouillage de ligne.

Les verrous de tables sont supérieurs aux verrous de page ou de ligne dans les cas suivants :

- les lectures ;

- les lectures et les modifications sur des clés strictes : c'est le cas si une modification ou un effacement de ligne peut être lu en une seule opération dans l'index.

UPDATE table_name SET column=value WHERE unique_key#
DELETE FROM table_name WHERE unique_key=#

- SELECT combiné avec INSERT (et quelques UPDATE et DELETE rares) ;

- de nombreux scans / GROUP BY sur toute la table, sans aucune écriture.

Autres possibilités de substitution au verrouillage de ligne ou de page

Le versionnage (comme celui que nous utilisons pour les insertions simultanées avec MySQL), où vous pouvez avoir un thread qui écrit et de nombreux autres qui lisent. Cela signifie que les bases ou tables supportent différentes vues des données, suivant le moment d'accès aux données. D'autres noms pour cette technique sont time travel, copy on write ou copy on demand.

La copy on demand (copie sur demande) est dans de nombreuses situations bien meilleure que le verrouillage de page ou de ligne. Le pire reste l'utilisation de mémoire, qui est bien plus forte qu'avec les verrous normaux.

Au lieu d'utiliser le verrouillage de ligne, vous pouvez utiliser des verrous au niveau de l'application (comme les get_lock/release_lock de MySQL). Cela ne fonctionne qu'avec les applications bien élevées.

7-3-2 - Problème de verrouillage de tables

MySQL utilise le verrouillage de table (au lieu du verrouillage de ligne ou de colonne) sur tous les types de tables, sauf InnoDB et BDB, pour obtenir un système de verrou à très haute vitesse.

Pour les tables InnoDB et BDB, MySQL n'utilise le verrouillage de table que si vous le demandez explicitement avec LOCK TABLES. Pour ces tables, nous vous recommandons de ne jamais utiliser la commande LOCK TABLES, car InnoDB utilise un verrouillage de ligne automatique, et BDB utilise un verrouillage de page, pour assurer l'isolation des transactions.

Pour les grandes tables, le verrouillage de table est meilleur que le verrouillage de ligne, pour la plupart des applications, mais il recèle quelques pièges.

Le verrouillage de table permet à de nombreux threads de lire dans la même table, mais si un thread désire écrire dans la table, il doit obtenir un verrou en écriture pour avoir un accès exclusif. Durant la modification, les autres threads qui voudront lire dans cette table, devront attendre.

Comme les modifications de tables sont considérées comme plus importantes que les lectures avec SELECT, toutes les commandes qui modifient la table ont priorité sur les lectures. Cela devrait vous assurer que les modifications ne sont pas retenues trop longtemps, à cause de nombreuses lectures sur une même table. Vous pouvez toutefois modifier cela avec l'option LOW_PRIORITY des commandes de modification, et l'option HIGH_PRIORITY de SELECT).

Depuis MySQL version 3.23.7, vous pouvez utiliser la variable max_write_lock_count pour forcer MySQL à laisser temporairement la place à toutes les commandes SELECT, après un certain nombre de modifications dans la table.

Le verrouillage de table est une mauvaise technique dans les situations suivantes :

- un client exécute une commande SELECT qui prend très longtemps ;

- un autre client exécute une commande UPDATE sur la table. Ce client va devoir attendre que la commande SELECT soit finie ;

- un autre client exécute une autre commande SELECT sur la même table. Comme UPDATE a la priorité sur SELECT, cette commande SELECT va attendre que UPDATE soit fini. Il va donc attendre que le premier SELECT soit fini.

Des solutions aux problèmes sont :

- essayez d'accélérer au maximum les commandes SELECT. Vous pourriez passer par une table de sommaire pour cela.

- démarrez mysqld avec l'option --low-priority-updates. Cela va donner aux commandes de modification une priorité plus faible que SELECT. Dans ce cas, c'est la commande SELECT du précédent scénario qui s'exécutera avant la commande INSERT ;

- vous pouvez donner à une commande spécifique INSERT, UPDATE ou DELETE, une priorité plus basse avec l'attribut LOW_PRIORITY ;

- démarrez mysqld avec une valeur faible pour max_write_lock_count afin de donner plus souvent la chance aux verrous READ la possibilité de lire des données, entre deux verrous WRITE ;

- vous pouvez spécifier que toutes les modifications d'un thread spécifique doivent être faites avec une priorité basse, en utilisant la commande SQL : SET LOW_PRIORITY_UPDATES=1. Voir Section 13.5.2.8, « Syntaxe de SET » ;

- vous pouvez spécifier qu'une requête particulière SELECT est très importante, en utilisant l'attribut HIGH_PRIORITY. Voir Section 13.1.7, « Syntaxe de SELECT » ;

- si vous avez des problèmes avec des INSERT combinés avec des SELECT, utilisez les tables MyISAM, car elles supportent les commandes SELECT et INSERT simultanées ;

- si vous voulez mélanger les commandes INSERT et SELECT, utilisez l'attribut DELAYED de la commande INSERT pour résoudre ce problème. Voir Section 13.1.4, « Syntaxe de INSERT » ;

- si vous avez des problèmes avec des combinaisons de SELECT et DELETE, l'option LIMIT de DELETE peut aider. Voir Section 13.1.1, « Syntaxe de DELETE » ;

- utiliser SQL_BUFFER_RESULT avec les commandes SELECT peut aider à réduire la durée des verrous. Voir Section 13.1.7, « Syntaxe de SELECT » ;

- vous pouvez changer le code de verrouillage dans le fichier mysys/thr_lock.c pour n'utiliser qu'une queue unique. Dans ce cas, les lectures et écritures auront la même priorité, ce qui peut aider certaines applications.

Voici quelques conseils avec le système de verrouillage de MySQL :

- les accès concurrents ne sont pas un problème si vous ne mélangez pas les sélections et les modifications de nombreuses lignes dans la même table ;

- vous pouvez utiliser LOCK TABLES pour accélérer les opérations : de nombreuses modifications dans un même verrou seront plus rapides. Répartir le contenu de la table en plusieurs tables peut aussi aider ;

- si vous rencontrez des problèmes de vitesse avec les verrous de table, vous devez être capables d'améliorer les performances en convertissant certaines tables en InnoDB ou BDB. Voir Chapitre 15, Le moteur de tables InnoDB. Voir Section 14.4, « Tables BDB ou BerkeleyDB ».

7-4 - Optimiser la structure de la base de données

7-4-1 - Conception

MySQL conserve les données et les index dans deux fichiers séparés. De nombreux (et en fait presque toutes) les autres bases mélangent les données et les index dans le même fichier. Nous pensons que le choix de MySQL est bien meilleur pour un grand nombre de systèmes modernes.

Une autre méthode de stockage des données est de conserver les informations de chaque colonne dans une zone séparée (par exemple SDBM et Focus). Cela va réduire les performances qui accèdent à plus d'une colonne. Comme cela dégénère vite lorsque plus d'une colonne est utilisée, nous pensons que ce modèle n'est pas bon pour une base de données généraliste.

Les cas les plus courants sont que les index et les données sont stockés ensemble (comme Oracle/Sybase). Dans ce cas, vous aurez aussi les informations de lignes dans la page finale de l'index. L'intérêt d'une telle organisation est que, dans de nombreuses situations, dépendant du cache d'index, vous économisez des lectures disques. Les problèmes de cette organisation sont :

- le scan des tables est bien plus lent, car vous devez lire les index pour obtenir les données ;

- vous ne pouvez pas utiliser uniquement l'index pour lire des données pour une requête ;

- vous utilisez beaucoup d'espace, et vous devez dupliquer des index de nœuds (car vous ne pouvez pas simplement stocker des lignes dans les nœuds) ;

- les suppressions vont perturber la table (comme les index ne sont pas modifiés lors de l'effacement) ;

- il est plus difficile de ne mettre en cache que les données.

7-4-2 - Rendre vos tables aussi compactes que possible

Une des optimisations simples est de réduire au maximum la taille de vos données et de vos index sur le disque et en mémoire. Cela peut donner des accélérations impressionnantes, car les lectures sur le disque sont plus rapides, et moins de mémoire centrale sera utilisée. L'indexation de colonnes de petite taille prend aussi moins de ressources.

MySQL supporte un grand nombre de types de table et de formats de ligne. Choisir ces types peut vous conduire à des améliorations de performances. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

Vous pouvez obtenir des gains de performance sur les tables et minimiser l'espace disque en utilisant les techniques ci-dessous.

- Utilisez les types les plus efficaces et les plus petits possible. MySQL a différents types spécialisés qui épargnent de l'espace disque et de la mémoire.

- Utilisez les types d'entiers les plus petits possible pour réduire les tables. Par exemple, MEDIUMINT est souvent préférable à INT.

- Déclarez les colonnes pour qu'elles soient NOT NULL si possible. Cela accélère les traitements, et vous fait gagner un bit par colonne. Notez que si vous avez vraiment besoin d'une valeur NULL dans votre application, il est recommandé de l'utiliser. Évitez simplement de l'utiliser par défaut sur toutes les colonnes.

- Si vous n'avez pas de colonne de taille variable (VARCHAR, TEXT ou BLOB), un format de ligne à taille fixe est utilisé. C'est plus rapide, mais cela prend plus d'espace sur le disque. Voir Section 14.1.3, « Formats de table MyISAM ».

- La clé primaire doit être aussi courte que possible. Cela rend l'identification des lignes plus efficace.

- Ne créez que des index dont vous avez besoin. Les index sont bons pour accélérer les lectures, mais sont plus lents lorsque vous écrivez des données. Si vous accédez essentiellement à votre table en lecture avec des combinaisons de colonnes, faites un index avec ces colonnes. Le premier index doit être la colonne la plus utilisée. Si vous utilisez constamment de nombreuses colonnes, vous devriez utiliser la colonne avec le plus de doublons en premier, pour obtenir une meilleure compression.

- S'il est probable qu'une colonne a un préfixe unique avec les premiers caractères, il est mieux de n'indexer que ce préfixe. MySQL supporte les index sur une partie de colonne. Les index les plus courts sont les plus efficaces, car ils prennent moins d'espace disque, et aussi, car ils absorbent plus de requêtes grâce au cache en mémoire. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

- Dans certaines circonstances, il peut être intéressant de séparer en deux une table qui est scannée très souvent. C'est particulièrement vrai pour les formats de tables dynamiques, et si possible, utilisez un format de table statique pour les colonnes les plus pertinentes.

7-4-3 - Index de colonnes

Tous les types de colonnes de MySQL peuvent être indexés. L'utilisation des index sur les colonnes pertinentes est la meilleure façon d'améliorer les performances des opérations de SELECT.

Le nombre maximum de clés et la longueur maximale des index sont définis pour chaque type de table. Voir Chapitre 14, Moteurs de tables MySQL et types de table. Vous pouvez avec tous les gestionnaires de tables avoir au moins 16 clés et une taille totale d'index d'au moins 256 octets.

Pour les colonnes CHAR et VARCHAR, il est possible d'indexer un préfixe de la colonne. C'est plus rapide et plus économe en espace disque que l'indexation de la colonne entière. La syntaxe pour indexer le début d'une colonne au moment de la création de la table ressemble à cela : voir Section 7.4.3, « Index de colonnes ».

Les moteurs de tables MyISAM et (depuis MySQL 4.0.14) InnoDB supportent aussi l'indexation des colonnes BLOB et TEXT. Lors de l'indexation d'une colonne BLOB ou TEXT, vous devez spécifier une taille pour l'index. Par exemple :

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Les préfixes peuvent atteindre 255 octets de longueur (ou 1000 octets pour les tables MyISAM et InnoDB depuis MySQL 4.1.2). Notez que les limites de préfixes sont mesurées en octets, alors que la limite de préfixe dans la commande CREATE TABLE est interprétée comme un nombre de caractères. Prenez-le en compte lorsque vous spécifiez une taille de préfixe pour une colonne qui utilise un jeu de caractères multioctets.

Depuis MySQL 3.23.23, vous pouvez aussi créer des index FULLTEXT. Ils sont utilisés pour les recherches en texte plein. Seules les tables MyISAM supportent les index FULLTEXT et uniquement pour les colonnes CHAR, VARCHAR, et TEXT. L'indexation se fait sur toute la largeur de la colonne. L'indexation par préfixe n'est pas possible. Voyez la section Section 12.6, « Recherche en texte intégral (Full-text) dans MySQL » pour plus de détails.

Depuis MySQL 4.1.0, vous pouvez créer des index spatiaux. Actuellement, le type de données spatial n'est supporté que par les tables MyISAM. Les données spatiales utilisent un R-tree.

Le moteur de tables MEMORY (HEAP) supporte les index hash. Depuis MySQL 4.1.0, ce moteur supporte aussi les index B-tree.

7-4-4 - Index sur plusieurs colonnes

MySQL peut créer des index sur plusieurs colonnes. Un index peut comprendre jusqu'à 15 colonnes. (Sur les colonnes de type CHAR ou VARCHAR, vous pouvez utiliser uniquement le début de la colonne pour l'indexation.) (Voir Section 7.4.3, « Index de colonnes ».)

Un index sur plusieurs colonnes peut être compris comme un tableau trié contenant des valeurs créées par concaténation des valeurs des colonnes indexées.

MySQL utilise les index sur plusieurs colonnes de telle sorte que les requêtes sont accélérées quand on spécifie une quantité connue de la première colonne de l'index dans une clause WHERE, même si on ne spécifie pas la valeur des autres colonnes.

On suppose qu'une table est créée avec les paramètres suivant :

mysql> CREATE TABLE test (
->       id INT NOT NULL,
->       nom CHAR(30) NOT NULL,
->       prenom CHAR(30) NOT NULL,
->       PRIMARY KEY (id),
->       INDEX nom_index (nom,prenom));

Alors l'index nom_index est un index de nom et de prenom. Cela sera utile pour les requêtes qui spécifient des valeurs dans une gamme donnée de nom, ou pour à la fois nom et prenom. Ainsi l'index nom_index sera utilisé pour les requêtes suivantes :

mysql> SELECT * FROM test WHERE nom="Widenius";

mysql> SELECT * FROM test WHERE nom="Widenius"
->                    AND prenom="Michael";

mysql> SELECT * FROM test WHERE nom="Widenius"
->                    AND (prenom="Michael" OR prenom="Monty");

mysql> SELECT * FROM test WHERE nom="Widenius"
->                    AND prenom >="M" AND prenom < "N";

Cependant, l'index nom_index ne sera pas utilisé pour les requêtes suivantes :

mysql> SELECT * FROM test WHERE prenom="Michael";

mysql> SELECT * FROM test WHERE nom="Widenius"
->                    OR prenom="Michael";

Pour plus d'informations sur la méthode de MySQL pour utiliser les index dans le but d'améliorer les performances des requêtes, voyez la section suivante.

7-4-5 - Comment MySQL utilise les index

Les index sont utilisés pour trouver des lignes de résultat avec une valeur spécifique, très rapidement. Sans index, MySQL doit lire successivement toutes les lignes, et à chaque fois, faire les comparaisons nécessaires pour extraire un résultat pertinent. Plus la table est grosse, plus c'est coûteux. Si la table dispose d'un index pour les colonnes utilisées, MySQL peut alors trouver rapidement les positions des lignes dans le fichier de données, sans avoir à fouiller toute la table. Si une table a 1000 lignes, l'opération sera alors 100 fois plus rapide qu'une lecture séquentielle. Notez que si vous devez lire la presque totalité des 1000 lignes, la lecture séquentielle se révélera alors plus rapide, malgré tout.

Tous les index de MySQL (PRIMARY, UNIQUE et INDEX) sont stockés sous la forme de B-tree. Les chaînes sont automatiquement préfixées et leurs espaces terminaux sont supprimés. Voir Section 13.2.4, « Syntaxe de CREATE INDEX  ».

Les index sont utilisés pour :

- trouver rapidement des lignes qui satisfont une clause WHERE ;

- écarter rapidement des lignes. S'il y a un choix à faire entre plusieurs index, MySQL utilise généralement celui qui retourne le plus petit nombre de lignes ;

- lire des lignes dans d'autres tables lors des jointures ;

- trouver les valeurs MAX() et MIN() pour une colonne indexée. C'est une opération qui est optimisée par le préprocesseur, qui vérifie si vous utilisez la constante WHERE key_part_# = sur toutes les parties de clés inférieures à < N. Dans ce cas, MySQL va faire une simple recherche de clés et remplacer l'expression par une constante. Si toutes les expressions sont remplacées par des constantes, la requête va alors être rapidement calculée :

SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10

- trier ou grouper des lignes dans une table, si le tri ou le regroupement est fait avec un préfixe à gauche utilisable (par exemple, ORDER BY key_part_1,key_part_2). La clé est lue en ordre inverse, si toutes les parties de clé sont suivies du mot-clé DESC. Voir Section 7.2.10, « Comment MySQL optimise ORDER BY » ;

- dans certains cas, la requête peut être optimisée pour lire des valeurs sans consulter le fichier de données. Si cette possibilité est utilisée avec des colonnes qui sont toutes numériques, et forme le préfixe de gauche d'une clé, les valeurs peuvent être lues depuis l'index, à grande vitesse :

SELECT key_part3 FROM table_name WHERE key_part1=1

Supposez que vous utilisiez la commande SELECT suivante :

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

Si un index multicolonne existe sur les colonnes col1 et col2, les lignes appropriées seront directement lues. Si des index séparés sur les colonnes col1 et col2 existent, l'optimiseur va essayer de trouver l'index le plus restrictif des deux, en décidant quel index débouche sur le moins de lignes possible.

Si une table a un index multicolonne, tout préfixe d'index peut être utilisé par l'optimiseur pour trouver des lignes. Par exemple, si vous avez un index à trois colonnes (col1,col2,col3), vous pouvez faire des recherches accélérées sur les combinaisons de colonnes (col1), (col1,col2) et (col1,col2,col3).

MySQL ne peut utiliser d'index partiel sur les colonnes ne formant pas un préfixe d'index. Supposez que vous avez la commande SELECT suivante :

mysql> SELECT * FROM tbl_name WHERE col1=val1;
mysql> SELECT * FROM tbl_name WHERE col2=val2;
mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

Si un index existe sur les colonnes (col1,col2,col3), seule la première requête pourra utiliser l'index ci-dessus. Les deux autres requêtes utilisent des colonnes indexées, mais les colonnes (col2) et (col2,col3) ne font pas partie du préfixe des colonnes (col1,col2,col3).

MySQL utilise aussi les index lors des comparaisons avec l'opérateur LIKE si l'argument de LIKE est une chaîne constante qui ne commence pas par un caractère joker. Par exemple, les requêtes SELECT suivantes utilisent des index :

mysql> SELECT * FROM tbl_name WHERE key_col LIKE "Patrick%";
mysql> SELECT * FROM tbl_name WHERE key_col LIKE "Pat%_ck%";

Dans le premier exemple, seules les lignes avec "Patrick" <= key_col < "Patricl" sont considérées. Dans le second exemple, "Pat" <= key_col < "Pau" sont considérées.

Les commandes SELECT suivantes n'utilisent pas d'index :

mysql> SELECT * FROM tbl_name WHERE key_col LIKE "%Patrick%";
mysql> SELECT * FROM tbl_name WHERE key_col LIKE other_col;

Dans la première requête, la valeur associée à LIKE commence avec un caractère joker. Dans le second exemple, la valeur associée à LIKE n'est pas une valeur constante.

MySQL 4.0 fait une autre optimisation avec l'opérateur LIKE. Si vous utilisez ... LIKE "%string%" et que string est plus grand que trois caractères, MySQL va utiliser l'algorithme Turbo Boyer-Moore qui prend une valeur initiale pour résoudre le masque, et l'exploite pour accélérer la recherche.

Les recherches qui utilisent la fonction column_name IS NULL vont utiliser les index si column_name sont des index.

MySQL normalement utilise l'index qui génère le moins de lignes possible. Un index est utilisé avec les colonnes que vous spécifiez, et les opérateurs suivants : =, >, >=, <, <=, BETWEEN et l'opérateur LIKE sans préfixe joker, c'est-à-dire de la forme 'quelquechose%'.

Un index qui ne s'applique pas à tous les niveaux de AND dans une requête WHERE, ne sera pas utilisé pour optimiser la requête. En d'autres termes, pour être capable d'utiliser un index pour optimiser une requête, un préfixe de l'index doit être utilisé dans toutes les parties de la formule logique contenant AND.

Les clauses WHERE suivantes utilisent des index :

... WHERE index_part1=1 AND index_part2=2 AND other_column=3
... WHERE index=1 OR A=10 AND index=2      /* index = 1 OR index = 2 */
... WHERE index_part1='hello' AND index_part_3=5
/* optimisé par "index_part1='hello'" */
... WHERE index1=1 and index2=2 or index1=3 and index3=3;
/* peut utiliser un index sur index1 mais pas sur index2 ou index 3 */

Ces clauses WHERE n'utilisent pas d'index :

... WHERE index_part2=1 AND index_part3=2  /* index_part_1 n'est pas utilisé */
... WHERE index=1 OR A=10                  /* Index n'est pas utilisé sur les deux parties du AND */
... WHERE index_part1=1 OR index_part2=10  /* Aucun index ne s'applique à toutes les colonnes */

Notez que dans certains cas, MySQL ne va pas utiliser un index, même s'il y en a un disponible. Si l'utilisation de l'index requiert que MySQL accède à plus de 30 % des lignes de la table (dans ce cas, un scan de table est probablement plus rapide, et demandera moins d'accès disques). Notez que si une telle requête utilise la clause LIMIT pour ne lire qu'une partie des lignes, MySQL utilisera tout de même l'index, car il va trouver plus rapidement les quelques lignes de résultat.

Les index hash ont des caractéristiques différentes de celles présentées.

- Elles sont utilisées uniquement pour les comparaisons avec les opérateurs = ou <=> (mais elles sont très rapides).

- L'optimiseur ne peut pas utiliser un index hash pour accélérer une clause ORDER BY. Ce type d'index ne peut être utilisé que pour rechercher la prochaine ligne dans l'ordre.

- MySQL ne peut déterminer approximativement le nombre de lignes qui sont présentes entre deux valeurs : cette valeur est utilisée par l'optimiseur d'intervalle pour décider quel index utiliser. Cela affecte certaines requêtes, si vous changez la table MyISAM en table MEMORY.

- Seules les clés entières peuvent être recherchées, pour une ligne. Avec un index B-tree, un préfixe peut être utilisé pour trouver les lignes.

7-4-6 - Le cache de clés des tables MyISAM

Pour réduire les accès aux disques, le moteur MyISAM emploie une stratégie utilisée par de nombreux systèmes de bases de données. Il utilise un cache qui garde en mémoire les blocs de tables les plus souvent utilisés.

- Pour les blocs d'index, une structure spéciale appelée cache de clés (buffer de clés) est entretenue. La structure contient un certain nombre de blocs de mémoire, où les blocs d'index les plus souvent sollicités résident.

- Pour les blocs de données, MySQL n'utilise pas de cache. Au lieu de cela, il exploite le cache natif du système de fichiers.

Cette section décrit les opérations basiques du cache de clés MyISAM. Puis, elle présente les modifications apportées en MySQL version 4.1 pour améliorer les performances du cache de clés, et vous donner un meilleur contrôle sur les opérations de cache.

- Les accès aux caches de clés ne sont pas séquentiels entre les threads. Des accès simultanés sont désormais possibles.

- Vous pouvez configurer plusieurs caches de clés, et assigner différents index de tables, spécifiquement.

Le mécanisme de cache de clés est aussi utilisé par les tables ISAM. Toutefois, ce n'est pas significatif. Les tables ISAM sont de moins en moins utilisées depuis l'introduction en MySQL 3.23 des tables MyISAM. MySQL 4.1 va plus loin : les tables ISAM sont désactivées par défaut.

Vous pouvez contrôler la taille du cache de clés avec la variable système key_buffer_size. Si cette variable vaut zéro, le cache ne sera pas utilisé. Le cache de clés est aussi désactivé si la valeur de key_buffer_size est trop petite pour allouer le nombre minimal de blocs de buffers (8).

Lorsque le cache de clés n'est pas opérationnel, les fichiers d'index sont lus avec le cache du système de fichiers, fourni par le système d'exploitation. En d'autres termes, les index sont lus avec la même technique que les blocs de données.

Un bloc d'index est une adresse unitaire pour le fichier d'index MyISAM. Généralement, la taille d'un bloc d'index est égale à la taille des nœuds de l'index B-tree. Les index sont représentés sur le disque en utilisant un arbre B-tree. Les nœuds terminaux sont appelés des feuilles. Les nœuds qui ne sont pas des feuilles sont dits non terminaux.

Tous les blocs de buffer dans la structure de cache de clés ont la même taille. Cette taille peut être égale, supérieure ou inférieure à la taille de bloc d'index de la table. Généralement, une de ces deux valeurs est un multiple de l'autre.

Lorsque des données d'un bloc d'index de table doivent être lues, le serveur commence par vérifier si elles sont disponibles dans le cache de clés, plutôt que sur le disque. C'est-à-dire, qu'il va préférer écrire ou lire dans le cache de clés plutôt que sur le disque. Sinon, le serveur choisit un bloc de cache contenant un index d'une autre table, et remplace les données par celles de la table qu'il manipule. Dès que le bloc est dans le cache, les données d'index sont accessibles.

Si un des blocs sélectionnés pour être écrasés, a été modifié, le bloc est considéré comme « sale. » Dans ce cas, avant d'être remplacé, il est d'abord écrit dans le fichier d'index, sur le disque.

Généralement, le serveur suit une heuristique LRU (Least Recently Used : le moins utilisé) : lorsqu'il choisit un bloc pour être remplacé, il sélectionne le bloc qui a été accédé le moins souvent. Pour faciliter ce choix, le module de cache de clés entretient une queue (la chaîne LRU) de tous les blocs utilisés. Lorsqu'un bloc doit être remplacé, les blocs du début de la queue sont les moins souvent sélectionnés, et sont les candidats au remplacement.

7-4-6-1 - Accès au cache de clés partagé

Avant MySQL 4.1, les accès au cache de clés étaient sérialisés : deux threads ne pouvaient y accéder simultanément. Les processus serveur demandent un bloc après avoir fini de traiter la requête précédente. En conséquence, une requête pour un bloc d'index qui n'est pas présente dans le cache de clés bloque l'accès aux autres threads lorsque le cache est complété avec le nouveau bloc.

Depuis la version 4.1.0, le serveur supporte un accès partagé au cache de clés.

- Un buffer qui n'est pas modifié peut être lu par plusieurs threads.

- Un buffer qui est modifié fait attendre les threads qui doivent l'utiliser jusqu'à la fin de la modification.

- Plusieurs threads peuvent initier des requêtes qui engendreront des remplacements de caches, tant qu'ils n'interfèrent pas les uns avec les autres : c'est-à-dire tant qu'ils ont besoin de blocs différents, et qu'ils remplacent des blocs différents.

L'accès partagé au cache de clés permet au serveur d'améliorer considérablement la vitesse d'exécution.

7-4-6-2 - Caches multiples de clés

Les accès partagés à un cache de clés améliorent grandement les performances, mais ne règlent pas les contentieux entre les threads. Ils sont toujours en compétition pour les structures de contrôle qui donnent l'accès aux caches de clés. Pour réduire ces frictions, MySQL 4.1.1 dispose de caches multiples de clés. Cela vous permet d'assigner différentes clés à différents caches.

Lorsqu'il peut y avoir un cache de clés multiple, le serveur doit savoir quel cache utiliser lors du traitement d'une requête, pour une table MyISAM. Par défaut, les index des tables MyISAM dans le cache par défaut. Pour assigner un index à un cache spécifique, utilisez la commande CACHE INDEX.

Par exemple, les deux commandes suivantes assignent les index des tables t1, t2 et t3 au cache de clés appelé hot_cache:

mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+

Note : si le serveur a été compilé en incluant le moteur de table ISAM, les tables ISAM utilisent le mécanisme de cache de clés. Mais les index ISAM utilisent uniquement le cache de clés par défaut, et ils ne peuvent pas être assignés à un autre cache.

Le cache de clés indiqué dans la commande CACHE INDEX peut être créé en spécifiant sa taille avec le paramètre SET GLOBAL ou en utilisant les options de démarrage. Par exemple :

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

Pour détruire un cache de clés, donnez-lui une taille de zéro :

mysql> SET GLOBAL keycache1.key_buffer_size=0;

Les variables de cache de clés sont des variables système structurées, qui ont un nom et des composants. Pour keycache1.key_buffer_size, keycache1 est le nom de variable du cache, et key_buffer_size est le composant de cache. Voyez Section 9.4.1, « Variables système structurées » pour une description de la syntaxe utilisée pour faire référence aux variables système structurées.

Par défaut, les index de tables sont assignés dans le cache de clés principal, dit aussi cache par défaut. Ce cache est créé au démarrage. Lorsqu'un cache de clés est détruit, les index qui lui étaient assignés sont assignés au cache par défaut.

Pour un serveur en charge, nous recommandons la stratégie suivante pour les caches de clés :

- un cache de clés principal qui représente 20 % de l'espace alloué pour tous les caches de clés. Il sera utilisé par les tables qui sont le plus sollicitées, mais qui ne sont pas modifiées ;

- un cache de clés minoritaire qui représente 20 % de l'espace alloué pour tous les caches de clés. Il sera utilisé pour les tables de taille intermédiaire, qui sont intensivement modifiées, comme des tables temporaires, par exemple ;

- un cache de clés secondaire qui représente 60 % de l'espace alloué pour tous les caches de clés. C'est le cache de clés par défaut, il sera utilisé pour toutes les autres tables.

Une raison pour utiliser les trois caches de clés est que l'accès à un des caches ne bloque pas l'accès aux autres. Les requêtes qui accèdent aux index d'un des caches ne sont pas en compétition avec les requêtes qui utilisent les index dans les autres caches. Les gains de performances sont aussi dus à :

- le cache principal est utilisé pour les requêtes en lecture et son contenu n'est jamais modifié. Par conséquent, lorsqu'un bloc d'index doit être lu sur le disque, le contenu du bloc remplacé n'a pas besoin d'être sauvé ;

- pour un index assigné au cache principal, s'il n'y a pas de requêtes qui font des scans d'index, il y a une haute probabilité que tous les blocs d'index qui ne sont pas terminaux resteront dans le cache ;

- une opération de modification sur une table temporaire est effectuée plus rapidement lorsque le nœud à modifier est déjà dans le cache, et n'a pas besoin d'être lu dans le disque. Si la taille des index de la table temporaire est comparable à la taille du cache minoritaire, la probabilité est très haute que l'index soit déjà dans le cache.

7-4-6-3 - Stratégie d'insertion au milieu

Par défaut, le système de gestion de cache de clés de MySQL 4.1 utilise la stratégie LRU pour choisir les blocs de cache qui doivent être remplacés, mais il accepte aussi une autre méthode plus sophistiquée, appelée « stratégie de l'insertion au milieu ».

Lors de l'utilisation de la stratégie d'insertion au milieu, la chaîne LRU est divisée en deux parties : une sous-chaîne principale, et une sous-chaîne secondaire. Le point de division entre les deux parties n'est pas fixé, mais le système s'assure que la partie principale n'est pas « trop petite », et qu'elle contient au moins key_cache_division_limit % de blocs de cache de clés. key_cache_division_limit est un composant d'une variable structurée de cache de clés, et sa valeur peut être modifiée indépendamment pour chaque cache.

Lorsqu'un bloc d'index est lu dans une table, depuis le cache de clés, il est placé à la fin de la sous-chaîne secondaire. Après un certain nombre d'accès, il est promu dans la sous-chaîne principale. Actuellement, le nombre d'accès requis pour passer un bloc et le même pour tous les blocs d'index. Dans le futur, nous allons permettre au compteur d'accès d'utiliser le niveau de B-tree : moins d'accès seront nécessaires à un nœud s'il contient un nœud non terminal d'un des niveaux supérieurs de l'index B-tree.

Un bloc de la chaîne principale est placé à la fin de la chaîne. Le bloc circule alors dans la sous-chaîne. Si le bloc reste à la fin de la sous-chaîne suffisamment longtemps, il est rétrogradé dans la chaîne secondaire. Ce temps est déterminé par la valeur du composant key_cache_age_threshold.

La valeur de seuil prescrit que, pour un cache de clés contenant N blocs, le bloc au début de la chaîne principale qui n'est pas accédé dans les derniers N*key_cache_age_threshold/100 accès doit être placé au début de la chaîne secondaire. Il devient le premier candidat à l'éviction, car les blocs de remplacement sont toujours pris au début de la chaîne secondaire.

La stratégie de l'insertion au milieu vous permet de garder les blocs les plus utilisés dans le cache. Si vous préférez utiliser la stratégie LRU classique, laissez la valeur de key_cache_division_limit à 100.

La stratégie d'insertion au milieu aide à améliorer les performances lorsque l'exécution d'une requête qui requiert un scan d'index place dans le cache toutes les valeurs de l'index. Pour éviter cela, vous devez utiliser la stratégie d'insertion au milieu, avec une valeur très inférieure à 100 pour key_cache_division_limit. Les blocs les plus utilisés seront conservés dans le cache durant un tel scan.

7-4-6-4 - Préchargement des index

S'il y a suffisamment de blocs dans le cache de clés pour contenir tout un index, ou au moins les blocs correspondant aux blocs non terminaux, alors cela vaut la peine de précharger l'index avant de commencer à l'utiliser. Le préchargement vous permet de mettre les blocs d'index dans un buffer de caches le plus efficacement : il lit les blocs séquentiellement sur le disque.

Sans le préchargement, les blocs seront placés dans le cache de clés, au fur et à mesure des besoins des requêtes. Même si les blocs resteront dans le cache, puisqu'il y a de la place pour tous, ils seront pris sur le disque dans un ordre aléatoire, et non séquentiellement.

Pour précharger un index dans un cache, utilisez la commande LOAD INDEX INTO CACHE. Par exemple, la commande suivante précharge les index des tables t1 et t2 :

mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table   | Op           | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status   | OK       |
| test.t2 | preload_keys | status   | OK       |
+---------+--------------+----------+----------+

L'option IGNORE LEAVES fait que les blocs non terminaux seuls seront lus dans l'index. Par conséquent, la commande ci-dessus va charger tous les blocs de l'index de t1, mais uniquement les blocs non terminaux de t2.

Si un index a été assigné à un cache de clés en utilisant la commande CACHE INDEX, le préchargement place les blocs dans ce cache. Sinon, l'index est chargé dans le cache par défaut.

7-4-6-5 - Taille des blocs du cache de clés

MySQL 4.1 propose une nouvelle variable key_cache_block_size, pour chaque clé. Cette variable spécifie la taille du bloc de buffer pour le cache de clés. Il sert à optimiser les performances d'E/S pour les fichiers d'index.

Les meilleures performances d'E/S sont obtenues lorsque la taille du buffer de lecture est égale à la taille des opérations natives d'E/S système. Mais en donnant une taille de bloc de clé égale à la taille du buffer d'E/S ne donne pas les meilleures performances. Lors de la lecture de grands blocs terminaux, le serveur charge beaucoup de données inutiles, ce qui empêche la lecture d'autres nœuds.

Actuellement, vous ne pouvez pas contrôler la taille des blocs d'index dans la table. Cette taille est fixée par le serveur lorsque le fichier d'index .MYI est créé, en fonction de la taille des index de la table. Dans la plupart des cas, il est choisi égal à la taille du buffer d'E/S. Dans le futur, cela sera changé, et la variable key_cache_block_size sera exploitée.

7-4-6-6 - Restructurer le cache de clés

Un cache de clés peut être restructuré à tout moment, en modifiant les valeurs de ses paramètres. Par exemple :

mysql> SET GLOBAL cold_cache.key_buffer_size=4*1024*1024;

Si vous assignez une nouvelle valeur aux variables key_buffer_size ou key_cache_block_size, le serveur va détruire l'ancienne structure du cache, et en recréer un, en se basant sur les nouvelles valeurs. Si le cache contient des blocs sales, le serveur va les sauver sur le disque avant de détruire et recréer le cache. La restructuration n'intervient pas si vous modifiez un autre paramètre du cache.

Lors de la restructuration d'un cache de clés, le serveur commence par vider le contenu des buffers sales sur le disque. Après cela, le contenu du cache devient inaccessible. Cependant, la restructuration ne bloque pas les requêtes qui utilisent des index qui sont dans le cache. Au lieu de cela, le serveur accède directement à la table et utilise le cache du système de fichiers. Le cache du système de fichiers n'est pas aussi efficace que celui du cache de clés : si les requêtes s'exécutent toujours, elles seront un peu ralenties. Une fois que le cache a été restructuré, il redevient accessible, et les blocs peuvent être placés dedans. Le cache du système de fichiers n'est plus utilisé.

7-4-7 - Comment MySQL compte les tables ouvertes

Quand vous utiliserez la commande mysqladmin status, vous verrez quelque chose de ce genre :

Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12

Cela vous laissera perplexe si vous n'avez que six tables.

MySQL est multithreadé, il peut donc exécuter plusieurs requêtes sur la même table simultanément. Pour minimiser les interférences entre deux threads ayant différentes actions sur le même fichier, la table est ouverte indépendamment par chacun des threads. Cela nécessite un peu de mémoire, mais augmente les performances. Avec les tables au format ISAM et MyISAM, cela requiert aussi un fichier additionnel de description du fichier des données. Avec ce type de tables, le fichier décrivant l'index est partagé entre tous les threads.

Vous pourrez lire plus sur le sujet à la section suivante : Voir Section 7.4.8, « Quand MySQL ouvre et ferme les tables ».

7-4-8 - Quand MySQL ouvre et ferme les tables

table_cache, max_connections et max_tmp_tables affectent le nombre maximum de tables que le serveur garde ouvertes. Si vous augmentez l'une de ces valeurs, vous pourriez rencontrer une des limites de votre système d'exploitation. Cependant, vous pourrez augmenter ces limites sur de nombreux systèmes d'exploitation. Consultez votre documentation système pour voir comment faire cela, car la méthode pour modifier la limite est différente pour chaque système.

table_cache est lié au max_connections. Par exemple, pour 200 connexions simultanées, vous devriez avoir un cache de tables d'environ 200 * n, où n est le nombre maximum de tables dans une jointure. Vous devez aussi réserver des pointeurs de fichiers supplémentaires pour les tables temporaires et les fichiers.

Assurez-vous que votre système d'exploitation peut gérer le nombre de pointeurs de fichiers demandé par l'option table_cache. Si table_cache est trop grand, MySQL peut être à court de pointeurs, et refuser des connexions, échouer à l'exécution de requêtes, ou être très instable. Vous devez aussi prendre en compte que les tables MyISAM peuvent avoir besoin de deux pointeurs de fichiers pour chaque table différente. Vous pouvez augmenter le nombre de pointeurs de fichiers disponibles pour MySQL avec l'option de démarrage --open-files-limit=#. Voir Section A.2.17, « Fichier non trouvé ».

Le cache de tables ouvertes reste au niveau de table_cache entrées (par défaut 64, cela peut être modifié avec l'option -O table_cache=# de mysqld). Notez que MySQL peut ouvrir temporairement plus de tables, pour être capable d'exécuter des requêtes.

Une table qui n'est pas utilisée est refermée, et supprimée du cache de tables, dans les circonstances suivantes :

- lorsque le cache est plein, et qu'un thread essaie d'ouvrir une table qui n'est pas dans le cache ;

- lorsque le cache contient plus de table_cache lignes, et qu'aucun thread n'utilise cette table ;

- lorsque quelqu'un utilise la commande mysqladmin refresh ou mysqladmin flush-tables ;

- lorsque quelqu'un exécute la commande FLUSH TABLES.

Lorsque le cache de tables se remplit, le serveur utilise la procédure suivante pour identifier une entrée du cache, pour la supprimer :

- les tables qui ne sont pas en cours d'utilisation sont libérées, en utilisant la table qui a été accédée depuis plus longtemps en premier ;

- si le cache est plein, et qu'aucune table ne peut être libérée, mais qu'une nouvelle table doit être ouverte, le cache est temporairement étendu ;

- si le cache est dans un état d'extension, et qu'une table passe de l'état d'utilisation à non-utilisation, la table est immédiatement fermée et libérée du cache.

Une table est ouverte pour chaque accès simultané. Cela signifie que si vous avez deux threads qui accèdent à la même table, ou accèdent à la même table deux fois dans la requête (avec AS), la table devra être ouverte deux fois. La première ouverture d'une table prend deux pointeurs de fichiers. Chaque utilisation supplémentaire de la même table ne prendra qu'un pointeur supplémentaire. Le pointeur de fichier supplémentaire de la première table est celui du fichier d'index. Ce pointeur est partagé entre les threads.

Si vous ouvrez une table avec HANDLER table_name OPEN, un objet de table dédié sera alloué pour le thread. Cet objet de table n'est pas partagé avec les autres threads, et il ne sera pas fermé avant que le thread n'appelle HANDLER table_name CLOSE, ou que le thread ne meurt. Voir Section 13.1.3, « Syntaxe de HANDLER ». Lorsque cela arrive, la table est placée dans le cache de tables (s'il n'est pas plein).

Vous pouvez vérifier si votre cache de tables n'est pas trop petit en vérifiant la variable de mysqld appelée Opened_tables. Si cette valeur est grande, même si vous n'avez pas trop abusé de la commande FLUSH TABLES, vous devrez augmenter la taille du cache. Voir Section 13.5.3.15, « Syntaxe de SHOW STATUS ».

7-4-9 - Inconvénients de la création d'un grand nombre de tables dans la même base de données

Si vous avez beaucoup de fichiers dans un dossier, les opérations d'ouverture, fermeture, et création seront ralenties. Si vous exécutez une requête SELECT sur plusieurs tables, il y aura une légère perte lorsque le cache de tables sera plein, car pour chaque table ouverte, une autre doit être fermée. Vous pouvez réduire cette perte en augmentant la taille du cache de tables.

7-5 - Optimiser le serveur MySQL

7-5-1 - Réglage du système, au moment de la compilation, et paramètres du démarrage

Nous démarrons par le niveau du système, car certaines décisions à ce niveau doivent être prises très tôt. Dans d'autres cas, un regard rapide à cette partie doit suffire, car ce n'est pas tellement important pour les gros gains. Toutefois, il est toujours sympathique de sentir combien on peut gagner en changeant des choses à ce niveau.

Le choix du système d'exploitation est vraiment important ! Pour utiliser au maximum les capacités de machines multiprocesseurs, il vaut mieux choisir Solaris (car les threads marchent vraiment très bien) ou Linux (car le noyau 2.2 supporte très bien le SMP). Mais les plates-formes Linux 32 bits limitent par défaut la taille des fichiers à 2 Go. Heureusement, cela sera bientôt réparé avec l'arrivée des nouveaux systèmes de fichiers (XFS/Reiserfs). Si vous souhaitez désespérément utiliser des fichiers de plus de 2 Go sur Linux-intel 32 bits, vous devriez utiliser le patch de LFS pour le système de fichier ext2.

Comme nous n'avons pas utilisé MySQL en production sur énormément de plates-formes, nous vous conseillons de tester votre plate-forme avant de la choisir définitivement.

Autres astuces

- Si vous avez suffisamment de RAM, vous pouvez supprimer toutes les partitions d'échange (swap). Certains systèmes d'exploitation utilisent parfois la partition d'échange quand bien même il reste de la mémoire libre.

- L'utilisation de l'option --skip-external-locking de MySQL empêche les verrous externes. Cela n'influencera pas les fonctionnalités de MySQL tant que vous n'utilisez qu'un seul serveur. Il faut cependant penser à arrêter le serveur (ou bien de verrouiller les parties pertinentes) avant d'utiliser myisamchk. Sur certains systèmes, cette option est inutile, car les verrous externes ne fonctionnent pas du tout.

L'option --skip-external-locking est activée par défaut quand on compile avec MIT-pthreads, car flock() n'est pas totalement supporté sur toutes les plates-formes par MIT-pthreads. Elle l'est également sur Linux, car le verrouillage des fichiers de Linux n'est pas encore sûr.

Les seuls cas où on ne peut pas utiliser --skip-external-locking sont si on utilise plusieurs serveurs (pas de clients) MySQL sur les mêmes données, ou si on lance myisamchk sur une table sans vider son tampon et sans la verrouiller au préalable.

Il est toujours possible d'utiliser LOCK TABLES/UNLOCK TABLES même si vous utilisez --skip-external-locking.

7-5-2 - Réglage des paramètres du serveur

Vous pouvez obtenir les tailles par défaut des tampons du serveur mysqld avec la commande :

shell> mysqld --help

Cette commande génère une liste de toutes les options de mysqld et des variables configurables. Cette sortie comprend les valeurs par défaut et ressemble à cela :

Possible variables for option --set-variable (-O) are:
back_log                 current value: 5
bdb_cache_size           current value: 1048540
binlog_cache_size        current value: 32768
connect_timeout          current value: 5
delayed_insert_timeout   current value: 300
delayed_insert_limit     current value: 100
delayed_queue_size       current value: 1000
flush_time               current value: 0
interactive_timeout      current value: 28800
join_buffer_size         current value: 131072
key_buffer_size          current value: 1048540
lower_case_table_names   current value: 0
long_query_time          current value: 10
max_allowed_packet       current value: 1048576
max_binlog_cache_size    current value: 4294967295
max_connections          current value: 100
max_connect_errors       current value: 10
max_delayed_threads      current value: 20
max_heap_table_size      current value: 16777216
max_join_size            current value: 4294967295
max_sort_length          current value: 1024
max_tmp_tables           current value: 32
max_write_lock_count     current value: 4294967295
myisam_sort_buffer_size  current value: 8388608
net_buffer_length        current value: 16384
net_retry_count          current value: 10
net_read_timeout         current value: 30
net_write_timeout        current value: 60
read_buffer_size         current value: 131072
record_rnd_buffer_size   current value: 131072
slow_launch_time         current value: 2
sort_buffer              current value: 2097116
table_cache              current value: 64
thread_concurrency       current value: 10
tmp_table_size           current value: 1048576
thread_stack             current value: 131072
wait_timeout             current value: 28800

Si un serveur mysqld est en cours d'exécution, vous pouvez voir les valeurs que les variables utilisent réellement en exécutant la commande :

mysql> SHOW VARIABLES;

Vous pouvez obtenir les statistiques et différents indicateurs de statut pour un serveur en fonctionnement avec cette commande :

mysql> SHOW STATUS;

Les variables de serveur et de statut sont aussi accessibles avec mysqladmin :

shell> mysqladmin variables
shell> mysqladmin extended-status

Vous pouvez trouver une description complète de toutes les variables système dans les sections Section 5.2.3, « Variables serveur système » et Section 5.2.4, « Variables de statut du serveur  ».

MySQL utilise des algorithmes très extensibles, donc vous pouvez utiliser très peu de mémoire. Si malgré tout vous fournissez plus de mémoire à MySQL, vous obtiendrez également de meilleures performances.

Les deux variables les plus importantes au moment du réglage d'un serveur MySQL sont key_buffer_size et table_cache. Vous devriez vous assurer que celles-ci sont bien paramétrées avant de modifier les autres variables.

Les exemples suivants indiquent quelques valeurs typiques pour différentes valeurs de configuration. Les exemples utilisent le script mysqld_safe et utilisent la syntaxe --name=value pour donner à la variable appelée name la valeur value. Cette syntaxe est disponible depuis MySQL 4.0. Pour les anciennes versions de MySQL, prenez en compte ces différences :

- utilisez safe_mysqld plutôt que mysqld_safe ;

- utilisez la syntaxe de modification des variables --set-variable=nom=valeur ou -O name=value ;

- pour les noms de variables qui finissent par _size, vous pouvez les spécifier sans le suffixe _size. Par exemple, l'ancien nom de sort_buffer_size est sort_buffer. L'ancien nom de read_buffer_size est record_buffer. Pour voir quelles variables votre version du serveur reconnaît, utilisez mysqld --help.

Si vous avez beaucoup de mémoire (>=256 Mo) et beaucoup de tables, et que vous désirez des performances maximales avec un faible de nombre de clients, vous devriez essayer quelque chose cela :

shell> safe_mysqld -O key_buffer=64M -O table_cache=256 \
-O sort_buffer=4M -O read_buffer_size=1M &

Si vous n'avez que 128 Mo et seulement quelques tables, mais que vous demandez beaucoup de classements, vous pouvez essayer cela :

shell> safe_mysqld -O key_buffer=16M -O sort_buffer=1M

Si vous avez peu de mémoire et beaucoup de connexions, essayez cela :

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k \
-O read_buffer_size=100k &

Ou encore :

shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k \
-O table_cache=32 -O read_buffer_size=8k -O net_buffer_length=1K &

Si vous utilisez GROUP BY ou ORDER BY sur des fichiers de taille supérieure à la mémoire disponible, vous devriez augmenter la valeur de record_rnd_buffer pour accélérer la lecture des lignes après que le classement a été fait.

À l'installation de MySQL, un répertoire support-files est créé, et contient plusieurs exemples de fichiers my.cnf: my-huge.cnf, my-large.cnf, my-medium.cnf et my-small.cnf. Vous pouvez les utiliser comme base pour optimiser votre système.

Si vous avez vraiment beaucoup de connexions, des problèmes peuvent apparaître avec le fichier d'échange si mysqld n'a pas été configuré pour utiliser peu de mémoire pour chaque connexion. mysqld fonctionne mieux si vous avec suffisamment de mémoire pour toutes les connexions, bien sûr !

Notez que si vous changez une option de mysqld, elle ne prendra effet qu'au prochain démarrage du serveur.

Pour voir les effets d'un changement de paramètre, essayez quelque chose comme ça :

shell> mysqld -O key_buffer=32m --help

Les valeurs des variables sont listées vers la fin du résultat. Assurez-vous bien de la présence de l'option --help en fin de ligne ; si ce n'est pas le cas, les options listées après dans la ligne de commande ne seront pas prises en compte à la sortie.

Pour plus d'informations sur le paramétrage du moteur InnoDB, voyez la section Section 15.12, « Conseils pour l'amélioration des performances InnoDB ».

7-5-3 - Contrôle des performances de l'optimiseur de requêtes

La tâche de l'optimiseur de requêtes est de trouver une méthode optimale pour exécuter une requête SQL. Comme la différence entre de « bonnes » et de « mauvaises » performances peut être de plusieurs grandeurs d'ordre, la plupart des optimiseurs de requêtes, y compris celui de MySQL, fait une recherche plus ou moins exhaustive des méthodes possibles pour traiter une requête. Pour les jointures, le nombre de méthodes croît exponentiellement avec le nombre de tables. Pour les petits nombres de tables (jusqu'à 7 ou 10), ce n'est pas sensible. Mais dès que de grosses requêtes sont soumises, le temps passé à l'optimisation peut être source de ralentissement pour le serveur.

MySQL 5.0.1 propose une nouvelle méthode plus souple pour l'optimisation, qui permet à l'utilisateur de contrôler l'exhaustivité de la recherche de l'optimiseur dans sa quête pour la méthode la plus efficace pour traiter une requête. L'idée générale est que plus le nombre de méthodes étudiées est petit, moins l'optimiseur prendra de temps à compiler la requête. D'un autre côté, comme l'optimiseur a omis certaines méthodes, il peut avoir mis de côté la méthode optimale.

Le comportement de l'optimiseur peut être contrôlé grâce à deux variables système :

- la variable optimizer_prune_level indique à l'optimiseur d'omettre des méthodes basées sur l'estimation du nombre de lignes utilisées dans les tables. Notre expérience montre que ce type de « prévision » échoue rarement, tout en réduisant considérablement le temps de compilation des requêtes. C'est pour cela que cette variable est active par défaut (optimizer_prune_level=1). Cependant, si vous pensez que l'optimiseur pourrait trouver mieux, alors cette option peut être désactivée (optimizer_prune_level=0), au risque de voir la compilation de la requête prendre beaucoup plus de temps. Notez que même si vous utilisez cette heuristique, l'optimiseur va étudier un nombre exponentiel de méthodes ;

- la variable optimizer_search_depth indique la « profondeur » d'analyse de l'optimiseur. Les valeurs les plus faibles de optimizer_search_depth peuvent conduire à de grandes différences dans le temps de compilation. Par exemple, une requête avec 12-13 ou plus peut facilement prendre des heures ou des jours à compiler si optimizer_search_depth a une valeur proche du nombre de tables à traiter. Mais, si optimizer_search_depth vaut 3 ou 4, le compilateur peut traiter cette requête en une minute environ. Si vous n'êtes pas sûr de la valeur raisonnable de optimizer_search_depth, donnez-lui la valeur de 0 pour que l'optimiseur puisse déterminer la valeur automatiquement.

7-5-4 - Influences de la compilation et des liaisons sur la vitesse de MySQL

La plupart des tests suivants ont été réalisés sous Linux avec les outils comparatifs de MySQL, mais ils peuvent donner quelques indications pour d'autres systèmes d'exploitation et sur une charge de travail différente.

Les exécutables les plus rapides sont obtenus en liant avec -static.

Sur Linux, le code le plus rapide sera obtenu en compilant avec pgcc et -O3. Pour compiler sql_yacc.cc avec ces options, il faut environ 200 Mo de mémoire, car gcc/pgcc demande beaucoup de mémoire pour créer toutes les fonctions d'une traite. Il est aussi possible d'utiliser CXX=gcc à la configuration de MySQL pour éviter l'inclusion de la bibliothèque libstdc++ (qui n'est pas nécessaire). Sachez que pour certaines versions de pgcc, le code résultant ne fonctionnera que sur de vrais processeurs Pentium, même si vous utilisez l'option du compilateur qui doit générer du code fonctionnant sur tour les types de processeurs x586 (comme AMD).

L'utilisation du meilleur compilateur et/ou de la meilleure option de compilation permet de gagner 10 à 30 % de vitesse dans vos applications. C'est très important quand vous compilez le serveur SQL vous-même !

Nous avons compilé avec les compilateurs de Cygnus CodeFusion et de Fujitsu, mais aucun des deux n'était suffisamment exempt d'erreurs pour permettre la compilation de MySQL avec l'optimisation.

À la compilation de MySQL, vous devriez uniquement utiliser le support des caractères que vous allez utiliser. (Option --with-charset=xxx.) Les distributions binaires standard de MySQL sont compilées avec le support de toutes les gammes de caractères.

Voici une liste des mesures que nous avons effectuées.

- L'utilisation de pgcc et la compilation complète avec l'option -O6 donne un serveur mysqld 1 % plus rapide qu'avec gcc 2.95.2.

- Si vous utilisez la liaison dynamique (sans -static), le résultat est 13 % plus lent sur Linux. Sachez que vous pouvez néanmoins utiliser la liaison dynamique pour les bibliothèques de MySQL. Seul le serveur a des performances critiques.

- Si vous allégez votre binaire mysqld avec l'option strip libexec/mysqld, vous obtenez un binaire jusqu'à 4 % plus rapide.

- Si vous utilisez TCP/IP plutôt que les sockets Unix, le résultat est 7,5 % plus lent sur le même ordinateur. (Si vous vous connectez sur localhost, MySQL utilisera les sockets par défaut.)

- Si vous vous connectez en TCP/IP depuis un autre ordinateur avec un lien Ethernet 100 Mo/s, le résultat sera 8 à 11 % plus lent.

- L'utilisation de connexions sécurisées (toutes les données chiffrées par le support interne de SSL) pour nos tests comparatifs a provoqué une perte de vitesse de 55 %.

- Si vous compilez avec --with-debug=full, vous perdrez 20 % de performances sur la plupart des requêtes, mais la perte peut être plus importante sur certaines requêtes (la suite de tests de MySQL tourne 35 % plus lentement). Si vous utilisez --with-debug, vous ne perdrez que 15 %. En démarrant une version de mysqld, compilée avec --with-debug=full, avec --skip-safemalloc, le résultat final devrait être proche d'une compilation avec --with-debug.

- Sur un Sun UltraSPARC-IIe, Forte 5.0 est 4 % plus rapide que gcc 3.2.

- Sur un Sun UltraSPARC-IIe, Forte 5.0 est 4 % plus rapide en mode 32 bits qu'en mode 64 bits.

- La compilation avec gcc 2.95.2 sur UltraSPARC avec l'option -mcpu=v8 -Wa,-xarch=v8plusa améliore les performances de 4 %.

- Sur Solaris 2.5.1, MIT-pthreads est 8-12 % plus lent que la gestion native des threads de Solaris sur monoprocesseur. Avec plus de charge ou de CPU, la différente devrait être encore plus grande.

- La compilation sur Linux-x86 avec gcc sans les pointeurs -fomit-frame-pointer ou -fomit-frame-pointer -ffixed-ebp rend mysqld 1 à 4 % plus rapide.

Autrefois les distributions fournies par MySQL AB de MySQL-Linux étaient compilées avec pgcc, mais nous avons dû revenir au simple gcc à cause d'un bogue dans pgcc qui générait du code qui ne fonctionnait pas sur AMD. Nous continuerons à utiliser gcc tant que ce bogue ne sera pas corrigé. Néanmoins, si vous avez une machine non AMD, vous pouvez obtenir des binaires plus rapides en compilant avec pgcc. Le binaire standard de MySQL pour Linux est lié statiquement pour être plus rapide et plus portable.

7-5-5 - Comment MySQL gère la mémoire

La liste suivante indique certaines techniques utilisées par le serveur mysqld pour gérer la mémoire. Lorsque c'est possible, la variable serveur liée à la mémoire est indiquée.

- Le buffer de clés (variable key_buffer_size) est partagé par tous les threads. Les autres buffers sont alloués par le serveur suivant les besoins. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

- Chaque connexion utilise un espace spécifique au thread :

- une pile (par défaut, 64 ko, variable thread_stack) ;

- un buffer de connexion (variable net_buffer_length) ;

- un buffer de résultat (variable net_buffer_length).

Le buffer de connexion et celui de résultat sont dynamiquement élargis jusqu'à max_allowed_packet suivant les besoins. Lorsque la requête s'exécute, une copie de la chaîne de requêtes est aussi allouée.

- Tous les threads partagent la même mémoire de base.

- Seules les tables compressées ISAM / MyISAM sont copiées en mémoire. Ceci est dû au fait que pour un espace de 32 bits, il n'y a pas de place pour les grosses tables en mémoire. Lorsque les systèmes de 64 bits seront plus répandus, nous pourrions généraliser le support pour la copie en mémoire.

- Chaque requête qui effectue une analyse séquentielle d'une table alloue un buffer de lecture (variable record_buffer).

- Lors de la lecture de lignes en ordre 'aléatoire' (par exemple, après un tri), un buffer de lecture aléatoire est alloué pour éviter les accès disques (variable record_rnd_buffer).

- Toutes les jointures sont faites en une seule passe, et la plupart des jointures sont faites sans utiliser de table temporaire. La plupart des tables temporaires sont faites en mémoire (table HEAP). Les tables temporaires avec beaucoup de données (calculées comme la somme des tailles de toutes les colonnes) ou qui contiennent des colonnes de type BLOB sont sauvées sur le disque.

Un problème avec les versions de MySQL antérieures à la version 3.23.2 est que si une table HEAP dépassait la taille maximale de tmp_table_size, vous obteniez une erreur The table tbl_name is full. Dans les nouvelles versions, ce problème est géré en passant automatiquement la table HEAP en une table MyISAM sur le disque. Pour contourner ce problème, vous pouvez augmenter la taille maximale des tables en mémoire en modifiant l'option tmp_table_size de mysqld, ou en modifiant l'option SQL BIG_TABLES dans le programme client. Voir Section 13.5.2.8, « Syntaxe de SET ». En MySQL version 3.20, la taille maximale de la table temporaire est record_buffer*16, ce qui fait que si vous utilisez cette version, vous aurez à augmenter la valeur de record_buffer. Vous pouvez aussi démarrer mysqld avec l'option --big-tables pour toujours stocker les tables temporaires sur le disque. Cependant, cela va affecter la vitesse de votre serveur pour les requêtes complexes.

- La plupart des requêtes qui sont triées allouent un buffer de tri, et entre 0 et 2 fichiers temporaires, suivant la taille du résultat. Voir Section A.4.4, « Où MySQL stocke les fichiers temporaires ? ».

- Toute l'analyse et les calculs sont faits en mémoire locale. Aucune mémoire supplémentaire n'est nécessaire pour les petits calculs, et les allocations et libérations de mémoire sont évitées. La mémoire n'est allouée que pour les chaînes très grandes (ceci se fait via malloc() et free()).

- Chaque fichier d'index est ouvert une fois, et le fichier de données est ouvert pour chaque thread concurrent. Pour chaque thread concurrent, une structure de table, une structure de colonne pour chaque colonne et un buffer de taille 3 * n est alloué (où n est la taille maximale de ligne, en dehors des colonnes de type BLOB). Une colonne de type BLOB utilise 5 à 8 octets de plus que la taille des données du BLOB. Les gestionnaires de tables ISAM/MyISAM utilisent un buffer d'une ligne de plus pour leur utilisation interne.

- Pour chaque table qui a une colonne BLOB, un buffer est dynamiquement agrandi pour lire les valeurs BLOB. Si vous analysez toute une table, un buffer aussi grand que la plus grande valeur de la colonne BLOB sera alloué.

- Les gestionnaires de tables pour les tables en cours d'utilisation sont sauvés dans un cache, et gérés comme une pile FIFO. Normalement, ce cache contient 64 lignes. Si une table doit être utilisée par deux threads concurrents simultanément, le cache contiendra deux entrées pour la table. Voir Section 7.4.8, « Quand MySQL ouvre et ferme les tables ».

- La commande mysqladmin flush-tables ferme toute les tables qui ne sont pas utilisées, et marque toutes les tables en cours d'utilisation pour qu'elles soient fermées dès la fin du thread. Cela va libérer l'essentiel de la mémoire utilisée.

ps et d'autres commandes de statut système peuvent indiquer que mysqld utilise beaucoup de mémoire. Ceci est peut-être dû à des erreurs de compatibilité. Par exemple, sous Solaris, ps compte la mémoire inutilisée entre les threads comme de la mémoire utilisée. Vous pouvez le vérifier en regardant l'état du swap avec swap -s. Nous avons testé mysqld avec les détecteurs de fuite mémoire commerciaux, et il n'y a aucune fuite.

7-5-6 - Comment MySQL utilise le DNS

Quand un nouveau thread se connecte à mysqld, mysqld crée nouveau thread pour traiter la requête. Ce thread contrôle d'abord si le nom de l'hôte est dans le cache des noms d'hôte. Si ce n'est pas le cas, le thread va appeler gethostbyaddr_r() et gethostbyname_r() pour résoudre le nom de l'hôte.

- Si le système d'opération supporte les fonctions gethostbyaddr_r() et gethostbyname_r(), compatibles avec les threads, elles sont utilisées pour la résolution.

- Si le système d'exploitation ne supporte pas les appels précédents, le thread va verrouiller un « mutex » et appeler gethostbyaddr() et gethostbyname() à la place. Sachez que dans ce cas, aucun autre thread ne peut résoudre de nom d'hôte qui n'est pas dans le cache tant que le premier thread n'a pas fini.

Il est possible de désactiver la recherche du nom par DNS en démarrant mysqld avec l'option --skip-name-resolve. Dans ce cas, il est toujours possible d'utiliser les adresses IP dans les tables de privilèges de MySQL.

Si votre service DNS est très lent et que vous avez beaucoup d'hôtes, vous pouvez améliorer les performances soit en désactivant le DNS avec --skip-name-resolve, soit en augmentant la taille de HOST_CACHE_SIZE (par défaut : 128) et en recompilant mysqld.

Il est possible de désactiver le cache de noms d'hôte avec --skip-host-cache. Il est possible de vider le cache des noms d'hôte avec FLUSH HOSTS ou avec mysqladmin flush-hosts.

Si vous ne voulez pas autoriser les connexions par TCP/IP, vous pouvez utiliser l'option --skip-networking au démarrage de mysqld.

7-6 - Problèmes avec les disques

- Comme mentionné plus tôt, les accès disques représentent une limitation. Ce problème devient de plus en plus apparent, au fur et à mesure que les données sont de plus en plus nombreuses, et que les techniques de cache deviennent impossibles. Pour les grandes bases de données, lorsque vous accédez aux données plus ou moins aléatoirement, vous pouvez être sûr que vous aurez besoin d'un accès disque pour lire, et de plusieurs autres pour écrire. Pour minimiser le problème, utilisez des disques avec des temps d'accès très faibles.

- Augmentez le nombre de disques disponibles (et donc, réduisez le coût d'un accès), en plaçant des données sur d'autres fichiers via des liens symboliques.

- Utiliser des liens symboliques

Cela signifie que vous allez faire un lien symbolique sur le fichier d'index et/ou le fichier de données sur un autre disque. Cela améliore les lectures et écritures (surtout si ces disques ne sont alors utilisés qu'à ça). Voir Section 7.6.1, « Utiliser des liens symboliques ».

- Parallélisme

Le parallélisme signifie que vous avez plusieurs disques matériels, et que vous écrivez le premier bloc de données sur le premier disque, puis le second bloc de données sur le second disque, et le énième bloc sur le énième disque, etc. Cela signifie que si la taille normale de vos données est moins grande que le nombre de disques disponibles, vous obtiendrez alors des performances additionnées. Notez que le parallélisme est très dépendant du nombre de disques disponibles et du système d'exploitation. Voir Section 7.1.5, « Utiliser vos propres tests de performance  ».

Notez que la différence de performance avec le parallélisme est très dépendante des paramètres. Suivant la façon avec laquelle vous avez configuré les disques en parallèle, et le nombre de disques que vous utilisez, le facteur d'amélioration peut être très variable. Notez que vous devez faire votre optimisation en lecture aléatoire ou séquentielle.

- Pour plus de robustesse, vous pouvez utiliser des disques en RAID 0+1 (parallélisme et réplication), mais dans ce cas, vous aurez besoin de 2*N disques pour contenir vos données sur N disques. C'est probablement l'option la plus sûre, si vous avez le budget pour cela. Vous risquez aussi d'avoir à investir dans un système de gestion de gros volumes de données pour gérer cela efficacement.

- Une bonne option est de garder les données semi-importantes (qui peuvent être régénérées) sur un disque RAID 0 tandis que les données vraiment importantes (comme les informations d'hôtes et les logs) sur un disque de type RAID 0+1 ou RAID N. RAID N peut être un problème si vous avez de nombreux accès en écriture, à cause du temps de modification des bits de parité.

- Sous Linux, vous pouvez améliorer les performances (jusqu'à 100 % en charge n'est pas difficile) en utilisant hdparm pour configurer votre interface disque. La commande suivante doit être une série de bonnes options de hdparm pour MySQL (et probablement d'autres applications) :

hdparm -m 16 -d 1

Notez que la performance et la robustesse des solutions ci-dessus dépendent de votre matériel, et nous vous conseillons vivement de tester votre système soigneusement après avoir utilisé hdparm ! Consultez le manuel de hdparm pour plus de détails. Si hdparm n'est pas utilisé correctement, le système de fichiers peut être corrompu. Sauvegardez tout avant d'expérimenter.

- Vous pouvez aussi modifier les paramètres suivants sur le système de fichiers que la base de données utilise.

Si vous n'avez pas besoin de savoir quand un fichier a été accédé la dernière fois (ce qui n'est pas utile avec un serveur de base de données), vous pouvez monter votre système de fichiers avec l'option -o noatime.

Sur de nombreux systèmes d'exploitation, vous pouvez monter des disques avec l'option -o async pour que le système de fichiers soit modifié de manière asynchrone. Si votre serveur est raisonnablement stable, vous devriez obtenir de bonnes performances sans sacrifier la stabilité (cette option est activée par défaut sur Linux).

7-6-1 - Utiliser des liens symboliques

Vous pouvez déplacer les dossiers de bases de données et les placer dans un autre endroit, puis remplacer les dossiers eux-mêmes par des liens symboliques vers ces autres endroits. Vous pourriez vouloir faire cela pour mettre la base de données sur un système de fichiers plus rapide, ou pour gagner de l'espace disque sur le système central, ou encore répartir vos tables sur différents disques.

Le mieux, pour cela, est de faire des liens symboliques des bases vers les différents disques, et de ne faire des liens symboliques sur les tables qu'en dernier ressort.

7-6-1-1 - Utiliser les liens symboliques pour les bases

Pour créer des liens symboliques sur les bases de données, vous devez commencer par créer un dossier sur un disque de destination, puis faire un lien symbolique depuis le dossier de données vers votre dossier de destination.

shell> mkdir /dr1/databases/test
shell> ln -s /dr1/databases/test mysqld-datadir

MySQL n'accepte pas que vous fassiez le lien depuis plusieurs bases sur le même dossier. Remplacer une base par un lien symbolique sera correct tant que vous n'essayez pas de faire des liens symboliques dans la même base. Supposez que vous la base db1 dans le dossier de données MySQL, puis que vous fassiez un lien symbolique db2 qui pointe sur db1 :

shell> cd /path/to/datadir
shell> ln -s db1 db2

Maintenant, pour toute table tbl_a de db1, il en apparaît aussi tbl_a dans db2. Si un thread modifie db1.tbl_a et un autre db2.tbl_a, il va y avoir un conflit.

Si vous avez vraiment besoin de cette fonctionnalité, vous devez changer le code suivant dans le fichier C mysys/mf_format.c:

if (!(MyFlags & MY_RESOLVE_LINK) ||
(!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))

Avant MySQL 4.0, recherchez cette instruction dans le fichier mysys/mf_format.c :

if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))

Remplacez l'instruction par :

if (1)

Sous Windows, vous pouvez utiliser des liens internes symboliques pour relier des bases en compilant MySQL avec l'option -DUSE_SYMDIR. Cela vous permettra de placer vos bases de données sur différentes partitions. Voir Section 7.6.1.3, « Utiliser des liens symboliques pour les bases de données sous Windows ».

7-6-1-2 - Utiliser les liens symboliques avec les tables sous Unix

Avant MySQL 4.0, vous ne deviez pas utiliser les liens symboliques avec les tables, si vous n'étiez pas très prudent avec. Le problème est que si vous exécutez ALTER TABLE, REPAIR TABLE ou OPTIMIZE TABLE sur une table symbolique, le lien sera supprimé et remplacé par le fichier original. Cela arrive, car les commandes ci-dessus fonctionnent en créant un fichier temporaire dans le dossier de base, et lorsque l'opération est faite, l'original est remplacé par la copie.

Vous ne devez pas utiliser des liens symboliques sur les tables, sur les systèmes qui ne supportent pas complètement la fonction realpath(). (Au moins Linux et Solaris supportent realpath())

En MySQL 4.0, les liens symboliques sont complètement supportés par les tables MyISAM. Les autres types de tables vous donneront des résultats étranges lorsque vous les utilisez comme indiqué ci-dessus.

La gestion des liens symboliques de MySQL 4.0 fonctionne comme ceci (uniquement pour les tables MyISAM).

Dans le dossier de données, vous allez toujours trouver le fichier de définition de tables, le fichier de structure et le fichier d'index.

- Dans le dossier de données, vous devez toujours avoir le fichier de définition de tables, le fichier de données et le fichier d'index. Les fichiers de données et d'index peuvent être déplacés ailleurs, et remplacés dans le dossier de données par des liens symboliques. Mais le fichier de définition ne le peut pas.

- Vous pouvez utiliser un lien symbolique avec le fichier d'index et celui de données, pour placer ces fichiers dans d'autres dossiers.

- Le lien symbolique peut être fait via le système d'exploitation (si mysqld ne fonctionne pas) ou avec la commande INDEX/DATA DIRECTORY="path-to-dir" dans CREATE TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

- myisamchk ne va pas remplacer un lien symbolique avec les données ou le fichier d'index, mais il va travailler directement sur le fichier vers lequel le lien pointe. Tous les fichiers temporaires seront créés dans le même dossier que le dossier qui contient les données ou le fichier d'index.

- Lorsque vous détruisez une table qui utilise un lien symbolique, le fichier et le lien symbolique sont détruits. C'est une bonne raison pour ne pas exécuter mysqld en tant que root ou donner des droits d'écriture à d'autres personnes dans les dossiers de données de MySQL.

- Si vous renommez une table avec ALTER TABLE RENAME vous n'avez pas à déplacer la table dans une autre base, le lien symbolique du dossier de base sera renommé avec le nouveau nom.

- Si vous utilisez la commande ALTER TABLE RENAME pour déplacer la table dans une autre base, la table sera déplacée dans l'autre base, et l'ancien lien symbolique et le fichier vers lequel il pointait seront détruits (en d'autres termes, la nouvelle table ne sera pas un lien symbolique).

- Si vous n'utilisez pas de lien symbolique, vous devriez utiliser l'option --skip-symlink de mysqld pour vous assurer que personne n'efface ou ne renomme un fichier en dehors du dossier de données de MySQL.

SHOW CREATE TABLE n'indique pas si une table a des liens symboliques, avant la version 4.0.15. C'est aussi vrai pour mysqldump, qui utilise SHOW CREATE TABLE pour générer les commandes CREATE TABLE.

Ce qui n'est pas encore supporté :

- ALTER TABLE ignore toutes les options INDEX/DATA DIRECTORY="path".

- BACKUP TABLE et RESTORE TABLE ne respectent pas les liens symboliques.

- Le fichier .frm ne doit jamais être un lien symbolique. Comme indiqué précédemment, seuls les fichiers d'index et de données peuvent être des liens symboliques. Si jamais vous le faites malgré tout, vous générerez des erreurs de cohérence. Supposez que vous une base db1 dans le dossier de données MySQL, et une table tbl1 dans cette base, et dans le dossier db1, vous faites un lien symbolique tbl2 qui pointe sur tbl1 :

shell> cd /path/to/datadir/db1
shell> ln -s tbl1.frm tbl2.frm
shell> ln -s tbl1.MYD tbl2.MYD
shell> ln -s tbl1.MYI tbl2.MYI

Il va y avoir des problèmes si un thread lit db1.tbl1 et qu'un autre modifie db1.tbl2 :

- le cache de requête sera induit en erreur (il va croire que tbl1 a été mis à jour, et retournera des résultats incohérents) ;

- la commande ALTER de la table tbl2 va aussi échouer.

7-6-1-3 - Utiliser des liens symboliques pour les bases de données sous Windows

Depuis MySQL 3.23.16, les serveurs mysqld-max et mysql-max-nt de la distribution MySQL sont compilés avec l'option -DUSE_SYMDIR. Cela vous permet de disposer d'un dossier de base de données sur un autre disque, en utilisant un lien symbolique vers ce dossier, même si la procédure à suivre pour configurer ce lien est différente.

Depuis MySQL 4.0, les liens symboliques sont activés par défaut. Si vous n'en avez pas besoin, vous pouvez les désactiver avec l'option skip-symbolic-links :

[mysqld]
skip-symbolic-links

Avant MySQL 4.0, les liens symboliques sont désactivés par défaut. Pour les activer, vous pouvez ajouter la ligne suivante dans votre fichier my.cnf ou my.ini :

[mysqld]
symbolic-links

Sous Windows, vous créez un lien symbolique vers une base de données MySQL en créant un fichier qui contient le nom du dossier de destination. Sauvez le fichier dans le dossier de données, en utilisant le nom db_name.sym, où db_name est le nom de la base.

Supposons que le dossier de données MySQL est C:\mysql\data et que votre base foo soit placée dans le dossier D:\data\foo, vous pouvez configurer les liens symboliques comme ceci :

1. Assurez-vous que le dossier D:\data\foo existe bien, en le créant si nécessaire. Si vous avez déjà un dossier appelé foo dans le dossier de données, vous devez le déplacer dans D:\data. Sinon, le lien symbolique sera inopérant. Pour éviter les problèmes, le serveur ne doit pas fonctionner lorsque vous déplacez le dossier ;

2. Créez le fichier C:\mysql\data\foo.sym qui contient le chemin D:\data\foo\.

Après cela, toutes les tables créées dans la base foo seront créées dans le dossier D:\data\foo. Notez que les liens symboliques ne seront pas utilisés si un dossier du même nom existe dans le dossier de données MySQL.

8 - MySQL Scripts clients et utilitaires

Il y a de nombreux programmes clients de MySQL, qui se connectent au serveur pour accéder aux bases ou effectuer des opérations administratives. D'autres utilitaires sont aussi disponibles. Ils ne communiquent pas avec le serveur, mais effectuent des opérations liées à MySQL.

Ce chapitre fournit un bref aperçu de ces programmes, et vous en dit plus long sur le fonctionnement de chacun. Les descriptions indiquent comment invoquer les programmes, et quelles options ils comprennent. Voyez Chapitre 4, Utiliser les programmes MySQL pour des informations plus générales sur les programmes et leurs options.

8-1 - Présentation des scripts serveur et utilitaires

Voici une brève liste des scripts et utilitaires pour le serveur.

- myisampack

Un utilitaire qui compresse les tables MyISAM pour produire des tables en lecture seule très compactes. Voir Section 8.2, « myisampack, le générateur de tables MySQL compressées en lecture seule ».

- mysql

Le client en ligne de commande, pour envoyer des requêtes à MySQL, interactivement, ou en batch. Voir Section 8.3, « mysql, l'outil en ligne de commande ».

- mysqlaccess

Un script qui vérifie les droits d'accès du trio : hôte, utilisateur et base de données.

- mysqladmin

Un utilitaire pour réaliser des opérations d'administration de la base, telles que les créations de bases, le rafraîchissement des tables de droits, l'écriture des tables sur le disque et la réouverture des fichiers de logs. mysqladmin permet aussi de lire la version, les processus et les informations de statut du serveur. Voir Section 8.4, « mysqladmin, administration d'un serveur MySQL ».

- mysqlbinlog

Utilitaire de lecture des requêtes au format binaire. Peut être utilisé après un crash, sur une vieille sauvegarde. Voir Section 8.5, « mysqlbinlog, Exécuter des requêtes dans le log binaire ».

- mysqlcc

Interface graphique avec le serveur MySQL. Voir Section 8.6, « mysqlcc, MySQL Control Center ».

- mysqlcheck

Un client d'entretien de tables, qui vérifie, répare, analyse et optimise les tables. Voir Section 8.7, « Utiliser mysqlcheck pour l'entretien et la réparation ».

- mysqldump

Exporte une base de données MySQL dans un fichier sous la forme de requêtes SQL, ou de fichiers texte, avec la tabulation comme séparateur. Un freeware amélioré, d'après une idée originale d'Igor Romanenko. Voir Section 8.8, « mysqldump, sauvegarde des structures de tables et les données ».

- mysqlhotcopy

Un utilitaire qui fait des sauvegardes rapides des tables MyISAM et ISAM alors que le serveur fonctionne. Voir Section 8.9, « mysqlhotcopy, copier les bases et tables MySQL ».

- mysqlimport

Importe les fichiers texte dans les tables, en utilisant la commande LOAD DATA INFILE. Voir Section 8.10, « mysqlimport, importer des données depuis des fichiers texte ».

- mysqlshow

Voir Section 8.11, « Afficher les bases, tables et colonnes ».

- perror

Un utilitaire qui affiche la signification des codes d'erreur MySQL. Voir Section 8.12, « perror, expliquer les codes d'erreurs ».

- replace

replace modifie des chaînes dans des fichiers, ou sur l'entrée standard. Voir Section 8.13, « L'utilitaire de remplacement de chaînes replace ».

Chaque programme MySQL accepte différentes options. Mais chaque programme dispose de l'option --help qui vous donne une description complète des options du programme. Par exemple, mysql --help.

Les clients MySQL qui communiquent avec le serveur, utilisent la bibliothèque mysqlclient est les variables d'environnements suivantes :

MYSQL_UNIX_PORT

Le fichier de sockets Unix par défaut. Utilisé pour les connexions à localhost.

MYSQL_TCP_PORT

Le port par défaut. Utilisé par les connexions TCP/IP.

MYSQL_PWD

Le mot de passe par défaut.

MYSQL_DEBUG

Les options de débogage.

TMPDIR

Le dossier où les tables et fichiers temporaires sont placés.

Utiliser MYSQL_PWD n'est pas sécuritaire, et est fortement déconseillé. Voir Section 5.6.6, « Garder vos mots de passe en lieu sûr ».

Vous pouvez remplacer les valeurs par défaut des options en spécifiant les valeurs dans un fichier d'options, ou en ligne de commande. Section 4.3, « Spécifier des options aux programmes ».

8-2 - myisampack, le générateur de tables MySQL compressées en lecture seule

myisampack sert à compresser des tables MyISAM et pack_isam sert à compresser les tables ISAM. Comme les tables ISAM sont obsolètes, nous ne traiterons que de myisampack, mais tout ce qui est dit au sujet de myisampack est aussi vrai pour pack_isam.

myisampack fonctionne en compressant séparément chaque colonne de la table. Les informations nécessaires à la décompression sont lues en mémoire lorsque la table est ouverte. Cela donne de bien meilleures performances lors de l'accès à des lignes individuelles, car vous n'avez qu'à décompresser exactement une des lignes, et non pas un bloc de disque entier. Généralement, myisampack compresse le fichier avec un gain de 40 à 70 %.

MySQL utilise la carte mémoire (mmap()) sur les tables compressées et utilise les outils classiques de lecture et écriture si mmap() ne fonctionne pas.

Notez bien ceci :

- si mysqld a été appelé avec l'option --skip-external-locking, ce n'est pas une bonne idée que d'appeler myisampack si la table risque d'être mise à jour par le processus principal ;

- après avoir compressé la table, celle-ci n'est plus accessible qu'en lecture. C'est souvent un état voulu (par exemple, pour être gravée sur un CD). De plus, autoriser les écritures dans une table compressée fait partie de notre liste de tâches, mais avec une très faible priorité ;

- myisampack peut aussi compresser des colonnes BLOB ou TEXT. L'ancien pack_isam (pour les tables ISAM) ne peut le faire.

myisampack est invoqué comme ceci :

shell> myisampack [options] filename ...

Chaque nom de fichier doit être le nom d'un fichier d'index (.MYI). Si vous n'êtes pas dans le dossier de données, vous devez spécifier le chemin complet jusqu'au fichier. Il est toléré que vous omettiez l'extension du fichier .MYI.

myisampack supporte les options suivantes.

- --help, -?

Affiche le message d'aide et quitte.

- --backup, -b

Fait une sauvegarde de la table sous le nom de tbl_name.OLD.

- --debug[=debug_options], -# [debug_options]

Affiche le log de débogage. La chaîne debug_options vaut souvent 'd:t:o,filename'.

- --force, -f

Force la compression de la table, même si elle grossit ou si le fichier temporaire existe déjà. myisampack crée un fichier temporaire appelé tbl_name.TMD lors de la compression. Si vous tuez myisampack, le fichier .TMD peut ne pas être effacé. Normalement, myisampack se termine avec une erreur s'il découvre que le fichier tbl_name.TMD existe. Avec --force, myisampack reprendra le travail.

- --join=big_tbl_name, -j big_tbl_name

Rassemble toutes les tables indiquées dans la ligne de commande dans une seule table appelée big_tbl_name. Toutes les tables qui seront combinées doivent être identiques (mêmes noms de colonnes, mêmes types, mêmes index, etc.)

- --packlength=#, -p #

Spécifie la taille de stockage de la longueur de ligne, en octets. Cette valeur doit être 1, 2, ou 3. (myisampack stocke toutes les lignes avec des pointeurs de lignes de 1, 2 ou 3 octets. Dans les cas normaux, myisampack peut déterminer la taille correcte avant de compresser le fichier, mais il peut aussi se rendre compte durant le processus qu'une autre taille aurait été plus appropriée, ou plus courte. Dans ce cas, myisampack va imprimer une note pour que vous le sachiez lors de la prochaine compression du même fichier.

- --silent, -s

Mode silencieux. Seules les erreurs seront affichées.

- --test, -t

Ne compresse pas la table, mais teste juste la compression.

- --tmp_dir=path, -T path

Utilise le dossier indiqué comme dossier pour les fichiers temporaires.

- --verbose, -v

Mode détaillé. Toutes les informations sur la progression de la compression seront affichées.

- --version, -V

Affiche la version et quitte.

- --wait, -w

Attend et réessaie, si la table était déjà en cours d'utilisation. Si le serveur mysqld a été démarré avec l'option --skip-external-locking, ce n'est pas une bonne idée d'appeler myisampack, car la table risque d'être modifiée durant la compression.

La séquence de commande illustre la session de compression :

shell> ls -l station.*
-rw-rw-r--   1 monty    my         994128 Apr 17 19:00 station.MYD
-rw-rw-r--   1 monty    my          53248 Apr 17 19:00 station.MYI
-rw-rw-r--   1 monty    my           5767 Apr 17 19:00 station.frm

shell> myisamchk -dvv station

MyISAM file:     station
Isam-version:  2
Creation time: 1996-03-13 10:08:58
Recover time:  1997-02-02  3:06:43
Data records:              1192  Deleted blocks:              0
Datafile: Parts:           1192  Deleted data:                0
Datafile pointer (bytes):     2  Keyfile pointer (bytes):     2
Max datafile length:   54657023  Max keyfile length:   33554431
Recordlength:               834
Record format: Fixed length

table description:
Key Start Len Index   Type                       Root  Blocksize    Rec/key
1   2     4   unique  unsigned long              1024       1024          1
2   32    30  multip. text                      10240       1024          1

Field Start Length Type
1     1     1
2     2     4
3     6     4
4     10    1
5     11    20
6     31    1
7     32    30
8     62    35
9     97    35
10    132   35
11    167   4
12    171   16
13    187   35
14    222   4
15    226   16
16    242   20
17    262   20
18    282   20
19    302   30
20    332   4
21    336   4
22    340   1
23    341   8
24    349   8
25    357   8
26    365   2
27    367   2
28    369   4
29    373   4
30    377   1
31    378   2
32    380   8
33    388   4
34    392   4
35    396   4
36    400   4
37    404   1
38    405   4
39    409   4
40    413   4
41    417   4
42    421   4
43    425   4
44    429   20
45    449   30
46    479   1
47    480   1
48    481   79
49    560   79
50    639   79
51    718   79
52    797   8
53    805   1
54    806   1
55    807   20
56    827   4
57    831   4

shell> myisampack station.MYI
Compressing station.MYI: (1192 records)
- Calculating statistics

normal:     20  empty-space:      16  empty-zero:        12  empty-fill:  11
pre-space:   0  end-space:        12  table-lookups:      5  zero:         7
Original trees:  57  After join: 17
- Compressing file
87.14%

shell> ls -l station.*
-rw-rw-r--   1 monty    my         127874 Apr 17 19:00 station.MYD
-rw-rw-r--   1 monty    my          55296 Apr 17 19:04 station.MYI
-rw-rw-r--   1 monty    my           5767 Apr 17 19:00 station.frm

shell> myisamchk -dvv station

MyISAM file:     station
Isam-version:  2
Creation time: 1996-03-13 10:08:58
Recover time:  1997-04-17 19:04:26
Data records:              1192  Deleted blocks:              0
Datafile: Parts:           1192  Deleted data:                0
Datafilepointer (bytes):      3  Keyfile pointer (bytes):     1
Max datafile length:   16777215  Max keyfile length:     131071
Recordlength:               834
Record format: Compressed

table description:
Key Start Len Index   Type                       Root  Blocksize    Rec/key
1   2     4   unique  unsigned long             10240       1024          1
2   32    30  multip. text                      54272       1024          1

Field Start Length Type                         Huff tree  Bits
1     1     1      constant                             1     0
2     2     4      zerofill(1)                          2     9
3     6     4      no zeros, zerofill(1)                2     9
4     10    1                                           3     9
5     11    20     table-lookup                         4     0
6     31    1                                           3     9
7     32    30     no endspace, not_always              5     9
8     62    35     no endspace, not_always, no empty    6     9
9     97    35     no empty                             7     9
10    132   35     no endspace, not_always, no empty    6     9
11    167   4      zerofill(1)                          2     9
12    171   16     no endspace, not_always, no empty    5     9
13    187   35     no endspace, not_always, no empty    6     9
14    222   4      zerofill(1)                          2     9
15    226   16     no endspace, not_always, no empty    5     9
16    242   20     no endspace, not_always              8     9
17    262   20     no endspace, no empty                8     9
18    282   20     no endspace, no empty                5     9
19    302   30     no endspace, no empty                6     9
20    332   4      always zero                          2     9
21    336   4      always zero                          2     9
22    340   1                                           3     9
23    341   8      table-lookup                         9     0
24    349   8      table-lookup                        10     0
25    357   8      always zero                          2     9
26    365   2                                           2     9
27    367   2      no zeros, zerofill(1)                2     9
28    369   4      no zeros, zerofill(1)                2     9
29    373   4      table-lookup                        11     0
30    377   1                                           3     9
31    378   2      no zeros, zerofill(1)                2     9
32    380   8      no zeros                             2     9
33    388   4      always zero                          2     9
34    392   4      table-lookup                        12     0
35    396   4      no zeros, zerofill(1)               13     9
36    400   4      no zeros, zerofill(1)                2     9
37    404   1                                           2     9
38    405   4      no zeros                             2     9
39    409   4      always zero                          2     9
40    413   4      no zeros                             2     9
41    417   4      always zero                          2     9
42    421   4      no zeros                             2     9
43    425   4      always zero                          2     9
44    429   20     no empty                             3     9
45    449   30     no empty                             3     9
46    479   1                                          14     4
47    480   1                                          14     4
48    481   79     no endspace, no empty               15     9
49    560   79     no empty                             2     9
50    639   79     no empty                             2     9
51    718   79     no endspace                         16     9
52    797   8      no empty                             2     9
53    805   1                                          17     1
54    806   1                                           3     9
55    807   20     no empty                             3     9
56    827   4      no zeros, zerofill(2)                2     9
57    831   4      no zeros, zerofill(1)                2     9

Les informations affichées par myisampack sont décrites ici.

- normal

Le nombre de colonnes pour lesquelles aucune compression n'est utilisée.

- empty-space

Le nombre de colonnes dont les valeurs ne contiennent que des octets : elles n'occuperont plus qu'un octet.

- empty-zero

Le nombre de colonnes dont les valeurs ne contiennent que des zéros : elles n'occuperont plus qu'un octet.

- empty-fill

Le nombre de colonnes de type entier qui n'occupent pas la totalité de l'espace de leur type. Elles seront réduites en taille (par exemple, une colonne de type INTEGER sera transformée en MEDIUMINT).

- pre-space

Le nombre de colonnes de nombres à virgule flottante qui ont des valeurs stockées avec des espaces initiaux. Dans ce cas, chaque valeur va contenir le nombre d'espaces initial.

- end-space

Le nombre de colonnes qui ont de nombreux espaces terminaux. Dans ce cas, chaque valeur va contenir un compte du nombre d'espaces terminaux.

- table-lookup

La colonne n'a que quelques valeurs différentes, qui seront converties en une colonne de type ENUM avant une compression de type Huffman.

- zero

Le nombre de colonnes pour lesquelles toutes les valeurs sont zéro.

- Original trees

Le nombre initial d'arbres Huffman.

- After join

Le nombre d'arbres Huffman distincts obtenus après avoir joint les arbres pour économiser de l'espace d'entête.

Après la compression d'une table, myisamchk -dvv affiche des informations supplémentaires pour chaque champ.

- Type

Le type de fichier peut contenir les informations suivantes.

- constant

Toutes les lignes ont la même valeur.

- no endspace

Ne stocke pas les espaces finals.

- no endspace, not_always

Ne stocke pas les espaces finals et ne compresse pas les espaces finals pour toutes les valeurs.

- no endspace, no empty

Ne stocke pas les espaces finals. Ne stocke pas les valeurs vides.

- table-lookup

La colonne a été convertie en ENUM.

- zerofill(n)

Les n chiffres significatifs sont toujours 0, et n'ont pas été stockés.

- no zeros

Ne stocke pas les zéros.

- always zero

Les valeurs 0 sont stockées sur un octet.

- Huff tree

L'arbre Huffman associé au champ.

- Bits

Le nombre de bits utilisés par l'arbre Huffman.

Après la compression de pack_isam/myisampack vous devez exécuter la commande isamchk/myisamchk pour recréer l'index. À ce moment, vous pouvez aussi trier les blocs d'index et créer des statistiques nécessaires pour l'optimiseur MySQL :

shell> myisamchk -rq --sort-index --analyze tbl_name.MYI

Une procédure similaire s'applique aux tables ISAM. Après avoir utilisé pack_isam, utilisez isamchk pour recréer les index :

shell> isamchk -rq --sort-index --analyze tbl_name.ISM

Après avoir installé la table compressée dans un dossier de données MySQL, vous devez exécuter la commande mysqladmin flush-tables pour forcer mysqld à utiliser cette nouvelle table.

Si vous voulez décompresser une table compressée, vous pouvez le faire avec l'option --unpack de la commande isamchk ou myisamchk.

8-3 - mysql, l'outil en ligne de commande

mysql est un simple script SQL (qui exploite GNU readline). Il supporte une utilisation interactive et non interactive. Lorsqu'il est utilisé interactivement, les résultats des requêtes sont présentés sous la forme d'une table au format ASCII. Lorsqu'il est utilisé non interactivement, par exemple, comme filtre, le résultat est fourni au format de liste avec séparation par tabulation (le format d'affichage peut être modifié en utilisant les options de ligne de commande).

Si vous avez des problèmes liés à des insuffisances de mémoire avec le client, utilisez l'option --quick! Cela force mysql à utiliser mysql_use_result() plutôt que mysql_store_result() pour lire les résultats.

Utiliser mysql est très simple. Il suffit de le démarrer comme ceci :

shell> mysql db_name

ou :

shell> mysql --user=user_name --password=your_password db_name

Tapez une commande SQL, puis terminez-la avec ';', '\g' ou '\G', et finissez avec entrée.

Vous pouvez exécuter un script avec :

shell> mysql db_name < script.sql > output.tab

mysql supporte les options suivantes.

- --help, -?

Affiche cette aide et quitte.

- --batch, _B

Affiche les résultats avec une tabulation comme résultat, et chaque ligne avec une nouvelle ligne. N'utilise pas l'historique.

- --character-sets-dir=path

Le dossier où les jeux de caractères sont créés. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --compress, _C

Utilise la compression avec le protocole client/serveur.

- --database=db_name, -D db_name

La base de données à utiliser. C'est particulièrement pratique dans le fichier d'options my.cnf.

- --debug[=debug_options], -# [debug_options]

Génère un log de débogage. La chaîne debug_options vaut souvent 'd:t:o,file_name'. Par défaut, la valeur est 'd:t:o,/tmp/mysql.trace'.

- --debug-info, -T

Affiche des informations de débogage lorsque le programme se termine.

- --default-character-set=charset

Configure le jeu de caractères par défaut. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --execute=statement, -e statement

Exécute une commande et quitte. Le résultat est au format de l'option --batch.

- --force, f

Continue même si vous recevez une erreur SQL.

- --host=host_name, -h host_name

Connexion avec l'hôte indiqué.

- --html, H

Produit un résultat au format HTML.

- --ignore-space, i

Ignore les espaces après les noms de fonctions. L'effet de cette commande est décrit dans la discussion sur IGNORE_SPACE de la section Section 5.2.2, « Le mode SQL du serveur ».

- --local-infile[={0|1}]

Active ou désactive la possibilité d'utiliser la commande LOCAL pour LOAD DATA INFILE. Sans valeur, cette option active LOCAL. Elle peut être configurée avec --local-infile=0 ou --local-infile=1 pour explicitement activer ou désactiver LOCAL. Activer LOCAL n'a pas d'effet si le serveur ne le supporte pas de son côté.

- --named-commands, -G

Les commandes nommées sont activées. Utilisez la forme \* uniquement, ou utilisez les commandes nommées au début d'une ligne se terminant par un point-virgule (';'). Depuis la version 10.9, le client démarre avec cette option activée par défaut. Avec l'option -g, le format long des commandes va continuer à fonctionner.

- --no-auto-rehash, -A

Pas de rehashage automatique. Cette option fait que mysql se lance plus rapidement, mais vous devez utiliser la commande rehash si vous voulez utiliser la complétion de nom de tables.

- --no-beep, -b

Ne fait pas de bip, lorsqu'une erreur survient.

- --no-named-commands, -g

Les commandes nommées sont désactivées. Utilisez uniquement la forme \* ou bien utilisez les commandes nommées en début de ligne, et terminez-la avec un point-virgule (';'). Depuis MySQL 3.23.22, mysql démarre avec cette option activée par défaut ! Cependant, même avec cette option, les formats de commandes longues fonctionneront sur la première ligne.

- --no-pager

Désactive le système de page, et affiche directement dans la sortie standard. Plus de détails dans la section Section 8.3.1, « Commandes mysql ».

- --no-tee

Désactive le fichier de sortie. Voyez l'aide interactive (\h). Plus de détails dans la section Section 8.3.1, « Commandes mysql ».

- --one-database, O

Ne modifie que la base par défaut. C'est pratique pour éviter les modifications dans les autres bases dans le fichier de logs.

- --pager[=command]

Type d'affichage. Par défaut, la variable d'environnement ENV vaut PAGER. Les pagineurs valides sont less, more, cat [> filename], etc. Voyez l'aide interactive (\h). Cette option n'est pas fonctionnelle en mode batch. Les pagineurs ne fonctionnent qu'avec Unix. Plus de détails dans la section Section 8.3.1, « Commandes mysql ».

- --password[=password], -p[password]

Le mot de passe utilisé lors de la connexion sur le serveur. S'il n'est pas donné en ligne de commande, il sera demandé interactivement. Notez que si vous utilisez la forme courte -p, vous ne devez pas laisser d'espace entre l'option et le mot de passe.

- --port=port_num, -P port_num

Le numéro de port TCP/IP pour la connexion.

- --prompt=format_str

Modifie le format de l'invite de commandes (prompt). Par défaut, c'est mysql>. Les séquences spéciales sont présentées dans la section Section 8.3.1, « Commandes mysql ».

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Spécifie le protocole de connexion à utiliser. Nouveau en MySQL version 4.1.

- --quick, -q

Ne met pas en cache le résultat, et l'affiche ligne par ligne. C'est plus lent pour le serveur, si le résultat est interrompu. N'utilise pas le fichier d'historique.

- --raw, -r

Écrit les valeurs des colonnes sans les conversions de protections. Utilisé en mode --batch

- --reconnect

Si la connexion est perdue, essaie de se reconnecter automatiquement au serveur, juste une fois. Pour supprimer la reconnexion automatique, utilisez --skip-reconnect. Nouveau en MySQL 4.1.0.

- --safe-updates, --i-am-a-dummy, -U

N'autorise que les commandes UPDATE et DELETE qui utilisent des clés. Voir plus bas pour des informations sur cette option. Vous pouvez annuler cette option si vous l'avez dans le fichier d'option my.cnf en utilisant la syntaxe --safe-updates. Voyez la section Section 8.3.3, « Conseils avec mysql » pour plus d'informations sur cette option.

- --silent, -s

Mode très silencieux.

- ----skip-column-names, -N

N'écrit pas les noms de colonnes dans les résultats.

- --skip-line-numbers, -L

N'écrit pas les numéros de lignes dans les erreurs. Très pratique lorsque vous voulez comparer des résultats qui incluent des messages d'erreur.

- --socket=path, -S path

Le fichier de sockets à utiliser pour la connexion.

- --table, -t

Affichage au format de table. C'est le mode par défaut pour le mode non batch.

- --tee=file_name

Ajoute tout dans le fichier de sortie. Voyez l'aide interactive (\h). Ne fonctionne pas en mode batch. Cette option est détaillée dans Section 8.3.1, « Commandes mysql ».

- --unbuffered, -n

Vide le buffer de requête après chaque requête.

- --user=user_name, -u user_name

Nom d'utilisateur pour la connexion, si ce n'est pas l'utilisateur Unix courant.

- --verbose, -v

Affichage plus détaillé (-v -v -v indique le format d'affichage de table).

- --version, -V

Affiche la version et quitte.

- --vertical, -E

Affiche le résultat d'une requête verticalement. Sans cette option, vous pouvez aussi obtenir ce format en terminant votre requête avec \G.

- --wait, -w

Attend et retente si la connexion s'interrompt, au lieu de quitter.

- --xml, -X

Affiche le résultat au format XML.

Vous pouvez aussi spécifier les variables suivantes avec la syntaxe --var=option.

- connect_timeout

Nombre de secondes avant que la connexion n'expire. Valeur par défaut : 0.

- max_allowed_packet

Taille maximale du paquet de communication avec le serveur. Valeur par défaut : 16777216.

- max_join_size

Limite automatique pour les commandes de jointure avec l'option --i-am-a-dummy. Valeur par défaut : 1 000 000 (un million).

- net_buffer_length

Buffer pour les communications TCP/IP et socket. Valeur par défaut : 16 ko.

- select_limit

Limite automatique pour les commandes SELECT avec l'option --i-am-a-dummy Valeur par défaut : 1000.

Il est aussi possible de configurer les variables en utilisant --set-variable=var_name=value ou la syntaxe -O var_name=value. Cependant, cette syntaxe est obsolète depuis MySQL 4.0.

Sous Unix, le client mysql écrit l'historique des requêtes dans un fichier. Par défaut, le fichier de requêtes s'appelle .mysql_history, et il est créé dans votre dossier racine. Pour spécifier un fichier différent, modifiez la variable d'environnement MYSQL_HISTFILE.

Si vous ne voulez pas entretenir un fichier d'historiques, supprimez .mysql_history s'il existe, puis utiliser l'une des techniques suivantes.

- Donnez à MYSQL_HISTFILE la valeur de /dev/null. Pour que cela soit pris en compte à chaque redémarrage, ajoutez cette ligne à votre script de démarrage.

- Faites un lien symbolique depuis .mysql_histfile vers /dev/null :

shell> ln -s /dev/null $HOME/.mysql_history

Il suffira de faire cela une seule fois.

8-3-1 - Commandes mysql

mysql envoie des requêtes SQL que vous avez saisies au serveur, pour exécution. Il y a aussi des commandes que le client mysql interprète. Si vous tapez 'help' en ligne de commande, mysql va afficher les commandes qu'il supporte :

mysql> help

MySQL commands:
?         (\h)    Synonym for `help`.
clear     (\c)    Clear command.
connect   (\r)    Reconnect to the server.
Optional arguments are db and host.
delimiter (\d)    Set query delimiter.
edit      (\e)    Edit command with $EDITOR.
ego       (\G)    Send command to mysql server,
display result vertically.
exit      (\q)    Exit mysql. Same as quit.
go        (\g)    Send command to mysql server.
help      (\h)    Display this help.
nopager   (\n)    Disable pager, print to stdout.
notee     (\t)    Don't write into outfile.
pager     (\P)    Set PAGER [to_pager].
Print the query results via PAGER.
print     (\p)    Print current command.
prompt    (\R)    Change your mysql prompt.
quit      (\q)    Quit mysql.
rehash    (\#)    Rebuild completion hash.
source    (\.)    Execute an SQL script file.
Takes a file name as an argument.
status    (\s)    Get status information from the server.
system    (\!)    Execute a system shell command.
tee       (\T)    Set outfile [to_outfile].
Append everything into given outfile.
use       (\u)    Use another database.
Takes database name as argument.

Les commandes edit, nopager, pager et system ne fonctionnent que sous Unix.

La commande status donne des détails sur la connexion et le serveur utilisés. Si vous fonctionnez en mode --safe-updates, status va aussi afficher les valeurs des variables de mysql qui affectent vos requêtes.

Pour enregistrer les requêtes et leur résultat, utilisez la commande tee. Toutes les données affichées à l'écran seront ajoutées à un fichier donné. Cela peut être très pratique pour déboguer. Vous pouvez activer cette fonctionnalité en ligne de commande, avec l'option --tee, ou interactivement avec la commande tee. Le fichier tee peut être désactivé interactivement avec la commande notee. Exécuter tee à nouveau réactive le log. Sans paramètre, le fichier précédent sera utilisé. Notez que tee envoie les requêtes dans le fichier après chaque commande, juste avant que mysql ne l'affiche.

La lecture et la recherche dans les résultats de requêtes en mode interactif est possible en utilisant les programmes Unix less, more, ou tout autre programme similaire, avec l'option --pager. Si vous ne spécifiez pas de valeur d'option, mysql regarde la valeur de la variable d'environnement PAGER, et utilise ce pager. Vous pouvez aussi l'activer interactivement avec la commande pager et la désactiver avec nopager. La commande prend un argument optionnel : s'il est fourni, le programme de pager indiqué sera utilisé. Sinon, le pager sera celui indiqué en ligne de commande, ou stdout si aucun pager n'était indiqué.

La pagination de sortie ne fonctionne que sous Unix, car elle utilise la fonction popen(), qui n'existe pas sous Windows. Pour Windows, la commande tee peut être utilisée pour sauver le résultat, même si ce n'est pas aussi pratique que pager pour naviguer dans le résultat.

Quelques conseils avec la commande pager :

- vous pouvez l'utiliser pour écrire les résultats dans un fichier :

mysql> pager cat > /tmp/log.txt

Vous pouvez lui passer les options que la page comprendra :

mysql> pager less -n -i -S

- dans le précédent exemple, notez l'option -S. Vous la trouverez pratique pour naviguer dans des résultats très larges. Parfois, un résultat très large est difficile à lire à l'écran. L'option -S de less rend le résultat plus lisible, car vous pouvez aussi scroller horizontalement, avec les flèches de droite et de gauche. Vous pouvez aussi utiliser interactivement -S dans less pour activer ou désactiver la navigation horizontale. Pour plus d'informations, voyez le manuel de less :

shell> man less

- vous pouvez spécifier des commandes de pages très complexes :

mysql> pager cat | tee /dr1/tmp/res.txt \
| tee /dr2/tmp/res2.txt | less -n -i -S

Dans cet exemple, la commande va envoyer les résultats de la commande dans deux fichiers différents, dans deux dossiers différents, placés sur deux systèmes de fichiers montés sur /dr1 et /dr2, mais affichera toujours le résultat à l'écran via less.

Vous pouvez aussi combiner les deux fonctions ci-dessus : activer le tee, spécifier le pager 'less' et vous serez capable de naviguer dans les résultats avec le less Unix, tout en enregistrant tous les résultats dans un fichier. La différence entre le tee d'Unix utilisé avec le pager et le tee intégré du client mysql, est que le tee intégré fonctionne même si vous n'avez pas de tee Unix disponible. Le tee enregistre tout ce qui est affiché à l'écran, alors que le tee Unix utilisé avec pager n'en note pas autant. Enfin, le tee interactif est plus facile à activer et désactiver, lorsque vous souhaitez enregistrer un résultat dans un fichier, mais que vous voulez désactiver cette fonctionnalité à d'autres moments.

Depuis MySQL version 4.0.2, il est possible de modifier l'invite de commandes de mysql. La chaîne de définition de l'invite de commandes accepte les séquences suivantes :

Option

Description

\v

version de mysqld

\d

database en cours

\h

hôte MySQL

\p

port de connexion

\u

nom d'utilisateur

\U

Identifiant complet username@host

\\

'\'

\n

nouvelle ligne

\t

tabulation

\

espace

\_

espace

\R

heure 24 h (0-23)

\r

heure 12 h (1-12)

\m

minutes

\y

année sur deux chiffres

\Y

année sur quatre chiffres

\D

format de date complet

\s

secondes

\w

jour de la semaine en trois lettres (Mon, Tue...)

\P

am/pm

\o

mois au format numérique

\O

mois en trois lettres (Jan, Feb...)

\c

compteur du nombre de commandes

'\' suivi de n'importe quelle lettre représente la lettre littéralement.

Si vous spécifiez une commande prompt sans argument, mysql utilisera l'invite de commandes par défaut de mysql>.

Vous pouvez modifier l'invite de commandes comme ceci :

- utiliser la variable d'environnement MYSQL_PS1, en lui donnant la chaîne d'invite. Par exemple :

shell> export MYSQL_PS1="(\u@\h) [\d]> "

- utiliser le fichier d'options

Vous pouvez configurer l'invite de commandes prompt dans le fichier d'options MySQL, comme /etc/my.cnf ou .my.cnf, dans le groupe mysql. Par exemple :

[mysql]
prompt=(\\u@\\h) [\\d]>\\_

Dans cet exemple, notez que les antislash sont doublés. Si vous configurez l'invite de commandes prompt dans un fichier d'options, il est recommandé de doubler les antislash, lorsque vous utilisez des options. Il y a des recoupements entre les séquences protégées et les options. Ces séquences sont listées dans Section 4.3.2, « Fichier d'options my.cnf ». Ce recoupement peut vous causer des problèmes avec des antislashs uniques. Par exemple, \s sera interprété comme un espace, plutôt que comme le nombre de secondes. La valeur suivante montre comment définir une invite avec l'heure au format HH:MM:SS> :

[mysql]
prompt="\\r:\\m:\\s> "

- utiliser une option de ligne de commande

Vous pouvez utiliser l'option --prompt dans la commande mysql. Par exemple :

shell> mysql --prompt="(\u@\h) [\d]> "
(user@host) [database]>

- interactivement

Vous pouvez aussi utiliser la commande prompt (ou \R) depuis le client pour modifier interactivement l'invite de commandes. Par exemple :

mysql> prompt (\u@\h) [\d]>\_
PROMPT set to '(\u@\h) [\d]>\_'
(user@host) [database]>
(user@host) [database]> prompt
Returning to default PROMPT of mysql>
mysql>

8-3-2 - Comment exécuter des commandes SQL depuis un fichier texte

Le client mysql peut être utilisé en mode interactif comme ceci :

shell> mysql database

Toutefois, il est aussi possible de rassembler les commandes SQL dans un fichier, et d'indiquer à mysql de lire les commandes dans ce fichier. Pour faire cela, créez un fichier texte fichier_texte qui contient les commandes SQL que vous souhaitez exécuter. Puis, exécutez ce fichier avec mysql comme ceci :

shell> mysql database < fichier_texte

Vous pouvez aussi démarrer votre fichier texte avec la commande USE nom_base. Dans ce cas, il n'est pas nécessaire de spécifier le nom de la base de données dans la ligne de commande :

shell> mysql < fichier_texte

Si vous avez déjà démarré le client mysql, vous pouvez exécuter un script SQL en utilisant la commande source :

mysql> source nom_fichier;

Pour plus d'informations sur le mode batch, consultez Section 3.5, « Utilisation de mysql en mode batch ».

8-3-3 - Conseils avec mysql

Cette section décrit certaines techniques qui vous aideront à utiliser mysql plus efficacement.

8-3-3-1 - Affichage des résultats verticalement

Certaines requêtes sont bien plus lisibles une fois affichées verticalement, au lieu de horizontalement. Par exemple, si la taille du texte est bien plus grande que la largeur de l'écran, ou qu'il y a des retours à la ligne, le format vertical est préférable :

mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1\G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
reply: monty@no.spam.com
mail_to: "Thimble Smith" <tim@no.spam.com>
sbj: UTF-8
txt: >>>>> "Thimble" == Thimble Smith writes:

Thimble> Hi.  I think this is a good idea.  Is anyone familiar
Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my
Thimble> TODO list and see what happens.

Yes, please do that.

Regards,
Monty
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)

8-3-3-2 - Utilisation de l'option --safe-updates

Pour les débutants, une option de démarrage pratique est --safe-updates (ou --i-am-a-dummy, qui a le même effet). Cette option a été introduite en MySQL 3.23.11. Elle est pratique si vous avec émis des commandes DELETE FROM tbl_name, mais que vous avez oublié la clause WHERE. Normalement, une telle commande va effacer toutes les lignes de la table. Avec --safe-updates, vous pouvez effacer uniquement les lignes dont vous spécifiez les valeurs de clé pour les identifier. Cela évite les accidents.

Lorsque vous utilisez l'option --safe-updates, mysql émet l'alerte suivante lorsqu'il se connecte à MySQL :

SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=1000,
SQL_MAX_JOIN_SIZE=1000000;

Voir Section 13.5.2.8, « Syntaxe de SET ».

La commande SET a l'effet suivant.

- Vous n'êtes pas autorisé à exécuter de commandes UPDATE et DELETE à moins que vous ne spécifiiez une contrainte de clé dans la clause WHERE où que vous fournissiez une clause LIMIT, ou les deux. Par exemple :

UPDATE tbl_name SET not_key_column=# WHERE key_column=#;

UPDATE tbl_name SET not_key_column=# LIMIT 1;

- Tous les résultats importants de SELECT sont automatiquement limités à 1000, à moins que la commande n'inclue la clause LIMIT.

- Les commandes SELECT multitables qui devront étudier plus d'un million de lignes sont annulées.

Pour spécifier des limites autres que 1000 et 1 000 000, vous pouvez remplacer les maxima avec --select_limit et --max_join_size :

shell> mysql --safe-updates --select_limit=500 --max_join_size=10000

8-3-3-3 - Désactiver la reconnexion automatique de mysql

Si le client mysql perd la connexion au serveur durant l'envoi d'une requête, il va immédiatement et automatiquement essayer de se reconnecter une fois au serveur, puis essayer d'envoyer à nouveau la requête. Toutefois, même si mysql réussit à se reconnecter, l'ancienne connexion a été fermée, et tous les objets temporaires ont été perdus : tables temporaires, configuration en auto_commit, variables utilisateur et de session. Ce comportement peut se révéler dangereux pour vous, comme dans l'exemple suivant, où le serveur est stoppé, puis relancé sans que vous le sachiez :

mysql> SET @a=1;
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO t VALUES(@a);
ERROR 2006: MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    1
Current database: test

Query OK, 1 row affected (1.30 sec)

mysql> SELECT * FROM t;
+------+
| a    |
+------+
| NULL |
+------+
1 row in set (0.05 sec)

La variable utilisateur @a a été perdue, et lors de la reconnexion, elle est indéfinie. S'il est important que mysql génère une erreur lors de la perte de connexion, vous pouvez lancer le client mysql avec l'option --skip-reconnect.

8-4 - mysqladmin, administration d'un serveur MySQL

mysqladmin est un utilitaire pour exécuter des commandes d'administration. Vous pouvez l'utiliser pour vérifier la configuration du serveur, créer et effacer des bases, etc.

La syntaxe de mysqladmin est :

shell> mysqladmin [OPTIONS] command [command-option] command ...

Le mysqladmin actuel supporte les commandes suivantes.

- create databasename

Crée une nouvelle base.

- drop databasename

Efface une base et toutes ses tables.

- extended-status

Affiche un message de statut du serveur très complet.

- flush-hosts

Vide tous les hôtes mis en cache.

- flush-logs

Vide de la mémoire tous les logs.

- flush-privileges

Recharger les tables de droits (identique à la commande reload).

- flush-status

Remet à zéro les variables de statut.

- flush-tables

Vide de la mémoire toutes les tables.

- flush-threads

Vide les threads de cache. Nouveau en MySQL 3.23.16.

- kill id,id,...

Termine un thread MySQL.

- password new-password

Spécifie un nouveau mot de passe. Modifie l'ancien mot de passe en new-password pour le compte que vous utilisez lors de la connexion avec mysqladmin.

- ping

Vérifie si mysqld fonctionne ou pas.

- processlist

Affiche la liste des processus du serveur. Cela revient à la commande SHOW PROCESSLIST. Si --verbose est utilisé, le résultat est le même que SHOW FULL PROCESSLIST.

- reload

Recharge les tables de droits.

- refresh

Vide de la mémoire toutes les tables, puis ferme et rouvre les fichiers de logs.

- shutdown

Éteint le serveur.

- slave-start

Démarre l'esclave de réplication.

- status

Affiche le message de statut court du serveur.

- slave-stop

Éteint l'esclave de réplication.

- variables

Affiche les variables disponibles.

- version

Affiche la version du serveur.

Toutes les commandes peuvent être réduites à leur préfixe simple. Par exemple :

shell> mysqladmin proc stat
+----+-------+-----------+----+-------------+------+-------+------+
| Id | User  | Host      | db | Command     | Time | State | Info |
+----+-------+-----------+----+-------------+------+-------+------+
| 6  | monty | localhost |    | Processlist | 0    |       |      |
+----+-------+-----------+----+-------------+------+-------+------+
Uptime: 10077  Threads: 1  Questions: 9  Slow queries: 0
Opens: 6 Flush tables: 1  Open tables: 2
Memory in use: 1092K  Max memory used: 1116K

La commande mysqladmin status liste les colonnes suivantes.

- Uptime

Nombre de secondes de vie du serveur MySQL.

- Threads

Nombre de threads actifs (clients).

- Questions

Nombre de questions reçues des clients depuis le démarrage de mysqld.

- Slow queries

Nombre de requêtes qui ont pris plus de long_query_time secondes. Voir Section 5.9.5, « Le log des requêtes lentes ».

- Opens

Combien de tables sont ouvertes par mysqld.

- Flush tables

Nombre de commandes flush ..., refresh et reload.

- Open tables

Nombre de tables qui sont ouvertes actuellement.

- Memory in use

Mémoire allouée directement par mysqld (uniquement disponible si MySQL a été compilé avec l'option --with-debug=full).

- Maximum memory used

Maximum de mémoire allouée directement par mysqld (uniquement disponible si MySQL a été compilé avec l'option --with-debug=full).

Si vous exécutez mysqladmin shutdown en vous connectant à un serveur local, avec un fichier de sockets Unix, mysqladmin va attendre que le fichier de processus du serveur soit supprimé, pour s'assurer que le serveur est bien arrêté.

mysqladmin supporte les options suivantes.

- --help, -?

Affiche le message d'aide et quitte.

- --character-sets-dir=path

Le dossier où les jeux de caractères sont stockés. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --compress, -C

Compresse toutes les informations entre le client et le serveur, si les deux le supportent.

- --count=#, -c #

Le nombre d'itérations à faire. Cela fonctionne uniquement avec --sleep (-i).

- --debug[=debug_options], -# [debug_options]

Écrit un log de débogage. La chaîne debug_options est souvent 'd:t:o,file_name'. La valeur par défaut est 'd:t:o,/tmp/mysqladmin.trace'.

- --force, -f

Ne demande pas de confirmation pour la commande drop database. Avec des commandes multiples, continue même si une erreur survient.

- --host=host_name, -h host_name

Connexion au serveur MYSQL avec le nom d'hôte donné.

- --password[=password], -p[password]

Le mot de passe utilisé lors de la connexion sur le serveur. S'il n'est pas donné en ligne de commande, il sera demandé interactivement. Notez que si vous utilisez la forme courte -p, vous ne devez pas laisser d'espace entre l'option et le mot de passe.

- --port=port_num, -P port_num

Le numéro de port TCP/IP pour la connexion.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Spécifie le protocole de connexion à utiliser. Nouveau en MySQL 4.1.

- --relative, -r

Affiche la différence entre la valeur courante et la valeur précédente, lorsqu'utilisé avec l'option -i. Actuellement, cette option fonctionne avec la commande extended-status.

- --silent, -s

Mode très silencieux.

- --sleep=delay, -i delay

Exécute les commandes encore et encore, avec delay secondes entre deux.

- --socket=path, -S path

Le fichier de sockets à utiliser pour la connexion.

- --user=user_name, -u user_name

Nom d'utilisateur pour la connexion, si ce n'est pas l'utilisateur Unix courant.

- --verbose, -v

Affichage plus détaillé (-v -v -v indique le format d'affichage de table).

- --version, -V

Affiche la version et quitte.

- --vertical, -E

Similaire à --relative, mais effectue un affichage vertical.

- --wait[=#], -w[#]

Si la connexion n'a pu être établie, attend et ressaie au lieu d'abandonner. Si une valeur est spécifiée, elle indique le nombre de tentatives. La valeur par défaut est une fois.

Vous pouvez aussi configurer ces options avec la syntaxe --var_name=value.

- connect_timeout

Le nombre de secondes avant une expiration de connexion. (Par défaut, 0.)

- shutdown_timeout

Le nombre de secondes d'attente de l'extinction. (Par défaut, 0.)

Il est aussi possible de configurer les variables en utilisant --set-variable=var_name=value ou la syntaxe -O var_name=value. Cependant, cette syntaxe est obsolète depuis MySQL 4.0.

8-5 - mysqlbinlog, Exécuter des requêtes dans le log binaire

Les fichiers de logs sont écrits dans un format binaire. Vous pouvez examiner le log binaire avec l'utilitaire mysqlbinlog. Il est disponible depuis MySQL 3.23.14.

Appelez mysqlbinlog comme ceci :

shell> mysqlbinlog [options] log-file ...

Par exemple, pour afficher le contenu du fichier de logs binaire binlog.000003, utilisez cette commande :

shell> mysqlbinlog binlog.0000003

Le résultat est toutes les requêtes contenues dans le fichier de logs binaire binlog.000003, avec différentes informations (durée de la requête, identifiant du thread qui l'a émise, timestamp d'émission, etc.).

Normalement, vous utilisez mysqlbinlog pour lire les fichiers de logs directement, et les envoyer au serveur MySQL local. Il est aussi possible de lire le fichier binaire sur un serveur distant en utilisant l'option --read-from-remote-server. Cependant, c'est une technique abandonnée, car nous préférons rendre plus simple l'utilisation des logs binaires sur un serveur MySQL local.

Lorsque vous lisez des logs binaires distants, les options de connexion peuvent être données pour indiquer comment se connecter au serveur, mais ils sont ignorés à moins que vous ne spécifiiez aussi l'option --read-from-remote-server. Ces options sont --host, --password, --port, --protocol, --socket et --user.

Vous pouvez aussi utiliser mysqlbinlog pour relayer des fichiers de logs écrits par un serveur esclave, dans une architecture de réplication. Les logs de relais sont au même format que le log binaire.

Le log binaire est présenté en détail dans la section Section 5.9.4, « Le log binaire ».

mysqlbinlog supporte les options suivantes.

- --help, -?

Affiche cette aide et quitte.

- --database=db_name, -d db_name

Limite les lignes à cette base de données (log local uniquement).

- --force-read, -f

Continue même si vous obtenez une erreur SQL.

- --host=host_name, -h host_name

Lit le log binaire depuis le serveur MySQL distant.

- --local-load=path, -l path

Prépare les fichiers temporaires destinés aux commandes LOAD DATA INFILE dans le dossier spécifié.

- --offset=N, -o N

Ignore les N premières lignes.

- --password[=password], -p[password]

Le mot de passe utilisé lors de la connexion sur le serveur. S'il n'est pas donné en ligne de commande, il sera demandé interactivement. Notez que si vous utilisez la forme courte -p, vous ne devez pas laisser d'espace entre l'option et le mot de passe.

- --port=port_num, -P port_num

Le numéro de port TCP/IP pour la connexion.

- --position=N, -j N

Commence la lecture dans le log binaire à la position N.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Spécifie le protocole de connexion à utiliser. Nouveau en MySQL version 4.1.

- --read-from-remote-server, -R

Lit le fichier de logs binaire depuis un serveur MySQL. Les options de connexion distantes seront ignorées à moins que cette option ne soit donnée. Ces options sont --host, --password, --port, --protocol, --socket et --user.

- --result-file=name, -r name

Export direct vers le fichier spécifié.

- --short-form, -s

Affiche uniquement les commandes du log, sans les informations supplémentaires.

- --socket=path, -S path

Le fichier de sockets à utiliser pour la connexion.

- --user=user_name, -u user_name

Le nom d'utilisateur MySQL lors de la connexion à distance.

- --version, -V

Affiche la version et quitte.

Vous pouvez aussi configurer les variables suivantes avec l'option --var_name=value.

- open_files_limit

Spécifie le nombre de pointeurs de fichier à réserver.

Vous pouvez envoyer le résultat de mysqlbinlog vers un client mysql avec un pipe : c'est une technique pour restaurer le serveur après un crash (voir Section 5.7.1, « Sauvegardes de base de données ») :

shell> mysqlbinlog hostname-bin.000001 | mysql

ou :

shell> mysqlbinlog hostname-bin.[0-9]* | mysql

Vous pouvez aussi rediriger le résultat de mysqlbinlog dans un fichier texte, modifier ce fichier (supprimer les requêtes qui vous gênent), puis exécuter ces requêtes, depuis le fichier, avec mysql. Après édition du fichier, exécutez les commandes qu'il contient comme d'habitude, avec le programme mysql.

mysqlbinlog dispose de l'option --position qui affiche les requêtes du log binaire à partir de la position spécifiée.

Si vous avez plus d'un fichier de logs binaire à exécuter sur le serveur MySQL, la méthode sûre est de tout faire avec la même connexion MySQL. Voici la méthode dangereuse :

shell> mysqlbinlog hostname-bin.000001 | mysql # DANGER!!
shell> mysqlbinlog hostname-bin.000002 | mysql # DANGER!!

Cela va causer des problèmes si le premier log contient des commandes de type CREATE TEMPORARY TABLE et que le second contient des requêtes d'utilisation de cette table : lorsque le premier mysql termine son exécution, il va détruire la table, et le second va rencontrer des erreurs « unknown table ».

Pour éviter cela, utilisez une seule connexion, surtout si vous utilisez des tables temporaires. Voici deux méthodes possibles :

shell> mysqlbinlog hostname-bin.000001 hostname-bin.000002 | mysql

la seconde méthode :

shell> mysqlbinlog hostname-bin.000001 >  /tmp/statements.sql
shell> mysqlbinlog hostname-bin.000002 >> /tmp/statements.sql
shell> mysql -e "source /tmp/statements.sql"

Depuis MySQL 4.0.14, mysqlbinlog peut préparer des requêtes valides pour mysql, afin d'il utilise la commande LOAD DATA INFILE depuis le log binaire. Comme le log contient les données à charger (c'est vrai depuis MySQL 4.0 ; MySQL 3.23 n'inscrivait pas les données à charger dans le log binaire, et le fichier original était nécessaire pour exécuter le contenu du log binaire), mysqlbinlog va copier ces données dans un fichier temporaire et émettre une commande LOAD DATA INFILE pour que mysql le charge. Le dossier du fichier temporaire est le dossier temporaire par défaut : il peut être modifié avec l'option local-load de mysqlbinlog.

Comme mysqlbinlog convertit les commandes LOAD DATA INFILE en commandes LOAD DATA LOCAL INFILE (c'est-à-dire qu'il ajouteLOCAL), le client et le serveur que vous utilisez pour traiter les commandes doivent être configurés pour autoriser l'option LOCAL. Voir Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL ».

ATTENTION : lorsque vous exécutez mysqlbinlog sur un fichier binaire, il va créer un fichier temporaire pour chaque commande LOAD DATA INFILE. Ces fichiers ne seront pas automatiquement effacés, car vous en aurez besoin lorsque vous exécuterez les commandes SQL générées. Il faudra les effacer manuellement lorsque vous n'en aurez plus besoin. Les fichiers portent le nom de temporary-dir/original_file_name-#-#.

Dans le futur, nous allons corriger ce problème, en permettant à mysqlbinlog de se connecter directement au serveur mysqld. Dans ce cas, nous pourrons supprimer tranquillement les fichiers de logs, lorsqu'ils auront été utilisés.

Avant MySQL 4.1, mysqlbinlog ne pouvait pas préparer de log SQL pour mysql lorsque le log binaire contenait des requêtes de différents threads, utilisant des tables temporaires de même nom, si les requêtes étaient mélangées. Ceci est corrigé en MySQL 4.1.

8-6 - mysqlcc, MySQL Control Center

mysqlcc, MySQL Control Center, est un client portable qui fournit une interface graphique (GUI) au serveur MySQL. Il supporte l'utilisation interactive, y compris la coloration syntaxique et la complétion. Il permet de gérer les tables et bases, et d'administrer le serveur.

Actuellement, mysqlcc fonctionne sur Windows et Linux.

mysqlcc n'est pas inclus avec les distributions MySQL, mais il peut être téléchargé séparément à http://dev.mysql.com/downloads/. Actuellement, mysqlcc fonctionne sur Windows et Linux.

Lancez mysqlcc en double-cliquant sur son icône en environnement graphique. En ligne de commande, utilisez ceci :

shell> mysqlcc [options]

mysqlcc supporte les options suivantes.

- --help, -?

Affiche cette aide.

- --blocking_queries, -b

Utilise les requêtes bloquantes.

- --compress, -C

Utilise la compression avec le protocole client/serveur.

- --connection_name=name, -c name

Synonyme de --server.

- --database=db_name, -d db_name

Base de données à utiliser. C'est généralement utile dans un fichier d'options.

- --history_size=#, -H #

Taille de l'historique de la fenêtre de requête.

- --host=host_name, -h host_name

Hôte de connexion.

- --local-infile[={0|1}]

Active ou désactive les fonctionnalités LOCAL de LOAD DATA INFILE. Sans valeur, cette option active LOCAL. LOCAL peut être spécifié sous la forme --local-infile=0 ou --local-infile=1 pour être désactivée ou activée. Activer LOCAL n'a pas d'effet si le serveur ne le supporte pas.

- --password[=password], -p[password]

Le mot de passe lors de la connexion au serveur. Si le mot de passe n'est pas donné en ligne de commande, il vous sera demandé. Notez que si vous utilisez la forme courte -p, vous ne devez pas mettre d'espace entre l'option et le mot de passe.

- --plugins_path=name, -g name

Chemin du dossier de module de MySQL Control Center.

- --port=port_num, -P port_num

Numéro de port TCP/IP pour la connexion.

- --query, -q

Ouvre une fenêtre de requête au démarrage.

- --register, -r

Ouvre la fenêtre de dialogue 'Register Server'.

- --server=name, -s name

Nom de la connexion de MySQL Control Center.

- --socket=path, -S path

Fichier de sockets à utiliser pour la connexion.

- -y, --syntax

Active la coloration syntaxique et la complétion.

- --syntax_file=name, -Y name

Fichier de syntaxe pour la complétion.

- --translations_path=name, -T name

Chemin jusqu'au dossier de traductions de MySQL Control Center.

- --user=user_name, -u user_name

Nom d'utilisateur.

- --version, -V

Affiche la version.

Vous pouvez spécifier les variables suivantes avec l'option -O ou --set-variable.

- connect_timeout

Nombre de secondes avant que la connexion expire (valeur par défaut 0).

- max_allowed_packet

Taille maximale des paquets à échanger avec le serveur (valeur par défaut 16777216).

- max_join_size

Limite automatique du nombre de lignes dans une jointure avec l'option --safe-updates (valeur par défaut 1 000 000).

- net_buffer_length

Buffer de communication TCP/IP (valeur par défaut 16384).

- select_limit

Limite automatique pour les commandes SELECT avec l'option --safe-updates (valeur par défaut 1000).

Notez que les syntaxes --set-variable=name=value et -O name=value sont obsolètes depuis MySQL 4.0. Utilisez --name=value.

8-7 - Utiliser mysqlcheck pour l'entretien et la réparation

Vous pouvez utiliser mysqlcheck comme outil d'entretien et de réparation pour les tables MyISAM. mysqlcheck est disponible depuis MySQL version 3.23.38.

mysqlcheck est similaire à myisamchk, mais il fonctionne différemment. mysqlcheck doit être utilisé lorsque le serveur mysqld fonctionne, alors que myisamchk doit être utilisé lorsque le serveur ne fonctionne pas. L'intérêt est que vous n'avez plus besoin d'interrompre le serveur pour vérifier ou réparer vos tables.

mysqlcheck utilise les commandes du serveur MySQL CHECK, REPAIR, ANALYZE et OPTIMIZE, d'une manière pratique pour l'utilisateur.

Il y a trois façons différentes d'utiliser mysqlcheck :

shell> mysqlcheck [options] db_name [tables]
shell> mysqlcheck [options] --databases DB1 [DB2 DB3...]
shell> mysqlcheck [options] --all-databases

Il peut aussi être utilisé comme mysqldump lorsqu'il faut choisir les bases et tables à traiter.

mysqlcheck dispose d'une fonctionnalité spéciale, comparé aux autres clients : le comportement par défaut, c'est-à-dire la vérification des tables, peut être modifiée en renommant le fichier binaire. Si vous voulez avoir un fichier qui répare les tables par défaut, il suffit de copier mysqlcheck sur votre disque, et de l'appeler mysqlrepair, ou bien, de faire un lien symbolique sur l'exécutable et de l'appeler mysqlrepair. Si vous appelez mysqlrepair, il va réparer les tables par défaut.

Les noms que vous pouvez utiliser pour que mysqlcheck réparer automatiquement les tables sont :

mysqlrepair

L'option par défaut est --repair

mysqlanalyze

L'option par défaut est --analyze

mysqloptimize

L'option par défaut est --optimize

Les options disponibles pour mysqlcheck sont listées ici. Vérifiez que votre version les supporte avec la commande mysqlcheck --help.

- -?, --help

Affiche ce message d'aide, et termine.

- --all-databases, -A

Vérifie toutes les bases. C'est la même chose que --databases dans toutes les bases sélectionnées.

- --all-in-1, -1

Au lieu de faire une requête par table, exécute toutes les requêtes dans une requête, séparément pour chaque base. Les noms de tables seront séparés par une virgule.

- --analyze, -a

Analyse les tables indiquées.

- --auto-repair

Si une table vérifiée est corrompue, la corrige automatiquement. La réparation sera faite après la vérification de toutes les tables, si des tables corrompues ont été découvertes.

- --character-sets-dir=...

Dossier contenant le jeu de caractères. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --check, -c

Vérifie les tables en erreur.

- --check-only-changed, -C

Vérifie uniquement les tables qui ont été modifiées depuis la dernière modification, ou qui n'ont pas été correctement fermées.

- --compress

Utiliser la compression du protocole client/serveur.

- --databases, -B

Pour tester plusieurs bases de données. Notez que la différence d'utilisation : dans ce cas, aucune table n'est précisée. Tous les arguments de noms sont considérés comme des noms de base.

- --debug[=debug_options], -# [debug_options]

Affiche le log de débogage. Souvent, la chaîne debug_options vaut 'd:t:o,nom_de_fichier'.

- --default-character-set=...

Spécifie le jeu de caractères par défaut. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --extended, -e

Si vous utilisez cette option avec CHECK TABLE, elle va s'assurer que la table est totalement cohérente, mais prendre un très long temps.

Si vous utilisez cette option avec REPAIR TABLE, elle va réaliser une réparation exhaustive de la table, qui peut non seulement prendre un temps très long, mais produire de nombreuses lignes erronées.

- --fast, -F

Ne vérifie que les tables qui n'ont pas été correctement fermées.

- --force, -f

Continue même si on rencontre une erreur SQL.

- --host=host_name, -h host_name

Connexion à l'hôte.

- --medium-check, -m

Plus rapide que la vérification complète, mais ne trouvera que 99.99 % de toutes les erreurs. Cela devrait être la bonne option pour la plupart des situations.

- --optimize, -o

Optimise la table.

- --password[=password], -p[password]

Le mot de passe à utiliser lors de la connexion au serveur. Si aucun mot de passe n'est fourni, il sera demandé en ligne de commande. Il ne faut pas laisser d'espace entre l'option -p et le mot de passe.

- --port=port_num, -P port_num

Le numéro de port de la connexion.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Pour spécifier le protocole à utiliser pour la connexion. Nouveau en MySQL 4.1.

- --quick, -q

Si vous utilisez cette option avec CHECK TABLE, elle va éviter que l'analyse ne traite toutes les lignes pour vérifier les mauvais liens. C'est la méthode d'analyse la plus rapide.

Si vous utilisez cette option avec REPAIR TABLE, elle va essayer de ne réparer que le fichier d'index. C'est la méthode la plus rapide pour la réparation.

- --repair, -r

Peut corriger presque tout, sauf les problèmes de doublons pour les clés uniques.

- --silent, -s

Affiche moins de messages d'erreur.

- --socket=path, -S path

Nom du fichier de sockets à utiliser pour la connexion.

- --tables

Remplace l'option --databases ou -B. Tous les arguments suivants sont considérés comme des noms de tables.

- --user=user_name, -u user_name

Nom d'utilisateur pour la connexion, si ce n'est pas l'utilisateur courant.

- --verbose, -v

Afficher des informations sur les différentes étapes.

- --version, -V

Affiche les informations de version, et termine.

8-8 - mysqldump, sauvegarde des structures de tables et les données

Utilitaire qui permet d'exporter une base ou un groupe de bases vers un fichier texte, pour la sauvegarde ou le transfert entre deux serveurs (pas nécessairement entre serveurs MySQL). L'export contiendra les requêtes SQL nécessaires pour créer la table et la remplir.

Si vous faites une sauvegarde du serveur, vous devriez aussi utiliser la commande mysqlhotcopy. Voir Section 8.9, « mysqlhotcopy, copier les bases et tables MySQL ».

Il y a plusieurs méthodes pour invoquer mysqldump :

shell> mysqldump [options] db_name [tables]
shell> mysqldump [options] --databases DB1 [DB2 DB3...]
shell> mysqldump [options] --all-databases

Si vous ne spécifiez pas de table, ou si vous utilisez l'option --databases ou --all-databases, la base de données complète sera exportée.

Vous pouvez obtenir une liste des options valides pour votre version de mysqldump avec la commande mysqldump --help.

Notez que si vous exécutez mysqldump sans l'option --quick ou --opt, mysqldump va charger la totalité du résultat en mémoire, avant de l'écrire. Cette option peut résoudre des problèmes de mémoire si vous exportez de grosses tables.

Notez que si vous utilisez une nouvelle copie du programme mysqldump, et que vous allez faire un export qui sera lu dans une vieille version de MySQL, vous ne devriez pas utiliser les options --opt et -e.

Les valeurs numériques hors des plages de validité comme -inf et inf, ainsi que NaN (not-a-number, pas un nombre) sont exportées par mysqldump comme NULL. Vous pouvez le voir dans la table suivante :

mysql> CREATE TABLE t (f DOUBLE);
mysql> INSERT INTO t VALUES(1e+111111111111111111111);
mysql> INSERT INTO t VALUES(-1e111111111111111111111);
mysql> SELECT f FROM t;
+------+
| f    |
+------+
|  inf |
| -inf |
+------+

Pour cette table, mysqldump produit l'export suivant :

--
-- Dumping data for table `t`
--

INSERT INTO t VALUES (NULL);
INSERT INTO t VALUES (NULL);

La signification de ce comportement est que si vous voulez exporter puis restaurer une table, le nouveau contenu sera peut-être différent de l'original. Notez que depuis MySQL 4.1.2 vous ne pouvez pas insérer la valeur inf dans la table, et ce comportement de mysqldump ne sera pertinent qu'avec les anciens serveurs.

mysqldump supporte les options suivantes.

- --help, -?

Affiche le message d'aide et quitte.

- --add-drop-table

Ajoute une commande drop table avant chaque requête de création de table.

- --add-locks

Ajoute une commande LOCK TABLES avant l'export de table et une commande UNLOCK TABLE après (pour accélérer les insertions dans MySQL). Voir Section 7.2.14, « Vitesse des requêtes INSERT ».

- --all-databases, -A

Exporte toutes les tables. C'est l'équivalent de l'option --databases avec toutes les bases de données sélectionnées.

- --allow-keywords

Permet la création de colonnes ayant des noms de mot réservé. Cela fonctionne en préfixant chaque nom de colonne avec le nom de la table.

- --comments[={0|1}]

Si cette option prend 0, elle supprime les informations additionnelles (comme les versions de programme, les versions d'hôte) dans les exports. L'option --skip-comments fait la même chose. Par défaut, la valeur de cette option est 1, pour conserver ces informations. Nouveau en MySQL 4.0.17.

- --compatible=name

Produit un résultat qui est compatible avec les autres bases de données, ou avec d'anciennes versions de MySQL. Les valeurs possibles de name sont mysql323, mysql40, postgresql, oracle, mssql, db2, sapdb, no_key_options, no_table_options, ou no_field_options. Pour utiliser plusieurs valeurs, séparez-les par des virgules. Ces valeurs ont la même signification que les options correspondantes de configuration du mode SQL. Voir Section 5.2.2, « Le mode SQL du serveur ».

Cette option requiert la version 4.1.0 ou plus récente. Avec les anciens serveurs, cela ne fait rien.

- --complete-insert, -c

Utilise des commandes INSERT complètes, avec les noms de colonnes.

- -C, --compress

Compresse toutes les informations entre le client et le serveur, les deux supportent la compression.

- --create-options

Inclut toutes les options spécifiques MySQL de création de tables dans les commandes CREATE TABLE. Avant MySQL 4.1.2, utilisez --all.

- --databases, -B

Pour exporter plusieurs bases de données. Notez la différence d'utilisation. Dans ce cas, aucune table n'est spécifiée. Tous les arguments de nom sont considérés comme des noms de base. Une ligne USE db_name; sera ajoutée dans l'export avant chaque base de données.

- --debug[=debug_options], -# [debug_options]

Active l'historique de débogage. La chaîne de format est généralement 'd:t:o,file_name'.

- --default-character-set=charset

Configure le jeu de caractères par défaut pour l'export. S'il n'est pas spécifié, mysqldump 10.3 (MySQL-4.1.2) ou plus récent va utiliser utf8. Les versions plus anciennes utiliseront latin1.

- --delayed

Les insertions se font avec la commande INSERT DELAYED.

- --delete-master-logs

Sur un maître de réplication, efface le log binaire une fois que l'opération d'export est faite. Cette option active automatiquement --first-slave. Elle a été ajoutée en MySQL 3.23.57 (pour MySQL 3.23) et MySQL 4.0.13 (pour MySQL 4.0).

- --disable-keys, -K

Pour chaque table, entoure les commandes d'INSERT avec les commandes /*!40000 ALTER TABLE tbl_name DISABLE KEYS */; et /*!40000 ALTER TABLE tbl_name ENABLE KEYS */;. Cela accélère les chargements du fichier d'export pour MySQL 4.0, car les index ne sont créés qu'après l'insertion. Cette option n'est effective que pour les tables MyISAM.

- --extended-insert, -e

Utilise la nouvelle syntaxe multiligne INSERT. (Cela donne des insertions plus courtes et plus efficaces).

- --fields-terminated-by=..., --fields-enclosed-by=..., --fields-optionally-enclosed-by=..., --fields-escaped-by=..., --lines-terminated-by=...

Ces options sont utilisées avec l'option -T et ont la même signification que les clauses correspondantes de la commande LOAD DATA INFILE. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

- --first-slave, -x

Verrouille toutes les tables de toutes les bases de données.

- --flush-logs, -F

Écrit tout le fichier de logs du serveur avant de commencer l'export. Notez que si vous utilisez cette option avec --all-databases (ou l'option -A), les logs seront vidés pour chaque base de données exportée.

- -f, --force,

Continue même si une erreur SQL survient durant l'export.

- --host=host_name, -h host_name

Exporte les données depuis le serveur MySQL vers l'hôte indiqué. L'hôte par défaut est localhost.

- --lock-tables, -l

Verrouille toutes les tables avant de commencer l'export. Les tables sont verrouillées avec READ LOCAL pour permettre des insertions concurrentes sur les tables MyISAM.

Notez que lorsque vous exportez des tables de bases différentes, l'option --lock-tables va verrouiller chaque base séparément. Cette option ne vous garantira pas que vos tables seront logiquement cohérentes entre les bases. Des tables de différentes bases pourraient être exportées dans des états très différents.

- --master-data

Cette option est similaire à --first-slave, mais produit aussi une commande CHANGE MASTER TO qui fait que le serveur esclave va commencer à la bonne position dans le log du maître, si vous utilisez cette exportation pour configurer initialement l'esclave.

- --no-create-db, -n

CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name; ne sera pas ajouté dans l'export. Sinon, la ligne ci-dessus sera ajoutée, si l'une des options --databases ou --all-databases a été activée.

- --no-create-info, -t

N'écrit pas les informations de création de tables (la requête CREATE TABLE).

- --no-data, -d

N'écrit aucune ligne d'informations sur la table. C'est très pratique si vous voulez simplement exporter la structure de la table.

- --opt

Identique à --quick --add-drop-table --add-locks --extended-insert --lock-tables. Vous obtiendrez l'export le plus rapide à importer dans un serveur MySQL.

- --password[=password], -p[password]

Le mot de passe à utiliser lors de la connexion au serveur. Notez que si vous utilisez l'option courte -p, vous ne devez pas laisser d'espace entre l'option et le mot de passe. Si vous spécifiez en omettant la partie '=your_pass', mysqldump vous demandera le mot de passe en ligne de commande.

- --port=port_num, -P port_num

Le port TCP/IP à utiliser avec l'hôte.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Pour spécifier le protocole de connexion à utiliser. Nouveau en MySQL 4.1.

- --quick, -q

Ne garde pas en buffer les requêtes, mais écrit immédiatement dans la sortie. Utilise mysql_use_result() pour cela.

- --quote-names, -Q

Protège les noms des tables et colonnes avec le caractère '`'.

- --result-file=file, -r file

Écrit directement dans le fichier indiqué. Cette option doit être utilisé sur MSDOS, car cela évite que la nouvelle ligne '\n' soient converties en '\n\r' (nouvelle ligne et retour chariot).

- --single-transaction

Cette option ajoute la commande SQL BEGIN avant d'exporter les données vers le serveur. C'est généralement pratique pour les tables InnoDB et le niveau d'isolation de transaction READ_COMMITTED, car ce mode va exporter l'état de la base au moment de la commande BEGIN sans bloquer les autres applications.

Lorsque vous utilisez cette option, pensez bien que seules les tables transactionnelles seront exportées dans un état cohérent, c'est-à-dire que les tables MyISAM ou HEAP qui seront exportées avec cette option, pourront changer d'état.

L'option --single-transaction a été ajoutée en version 4.0.2. Cette option est mutuellement exclusive avec l'option --lock-tables, car LOCK TABLES va valider une transaction interne précédente.

- --socket=path, -S path

Le fichier de sockets à utiliser pour les connexions locales (à localhost), qui est l'hôte par défaut.

- --skip-comments

Identique à que --comments = 0.

- --tab=path, -T path

Crée un fichier table_name.sql, qui contient les commandes SQL CREATE, et un fichier table_name.txt, qui contient les données, pour chaque table. Le format du fichier .txt est celui qui est spécifié par les options --fields-xxx et --lines--xxx. Note : cette option ne fonctionne qui si mysqldump est exécuté sur la même machine que le démon mysqld, et que le nom d'utilisateur et le groupe de mysqld (normalement l'utilisateur mysql, et le groupe mysql) ont des permissions pour créer et écrire un fichier dans le dossier que vous spécifiez.

- --tables

Remplace l'option --databases ou -B. Tous les arguments suivant les options sont considérés comme des noms de tables.

- --user=user_name, -u user_name

Le nom d'utilisateur MySQL lors de la connexion à un serveur distant.

- --verbose, -v

Mode détaillé. Affiche plus d'informations sur les faits et gestes du programme.

- --version, -V

Affiche la version du programme et quitte.

- --where='where-condition', -w 'where-condition'

Exporte uniquement les lignes sélectionnées. Notez que les guillemets sont obligatoires.

Exemples :

"--where=user='jimf'"
"-wuserid>1"
"-wuserid<1"

- -X, --xml

Exporte la base au format XML.

Vous pouvez aussi configurer les variables système suivantes avec la syntaxe --var_name=value.

- max_allowed_packet

La taille maximale du buffer pour les communications client/serveur. La valeur de cette variable peut être au maximum de 16 Mo avant MySQL 4.0, et jusqu'à 1 Go depuis MySQL 4.0. Lors de la création de commandes d'insertions multiples (avec l'option --extended-insert ou --opt), mysqldump va créer des lignes ayant une taille maximale de max_allowed_packet octets. Si vous augmentez la valeur de cette variable, assurez-vous que max_allowed_packet est assez grande dans le serveur.

- net_buffer_length

La taille initiale du buffer de communication.

Il est aussi possible de configurer les variables en utilisant --set-variable=var_name=value ou -O var_name=value. Mais cette syntaxe est obsolète depuis MySQL 4.0.

L'usage normal de mysqldump est probablement de faire des sauvegardes de bases.

mysqldump --opt database > backup-file.sql

Vous pouvez importer les données dans la base MySQL avec :

mysql database < backup-file.sql

ou

mysql -e "source /patch-to-backup/backup-file.sql" database

Cependant, il est très pratique pour remplir un autre serveur MySQL avec des informations depuis une base :

mysqldump --opt database | mysql ---host=remote-host -C database

Il est possible d'exporter plusieurs bases de données en une seule commande :

mysqldump --databases database1 [database2 ...] > my_databases.sql

Si vous souhaitez exporter toutes les bases, vous pouvez utiliser :

mysqldump --all-databases > all_databases.sql

Pour plus d'informations sur les sauvegardes, voyez Section 5.7.1, « Sauvegardes de base de données ».

8-9 - mysqlhotcopy, copier les bases et tables MySQL

mysqlhotcopy est un script Perl qui utilise LOCK TABLES, FLUSH TABLES et cp ou scp pour faire rapidement des sauvegardes de bases. C'est la méthode la plus rapide pour faire une sauvegarde. C'est aussi le moyen le plus sûr pour copier des tables et bases, mais il ne peut fonctionner que sur la machine qui contient les fichiers de données. mysqlhotcopy fonctionne uniquement sous Unix, et il ne fonctionne qu'avec les tables de type MyISAM et ISAM.

shell> mysqlhotcopy db_name [/path/to/new_directory]

shell> mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory

shell> mysqlhotcopy db_name./regex/

mysqlhotcopy supporte les options suivantes.

- -?, --help

Affiche un écran d'aide et quitte.

- --allowold

Ne pas annuler si la sauvegarde existe déjà (la renomme simplement en _old).

- --checkpoint=db_name.tbl_name

Insère un point de contrôle dans la table spécifiée (base.table).

- --debug

Active le débogage.

- --dryrun, -n

Rapporte les actions réalisées sans les faire.

- --flushlog

Vide les logs sur le disque une fois que toutes les tables sont verrouillées.

- --keepold

Ne pas effacer une sauvegarde précédente (celle qui a été renommée) lorsque c'est terminé.

- --method=#

Méthode de copie (cp ou scp).

- --noindices

Ne pas inclure les fichiers d'index complets dans la copie, pour faire des fichiers de sauvegarde plus petits et plus rapides. Les index peuvent toujours être reconstruits plus tard avec myisamchk -rq..

- -p, --password=#

Mot de passe utilisé pour la connexion au serveur.

- --port=port_num, -P port_num

Port utilisé pour la connexion au serveur.

- --quiet, -q

Mode silencieux. N'affiche que les erreurs.

- --regexp=expr

Copie toutes les bases dont le nom vérifie un masque d'expression régulière.

- --socket=path, -S path

Socket utilisée pour la connexion au serveur.

- --suffix=str

Suffixe des noms des bases copiées.

- --tmpdir=path

Dossier temporaire (au lieu de /tmp).

- --user=user_name, -u user_name

Nom d'utilisateur pour la connexion au serveur.

Vous pouvez essayer perldoc mysqlhotcopy pour avoir plus de documentation sur mysqlhotcopy.

mysqlhotcopy lit les options du groupe [client] et [mysqlhotcopy] dans le fichier d'options.

Pour être capable d'exécuter mysqlhotcopy, vous avez besoin des droits d'écriture dans le dossier de sauvegarde, et le droit de SELECT dans les tables que vous souhaitez copier, ainsi que les droits MySQL de RELOAD (pour utiliser la commande FLUSH TABLES).

shell> perldoc mysqlhotcopy

8-10 - mysqlimport, importer des données depuis des fichiers texte

mysqlimport fournit une interface en ligne de commande à la commande SQL LOAD DATA INFILE. La plupart des options de mysqlimport correspondent directement aux mêmes options de LOAD DATA INFILE. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

mysqlimport est appelé comme ceci :

shell> mysqlimport [options] database textfile1 [textfile2 ...]

Pour chaque fichier texte indiqué dans la ligne de commande, mysqlimport supprime toute extension du nom du fichier, et utilise le résultat pour déterminer le nom de la table qui va recevoir le contenu du fichier. Par exemple, pour des fichiers appelés patient.txt, patient.text et patient seront tous importés dans la table patient.

mysqlimport supporte les options suivantes.

- --help, -?

Affiche le message d'aide et quitte.

- --columns=column_list, -c column_list

Cette option prend une liste de noms de colonnes, séparés par des virgules. Ce champ est utilisé pour créer une commande LOAD DATA INFILE correcte, qui sera alors passée à MySQL.

- --compress, -C

Compresse toutes les informations entre le client et le serveur, si c'est possible.

- --debug[=debug_options], -# [debug_options]

Active le débogage. la valeur de debug_options est souvent : 'd:t:o,file_name'.

- --delete, -D

Vide la table avant d'importer le fichier texte.

- --fields-terminated-by=..., --fields-enclosed-by=..., --fields-optionally-enclosed-by=..., --fields-escaped-by=..., --lines-terminated-by=...

Ces options ont la même signification que les clauses correspondantes de LOAD DATA INFILE. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

- --force, -f

Ignore les erreurs. Par exemple, si une table n'existe pas pour un fichier texte, mysqlimport va continuer de traiter les autres fichiers. Sans --force, mysqlimport se termine dès qu'une erreur survient.

- --host=host_name, -h host_name

Importe les données sur le serveur MySQL, avec l'hôte spécifié. La valeur par défaut est localhost.

- --ignore, -i

Voir la description de --replace.

- --ignore-lines=n

Ignore les n premières lignes du fichier de données.

- --local, -L

Lit les fichiers d'entrée dans le client. Par défaut, les fichiers texte sont supposés être lus par le serveur, si vous vous connectez à localhost (qui l'hôte par défaut).

- --lock-tables, -l

Verrouille toutes les tables en écriture avant de ne traiter les fichiers texte. Cela assure que toutes les tables sont synchronisées sur le serveur.

- --password[=password], -p[password]

Le mot de passe à utiliser lors de la connexion au serveur. Notez que si vous utilisez l'option courte (-p), vous ne pouvez pas laisser d'espace entre l'option est le mot de passe. Si vous ne spécifiez pas le mot de passe avec l'option, mysqlimport va vous demander le mot de passe en ligne.

- --port=port_num, -P port_num

Le port TCP/IP utilisé avec l'hôte. Cela sert pour les connexions à des hôtes qui ne sont pas localhost, pour lesquels la socket Unix est utilisée.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Spécifie le protocole à utiliser pour se connecter. Nouveau en MySQL version 4.1.

- --replace, -r

Les options --replace et --ignore contrôlent la gestion des lignes lues envers les lignes qui existent déjà sur le serveur. Si vous spécifiez l'option --replace, les nouvelles lignes remplaceront les lignes existantes. Si vous spécifiez --ignore, les lignes qui sont en double dans une table qui dispose d'une colonne de type unique. Si vous ne spécifiez pas ces options, une erreur surviendra lorsqu'une clé en double sera trouvée, et la lecture du reste du fichier sera annulée.

- --silent, -s

Mode silencieux. N'affiche que les erreurs qui surviennent.

- --socket=path, -S path

Le fichier de sockets à utiliser lors de la connexion à localhost (qui est l'hôte par défaut).

- --user=user_name, -u user_name

Le nom de l'utilisateur MySQL à utiliser lors de la connexion au serveur MySQL. La valeur par défaut est celle de votre utilisateur Unix.

- --verbose, -v

Mode détaillé. Affiche bien plus d'informations sur les actions du programme.

- --verbose, -v

Affiche la version et quitte.

Voici un exemple d'utilisation de mysqlimport :

$ mysql --version
mysql  Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686)
$ uname -a
Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
$ mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test
$ ed
a
100     Max Sydow
101     Count Dracula
.
w imptest.txt
32
q
$ od -c imptest.txt
0000000   1   0   0  \t   M   a   x       S   y   d   o   w  \n   1   0
0000020   1  \t   C   o   u   n   t       D   r   a   c   u   l   a  \n
0000040
$ mysqlimport --local test imptest.txt
test.imptest: Records: 2  Deleted: 0  Skipped: 0  Warnings: 0
$ mysql -e 'SELECT * FROM imptest' test
+------+---------------+
| id   | n             |
+------+---------------+
|  100 | Max Sydow     |
|  101 | Count Dracula |
+------+---------------+

8-11 - Afficher les bases, tables et colonnes

mysqlshow peut être utilisé pour lister les bases qui existent, leurs tables et leurs colonnes.

Avec le programme mysql vous pouvez obtenir des informations avec la commande SHOW. Les mêmes informations sont disponibles en utilisant ces commandes directement. Par exemple, vous pouvez utiliser le client mysql. Voir Section 13.5.3, « Syntaxe de SHOW ».

mysqlshow est utilisé comme ceci :

shell> mysqlshow [OPTIONS] [database [table [column]]]

- Si aucune base n'est indiquée, toutes les bases de données sont listées.

- Si aucune table n'est nommée, toutes les tables de la base sont affichées.

- Si aucune colonne n'est nommée, toutes les colonnes et leur type sont affichés.

Notez que dans les nouvelles versions de MySQL, vous ne verrez que les bases de données, tables et colonnes pour lesquelles vous avez des droits.

Si le dernier argument contient un caractère joker shell ou SQL ('*', '?', '%' ou '_') alors seules les entités qui valident ce masque sont affichées. Si une base contient des caractères soulignés, ils doivent être protégés avec un antislash (certains shell Unix en demande même deux), afin de lister correctement les tables et les colonnes. Les '*' et '?' sont convertis en jokers SQL '%' and '_'. Cela peut causer des confusions lorsque vous essayez d'afficher des colonnes qui contiennent un souligné '_', comme c'est le cas avec mysqlshow qui ne vous affiche que les colonnes qui vérifient le masque. Ceci est facilement corrigé en ajoutant un caractère '%' en plus dans la ligne de commande (comme argument séparé).

mysqlshow supporte les options suivantes.

- --help, -?

Affiche cette aide et quitte.

- --character-sets-dir=path

Le dossier où les jeux de caractères sont créés. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --compress, -C

Utilise la compression avec le protocole client/serveur.

- --debug[=debug_options], -# [debug_options]

Génère un log de débogage. La chaîne debug_options vaut souvent 'd:t:o,file_name'. Par défaut, la valeur est 'd:t:o,/tmp/mysql.trace'.

- --default-character-set=charset

Configure le jeu de caractères par défaut. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- --host=host_name, -h host_name

Connexion avec l'hôte indiqué.

- --keys, -k

Affiche les index de la table.

- --password[=password], -p[password]

Le mot de passe utilisé lors de la connexion sur le serveur. S'il n'est pas donné en ligne de commande, il sera demandé interactivement. Notez que si vous utilisez la forme courte -p, vous ne devez pas laisser d'espace entre l'option et le mot de passe.

- --port=port_num, -P port_num

Le numéro de port TCP/IP pour la connexion.

- --protocol={TCP | SOCKET | PIPE | MEMORY}

Spécifie le protocole de connexion à utiliser. Nouveau en MySQL version 4.1.

- --socket=path, -S path

Le fichier de sockets à utiliser pour la connexion.

- --status, -i

Affiche des informations supplémentaires sur chaque table.

- --user=user_name, -u user_name

Nom d'utilisateur pour la connexion, si ce n'est pas l'utilisateur Unix courant.

- --verbose, -v

Affichage plus détaillé (-v -v -v indique le format d'affichage de table).

- --version, -V

Affiche la version et quitte.

8-12 - perror, expliquer les codes d'erreurs

Pour la plupart des erreurs système, MySQL va, en plus d'un message interne, aussi afficher un code d'erreur, dans l'un des styles suivants :

message ... (errno: #)
message ... (Errcode: #)

Vous pouvez découvrir ce que ce code d'erreur signifie soit en examinant la documentation de votre système, soit en utilisant l'utilitaire perror.

perror affiche une description pour le code d'erreur, ou, pour une erreur du gestionnaire de tables MyISAM/ISAM.

perror est appelé comme ceci :

shell> perror [options] errorcode ...

Exemple :

shell> perror 13 64
Error code  13:  Permission denied
Error code  64:  Machine is not on the network

Notez que les messages d'erreur sont dépendants du système. Un message d'erreur peut avoir différentes explications sur différents systèmes.

8-13 - L'utilitaire de remplacement de chaînes replace

L'utilitaire replace modifie les chaînes dans des fichiers. Elle utilise une machine à états finis pour rechercher d'abord les plus grandes chaînes. Elle peut être utilisée pour faire des échanges de chaînes, entre les chaînes a et b de deux fichiers file1 et file2:

shell> replace a b b a -- file1 file2 ...

Utilisez l'option -- pour indiquer où la liste de chaînes de remplacement s'arrête, et où commence la liste de fichiers.

Tout fichier nommé en ligne de commande est modifié directement : il est recommandé de faire des sauvegardes de fichiers originaux.

Si aucun fichier n'est nommé en ligne de commande, replace lit l'entrée standard, et écrit dans la sortie standard. Dans ce cas, aucune option -- n'est nécessaire.

Le programme replace sert à msql2mysql. Voir Section 24.1.1, « msql2mysql, convertit des programmes mSQL vers MySQL ».

replace supporte les options suivantes.

- -?, -I

Affiche le message d'aide et quitte.

- -# debug_options

Écrit un log de débogage. La chaîne debug_options vaut souvent 'd:t:o,file_name'.

- -s

Mode silencieux. Affiche moins d'informations sur les activités du programme.

- -v

Mode prolifique. Affiche plus d'informations sur les activités du programme.

- -V

Affiche la version, et quitte.

9 - Structure du langage

Ce chapitre présente les règles d'écriture des commandes SQL avec MySQL.

- Les valeurs littérales telles que les nombres et chaînes.

- Les identifiants de tables et colonnes.

- Les variables utilisateur et système.

- Les commentaires.

- Les mots réservés.

9-1 - Littéraux : comment écrire les chaînes et les nombres

Cette section décrit les différentes façons d'écrire les chaînes et les nombres en MySQL. Elle couvre aussi les différentes nuances et quiproquos que vous pouvez rencontrer lorsque vous manipulez ces types de données.

9-1-1 - Chaînes

Une chaîne est une séquence de caractères, entourée de guillemets simples (''') ou doubles ('"'). Exemples :

Si le serveur SQL est en mode ANSI_QUOTES, les chaînes littérales ne peuvent être mises qu'entre guillemets simples. Une chaîne avec des guillemets double sera interprétée comme un identifiant.

'une chaîne'
"une autre chaîne"

Depuis MySQL 4.1.1, les littéraux disposent d'une option de jeu de caractères et de collation avec la clause COLLATE :

[_charset_name]'string' [COLLATE collation_name]

Exemples :

SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;

Pour plus d'informations sur ces formes de chaînes de caractères, voyez Section 10.3.7, « Jeu de caractères et collation des chaînes littérales ».

À l'intérieur d'une chaîne, certaines séquences de caractères ont une signification spéciale. Chacune d'elles commence par un anti-slash ('\'), connu comme le caractère d'échappement. MySQL reconnaît les séquences suivantes :

\0

Un 0 ASCII (NUL).

\'

Un guillemet simple (''').

\"

Un guillemet double ('"').

\b

Un effacement.

\n

Une nouvelle ligne.

\r

Un retour chariot.

\t

Une tabulation.

\z

ASCII(26) (Contrôle-Z). Ce caractère peut être encodé pour vous éviter des problèmes avec Windows, vu qu'il équivaut à une fin de fichier sur cet OS. (ASCII(26) vous posera des problèmes si vous utilisez mysql base < fichier.)

\\

Un anti-slash ('\').

\%

Un signe pourcentage littéral : '%'. Voir les notes ci-dessous.

\_

Un signe souligné littéral : '_'. Voir les notes ci-dessous.

Ces séquences sont sensibles à la casse. Par exemple, '\b' est interprétée comme un anti-slash, mais '\B' est interprété comme la lettre 'B'.

Les caractères '\%' et '\_' sont utilisés pour rechercher des chaînes littérales '%' et '_' dans un contexte d'expressions régulières. Sinon, ces caractères sont interprétés comme des caractères joker. Voir Section 12.3.1, « Opérateurs de comparaison pour les chaînes de caractères ». Notez que si vous utilisez '\%' ou '\_' dans d'autres contextes, ces séquences retourneront '\%' et '\_' et non '%' et '_'.

Il y a plusieurs façons d'intégrer un guillemet dans une chaîne.

- Un ''' à l'intérieur d'une chaîne entourée de ''' peut être noté ''''.

- Un '"' à l'intérieur d'une chaîne entourée de '"' peut être noté '""'.

- Vous pouvez faire précéder le guillemet par caractère d'échappement ('\').

- Un guillemet simple ''' à l'intérieur d'une chaîne à guillemets doubles '"' n'a besoin d'aucun traitement spécial (ni doublage, ni échappement). De même, aucun traitement spécial n'est requis pour un guillemet double '"' à l'intérieur d'une chaîne à guillemets simples '''.

Le SELECT montré ici explique comment les guillemets et les échappements fonctionnent :

mysql> SELECT 'bonjour', '"bonjour"', '""bonjour""', 'bon''jour', '\'bonjour';
+---------+-----------+-------------+----------+----------+
| bonjour | "bonjour" | ""bonjour"" | bon'jour | 'bonjour |
+---------+-----------+-------------+----------+----------+

mysql> SELECT "bonjour", "'bonjour'", "''bonjour''", "bon""jour", "\"bonjour";
+---------+-----------+-------------+----------+----------+
| bonjour | 'bonjour' | ''bonjour'' | bon"jour | "bonjour |
+---------+-----------+-------------+----------+----------+

mysql> SELECT "Voilà\n3\nlignes";
+--------------------+
| Voilà
3
lignes |
+--------------------+

Si vous voulez insérer des données binaires dans un champ chaîne (comme un BLOB), les caractères suivants doivent être échappés :

NUL

ASCII 0. Représentez-le avec '\0' (un anti-slash suivi du caractère ASCII '0').

\

ASCII 92, anti-slash. À représenter avec '\\'.

'

ASCII 39, guillemet simple. À représenter avec '\''.

"

ASCII 34, guillemet double. À représenter avec '\"'.

Lorsque vous écrivez des applications, toutes les chaînes qui risquent de contenir ces caractères spéciaux doivent être protégées avant d'être intégrées dans la commande SQL. Vous pouvez faire cela de deux manières différentes :

- passez la chaîne à une fonction qui protège les caractères spéciaux. Par exemple, en langage C, vous pouvez utiliser la fonction mysql_real_escape_string(). Voir Section 24.2.3.47, « mysql_real_escape_string() ». L'interface Perl DBI fournit une méthode basée sur les guillemets pour convertir les caractères spéciaux en leur séquence correspondante. Voir Section 24.4, « API Perl pour MySQL » ;

- au lieu de protéger explicitement tous les caractères, de nombreuses interfaces MySQL fournissent un système de variables qui vous permettent de mettre des marqueurs dans la requête, et de lier les variables à leur valeur au moment de leur exécution. Dans ce cas, l'interface se charge de protéger les caractères spéciaux pour vous.

9-1-2 - Nombres

Les entiers sont représentés comme une séquence de chiffres. Les décimaux utilisent '.' comme séparateur décimal. Tous les types de nombres peuvent être précédés d'un '-' pour indiquer une valeur négative.

Exemples d'entiers valides :

1221
0
-32

Exemples de nombres à virgule flottante :

294.42
-32032.6809e+10
148.00

Un entier peut être utilisé dans un contexte décimal, il sera interprété comme le nombre décimal équivalent.

9-1-3 - Valeurs hexadécimales

MySQL supporte les valeurs hexadécimales. Dans un contexte numérique, elles agissent comme des entiers (précision 64 bits). Dans un contexte de chaîne, elles agissent comme une chaîne binaire où chaque paire de caractères hexadécimaux est convertie en caractère :

mysql> SELECT x'4D7953514C';
-> 'MySQL'
mysql> SELECT 0xa+0;
-> 10
mysql> SELECT 0x5061756c;
-> 'Paul'

En MySQL 4.1 (et en MySQL 4.0 si vous utilisez l'option --new), le type par défaut d'une valeur hexadécimale est chaîne. Si vous voulez vous assurer qu'une telle valeur est traitée comme un nombre, vous pouvez utiliser CAST(... AS UNSIGNED) :

mysql> SELECT 0x41, CAST(0x41 AS UNSIGNED);
-> 'A', 65

La syntaxe 0x est basée sur ODBC. Les chaînes hexadécimales sont souvent utilisées par ODBC pour fournir des valeurs aux colonnes BLOB. La syntaxe x'hexstring' est nouvelle en 4.0 et est basée sur le standard SQL.

Depuis MySQL 4.0.1, vous pouvez convertir une chaîne ou nombre en chaîne au format hexadécimal avec la fonction HEX() :

mysql> SELECT HEX('cat');
-> '636174'
mysql> SELECT 0x636174;
-> 'cat'

9-1-4 - Valeurs booléennes

Depuis MySQL version 4.1, la constante TRUE vaut 1 et la constante FALSE vaut 0. Les noms des constantes peuvent être écrits en minuscules ou majuscules.

mysql> SELECT TRUE, true, FALSE, false;
-> 1, 1, 0, 0

9-1-5 - Champs de bits

Depuis MySQL 5.0.3, les champs de bits peuvent être écrits avec la notation b'value'. value est une valeur binaire écrite avec des 0 et des 1.

La notation en champ de bits est pratique pour spécifier des données qui doivent être assignées à une colonne de type BIT :

mysql> CREATE TABLE t (b BIT(8));
mysql> INSERT INTO t SET b = b'11111111';
mysql> INSERT INTO t SET b = b'1010';
+------+----------+----------+----------+
| b+0  | BIN(b+0) | OCT(b+0) | HEX(b+0) |
+------+----------+----------+----------+
|  255 | 11111111 | 377      | FF       |
|   10 | 1010     | 12       | A        |
+------+----------+----------+----------+

9-1-6 - Valeurs NULL

La valeur NULL signifie « pas de données » et est différente des valeurs comme 0 pour les nombres ou la chaîne vide pour les types chaîne. Voir Section A.5.3, « Problèmes avec les valeurs NULL ».

NULL peut être représenté par \N lors de la récupération ou écriture avec des fichiers (LOAD DATA INFILE, SELECT ... INTO OUTFILE). Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

9-2 - Noms de bases, tables, index, colonnes et alias

Les noms des bases de données, tables, index, colonnes et alias suivent tous les mêmes règles en MySQL.

La table suivante décrit la taille maximale et les caractères autorisées pour chaque type d'identifiant.

Identifiant

Longueur maximale

Caractères autorisés

Base de données

64

Tous les caractères autorisés dans un nom de dossier à part '/', '\' et '.'.

Table

64

Tous les caractères autorisés dans le nom d'un fichier à part '/' et '.'.

Colonne

64

Tous.

Index

64

Tous.

Alias

255

Tous.

Notez qu'en plus de ce qui précède, vous n'avez pas droit aux caractères ASCII(0) ou ASCII(255) dans un identifiant. Avant MySQL 4.1, les identifiants ne pouvaient pas contenir de guillemets.

Depuis MySQL 4.1, les identifiants sont stockés en Unicode (UTF8). Cela s'applique aux identifiants stockés dans les tables de définitions du fichier .frm, et aux identifiants stockés dans les tables de droits de la base mysql. Même si les identifiants Unicode peuvent inclure des caractères multioctets, notez que les tailles maximales affichées dans la table sont donnés en octets. Si un identifiant contient un caractère multioctet, le nombre de caractères autorisé est alors inférieur aux chiffres affichés.

Un identifiant peut être entre guillemets ou pas. Si un identifiant est un mot réservé, ou qu'il contient des caractères spéciaux, vous devez le mettre entre guillemets lorsque vous l'utilisez. Pour une liste des mots réservés, voyez Section 9.6, « Cas des mots réservés MySQL ». Les caractères spéciaux sont hors de la plage des caractères alphanumérique et '_' et '$'.

Notez que si un identifiant est un mot réservé, ou contient des caractères spéciaux, vous devez absolument le protéger avec '`' :

Le caractère de protection des identifiants est le guillemet oblique '`' :

mysql> SELECT * FROM `select` WHERE `select`.id > 100;

Si vous utilisez MySQL avec les modes MAXDB ou ANSI_QUOTES, il est aussi possible d'utiliser les guillemets doubles pour les identifiants :

mysql> CREATE TABLE "test" (col INT);
ERROR 1064: You have an error in your SQL syntax. (...)
mysql> SET SQL_MODE="ANSI_QUOTES";
mysql> CREATE TABLE "test" (col INT);
Query OK, 0 rows affected (0.00 sec)

Voir Section 1.5.2, « Sélectionner les modes SQL ».

Depuis MySQL 4.1, les guillemets peuvent être inclus dans les noms d'identifiants. Si le caractère inclus dans l'identifiant est le même que celui qui est utilisé pour protéger l'identifiant, doublez-le. La commande suivante crée la table a`b, qui contient la colonne c"d :

mysql> CREATE TABLE `a``b` (`c"d` INT);

La protection d'identifiant par guillemets a été introduite en MySQL 3.23.6 pour permettre l'utilisation de mots réservés ou des caractères spéciaux dans les noms de colonnes. Avant la version 3.23.6, vous ne pouviez pas utiliser les identifiants qui utilisent des guillemets, et les règles sont plus restrictives.

- Un nom d'identifiant est constitué de caractères alphanumériques issus du jeu de caractères courant, plus '_' et '$'. Le jeu de caractères par défaut est ISO-8859-1 (Latin1). Cela peut être modifié avec l'option de démarrage --default-character-set de mysqld. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

- Un nom peut commencer avec n'importe quel caractère qui est valide dans un identifiant. En particulier, un nom peut commencer par un chiffre : cela est différent dans de nombreuses autres bases de données. Cependant, un nom sans guillemet ne peut pas contenir uniquement des chiffres.

- Vous ne pouvez pas utiliser le caractère '.' dans les noms, car il est utilisé pour les formats complets de référence aux colonnes, en utilisant les noms de tables ou de bases. (voir Section 9.2.1, « Identifiants »).

Il est recommandé de ne pas utiliser de noms comme 1e, car une expression comme 1e+1 est ambigüe. Elle pourrait être interprétée comme l'expression 1e + 1 ou comme le nombre 1e+1, suivant le contexte.

9-2-1 - Identifiants

MySQL autorise l'utilisation de noms qui sont constitués d'un seul identifiant, ou d'identifiants multiples. Les composants d'un tel nom doivent être séparés par le caractère point ('.'). Le premier composant détermine le contexte dans lequel l'identifiant final est interprété.

En MySQL, vous pouvez faire référence à une colonne en utilisant l'une des trois formes suivantes :

Référence de colonne

Signification

col_name

La colonne col_name de n'importe quelle table de la requête qui contient une colonne de ce nom.

tbl_name.col_name

La colonne col_name de la table tbl_name de la base de données par défaut.

db_name.tbl_name.col_name

La colonne col_name de la table tbl_name de la base db_name. Cette syntaxe n'est pas disponible avant MySQL version 3.22.

Si un composant d'un nom complexe requiert des guillemets de protection, vous devez protéger chaque composant individuellement plutôt que l'identifiant dans son ensemble. Par exemple, `my-table`.`my-column` est valide, mais `my-table.my-column` ne l'est pas.

Vous n'êtes pas obligé de spécifier le nom d'une table tbl_name ou le nom de la base db_name.tbl_name comme préfixe dans une requête, à moins que la référence soit ambiguë. Supposez que les tables t1 et t2 contiennent toutes les deux une colonne c, et que vous lisez le contenu de la colonne c dans une commande SELECT qui utilise les deux tables t1 et t2. Dans ce cas, c est ambigue, car ce n'est pas un nom unique dans les différentes tables de la commande. Vous devez le préciser avec un nom de table, comme dans t1.c ou t2.c. Similairement, si vous lisez des colonnes dans une table t de la base db1 et dans la table t de la base db2 dans la même commande, vous devez utiliser les noms complets de colonnes, comme db1.t.col_name et db2.t.col_name.

La syntaxe .tbl_name correspond à la table tbl_name de la base courante. Cette syntaxe est acceptée pour la compatibilité avec ODBC, car certains programmes ODBC préfixent le nom de la table avec un caractère point '.'.

9-2-2 - Sensibilité à la casse pour les noms

En MySQL, les bases et les tables correspondent à des dossiers et des fichiers. Les tables dans une base correspondent au moins à un fichier dans le dossier de base et possiblement plusieurs, suivant le moteur de table utilisé. Par conséquent, la sensibilité à la casse du système déterminera la sensibilité à la casse des noms de bases de données et tables. Cela signifie que les noms sont insensibles à la casse sous Windows, et sensibles sous la plupart des variétés Unix. Mac OS X est une exception, car il est basé sur Unix, mais le système de fichiers par défaut (HFS+) n'est pas sensible à la casse. Cependant, Mac OS X supporte aussi les volumes UFS, qui sont sensibles à la casse, comme les autres Unix. Voir Section 1.5.4, « Extensions MySQL au standard SQL-92 ».

Note : même si les noms ne sont pas sensibles à la casse sous Windows, vous ne devez pas vous référer à une entité en utilisant différentes casses dans la même requête. La requête suivante ne fonctionnera pas, car elle se réfère à une table avec ma_table et MA_TABLE :

mysql> SELECT * FROM ma_table WHERE MA_TABLE.col=1;

Les noms de colonnes et d'alias sont insensibles à la casse dans tous les cas.

Les alias sur tables sont sensibles à la casse avant MySQL 4.1.1. La requête suivante ne marchera pas, car elle se réfère à a et A :

mysql> SELECT nom_de_colonne FROM nom_de_table AS a
->                 WHERE a.nom_de_colonne = 1 OR A.nom_de_colonne = 2;

Si vous avez du mal à vous souvenir de la casse des noms de bases et de tables, adoptez une convention, comme toujours créer les bases et les tables en utilisant des minuscules.

La façon de stocker les noms sur le disque et leur utilisation dans les syntaxes MySQL est définie par la variable lower_case_table_names, qui peut être spécifié au lancement de mysqld. lower_case_table_names peut prendre l'une des valeurs suivantes :

Valeur

Signification

0

Les noms de tables et bases sont stockés sur le disque avec la casse utilisée dans la commande CREATE TABLE ou CREATE DATABASE. Les comparaisons de noms sont sensibles à la casse. C'est le comportement par défaut sous Unix. Notez que si vous forcez cette valeur à 0 avec l'option --lower-case-table-names=0 sur un système insensible à la casse, et que vous accéder à la table avec une autre casse, alors vous pouvez avoir des corruptions d'index.

1

Les noms de tables sont stockés en minuscules sur le disque, et les comparaisons de nom de tables sont insensibles à la casse. Ce comportement s'applique aussi aux noms de bases de données depuis MySQL 4.0.2, et aux alias de tables depuis 4.1.1. C'est la valeur par défaut sur les systèmes Windows et Mac OS X.

2

Les tables et bases sont stockés sur le disque avec la casse spécifiée dans CREATE TABLE et CREATE DATABASE, mais MySQL les convertit en minuscules lors des recherches. Les comparaisons de noms sont insensibles à la casse. Note : cela ne fonctionne que sur les systèmes de fichiers qui sont insensibles à la casse. Les noms de tables InnoDB sont stockés en minuscules, comme pour lower_case_table_names=1. Donne à lower_case_table_names la valeur de 2 est possible depuis MySQL 4.0.18.

Si vous utilisez MySQL sur une seule plate-forme, vous n'aurez pas à changer la valeur de lower_case_table_names variable. Cependant, vous pouvez rencontrer des problèmes lors des transferts entre plates-formes, où les systèmes de fichiers différent de par leur sensibilité à la casse. Par exemple, sous Unix, vous pouvez avoir deux tables ma_table et MA_TABLE, alors que sous Windows, ces deux noms représentent la même table. Pour éviter les problèmes de transferts de noms, vous avez deux choix :

- utiliser l'option lower_case_table_names=1 sur tous les systèmes. L'inconvénient le plus sérieux est que lorsque vous utilisez SHOW TABLES ou SHOW DATABASES, vous ne verrez pas la casse originale des noms ;

- utiliser lower_case_table_names=0 sous Unix et lower_case_table_names=2 sous Windows. Cela préserve la casse des noms de tables ou bases. L'inconvénient est que vous devez vous assurer que les requêtes utilisent toujours la bonne casse sous Windows. Si vous transférez vos requêtes vers Unix, où la casse des noms aura son importance, les requêtes ne fonctionneraient plus.

Notez qu'avant de passer la valeur de lower_case_table_names à 1 sous Unix, vous devez commencer par convertir vos anciens noms de tables et bases en minuscules, avant de redémarrer mysqld.

9-3 - Variables utilisateur

MySQL supporte les variables utilisateur spécifiques à la connexion avec la syntaxe @variablename. Un nom de variable consiste en caractères alphanumériques, basés sur le jeu de caractères courant, de '_', '$', et '.'. Le jeu de caractères par défaut est ISO-8859-1 Latin1. Cette valeur peut être changée en utilisant l'option --default-character-set de mysqld. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage ».

Les variables n'ont pas besoin d'être initialisés. Elles sont à NULL par défaut et peuvent contenir un entier, un réel ou une chaîne. Toutes les variables d'un thread sont automatiquement libérées lorsque le thread se termine.

Vous pouvez déclarer une variable avec la syntaxe de SET :

SET @variable= { expression entier | expression réel | expression chaîne }
[,@variable= ...].

Vous pouvez aussi assigner une valeur à une variable avec d'autres commandes que SET. Par contre, dans ce cas-là, l'opérateur d'assignation est := au lieu de =, parce que = est réservé aux comparaisons dans les requêtes autres que SET :

mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

Les variables utilisateur peuvent être utilisées là où les expressions sont allouées. Notez que cela n'inclut pas pour l'instant les contextes où un nombre est explicitement requis, comme ce qui est le cas avec la clause LIMIT dans une requête SELECT, ou la clause IGNORE nombre LINES dans une requête LOAD DATA.

Note : dans une requête SELECT, chaque expression n'est évaluée que lors de l'envoi au client. Cela signifie que pour les clauses HAVING, GROUP BY, ou ORDER BY, vous ne pouvez vous référer à une expression qui implique des variables qui sont définies dans la partie SELECT. Par exemple, la requête suivante ne produira pas le résultat escompté :

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM nom_de_table HAVING b=5;

La raison est que @aa ne contiendra pas la valeur de la ligne courante, mais celle de id pour la dernière ligne acceptée.

La règle générale est de ne jamais assigner et utiliser la même variable dans la même commande.

Un autre problème avec l'affectation de variable et son utilisation dans la même commande est que le type de valeur par défaut est basé sur le type de la variable dans la commande de départ. Une variable non assignée est supposée être de type NULL ou de type STRING. L'exemple suivant illustre bien ce cas de figure :

mysql> SET @a="test";
mysql> SELECT @a,(@a:=20) FROM table_name;

Dans ce cas, MySQL va indiquer au client que la colonne 1 est une chaîne, et il convertira tous les accès à la variable @a en chaîne, même si @a recevra finalement un nombre dans la seconde ligne. Après l'exécution de la commande, @a sera considéré comme un nombre.

Si vous avez des problèmes avec cela, essayer d'éviter d'affecter et d'utiliser la même variable dans la même commande, ou bien initialisez la variable avec les valeurs de 0, 0.0 ou "" avant de l'utiliser.

9-4 - Variables système

À partir de la version 4.0.3, nous fournissons un meilleur accès à beaucoup de variables système et variables de connexion. On peut changer la plupart d'entre elles sans avoir à stopper le serveur.

Le serveur mysqld dispose de deux types de variables. Les variables globales, qui affectent l'ensemble du serveur. Les variables de session qui affectent des connexions individuelles.

Lorsque mysqld démarre, toutes les variables globales sont initialisées à partir des arguments passés en ligne de commande et des fichiers de configuration. Vous pouvez changer ces valeurs avec la commande SET GLOBAL. Lorsqu'un nouveau thread est créé, les variables spécifiques aux threads sont initialisées à partir des variables globales et ne changeront pas même si vous utilisez la commande SET GLOBAL.

Le serveur entretient aussi un jeu de variables de session pour chaque client qui se connecte. Les variables de session d'un client sont initialisées au moment de la connexion, en utilisant les valeurs correspondantes globales. Pour les variables de session qui sont dynamiques, le client peut les changer avec la commande SET SESSION var_name. Modifier les variables de session d'une connexion ne requiert aucun droit spécifique, mais le client ne peut changer que ses propres variables de session, et non pas celles d'un autre client.

Une modification à une variable globale est visible à tous les clients qui accèdent à cette variable. Mais, cela n'affecte la variable de session correspondante que lors de la prochaine connexion. Les connexions déjà établies ne sont pas affectées par un changement de variable globale. (Pas même le client qui a émis la commande SET GLOBAL.)

Pour définir la valeur d'une variable GLOBAL, vous devez utiliser l'une des syntaxes suivantes. Ici nous utilisons la variable sort_buffer_size à titre d'exemple.

Pour donner la valeur à une variable GLOBAL, utilisez l'une de ces syntaxes :

mysql> SET GLOBAL sort_buffer_size=value;
mysql> SET @@global.sort_buffer_size=value;

Pour définir la valeur d'une variable SESSION, vous devez utiliser l'une des syntaxes suivantes :

mysql> SET SESSION sort_buffer_size=value;
mysql> SET @@session.sort_buffer_size=value;
mysql> SET sort_buffer_size=value;

LOCAL est un synonyme de SESSION.

Si vous ne spécifiez pas GLOBAL ou SESSION alors SESSION est utilisé. Voir Section 13.5.2.8, « Syntaxe de SET ».

Pour récupérer la valeur d'une variable de type GLOBAL vous pouvez utiliser l'une des commandes suivantes :

mysql> SELECT @@global.sort_buffer_size;
mysql> SHOW GLOBAL VARIABLES like 'sort_buffer_size';

Pour récupérer la valeur d'une variable de type SESSION vous pouvez utiliser l'une des commandes suivantes :

mysql> SELECT @@sort_buffer_size;
mysql> SELECT @@session.sort_buffer_size;
mysql> SHOW SESSION VARIABLES like 'sort_buffer_size';

Ici aussi, LOCAL est un synonyme de SESSION.

Lorsque vous récupérez une valeur de variable avec la syntaxe @@nom_variable et que vous ne spécifiez pas GLOBAL ou SESSION, MySQL retournera la valeur spécifique au thread (SESSION) si elle existe. Sinon, MySQL retournera la valeur globale.

Pour la commande SHOW VARIABLES, si vous ne spécifiez pas GLOBAL, SESSION ou LOCAL, MySQL retourne les valeurs de SESSION.

La raison d'imposer la présence du mot GLOBAL pour configurer une variable de type GLOBAL mais non pour la lire est pour être sûr que vous n'aurez pas de problèmes plus tard si vous voulez introduire ou effacer une variable spécifique au thread qui aurait le même nom. Dans ce cas, vous pourriez changer accidentellement l'état du serveur pour toutes les connexions (et non la vôtre uniquement).

Plus d'informations sur les options de démarrage du système et les variables système sont dans les sections Section 5.2.1, « Options de ligne de commande de mysqld » et Section 5.2.3, « Variables serveur système ». Une liste des variables qui peuvent être modifiées durant l'exécution est présentée dans Section 5.2.3.1, « Variables système dynamiques ».

9-4-1 - Variables système structurées

Les variables système structurées sont supportées depuis MySQL 4.1.1. Une variable structurée diffère d'une variable système classique sur deux points :

- sa valeur est une structure avec des composants qui spécifient des paramètres serveur qui sont étroitement liés ;

- il peut y avoir plusieurs instances d'une même variable système structurée. Chacune d'entre elles a un nom différent, et fait référence à une ressource différente, gérée sur le serveur.

Actuellement, MySQL supporte un type de variables système structurées. Il spécifie les paramètres qui gouvernent les caches de clés. Une variable système structurée de cache de clés contient les composants suivants :

- key_buffer_size ;

- key_cache_block_size ;

- key_cache_division_limit ;

- key_cache_age_threshold.

L'objectif de cette section est de décrire la syntaxe d'opération avec les variables système structurées. Les variables du cache de clés sont utilisées comme exemple syntaxique, mais les détails concernant le cache de clés sont disponibles dans la section Section 7.4.6, « Le cache de clés des tables MyISAM ».

Pour faire référence à un composant d'une variable système structurée, vous pouvez utiliser un nom composé, au format nom_d_instance.nom_du_composant. Par exemple :

hot_cache.key_buffer_size
hot_cache.key_cache_block_size
cold_cache.key_cache_block_size

Pour chaque variable système structurée, une instance avec le nom default est toujours prédéfinie. Si vous faites référence à un composant d'une variable système structurée sans aucun nom d'instance, l'instance default sera utilisée. Par conséquent, default.key_buffer_size et key_buffer_size font référence à la même variable système structurée.

Les règles de nommage pour les variables système structurées et ses composants sont les suivantes.

- Pour un type donné de variables système structurées, chaque instance doit avoir un nom unique à l'intérieur de ce type. Cependant, les noms d'instances doivent être uniques à l'intérieur des types de variables système structurées. Par exemple, chaque variable système structurée aura une instance default, ce qui fait que default n'est pas unique à l'intérieur des types de variables.

- Les noms de composants de chaque variable système structurée doit être unique à travers tous les noms de variables système. Si ce n'était pas vrai (c'est-à-dire, si deux types de variables structurées pouvaient partager des noms de composants), il ne serait pas facile de trouver la variable structurée par défaut, pour ce type.

- Si un nom de variable système structurée n'est pas valide en tant qu'identifiant non protégé, il faut utiliser les guillemets obliques pour le protéger. Par exemple, hot-cache n'est pas valide, mais `hot-cache` l'est.

- global, session, et local ne sont pas des noms de composants valides. Cela évite les conflits avec des notations comme @@global.var_name, qui fait référence à des variables système non structurées.

Actuellement, les deux premières règles ne peuvent pas être violées, puisqu'il n'y a qu'un seul type de variables système structurées, celui des caches de clés. Ces règles prendront leur importance si d'autres types de variables structurées sont créés dans le futur.

À une exception près, il est possible de faire référence à une variable système structurée en utilisant des noms composés, dans un contexte où un nom de variable simple est utilisé. Par exemple, vous pouvez assigner une valeur à une variable structurée en utilisant la ligne de commande suivante :

shell> mysqld --hot_cache.key_buffer_size=64K

Dans un fichier d'options, faites ceci :

[mysqld]
hot_cache.key_buffer_size=64K

Si vous lancez le serveur avec cette option, il va créer un cache de clés appelé hot_cache, avec une taille de 64 ko, en plus du cache de clés par défaut, qui a une taille de 8 Mo.

Supposez que vous démarriez le serveur avec ces options :

shell> mysqld --key_buffer_size=256K \
--extra_cache.key_buffer_size=128K \
--extra_cache.key_cache_block_size=2096

Dans ce cas, le serveur utilise une taille par défaut de 256 ko pour le cache. Vous pourriez aussi écrire --default.key_buffer_size=256K. De plus, le serveur crée un second cache de clé appelé extra_cache, de taille 128 ko, avec une taille de bloc de buffers de 2096 octets.

L'exemple suivant démarre le serveur avec trois caches de clés différents, avec des tailles de ratio 3:1:1 :

shell> mysqld --key_buffer_size=6M \
--hot_cache.key_buffer_size=2M \
--cold_cache.key_buffer_size=2M

Les variables système structurées peuvent être affectées et lues durant l'exécution. Par exemple, pour créer un cache de clés appelé hot_cache, de taille 10 Mo, utilisez une des commandes suivantes :

mysql> SET GLOBAL hot_cache.key_buffer_size = 10*1024*1024;
mysql> SET @@global.hot_cache.key_buffer_size = 10*1024*1024;

Pour lire la taille du cache, faites ceci :

mysql> SELECT @@global.hot_cache.key_buffer_size;

Cependant, la commande suivante ne fonctionne pas. La variable n'est pas interprétée comme un nom composé, mais comme une simple chaîne pour l'opérateur LIKE :

mysql> SHOW GLOBAL VARIABLES LIKE 'hot_cache.key_buffer_size';

C'est l'exception où vous ne pouvez pas utiliser une variable système structurée, là où une variable simple fonctionnerait.

9-5 - Syntaxe des commentaires

Le serveur MySQL supporte trois types de commentaires :

- depuis '#' jusqu'à la fin de la ligne ;

- depuis '--' jusqu'à la fin de la ligne. Ce style est supporté depuis MySQL 3.23.3. Notez que le commentaire '--' (double-tiret) requiert que le second tiret soit suivi d'un espace ou par un autre caractère de contrôle comme une nouvelle ligne. Cette syntaxe diffère légèrement des standards SQL, comme discuté dans la section Section 1.5.5.7, « '--' comme début de commentaire » ;

- depuis '/*' jusqu'à '*/'. La séquence de fermeture n'a pas besoin d'être sur la même ligne, ce qui permet de répartir le commentaire sur plusieurs lignes.

Voici un exemple avec les trois types de commentaires :

mysql> SELECT 1+1;     # Ce commentaire se continue jusqu'à la fin de la ligne
mysql> SELECT 1+1;     -- Ce commentaire se continue jusqu'à la fin de la ligne
mysql> SELECT 1 /* Ceci est un commentaire dans la ligne */ + 1;
mysql> SELECT 1+
/*
Ceci est un commentaire
sur plusieurs lignes
*/
1;

La syntaxe des commentaires décrite ici s'applique à l'analyseur du serveur mysqld, lorsqu'il traite les commandes SQL. Le client mysql peut aussi effectuer des analyses de commandes avant de les envoyer : par exemple, il recherche les limites de requêtes dans les commandes multilignes. Cependant, il y a des limitations dans la façon de gérer les commentaires /* ... */.

- Les guillemets (simples et doubles) sont considérés comme des indications de début de chaîne, même dans un commentaire. Si le guillemet n'est pas refermé (par un second guillemet), l'analyseur ne réalisera pas que le commentaire est fini. Si vous utilisez mysql interactivement, vous pouvez vous en apercevoir, car il va modifier l'invite de commande de mysql> en '> ou ">.

- Un point-virgule sert à indiquer la fin de la commande SQL, et tout ce qui suit un point-virgule est considéré comme étant une nouvelle requête.

Ces limitations s'appliquent aussi bien à mysql en ligne de commande, que lorsque vous demandez à mysql de lire des commandes depuis un fichier (mysql < un-fichier).

9-6 - Cas des mots réservés MySQL

Un problème récurrent provient de la tentative de création de tables avec des noms de colonnes qui sont des types de champs ou des fonctions natives de MySQL, comme TIMESTAMP ou GROUP. Il vous est permis de le faire (par exemple ABS est permis comme nom de colonne), mais les espaces ne sont pas permis entre le nom d'une fonction et la première '(' suivante lors de l'utilisation de fonctions qui sont aussi des noms de colonnes.

Un effet secondaire de ce comportement est que l'omission d'espace dans certains contexte fait que l'identifiant est interprété comme un nom de fonction. Par exemple, cette commande est valide :

mysql> CREATE TABLE abs (val INT);

Mais omettre l'espace après abs génère une erreur de syntaxe, car la commande semble utiliser la fonction ABS() :

mysql> CREATE TABLE abs(val INT);

Si vous lancez le serveur l'option de mode IGNORE_SPACE, le serveur autorisera l'appel de fonction avec un espace entre le nom de la fonction et le caractère de parenthèse ouvrante '(' suivant. Les noms de fonctions sont alors considérés comme des mots réservés. Comme pour les résultats, les noms de colonnes qui sont identiques au nom de fonctions doivent être placés entre guillemets, tels que décrit dans Section 9.2, « Noms de bases, tables, index, colonnes et alias ». Le mode SQL du serveur est contrôlé par la procédure de la section Section 1.5.2, « Sélectionner les modes SQL ».

Les mots suivants sont explicitement réservés en MySQL. La plupart sont interdits par ANSI SQL92 en tant que nom de colonnes ou de tables (par exemple, GROUP). Quelques uns sont réservés parce que MySQL en a besoin et utilise (actuellement) un analyseur yacc :

ADD

ALL

ALTER

ANALYZE

AND

AS

ASC

ASENSITIVE

BEFORE

BETWEEN

BIGINT

BINARY

BLOB

BOTH

BY

CALL

CASCADE

CASE

CHANGE

CHAR

CHARACTER

CHECK

COLLATE

COLUMN

CONDITION

CONNECTION

CONSTRAINT

CONTINUE

CONVERT

CREATE

CROSS

CURRENT_DATE

CURRENT_TIME

CURRENT_TIMESTAMP

CURRENT_USER

CURSOR

DATABASE

DATABASES

DAY_HOUR

DAY_MICROSECOND

DAY_MINUTE

DAY_SECOND

DEC

DECIMAL

DECLARE

DEFAULT

DELAYED

DELETE

DESC

DESCRIBE

DETERMINISTIC

DISTINCT

DISTINCTROW

DIV

DOUBLE

DROP

DUAL

EACH

ELSE

ELSEIF

ENCLOSED

ESCAPED

EXISTS

EXIT

EXPLAIN

FALSE

FETCH

FLOAT

FLOAT4

FLOAT8

FOR

FORCE

FOREIGN

FROM

FULLTEXT

GOTO

GRANT

GROUP

HAVING

HIGH_PRIORITY

HOUR_MICROSECOND

HOUR_MINUTE

HOUR_SECOND

IF

IGNORE

IN

INDEX

INFILE

INNER

INOUT

INSENSITIVE

INSERT

INT

INT1

INT2

INT3

INT4

INT8

INTEGER

INTERVAL

INTO

IS

ITERATE

JOIN

KEY

KEYS

KILL

LABEL

LEADING

LEAVE

LEFT

LIKE

LIMIT

LINES

LOAD

LOCALTIME

LOCALTIMESTAMP

LOCK

LONG

LONGBLOB

LONGTEXT

LOOP

LOW_PRIORITY

MATCH

MEDIUMBLOB

MEDIUMINT

MEDIUMTEXT

MIDDLEINT

MINUTE_MICROSECOND

MINUTE_SECOND

MOD

MODIFIES

NATURAL

NOT

NO_WRITE_TO_BINLOG

NULL

NUMERIC

ON

OPTIMIZE

OPTION

OPTIONALLY

OR

ORDER

OUT

OUTER

OUTFILE

PRECISION

PRIMARY

PROCEDURE

PURGE

RAID0

READ

READS

REAL

REFERENCES

REGEXP

RELEASE

RENAME

REPEAT

REPLACE

REQUIRE

RESTRICT

RETURN

REVOKE

RIGHT

RLIKE

SCHEMA

SCHEMAS

SECOND_MICROSECOND

SELECT

SENSITIVE

SEPARATOR

SET

SHOW

SMALLINT

SONAME

SPATIAL

SPECIFIC

SQL

SQLEXCEPTION

SQLSTATE

SQLWARNING

SQL_BIG_RESULT

SQL_CALC_FOUND_ROWS

SQL_SMALL_RESULT

SSL

STARTING

STRAIGHT_JOIN

TABLE

TERMINATED

THEN

TINYBLOB

TINYINT

TINYTEXT

TO

TRAILING

TRIGGER

TRUE

UNDO

UNION

UNIQUE

UNLOCK

UNSIGNED

UPDATE

USAGE

USE

USING

UTC_DATE

UTC_TIME

UTC_TIMESTAMP

VALUES

VARBINARY

VARCHAR

VARCHARACTER

VARYING

WHEN

WHERE

WHILE

WITH

WRITE

X509

XOR

YEAR_MONTH

ZEROFILL

Les symboles suivants (issus de la table ci-dessus) sont interdits par ANSI SQL, mais permis par MySQL en tant que noms de colonnes ou de tables. Cela est dû au fait que ces noms sont très courants, et de nombreux programmeurs les ont déjà utilisés.

- ACTION

- BIT

- DATE

- ENUM

- NO

- TEXT

- TIME

- TIMESTAMP

10 - Jeux de caractères et Unicode

L'amélioration du support des jeux de caractères est un des progrès de MySQL en version 4.1. Ce chapitre couvre :

- ce que sont les jeux de caractères et les collations ;

- le système par défaut à plusieurs niveaux ;

- nouvelle syntaxe en MySQL 4.1 ;

- fonctions et opérations affectées ;

- support d'Unicode ;

- la signification de chaque jeu de caractères et collation.

Le support des jeux de caractères est inclus dans les tables MySISAM, MEMORY (HEAP), et depuis MySQL 4.1.2, InnoDB. Le moteur de table ISAM n'inclut pas le support des jeux de caractères, et il n'y a pas de plan pour le faire, car ISAM est abandonnée.

10-1 - Jeux de caractères et collation : généralités

Un jeu de caractères est un ensemble de symboles et de codes. Une collation est un ensemble de règles permettant la comparaison de caractères dans un jeu. Pour rendre ces définitions plus concrètes, voici un exemple avec un alphabet imaginaire.

Supposons que nous avons un alphabet de quatre lettres : 'A', 'B', 'a', 'b'. Nous assignons à chaque lettre un nombre comme ceci : 'A' = 0, 'B' = 1, 'a' = 2, 'c' = 3. La lettre 'A' est un symbole, le chiffre 0 est le code de 'A', et la combinaison des quatre lettres et de leur code forme le jeu de caractères.

Maintenant, supposons que nous voulions comparer deux chaînes de caractères : 'A' et 'B'. Le plus simple pour cela est de regarder leur code : 0 pour 'A' et 1 pour 'B', et comme 0 est inférieure à 1, nous pouvons dire que 'A' est plus petit que 'B'. Ce que nous venons de faire est une collation pour notre jeu de caractères. La collation est un ensemble de règles, qui se résume à ceci dans notre cas : « compare les codes ». Cette règle est la plus simple collation binaire.

Si nous devons différencier les majuscules des minuscules, nous aurons au moins deux règles : (1) traiter les minuscules 'a' et 'b' comme des équivalents de 'A' et 'B'; (2) puis comparer leur code respectif. Nous appelons cette règle une collation sensible à la casse. C'est un peu plus complexe que la règle précédente.

En réalité, la plupart des jeux de caractères ont de nombreux caractères : ce n'est pas simplement 'A' et 'B' mais des alphabets entiers, ou des systèmes d'écriture orientaux avec des milliers de caractères, incluant des caractères spéciaux et la ponctuation. Dans la vraie vie, une collation a de très nombreuses règles, concernant la sensibilité à la casse ou encore l'insensibilité aux accents (un accent est une marque attachée aux lettres comme le 'Ö') allemand) et les caractères multiples comme le e dans l'o 'œ' = 'oe' de l'une des deux collations allemandes.

MySQL 4.1 peut faire cela pour vous :

- stocker des chaînes dans différents jeux de caractères ;

- comparer des chaînes à l'aide de différentes collations ;

- mélanger différents jeux de caractères et collations sur le même serveur, la même base ou même, la même table ;

- permettre la spécification du jeu de caractères et de la collation à n'importe quel niveau.

Sous cet angle, MySQL 4.1 est bien plus souple que MySQL 4.0 et que les autres bases de données. Mais, pour pouvoir utiliser ces nouvelles fonctionnalités, vous devez savoir quels sont les jeux de caractères et les collations disponibles, comment les modifier ou comment les utiliser avec les opérateurs.

10-2 - Jeux de caractères et collation dans MySQL

Un jeu de caractères a toujours au moins une collation. Pour lister les jeux de caractères disponibles, utilisez la commande SHOW CHARACTER SET :

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+
| Charset  | Description                 | Default collation   |
+----------+-----------------------------+---------------------+
| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |
| dec8     | DEC West European           | dec8_swedish_ci     |
| cp850    | DOS West European           | cp850_general_ci    |
| hp8      | HP West European            | hp8_english_ci      |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |
| latin1   | ISO 8859-1 West European    | latin1_swedish_ci   |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |
...

Le résultat inclut en réalité une autre colonne, qui n'est pas présentée dans cette page, à des fins de publication.

Tout jeu de caractères a toujours au moins une collation. Il peut en avoir plusieurs.

Pour lister les collations d'un jeu de caractères, utilisez la commande SHOW COLLATION. Par exemple, pour afficher les collations du jeu de caractères latin1 (« ISO-8859-1 West European »), utilisez cette commande, et recherchez les noms de collation qui commencent par latin1 :

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          |       0 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       1 |
| latin1_danish_ci  | latin1  | 15 |         |          |       0 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       1 |
| latin1_general_ci | latin1  | 48 |         |          |       0 |
| latin1_general_cs | latin1  | 49 |         |          |       0 |
| latin1_spanish_ci | latin1  | 94 |         |          |       0 |
+-------------------+---------+----+---------+----------+---------+

Les collations latin1 ont les significations suivantes :

Collation

Signification

latin1_bin

Binaire, suivant l'encodage latin1

latin1_danish_ci

Danois/norvégien

latin1_general_ci

Multilingue

latin1_general_cs

Multilingue, sensible à la casse

latin1_german1_ci

Allemand DIN-1

latin1_german2_ci

Allemand DIN-2

latin1_spanish_ci

Espagnol moderne

latin1_swedish_ci

Suédois/finlandais

Les collations ont les caractéristiques suivantes :

- deux jeux de caractères différents ne peuvent pas avoir la même collation ;

- chaque jeu de caractères a une collation qui est la collation par défaut. Par exemple, la collation par défaut de latin1 est latin1_swedish_ci ;

- il y a une convention pour les noms de collation : elles commencent par le nom du jeu de caractères auquel elles sont associées ; elles incluent généralement un nom de langue, et finissent par _ci (case insensitive, insensible à la casse), _cs (case sensitive, sensible à la casse), _bin (binaire), ou _uca (Algorithme Unicode, Unicode Collation Algorithm).

10-3 - Déterminer le jeu de caractères et la collation par défaut

Il y a une configuration par défaut pour chaque jeu de caractères et collation à quatre niveaux : serveur, base de données, table, connexion. La description suivante peut paraître complexe, mais il a été montré qu'en pratique la mise par défaut par niveaux multiples mène à des résultats simples et évidents.

10-3-1 - Jeu de caractères et collation serveur

Le serveur MySQL a un jeu de caractères et une collation serveur, qui ne peuvent pas être nuls.

MySQL détermine le jeu de caractères et la collation serveurs comme suit :

- en fonction de l'option de configuration active quand le serveur démarre ;

- en fonction des valeurs de configuration à l'exécution.

À ce niveau, la décision est simple. Le jeu de caractères serveur et sa collation dépendent des options que vous utilisez au démarrage de mysqld. Vous pouvez utiliser --default-character-set=character_set_name comme jeu de caractères et vous pouvez en même temps ajouter --default-collation=collation_name pour la collation. Si vous n'indiquez pas de jeu de caractères, cela revient à dire --default-character-set=latin1. Si vous indiquez un jeu de caractères (par exemple, latin1) mais pas de collation, cela revient à dire : --default-charset=latin1 --collation=latin1_swedish_ci, car latin1_swedish_ci est la collation par défaut de latin1. par conséquent, les trois commandes suivantes ont toutes le même effet :

shell> mysqld
shell> mysqld --default-character-set=latin1
shell> mysqld --default-character-set=latin1
--default-collation=latin1_swedish_ci

Une façon de changer la configuration par défaut est de recompiler MySQL. Si vous voulez changer le jeu de caractères et la collation par défaut du serveur quand vous compilez depuis les sources, utilisez --with-character-set et --with-collation comme arguments pour configure. Par exemple :

shell> ./configure --with-character-set=latin1

ou :

shell> ./configure --with-character-set=latin1
--with-collation=latin1_german1_ci

mysqld et configure vérifient aussi que la combinaison jeu de caractères/collation est valide. Ces programmes affichent un message erreur et se terminent si la combinaison n'est pas valide.

10-3-2 - Jeu de caractères et collation de base de données

Toute base de données a un jeu de caractères de base de données et une collation de base de données, qui ne peuvent pas être nulles. Les commandes CREATE DATABASE et ALTER DATABASE permettent de utiliser optionnellement ces deux attributs :

CREATE DATABASE db_name
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]

ALTER DATABASE db_name
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]

Exemple :

CREATE DATABASE db_name
DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;

MySQL choisit le jeu de caractères et la collation de base de données comme ceci :

- si les deux clauses CHARACTER SET X et COLLATE Y ont été spécifiées, alors leurs valeurs sont utilisées ;

- si CHARACTER SET X a été spécifiée sans COLLATE, alors le jeu de caractères est X et sa collation par défaut ;

- sinon, le jeu de caractères et la collation par défaut du serveur sont utilisés.

La syntaxe MySQL CREATE DATABASE ... DEFAULT CHARACTER SET ... est analogue à la syntaxe du standard SQL CREATE SCHEMA ... CHARACTER SET .... Il est donc possible de créer des bases de données avec différents jeux de caractères et collations, sur le même serveur MySQL.

Le jeu de caractères et la collation sont utilisés comme valeur par défaut pour les tables, lorsque ces informations ne sont pas spécifiées dans les commandes CREATE TABLE. Elles n'ont pas d'autre utilité.

10-3-3 - Jeu de caractères de tables et collation

Chaque table a un jeu de caractères et une collation de table qui ne peut pas être nulle. Les commandes CREATE TABLE et ALTER TABLE ont maintenant des options pour préciser le jeu de caractères et la collation :

CREATE TABLE table_name ( column_list )
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]

ALTER TABLE table_name
[DEFAULT CHARACTER SET character_set_name] [COLLATE collation_name]

Exemple :

CREATE TABLE t1 ( ... ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

MySQL choisit le jeu de caractères et la collation :

- si CHARACTER SET X et COLLATE Y sont précisés tous les deux, alors on adopte le jeu de caractères X et la collation Y ;

- si CHARACTER SET X était précisé sans COLLATE, alors on adopte le jeu de caractères X et sa collation par défaut ;

- sinon, le jeu de caractères et la collation de la base de données sont utilisés.

Le jeu de caractères et la collation sont utilisés comme valeurs par défaut si ces deux attributs ne sont pas précisés par la définition d'une colonne. Le jeu de caractères et la collation sont des extensions MySQL : il n'y a pas de telles fonctionnalités en SQL standard.

10-3-4 - Jeu de caractères de colonne et collation

Chaque colonne de « character » (c'est-à-dire les colonnes de type CHAR, VARCHAR, ou TEXT) a un jeu de caractères de colonne et une collation de colonne qui ne peut pas être nulle. La syntaxe de définition de colonne a maintenant des clauses optionnelles pour préciser le jeu de caractères de colonne et la collation :

column_name {CHAR | VARCHAR | TEXT} (column_length)
[CHARACTER SET character_set_name [COLLATE collation_name]]

Exemple :

CREATE TABLE Table1
(
column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci
);

MySQL choisit le jeu de caractères et la collation de colonne comme ceci :

- si CHARACTER SET X et COLLATE Y sont spécifiés, alors le jeu de caractères est X et la collation Y ;

- si CHARACTER SET X a été spécifié sans la clause COLLATE, alors le jeu de caractères est X et la collation est sa collation par défaut ;

- sinon, MySQL utilise le jeu de caractères et la collation par défaut.

Les clauses CHARACTER SET et COLLATE font partie du standard SQL.

10-3-5 - Exemples d'attribution de jeu de caractères et collation

Les exemples suivants montrent comment MySQL détermine le jeu de caractères par défaut et les valeurs de collation.

Exemple 1 : définition de table et colonne

CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci
) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;

Vous avez ici une colonne avec un jeu de caractères latin1 et une collation latin1_german1_ci. La définition est explicite, c'est donc direct. Veuillez noter qu'il n'y a pas de problème à stocker une colonne latin1 dans une table latin2.

Exemple 2 : définition de table et colonne

CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

Cette fois-ci nous avons une colonne avec un jeu de caractères latin1 et une collation par défaut. Maintenant, bien que cela puisse sembler naturel, la collation par défaut n'est pas spécifiée au niveau de la table. À la place, comme la collation par défaut de latin1 est toujours latin1_swedish_ci, la colonne c1 aura la collation latin1_swedish_ci (et non latin1_danish_ci).

Exemple 3 : définition de table et colonne

CREATE TABLE t1
(
c1 CHAR(10)
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

Nous avons une colonne avec un jeu de caractères par défaut et une collation par défaut. Dans ces conditions, MySQL regarde au niveau de la table pour déterminer le jeu de caractères et la collation. Par conséquent le jeu de caractères de la colonne c1 est latin1 et sa collation est latin1_danish_ci.

Exemple 4: définition de base, table et colonne

CREATE DATABASE d1 DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci;
USE d1;
CREATE TABLE t1
(
c1 CHAR(10)
);

Nous créons une colonne sans préciser son jeu de caractères ni sa collation. Nous ne spécifions pas non plus de jeu de caractères ni de collation au niveau de la table. Dans ces conditions, MySQL cherche au niveau de la base de données. (La configuration de la base de donnée devient celle de la table, et par conséquent celle de la colonne.) Donc le jeu de caractères de colonne c1 est latin2 et sa collation est latin2_czech_ci.

10-3-6 - Jeux de caractères et collations de connexion

Plusieurs variables contrôlent les jeux de caractères et collations du système pour un client. Certaines ont déjà été mentionnées précédemment :

- le jeu de caractères et la collation sont disponibles dans les variables character_set_server et collation_server ;

- le jeu de caractères et la collation par défaut de la base de données sont disponibles dans character_set_database et collation_database.

D'autres variables et collations sont impliquées dans la gestion des connexions entre un client et un serveur. Chaque client a un jeu de caractères et une collation attitrés.

Pensez à ce qu'est une « connexion » : c'est ce que vous faites lorsque vous vous connectez au serveur. Le client envoie des SQL commandes comme des requêtes, au travers de la connexion, vers le serveur. Le serveur renvoie des réponses, comme des jeux de résultats, au client, au travers de la connexion. Ceci mène à plusieurs questions telles que :

- dans quel jeu de caractères est la requête lorsqu'elle quitte le client ?

Le serveur utilise la variable character_set_client pour connaître le jeu de caractères des requêtes émises par le client ;

- dans quel jeu de caractères le serveur devrait-il traduire la requête après l'avoir reçue ?

Pour cela, character_set_connection et collation_connection sont utilisées par le serveur. Il convertit les requêtes envoyées par le client de character_set_client en character_set_connection (hormis les chaînes littérales qui sont précédées de _latin1 ou _utf8). collation_connection est importante pour les comparaisons de chaînes littérales. Pour les comparaisons de chaînes avec des colonnes, la collation de la colonne a la priorité ;

- dans quel jeu de caractères le serveur devrait-il traduire les résultats ou messages d'erreur avant de les renvoyer au client ?

La variable character_set_results indique le jeu de caractères que le serveur utilise pour retourner les résultats aux clients. Cela inclut les données telles que les noms de colonnes ou les métadonnées.

Vous pouvez configurez ces options-là, ou vous pouvez vous fier aux configurations par défaut (auquel cas vous pouvez sauter cette section).

Il y a deux commandes qui permettent de modifier le jeu de caractères de la connexion :

SET NAMES 'charset_name'
SET CHARACTER SET charset_name

SET NAMES indique ce qui est dans la commande SQL que le client envoie. Par conséquent, SET NAMES cp1251 indique au serveur : « les futurs messages fournis par ce client seront dans le jeu de caractères cp1251 » et le serveur est libre de les traduire dans son propre jeu de caractères, éventuellement.

La commande SET NAMES 'x' est équivalente à ces trois commandes :

mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;

SET CHARACTER SET est similaire, mais spécifie le jeu de caractères et la collation par défaut des bases pour la connexion. Une commande SET CHARACTER SET x est équivalente à :

mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET collation_connection = @@collation_database;

Lorsque vous exécutez la commande SET NAMES ou SET CHARACTER SET, vous changez aussi la collation de la connexion. Cependant, la collation de connexion existe uniquement par cohérence. Généralement sa valeur n'a pas d'importance.

Avec le client mysql, il n'est pas nécessaire d'exécuter la commande SET NAMES à chaque démarrage. Vous pouvez ajouter l'option --default-character-set-name dans la ligne de commande de mysql, ou dans le fichier d'options. Par exemple, la ligne suivante est exécutée automatiquement à chaque démarrage de mysql :

[mysql]
default-character-set=koi8r

EXEMPLE : supposez que column1 est défini par CHAR(5) CHARACTER SET latin2. Si vous n'indiquez pas SET CHARACTER SET, alors la commande SELECT column1 FROM t retournera les valeurs de la colonne column1 en utilisant le jeu de caractères latin2. Si, d'un autre côté, vous utilisez la commande SET CHARACTER SET latin1, le serveur va alors convertir le résultat de latin2 en latin1 juste avant de l'envoyer. De telles conversions sont lentes.

Si vous ne voulez pas que le serveur fasse des conversions, utilisez la valeur NULL à character_set_results :

mysql> SET character_set_results = NULL;

10-3-7 - Jeu de caractères et collation des chaînes littérales

Chaque chaîne de caractères littérale a un jeu de caractères et une collation qui ne peut pas être nulle.

Une chaîne de caractères littérale peut avoir un spécificateur optionnel de jeu de caractères optionnel et une clause COLLATE :

[_character_set_name]'string' [COLLATE collation_name]

Exemples :

SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;

La simple commande SELECT 'string' utilise le jeu de caractères par défaut de la connexion.

L'expression _character_set_name est formellement appelée un spécificateur (introducer). Elle indique à l'analyseur : « la chaîne qui va suivre utilise le jeu de caractères X. » Cela a été source de confusions par le passé, aussi nous insistons sur le fait qu'un spécificateur ne provoque pas de conversion. C'est strictement une indication, qui ne change pas la valeur de la chaîne. Un spécificateur est aussi autorisé avant des notations littérales hexadécimale et numérique (x'literal' et 0xnnnn), et avant ? (qui est une substitution de paramètre lorsque l'on utilise des commandes préparées avec une interface de langage de programmation).

Exemples :

SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;
SELECT _latin1 ?;

MySQL détermine le jeu de caractères et la collation de la façon suivante :

- si, à la fois _X et COLLATE Y ont été précisés, alors le jeu de caractères est X et la collation littérale est Y ;

- si _X est précisé mais que COLLATE ne l'est pas, alors le jeu de caractères de la chaîne littérale est X et la collation est la collation par défaut du jeu de caractères X ;

- sinon, on utilise le jeu de caractères et la collation par défaut de la connexion.

Exemples

- Une chaîne avec le jeu de caractères latin1 et la collation latin1_german1_ci :

SELECT _latin1'Müller' COLLATE latin1_german1_ci;

- Une chaîne avec le jeu de caractères latin1 et sa collation par défaut, c'est-à-dire latin1_swedish_ci :

SELECT _latin1'Müller';

- Une chaîne avec le jeu de caractères et la collation connexion/littérale :

SELECT 'Müller';

Les introducteurs de jeux de caractères et la clause COLLATE sont implémentés selon la spécification standard SQL.

10-3-8 - Clause COLLATE dans différentes parties d'une requête SQL

Avec la clause COLLATE, vous pouvez remplacer la collation par défaut, quelle qu'elle soit, par une comparaison. COLLATE peut être utilisé dans différentes parties des requêtes SQL. Voici quelques exemples.

- Avec ORDER BY :

SELECT k
FROM t1
ORDER BY k COLLATE latin1_german2_ci;

- Avec AS :

SELECT k COLLATE latin1_german2_ci AS k1
FROM t1
ORDER BY k1;

- Avec GROUP BY :

SELECT k
FROM t1
GROUP BY k COLLATE latin1_german2_ci;

- Avec les fonctions d'agrégation :

SELECT MAX(k COLLATE latin1_german2_ci)
FROM t1;

- Avec DISTINCT :

SELECT DISTINCT k COLLATE latin1_german2_ci
FROM t1;

- Avec WHERE :

SELECT *
FROM t1
WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;

- Avec HAVING :

SELECT k
FROM t1
GROUP BY k
HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;

10-3-9 - COLLATE clause de précédence

La clause COLLATE a une précédence (plus haute que ||), donc les expressions suivantes sont équivalentes :

x || y COLLATE z
x || (y COLLATE z)

10-3-10 - Opérateur BINARY

L'opérateur BINARY est un raccourci pour une clause COLLATE. Par exemple BINARY 'x' est équivalent à 'x' COLLATE y, où y est le nom d'une collation binaire appropriée. Par exemple, si nous supposons que a appartient au jeu de caractères latin1, les deux requêtes suivantes ont le même effet :

SELECT * FROM t1 ORDER BY BINARY a;
SELECT * FROM t1 ORDER BY a COLLATE latin1_bin;

Note : chaque jeu de caractères a une collation binaire.

10-3-11 - Quelques cas spéciaux où la détermination de la collation est difficile

Dans la grande majorité des requêtes, la collation utilisée par MySQL pour résoudre une comparaison est évidente. Par exemple, dans les cas suivants, il devrait être clair que la collation sera « la collation de colonne de la colonne x » :

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

Cependant, quand des opérandes multiples sont en jeu, il peut y avoir des ambiguïtés. Par exemple :

SELECT x FROM T WHERE x = 'Y';

Cette requête devrait-elle utiliser la collation de la colonne x, ou celle de la chaîne littérale 'Y'?

Le standard SQL résout de telles questions en utilisant ce qui portait le nom de règles coercitives (« coercibility »). L'essence de la question est : puisque x et 'Y' ont tous deux des collations différentes, laquelle a priorité? C'est une question complexe, mais ces règles devraient résoudre la plupart des situations.

- Une clause explicite COLLATE a pour priorité 4.

- Une concaténation de deux chaînes avec des collations différentes a pour priorité 3.

- La collation d'une colonne a priorité 2.

- La collation d'une chaîne littérale a pour priorité 1.

Ces règles résolvent les ambiguïtés de la façon suivante.

- Utiliser la collation qui a la précédence la plus élevée.

- Si les deux opérandes ont une collation de même priorité, alors il y a erreur si les collations ne sont pas les mêmes.

Exemples :

column1 = 'A'

Utilise la collation de la colonne column1

column1 = 'A' COLLATE x

Utilise la collation de 'A'

column1 COLLATE x = 'A' COLLATE y

Erreur

La fonction COERCIBILITY() peut être utilisée pour déterminer la coercibilité d'une chaîne :

mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
-> 0
mysql> SELECT COERCIBILITY('A');
-> 3

Voir Section 12.8.3, « Fonctions d'informations ».

10-3-12 - Les collations doivent correspondre au bon jeu de caractères

Souvenez-vous que chaque jeu de caractères a une ou plusieurs collations, et que chaque collation est associée à un et un seul jeu de caractères. Par conséquent, la commande suivante engendre un message d'erreur, car la collation latin2_bin n'est pas autorisée avec le jeu de caractères latin1 :

mysql> SELECT _latin1 'x' COLLATE latin2_bin;
ERROR 1251: COLLATION 'latin2_bin' is not valid
for CHARACTER SET 'latin1'

Dans certaines cas, les expressions qui fonctionnaient avant MySQL 4.1 échoueront en MySQL 4.1 si vous ne prenez pas en compte les collations et jeux de caractères. Par exemple, avant la version 4.1, cette commande fonctionnait comme :

mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
+-------------------------------+
| SUBSTRING_INDEX(USER(),'@',1) |
+-------------------------------+
| root                          |
+-------------------------------+

Après une mise à jour en MySQL 4.1, la commande échoue :

mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
ERROR 1267 (HY000): Illegal mix of collations
(utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE)
for operation 'substr_index'

La raison à cela est que les noms d'utilisateurs sont stockés en UTF8 (voir Section 10.6, « UTF8 pour les métadonnées »). Par conséquent, la fonction USER() et la chaîne littérale '@' ont des jeux de caractères différents et des collations différentes :

mysql> SELECT COLLATION(USER()), COLLATION('@');
+-------------------+-------------------+
| COLLATION(USER()) | COLLATION('@')    |
+-------------------+-------------------+
| utf8_general_ci   | latin1_swedish_ci |
+-------------------+-------------------+

Un moyen pour corriger cela est de dire à MySQL qu'il doit interpréter les chaînes littérales avec le jeu de caractères utf8 :

mysql> SELECT SUBSTRING_INDEX(USER(),_utf8'@',1);
+------------------------------------+
| SUBSTRING_INDEX(USER(),_utf8'@',1) |
+------------------------------------+
| root                               |
+------------------------------------+

Un autre moyen est de changer le jeu de caractères et la collation de la connexion en utf8. Vous pouvez aussi utiliser la commande SET NAMES 'utf8' ou les variables système character_set_connection et collation_connection.

10-3-13 - Un exemple de l'effet de collation

Supposons que la colonne X dans la table T a ces valeurs de colonne latin1 :

Muffler
Müller
MX Systems
MySQL

Et supposons que les valeurs de la colonne soient récupérées en utilisant la commande suivante :

SELECT X FROM T ORDER BY X COLLATE collation_name;

L'ordre résultant des valeurs pour différentes collations est montré dans cette table :

latin1_swedish_ci

latin1_german1_ci

latin1_german2_ci

Muffler

Muffler

Müller

MX Systems

Müller

Muffler

Müller

MX Systems

MX Systems

MySQL

MySQL

MySQL

Cette table est un exemple qui montre quel effet cela aurait si l'on utilisait des collations différentes dans une clause ORDER BY. Le caractère qui pose problème dans cet exemple est le U avec deux points dessus. Les allemands l'appellent U-umlaut, mais nous l'appellerons U-tréma.

- La première colonne montre le résultat de SELECT en utilisant la collation suédoise/finlandaise, qui dit que le u-tréma est trié comme le Y

- La seconde colonne montre le résultat de SELECT en utilisant la règle German DIN-1, qui dit que le U-tréma est trié comme le U.

- La troisième colonne montre le résultat de SELECT en utilisant la règle German DIN-2 qui dit que le u-tréma est trié comme le UE.

Trois collations différentes engendrent trois résultats différents. MySQL est là pour gérer cela. En utilisant la collation appropriée, vous pouvez choisir l'ordre de tri que vous voulez.

10-4 - Opérations affectées par le support de jeux de caractères

Cette section décrit des opérations qui prennent maintenant en compte des informations sur le jeu de caractères.

10-4-1 - Chaînes résultats

MySQL a de nombreux opérateurs et fonctions qui retournent une chaîne. Cette section répond à la question : quels sont le jeu de caractères et la collation d'une telle chaîne ?

Pour des fonctions simples qui prennent une chaîne en entrée et renvoient une chaîne comme résultat en sortie, le jeu de caractères du résultat et sa collation sont les mêmes que deux de l'argument principal. Par exemple, UPPER(X) renvoie une chaîne dont la chaîne de caractères et la collation sont les mêmes que celles de X.

Le même concept s'applique à : INSTR(), LCASE(), LOWER(), LTRIM(), MID(), REPEAT(), REPLACE(), REVERSE(), RIGHT(), RPAD(), RTRIM(), SOUNDEX(), SUBSTRING(), TRIM(), UCASE(), UPPER(). Veuillez aussi noter que la fonction REPLACE(), contrairement à toutes les autres fonctions, ignore la collation de la chaîne d'entrée et effectue une comparaison insensible à la casse à chaque fois.

Pour des opérations qui combinent des entrées de chaînes multiples et renvoient une chaîne seule en sortie, les « règles d'agrégation » du standard SQL99 s'appliquent. Les règles sont :

- si COLLATE X est explicitement donné, alors on utilise X ;

- si COLLATE X et COLLATE Y sont explicitement donnés, alors erreur ;

- sinon, si toutes les collations sont la même collation X, alors utilise X ;

- sinon, le résultat n'a pas de collation.

Par exemple, avec CASE ... WHEN a THEN b WHEN b THEN c COLLATE X END, la collation résultante est X. L'exemple s'applique à : CONCAT(), GREATEST(), IF(), LEAST(), CASE, UNION, ||, ELT().

Pour des opérations qui convertissent vers des données caractères, le jeu de caractères de la chaîne résultante et sa collation sont dans le jeu de caractères de connexion et ont la collation de connexion.

Ceci s'applique à : CHAR(), CAST(), CONV(), FORMAT(). HEX(), SPACE().

10-4-2 - CONVERT()

CONVERT() fournit une méthode pour convertir des données entre différents jeux de caractères. La syntaxe est :

CONVERT(expr USING transcoding_name)

Avec MySQL, les noms de conversion sont les mêmes que les noms des jeux de caractères correspondants.

Exemples :

SELECT CONVERT(_latin1'Müller' USING utf8);
INSERT INTO utf8table (utf8column)
SELECT CONVERT(latin1field USING utf8) FROM latin1table;

CONVERT(... USING ...) est implémenté selon le standard SQL-99.

10-4-3 - CAST()

Vous pouvez aussi utiliser CAST() pour convertir une chaîne dans un jeu de caractères différent. Le nouveau format est :

CAST ( character_string AS character_data_type
CHARACTER SET character_set_name )

Exemple :

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);

Vous ne pouvez pas utiliser une clause COLLATE dans un CAST(), mais vous pouvez l'utiliser en dehors. Cela revient à dire que CAST(... COLLATE ...) est interdit, mais CAST(...) COLLATE ... est autorisé.

Exemple :

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

Si vous utilisez CAST() sans préciser CHARACTER SET, alors le jeu de caractères et la collation résultants sont le jeu de caractères de la connexion et sa collation par défaut. Si vous utilisez CAST() avec CHARACTER SET X, alors le jeu de caractères résultant est X et la collation résultante est la collation par défaut de X.

10-4-4 - Commande SHOW

Plusieurs commandes SHOW sont nouvelles ou modifiées en MySQL 4.1 pour fournir de nouvelles informations sur les jeux de caractères. SHOW CHARACTER SET, SHOW COLLATION et SHOW CREATE DATABASE sont nouveaux. SHOW CREATE TABLE et SHOW COLUMNS sont modifiés.

La commande SHOW CHARACTER SET affiche tous les jeux de caractères disponibles. Elle accepte la clause optionnelle LIKE qui indique quels noms de caractères rechercher. Par exemple :

mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | ISO 8859-1 West European    | latin1_swedish_ci |      1 |
| latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
+---------+-----------------------------+-------------------+--------+

Voir Section 13.5.3.1, « Commande SHOW CHARACTER SET ».

Le résultat de SHOW COLLATION inclut tous les jeux de caractères disponibles. Elle accepte la clause optionnelle LIKE qui indique quels noms de collation rechercher. Par exemple :

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          |       0 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
| latin1_danish_ci  | latin1  | 15 |         |          |       0 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       0 |
| latin1_general_ci | latin1  | 48 |         |          |       0 |
| latin1_general_cs | latin1  | 49 |         |          |       0 |
| latin1_spanish_ci | latin1  | 94 |         |          |       0 |
+-------------------+---------+----+---------+----------+---------+

Voir Section 13.5.3.2, « Syntaxe de SHOW COLLATION ».

SHOW CREATE DATABASE affiche la commande CREATE DATABASE qui va créer la base de données. Le résultat inclut toutes les options de bases de données. DEFAULT CHARACTER SET et COLLATE sont supportés. Toutes les options sont stockées dans un fichier texte, appelé db.opt qui peut être trouvé dans le fichier de bases de données.

mysql> SHOW CREATE DATABASE a\G
*************************** 1. row ***************************
Database: a
Create Database: CREATE DATABASE `a`
/*!40100 DEFAULT CHARACTER SET macce */

Voir Section 13.5.3.4, « Syntaxe de SHOW CREATE DATABASE ».

SHOW CREATE TABLE est similaire, mais affiche la commande CREATE TABLE pour créer une table donnée. Les définitions de colonnes incluent maintenant toutes les spécifications de jeu de caractères, et les options de tables aussi.

Voir Section 13.5.3.5, « Syntaxe de SHOW CREATE TABLE ».

La commande SHOW COLUMNS affiche la collation des colonnes d'une table, lorsqu'elle est appelée avec SHOW FULL COLUMNS. Les colonnes de type CHAR, VARCHAR et TEXT ont des collations de type non NULL. Les valeurs numériques et non caractères ont des collations NULL. Par exemple :

mysql> SHOW FULL COLUMNS FROM t;
+-------+---------+------------+------+-----+---------+-------+
| Field | Type    | Collation  | Null | Key | Default | Extra |
+-------+---------+------------+------+-----+---------+-------+
| a     | char(1) | latin1_bin | YES  |     | NULL    |       |
| b     | int(11) | NULL       | YES  |     | NULL    |       |
+-------+---------+------------+------+-----+---------+-------+

Le jeu de caractères ne fait pas partie de l'affichage. Le nom du jeu de caractères est lié à la collation.

Voir Section 13.5.3.3, « Syntaxe de SHOW COLUMNS ».

10-5 - Support de Unicode

Depuis la version 4.1 de MySQL, il y deux nouveaux jeux de caractères pour stocker des données Unicode :

- ucs2, le jeu de caractères Unicode UCS-2 ;

- utf8, l'encodage UTF-8 du jeu de caractères Unicode.

En UCS-2 (binary Unicode representation) chaque caractère est représenté par un code Unicode de deux octets avec l'octet le plus significatif en premier. Par exemple : « LATIN CAPITAL LETTER A » a le code 0x0041 et est stocké comme une séquence à deux octets 0x00 0x41. « CYRILLIC SMALL LETTER YERU » (Unicode 0x044B) est stocké comme une séquence à deux octets 0x04 0x4B. Pour les caractères Unicode et leurs codes veuillez consulter Unicode Home Page.

Restriction temporaire : UCS-2 ne peut pas (encore) être utilisé comme jeu de caractères client. Cela signifie que SET NAMES ucs2 ne fonctionnera pas.

Le jeu de caractères UTF8 (transform Unicode representation) est un substitut pour stocker les données Unicode. il est implémenté selon la RFC 2279. L'idée du jeu de caractères UTF-8 est que différents caractères Unicode soient représentés par des séquences de différentes longueurs.

- les lettres, chiffres et caractères de ponctuation latins de base utilisent un octet ;

- la plupart des lettres européennes et moyen-orientales sont stockées avec une séquence à deux octets : les lettres latines étendues (avec les tildes, macrons, accents graves, aigus et autres accents), cyrilliques, grecques, arméniennes, hébreuses, arabes, syriaques et autres ;

- les idéographes coréens, chinois et japonais utilisent des séquences à trois octets.

Actuellement, MySQL UTF8 ne supporte pas les séquences à 4 octets.

Conseil : pour économiser de l'espace avec UTF-8, utilisez VARCHAR au lieu de CHAR. Sinon, MySQL doit réserver 30 octets pour une colonne CHAR(10) CHARACTER SET utf8 parce que c'est la longueur maximale à accepter.

10-6 - UTF8 pour les métadonnées

Les métadonnées sont les données sur les données. Tout ce qui décrit la base de données, par opposition au contenu de la base de données, sont des métadonnées. Ainsi, les noms de colonnes, les noms de bases de données, les noms d'utilisateur, les noms de version et la plupart des résultats chaînes de SHOW, sont des métadonnées.

La représentation des métadonnées doit satisfaire les contraintes suivantes.

- Toutes les métadonnées doivent être dans le même jeu de caractères. Sinon SHOW ne fonctionnerait pas correctement, car des lignes différentes de la même colonne seraient dans des jeux de caractères différents.

- Les métadonnées doivent inclure tous les caractères de toutes les langues. Sinon, les utilisateurs ne pourraient pas nommer les colonnes et les tables dans leur langue.

Pour atteindre ces deux objectifs, MySQL enregistre les métadonnées dans un jeu de caractères Unicode, nommé UTF8. Cela ne causera pas de perturbation si vous n'utilisez jamais de caractères accentués, mais si vous les utilisez, sachez que les métadonnées sont en UTF8.

Cela signifie que les fonctions USER() et ses synonymes, SESSION_USER() et SYSTEM_USER()), CURRENT_USER(), et VERSION() auront le jeu de caractères UTF8 par défaut.

Le serveur assigne la variable système character_set_system avec le jeu de caractères des métadonnées :

mysql> SHOW VARIABLES LIKE 'character_set_system';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_system | utf8  |
+----------------------+-------+

Le stockage des métadonnées utilisant Unicode ne signifie pas que les entêtes et les résultats de la fonction DESCRIBE seront dans le jeu de caractères character_set_system. Lorsque vous envoyez la commande SELECT column1 FROM t, le nom de la colonne column1 sera retourné par le serveur vers le client dans le jeu de caractères déterminé par la commande SET NAMES. Plus spécifiquement, le jeu de caractères est déterminé par la valeur de la variable système character_set_results. Si cette variable vaut NULL, aucune conversion n'est effectuée, et le serveur retourne les données dans leur jeu de caractères original (tel qu'indiqué par character_set_system).

Si vous voulez que le serveur affiche les résultats des métadonnées dans un jeu de caractères autre que UTF8, alors utilisez SET CHARACTER SET pour forcer le serveur faire la conversion (voir Section 10.3.6, « Jeux de caractères et collations de connexion »), ou configurez le client pour qu'il fasse la conversion. Il est toujours plus efficace de configurer le client pour qu'il fasse la conversion, mais ce choix ne sera pas toujours possible pour de nombreux clients jusqu'à tard dans le cycle des produits MySQL 4.x.

Si vous utilisez seulement, par exemple, la fonction USER() pour une comparaison ou une assignation dans une seule commande... ne vous inquiétez pas. MySQL fera des conversions automatiques pour vous.

SELECT * FROM Table1 WHERE USER() = latin1_column;

Ceci fonctionnera, car le contenu de latin1_column est automatiquement converti en UTF8 avant la comparaison.

INSERT INTO Table1 (latin1_column) SELECT USER();

Ceci fonctionnera, car le contenu de USER() est automatiquement converti en latin1 avant l'assignation. La conversion automatique n'est pas encore complètement implémentée, mais devrait fonctionner correctement dans une version ultérieure.

Bien que la conversion automatique ne soit pas un standard SQL, le document de standard SQL dit que chaque jeu de caractères est (en termes de caractères supportés) un « sous-jeu » de l'Unicode.

Comme c'est un principe bien connu que « ce qui s'applique à un super-jeu peut s'appliquer à un sous-jeu », nous croyons que la collation d'Unicode peut s'appliquer à des comparaisons avec des chaînes non Unicode.

10-7 - Compatibilité avec d'autres bases de données

Pour la compatibilité avec SAP DB, les deux commandes suivantes sont identiques :

CREATE TABLE t1 (f1 CHAR(n) UNICODE);
CREATE TABLE t1 (f1 CHAR(n) CHARACTER SET ucs2);

10-8 - Nouveau format de fichier de configuration de jeux de caractères

En MySQL version 4.1, la configuration du jeu de caractères est stockée dans des fichiers XML : un fichier par jeu de caractères. Dans les versions précédentes, cette information était stockée dans les fichiers .conf.

10-9 - Jeux de caractères nationaux

En MySQL version 4.x et plus ancien, NCHAR et CHAR étaient synonymes. ANSI définit NCHAR ou NATIONAL CHAR comme une manière de définir le jeu de caractères par défaut d'une colonne de type CHAR. MySQL utilise utf8 comme jeu de caractères prédéfini. Par exemple, les définitions de ces colonnes sont identiques :

CHAR(10) CHARACTER SET utf8
NATIONAL CHARACTER(10)
NCHAR(10)

de même que :

VARCHAR(10) CHARACTER SET utf8
NATIONAL VARCHAR(10)
NCHAR VARCHAR(10)
NATIONAL CHARACTER VARYING(10)
NATIONAL CHAR VARYING(10)

Vous pouvez utiliser N'literal' pour indiquer qu'une chaîne utilise le jeu de caractères national.

Ces deux commandes sont équivalentes :

SELECT N'some text';
SELECT _utf8'some text';

10-10 - Préparer le passage de version 4.0 en 4.1

Que faut-il faire pour mettre à jour MySQL au niveau des jeux de caractères ? MySQL 4.1 est presque totalement compatible avec les versions 4.0 et plus anciennes, pour la simple raison que toutes les fonctionnalités sont nouvelles, et ne peuvent entrer en conflit avec une version plus ancienne. Cependant, il y a quelques différences qu'il faut avoir en tête.

Le plus important : le « jeu de caractères de MySQL 4.0 » a les caractéristiques des « jeux de caractères de MySQL 4.1 » et des « collations MySQL 4.1. » Vous devez désapprendre cela. Par conséquent, nous n'allons pas rassembler les jeux de caractères et les collations dans le même objet agglomérant.

Il n'y a pas de traitement spécial pour les jeux de caractères nationaux de MySQL 4.1. NCHAR n'est pas le même que CHAR, et les littéraux N'...' sont différents des littéraux '...'.

Finalement, il y a un format de fichier différent pour stocker les informations sur les jeux de caractères et les collations. Assurez-vous d'avoir installé le dossier /share/mysql/charsets/ qui contient les nouveaux fichiers de configuration.

Si vous voulez lancer mysqld dans une installation 4.1.x avec les données de MySQL 4.0, lancez le serveur avec le même jeu de caractères et collation que l'ancien serveur. Dans ce cas, vous n'aurez pas besoin de réindexer vos données.

Voici deux moyens de le faire :

shell> ./configure --with-character-set=... --with-collation=...
shell> ./mysqld --default-character-set=... --default-collation=...

Si vous utilisez mysql avec, par exemple, le jeu de caractères MySQL 4.0 danois, vous devez utiliser maintenant le jeu de caractères latin1 avec la collation latin1_danish_ci :

shell> ./configure --with-character-set=latin1
--with-collation=latin1_danish_ci
shell> ./mysqld --default-character-set=latin1
--default-collation=latin1_danish_ci

Utilisez la table de la section Section 10.10.1, « Jeux de caractères 4.0 et binômes de jeux de caractères/collations 4.1 correspondants » pour retrouver les anciens jeux de caractères 4.0 et leur équivalent 4.1 en jeu de caractères et collations.

Si vous avez des données non latin1 qui sont stockées dans une table 4.0 latin1 et que vous voulez convertir la table pour que les définitions reflètent le véritable jeu de caractères, utilisez les instructions de la section Section 10.10.2, « Conversion de colonnes version 4.0 en version 4.1 ».

10-10-1 - Jeux de caractères 4.0 et binômes de jeux de caractères/collations 4.1 correspondants

ID

Jeu de caractères 4.0

Jeu de caractères 4.1

Collation 4.1

1

big5

big5

big5_chinese_ci

2

czech

latin2

latin2_czech_ci

3

dec8

dec8

dec8_swedish_ci

4

dos

cp850

cp850_general_ci

5

german1

latin1

latin1_german1_ci

6

hp8

hp8

hp8_english_ci

7

koi8_ru

koi8r

koi8r_general_ci

8

latin1

latin1

latin1_swedish_ci

9

latin2

latin2

latin2_general_ci

10

swe7

swe7

swe7_swedish_ci

11

usa7

ascii

ascii_general_ci

12

ujis

ujis

ujis_japanese_ci

13

sjis

sjis

sjis_japanese_ci

14

cp1251

cp1251

cp1251_bulgarian_ci

15

danish

latin1

latin1_danish_ci

16

hebrew

hebrew

hebrew_general_ci

17

win1251

(removed)

(removed)

18

tis620

tis620

tis620_thai_ci

19

euc_kr

euckr

euckr_korean_ci

20

estonia

latin7

latin7_estonian_ci

21

hungarian

latin2

latin2_hungarian_ci

22

koi8_ukr

koi8u

koi8u_ukrainian_ci

23

win1251ukr

cp1251

cp1251_ukrainian_ci

24

gb2312

gb2312

gb2312_chinese_ci

25

greek

greek

greek_general_ci

26

win1250

cp1250

cp1250_general_ci

27

croat

latin2

latin2_croatian_ci

28

gbk

gbk

gbk_chinese_ci

29

cp1257

cp1257

cp1257_lithuanian_ci

30

latin5

latin5

latin5_turkish_ci

31

latin1_de

latin1

latin1_german2_ci

10-10-2 - Conversion de colonnes version 4.0 en version 4.1

Normalement, votre serveur utilise le jeu de caractères par défaut latin1. Si vous avez stocké des données qui sont dans un autre jeu de caractères que ceux supportés par la version 4.1, vous pouvez convertir la colonne. Cependant, vous devriez éviter de convertir directement les colonnes de latin1 vers un « vrai » jeu de caractères. Cela peut conduire à des pertes de données. Au lieu de cela, convertissez la colonne en un type de colonne binaire, avec le jeu de caractères voulu. La conversion avec un format binaire conservera les données intactes. Par exemple, supposez que vous avez une table version 4.0, avec trois colonnes qui sont utilisées pour stocker des valeurs avec les jeux de caractères latin1, latin2 et utf8 :

CREATE TABLE t
(
latin1_col CHAR(50),
latin2_col CHAR(100),
utf8_col CHAR(150)
);

Après mise à jour en MySQL version 4.1, vous pouvez convertir cette table pour qu'elle laisse intacte la colonne latin1_col, mais modifie les colonnes latin2_col et utf8_col pour qu'elles utilisent les jeux de caractères latin2 et utf8. D'abord, sauvez votre table, puis convertissez les colonnes comme ceci :

ALTER TABLE t MODIFY latin2_col BINARY(100);
ALTER TABLE t MODIFY utf8_col BINARY(150);
ALTER TABLE t MODIFY latin2_col CHAR(100) CHARACTER SET latin2;
ALTER TABLE t MODIFY utf8_col CHAR(150) CHARACTER SET utf8;

La première commande « supprime » les informations de jeux de caractères des colonnes latin2_col et utf8_col. Les deux autres commandes assignent le bon jeu de caractères aux deux colonnes.

Si vous voulez, vous pouvez combiner les deux conversions en une seule commande :

ALTER TABLE t
MODIFY latin2_col BINARY(100),
MODIFY utf8_col BINARY(150);
ALTER TABLE t
MODIFY latin2_col CHAR(100) CHARACTER SET latin2,
MODIFY utf8_col CHAR(150) CHARACTER SET utf8;

10-11 - Les jeux de caractères et collation supportés par MySQL

Voici une liste annotée de jeux de caractères et de collations que MySQL supporte. Puisque les options et configurations d'installation diffèrent, certains sites n'auront pas tous ces éléments dans leur liste, et certains sites auront des éléments qui ne sont pas sur la liste, car la définition de nouveaux jeux de caractères ou collations est directe.

MySQL supporte plus de 70 collations pour plus de 30 jeux de caractères.

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |      2 |
| dec8     | DEC West European           | dec8_swedish_ci     |      1 |
| cp850    | DOS West European           | cp850_general_ci    |      1 |
| hp8      | HP West European            | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |      1 |
| latin1   | ISO 8859-1 West European    | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                    | ascii_general_ci    |      1 |
| ujis     | EUC-JP Japanese             | ujis_japanese_ci    |      3 |
| sjis     | Shift-JIS Japanese          | sjis_japanese_ci    |      2 |
| cp1251   | Windows Cyrillic            | cp1251_bulgarian_ci |      1 |
| hebrew   | ISO 8859-8 Hebrew           | hebrew_general_ci   |      1 |
| tis620   | TIS620 Thai                 | tis620_thai_ci      |      1 |
| euckr    | EUC-KR Korean               | euckr_korean_ci     |      2 |
| koi8u    | KOI8-U Ukrainian            | koi8u_general_ci    |      1 |
| gb2312   | GB2312 Simplified Chinese   | gb2312_chinese_ci   |      2 |
| greek    | ISO 8859-7 Greek            | greek_general_ci    |      1 |
| cp1250   | Windows Central European    | cp1250_general_ci   |      1 |
| gbk      | GBK Simplified Chinese      | gbk_chinese_ci      |      2 |
| latin5   | ISO 8859-9 Turkish          | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian          | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 |
| ucs2     | UCS-2 Unicode               | ucs2_general_ci     |      2 |
| cp866    | DOS Russian                 | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak  | keybcs2_general_ci  |      1 |
| macce    | Mac Central European        | macce_general_ci    |      1 |
| macroman | Mac West European           | macroman_general_ci |      1 |
| cp852    | DOS Central European        | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic          | latin7_general_ci   |      1 |
| cp1256   | Windows Arabic              | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic              | cp1257_general_ci   |      1 |
| binary   | Binary pseudo charset       | binary              |      1 |
+----------+-----------------------------+---------------------+--------+
33 rows in set (0.01 sec)

Note : tous les jeux de caractères sont une collation binaire. Nous n'avons pas inclus cette collation dans les descriptions qui suivent.

10-11-1 - Les jeux de caractère Unicode

Il y a deux jeux de caractères Unicode. Vous pouvez stocker des textes dans près de 650 langues en utilisant ces jeux de caractères. Nous n'avons pas encore ajouté un grand nombre de collations pour ces deux nouveaux jeux, mais cela se fera bientôt. Actuellement, ils ont des collations par défaut pour l'insensibilité à la casse et aux accents, plus une collation binaire.

Actuellement, la collation ucs2_general_uca ne supporte que partiellement l'algorithme de collations d'Unicode. Certains jeux de caractères ne sont pas supportés.

- Collations ucs2 (UCS-2 Unicode) :

- ucs2_bin ;

- ucs2_general_ci (par défaut) ;

- ucs2_general_uca.

- Collations utf8 (UTF-8 Unicode) :

- utf8_bin ;

- utf8_general_ci (par défaut).

10-11-2 - Les jeux de caractères d'Europe de l'Ouest

Les jeux de caractères de l'Europe de l'Ouest recouvrent la plupart des langues d'Europe de l'Ouest comme le français, l'espagnol, le catalan, le basque, le portugais, l'italien, l'albanais, le néerlandais, l'allemand le danois, le suédois, le norvégien, le finlandais, le faroe, l'islandais, l'irlandais, l'écossais, et l'anglais.

- Collations ascii (US ASCII) :

- ascii_bin ;

- ascii_general_ci (par défaut).

- Collations cp850 (DOS West European) :

- cp850_bin ;

- cp850_general_ci (par défaut).

- Collations dec8 (DEC West European) :

- dec8_bin ;

- dec8_swedish_ci (par défaut).

- Collations hp8 (HP West European) :

- hp8_bin ;

- hp8_english_ci (par défaut).

- Collations latin1 (ISO 8859-1 West European) :

- latin1_bin ;

- latin1_danish_ci ;

- latin1_general_ci ;

- latin1_general_cs ;

- latin1_german1_ci ;

- latin1_german2_ci ;

- latin1_spanish_ci ;

- latin1_swedish_ci (par défaut).

Le jeu de caractères latin1 est le jeu de caractères par défaut. La collation latin1_swedish_ci est la collation par défaut qui est probablement utilisée par la majorité des clients de MySQL. Il est souvent dit que ceci est basé sur les règles de collation suédoises/finlandaises, mais vous trouverez des suédois et des finlandais qui ne sont pas d'accord avec cette affirmation.

Les collations latin1_german1_ci et latin1_german2_ci sont basées sur les standards DIN-1 and DIN-2, où DIN signifie Deutsches Institut für Normung (c'est la contrepartie allemande d'ANSI). DIN-1 est appelée la collation dictionnaire et DIN-2 est appelée la collation annuaire.

- règles latin1_german1_ci (dictionnaire) : 'Ä' = 'A', 'Ö' = 'O', 'Ü' = 'U', 'ß' = 's' ;

- règles latin1_german2_ci (annuaire) : 'Ä' = 'AE', 'Ö' = 'OE', 'Ü' = 'UE', 'ß' = 'ss'.

Dans la collation latin1_spanish_ci, 'Ñ' (N-tilde) est une lettre séparée entre 'N' et 'O'.

- Collations macroman (Mac West European) :

- macroman_bin ;

- macroman_general_ci (par défaut).

- Collations swe7 (7 bits Swedish) :

- swe7_bin :

- swe7_swedish_ci (par défaut).

10-11-3 - Les jeux de caractères d'Europe centrale

MySQL supporte les jeux de caractères utilisés en République tchèque, en Slovaquie, Hongrie, Roumanie, Slovénie, Croatie, et Pologne.

- collations cp1250 (Windows Central European) :

- cp1250_bin ;

- cp1250_czech_ci ;

- cp1250_general_ci (par défaut).

- collations cp852 (DOS Central European) :

- cp852_bin ;

- cp852_general_ci (par défaut).

- collations keybcs2 (DOS Kamenicky Czech-Slovak) :

- keybcs2_bin ;

- keybcs2_general_ci (par défaut).

- collations latin2 (ISO 8859-2 Central European) :

- latin2_bin ;

- latin2_croatian_ci ;

- latin2_czech_ci ;

- latin2_general_ci (par défaut) ;

- latin2_hungarian_ci.

- collations macce (Mac Central European) :

- macce_bin ;

- macce_general_ci (par défaut).

10-11-4 - Jeu de caractères pour l'Europe du Sud et le Moyen-Orient

- Collations armscii8 (ARMSCII-8 Armenian) :

- armscii8_bin ;

- armscii8_general_ci (par défaut).

- Collations cp1256 (Windows Arabic) :

- cp1256_bin ;

- cp1256_general_ci (par défaut).

- Collations geostd8 (GEOSTD8 Georgian) :

- geostd8_bin ;

- geostd8_general_ci (par défaut).

- Collations greek (ISO 8859-7 Greek) :

- greek_bin ;

- greek_general_ci (par défaut).

- Collations hebrew (ISO 8859-8 Hebrew) :

- hebrew_bin ;

- hebrew_general_ci (par défaut).

- Collations latin5 (ISO 8859-9 Turkish) :

- latin5_bin ;

- latin5_turkish_ci (par défaut).

10-11-5 - Les jeux de caractères baltes

Les jeux de caractères baltes couvrent les langues estonienne, lettonne et lituanienne. Il y a actuellement deux jeux de caractères baltiques supportés :

- Collations cp1257 (Windows Baltic) :

- cp1257_bin ;

- cp1257_general_ci (par défaut) ;

- cp1257_lithuanian_ci.

- Collations latin7 (ISO 8859-13 Baltic) :

- latin7_bin ;

- latin7_estonian_cs ;

- latin7_general_ci (par défaut) ;

- latin7_general_cs.

10-11-6 - Les jeux de caractère cyrilliques

Voici les jeux de caractères cyrilliques et les collations à utiliser avec les langues suivantes : biélorusse, bulgare, russe, ukrainien.

- Collations cp1251 (Windows Cyrillic) :

- cp1251_bin ;

- cp1251_bulgarian_ci ;

- cp1251_general_ci (par défaut) ;

- cp1251_general_cs ;

- cp1251_ukrainian_ci.

- Collations cp866 (DOS Russian) :

- cp866_bin ;

- cp866_general_ci (par défaut).

- Collations koi8r (KOI8-R Relcom Russian) :

- koi8r_bin ;

- koi8r_general_ci (par défaut).

- Collations koi8u (KOI8-U Ukrainian) :

- koi8u_bin ;

- koi8u_general_ci (par défaut).

10-11-7 - Les jeux de caractères asiatiques

Les jeux de caractères asiatiques que nous supportons incluent le chinois, le japonais, le coréen et le thaïlandais. Ces jeux peuvent être compliqués. Par exemple, les jeux chinois doivent permettre des milliers de caractères différents.

- Collations big5 (Big5 Traditional Chinese) :

- big5_bin ;

- big5_chinese_ci (par défaut).

- Collations euckr (EUC-KR Korean) :

- euckr_bin ;

- euckr_korean_ci (par défaut).

- Collations gb2312 (GB2312 Simplified Chinese) :

- gb2312_bin ;

- gb2312_chinese_ci (par défaut).

- Collations gbk (GBK Simplified Chinese) :

- gbk_bin ;

- gbk_chinese_ci (par défaut).

- Collations sjis (Shift-JIS Japanese) :

- sjis_bin ;

- sjis_japanese_ci (par défaut).

- Collations tis620 (TIS620 Thai) :

- tis620_bin ;

- tis620_thai_ci (par défaut).

- Collations ujis (EUC-JP Japanese) :

- ujis_bin ;

- ujis_japanese_ci (par défaut).

11 - Types de colonnes

MySQL supporte un grand nombre de types de colonnes, qui peuvent être rassemblées en trois catégories : les types numériques, temporels et chaînes. Cette section vous donne un aperçu des types disponibles, et résume les besoins de stockage de chaque colonne, puis fournit une description détaillée des propriétés de chaque type de données. Cette présentation est volontairement courte. Les descriptions détaillées peuvent être consultées pour plus d'informations sur chaque type, comme les formats autorisés.

MySQL 4.1 et plus récentes supportent des extensions pour gérer les données géographiques. Des informations sur ces types sont disponibles dans la section Chapitre 18, Données spatiales avec MySQL.

Plusieurs définitions de colonnes partagent la même convention :

- M

indique la taille maximale d'affichage. La taille maximale légale est de 255 ;

- D

s'applique aux types à virgule flottante, et indique le nombre de chiffres qui suivent la virgule décimale. Le nombre maximal est de 30, mais ne devrait pas dépasser M-2 ;

- []

les crochets ('[' et ']') indiquent des spécifications qui sont optionnelles.

11-1 - Introduction aux types de colonnes

11-1-1 - Présentation des types numériques

Un résumé des colonnes numériques suit. Pour plus de détails sur les types numériques, voyez la section Section 11.2, « Types numériques ». La taille des colonnes est dans la section Section 11.5, « Capacités des colonnes ».

Si vous spécifiez l'option ZEROFILL pour une valeur numérique, MySQL va automatiquement ajouter l'attribut UNSIGNED à la colonne.

Attention : soyez conscient que lorsque vous utilisez la soustraction entre deux entiers, dont l'un est de type UNSIGNED, le résultat sera sans signe ! Voir Section 12.7, « Fonctions de transtypage ».

- TINYINT[(M)] [UNSIGNED] [ZEROFILL]

Un très petit entier. L'intervalle de validité pour les entiers signés est de -128 à 127. L'intervalle de validité pour les entiers non signés est 0 à 255.

- BIT, BOOL, BOOLEAN

Ce sont des synonymes de TINYINT(1). Le synonyme BOOLEAN a été ajouté en version 4.1.0.

Un type booléen complet, qui sera introduit pour être en accord avec la norme SQL-99.

- SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

Un petit entier. L'intervalle de validité pour les entiers signés est de -32768 à 32767. L'intervalle de validité pour les entiers non signés est 0 à 65535.

- MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]

Un entier. L'intervalle de validité pour les entiers signés est de -8388608 à 8388607. L'intervalle de validité pour les entiers non signés est 0 à 16777215.

- INT[(M)] [UNSIGNED] [ZEROFILL]

Un grand entier. L'intervalle de validité pour les entiers signés est de -2147483648 à 2147483647. L'intervalle de validité pour les entiers non signés est 0 à 4294967295.

- INTEGER[(M)] [UNSIGNED] [ZEROFILL]

Ceci est un synonyme INT.

- BIGINT[(M)] [UNSIGNED] [ZEROFILL]

Un très grand entier. L'intervalle de validité pour les entiers signés est de -9223372036854775808 à 9223372036854775807. L'intervalle de validité pour les entiers non signés est 0 à 18446744073709551615.

Quelques conseils à suivre avec les colonnes de type BIGINT :

- tous les calculs arithmétiques sont faits en utilisant des BIGINT signés ou des valeurs DOUBLE. Il est donc recommandé de ne pas utiliser de grands entiers non signés dont la taille dépasse 9223372036854775807 (63 bits), hormis avec les fonctions sur les bits ! Si vous faites cela, les derniers chiffres du résultat risquent d'être faux, à cause des erreurs d'arrondis lors de la conversion de BIGINT en DOUBLE.

MySQL 4.0 peut gérer des BIGINT dans les cas suivants.

- Utiliser des entiers pour stocker des grandes valeurs entières non signées, dans une colonne de type BIGINT.

- Avec MIN(big_int_column) et MAX(big_int_column).

- Avec les opérateurs (+, -, *, etc.) où tous les opérandes sont des entiers.

- Vous pouvez toujours stocker une valeur entière exacte BIGINT dans une colonne de type chaîne. Dans ce cas, MySQL fera des conversions chaîne/nombre, qui n'utilisera pas de représentation intermédiaire en nombres réels.

- '-', '+' et '*' utiliseront l'arithmétique entière des BIGINT lorsque les deux arguments sont des entiers. Cela signifie que si vous multipliez deux entiers (ou des résultats de fonctions qui retournent des entiers), vous pourriez rencontrer des résultats inattendus lorsque le résultat est plus grand que 9223372036854775807.

- FLOAT(precision) [UNSIGNED] [ZEROFILL]

Un nombre à virgule flottante. precision peut valoir <=24 pour une précision simple, et entre 25 et 53 pour une précision double. Ces types sont identiques aux types FLOAT et DOUBLE, décrits ci-dessous. FLOAT(X) a le même intervalle de validité que FLOAT et DOUBLE, mais la taille d'affichage et le nombre de décimales sont indéfinis.

En MySQL version 3.23, c'est un véritable nombre à virgule flottante. Dans les versions antérieures, FLOAT(precision) avait toujours 2 décimales.

Notez qu'utiliser FLOAT peut vous donner des résultats inattendus, car tous les calculs de MySQL sont faits en double précision. Voir Section A.5.7, « Résoudre les problèmes des lignes non retournées ».

Cette syntaxe est fournie pour assurer la compatibilité avec ODBC.

Utiliser des FLOAT peut vous donner des résultats inattendus, car les calculs sont faits en précision double. Voir Section A.5.7, « Résoudre les problèmes des lignes non retournées ».

- FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

Un petit nombre à virgule flottante, en précision simple. Les valeurs possibles vont de -3.402823466E+38 à -1.175494351E-38, 0, et 1.175494351E-38 à 3.402823466E+38. Si UNSIGNED est spécifié, les valeurs négatives sont interdites. L'attribut M indique la taille de l'affichage, et D est le nombre de décimales. FLOAT sans argument et FLOAT(X) (où X est dans l'intervalle 0 à 24) représente les nombres à virgule flottante en précision simple.

- DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

Un nombre à virgule flottante, en précision double. Les valeurs possibles vont de -1.7976931348623157E+308 à -2.2250738585072014E-308, 0, et 2.2250738585072014E-308 à 1.7976931348623157E+308. Si UNSIGNED est spécifié, les valeurs négatives sont interdites. L'attribut M indique la taille de l'affichage, et D est le nombre de décimales. DOUBLE sans argument et FLOAT(X) (où X est dans l'intervalle 25 à 53) représente les nombres à virgule flottante en précision double.

- DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]

Ce sont des synonymes pour DOUBLE.

Exception : si le serveur SQL utilise l'option REAL_AS_FLOAT, REAL est alors un synonyme de FLOAT plutôt que DOUBLE.

- DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

Un nombre à virgule flottante littéral. Il se comporte comme une colonne de type CHAR : « littéral » (« unpacked ») signifie que le nombre est stocké sous forme de chaîne : chaque caractère représente un chiffre. La virgule décimale et le signe moins '-' des nombres négatifs ne sont pas comptés dans M (mais de l'espace leur est réservé). Si D vaut 0, les valeurs n'auront pas de virgule décimale ou de partie décimale. L'intervalle de validité du type DECIMAL est le même que DOUBLE, mais le vrai intervalle de validité de DECIMAL peut être restreint par le choix de la valeur de M et D. Si UNSIGNED est spécifié, les valeurs négatives sont interdites.

Si D est omis, la valeur par défaut est 0. Si M est omis, la valeur par défaut est 10.

Avant MySQL Version 3.23, l'argument M devait inclure l'espace nécessaire pour la virgule et le signe moins.

- DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]

Ce sont des synonymes pour DECIMAL.

L'alias FIXED a été ajouté en version 4.1.0 pour assurer la compatibilité avec les autres serveurs.

11-1-2 - Présentation des types de données temporels : dates et heures

Une description succincte des types de données temporels suit. Pour plus d'informations, voyez la section Section 11.3, « Les types date et heure ». La taille de stockage des valeurs est présentée dans la section Section 11.5, « Capacités des colonnes ».

- DATE

Une date. L'intervalle supporté va de '1000-01-01' à '9999-12-31'. MySQL affiche les valeurs de type DATE au format 'YYYY-MM-DD', mais vous permet d'assigner des valeurs DATE en utilisant plusieurs formats de chaînes et nombres.

- DATETIME

Une combinaison de date et heure. L'intervalle de validité va de '1000-01-01 00:00:00' à '9999-12-31 23:59:59'. MySQL affiche les valeurs de type DATE au format 'YYYY-MM-DD HH:MM:SS', mais vous permet d'assigner des valeurs DATE en utilisant plusieurs formats de chaînes et nombres.

- TIMESTAMP[(M)]

Un timestamp. L'intervalle de validité va de '1970-01-01 00:00:00' à quelque part durant l'année 2037.

En MySQL 4.0 et plus récent, les valeurs TIMESTAMP sont affichées au format YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD ou YYMMDD, suivant que la valeur de M est 14 (ou absente), 12, 8 ou 6, respectivement, mais vous permet d'assigner des valeurs aux colonnes TIMESTAMP en utilisant des nombres ou des chaînes.

Depuis MySQL 4.1, TIMESTAMP est retournée comme une chaîne, au format 'YYYY-MM-DD HH:MM:SS'. Si vous voulez que MySQL vous retourne un nombre, ajoutez +0 à la colonne. Les différentes tailles de timestamp ne sont pas supportées. Depuis la version 4.0.12, l'option --new peut être utilisée pour que le serveur adopte le comportement de la version 4.1.

Une colonne TIMESTAMP est utile pour enregistrer les dates et heures des opérations INSERT et UPDATE, car elle prend automatiquement date actuellement si vous ne lui assignez pas de valeur par vous-même. Vous pouvez aussi lui donner la valeur courante en lui donnant la valeur NULL.

L'argument M affecte l'affichage des colonnes de type TIMESTAMP. Ses valeurs sont toujours stockées sur 4 octets.

Notez que les colonnes TIMESTAMP(M) où M vaut 8 ou 14 sont indiquées comme étant des nombres, alors que les colonnes TIMESTAMP(M) sont indiquées comme étant des chaînes. Cela est fait pour s'assurer que l'ont peut enregistrer et lire correctement les tables ayant ce type.

- TIME

Une heure. L'intervalle va de '-838:59:59' à '838:59:59'. MySQL affiche les valeurs TIME au format 'HH:MM:SS', mais vous permet d'assigner des valeurs TIME en utilisant des nombres ou des chaînes.

- YEAR[(2|4)]

Une année, au format 2 ou 4 chiffres (par défaut, c'est 4 chiffres). Les valeurs possibles vont de 1901 à 2155 plus 0000 pour le format à 4 chiffres, et de 1970 à 2069 si vous utilisez le format à 2 chiffres. MySQL affiche les valeurs YEAR au format YYYY, mais vous permet d'assigner des valeurs en utilisant des nombres ou des chaînes. Le type YEAR n'est pas disponible avant la version 3.22.

11-1-3 - Présentation des types de chaînes

Voici une présentation sommaire des types chaînes de caractères. Pour plus d'informations, voyez Section 11.4, « Les types chaînes ». Les tailles de stockage des lignes sont données dans Section 11.5, « Capacités des colonnes ».

Dans certains cas, MySQL change le type d'une colonne en un autre, lors de l'utilisation des commandes CREATE TABLE et ALTER TABLE. Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

Une modification qui affecte de nombreux types de colonnes est que depuis MySQL version 4.1.1, les définitions de colonnes peuvent inclure l'attribut CHARACTER SET pour spécifier le jeu de caractères, et, éventuellement, la collation de la colonne. Cela s'applique à CHAR, VARCHAR, les types TEXT types, ENUM et SET. Par exemple :

CREATE TABLE t
(
c1 CHAR(20) CHARACTER SET utf8,
c2 CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin
);

Cette définition de table crée une colonne appelée c1 dont le jeu de caractères est utf8 avec la collation par défaut de ce jeu de caractères, et une colonne appelée c2 qui a le jeu de caractères latin1 et la collation binaire du jeu de caractères. La collation binaire n'est pas sensible à la casse.

Le tri et les comparaisons de colonnes sont basés sur le jeu de caractères de la colonne. Avant MySQL 4.1, les tris et comparaisons étaient faits avec la collation du jeu de caractères du serveur. Pour les colonnes CHAR et VARCHAR, vous pouvez déclarer la colonne avec l'attribut BINARY pour que le tri et la recherche soient insensibles à la casse, utilisant le jeu de caractères sous-jacent, plutôt qu'un ordre lexical.

Pour plus de détails, voyez Chapitre 10, Jeux de caractères et Unicode.

De plus, depuis la version 4.1, MySQL interprète les spécifications de taille d'une colonne en termes de nombre de caractères. Les versions précédentes interprétaient les tailles en nombre d'octets.

- [NATIONAL] CHAR(M) [BINARY | ASCII | UNICODE]

Une chaîne de caractères de taille fixe, toujours complété à droite par des espaces pour remplir l'espace de stockage. L'intervalle de M va de 0 à 255 (1 à 255 pour les versions antérieures à la version 3.23). Les espaces terminaux sont supprimés lorsque la valeur est relue. Les valeurs CHAR sont triées et comparées sans tenir compte de la casse, en utilisant le jeu de caractères par défaut, à moins que le mot-clé BINARY ne soit utilisé.

Note : les espaces terminaux sont supprimés lorsque la valeur est stockée.

Depuis la version 4.1.0, si la valeur M est supérieure à 255, une colonne de type TEXT est créée. Ceci est une fonctionnalité de compatibilité.

NATIONAL CHAR (sous son équivalent raccourci NCHAR) est le nom SQL-99 pour définir une colonne de type CHAR qui utilise le jeu de caractères par défaut. C'est le comportement par défaut de MySQL.

CHAR est un raccourci pour CHARACTER.

Depuis la version 4.1.0, l'attribut ASCII peut être spécifié avec, pour assigner le jeu de caractères latin1 à une colonne de type CHAR.

Depuis la version 4.1.1, l'attribut UNICODE peut être spécifié pour assigner le jeu de caractères ucs2 à une colonne CHAR.

MySQL permet la création d'une colonne de type CHAR(0). Ceci est principalement utile dans de vieilles applications, qui ont besoin de la colonne, mais n'ont pas besoin de la valeur. C'est aussi pratique pour avoir une colonne à deux valeurs : un CHAR(0), qui n'est pas défini comme NOT NULL, va occuper un bit, et prendre deux valeurs : NULL ou "".

- CHAR

Ceci est un synonyme de CHAR(1).

- [NATIONAL] VARCHAR(M) [BINARY]

Une chaîne de taille dynamique. M représente la taille maximale de la valeur dans une colonne. L'intervalle de M va de 0 à 255 caractères (1 à 255 avant MySQL 4.0.2).

Note : les espaces terminaux sont supprimés lorsque la valeur est stockée (cela diffère des spécifications de SQL-99).

Depuis la version 4.1.0, si la valeur M est supérieure à 255, Une colonne de type TEXT est créée. Ceci est une fonctionnalité de compatibilité. Par exemple une colonne VARCHAR(500) est convertie en TEXT, et VARCHAR(200000) est convertie en MEDIUMTEXT. Attention, cette conversion affecte la suppression des espaces finals...

VARCHAR est un raccourci pour CHARACTER VARYING.

- TINYBLOB, TINYTEXT

Une colonne TINYBLOB ou TINYTEXT peut contenir au maximum 255 (2^8 - 1) caractères.

- BLOB, TEXT

Une colonne TEXT ou BLOB peut contenir au maximum 65535 (2^16 - 1) caractères.

- MEDIUMBLOB, MEDIUMTEXT

Une colonne MEDIUMTEXT ou MEDIUMBLOB peut contenir au maximum 16777215 (2^24 - 1) caractères.

- LONGBLOB, LONGTEXT

Une colonne LONGTEXT ou LONGBLOB peut contenir au maximum 4294967295 ou 4 Go (2^32 - 1) caractères. Jusqu'en version 3.23 le protocole client/serveur et les tables MyISAM avaient une limite de 16 Mo par paquet de communication pour une ligne de table. Depuis les versions 4.x, la taille maximale d'un LONGTEXT ou LONGBLOB dépend de la taille maximale de paquet de communication pour le protocole de communication, et de la mémoire disponible.

- ENUM('value1','value2',...)

Une énumération. Un objet chaîne qui peut prendre une valeur, choisie parmi une liste de valeurs 'valeur1', 'valeur2', ..., NULL ou la valeur spéciale d'erreur "". Une valeur ENUM peut avoir un maximum de 65535 valeurs distinctes.

- SET('value1','value2',...)

Un ensemble. Un objet chaîne, qui peut prendre zéro, une ou plusieurs valeurs, choisies parmi une liste de valeurs 'valeur1', 'valeur2', ... Une valeur SET peut avoir un maximum de 64 membres.

11-2 - Types numériques

MySQL supporte tous les types numériques de la norme ANSI/ISO SQL92. Ceux-ci représentent les types numériques exacts (NUMERIC, DECIMAL, INTEGER, et SMALLINT), ainsi que les types approchés (FLOAT, REAL, et DOUBLE PRECISION). Le mot-clé INT est un synonyme de INTEGER, et le mot-clé DEC est un synonyme de DECIMAL.

Les types NUMERIC et DECIMAL sont considérés comme identiques par MySQL, comme l'autorise le standard SQL92. Ils sont utilisés par des valeurs dont il est primordial de conserver la précision exacte, comme pour des données financières. Lorsque vous déclarez des colonnes avec l'un de ces types, vous pouvez indiquer la précision et l'échelle comme ceci :

salaire DECIMAL(5,2)

Dans cet exemple, 5 (précision) représente le nombre de décimales signifiantes qui seront stockées pour les valeurs, et 2 (échelle) représente le nombre de chiffres qui seront stockés après le symbole des décimales.

Les valeurs de type DECIMAL et NUMERIC sont stockées sous forme de chaînes de caractères, plutôt que comme des nombres à virgule flottante, afin de préserver la précision décimale des valeurs. Un caractère est donc nécessaire pour chaque chiffre, plus la virgule (si scale > 0), et le signe moins '-' (pour les nombres négatifs). Si scale vaut 0, les valeurs de type DECIMAL et NUMERIC ne comporteront pas de valeur décimale, ni de virgule.

Les standards SQL requièrent que la colonne salary soit capable de stocker toute valeur de 5 chiffres et 2 décimales. Dans ce cas, l'intervalle de valeurs qui peuvent être stockées dans la colonne salary va de -999.99 et 999.99. MySQL dévie de cette spécification de deux manières :

- à la limite supérieure de l'intervalle, la colonne peut stocker les nombres jusqu'à 9999.99. Pour les nombres positifs, MySQL utilise l'octet réservé au signe pour étendre la limite supérieure ;

- les colonnes DECIMAL de MySQL avant 3.23 sont stockées différemment et ne peuvent pas représenter toutes les valeurs requises par le standard SQL. Ceci est dû au fait que pour DECIMAL(M,D), la valeur de M inclut les octets pour le signe et le point décimal. L'intervalle de la colonne salary avant MySQL 3.23 serait de -9.99 à 99.99.

Avec les standards SQL, la syntaxe DECIMAL(p) est équivalente à DECIMAL(p,0). De manière similaire, la syntaxe DECIMAL est équivalente à DECIMAL(p,0), où l'implémentation est autorisée à choisir la valeur de p. Depuis MySQL 3.23.6, ces deux variantes de DECIMAL et NUMERIC sont supportées. La valeur par défaut de M est 10. Avant la version 3.23.6, M et D devaient être spécifiés explicitement.

L'intervalle de validité maximal des valeurs de type DECIMAL et NUMERIC est le même que pour le type DOUBLE, mais l'intervalle réel peut être limité par le choix des paramètres précision et scale. Lorsqu'une valeur ayant trop de décimales est affectée à une colonne, la valeur est arrondie à scale décimales. Lorsqu'une valeur est hors des limites de validité de la colonne DECIMAL ou NUMERIC, MySQL enregistre la plus grande valeur qu'il peut à la place.

En extension de la norme ANSI/ISO SQL92, MySQL supporte aussi les types entiers TINYINT, MEDIUMINT, et BIGINT, comme présenté ci-dessus. Une autre extension supportée par MySQL permet de spécifier optionnellement la taille d'affichage, sous la forme d'une valeur entière entre parenthèses, juste après le mot-clé spécifiant le type (par exemple, INT(4)). Cette spécification de taille est utilisée pour remplir à gauche, avec le caractère de remplissage par défaut, les nombres dont la taille est inférieure à celle spécifiée, mais uniquement à l'affichage : cela ne réduit pas l'intervalle de validité des valeurs qui peuvent être stockées dans la colonne.

Lorsqu'elle est utilisée avec l'attribut de colonne optionnel ZEROFILL, le caractère de remplissage par défaut est remplacé par le caractère zéro. Par exemple, pour une colonne dont le type est INT(5) ZEROFILL, la valeur 4 sera lue 00004.

Notez que si vous stockez des nombres plus grands que la taille maximale d'affichage, vous pouvez rencontrer des problèmes lors de jointures de tables particulièrement compliquées, surtout si MySQL génère des tables temporaires : dans ce cas, MySQL pense que les données étaient limitées par l'affichage.

Tous les types entiers ont un attribut optionnel (non standard) UNSIGNED (non signé, en français). Les valeurs non signées peuvent être utilisées pour n'autoriser que des valeurs positives dans une colonne, ou bien pour exploiter un intervalle de validité plus haut. Depuis la version 4.0.2 de MySQL, les nombres à virgule flottante peuvent aussi être UNSIGNED Comme avec les types entiers, cet attribut interdit les valeurs négatives dans la colonne, mais n'élève pas l'intervalle de validité.

Le type FLOAT est utilisé pour représenter des données numériques approchées. La norme ANSI/ISO SQL92 permet la spécification optionnelle de la précision (mais pas de l'intervalle de validité) en fournissant le nombre de décimales voulues après la spécification de type, et entre parenthèses. L'implémentation de MySQL supporte aussi le paramétrage de la précision. Si le mot-clé FLOAT est utilisé pour une colonne sans précision supplémentaire, MySQL utilise quatre octets pour stocker les valeurs. Une syntaxe alternative existe aussi, elle utilise deux paramètres optionnels après le mot-clé FLOAT. Avec cette option, le premier nombre représente toujours la taille de stockage nécessaire pour la valeur, et le second nombre représente le nombre de chiffres à stocker et afficher, après la virgule décimale (comme pour les types DECIMAL et NUMERIC). Lorsque MySQL stocke un nombre pour une telle colonne, et que cette valeur a plus de décimales que requis, la valeur est arrondie pour éliminer les chiffres surnuméraires.

Les types REAL et DOUBLE PRECISION n'acceptent pas de paramétrage de la précision. En extension du standard ANSI/ISO SQL92, MySQL reconnaît DOUBLE comme un synonyme du type DOUBLE PRECISION. Contrairement à la norme qui requiert que REAL soit plus petit que DOUBLE PRECISION, MySQL implémente ces deux types comme des nombres à virgule flottante de 8 octets, en double précision (lorsque le mode « ANSI » n'est pas activé). Pour une portabilité maximale, les applications réclamant le stockage de nombres approchés doivent utiliser les types FLOAT ou DOUBLE PRECISION sans spécification de précision ou de nombre de décimales.

Lorsque MySQL doit stocker une valeur qui est hors de l'intervalle de validité d'une colonne, il ramène la valeur à la plus proche possible, et stocke cette valeur. Par exemple, l'intervalle de validité d'une colonne d'entiers INT va de -2147483648 à 2147483647. Si vous essayez d'insérer -9999999999 dans une colonne de ce type, la valeur sera ramenée à la plus proche possible, c'est-à-dire -2147483648. De même, si vous essayez d'insérer 9999999999, 2147483647 sera stocké à la place.

Si la colonne INT possède l'attribut UNSIGNED, l'intervalle de validité est aussi large, mais les valeurs extrêmes se décalent vers 0 et 4294967295. Si vous essayez de stocker -9999999999 et 9999999999 dans cette colonne, vous obtiendrez respectivement 0 et 4294967296.

Les dépassements de capacité entraînant des troncatures sont affichés comme des alertes (« warnings ») lors de l'utilisation des commandes ALTER TABLE, LOAD DATA INFILE, UPDATE, et les insertions INSERT multiples.

Type

Octets

De

A

TINYINT

1

-128

127

SMALLINT

2

-32768

32767

MEDIUMINT

3

-8388608

8388607

INT

4

-2147483648

2147483647

BIGINT

8

-9223372036854775808

9223372036854775807

11-3 - Les types date et heure

Les types date et heure sont DATETIME, DATE, TIMESTAMP, TIME, et YEAR. Chacun d'eux à une échelle de valeurs légales, de même que la valeur « zéro » quand vous spécifiez une valeur illégale. À noter que MySQL vous permet d'enregistrer certaines dates qui ne sont pas strictement légales, par exemple 1999-11-31. La raison est que nous pensons que la vérification des dates est à faire niveau application. Pour accélérer les tests, MySQL vérifie juste que le mois est entre 0 et 12 et que le jour est entre 0 et 31. Les intervalles précédents sont définis de cette façon, car MySQL vous permet d'enregistrer dans une colonne DATE ou DATETIME, des dates où le jour de la semaine ou le jour du mois est zéro. C'est extrêmement utile pour les applications où vous avez besoin d'enregistrer une date d'anniversaire pour laquelle vous n'avez pas la date exacte. Dans ce cas, vous enregistrez simplement la date comme 1999-00-00 ou 1999-01-00. (Vous ne devez pas vous attendre à obtenir de valeurs correctes de fonctions telles que DATE_SUB() ou DATE_ADD pour des dates comme cela.)

Voici quelques considérations à garder à l'esprit quand vous manipulerez ce type de champs.

- MySQL extrait les valeurs d'un champ date ou heure dans un format standard, mais essaye d'interpréter une grande variété de formats pour les valeurs que vous donnez (par exemple, quand vous essayez de comparer ou attribuer une valeur à un champ de type date ou heure). Néanmoins, seuls les formats décrits dans les sections suivantes sont disponibles. Il est attendu que vous fournissiez des valeurs légales et des erreurs imprévues peuvent survenir si vous utilisez d'autre formats.

- Même si MySQL essaye d'interpréter les valeurs sous différents formats, il s'attend toujours à ce que l'année soit dans la partie gauche de la valeur. Les dates doivent être données sous la forme année-mois-jour (exemple : 98-09-04), au lieu de mois-jour-année ou jour-mois-année qui sont très utilisés ailleurs (comme 09-04-98 ou '04-09-98').

- Les dates représentées par deux chiffres pour les années sont ambigües, car le siècle n'est pas connu. MySQL interprète les années sur deux chiffres suivant les règles suivantes :

- si l'année est dans l'intervalle 00-69, elle est convertie en 2000-2069 ;

- si l'année est dans l'intervalle 70-99, elle est convertie en 1970-1999.

- MySQL convertit automatiquement une date ou heure en nombre si la valeur est utilisée dans un contexte numérique et vice versa.

- Lorsque MySQL rencontre une valeur hors d'intervalle pour un type date ou heure qui est donc illégale pour ce type (voir le début de cette section), il la convertit à la valeur « zéro » de ce type. (L'exception est que les valeurs hors intervalle pour les champs TIME sont coupées à la limite appropriée des valeurs de TIME.) Le tableau suivant présente le format de la valeur « zéro » de chaque type :

Column type

valeur du « zéro »

DATETIME

'0000-00-00 00:00:00'

DATE

'0000-00-00'

TIMESTAMP

00000000000000 (la longueur dépend de la taille de l'affichage)

TIME

'00:00:00'

YEAR

0000

- La valeur « zéro » est spéciale, mais vous pouvez l'enregistrer ou vous y référer explicitement en utilisant les valeurs contenues dans le tableau ci-dessus. Vous pouvez aussi le faire en utilisant la valeur '0' ou 0 qui est plus facile à manipuler.

- La date ou le temps « Zéro » utilisé avec MyODBC est automatiquement convertie en NULL à partir de la version 2.50.12 de MyODBC, car ODBC ne peut manipuler de telles valeurs.

11-3-1 - Les types DATETIME, DATE et TIMESTAMP

Les types DATETIME, DATE et TIMESTAMP sont liés. Cette section décrit leurs caractéristiques, leurs similarités et leurs différences.

Le type DATETIME est prévu lorsque vous souhaitez stocker une date et une heure. MySQL affiche les valeurs de type DATETIME au format 'AAAA-MM-JJ HH:MM:SS'. L'intervalle de validité va de '1000-01-01 00:00:00' à '9999-12-31 23:59:59'. (« Validité » signifie que même si d'autres valeurs plus anciennes peuvent être manipulées, il n'est pas garanti qu'elles le seront).

Le type DATE est prévu lorsque vous souhaitez stocker une date. MySQL affiche les valeurs de type DATE au format 'AAAA-MM-JJ'. L'intervalle de validité va de '1000-01-01' à '9999-12-31'.

La colonne TIMESTAMP a vu ses propriétés et comportements évoluer avec les versions de MySQL et le mode SQL du serveur.

Vous pouvez spécifier les valeurs des colonnes DATETIME, DATE et TIMESTAMP, avec les formats communs suivants.

- Une chaîne au format 'AAAA-MM-JJ HH:MM:SS' ou 'AA-MM-JJ HH:MM:SS'. Une syntaxe plus souple est permise : tout caractère de ponctuation peut être utilisé comme délimiteur entre les parties de temps ou heure. Par exemple, '98-12-31 11:30:45', '98.12.31 11+30+45', '98/12/31 11*30*45', et '98@12@31 11^30^45' sont équivalents.

- Une chaîne au format 'AAAA-MM-JJ' ou 'AA-MM-JJ'. Une syntaxe plus flexible est aussi acceptée ici. Par exemple, '98-12-31', '98.12.31', '98/12/31', et '98@12@31' sont équivalent.

- Une chaîne sans aucun délimiteur sous la forme 'AAAAMMJJHHMMSS' ou 'AAMMJJHHMMSS', en supposant qu'une telle chaîne ait un sens en termes de date. Par exemple '19970523091528' et '970523091528' sont interprétés comme '1997-05-23 09:15:28', mais '971122129015' est invalide (les minutes ne sont pas valides) et devient alors '0000-00-00 00:00:00'.

- Une chaîne sans aucun délimiteur sous la forme 'AAAAMMJJ' ou 'AAMMJJ', en supposant qu'une telle chaîne ait un sens en termes de date. Par exemple, '19970523' et '970523' sont interprétés comme '1997-05-23', mais '971332' est invalide (les mois ne sont pas valides) et devient alors '0000-00-00'.

- Un nombre au format AAAAMMJJHHMMSS ou AAMMJJHHMMSS, en supposant qu'un tel nombre ait un sens en termes de date. Par exemple, 19830905132800 et 830905132800 sont interprétés comme '1983-09-05 13:28:00'.

- Un nombre au format AAAAMMJJ ou AAMMJJ en supposant qu'un tel nombre ait un sens en termes de date. Par exemple, 19830905 et 830905 sont interprétés comme '1983-09-05'.

- Un résultat de fonction qui retourne une valeur acceptable dans une colonne de type DATETIME, DATE, ou TIMESTAMP, tels que NOW() ou CURRENT_DATE.

Les valeurs invalides DATETIME, DATE ou TIMESTAMP sont remplacées par la date « zéro » du type approprié (respectivement '0000-00-00 00:00:00', '0000-00-00', ou 00000000000000).

Pour la valeur spécifiée sous forme de chaînes avec des délimiteurs de date, il n'est pas nécessaire de spécifier les deux chiffres pour les mois ou les dates qui sont inférieurs à 10. Par exemple, '1979-6-9' est valide et est équivalent à '1979-06-09'. Similairement, pour les valeurs spécifiées sous forme de chaîne avec des délimiteurs d'heure, il n'est pas obligatoire de spécifier les deux chiffres des heures, minutes et secondes qui sont inférieures à 10. '1979-10-30 1:2:3' est valide et est équivalent à '1979-10-30 01:02:03'.

Les valeurs spécifiées sous forme de nombres doivent avoir 6, 8, 12, ou 14 chiffres de long. Si le nombre a 8 ou 14 chiffres, MySQL suppose que le format est AAAAMMJJ ou AAAAMMJJHHMMSS (respectivement) et que l'année est représentée par les 4 premiers chiffres. Si le nombre a 6 ou 12 chiffres, MySQL suppose que le format est AAMMJJ ou AAMMJJHHMMSS (respectivement) et que l'année est représentée par les 2 premiers chiffres. Les nombres qui ne sont pas d'une taille valide, sont complétés avec des 0 jusqu'à la taille lisible la plus proche.

Les valeurs spécifiées sous forme de chaînes sans délimiteurs sont interprétées en fonction de leur taille. Si la chaîne à 8 ou 14 caractères de long, l'année est supposée avoir 4 chiffres. Sinon, l'année est supposée avoir 2 chiffres. La chaîne est interprétée de gauche à droite, en lisant successivement l'année, le mois, la date, l'heure, les minutes et les secondes, tant qu'il y a des valeurs dans la chaîne. Cela signifie que vous ne devez pas utiliser de chaînes qui ont moins de 6 caractères. Par exemple, si vous spécifiez '9903', en pensant qu'il représente Mars 1999, vous vous apercevrez que MySQL insère à la place la date « zéro » dans votre table. Cela est dû au fait que si l'année et le mois sont 99 et 03, la date est 0, ce qui en fait une date invalide, qui est rejetée par MySQL.

Dans une certaine mesure, vous pouvez assigner des valeurs d'une colonne à une autre colonne d'un autre type. Cependant, vous devez vous attendre à quelques altérations ou pertes de valeurs durant la conversion :

- Si vous assignez une valeur DATE à une colonne de type DATETIME ou TIMESTAMP, la partie représentant les heures vaudra '00:00:00', car les colonnes de type DATE ne contiennent pas d'information d'heure.

- Si vous assignez une valeur DATETIME ou TIMESTAMP à une colonne de type DATE, la composante heure sera perdue, car les colonnes de type DATE ne contiennent pas d'information d'heure.

- N'oubliez pas que même si les valeurs DATETIME, DATE, et TIMESTAMP peuvent être spécifiées avec différents formats, ces types n'ont pas les mêmes intervalles de validité. Par exemple, les valeurs de type TIMESTAMP ne peuvent pas prendre de valeurs antérieures à 1970 ou postérieures à 2037. Cela signifie qu'une date telle que '1968-01-01', est légale dans les colonnes de type DATETIME, mais n'est pas valide pour les TIMESTAMP, et sera convertie en date zéro (0) si elle est assignée à une telle colonne.

Attention à certains pièges concernant les spécifications de dates.

- La syntaxe à délimiteur libre peut être une source de problèmes. Par exemple, une valeur telle que '10:11:12' ressemble à une heure, à cause du délimiteur ':', mais avec une colonne de date, elle sera interprétée comme la date '2010-11-12'. La valeur '10:45:15' sera convertie en '0000-00-00', car '45' n'est pas un mois valide.

- Le serveur MySQL effectue seulement la vérification de base la validité d'une date : jours 00-31, mois 00-12, années 1000-9999. N'importe quelle date qui n'est pas dans cette marge retournera 0000-00-00. Veuillez noter que ceci vous permet toujours de stocker les dates inadmissibles telles que 2002-04-31. Il permet à des applications web de stocker des données d'une forme sans vérifier plus loin. Pour s'assurer qu'une date est valide, vous devrez effectuer un test dans votre application.

- Les années spécifiées avec deux chiffres seulement sont ambigus, car il manque le siècle. MySQL interprète les années à deux chiffres suivant ces règles :

- les années de l'intervalle 00-69 sont converties en 2000-2069 ;

- les années de l'intervalle 70-99 sont converties en 1970-1999.

11-3-1-1 - Comportement de TIMESTAMP avant MySQL 4.1

Le type TIMESTAMP est prévu pour stocker automatiquement l'heure courante lors d'une commande INSERT ou UPDATE. Si vous avez plusieurs colonnes de type TIMESTAMP, seule la première colonne sera mise à jour automatiquement.

La modification automatique de la première colonne de type TIMESTAMP survient si l'une des conditions suivantes est remplie :

- vous insérez explicitement la valeur NULL dans la colonne ;

- la colonne n'est pas spécifiée explicitement dans la commande INSERT ou LOAD DATA INFILE ;

- la colonne n'est pas spécifiée explicitement dans la commande UPDATE et d'autres colonnes changent de valeur (notez qu'une commande UPDATE qui affecte une valeur qui est déjà celle de la colonne sera ignorée, et la colonne TIMESTAMP ne sera pas modifiée, car la ligne n'est pas à proprement parler modifiée. MySQL ignore alors ces modifications pour des raisons d'efficacité).

Les autres colonnes de type TIMESTAMP, hormis la première, peuvent aussi prendre la valeur courante. Affectez-lui alors la valeur NULL ou la fonction NOW().

Vous pouvez affecter à n'importe quelle colonne de type TIMESTAMP une valeur différente de l'heure et la date courant en fournissant une valeur explicite. Cela s'applique aussi à la première colonne de type TIMESTAMP. Par exemple, si vous voulez affecter la date de création d'une ligne à une colonne de type TIMESTAMP, mais ne plus y toucher ultérieurement.

- Laissez MySQL donner la valeur de la colonne lors de la création de la ligne. Cela va initialiser la colonne à la date et heure courante.

- Lorsque vous faites des modifications ultérieures, affectez explicitement à la colonne TIMESTAMP sa propre valeur.

UPDATE tbl_name
SET timestamp_col = timestamp_col,
other_col1 = new_value1,
other_col2 = new_value2, ...

D'un autre côté, vous pouvez aussi facilement initialiser la colonne TIMESTAMP avec NOW() lors de sa création, puis ne plus la modifier ultérieurement.

L'intervalle de validité des valeurs TIMESTAMP va du début de l'année 1970 jusque quelque part durant l'année 2037, avec une précision d'une seconde. Les valeurs sont affichées comme des nombres entiers.

Le format d'affichage des valeurs TIMESTAMP dépend de la taille d'affichage, comme illustré ci-dessous. Le format total TIMESTAMP a 14 chiffres, mais les colonnes TIMESTAMP peuvent être créées avec des formats plus courts :

Type de colonne

Format d'affichage

TIMESTAMP(14)

YYYYMMDDHHMMSS

TIMESTAMP(12)

YYMMDDHHMMSS

TIMESTAMP(10)

YYMMDDHHMM

TIMESTAMP(8)

YYYYMMDD

TIMESTAMP(6)

YYMMDD

TIMESTAMP(4)

YYMM

TIMESTAMP(2)

YY

Toutes les colonnes de type TIMESTAMP ont la même taille de stockage, indépendamment de la taille d'affichage. Les formats les plus courants sont 6, 8, 12, et 14. Vous pouvez spécifier une taille arbitraire lors de la création de la table, mais 0 et les valeurs supérieures à 14 sont ramenées à 14. Les valeurs impaires sont aussi ramenées au nombre pair supérieur.

Les colonnes TIMESTAMP stockent une date valide, en utilisant la totalité de l'espace de stockage, quelle que soit la valeur de l'affichage. Cela a les implications suivantes.

- Spécifiez toujours l'année, le mois et le jour, même si le type de colonne est TIMESTAMP(4) ou TIMESTAMP(2). Sinon, la valeur ne sera pas légale et 0 sera stocké.

- Si vous utilisez la commande ALTER TABLE pour réduire la largeur d'une colonne TIMESTAMP, les informations qui étaient affichées sont désormais « cachées », mais pas détruites.

- Similairement, réduire une colonne de type TIMESTAMP ne cause aucune perte d'informations, en dehors du fait que ces informations ne sont plus affichées.

- Bien que les valeurs TIMESTAMP soient stockées avec une précision d'une seconde, la seule fonction qui travaille directement avec ces valeurs est la fonction UNIX_TIMESTAMP(). Les autres fonctions opèrent sur des valeurs lues et formatées. Cela signifie que vous ne pouvez pas utiliser de fonctions telles que HOUR() ou SECOND() à moins que le format d'affichage de la valeur TIMESTAMP ne présente cette valeur. Par exemple, les heures ne sont jamais affichées dans une colonne de type TIMESTAMP à moins que la taille d'affichage de la colonne ne soit d'au moins 10. L'utilisation de la fonction HOUR() sur une valeur ayant un format d'affichage plus court que 10 retournera un résultat inutilisable.

11-3-1-2 - Propriétés de TIMESTAMP depuis la version 4.1

Depuis MySQL 4.1.0, les propriétés des colonnes TIMESTAMP diffèrent des versions précédentes de MySQL.

- Les colonnes TIMESTAMP sont affichées dans le même format que les valeurs des colonnes DATETIME.

- Les tailles d'affichage ne sont plus supportées comme décrit dans la section précédente. En d'autres termes, vous ne pouvez pas utiliser TIMESTAMP(2), TIMESTAMP(4), etc.

De plus, si le serveur MySQL est en mode MAXDB, TIMESTAMP est identique à DATETIME. C'est-à-dire que si le serveur fonctionne en mode MAXDB au moment où la table est créée, toutes les colonnes TIMESTAMP créées sont en fait de type DATETIME. En conséquence, ces colonnes utilisent le format d'affichage DATETIME, ont le même intervalle de validité et aucune mise à jour automatique n'intervient.

MySQL peut fonctionner en mode MAXDB depuis la version 4.1.1. Pour activer ce mode, lancez le serveur avec le mode MAXDB au démarrage avec l'option --sql-mode=MAXDB, ou en modifiant la variable sql_mode durant l'exécution :

mysql> SET GLOBAL sql_mode=MAXDB;

Un client peut mettre le serveur en mode MAXDB pour sa propre connexion avec la commande suivante :

mysql> SET SESSION sql_mode=MAXDB;

11-3-2 - Le type TIME

MySQL lit et affiche les colonnes de type TIME au format 'HH:MM:SS' (ou 'HHH:MM:SS' pour les grandes quantités d'heures). Les valeurs de TIME vont de '-838:59:59' à '838:59:59'. La raison de cet intervalle de validité si large est que les colonnes de type TIME peuvent être utilisées pour représenter non seulement des heures du jour, mais aussi des durées entre deux événements (ce qui peut dépasser largement les 24 heures, ou même, être négatif).

Vous pouvez spécifier une valeur de type TIME avec différents formats.

- Une chaîne au format 'D HH:MM:SS.fraction'. (Notez que MySQL ne stockera pas la fraction d'une valeur TIME.)

Vous pouvez aussi utiliser l'une des syntaxes suivantes : HH:MM:SS.fraction, HH:MM:SS, HH:MM, D HH:MM:SS, D HH:MM, D HH ou SS. Ici, D peut prendre des valeurs entre 0 et 33.

- Une chaîne sans délimiteur au format 'HHMMSS', en supposant que cela puisse avoir un sens en termes de date. Par exemple, '101112' est interprété comme '10:11:12', mais '109712' est invalide (le nombre de minutes n'a pas de sens), et devient la date zéro : '00:00:00'.

- Un nombre au format HHMMSS, en supposant que cela puisse avoir un sens en termes de date. Par exemple, 101112 est interprété comme '10:11:12'. Les autres formats sont aussi compris : SS, MMSS, HHMMSS et HHMMSS.fraction. Notez que MySQL ne stocke pas encore les fractions de secondes.

- Le résultat d'une fonction qui retourne une valeur acceptable dans un contexte de valeurs TIME, comme CURRENT_TIME.

Pour les valeurs TIME spécifiées avec des délimiteurs, il n'est pas nécessaire de préciser deux chiffres pour les valeurs inférieurs à 10 pour les heures, minutes et secondes. '8:3:2' est la même chose que '08:03:02'.

Soyez soigneux lors de l'utilisation de valeurs « courtes » à une colonne de type TIME. MySQL interprète les valeurs en supposant que les chiffres de droite représentent les secondes (MySQL interprète les valeurs TIME comme des durées et non comme des heures d'une journée). Par exemple, vous pouvez penser que les valeurs '11:12', '1112' et 1112 représentent '11:12:00' (12 minutes après 11 heures), mais MySQL les interprétera comme '00:11:12' (11 minutes, 12 secondes). Similairement, '12' et 12 représentent '00:00:12'. Les valeurs de TIME déclarées avec des :, au contraire, sont toujours traités comme des heures de journée. '11:12' signifiera '11:12:00' et non pas 00:11:12

Les valeurs hors de l'intervalle de validité de TIME, mais qui sont valides sont ramenées à la valeur maximale stockable la plus proche. Par exemple, '-850:00:00' et '850:00:00' sont respectivement converties en '-838:59:59' et '838:59:59'.

Les valeurs TIME non valides sont transformées en date zéro '00:00:00'. Notez que comme '00:00:00' est elle-même une valeur TIME valide, vous n'aurez pas le moyen de faire la différence entre une valeur '00:00:00' stockée en connaissance de cause, et '00:00:00' stockée à cause d'une erreur.

11-3-3 - Le type YEAR

Le type YEAR est un type d'un octet utilisé pour représenter les années.

MySQL extrait et affiche la valeur de YEAR au format YYYY. L'échelle va de 1901 à 2155.

Vous pouvez spécifier la valeur de YEAR en plusieurs formats.

- Une chaîne de quatre chiffres entre '1901' et '2155'.

- Un nombre à quatre chiffres entre 1901 et 2155.

- Une chaîne de deux chiffres entre '00' et '99'. Les valeurs entre '00' et '69' et entre '70' et '99' sont respectivement converties en valeurs YEAR comprises entre 2000 et 2069 d'une part, et 1970 et 1999 de l'autre.

- Une nombre de deux chiffres entre 1 et 99. Les valeurs entre 1 et 69 et entre 70 et 99 sont respectivement converties en valeurs YEAR comprises entre 2001 et 2069 d'une part, et 1970 et 1999 d'autre part. Notez que le rang de valeurs pour les nombres à deux chiffres est totalement différent du rang pour les chaînes à deux chiffres parce que vous ne pouvez pas spécifier deux zéro directement en tant que nombre et le faire interpréter en tant que 2000. Vous devez le spécifier comme chaîne '0' ou '00' sinon il sera interprété comme 0000.

- En tant que résultat d'une fonction retournant une valeur acceptable dans le contexte de YEAR, comme as NOW().

Les valeurs illégales pour YEAR sont converties en 0000.

11-3-4 - An 2000 et les types date

MySQL lui-même est compatible an 2000. (Voir Section 1.2.5, « Compatibilité an 2000 »), mais les valeurs manipulées par MySQL peuvent ne pas l'être. N'importe quelle valeur n'ayant que deux chiffres pour représenter l'année est ambigüe, car le siècle n'est pas précisé. Ces valeurs doivent être interprétées comme des valeurs à 4 chiffres, car MySQL stocke les années en interne en utilisant 4 chiffres.

Pour les types DATETIME, DATE, TIMESTAMP, et YEAR, MySQL interprète les dates ambigües en se basant sur les règles suivantes.

- Les valeurs d'années comprises dans l'intervalle 00-69 sont converties en 2000-2069.

- Les valeurs d'années comprises dans l'intervalle 70-99 sont converties en 1970-1999.

Gardez bien à l'esprit que ces règles ne sont que la meilleure approximation possible d'une valeur. Si l'heuristique proposée par MySQL ne fournit pas les valeurs attendues, vous devrez fournir une valeur sans ambiguïté (à 4 chiffres).

ORDER BY ordonnera correctement les types YEAR/DATE/DATETIME à deux chiffres.

Notez aussi que quelques fonctions comme MIN() et MAX() convertiront un TIMESTAMP/DATE en nombre. Cela signifie qu'un timestamp avec une année à deux chiffres ne donnera pas de résultats corrects avec ces fonctions. Une solution dans ce cas est de convertir le TIMESTAMP/DATE en une année à 4 chiffres ou d'utiliser quelque chose comme MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS)).

11-4 - Les types chaînes

Les types chaînes sont CHAR, VARCHAR, BLOB, TEXT, ENUM, et SET. Cette section décrit comment ces types fonctionnent, leur besoin en espace et comment les utiliser dans vos requêtes.

11-4-1 - Les types CHAR et VARCHAR

Les types CHAR et VARCHAR sont similaires, mais diffèrent dans la manière dont ils sont stockés et récupérés.

La longueur d'une colonne CHAR est fixée à la longueur que vous avez définie lors de la création de la table. La longueur peut être n'importe quelle valeur entre 1 et 255. (Dans la version 3.23 de MySQL, la longueur est comprise entre 0 et 255.) Quand une valeur CHAR est enregistrée, elle est complétée à droite avec des espaces jusqu'à atteindre la valeur fixée. Quand une valeur de CHAR est lue, les espaces en trop sont retirés.

Les valeurs contenues dans les colonnes de type VARCHAR sont de tailles variables. Vous pouvez déclarer une colonne VARCHAR pour que sa taille soit comprise entre 1 et 255, exactement comme pour les colonnes CHAR. Par contre, contrairement à CHAR, les valeurs de VARCHAR sont stockées en utilisant autant de caractères que nécessaire, plus un octet pour mémoriser la longueur. Les valeurs ne sont pas complétées. Au contraire, les espaces finals sont supprimés avant stockage (ce qui ne fait pas partie des spécifications ANSI SQL).

Si vous assignez une chaîne de caractères qui dépasse la capacité de la colonne CHAR ou VARCHAR, celle-ci est tronquée jusqu'à la taille maximale du champ.

Le tableau suivant illustre les différences entre les deux types de colonnes en montrant les différences entre l'enregistrement dans une colonne CHAR(4) ou VARCHAR(4) :

Valeur

CHAR(4)

Espace requis

VARCHAR(4)

Espace requis

''

'    '

4 octets

''

1 octet

'ab'

'ab  '

4 octets

'ab'

3 octets

'abcd'

'abcd'

4 octets

'abcd'

5 octets

'abcdefgh'

'abcd'

4 octets

'abcd'

5 octets

Les valeurs lues dans les colonnes de type CHAR(4) et VARCHAR(4) seront les mêmes dans tous les cas, car les espaces finals sont retirés des valeurs issues de colonnes de type CHAR lors de la lecture.

Les valeurs dans les colonnes CHAR et VARCHAR sont classées et comparées sans tenir compte de la casse, à moins que l'attribut BINARY n'ait été spécifié lors de la création de la table. L'attribut BINARY signifie que les valeurs sont classées et triées en tenant compte de la casse, suivant l'ordre des caractères ASCII de la machine où est installé le serveur MySQL. BINARY n'affecte pas les méthodes de lecture et de stockage des valeurs.

L'attribut BINARY se propage dans une expression : il suffit qu'une seule colonne, utilisée dans une expression, ait l'attribut BINARY pour que toute l'expression ne tienne plus compte de la casse.

MySQL peut changer automatiquement le type d'une colonne CHAR ou VARCHAR lors de la création de la table. Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

11-4-2 - Les types BINARY and VARBINARY

Les types BINARY et VARBINARY sont similaires à CHAR et VARCHAR, hormis le fait qu'ils contiennent des chaînes binaires, plutôt que des chaînes de texte. C'est-à-dire, qu'ils contiennent des chaînes d'octets, plutôt que des chaînes de caractères. Cela signifie qu'ils n'ont pas de jeu de caractères associé, et les tris et comparaisons sont basés sur la valeur numérique de l'octet.

La taille maximale pour les types BINARY et VARBINARY, est la même que celles de CHAR et VARCHAR, hormis le fait que la taille de BINARY et VARBINARY est une taille en octets, et non pas en caractères.

La gestion des espaces finals est la même pour BINARY et VARBINARY que pour CHAR et VARCHAR. Lorsqu'une valeur BINARY est stockée, elle est complétée à droite avec des espaces. Lorsque les valeurs BINARY sont lues, les espaces finals sont supprimés. Pour VARBINARY, les espaces finals sont supprimés lorsque la valeur est stockée. Depuis MySQL 5.0.3, les espaces finals sont conservés. Gardez ces caractéristiques en tête si vous envisagez d'utiliser ces types de données, et que les valeurs risquent de se terminer par des espaces.

Avant MySQL 4.1.2, BINARY(M) et VARBINARY(M) étaient traités comme des CHAR(M) BINARY et VARCHAR(M) BINARY. Depuis MySQL 4.1.2, BINARY et VARBINARY sont disponibles en tant que types de données distincts, et pour CHAR(M) BINARY et VARCHAR(M) BINARY, l'attribut BINARY n'active pas le traitement binaire des colonnes. À la place, la collation binaire de la colonne sera utilisée, mais la colonne elle-même contiendra des caractères, plutôt que des octets. Par exemple, en version 4.1 et plus récentes, CHAR(5) BINARY est traité comme CHAR(5) CHARACTER SET latin1 COLLATE latin1_bin, en supposant que le jeu de caractères par défaut est latin1.

11-4-3 - Les types BLOB et TEXT

Une valeur de type BLOB est un objet binaire de grande taille, qui peut contenir une quantité variable de données. Les quatre types BLOB (TINYBLOB, BLOB, MEDIUMBLOB, et LONGBLOB) ne différent que par la taille maximale de données qu'ils peuvent stocker. Voir Section 11.5, « Capacités des colonnes ».

Les quatre types TEXT (TINYTEXT, TEXT, MEDIUMTEXT, et LONGTEXT correspondent aux types BLOB équivalents, et ont les mêmes contraintes de stockage. Les seules différences entre les colonnes de type BLOB et celles de type TEXT se situent au niveau des tris et comparaisons : les tris, faits sur les BLOB, contrairement à ceux faits sur les TEXT, tiennent compte de la casse. En d'autres termes, une valeur TEXT est une valeur BLOB insensible à la casse.

Si vous assignez une valeur trop grande à une colonne de type BLOB ou TEXT, la valeur sera tronquée à la taille maximale possible.

Dans la majorité des cas, vous pouvez considérer une colonne de type TEXT comme une colonne de type VARCHAR, aussi grande que vous le souhaitez. De même, vous pouvez considérer une colonne de type BLOB comme une colonne de type VARCHAR BINARY. Les seules différences sont :

- vous pouvez indexer les colonnes de type BLOB ou TEXT à partir de la version 3.23.2 de MySQL. Les versions plus anciennes ne peuvent pas indexer ces colonnes ;

- pour les index des colonnes BLOB et TEXT, vous devez spécifier une taille d'index. Pour les colonnes de type CHAR et VARCHAR, la taille du préfixe est optionnelle ;

- il n'y a pas de suppression des espaces finals lors du stockage de valeur dans des colonnes de type BLOB et TEXT, ce qui est le cas dans pour les colonnes de type VARCHAR ;

- les colonnes BLOB et TEXT ne peuvent avoir de valeur par défaut. (DEFAULT)

MyODBC considère les valeurs BLOB comme des LONGVARBINARY et les valeurs TEXT comme des LONGVARCHAR.

Vous pouvez rencontrer les problèmes suivants, à cause de la grande taille des colonnes de type BLOB et TEXT, lors de leur utilisation.

- Si vous voulez utiliser les commandes GROUP BY ou ORDER BY sur une colonne de type BLOB ou TEXT, vous devez d'abord la convertir en un objet de taille fixe. Le meilleur moyen est d'utiliser la fonction SUBSTRING. Par exemple :

mysql> SELECT comment FROM nom_de_table,SUBSTRING(comment,20) AS substr
->                 ORDER BY substr;

Si vous le ne faites pas, seuls les max_sort_length premiers octets de la colonne seront utilisés pour le tri. La valeur par défaut de max_sort_length est 1024. Cette valeur peut être modifiée en utilisant l'option -O au démarrage du serveur mysqld. Vous pouvez utiliser la commande GROUP BY sur une colonne de type BLOB ou TEXT en spécifiant la position de la colonne, ou avec un alias :

mysql> SELECT id,SUBSTRING(blob_col,1,100) FROM nom_de_table GROUP BY 2;
mysql> SELECT id,SUBSTRING(blob_col,1,100) AS b FROM nom_de_table GROUP BY b;

- La taille maximale d'un objet BLOB ou TEXT est déterminée par son type, mais la valeur la plus grande que vous pouvez transmettre au programme client est déterminée par la quantité de mémoire disponible sur le serveur et par la taille des buffers de communication. Vous pouvez changer la taille des buffers de communication, mais vous devez le faire sur le serveur et le client en même temps. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

Par exemple, mysql et mysqldump vous autorisent tous les deux à modifier la valeur cliente de max_allowed_packet. Voyez Section 7.5.2, « Réglage des paramètres du serveur », Section 8.3, « mysql, l'outil en ligne de commande » et Section 8.8, « mysqldump, sauvegarde des structures de tables et les données ».

Notez que chaque valeur BLOB ou TEXT est représentée en interne par un objet alloué séparément, contrairement à tous les autres types de colonne, pour lesquels la place de stockage est allouée une fois pour chaque colonne, lorsque la table est ouverte.

11-4-4 - Le type ENUM

Une énumération ENUM est une chaîne dont la valeur est choisie parmi une liste de valeurs autorisées lors de la création de la table.

Cette chaîne peut aussi être la chaîne vide ("") ou NULL dans certaines circonstances.

- Si vous insérez une valeur illégale dans une énumération ENUM (c'est-à-dire, une chaîne qui n'est pas dans la liste de valeurs autorisées), la chaîne vide est insérée pour représenter une erreur. Cette chaîne peut être distinguée d'une chaîne vide « normale » par le fait que cette chaîne à la valeur numérique 0. Nous reviendrons sur ce point plus tard.

- Si une colonne d'énumération est déclarée NULL, NULL devient aussi une valeur autorisée, et la valeur par défaut est alors NULL. Si une colonne d'énumération est déclarée NOT NULL, la valeur par défaut est le premier élément de la liste des valeurs autorisées.

Chaque élément de l'énumération dispose d'un index.

- Les valeurs de la liste des valeurs autorisées sont indexées à partir de 1.

- L'index de la chaîne vide (cas d'erreur) est 0. Cela signifie que vous pouvez utiliser la sélection suivante pour repérer les valeurs d'énumération invalides :

mysql> SELECT * FROM nom_de_table WHERE enum_col=0;

- L'index de la valeur NULL est NULL.

Par exemple, une colonne créée comme ENUM("un", "deux", "trois") peut prendre n'importe quelle valeur ci-dessous. L'index de chaque valeur est aussi présenté :

Valeur

Index

NULL

NULL

""

0

"un"

1

"deux"

2

"trois"

3

Une énumération peut avoir un maximum de 65 535 éléments.

À partir de la version 3.23.51, les espaces en début et fin de chaîne sont automatiquement supprimés des éléments de l'énumération ENUM lorsque la table est créée.

La casse des lettres est sans importance lors de l'assignation de valeurs dans une énumération. Cependant, les valeurs lues dans la base auront la même casse que celle spécifiée lors de la création de la table.

Si vous lisez le contenu d'une énumération dans un contexte numérique, l'index de la valeur ENUM sera retourné. Par exemple, vous pouvez lire des valeurs numériques comme ceci :

mysql> SELECT enum_col+0 FROM nom_de_table;

Si vous stockez un nombre dans une colonne de type ENUM, le nombre sera traité comme un index, et la valeur stockée sera celle de l'élément ayant cet index (attention, cela ne fonctionnera pas avec les commandes LOAD DATA, car cette dernière traite toutes les valeurs comme des chaînes). Il est déconseillé de stocker des valeurs numériques dans un ENUM, car cela engendre des confusions. Par exemple, la colonne suivante est une énumération de chaînes contenant les valeurs '0', '1' et '2', mais leur valeur numérique est 1, 2 et 3 :

numbers ENUM('0','1','2')

Les valeurs de type ENUM sont triées en fonction de l'ordre des éléments, fixé à la création de la table (en d'autres termes, les valeurs ENUM sont stockées en fonction de leur index). Par exemple, "a" précède "b" dans l'énumération ENUM("a", "b"), mais "b" précède "a" dans l'énumération ENUM("b", "a"). La chaîne vide précède toujours les chaînes non vides, et NULL précède toutes les valeurs.

Si vous voulez connaître toutes les valeurs possibles d'une colonne de type ENUM, pensez à utiliser cette commande : SHOW COLUMNS FROM nom_de_table LIKE enum_column_name, puis analysez la définition de la colonne de type ENUM (deuxième colonne dans le résultat).

11-4-5 - Le type SET

Un SET est une chaîne qui peut avoir zéro ou plusieurs valeurs, chacune doit être choisie dans une liste de valeurs définies lors de la création de la table. Les valeurs des colonnes SET composées de plusieurs membres sont définies en séparant celles-ci avec des virgules (','). Ce qui fait que la valeur d'un membre de SET ne peut contenir lui-même de virgule.

Par exemple, une colonne définie en tant que SET("un", "deux") NOT NULL peut avoir l'une de ces valeurs :

""
"un"
"deux"
"un,deux"

Un SET peut avoir au plus 64 membres.

À partir de la version 3.23.51, les espaces en trop sont automatiquement effacés des membres de SET lorsque la table est créée.

MySQL enregistre les valeurs de SET numériquement. Le bit de poids faible de la valeur correspond alors au premier élément de la liste. Si vous utilisez une valeur SET dans un contexte numérique, les bits des éléments dans cet ensemble seront mis à un, et les autres à zéro. Par exemple, vous pouvez obtenir un entier à partir d'un ensemble comme ceci :

mysql> SELECT col_set+0 FROM nom_de_table;

Si un nombre est enregistré dans une colonne SET, les bits un à un de ce nombre représenteront les éléments placés dans cet ensemble. Supposons qu'une colonne est spécifiée en tant que SET("a","b","c","d"), les membres ont alors les valeurs suivantes :

SET membre

Valeur décimale

Valeur binaire

a

1

0001

b

2

0010

c

4

0100

d

8

1000

Si vous assignez 9 à cette colonne, cela donne 1001 en binaire, ce qui fait que les valeurs du premier et quatrième membres "a" et "d" sont sélectionnés et la valeur résultante est "a,d".

Pour les valeurs se composant de plus d'un membre du SET, l'ordre des membres n'a pas d'importance lors des insertions. Le nombre d'occurrences d'un élément n'importe pas non plus. Lorsque la valeur sera lue ultérieurement, chaque élément n'apparaîtra qu'une seule fois, et dans l'ordre donné à la déclaration de la colonne. Par exemple, si une colonne est spécifiée comme SET("a","b","c","d"), alors "a,d", "d,a", et "d,a,a,d,d" seront tous représentés par "a,d".

Si vous spécifiez une valeur incorrecte dans une colonne SET, la valeur sera ignorée.

Les valeurs de SET sont triées numériquement. La valeur NULL précède toutes les autres.

Normalement, vous exécuterez un SELECT sur une colonne SET en utilisant l'opérateur LIKE ou la fonction FIND_IN_SET() :

mysql> SELECT * FROM nom_de_table WHERE set_col LIKE '%value%';
mysql> SELECT * FROM nom_de_table WHERE FIND_IN_SET('value',set_col)>0;

Mais ce qui suit fonctionnera aussi :

mysql> SELECT * FROM nom_de_table WHERE set_col = 'val1,val2';
mysql> SELECT * FROM nom_de_table WHERE set_col & 1;

La première requête cherche les lignes qui correspondent exactement. La seconde ne cherche que les lignes contenant le premier membre du set.

Si vous voulez connaître toutes les valeurs possibles d'une colonne SET, vous devez utiliser : SHOW COLUMNS FROM nom_de_table LIKE nom_colonne_set et étudier la définition du SET dans la seconde colonne.

11-5 - Capacités des colonnes

Les capacités de stockage de chaque type de colonnes de MySQL sont listées par catégories.

Capacités de stockage des colonnes numériques

Type de colonne

Espace requis

TINYINT

1 octet

SMALLINT

2 octets

MEDIUMINT

3 octets

INT,INTEGER

4 octets

BIGINT

8 octets

FLOAT(p)

4 if X <= 24 or 8 if 25 <= X <= 53

FLOAT

4 octets

DOUBLE PRECISION, REAL

8 octets

DECIMAL(M,D)

M+2 octets si D > 0, M+1 octets si D = 0 (D+2, si M < D)

Capacités de stockage des colonnes de données temporelles

Type de colonne

Espace requis

DATE

3 octets

DATETIME

8 octets

TIMESTAMP

4 octets

TIME

3 octets

YEAR

1 octet

Capacités de stockage des colonnes de texte

Type de colonne

Espace requis

CHAR(M)

M octets, 1 <= M <= 255

VARCHAR(M)

L+1 octets, avec L <= M et 1 <= M <= 255

TINYBLOB, TINYTEXT

L+1 octets, avec L < 2^8

BLOB, TEXT

L+2 octets, avec L < 2^16

MEDIUMBLOB, MEDIUMTEXT

L+3 octets, avec L < 2^24

LONGBLOB, LONGTEXT

L+4 octets, avec L < 2^32

ENUM('valeur1','valeur2',...)

1 ou 2 octets, suivant le nombre d'éléments de l'énumération (65 535 au maximum)

SET('valeur1','valeur2',...)

1, 2, 3, 4 ou 8 octets, suivant le nombre de membres de l'ensemble (64 au maximum)

Les types VARCHAR, BLOB et TEXT sont de longueur variable, et l'espace disque requis dépend de la taille réelle de la valeur présente dans la colonne, (taille représentée par L dans le tableau précédent) et non pas de la taille maximale de la colonne. Par exemple une colonne VARCHAR(10) peut contenir une chaîne de 10 caractères. L'espace requis est dans ce cas-là la longueur de la chaîne (L), plus 1 octet pour enregistrer la longueur de celle-ci. Pour la chaîne 'abcd', L est égal à 4 et l'espace requis est de 5 octets.

Les types BLOB et TEXT requièrent 1, 2, 3, ou 4 octets pour mémoriser la taille de la valeur dans la colonne, suivant la longueur maximale du type. Voir Section 11.4.3, « Les types BLOB et TEXT ».

Si une table inclut au moins une colonne de taille variable, la ligne sera de taille variable. Notez que lorsqu'une table est créée, MySQL peut, dans certaines circonstances, changer automatiquement une colonne de taille variable en colonne à taille fixe (et vice-versa). Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

La taille d'un ENUM est déterminée par le nombre d'éléments de l'énumération. Un octet est nécessaire pour les énumérations ayant jusqu'à 255 valeurs possibles. Deux octets sont nécessaires pour les énumérations ayant jusqu'à 65 535 valeurs possibles. Voir Section 11.4.4, « Le type ENUM ».

La taille d'un SET est déterminée par le nombre de ses membres. S'il y en a N, l'objet occupe (N+7)/8 octets, arrondis à 1, 2, 3, 4, ou 8 octets. Un SET peut avoir au plus 64 membres. Voir Section 11.4.5, « Le type SET ».

La taille maximale d'une ligne dans une table MyISAM est de 65 534 octets. Les colonnes BLOB et TEXT acceptent jusqu'à 5-9 octets en dessous de cette taille.

11-6 - Choisir le bon type de colonne

Pour une utilisation optimale des capacités de stockage, essayez d'utiliser le type le plus optimal dans chaque cas. Par exemple, si une colonne du type entier sera utilisée pour des valeurs entre 1 et 99999, le type MEDIUMINT UNSIGNED sera le plus approprié.

La représentation des valeurs monétaires est un problème commun. Avec MySQL, vous devrez utiliser le type DECIMAL. Il est sauvegardé en tant que chaîne, aucune perte de précision ne devrait avoir lieu. Si la précision n'est pas très importante, vous pouvez utiliser le type DOUBLE.

Pour une haute précision, vous pouvez toujours transcrire en nombre décimaux, et les enregistrer dans des BIGINT. Cela vous permettra d'effectuer tous vos calculs avec des entiers et de convertir à nouveau en nombre décimaux au besoin.

11-7 - Utilisation des types de données issues d'autres SGBDR

Pour faciliter l'importation de codes SQL issus d'autres systèmes de gestion de bases de données, MySQL convertit les types de colonnes comme le montre le tableau suivant. Cette conversion facilite l'import de structures de tables.

Autre dénomination

Type MySQL

BINARY(M)

CHAR(M) BINARY

CHAR VARYING(M)

VARCHAR(M)

FLOAT4

FLOAT

FLOAT8

DOUBLE

INT1

TINYINT

INT2

SMALLINT

INT3

MEDIUMINT

INT4

INT

INT8

BIGINT

LONG VARBINARY

MEDIUMBLOB

LONG VARCHAR

MEDIUMTEXT

LONG

MEDIUMTEXT (depuis MySQL 4.1.0)

MIDDLEINT

MEDIUMINT

VARBINARY(M)

VARCHAR(M) BINARY

La conversion du type de colonnes s'effectue lors de la création. Si vous créez une table avec des types issus d'un autre SGBDR, puis que vous exécutez la commande DESCRIBE nom_de_table, MySQL fournira la structure de la table en utilisant les types équivalents.

12 - Fonctions à utiliser dans les clauses SELECT et WHERE

Les expressions peuvent être utilisées en différents endroits des requêtes SQL, comme dans les clauses ORDER BY et HAVING des commandes SELECT, dans les clauses WHERE de SELECT, DELETE et UPDATE, ou dans les commandes SET. Les expressions peuvent contenir des valeurs littérales, des noms de colonnes, la valeur NULL, des fonctions et des opérateurs. Ce chapitre décrit les fonctions et opérateurs qui sont autorisés pour écrire une expression avec MySQL.

Une expression contenant NULL produira toujours la valeur NULL comme résultat. (Sauf contre-indication dans le manuel.)

Note : il ne doit pas y avoir d'espace entre le nom d'une fonction et la parenthèse ouvrante la suivant. Cela aide l'analyseur MySQL à distinguer les appels à ces fonctions des références aux tables ou colonnes ayant le même nom qu'une fonction. Les espaces autour des arguments sont autorisés.

Vous pouvez forcer MySQL à accepter les espaces après les noms de fonctions grâce à l'option --ansi de mysqld, ou en utilisant l'option CLIENT_IGNORE_SPACE avec mysql_connect. Dans ce cas, toutes les fonctions définies deviendront des mots strictement réservés. Voir Section 1.5.3, « Exécuter MySQL en mode ANSI ».

Dans un souci de simplicité, les affichages des résultats de mysql sont fournis sous forme abrégée. Par exemple :

mysql> SELECT MOD(29,9);
1 rows in set (0.00 sec)

+-----------+
| mod(29,9) |
+-----------+
|         2 |
+-----------+

est affiché comme ceci :

mysql> SELECT MOD(29,9);
-> 2

12-1 - Opérateurs et fonctions tous types

12-1-1 - Précédence des opérateurs

La priorité des opérateurs est présentée dans la liste suivante, depuis la priorité la plus basse à la plus haute. Les opérateurs sur la même ligne ont la même priorité.

:=
||, OR, XOR
&&, AND
BETWEEN, CASE, WHEN, THEN, ELSE
=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
|
&
<<, >>
-, +
*, /, DIV, %, MOD
^
- (unary minus), ~ (unary bit inversion)
NOT, !
BINARY, COLLATE

12-1-2 - Parenthèses

- ( ... )

Utilisez les parenthèses pour forcer l'ordre des évaluations dans une expression. Par exemple :

mysql> SELECT 1+2*3;
-> 7
mysql> SELECT (1+2)*3;
-> 9

12-1-3 - Opérateurs de comparaison

Les opérations de comparaison donnent comme résultats 1 (TRUE), 0 (FALSE), ou NULL. Ces fonctions fonctionnent pour les nombres comme pour les chaînes. Les nombres sont automatiquement transformés en chaînes et les chaînes en nombres si besoin en est (comme en Perl).

MySQL effectue les comparaisons enr respectant les règles suivantes.

- Si l'un ou les deux arguments sont NULL, le résultat de la comparaison est NULL, exception faite pour l'opérateur <=>.

- Si les deux arguments de la comparaison sont des chaînes, ils seront comparés en tant que chaînes.

- Si les deux arguments sont des entiers, ils sont comparés en tant qu'entiers.

- Les valeurs hexadécimales sont traitées en tant que chaînes binaires si elles ne sont pas comparées à un nombre.

- Si l'un des arguments est une colonne de type TIMESTAMP ou DATETIME et que l'autre est une constante, celle-ci est convertie en timestamp avant que la comparaison ne s'opère. Cela est fait pour être mieux compatible avec ODBC.

- Dans tous les autres cas, les arguments sont comparés en tant que nombres à décimale flottante (réels).

Par défaut, la comparaison des chaînes s'effectue d'une façon insensible à la casse en utilisant le jeu de caractères courant (ISO-8859-1 Latin1 par défaut, qui fonctionne aussi très bien pour l'anglais).

Si vous comparez des chaînes insensibles à la casse, avec les opérateurs standards (=, <>..., mais pas avec LIKE) les espaces terminaux seront ignorés (espaces, tabulations et nouvelles lignes).

mysql> SELECT "a" ="A \n";
-> 1

Les exemples suivants montrent la conversion des chaînes en nombres pour les opérations de comparaison :

mysql> SELECT 1 > '6x';
-> 0
mysql> SELECT 7 > '6x';
-> 1
mysql> SELECT 0 > 'x6';
-> 0
mysql> SELECT 0 = 'x6';
-> 1

- =

Égal :

mysql> SELECT 1 = 0;
-> 0
mysql> SELECT '0' = 0;
-> 1
mysql> SELECT '0.0' = 0;
-> 1
mysql> SELECT '0.01' = 0;
-> 0
mysql> SELECT '.01' = 0.01;
-> 1

- <=>

Comparaison compatible avec NULL. Cet opérateur fait une comparaison d'égalité comme l'opérateur =, mais retourne 1 plutôt que NULL si les deux opérandes sont NULL, et 0 plutôt que NULL si un opérande est NULL.

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
-> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
-> 1, NULL, NULL

<=> a été ajouté en MySQL 3.23.0.

- <>, != Différent :

mysql> SELECT '.01' <> '0.01';
-> 1
mysql> SELECT .01 <> '0.01';
-> 0
mysql> SELECT 'zapp' <> 'zappp';
-> 1

- <=

Inférieur ou égal :

mysql> SELECT 0.1 <= 2;
-> 1

- <

Strictement inférieur :

mysql> SELECT 2 < 2;
-> 0

- >=

Supérieur ou égal :

mysql> SELECT 2 >= 2;
-> 1

- >

Strictement supérieur :

mysql> SELECT 2 > 2;
-> 0

- IS NULL, IS NOT NULL

Tester si une valeur est ou n'est pas NULL :

mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
-> 0 0 1
mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
-> 1 1 0

Pour être compatible avec les autres programmes, MySQL gère les appels qui utilisent IS NULL de la façon suivante.

- Vous pouvez trouver le dernier enregistrement inséré en utilisant :

SELECT * FROM nom_de_table WHERE auto_col IS NULL

Cela peut être interdit en mettant SQL_AUTO_IS_NULL=0. Voir Section 13.5.2.8, « Syntaxe de SET ».

- Pour les colonnes NOT NULL DATE et DATETIME, vous pouvez sélectionner les lignes ayant la date spéciale 0000-00-00 avec :

SELECT * FROM nom_de_table WHERE date_column IS NULL

C'est une fonctionnalité nécessaire pour que certaines applications ODBC fonctionnent (car ODBC ne supporte pas les dates 0000-00-00).

- expression BETWEEN min AND max

Si expression est supérieure ou égale à min et expression est inférieure ou égale à max, BETWEEN retourne 1, sinon 0. Ceci est équivalent à l'expression (min <= expression AND expression <= max) si tous les arguments sont du même type. Dans tous les autres cas, la conversion de type prend place, selon les règles suivantes, mais appliquées aux trois arguments. Notez qu'avant la 4.0.5, les arguments étaient convertis au type de expr.

mysql> SELECT 1 BETWEEN 2 AND 3;
-> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
-> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
-> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
-> 0

- expr NOT BETWEEN min AND max

Même chose que NOT (expr BETWEEN min AND max).

- COALESCE(list)

Retourne le premier élément non NULL de la liste :

mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL

- GREATEST(value1,value2,...)

Avec deux ou plusieurs arguments, retourne la valeur la plus grande. Les arguments sont comparés en utilisant les mêmes règles que pour LEAST().

mysql> SELECT GREATEST(2,0);
-> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
-> 767.0
mysql> SELECT GREATEST('B','A','C');
-> 'C'

Avant MySQL 3.22.5, vous pouvez utiliser MAX() au lieu de GREATEST().

- expr IN (valeur,...)

Retourne 1 si expr est l'une des valeurs dans la liste IN, sinon retourne 0. Si toutes les valeurs sont des constantes, toutes les valeurs sont évaluées avec le type de expr et triées. La recherche de l'élément est alors faite en utilisant la recherche binaire. Cela signifie que IN est très rapide si les valeurs contenues dans la liste IN sont toutes des constantes. Si expr est une chaîne sensible à la casse, la comparaison est faite dans un contexte sensible à la casse :

mysql> SELECT 2 IN (0,3,5,'wefwf');
-> 0
mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
-> 1

Depuis MySQL version 4.1, une clause IN() peut aussi contenir une sous-requête. Voir Section 13.1.8.3, « Sous-requêtes avec les clauses ANY, IN et SOME ».

- expr NOT IN (value,...)

Même chose que NOT (expr IN (valeur,...)).

- ISNULL(expr)

Si expr est NULL, ISNULL() retourne 1, sinon il retourne 0 :

mysql> SELECT ISNULL(1+1);
-> 0
mysql> SELECT ISNULL(1/0);
-> 1

Notez que la comparaison de deux valeurs NULL en utilisant = donnera toujours false !

- INTERVAL(N,N1,N2,N3,...)

Retourne 0 si N < N1, 1 si N < N2, etc. Tous les arguments sont traités en tant qu'entiers. Il est requis que N1 < N2 < N3 < ... < Nn pour que cette fonction fonctionne correctement. Cela est dû à la recherche binaire utilisée (très rapide) :

mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
-> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0

- LEAST(value1,value2,...)

Avec deux arguments ou plus, retourne la plus petite valeur. Les arguments sont comparés avec les règles suivantes.

- Si la valeur retournée est utilisée dans un contexte INTEGER ou que tous les arguments sont des entiers, ils sont comparés comme des entiers.

- Si la valeur retournée est utilisée dans un contexte REAL ou que tous les arguments sont des entiers, ils sont comparés comme des entiers.

- Si un des arguments est une chaîne sensible à la casse, les arguments sont comparés comme des chaînes sensibles à la casse.

- Dans les autres cas, les arguments sont comparés comme des chaînes insensibles à la casse.

mysql> SELECT LEAST(2,0);
-> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
-> 3.0
mysql> SELECT LEAST('B','A','C');
-> 'A'

Avant MySQL 3.22.5, vous pouvez utiliser MIN() au lieu de LEAST().

Notez que les conversions précédentes peuvent produire des résultats étranges dans certains cas limites :

mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED);
-> -9223372036854775808

Cela arrive parce que MySQL lit 9223372036854775808.0 dans un contexte d'entier. La représentation entière n'est pas suffisante pour contenir la valeur, alors elle est transformée en entier signé.

12-1-4 - Opérateurs logiques

En SQL, tous les opérateurs logiques évaluent à TRUE, FALSE ou NULL (INCONNU). En MySQL, c'est implémenté en 1 (TRUE), 0 (FALSE), et NULL. La plupart de ce qui suit est commun entre les différentes bases de données SQL, pourtant, certains systèmes pourraient retourner une valeur non nulle pour TRUE (pas obligatoirement 1).

- NOT, !

NOT (NON) logique. Évalue à 1 si l'opérande est 0, à 0 si l'opérande est non nul, et NOT NULL retourne NULL.

mysql> SELECT NOT 10;
-> 0
mysql> SELECT NOT 0;
-> 1
mysql> SELECT NOT NULL;
-> NULL
mysql> SELECT ! (1+1);
-> 0
mysql> SELECT ! 1+1;
-> 1

Le dernier exemple donne 1, car l'expression est évaluée comme (!1)+1.

- AND, &&

AND (ET) logique. Évalue à 1 si tous les opérandes sont différents de zéro et de NULL, à 0 si l'un des opérandes est 0, dans les autres cas, NULL est retourné.

mysql> SELECT 1 && 1;
-> 1
mysql> SELECT 1 && 0;
-> 0
mysql> SELECT 1 && NULL;
-> NULL
mysql> SELECT 0 && NULL;
-> 0
mysql> SELECT NULL && 0;
-> 0

Notez que pour les versions antérieures à la 4.0.5 l'évaluation est interrompue lorsque NULL est rencontré, au lieu de continuer à tester une éventuelle existence de 0. Cela signifie que dans ces versions, SELECT (NULL AND 0) retourne NULL au lieu de 0. En 4.0.5 le code a été revu pour que le résultat réponde toujours aux normes ANSI tout en optimisant le plus possible.

- OR, ||

OR (OU inclusif) logique. Évalue à 1 si aucun opérande n'est nul, à NULL si l'un des opérandes est NULL, sinon 0 est retourné.

mysql> SELECT 1 || 1;
-> 1
mysql> SELECT 1 || 0;
-> 1
mysql> SELECT 0 || 0;
-> 0
mysql> SELECT 0 || NULL;
-> NULL
mysql> SELECT 1 || NULL;
-> 1

- XOR

XOR (OU exclusif) logique. Retourne NULL si l'un des opérandes est NULL. Pour les opérandes non NULL, évalue à 1 si un nombre pair d'opérandes est non nul, sinon 0 est retourné.

mysql> SELECT 1 XOR 1;
-> 0
mysql> SELECT 1 XOR 0;
-> 1
mysql> SELECT 1 XOR NULL;
-> NULL
mysql> SELECT 1 XOR 1 XOR 1;
-> 1

a XOR b est mathématiquement égal à (a AND (NOT b)) OR ((NOT a) and b).

12-2 - Les fonctions de contrôle

- IFNULL(expr1,expr2)

Si l'argument expr1 n'est pas NULL, la fonction IFNULL() retournera l'argument expr1, sinon elle retournera l'argument expr2. La fonction IFNULL() retourne une valeur numérique ou une chaîne de caractères, suivant le contexte d'utilisation :

mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'oui');
-> 'oui'

En version 4.0.6 et plus récentes, le résultat par défaut de IFNULL(expr1,expr2) est le plus « général » des deux expressions, dans l'ordre de type STRING, REAL ou INTEGER. La différence avec les anciennes versions de MySQL ne sera notable que si vous créez une table basée sur des expressions, ou si MySQL stocke en interne des valeurs issues de IFNULL() dans une table temporaire.

CREATE TABLE foo SELECT IFNULL(1,"test") as test;

En MySQL 4.0.6, le type de la colonne test est CHAR(4) tandis que dans les versions plus anciennes, vous auriez obtenu un BIGINT.

- NULLIF(expr1,expr2)

Si l'expression expr1 = expr2 est vraie, la fonction retourne NULL sinon elle retourne expr1. Cela revient à faire CASE WHEN x = y THEN NULL ELSE x END :

mysql> SELECT NULLIF(1,1);
-> NULL
mysql> SELECT NULLIF(1,2);
-> 1

Notez que l'argument expr1 est évalué deux fois dans MySQL si les arguments sont égaux.

- IF(expr1,expr2,expr3)

Si l'argument expr1 vaut TRUE (expr1 <> 0 et expr1 <> NULL) alors la fonction IF() retourne l'argument expr2, sinon, elle retourne l'argument expr3. La fonction IF() retourne une valeur numérique ou une chaîne de caractères, suivant le contexte d'utilisation :

mysql> SELECT IF(1>2,2,3);
-> 3
mysql> SELECT IF(1<2,'oui','non');
-> 'oui'
mysql> SELECT IF(STRCMP('test','test1'),'non','oui');
-> 'non'

Si l'argument expr2 ou expr3 est explicitement NULL alors le type du résultat de la fonction IF() est le type de la colonne non NULL. (Ce comportement est nouveau dans MySQL 4.0.3.)

L'argument expr1 est évalué comme un entier, cela signifie que si vous testez un nombre à virgule flottante ou une chaîne de caractères, vous devez utiliser une opération de comparaison :

mysql> SELECT IF(0.1,1,0);
-> 0
mysql> SELECT IF(0.1<>0,1,0);
-> 1

Dans le premier exemple ci-dessus, IF(0.1) retourne 0 parce que 0.1 est converti en une chaîne de caractères, ce qui revient à tester IF(0). Ce n'est certainement pas ce que vous désiriez. Dans le second exemple, la comparaison teste si le nombre à virgule flottante est différent de zéro. Le résultat de cette comparaison sera un entier.

Le type de la fonction IF() (ce qui peut être important s'il est stocké dans une table temporaire) est calculé, dans la Version 3.23 de MySQL, comme suit :

Expression

Valeur retournée

expr2 ou expr3 retourne une chaîne

chaîne

expr2 ou expr3 retourne un nombre à virgule

nombre à virgule

expr2 ou expr3 retourne un entier

entier

Si expr2 et expr3 sont des chaînes de caractères, alors le résultat est insensible à la casse si les deux chaînes de caractères sont insensibles à la casse. (À partir de la version 3.23.51 de MySQL)

- CASE valeur WHEN [compare-value] THEN résultat [WHEN [compare-value] THEN résultat ...] [ELSE résultat] END, CASE WHEN [condition] THEN résultat [WHEN [condition] THEN résultat ...] [ELSE résultat] END

La première version retourne résultat si valeur=compare-value. La seconde version retourne le résultat de la première condition qui se réalise. Si aucune des conditions n'est réalisée, alors le résultat de la clause ELSE est retourné. S'il n'y a pas de clause ELSE alors NULL est retourné :

mysql> SELECT CASE 1 WHEN 1 THEN "un"
WHEN 2 THEN "deux" ELSE "plus" END;
-> "un"
mysql> SELECT CASE WHEN 1>0 THEN "vrai" ELSE "faux" END;
-> "vrai"
mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
-> NULL

Le type de la valeur retournée (INTEGER, DOUBLE ou STRING) est de même type que la première valeur retournée (l'expression après le premier THEN).

12-3 - Fonctions de chaînes de caractères

Les fonctions qui traitent les chaînes de caractères retournent NULL si la longueur du résultat finit par dépasser la taille maximale du paramètre max_allowed_packet, défini dans la configuration du serveur. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

Pour les fonctions qui opèrent sur des positions à l'intérieur d'une chaîne, la position initiale est 0.

- ASCII(str)

Retourne le code ASCII du premier caractère de la chaîne de caractères str. Retourne 0 si la chaîne de caractères str est vide. Retourne NULL si la chaîne de caractères str est NULL. ASCII() fonctionne avec des valeurs numériques entre 0 et 255.

mysql> SELECT ASCII('2');
-> 50
mysql> SELECT ASCII(2);
-> 50
mysql> SELECT ASCII('dx');
-> 100

Voir aussi la fonction ORD().

- BIN(N)

Retourne une chaîne de caractères représentant la valeur binaire de l'argument N, où l'argument N est un nombre de type BIGINT. Cette fonction est un équivalent de CONV(N,10,2). Retourne NULL si l'argument N est NULL.

mysql> SELECT BIN(12);
-> '1100'

- BIT_LENGTH(str)

Retourne le nombre de bits de la chaîne de caractères str.

mysql> SELECT BIT_LENGTH('text');
-> 32

BIT_LENGTH() a été ajouté en MySQL 4.0.2.

- CHAR(N,...)

La fonction CHAR() interprète les arguments comme des entiers et retourne une chaîne de caractères, constituée des caractères, identifiés par leur code ASCII. Les valeurs NULL sont ignorées :

mysql> SELECT CHAR(77,121,83,81,'76');
-> 'MySQL'
mysql> SELECT CHAR(77,77.3,'77.3');
-> 'MMM'

- CHAR_LENGTH(str)

Retourne le nombre de caractères de la chaîne str. Un caractère multioctet compte comme un seul caractère. Cela signifie que pour une chaîne contenant 5 caractères de 2 octets, LENGTH() retournera 10, alors que CHAR_LENGTH() retournera 5.

- CHARACTER_LENGTH(str)

CHARACTER_LENGTH() est un synonyme de CHAR_LENGTH().

- COMPRESS(string_to_compress)

Compresse une chaîne. Cette fonction requiert la présence de la bibliothèque zlib. Sinon, la valeur retournée sera toujours NULL.

mysql> SELECT LENGTH(COMPRESS(REPEAT('a',1000)));
-> 21
mysql> SELECT LENGTH(COMPRESS(''));
-> 0
mysql> SELECT LENGTH(COMPRESS('a'));
-> 13
mysql> SELECT LENGTH(COMPRESS(REPEAT('a',16)));
-> 15

La chaîne compressée est stockée de la manière suivante.

- Les chaînes vides sont stockées comme des chaînes vides.

- Les chaînes non vides sont stockées avec 4 octets de plus, indiquant la taille de la chaîne non compressée, suivie de la chaîne compressée. Si la chaîne se termine avec des espaces, un point supplémentaire '.' est ajouté, pour éviter que les espaces terminaux soient supprimés de la chaîne. N'utilisez pas les types CHAR ou VARCHAR pour stocker des chaînes compressées. Il est mieux d'utiliser un type BLOB.

COMPRESS() a été ajouté en MySQL 4.1.1.

- CONCAT(str1,str2,...)

Retourne une chaîne représentant la concaténation des arguments. Retourne NULL si un des arguments est NULL. Cette fonction peut prendre plus de 2 arguments. Si un argument est un nombre, il sera converti en son équivalent sous forme de chaîne de caractères :

mysql> SELECT CONCAT('My', 'S', 'QL');
-> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
-> NULL
mysql> SELECT CONCAT(14.3);
-> '14.3'

- CONCAT_WS(separator, str1, str2,...)

La fonction CONCAT_WS() signifie CONCAT With Separator, c'est-à-dire « concaténation avec séparateur ». Le premier argument est le séparateur utilisé pour le reste des arguments. Le séparateur peut être une chaîne de caractères, tout comme le reste des arguments. Si le séparateur est NULL, le résultat sera NULL. Cette fonction ignorera tous les arguments de valeur NULL et vides, hormis le séparateur. Le séparateur sera ajouté entre tous les arguments à concaténer :

mysql> SELECT CONCAT_WS(",","Premier nom","Deuxième nom","Dernier nom");
-> 'Premier nom,Deuxième nom,Dernier nom'
mysql> SELECT CONCAT_WS(",","Premier nom",NULL,"Dernier nom");
-> 'Premier nom,Dernier nom'

- CONV(N,from_base,to_base)

Convertit des nombres entre différentes bases. Retourne une chaîne de caractères représentant le nombre N, converti de la base from_base vers la base to_base. La fonction retourne NULL si un des arguments est NULL. L'argument N est interprété comme un entier, mais peut être spécifié comme un entier ou une chaîne de caractères. Le minimum pour la base est 2 et son maximum est 36. Si to_base est un nombre négatif, N sera considéré comme un nombre signé. Dans le cas contraire, N sera traité comme un nombre non signé. La fonction CONV travaille avec une précision de 64 bits :

mysql> SELECT CONV("a",16,2);
-> '1010'
mysql> SELECT CONV("6E",18,8);
-> '172'
mysql> SELECT CONV(-17,10,-18);
-> '-H'
mysql> SELECT CONV(10+"10"+'10'+0xa,10,10);
-> '40'

- ELT(N,str1,str2,str3,...)

Retourne str1 si N = 1, str2 si N = 2, et ainsi de suite. Retourne NULL si N est plus petit que 1 ou plus grand que le nombre d'arguments. La fonction ELT() est un complément de la fonction FIELD() :

mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
-> 'ej'
mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
-> 'foo'

- EXPORT_SET(bits,on,off,[séparateur,[nombre_de_bits]])

Retourne une chaîne dont tous les bits à 1 dans « bit » sont représentés par la chaîne « on », et dont tous les bits à 0 sont représentés par la chaîne « off ». Chaque chaîne est séparée par 'séparateur' (par défaut, une virgule '','') et seul « nombre_de_bits » (par défaut, 64) « bits » est utilisé :

mysql> SELECT EXPORT_SET(5,'Y','N',',',4)
-> Y,N,Y,N

- FIELD(str,str1,str2,str3,...)

Retourne l'index de la chaîne str dans la liste str1, str2, str3, .... Retourne 0 si str n'est pas trouvé. La fonction FIELD() est un complément de la fonction ELT() :

mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 2
mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 0

- FIND_IN_SET(str,strlist)

Retourne une valeur de 1 à N si la chaîne str se trouve dans la liste strlist constituée de N chaînes. Une liste de chaînes est une chaîne composée de sous-chaînes séparées par une virgule ','. Si le premier argument est une chaîne constante et le second, une colonne de type SET, la fonction FIND_IN_SET() est optimisée pour utiliser une recherche binaire très rapide. Retourne 0 si str n'est pas trouvé dans la liste strlist ou si la liste strlist est une chaîne vide. Retourne NULL si l'un des arguments est NULL. Cette fonction ne fonctionne pas correctement si le premier argument contient une virgule ',' :

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2

- HEX(N_or_S)

Si l'argument N_OR_S est un nombre, cette fonction retournera une chaîne de caractères représentant la valeur hexadécimale de l'argument N, où l'argument N est de type BIGINT. Cette fonction est un équivalent de CONV(N,10,16).

Si N_OR_S est une chaîne de caractères, cette fonction retournera une chaîne de caractères hexadécimale de N_OR_S où chaque caractère de N_OR_S est converti en 2 chiffres hexadécimaux. C'est l'inverse de la chaîne 0xff.

mysql> SELECT HEX(255);
-> 'FF'
mysql> SELECT HEX("abc");
-> 616263
mysql> SELECT 0x616263;
-> "abc"

- INSERT(str,pos,len,newstr)

Retourne une chaîne de caractères str, après avoir remplacé la portion de chaîne commençant à la position pos et de longueur len caractères, par la chaîne newstr :

mysql> SELECT INSERT('Quadratic', 3, 4, 'What');
-> 'QuWhattic'

Cette fonction gère les caractères multioctets.

- INSTR(str,substr)

Retourne la position de la première occurrence de la chaîne substr dans la chaîne de caractères str. Cette fonction est exactement la même que la fonction LOCATE(), à la différence que ces arguments sont inversés :

mysql> SELECT INSTR('foobarbar', 'bar');
-> 4
mysql> SELECT INSTR('xbar', 'foobar');
-> 0

Cette fonction gère les caractères multioctets. Dans la version 3.23 de MySQL, cette fonction est sensible à la casse, alors que dans la version 4.0 de MySQL, cette fonction sera sensible à la casse si l'argument est une chaîne de caractères binaire.

- LCASE(str)

LCASE() est un synonyme de LOWER().

- LEFT(str,len)

Retourne les len caractères les plus à gauche de la chaîne de caractères str :

mysql> SELECT LEFT('foobarbar', 5);
-> 'fooba'

Cette fonction gère les caractères multioctets.

- LENGTH(str)

Retourne la taille de la chaîne str, mesurée en octets. Un caractère multioctet compte comme un seul caractère. Cela signifie que pour une chaîne contenant 5 caractères de 2 octets, LENGTH() retournera 10, alors que CHAR_LENGTH() retournera 5.

mysql> SELECT LENGTH('text');
-> 4

- LOAD_FILE(file_name)

Lit le fichier file_name et retourne son contenu sous la forme d'une chaîne de caractères. Le fichier doit se trouver sur le serveur qui exécute MySQL, vous devez spécifier le chemin absolu du fichier et vous devez avoir les droits en lecture sur celui-ci. Le fichier doit pouvoir être lisible par tous et doit être plus petit que max_allowed_packet.

Si ce fichier n'existe pas ou ne peut pas être lu pour différentes raisons, la fonction retourne NULL :

mysql> UPDATE tbl_name
SET blob_column=LOAD_FILE("/tmp/picture")
WHERE id=1;

Si vous n'utilisez pas la version 3.23 de MySQL, vous devez lire le fichier depuis votre application et créer ainsi votre requête INSERT vous-même, pour mettre à jour la base de données avec le contenu de ce fichier. Une des possibilités pour réaliser ceci, si vous utilisez la bibliothèque MySQL++, peut être trouvée à http://www.mysql.com/documentation/mysql++/mysql++-examples.html.

- LOCATE(substr,str), LOCATE(substr,str,pos)

Retourne la position de la première occurrence de la chaîne substr dans la chaîne de caractères str. Retourne 0 si substr ne se trouve pas dans la chaîne de caractères str :

mysql> SELECT LOCATE('bar', 'foobarbar');
-> 4
mysql> SELECT LOCATE('xbar', 'foobar');
-> 0
mysql> SELECT LOCATE('bar', 'foobarbar',5);
-> 7

Cette fonction gère les caractères multioctets. Dans la version 3.23 de MySQL, cette fonction est sensible à la casse, alors que dans la version 4.0 de MySQL, cette fonction sera sensible à la casse si l'argument est une chaîne de caractères binaire.

- LOWER(str)

Retourne la chaîne str avec tous les caractères en minuscules, en fonction du jeu de caractères courant (par défaut, c'est le jeu ISO-8859-1 Latin1) :

mysql> SELECT LOWER('QUADRATIQUE');
-> 'quadratique'

Cette fonction gère les caractères multioctets.

- LPAD(str,len,padstr)

Retourne la chaîne de caractères str, complétée à gauche par la chaîne de caractères padstr jusqu'à ce que la chaîne de caractères str atteigne len caractères de long. Si la chaîne de caractères str est plus longue que len caractères, elle sera raccourcie à len caractères.

mysql> SELECT LPAD('hi',4,'??');
-> '??hi'

- LTRIM(str)

Retourne la chaîne de caractères str sans les espaces initiaux :

mysql> SELECT LTRIM('  barbar');
-> 'barbar'

- MAKE_SET(bits,str1,str2,...)

Retourne une liste (une chaîne contenant des sous-chaînes séparées par une virgule ',') constituée de chaînes qui ont le bit correspondant dans la liste bits. str1 correspond au bit 0, str2 au bit 1, etc. Les chaînes NULL dans les listes str1, str2, ... sont ignorées :

mysql> SELECT MAKE_SET(1,'a','b','c');
-> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
-> 'hello,world'
mysql> SELECT MAKE_SET(0,'a','b','c');
-> ''

- MID(str,pos,len)

MID(str,pos,len) est un synonyme de SUBSTRING(str,pos,len).

- OCT(N)

Retourne une chaîne de caractères représentant la valeur octale de l'argument N, où l'argument N est un nombre de type BIGINT. Cette fonction est un équivalent de CONV(N,10,8). Retourne NULL si l'argument N est NULL :

mysql> SELECT OCT(12);
-> '14'

- OCTET_LENGTH(str)

OCTET_LENGTH() est un synonyme de LENGTH().

- ORD(str)

Si le premier caractère de la chaîne str est un caractère multioctet, la fonction retourne le code de ce caractère, calculé à partir du code ASCII retourné par cette formule :

(1st octet * 256)
+ (2nd octet * 256^2)
+ (3rd octet * 256^3) ...

Si le premier caractère n'est pas un caractère multioctet, la fonction retournera la même valeur que la fonction ASCII() :

mysql> SELECT ORD('2');
-> 50

- POSITION(substr IN str)

POSITION(substr IN str) est un synonyme de LOCATE(substr,str).

- QUOTE(str)

Échappe les caractères d'une chaîne pour produire un résultat qui sera exploitable dans une requête SQL. Les caractères suivants seront précédés d'un antislash dans la chaîne retournée : le guillemet simple ('''), l'antislash ('\'), ASCII NUL, et le Contrôle-Z. Si l'argument vaut NULL, la valeur retournée sera le mot « NULL » sans les guillemets simples. La fonction QUOTE a été ajoutée en MySQL version 4.0.3.

mysql> SELECT QUOTE("Don't");
-> 'Don\'t!'
mysql> SELECT QUOTE(NULL);
-> NULL

- REPEAT(str,count)

Retourne une chaîne de caractères constituée de la répétition de count fois la chaîne str. Si count <= 0, retourne une chaîne vide. Retourne NULL si str ou count sont NULL :

mysql> SELECT REPEAT('MySQL', 3);
-> 'MySQLMySQLMySQL'

- REPLACE(str,from_str,to_str)

Retourne une chaîne de caractères str dont toutes les occurrences de la chaîne from_str sont remplacées par la chaîne to_str :

mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
-> 'WwWwWw.mysql.com'

Cette fonction gère les caractères multioctets.

- REVERSE(str)

Retourne une chaîne dont l'ordre des caractères est l'inverse de la chaîne str :

mysql> SELECT REVERSE('abc');
-> 'cba'

Cette fonction gère les caractères multioctets.

- RIGHT(str,len)

Retourne les len caractères les plus à droite de la chaîne de caractères str :

mysql> SELECT RIGHT('foobarbar', 4);
-> 'rbar'

Cette fonction gère les caractères multioctets.

- RPAD(str,len,padstr)

Retourne la chaîne de caractères str, complétée à droite par la chaîne de caractères padstr jusqu'à ce que la chaîne de caractères str atteigne len caractères de long. Si la chaîne de caractères str est plus longue que len caractères, elle sera raccourcie à len caractères.

mysql> SELECT RPAD('hi',5,'?');
-> 'hi???'

- RTRIM(str)

Retourne la chaîne de caractères str sans les espaces finals :

mysql> SELECT RTRIM('barbar   ');
-> 'barbar'

Cette fonction gère les caractères multioctets.

- SOUNDEX(str)

Retourne la valeur Soundex de la chaîne de caractères str. Deux chaînes qui ont des sonorités proches auront des valeurs soundex proches. Une chaîne Soundex standard possède 4 caractères, mais la fonction SOUNDEX() retourne une chaîne de longueur arbitraire. Vous pouvez utiliser la fonction SUBSTRING() sur ce résultat pour obtenir une chaîne Soundex standard. Tout caractère non alphanumérique sera ignoré. Tous les caractères internationaux qui ne font pas partie de l'alphabet de base (A-Z) seront considérés comme des voyelles :

mysql> SELECT SOUNDEX('Hello');
-> 'H400'
mysql> SELECT SOUNDEX('Quadratically');
-> 'Q36324'

Note : cette fonction implémente l'algorithme soundex original, et non la version populaire améliorée (aussi décrite par D. Knuth). La différence est que la version originale supprime les voyelles, puis les doublons, alors que la version améliorée supprime les doublons d'abord, et ensuite, les voyelles.

- expr1 SOUNDS LIKE expr2

Identique à SOUNDEX(expr1)=SOUNDEX(expr2) (disponible depuis la version 4.1).

- SPACE(N)

Retourne une chaîne constituée de N espaces :

mysql> SELECT SPACE(6);
-> '      '

- SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len)

Retourne une chaîne de len caractères de long de la chaîne str, à partir de la position pos. La syntaxe ANSI SQL92 utilise une variante de la fonction FROM :

mysql> SELECT SUBSTRING('Quadratically',5);
-> 'ratically'
mysql> SELECT SUBSTRING('foobarbar' FROM 4);
-> 'barbar'
mysql> SELECT SUBSTRING('Quadratically',5,6);
-> 'ratica'

Cette fonction gère les caractères multioctets.

- SUBSTRING_INDEX(str,delim,count)

Retourne une portion de la chaîne de caractères str, située avant count occurrences du délimiteur delim. Si l'argument count est positif, tout ce qui précède le délimiteur final sera retourné. Si l'argument count est négatif, tout ce qui suit le délimiteur final sera retourné :

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql'
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'

Cette fonction gère les caractères multioctets.

- TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)

Retourne la chaîne de caractères str dont tous les préfixes et/ou suffixes remstr ont été supprimés. Si aucun des spécificateurs BOTH, LEADING ou TRAILING n'est fourni, BOTH est utilisé comme valeur par défaut. Si remstr n'est pas spécifié, les espaces sont supprimés :

mysql> SELECT TRIM('  bar   ');
-> 'bar'
mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
-> 'barxxx'
mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
-> 'bar'
mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
-> 'barx'

Cette fonction gère les caractères multioctets.

- UCASE(str)

UCASE() est un synonyme de UPPER().

- UNCOMPRESS(string_to_uncompress)

Décompresse une chaîne compressée avec COMPRESS(). Si l'argument n'est pas une valeur compressée, le résultat est NULL. Cette fonction requiert la bibliothèque zlib. Sinon, la valeur retournée est toujours NULL.

mysql> SELECT UNCOMPRESS(COMPRESS('any string'));
-> 'any string'
mysql> SELECT UNCOMPRESS('any string');
-> NULL

UNCOMPRESS() a été ajoutée en MySQL 4.1.1.

- UNCOMPRESSED_LENGTH(compressed_string)

Retourne la taille de la chaîne avant compression.

mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));
-> 30

UNCOMPRESSED_LENGTH() a été ajoutée en MySQL 4.1.1.

- UNHEX(str)

Le contraire de HEX(string). C'est-à-dire, chaque paire de chiffres hexadécimaux est interprétée comme des nombres, et convertie en un caractère représenté par le nombre. Le résultat est retourné sous forme de chaîne binaire.

mysql> SELECT UNHEX('4D7953514C');
-> 'MySQL'
mysql> SELECT 0x4D7953514C;
-> 'MySQL'
mysql> SELECT UNHEX(HEX('string'));
-> 'string'
mysql> SELECT HEX(UNHEX('1267'));
-> '1267'

UNHEX() a été ajoutée en MySQL 4.1.2.

- UPPER(str)

Retourne la chaîne str en majuscules, en fonction du jeu de caractères courant. Par défaut, c'est le jeu ISO-8859-1 Latin1 :

mysql> SELECT UPPER('Hey');
-> 'HEY'

Cette fonction gère les caractères multioctets.

12-3-1 - Opérateurs de comparaison pour les chaînes de caractères

MySQL convertit automatiquement les nombres en chaînes et vice-versa :

mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'

Si vous devez convertir explicitement un nombre en chaîne, passez-le en argument de la fonction CONCAT().

mysql> SELECT 38.8, CAST(38.8 AS CHAR);
-> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'

CAST() est recommandée, mais elle a été ajoutée en MySQL 4.0.2.

Si une fonction de chaîne de caractères est donnée comme chaîne binaire dans un argument d'une autre fonction, le résultat sera aussi une chaîne binaire. Les nombres convertis en chaînes sont traités comme des chaînes binaires. Cela affecte les comparaisons.

Normalement, si l'une des expressions dans une comparaison de chaînes est sensible à la casse, la comparaison est exécutée en tenant compte de la casse.

- expr LIKE pat [ESCAPE 'escape-char']

La réalisation d'expression utilisant les expressions régulières simples de comparaison de SQL. Retourne 1 (TRUE) ou 0 (FALSE). Avec LIKE, vous pouvez utiliser les deux jokers suivants :

Char

Description

%

Remplace n'importe quel nombre de caractères, y compris aucun

_

Remplace exactement un caractère

mysql> SELECT 'David!' LIKE 'David_';
-> 1
mysql> SELECT 'David!' LIKE '%D%v%';
-> 1

Pour tester la présence littérale d'un joker, précédez-le d'un caractère d'échappement. Si vous ne spécifiez pas le caractère d'échappement ESCAPE, le caractère '\' sera utilisé :

String

Description

\%

Remplace le caractère littéral '%'

\_

Remplace le caractère littéral '_'

mysql> SELECT 'David!' LIKE 'David\_';
-> 0
mysql> SELECT 'David_' LIKE 'David\_';
-> 1

Pour spécifier un caractère d'échappement différent, utilisez la clause ESCAPE :

mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
-> 1

Les deux exemples suivants illustrent le fait que les comparaisons de chaînes de caractères ne sont pas sensibles à la casse à moins qu'un des opérandes soit une chaîne binaire.

mysql> SELECT 'abc' LIKE 'ABC';
-> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
-> 0

LIKE est également autorisé pour les expressions numériques. (C'est une extension MySQL à la norme ANSI SQL LIKE.)

mysql> SELECT 10 LIKE '1%';
-> 1

Note : comme MySQL utilise la syntaxe d'échappement de caractères du langage C dans les chaînes (par exemple, '\n'), vous devez doubler tous les slashes '\' que vous utilisez dans les expressions LIKE. Par exemple, pour rechercher les nouvelles lignes ('\n'), vous devez le spécifier comme cela : '\\n'. Pour rechercher un antislash ('\'), vous devez le spécifier comme cela : '\\\\' (les antislashes sont supprimés une première fois par l'analyseur syntaxique, puis une deuxième fois par le moteur d'expressions régulières, ce qui ne laisse qu'un seul antislash à la fin).

Note : actuellement, LIKE n'est pas compatible avec les caractères multioctets. La comparaison est faite caractère par caractère.

- expr NOT LIKE pat [ESCAPE 'escape-char']

Équivalent à NOT (expr LIKE pat [ESCAPE 'escape-char']).

- expr NOT REGEXP pat, expr NOT RLIKE pat

Équivalent à NOT (expr REGEXP pat).

- expr REGEXP pat, expr RLIKE pat

Effectue une recherche de chaînes avec l'expression régulière pat. Le masque peut être une expression régulière étendue. Voir la section Annexe F, Expressions régulières MySQL. Retourne 1 si expr correspond au masque pat, sinon, retourne 0. RLIKE est un synonyme de REGEXP, fourni pour assurer la compatibilité avec mSQL. Note : comme MySQL utilise la syntaxe d'échappement de caractères du langage C dans les chaînes (par exemple, '\n'), vous devez doubler tous les antislashes '\' que vous utilisez dans les expressions REGEXP. À partir de la version 3.23.4 de MySQL, REGEXP est insensible à la casse pour les comparaisons de chaînes normales (non binaires) :

mysql> SELECT 'Monty!' REGEXP 'm%y%%';
-> 0
mysql> SELECT 'Monty!' REGEXP '.*';
-> 1
mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
-> 1
mysql> SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';
-> 1  0
mysql> SELECT 'a' REGEXP '^[a-d]';
-> 1

- STRCMP(expr1,expr2)

STRCMP() retourne 0 si les chaînes sont identiques, -1 si la première chaîne est plus petite que la seconde et 1 dans les autres cas :

mysql> SELECT STRCMP('text', 'text2');
-> -1
mysql> SELECT STRCMP('text2', 'text');
-> 1
mysql> SELECT STRCMP('text', 'text');
-> 0

Depuis MySQL 4.0, STRCMP() utilise le jeu de caractères courant pour effectuer des comparaisons. Cela fait que le comportement par défaut est la comparaison insensible à la casse, à moins que l'un des deux opérandes soit une chaîne binaire. Avant MySQL 4.0, STRCMP() était sensible à la casse.

12-4 - Fonctions numériques

12-4-1 - Opérations arithmétiques

Les opérateurs arithmétiques usuels sont disponibles. Notez que dans le cas de '-', '+' et '*', le résultat est calculé avec en BIGINT avec une précision de 64 bits si les deux arguments sont des entiers ! Si l'un des arguments est un entier non signé, et que l'autre argument est aussi un entier, le résultat sera un entier non signé. Voir Section 12.7, « Fonctions de transtypage ».

- +

Addition :

mysql> SELECT 3+5;
-> 8

- -

Soustraction :

mysql> SELECT 3-5;
-> -2

- -

Moins unaire. Change le signe de l'argument :

mysql> SELECT - 2;
-> -2

Notez que si cet opérateur est utilisé avec un BIGINT, la valeur retournée est un BIGINT ! Cela signifie que vous devez éviter d'utiliser - sur des entiers qui peuvent avoir une valeur de -2^63 !

- *

Multiplication :

mysql> SELECT 3*5;
-> 15
mysql> SELECT 18014398509481984*18014398509481984.0;
-> 324518553658426726783156020576256.0
mysql> SELECT 18014398509481984*18014398509481984;
-> 0

Le résultat du dernier calcul est incorrect, car le résultat de la multiplication des deux entiers a dépassé la capacité de calcul de BIGINT (64 bits).

- /

Division :

mysql> SELECT 3/5;
-> 0.60

La division par zéro produit un résultat NULL :

mysql> SELECT 102/(1-1);
-> NULL

Une division sera calculée en BIGINT seulement si elle est effectuée dans un contexte où le résultat est transformé en entier.

- DIV

Division entière. Similaire à FLOOR() mais compatible avec les valeurs BIGINT.

mysql> SELECT 5 DIV 2;
-> 2

DIV a été ajouté en MySQL 4.1.0.

12-4-2 - Fonctions mathématiques

Toutes les fonctions mathématiques retournent NULL en cas d'erreur.

- ABS(X)

Retourne la valeur absolue de X.

mysql> SELECT ABS(2);
-> 2
mysql> SELECT ABS(-32);
-> 32

Cette fonction est utilisable avec les valeurs issues des champs BIGINT.

- ACOS(X)

Retourne l'arc cosinus de X, c'est-à-dire, la valeur de l'angle dont X est le cosinus. Retourne NULL si X n'est pas dans l'intervalle -1 - 1.

mysql> SELECT ACOS(1);
-> 0.000000
mysql> SELECT ACOS(1.0001);
-> NULL
mysql> SELECT ACOS(0);
-> 1.570796

- ASIN(X)

Retourne l'arc sinus de X, c'est-à-dire, la valeur de l'angle dont le sinus est X. Retourne NULL si X n'est pas dans l'intervalle -1 - 1 :

mysql> SELECT ASIN(0.2);
-> 0.201358
mysql> SELECT ASIN('foo');
-> 0.000000

- ATAN(X)

Retourne l'arc tangente de X, c'est-à-dire, la valeur de l'angle dont la tangente est X.

mysql> SELECT ATAN(2);
-> 1.107149
mysql> SELECT ATAN(-2);
-> -1.107149

- ATAN(Y,X), ATAN2(Y,X)

Retourne l'arc tangente des variables X et Y. Cela revient à calculer l'arc tangente de Y / X, excepté que les signes des deux arguments servent à déterminer le quadrant du résultat :

mysql> SELECT ATAN(-2,2);
-> -0.785398
mysql> SELECT ATAN2(PI(),0);
-> 1.570796

- CEILING(X), CEIL(X)

Retourne la valeur entière supérieure de X.

mysql> SELECT CEILING(1.23);
-> 2
mysql> SELECT CEILING(-1.23);
-> -1

Notez que la valeur retournée sera de type BIGINT !

- COS(X)

Retourne le cosinus de X, où X est donné en radians.

mysql> SELECT COS(PI());
-> -1.000000

- COT(X)

Retourne la cotangente de X.

mysql> SELECT COT(12);
-> -1.57267341
mysql> SELECT COT(0);
-> NULL

- CRC32(expr)

Calcule la somme de contrôle et retourne un entier 32 bits non signé. Le résultat est la valeur NULL si l'argument est NULL. L'argument attendu est une chaîne, et sera traité comme une chaîne s'il n'est pas du bon type.

mysql> SELECT CRC32('MySQL');
-> 3259397556

CRC32() est disponible en MySQL 4.1.0.

- DEGREES(X)

Retourne l'argument X, converti de radians en degrés.

mysql> SELECT DEGREES(PI());
-> 180.000000

- EXP(X)

Retourne la valeur de e (la base des logarithmes naturels) élevé à la puissance X.

mysql> SELECT EXP(2);
-> 7.389056
mysql> SELECT EXP(-2);
-> 0.135335

- FLOOR(X)

Retourne la valeur entière inférieure de X.

mysql> SELECT FLOOR(1.23);
-> 1
mysql> SELECT FLOOR(-1.23);
-> -2

Notez que la valeur retournée sera de type BIGINT !

- LN(X)

Retourne le logarithme naturel de X (népérien).

mysql> SELECT LN(2);
-> 0.693147
mysql> SELECT LN(-2);
-> NULL

Cette fonction a été ajoutée à MySQL à partir de la version 4.0.3. C'est un synonyme de la fonction LOG(X).

- LOG(X), LOG(B,X)

Appelée avec un seul paramètre, cette fonction retourne le logarithme naturel (népérien) de X.

mysql> SELECT LOG(2);
-> 0.693147
mysql> SELECT LOG(-2);
-> NULL

Appelée avec deux paramètres, cette fonction retourne le logarithme naturel de X pour une base B arbitraire :

mysql> SELECT LOG(2,65536);
-> 16.000000
mysql> SELECT LOG(1,100);
-> NULL

Cette base arbitraire a été ajoutée à MySQL à partir de la version 4.0.3. LOG(B,X) est l'équivalent de LOG(X)/LOG(B).

- LOG2(X)

Retourne le logarithme en base 2 de X.

mysql> SELECT LOG2(65536);
-> 16.000000
mysql> SELECT LOG2(-100);
-> NULL

LOG2() est utile pour trouver combien de bits sont nécessaires pour stocker un nombre. Cette fonction a été ajoutée à MySQL à partir de la version 4.0.3. Dans les versions antérieures, vous pouvez utiliser LOG(X)/LOG(2) en remplacement.

- LOG10(X)

Retourne le logarithme en base 10 de X.

mysql> SELECT LOG10(2);
-> 0.301030
mysql> SELECT LOG10(100);
-> 2.000000
mysql> SELECT LOG10(-100);
-> NULL

- MOD(N,M), N % M, N MOD M

Modulo (équivalent de l'opérateur % dans le langage C). Retourne le reste de la division de N par M.

mysql> SELECT MOD(234, 10);
-> 4
mysql> SELECT 253 % 7;
-> 1
mysql> SELECT MOD(29,9);
-> 2

Cette fonction ne pose pas de problèmes avec les BIGINT.

- PI()

Retourne la valeur de pi. Par défaut, 5 décimales sont retournées, mais MySQL utilise la double précision pour pi.

mysql> SELECT PI();
-> 3.141593
mysql> SELECT PI()+0.000000000000000000;
-> 3.141592653589793116

- POW(X,Y), POWER(X,Y)

Retourne la valeur de X élevée à la puissance Y :

mysql> SELECT POW(2,2);
-> 4.000000
mysql> SELECT POW(2,-2);
-> 0.250000

- RADIANS(X)

Retourne l'argument X, converti de degrés en radians.

mysql> SELECT RADIANS(90);
-> 1.570796

- RAND(), RAND(N)

Retourne un nombre aléatoire à virgule flottante compris dans l'intervalle 0 - 1.0. Si l'argument entier N est spécifié, il est utilisé comme initialisation du générateur de nombres aléatoires.

mysql> SELECT RAND();
-> 0.9233482386203
mysql> SELECT RAND(20);
-> 0.15888261251047
mysql> SELECT RAND(20);
-> 0.15888261251047
mysql> SELECT RAND();
-> 0.63553050033332
mysql> SELECT RAND();
-> 0.70100469486881

Vous ne pouvez pas utiliser une colonne de valeur RAND() dans une clause ORDER BY, parce que ORDER BY va évaluer la colonne plusieurs fois. Dans la version 3.23 de MySQL, vous pouvez, tout de même, faire ceci :

mysql> SELECT * FROM tbl_name ORDER BY RAND();

Cette syntaxe est très pratique pour faire une sélection aléatoire de lignes :

mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d
-> ORDER BY RAND() LIMIT 1000;

Notez que la fonction RAND() dans une clause WHERE sera réévaluée à chaque fois que WHERE sera exécuté.

RAND() n'est pas un générateur parfait de nombres aléatoires, mais reste une manière rapide de produire des nombres aléatoires portables selon les différentes plates-formes pour une même version de MySQL.

- ROUND(X), ROUND(X,D)

Retourne l'argument X, arrondi à un nombre à D décimales. Avec deux arguments, la valeur est arrondie avec D décimales.

Si D vaut 0, le résultat n'aura ni de partie décimale, ni de séparateur décimal.

mysql> SELECT ROUND(-1.23);
-> -1
mysql> SELECT ROUND(-1.58);
-> -2
mysql> SELECT ROUND(1.58);
-> 2
mysql> SELECT ROUND(1.298, 1);
-> 1.3
mysql> SELECT ROUND(1.298, 0);
-> 1
mysql> SELECT ROUND(23.298, -1);
-> 20

Notez que le comportement de l'opérateur ROUND(), lorsque l'argument est exactement entre deux entiers, dépend de la bibliothèque C active. Certaines arrondissent toujours à l'entier pair le plus proche, toujours vers le haut, toujours vers le bas, ou toujours vers zéro. Si vous avez besoin d'un certain type d'arrondissement, vous devez utiliser une fonction bien définie comme TRUNCATE() ou FLOOR().

- SIGN(X)

Retourne le signe de l'argument sous la forme -1, 0, ou 1, selon que X est négatif, zéro, ou positif.

mysql> SELECT SIGN(-32);
-> -1
mysql> SELECT SIGN(0);
-> 0
mysql> SELECT SIGN(234);
-> 1

- SIN(X)

Retourne le sinus de X, où X est donné en radians.

mysql> SELECT SIN(PI());
-> 0.000000

- SQRT(X)

Retourne la racine carrée de X.

mysql> SELECT SQRT(4);
-> 2.000000
mysql> SELECT SQRT(20);
-> 4.472136

- TAN(X)

Retourne la tangente de X, où X est donné en radians.

mysql> SELECT TAN(PI()+1);
-> 1.557408

- TRUNCATE(X,D)

Retourne l'argument X, tronqué à D décimales. Si D vaut 0, le résultat n'aura ni séparateur décimal ni partie décimale.

mysql> SELECT TRUNCATE(1.223,1);
-> 1.2
mysql> SELECT TRUNCATE(1.999,1);
-> 1.9
mysql> SELECT TRUNCATE(1.999,0);
-> 1
mysql> SELECT TRUNCATE(-1.999,1);
-> -1.9

À partir de MySQL 3.23.51 tous les nombres sont arrondis vers zéro.

Notez que les nombres décimaux ne sont pas stockés exactement comme les nombres entiers, mais comme des valeurs doubles. Vous pouvez être dupés par le résultat suivant :

mysql> SELECT TRUNCATE(10.28*100,0);
-> 1027

Ce résultat est normal, car 10.28 est actuellement stocké comme cela 10.2799999999999999.

12-5 - Fonctions de dates et d'heures

Cette section décrit les fonctions qui peuvent être utilisées pour manipuler les valeurs temporelles. Voir Section 11.3, « Les types date et heure » pour une description détaillée des intervalles de validité de chaque type, ainsi que les formats valides de spécifications des dates et heures.

Voici un exemple d'utilisation des fonctions de dates. La requête suivante sélectionne toutes les lignes dont la colonne date_col représente une date de moins de 30 jours :

mysql> SELECT quelquechose FROM nom_de_table
WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;

Notez que cette requête va aussi sélectionner des lignes dont les dates sont dans le futur.

Les fonctions qui utilisent des valeurs de date acceptent les valeurs de type DATETIME et ignore la partie horaire. Les fonctions qui attendent des heures acceptent les valeurs littérales et ignorent la partie de date.

Les fonctions qui retournent la date ou l'heure courante sont évaluées une fois par requête, tout au début. Cela signifie que des références multiples à la fonction NOW() dans une même requête produiront toujours le même résultat. Ce principe s'applique aussi à CURDATE(), CURTIME(), UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP(), et leurs synonymes.

Les intervalles de valeurs de retour des fonctions suivantes s'appliquent aux dates complètes. Si une date est une valeur « zéro » ou une date incomplète, comme '2001-11-00', les fonctions qui extraient une partie d'une date retourneront 0. Par exemple, DAYOFMONTH('2001-11-00') retourne 0.

- ADDDATE(date,INTERVAL expr type), ADDDATE(expr,days)

Lorsqu'elle est utilisée avec la forme INTERVAL, ADDDATE() est un synonyme de DATE_ADD(). La fonction complémentaire SUBDATE() est un synonyme DATE_SUB().

mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
-> '1998-02-02'
mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
-> '1998-02-02'

Depuis MySQL 4.1.1, la seconde syntaxe est utilisée si expr est une expression de type DATE ou DATETIME, et que days est un nombre de jours à ajouter à expr.

mysql> SELECT ADDDATE('1998-01-02', 31);
-> '1998-02-02'

- ADDTIME(expr,expr2)

ADDTIME() ajoute expr2 à expr et retourne le résultat. expr est une expression de type DATE ou DATETIME, et expr2 est une expression de type TIME.

mysql> SELECT ADDTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
-> '1998-01-02 01:01:01.000001'
mysql> SELECT ADDTIME("01:00:00.999999", "02:00:00.999998");
-> '03:00:01.999997'

ADDTIME() a été ajouté en MySQL 4.1.1.

- CURDATE(), CURRENT_DATE

Retourne la date courante au format 'YYYY-MM-DD' ou YYYYMMDD, suivant le contexte numérique ou chaîne :

mysql> SELECT CURDATE();
-> '1997-12-15'
mysql> SELECT CURDATE() + 0;
-> 19971215

- CURRENT_DATE, CURRENT_DATE()

CURRENT_DATE et CURRENT_DATE() sont synonymes de CURDATE().

- CURTIME()

Retourne l'heure courante au format 'HH:MM:SS' or HHMMSS suivant le contexte numérique ou chaîne :

mysql> SELECT CURTIME();
-> '23:50:26'
mysql> SELECT CURTIME() + 0;
-> 235026

- CURRENT_TIME, CURRENT_TIME()

CURRENT_TIME et CURRENT_TIME() sont synonymes de CURTIME().

- CURRENT_TIMESTAMP, CURRENT_TIMESTAMP()

CURRENT_TIMESTAMP et CURRENT_TIMESTAMP() sont synonymes de NOW().

- DATE(expr)

Extrait la partie date de l'expression expr de type DATE ou DATETIME.

mysql> SELECT DATE('2003-12-31 01:02:03');
-> '2003-12-31'

DATE() est disponible depuis MySQL 4.1.1.

- DATEDIFF(expr,expr2)

DATEDIFF() retourne le nombre de jours entre la date de début expr et la date de fin expr2. expr et expr2 sont des expressions de type DATE ou DATETIME. Seule la partie DATE est utilisée dans le calcul.

mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
-> 1
mysql> SELECT DATEDIFF('1997-11-31 23:59:59','1997-12-31');
-> -30

DATEDIFF() est disponible depuis MySQL 4.1.1.

- DATE_ADD(date,INTERVAL expr type), DATE_SUB(date,INTERVAL expr type)

Ces fonctions effectuent des calculs arithmétiques sur les dates.

Depuis MySQL 3.23, INTERVAL expr type est autorisé des deux côtés de l'opérateur + si l'expression de l'autre côté est de type DATE ou DATETIME. Pour l'opérateur -, INTERVAL expr type est autorisé uniquement du côté droit, car on ne peut pas soustraire une date d'un intervalle (voir les exemples ci-dessous).

date est une valeur de type DATETIME ou DATE qui spécifie la date de début. expr est une expression qui spécifie une valeur d'intervalle à ajouter ou soustraire de la date initiale. expr est une chaîne : elle peut commencer avec '-' pour les intervalles négatifs. type est un mot-clé, indiquant comment l'expression doit être interprétée.

Le tableau suivant indique la signification des arguments type et expr :

type Valeur

Attendue expr Format

MICROSECOND

MICROSECONDS

SECOND

SECONDS

MINUTE

MINUTES

HOUR

HOURS

DAY

DAYS

WEEK

WEEKS

MONTH

MONTHS

QUARTER

QUARTERS

YEAR

YEARS

SECOND_MICROSECOND

'SECONDS.MICROSECONDS'

MINUTE_MICROSECOND

'MINUTES.MICROSECONDS'

MINUTE_SECOND

'MINUTES:SECONDS'

HOUR_MICROSECOND

'HOURS.MICROSECONDS'

HOUR_SECOND

'HOURS:MINUTES:SECONDS'

HOUR_MINUTE

'HOURS:MINUTES'

DAY_MICROSECOND

'DAYS.MICROSECONDS'

DAY_SECOND

'DAYS HOURS:MINUTES:SECONDS'

DAY_MINUTE

'DAYS HOURS:MINUTES'

DAY_HOUR

'DAYS HOURS'

YEAR_MONTH

'YEARS-MONTHS'

Les valeurs de type DAY_MICROSECOND, HOUR_MICROSECOND, MINUTE_MICROSECOND, SECOND_MICROSECOND, et MICROSECOND ont été ajoutées en MySQL 4.1.1. Les valeurs QUARTER et WEEK sont disponibles depuis MySQL 5.0.0.

MySQL autorise tous les signes de ponctuation, comme délimiteur dans le format de expr. Ceux qui sont affichés dans la table sont des suggestions. Si l'argument date est une valeur DATE et que vos calculs impliquent des parties YEAR, MONTH et DAY (c'est-à-dire, sans partie horaire), le résultat sera de type DATE. Sinon, le résultat est de type DATETIME :

mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;
-> '1998-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '1997-12-31';
-> '1998-01-01'
mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND;
-> '1997-12-31 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
->                 INTERVAL 1 SECOND);
-> '1998-01-01 00:00:00'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
->                 INTERVAL 1 DAY);
-> '1998-01-01 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
->                 INTERVAL '1:1' MINUTE_SECOND);
-> '1998-01-01 00:01:00'
mysql> SELECT DATE_SUB('1998-01-01 00:00:00',
->                 INTERVAL '1 1:1:1' DAY_SECOND);
-> '1997-12-30 22:58:59'
mysql> SELECT DATE_ADD('1998-01-01 00:00:00',
->                 INTERVAL '-1 10' DAY_HOUR);
-> '1997-12-30 14:00:00'
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02'
mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
->                 INTERVAL '1.999999' SECOND_MICROSECOND);
-> '1993-01-01 00:00:01.000001'

Si vous spécifiez un intervalle qui est trop court (il n'inclut pas toutes les parties d'intervalle attendues par type), MySQL suppose que vous avez omis les valeurs de gauche. Par exemple, si vous spécifiez un type type de DAY_SECOND, la valeur expr devrait contenir des jours, heures, minutes et secondes. Si vous fournissez une valeur de la forme '1:10', MySQL suppose que les jours et heures manquent, et que la valeur représente des minutes et secondes. En d'autres termes, '1:10' DAY_SECOND est interprété comme '1:10' MINUTE_SECOND. C'est similaire au comportement de MySQL avec les valeurs de type TIME, qui représente des durées plutôt que des horaires.

Notez que si vous ajoutez ou soustrayez à une valeur de type DATE des horaires, le résultat sera automatiquement au format DATETIME :

mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);
-> '1999-01-02'
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);
-> '1999-01-01 01:00:00'

Si vous utilisez des dates mal formées, le résultat sera NULL. Si vous ajoutez des MONTH, YEAR_MONTH ou YEAR, et que le résultat a un jour du mois qui est au-delà de ce qui est possible dans le mois, le jour sera adapté au plus grand jour possible du mois. Par exemple :

mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);
-> '1998-02-28'

Notez que dans l'exemple précédent, le mot-clé INTERVAL et le spécificateur type sont insensibles à la casse.

- DATE_FORMAT(date,format)

Formate la date date avec le format format. Les spécificateurs suivants peuvent être utilisés dans la chaîne format :

Option

Description

%%

Un signe pourcentage littéral '%'

%a

Nom du jour de la semaine, en abrégé et en anglais (Sun..Sat)

%b

Nom du mois, en abrégé et en anglais (Jan..Dec)

%c

Mois, au format numérique (1..12)

%d

Jour du mois, au format numérique (00..31)

%D

Jour du mois, avec un suffixe anglais (1st, 2nd, 3rd, etc.)

%e

Jour du mois, au format numérique (0..31)

%f

Microsecondes (000000..999999)

%H

Heure (00..23)

%h

Heure (01..12)

%I

Heure (01..12)

%i

Minutes, au format numérique (00..59)

%j

Jour de l'année (001..366)

%k

Heure (0..23)

%l

Heure (1..12)

%m

Mois, au format numérique (01..12)

%M

Nom du mois (January..December)

%p

AM ou PM

%r

Heures, au format 12 heures (hh:mm:ss [AP]M)

%s

Secondes (00..59)

%S

Secondes (00..59)

%T

Heures, au format 24 heures (hh:mm:ss)

%U

Numéro de la semaine (00..53), où dimanche est le premier jour de la semaine

%u

Numéro de la semaine (00..53), où lundi est le premier jour de la semaine

%V

Numéro de la semaine (01..53), où dimanche est le premier jour de la semaine, utilisé avec '%X'

%v

Numéro de la semaine (01..53), où lundi est le premier jour de la semaine, utilisé avec '%x'

%W

Nom du jour de la semaine (Sunday..Saturday)

%w

Numéro du jour de la semaine (0=Sunday..6=Saturday)

%X

Année, pour les semaines qui commencent le dimanche, au format numérique, sur 4 chiffres, utilisé avec '%V'

%x

Année, pour les semaines qui commencent le lundi, au format numérique, sur 4 chiffres, utilisé avec '%v'

%y

Année, au format numérique, sur 2 chiffres

%Y

Année, au format numérique, sur 4 chiffres

Tous les autres caractères sont simplement copiés dans le résultat sans interprétation.

Le format %f est disponible depuis MySQL 4.1.1.

Depuis MySQL version 3.23, le caractère '%' est requis devant les caractères de format. Dans les versions antérieures de MySQL, '%' était optionnel.

La raison qui fait que les intervalles de mois et de jours commencent avec zéro est que MySQL autorise les dates incomplètes comme '2004-00-00', depuis MySQL 3.23.

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
-> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
-> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%D %y %a %d %m %b %j');
-> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%H %k %I %r %T %S %w');
-> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
-> '1998 52'

- DAY(date)

DAY() est un synonyme de DAYOFMONTH(). Cette fonction est disponible depuis MySQL 4.1.1.

- DAYNAME(date)

Retourne le nom du jour de la semaine de date :

mysql> SELECT DAYNAME('1998-02-05');
-> 'Thursday'

- DAYOFMONTH(date)

Retourne le jour de la date date, dans un intervalle de 1 à 31 :

mysql> SELECT DAYOFMONTH('1998-02-03');
-> 3

- DAYOFWEEK(date)

Retourne l'index du jour de la semaine : pour date (1 = dimanche, 2 = lundi, ... 7 = samedi). Ces index correspondent au standard ODBC :

mysql> SELECT DAYOFWEEK('1998-02-03');
-> 3

- DAYOFYEAR(date)

Retourne le jour de la date date, dans un intervalle de 1 à 366 :

mysql> SELECT DAYOFYEAR('1998-02-03');
-> 34

- EXTRACT(type FROM date)

La fonction EXTRACT() utilise les mêmes types d'intervalles que la fonction DATE_ADD() ou la fonction DATE_SUB(), mais extrait des parties de dates plutôt que des opérations de dates.

mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
-> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
-> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
-> 20102
mysql> SELECT EXTRACT(MICROSECOND FROM "2003-01-02 10:30:00.00123");
-> 123

- FROM_DAYS(N)

Retourne la date correspondant au nombre de jours (N) depuis la date 0 :

mysql> SELECT FROM_DAYS(729669);
-> '1997-10-07'

FROM_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du calendrier grégorien (1582), car elle ne prend pas en compte les jours perdus lors du changement de calendrier.

- FROM_UNIXTIME(unix_timestamp)

Retourne une représentation de l'argument unix_timestamp sous la forme 'YYYY-MM-DD HH:MM:SS' ou YYYYMMDDHHMMSS, suivant si la fonction est utilisée dans un contexte numérique ou de chaîne.

mysql> SELECT FROM_UNIXTIME(875996580);
-> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
-> 19971004222300

Si format est donné, le résultat est formaté en fonction de la chaîne format. format peut contenir les mêmes options de format que celles utilisées par DATE_FORMAT() :

mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),
->                      '%Y %D %M %h:%i:%s %x');
-> '2003 6th August 06:22:58 2003'

- GET_FORMAT(DATE | TIME | TIMESTAMP, 'EUR' | 'USA' | 'JIS' | 'ISO' | 'INTERNAL')

Retourne une chaîne de format. Cette fonction est pratique lorsqu'elle est utilisée avec les fonctions DATE_FORMAT() et STR_TO_DATE().

Les trois valeurs possibles pour le premier argument, et les cinq valeurs possibles pour le second argument donnent 15 formats d'affichage (pour les options utilisées, voyez le tableau de la fonction DATE_FORMAT()) :

Appel fonction

Résultat

GET_FORMAT(DATE,'USA')

'%m.%d.%Y'

GET_FORMAT(DATE,'JIS')

'%Y-%m-%d'

GET_FORMAT(DATE,'ISO')

'%Y-%m-%d'

GET_FORMAT(DATE,'EUR')

'%d.%m.%Y'

GET_FORMAT(DATE,'INTERNAL')

'%Y%m%d'

GET_FORMAT(TIMESTAMP,'USA')

'%Y-%m-%d-%H.%i.%s'

GET_FORMAT(TIMESTAMP,'JIS')

'%Y-%m-%d %H:%i:%s'

GET_FORMAT(TIMESTAMP,'ISO')

'%Y-%m-%d %H:%i:%s'

GET_FORMAT(TIMESTAMP,'EUR')

'%Y-%m-%d-%H.%i.%s'

GET_FORMAT(TIMESTAMP,'INTERNAL')

'%Y%m%d%H%i%s'

GET_FORMAT(TIME,'USA')

'%h:%i:%s %p'

GET_FORMAT(TIME,'JIS')

'%H:%i:%s'

GET_FORMAT(TIME,'ISO')

'%H:%i:%s'

GET_FORMAT(TIME,'EUR')

'%H.%i.%S'

GET_FORMAT(TIME,'INTERNAL')

'%H%i%s'

Le format ISO est le format ISO 9075, et non ISO 8601.

mysql> SELECT DATE_FORMAT('2003-10-03', GET_FORMAT(DATE, 'EUR')
-> '03.10.2003'
mysql> SELECT STR_TO_DATE('10.31.2003', GET_FORMAT(DATE, 'USA'))
-> 2003-10-31

GET_FORMAT() est disponible depuis MySQL 4.1.1. Voyez Voir Section 13.5.2.8, « Syntaxe de SET ».

- HOUR(time)

Retourne le nombre d'heures pour l'heure time, dans un intervalle de 0 à 23 :

mysql> SELECT HOUR('10:05:03');
-> 10

Cependant, l'intervalle des valeurs TIME est bien plus grand, et donc, HOUR peut retourner des valeurs plus grandes que 23 :

mysql> SELECT HOUR('272:59:59');
-> 272

- LAST_DAY(date)

Prend une valeur de format DATE ou DATETIME, et retourne le dernier jour du mois correspondant. Retourne NULL si l'argument est invalide.

mysql> SELECT LAST_DAY('2003-02-05'), LAST_DAY('2004-02-05');
-> '2003-02-28', '2004-02-29'
mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
-> '2004-01-31'
mysql> SELECT LAST_DAY('2003-03-32');
-> NULL

LAST_DAY() est disponible depuis MySQL 4.1.1.

- LOCALTIME, LOCALTIME()

LOCALTIME et LOCALTIME() sont synonymes de NOW().

- LOCALTIMESTAMP, LOCALTIMESTAMP()

LOCALTIMESTAMP et LOCALTIMESTAMP() sont synonymes de NOW().

- MAKEDATE(year,dayofyear)

Retourne une valeur de format DATE, à partir d'une année et du numéro de jour. dayofyear doit être plus grand que 0 ou le résultat sera NULL.

mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);
-> '2001-01-31', '2001-02-01'
mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
-> '2001-12-31', '2004-12-30'
mysql> SELECT MAKEDATE(2001,0);
-> NULL

MAKEDATE() est disponible depuis MySQL 4.1.1.

- MAKETIME(hour,minute,second)

Retourne une valeur de format TIME, calculée à partir des arguments hour, minute et second.

mysql> SELECT MAKETIME(12,15,30);
-> '12:15:30'

MAKETIME() est disponible depuis MySQL 4.1.1.

- MICROSECOND(expr)

Retourne le nombre de microsecondes dans l'expression de type TIME ou DATETIME expr, sous la forme d'un nombre entre 0 et 999999.

mysql> SELECT MICROSECOND('12:00:00.123456');
-> 123456
mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010');
-> 10

MICROSECOND() est disponible depuis MySQL 4.1.1.

- MINUTE(time)

Retourne le nombre de minutes pour l'heure time, dans un intervalle de 0 à 59 :

mysql> SELECT MINUTE('98-02-03 10:05:03');
-> 5

- MONTH(date)

Retourne le numéro du mois de la date date, dans un intervalle de 1 à 12 :

mysql> SELECT MONTH('1998-02-03');
-> 2

- MONTHNAME(date)

Retourne le nom du mois de la date date :

mysql> SELECT MONTHNAME("1998-02-05");
-> 'February'

- NOW()

Retourne la date courante au format 'YYYY-MM-DD HH:MM:SS' ou YYYYMMDDHHMMSS, suivant le contexte numérique ou chaîne :

mysql> SELECT NOW();
-> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
-> 19971215235026

- PERIOD_ADD(P,N)

Ajoute N mois à la période P (au format YYMM ou YYYYMM). Retourne une valeur dans le format YYYYMM.

Notez que l'argument P n'est pas de type date :

mysql> SELECT PERIOD_ADD(9801,2);
-> 199803

- PERIOD_DIFF(P1,P2)

Retourne le nombre de mois entre les périodes P1 et P2. P1 et P2 doivent être au format YYMM ou YYYYMM.

Notez que les arguments P1 et P2 ne sont pas de type date :

mysql> SELECT PERIOD_DIFF(9802,199703);
-> 11

- QUARTER(date)

Retourne le numéro du trimestre de la date date, dans un intervalle de 1 à 4 :

mysql> SELECT QUARTER('98-04-01');
-> 2

- SECOND(time)

Retourne le nombre de secondes pour l'heure time, dans un intervalle de 0 à 59 :

mysql> SELECT SECOND('10:05:03');
-> 3

- SEC_TO_TIME(seconds)

Retourne l'argument seconds, converti en heures, minutes et secondes au format 'HH:MM:SS' ou HHMMSS, suivant le contexte numérique ou chaîne :

mysql> SELECT SEC_TO_TIME(2378);
-> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
-> 3938

- STR_TO_DATE(str,format)

Cette fonction est l'inverse de la fonction DATE_FORMAT(). Elle prend la chaîne str, et une chaîne de format format, puis retourne une valeur DATETIME.

Les valeurs de type DATE, TIME ou DATETIME contenues dans la chaîne str doivent être au format format. Pour les options qui sont utilisables dans la chaîne format, voyez le tableau dans la description de la fonction DATE_FORMAT(). Tous les autres caractères sont utilisés littéralement, et ne seront pas interprétés. Si str contient une valeur illégale, STR_TO_DATE() retourne NULL.

mysql> SELECT STR_TO_DATE('03.10.2003 09.20', '%d.%m.%Y %H.%i')
-> 2003-10-03 09:20:00
mysql> SELECT STR_TO_DATE('10rap', '%crap')
-> 0000-10-00 00:00:00
mysql> SELECT STR_TO_DATE('2003-15-10 00:00:00', '%Y-%m-%d %H:%i:%s')
-> NULL

STR_TO_DATE() est disponible depuis MySQL 4.1.1.

- SUBDATE(date,INTERVAL expr type), SUBDATE(expr,days)

Lorsqu'elle est utilisée avec la forme INTERVAL du second argument, SUBDATE() est synonyme DATE_SUB().

mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02'
mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02'

Depuis MySQL 4.1.1, la seconde syntaxe est autorisée, où expr est une expression de type DATE ou DATETIME et days est le nombre de jours à soustraire de l'expression expr.

mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31);
-> '1997-12-02 12:00:00'

- SUBTIME(expr,expr2)

SUBTIME() soustrait expr2 de expr et retourne le résultat. expr est une expression de format DATE ou DATETIME et expr2 est une expression de type TIME.

mysql> SELECT SUBTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
-> '1997-12-30 22:58:58.999997'
mysql> SELECT SUBTIME("01:00:00.999999", "02:00:00.999998");
-> '-00:59:59.999999'

SUBTIME() a été ajoutée en MySQL 4.1.1.

- SYSDATE()

SYSDATE() est un synonyme de NOW().

- TIME(expr)

Extrait la partie horaire de l'expression expr, de type TIME ou DATETIME.

mysql> SELECT TIME('2003-12-31 01:02:03');
-> '01:02:03'
mysql> SELECT TIME('2003-12-31 01:02:03.000123');
-> '01:02:03.000123'

TIME() a été ajoutée en MySQL 4.1.1.

- TIMEDIFF(expr,expr2)

TIMEDIFF() retourne la durée entre l'heure de début expr et l'heure de fin expr2. expr et expr2 sont des expressions de type TIME ou DATETIME, et doivent être de même type.

mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01 00:00:00.000001');
-> '-00:00:00.000001'
mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001','1997-12-30 01:01:01.000002');
-> '46:58:57.999999'

TIMEDIFF() a été ajoutée en MySQL 4.1.1.

- TIMESTAMP(expr), TIMESTAMP(expr,expr2)

Avec un seul argument, retourne l'expression expr de type DATE ou DATETIME sous la forme d'une valeur DATETIME. Avec deux arguments, ajouter l'expression expr2 à l'expression expr et retourne le résultat au format DATETIME.

mysql> SELECT TIMESTAMP('2003-12-31');
-> '2003-12-31 00:00:00'
mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
-> '2004-01-01 00:00:00'

TIMESTAMP() a été ajoutée en MySQL 4.1.1.

- TIMESTAMPADD(interval,int_expr,datetime_expr)

Ajoute l'expression entière int_expr à l'expression datetime_expr au format DATE ou DATETIME. L'unité de int_expr est donnée avec l'argument interval, qui peut être l'une des valeurs suivantes : FRAC_SECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, ou YEAR.

La valeur interval peut être spécifiée, en utilisant un des mots-clés cités, ou avec le préfixe SQL_TSI_. Par exemple, DAY et SQL_TSI_DAY sont tous les deux valides.

mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');
-> '2003-01-02 00:01:00'
mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');
-> '2003-01-09'

TIMESTAMPADD() a été ajoutée en MySQL 5.0.0.

- TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)

Retourne la différence entière entre les expressions datetime_expr1 et datetime_expr2, de format DATE et DATETIME. L'unité du résultat est donnée par l'argument interval. Les valeurs légales de interval sont les mêmes que pour la fonction TIMESTAMPADD().

mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
-> 3
mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
-> -1

TIMESTAMPDIFF() a été ajoutée en MySQL 5.0.0.

- TIME_FORMAT(time,format)

Cette fonction est utilisée exactement comme la fonction DATE_FORMAT() ci-dessus, mais la chaîne format ne doit utiliser que des spécificateurs d'heures, qui gèrent les heures, minutes et secondes. Les autres spécificateurs génèreront la valeur NULL ou 0.

Si la valeur time contient une valeur d'heure qui est plus grande que 23, les formats %H et %k produiront une valeur qui est hors de l'intervalle 0..23. L'autre format d'heure produira une heure modulo 12 :

mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');
-> '100 100 04 04 4'

- TIME_TO_SEC(time)

Retourne l'argument time, converti en secondes :

mysql> SELECT TIME_TO_SEC('22:23:00');
-> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
-> 2378

- TO_DAYS(date)

Retourne le nombre de jours depuis la date 0 jusqu'à la date date :

mysql> SELECT TO_DAYS(950501);
-> 728779
mysql> SELECT TO_DAYS('1997-10-07');
-> 729669

TO_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du calendrier grégorien (1582), car elle ne prend pas en compte les jours perdus lors du changement de calendrier.

N'oubliez pas que MySQL convertit les années représentées sur deux chiffres en dates à quatre chiffres, en utilisant les règles de la section Section 11.3, « Les types date et heure ». Par exemple, '1997-10-07' et '97-10-07' sont identiques :

mysql> SELECT TO_DAYS('1997-10-07'), TO_DAYS('97-10-07');
-> 729669, 729669

Pour les dates antérieures à 1582, les résultats sont indéfinis.

- UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)

Lorsqu'elle est appelée sans argument, cette fonction retourne un timestamp Unix (nombre de secondes depuis '1970-01-01 00:00:00' GMT). Si UNIX_TIMESTAMP() est appelée avec un argument date, elle retourne le timestamp correspondant à cette date. date peut être une chaîne de type DATE, DATETIME, TIMESTAMP, ou un nombre au format YYMMDD ou YYYYMMDD, en horaire local :

mysql> SELECT UNIX_TIMESTAMP();
-> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
-> 875996580

Lorsque UNIX_TIMESTAMP est utilisé sur une colonne de type TIMESTAMP, la fonction reçoit directement la valeur, sans conversion explicite. Si vous donnez à UNIX_TIMESTAMP() une date hors de son intervalle de validité, elle retourne 0.

Si vous voulez soustraire une colonne de type UNIX_TIMESTAMP(), vous devez sûrement vouloir un résultat de type entier signé. Voir Section 12.7, « Fonctions de transtypage ».

- UTC_DATE, UTC_DATE()

Retourne la date UTC courante au format 'YYYY-MM-DD' ou YYYYMMDD suivant le contexte numérique ou chaîne :

mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
-> '2003-08-14', 20030814

UTC_DATE() est disponible depuis MySQL 4.1.1.

- UTC_TIME, UTC_TIME()

Retourne l'heure UTC courante au format 'HH:MM:SS' or HHMMSS suivant le contexte numérique ou chaîne :

mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
-> '18:07:53', 180753

UTC_TIME() est disponible depuis MySQL 4.1.1.

- UTC_TIMESTAMP, UTC_TIMESTAMP()

Retourne l'heure et la date UTC courante au format 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS suivant le contexte numérique ou chaîne :

mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;
-> '2003-08-14 18:08:04', 20030814180804

UTC_TIMESTAMP() est disponible depuis MySQL 4.1.1.

- WEEK(date [,mode])

Avec un seul argument, retourne le numéro de la semaine dans l'année de la date date, dans un intervalle de 0 à 53 (oui, il peut y avoir un début de semaine numéro 53), en considérant que dimanche est le premier jour de la semaine. Avec deux arguments, la fonction WEEK() vous permet de spécifier si les semaines commencent le dimanche ou le lundi et la valeur retournée sera dans l'intervalle 0-53 ou bien 1-52. Lorsque l'argument mode est omis, la valeur de la variable default_week_format (ou 0 en MySQL 4.0 ou plus ancien) est utilisé. Voir Section 13.5.2.8, « Syntaxe de SET ».

Voici un tableau explicatif sur le fonctionnement du second argument :

Valeur

Signification

0

La semaine commence le Sunday ; l'intervalle de valeur de retour va de 0 à 12 ; la semaine 1 est la première semaine de l'année

1

La semaine commence le Monday ; l'intervalle de valeur de retour va de 0 à 12 ; la semaine 1 est la première semaine de l'année qui a plus de trois jours

2

La semaine commence le Sunday ; l'intervalle de valeur de retour va de 1 à 12 ; la semaine 1 est la première semaine de l'année

3

La semaine commence le Monday ; l'intervalle de valeur de retour va de 1 à 12 ; la semaine 1 est la première semaine de l'année qui a plus de trois jours

4

La semaine commence le Sunday ; l'intervalle de valeur de retour va de 0 à 12 ; la semaine 1 est la première semaine de l'année qui a plus de trois jours

5

La semaine commence le Monday ; l'intervalle de valeur de retour va de 0 à 12 ; la semaine 1 est la première semaine de l'année

6

La semaine commence le Sunday ; l'intervalle de valeur de retour va de 1 à 12 ; la semaine 1 est la première semaine de l'année qui a plus de trois jours

7

La semaine commence le Monday ; l'intervalle de valeur de retour va de 1 à 12 ; la semaine 1 est la première semaine de l'année

Le mode 3 est disponible depuis MySQL 4.0.5. Le mode 4 est disponible depuis MySQL 4.0.17.

mysql> SELECT WEEK('1998-02-20');
-> 7
mysql> SELECT WEEK('1998-02-20',0);
-> 7
mysql> SELECT WEEK('1998-02-20',1);
-> 8
mysql> SELECT WEEK('1998-12-31',1);
-> 53

Note : en version 4.0, WEEK(date,0) a été modifiée pour correspondre au système calendaire des USA. Avant cela, WEEK() était calculé incorrectement, pour des dates américaines : en effet, WEEK(date) et WEEK(date,0) étaient incorrects.

Si vous préférez que le résultat soit calculé en fonction de l'année qui contient le premier jour de la semaine de la date utilisée en argument, vous devriez utiliser les valeurs 2, 3, 6, or 7 de l'argument mode.

mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
-> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
-> 52

Alternativement, utilisez la fonction YEARWEEK() :

mysql> SELECT YEARWEEK('2000-01-01');
-> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
-> '52'

- WEEKDAY(date)

Retourne l'index du jour de la semaine, avec la conversion suivante : date (0 = lundi, 1 = mardi, ... 6 = dimanche).

mysql> SELECT WEEKDAY('1997-10-04 22:23:00');
-> 5
mysql> SELECT WEEKDAY('1997-11-05');
-> 2

- WEEKOFYEAR(date)

Retourne le numéro de semaine dans l'année, sous forme d'un nombre compris entre 1 et 53.

mysql> SELECT WEEKOFYEAR('1998-02-20');
-> 8

WEEKOFYEAR() est disponible depuis MySQL 4.1.1.

- YEAR(date)

Retourne l'année de la date date, dans un intervalle de 1000 à 9999 :

mysql> SELECT YEAR('98-02-03');
-> 1998

mysql> SELECT YEAR('98-02-03');
-> 1998

- YEARWEEK(date), YEARWEEK(date,start)

Retourne l'année et la semaine d'une date. L'argument start fonctionne exactement comme l'argument start de la fonction WEEK(). Notez que l'année dans le résultat peut être différente de l'année passée en argument, pour la première et la dernière semaine de l'année.

mysql> SELECT YEARWEEK('1987-01-01');
-> 198653

Notez que le numéro de semaine est différent de celui que la fonction WEEK() retourne (0) pour les arguments optionnels 0 ou 1, comme WEEK() puis retourne la semaine dans le contexte de l'année.

12-6 - Recherche en texte intégral (Full-text) dans MySQL

- MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])

Depuis la version 3.23.23, MySQL propose l'indexation et la recherche sur l'ensemble d'un champ TEXT (full-text). Les index en texte intégral de MySQL sont des index de type FULLTEXT. Les index FULLTEXT sont utilisés avec les tables MyISAM et peuvent être créés depuis des colonnes de types CHAR, VARCHAR, ou TEXT au moment de CREATE TABLE ou plus tard avec ALTER TABLE ou CREATE INDEX. Pour les enregistrements les plus grands, il sera plus rapide de charger les données dans une table qui n'a pas d'index FULLTEXT, et ensuite de créer l'index avec ALTER TABLE (ou CREATE INDEX). L'enregistrement de données dans une table qui a déjà des index FULLTEXT sera plus lent.

Les contraintes sur la recherche en texte intégral sont listées dans la section Section 12.6.3, « Restrictions avec la recherche en texte intégral ».

La recherche en texte intégral est effectuée par la fonction MATCH().

mysql> CREATE TABLE articles (
->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
->   title VARCHAR(200),
->   body TEXT,
->   FULLTEXT (title,body)
-> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
-> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
-> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
-> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
-> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
-> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles
->          WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

La fonction MATCH() effectue la recherche d'une chaîne de caractères dans une liste de textes (et dans un groupe d'une ou plusieurs colonnes utilisées pour l'index FULLTEXT). La chaîne recherchée est donnée en argument à AGAINST(). La recherche est sans distinguer les majuscules des minuscules. Pour chaque ligne de la table, MATCH() retourne une valeur de pertinence, qui est une mesure de la ressemblance entre le chaîne recherchée et le texte de la ligne dans la colonne donnée dans la liste de MATCH().

Quand MATCH() est utilisé comme condition de WHERE (voir l'exemple suivant) les lignes retournées sont automatiquement organisées avec la pertinence la plus élevé en premier. La pertinence est un nombre décimal positif. La pertinence de zéro signifie qu'il n'y a pas de similarité. La pertinence est calculée en fonction du nombre de mots dans la ligne, du nombre de mots uniques dans cette ligne, du nombre total de mots dans la liste, et du nombre de documents (lignes) qui contiennent un mot en particulier.

Pour les recherches en texte intégral et en langage naturel, la technique impose que les colonnes utilisées avec la fonction MATCH() doivent être les mêmes que les colonnes utilisées dans un index FULLTEXT. Dans la requête précédente, notez que les colonnes nommées dans la fonction MATCH() (title et body) sont les mêmes que celles de la définition de la table article et son index FULLTEXT. Si vous voulez rechercher le titre title ou le corps body séparément, vous devrez créer un index FULLTEXT pour chaque colonne.

Il est aussi possible d'exécuter une recherche en mode booléen. Ceci est décrit dans les sections Section 12.6.1, « Booléens de recherches en texte intégral » et Section 12.6.2, « Recherche en texte intégral avec extension de requête ».

L'exemple précédent est une illustration élémentaire qui montre comment on utilise la fonction MATCH(). Les lignes sont retournées par ordre décroissant de pertinence. L'exemple suivant montre comment récupérer la valeur de pertinence explicitement. Comme il n'y a pas de condition WHERE ni de condition ORDER BY les lignes retournées ne sont pas ordonnées.

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
|  1 |                        0.64840710366884 |
|  2 |                                       0 |
|  3 |                        0.66266459031789 |
|  4 |                                       0 |
|  5 |                                       0 |
|  6 |                                       0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

L'exemple suivant est plus complexe. La requête retourne la valeur de pertinence et organise les lignes par ordre décroissant de pertinence. Pour obtenir ce résultat, il faut spécifier MATCH() deux fois. Cela ne cause pas de surcharge, car l'optimiseur de MySQL remarquera que les deux appels à MATCH() sont identiques et appellent le code de recherche sur texte intégral une seule fois.

mysql> SELECT id, body, MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root') AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body                                | score           |
+----+-------------------------------------+-----------------+
|  4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
|  6 | When configured properly, MySQL ... |   1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

MySQL utilise un filtre très simple pour séparer le texte en mots. Un « mot » est n'importe quelle chaîne de caractères constituée de lettres, chiffres, ''' et '_'. Tout « mot » présent dans la liste des mots à ignorés ou qui est trop court (3 caractères ou moins) est ignoré.

- Un mot trop court est ignoré. La taille minimale pour un mot dans les recherches est de 4 lettres.

- Les mots de la liste sont ignorés. Un mot banni est par exemple « the » ou « some », « un » ou « les » en français, qui sont considérés comme trop communs pour avoir une valeur intrinsèque. Il y a une liste de mots bannis en anglais par défaut.

La taille minimale des mots et la liste de mots à ignorer sont décrites dans la section Section 12.6.4, « Paramétrage précis de la recherche en texte intégral de MySQL ».

Tous les mots corrects de la liste et de la requête sont pondérés en fonction de leur importance dans la liste ou la requête. De cette façon, un mot présent dans de nombreuses lignes aura un poids faible (et peut être même un poids nul), car il a peu d'importance dans cette requête particulière. Au contraire, si le mot est rare, il recevra un poids fort. Le poids des mots sont alors rassemblés pour calculer la pertinence de la ligne.

Une telle technique fonctionne plus efficacement sur de grands volumes de données (en fait, elle est optimisée pour cela). Avec les toutes petites tables, la distribution des mots ne reflète par correctement leur valeur sémantique et ce modèle peut parfois produire des résultats étranges.

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

La recherche du mot MySQL ne donne aucun résultat dans l'exemple précédent, car il est présent dans plus de la moitié des lignes. Ainsi, il est considéré comme un mot à ignorer (un mot avec une valeur sémantique nulle). C'est le comportement le plus optimal : un langage de requêtes ne doit pas retourner chaque ligne d'une table de 1 Go.

Un mot qui est trouvé dans la moitié des enregistrements d'une table n'est pas efficace pour trouver les documents appropriés. En fait, il trouvera sûrement beaucoup de documents inappropriés à la recherche. On sait tous que cela arrive souvent lorsqu'on recherche quelque chose sur Internet en utilisant un moteur de recherche. C'est en suivant ce raisonnement que ces lignes se sont vu attribuer une valeur sémantique très basse dans ce cas particulier.

Le seuil de 50 % a un impact significatif lorsque vous commencez à comprendre comment fonctionne l'index : si vous créez une table et insérez une ou deux lignes, chaque mot apparaîtra dans 50 % des lignes. Résultat, la recherche ne trouvera rien. Assurez-vous d'insérer au moins trois lignes, et même plus.

12-6-1 - Booléens de recherches en texte intégral

Depuis la version 4.0.1, MySQL peut aussi effectuer des recherches en texte intégral avec l'option IN BOOLEAN MODE.

mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+
| id | title                 | body                                |
+----+-----------------------+-------------------------------------+
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Well | After you went through a ...        |
|  3 | Optimizing MySQL      | In this tutorial we will show ...   |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security        | When configured properly, MySQL ... |
+----+-----------------------+-------------------------------------+

Cette requête recherche toutes les lignes qui contiennent le mot « MySQL », mais qui ne contient pas le mot « YourSQL ».

Les recherches booléennes en texte intégral ont les caractéristiques suivantes.

- Elle n'utilise pas le seuil de 50 %.

- Elles ne trient pas automatiquement les lignes par ordre de pertinence décroissante. Vous pouvez le voir dans l'exemple précédent : la ligne ayant la plus grande pertinence est celle qui contient « MySQL » deux fois, mais elle est listée en dernier.

- Elles peuvent fonctionner dans l'index FULLTEXT, même si c'est particulièrement lent.

La recherche booléenne en texte intégral supporte les opérateurs suivants.

- +

Un signe + initial indique que le mot doit être présent dans la ligne retournée.

- -

Un signe - initial indique que le mot ne doit pas être présent dans la ligne retournée.

- (pas d'opérateur)

Par défaut, lorsque ni +, ni - n'est spécifié), le mot est optionnel, mais les lignes qui le contiennent seront mieux cotées. Cela imite le comportement de MATCH() ... AGAINST() sans l'option IN BOOLEAN MODE.

- > <

Ces deux opérateurs servent à changer la contribution d'un mot à la pertinence. L'opérateur > accroît la contribution, et l'opérateur < la décroît. Voir un exemple ci-dessous.

- ( )

Les parenthèses servent à grouper des mots en sous-expressions. Les groupes de parenthèses peuvent être imbriqués.

- ~

Un signe tilde initial marque la négation, et fait que la contribution du mot à la pertinence sera négative. Cet opérateur est pratique pour marquer les mots ambigus. Une ligne qui contient un tel mot sera classée bien plus bas, mais elle ne sera pas exclue, comme ce serait le cas avec -.

- *

Un astérisque est l'opérateur de troncature. Contrairement aux autres opérateurs, il doit être en suffixe et non pas en préfixe.

- "

Une phrase entre guillemets doubles ('"') est recherchée littéralement, telle qu'elle a été saisie.

Les exemples ci-dessous illustrent quelques résultats de chaînes de recherche avec les opérateurs.

- 'pomme banane'

Recherche les lignes qui contiennent au moins un de ces mots.

- '+pomme +jus'

Recherche les lignes qui contiennent ces deux mots.

- '+pomme macintosh'

Recherche les lignes qui contiennent le mot « pomme », mais classe plus haut les lignes qui contiennent aussi « macintosh ».

- '+pomme -macintosh'

Recherche les lignes qui contiennent « pomme » et pas « macintosh ».

- '+pomme +(>tatin <strudel)'

Recherche les lignes qui contiennent les mots « pomme » et « tatin », ou « pomme » et « strudel » (dans n'importe quel ordre), mais classe « pomme tatin » plus haut que « pomme strudel ».

- 'pomm*'

Trouve les lignes qui contiennent des mots tels que « pomme », « pommes », « pommier », ou « pommeau ».

- '"deux mots"'

Recherche les lignes qui contiennent exactement la phrase « deux mots » (par exemple, les lignes qui contiennent « deux mots d'amour » mais pas « le mot deux »). Notez que les caractères '"' qui entourent la phrase délimitent la phrase. Ils ne délimitent pas la chaîne.

12-6-2 - Recherche en texte intégral avec extension de requête

Depuis la version 4.1.1, la recherche en texte intégral supporte l'extension de requête (en particulier la variable dite « extension aveugle »). C'est généralement utile lorsque la phrase de recherche est trop courte, ce qui signifie que l'utilisateur sous-entend des informations. Par exemple, un utilisateur qui recherche « database » peut en fait rechercher « MySQL8 », « Oracle », « DB2 » ou encore « RDBMS » : ce sont des solutions qui doivent être liées à « databases » et être retournée. C'est de l'information implicite.

L'extension de requête aveugle (dite aussi, pertinence automatique), fonctionne en faisant la même recherche deux fois : la seconde fois, la recherche est complétée avec les mots les plus fréquents des premiers résultats. Par conséquent, si un de ces documents contenait « databases » et « MySQL », la seconde recherche va rechercher les documents qui contiennent « MySQL » mais pas « database ». L'exemple suivant illustre la différence :

mysql> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM articles
-> WHERE MATCH (title,body)
-> AGAINST ('database' WITH QUERY EXPANSION);
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  3 | Optimizing MySQL  | In this tutorial we will show ...        |
+----+-------------------+------------------------------------------+
3 rows in set (0.00 sec)

Un autre exemple est la recherche de livres de Georges Simenon, de la série Maigret, alors que l'utilisateur ne sait pas trop comment écrire « Maigret ». Alors que la recherche de « Megre and the reluctant witnesses » ne conduit qu'à « Maigret and the Reluctant Witnesses » sans l'extension aveugle, la version avec extension aveugle va sortir la collection complète des livres avec le mot « Maigret ».

Note : comme l'extension aveugle augmente le niveau de bruit, en retournant des documents sans rapport, elle n'est utile que si la phrase de recherche est courte.

12-6-3 - Restrictions avec la recherche en texte intégral

- La recherche en texte intégral n'est supportée que par les tables MyISAM.

- Depuis MySQL 4.1.1, les recherches en texte plein peuvent être utilisées avec la plupart des jeux de caractères. L'exception est pour Unicode, le jeu de caractères utf8 peut être utilisé, mais pas ucs2.

- Depuis MySQL 4.1, l'utilisation de jeux de caractères multiples dans une table est supportée. Cependant, toutes les colonnes dans un index FULLTEXT doivent avoir le même jeu de caractères et collation.

- Les arguments de MATCH() doivent correspondre exactement à la liste de colonnes de certaines définitions d'index FULLTEXT pour la table, sauf si MATCH() est utilisé dans un contexte BOOLEAN.

- L'argument de AGAINST() doit être une chaîne constante.

12-6-4 - Paramétrage précis de la recherche en texte intégral de MySQL

La recherche sur texte entier n'a malheureusement pas encore beaucoup de paramètres modifiables par l'utilisateur, même si l'ajout de certains apparaît très haut dans la liste de tâches. Si vous utilisez MySQL depuis les sources (Voir Section 2.4, « Installation de MySQL avec une distribution source ».), vous pouvez mieux contrôler le fonctionnement de la recherche sur texte entier.

La recherche sur texte entier a été paramétrée pour une efficacité de recherche maximale. La modification du comportement par défaut ne fera généralement que diminuer la qualité des résultats des recherches. Il ne faut pas modifier les sources de MySQL sans savoir précisément ce qu'on fait.

- La taille minimale des mots à indexer est définie dans la variable ft_min_word_len de MySQL. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ». Vous pouvez modifier cette valeur pour celle que vous préférez, puis reconstruire les index FULLTEXT. (Cette variable n'existe que pour la version 4.0 de MySQL) La valeur par défaut de cette option est de 4 caractères. Modifiez-la, puis recompilez les index FULLTEXT. Par exemple, si vous souhaitez pouvoir rechercher des mots de 3 caractères, vous pouvez donner à cette variable la valeur suivante dans le fichier d'options :

[mysqld]
ft_min_word_len=3

Puis, relancez le serveur et recompilez vos index FULLTEXT.

- La liste des mots rejetés est définie dans la variable ft_stopword_file. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ». Modifiez-la selon vos goûts, reconstruisez vos index FULLTEXT.

- Le taux de 50 % est déterminé par la méthode de pondération choisie. Pour le désactiver, il faut changer la ligne suivante dans myisam/ftdefs.h :

#define GWS_IN_USE GWS_PROB

Par la ligne :

#define GWS_IN_USE GWS_FREQ

Puis recompiler MySQL. Il n'est pas nécessaire de reconstruire les index dans ce cas. Note : en faisant ces modifications, vous diminuez énormément les capacités de MySQL à fournir des valeurs pertinentes pour la fonction MATCH(). Si vous avez réellement besoin de faire des recherches avec ces mots courants, il est préférable de rechercher EN MODE BOOLEEN, lequel ne respecte pas le taux de 50 %.

- Pour changer les opérateurs utilisés pour les recherches booléennes, modifiez la variable système ft_boolean_syntax (disponible depuis MySQL 4.0.1). La variable peut aussi être modifiée durant le fonctionnement du serveur, mais vous devez avoir les droits de SUPER. La recompilation des index n'est pas possible. Section 5.2.3, « Variables serveur système » décrit les règles de définition de cette variable.

Si vous modifiez des variables d'indexation de textes qui affectent les index (les variables (ft_min_word_len, ft_max_word_len et ft_stopword_file), vous devez reconstruire les index FULLTEXT après avoir fait les modifications et relancé le serveur. Pour reconstruire les index, il est suffisant de faire une réparation QUICK :

mysql> REPAIR TABLE tbl_name QUICK;

Si vous utilisez spécifiquement les fonctionnalités IN BOOLEAN MODE, si vous mettez à jour depuis MySQL 3.23 vers 4.0 ou plus récent, il est nécessaire de remplacer aussi les entêtes des index. Pour cela, utilisez l'opération de réparation USE_FRM :

mysql> REPAIR TABLE nom_de_table USE_FRM;

C'est nécessaire, car les recherches booléennes en texte plein requièrent une option dans l'entête qui n'était pas présente en MySQL en version 3.23, et elle n'est pas ajoutée si vous faites une réparation de type QUICK. Si vous tentez une recherche booléenne sans reconstruire l'index comme ceci, la recherche retournera des résultats incorrects.

Notez que si vous utilisez myisamchk pour effectuer une opération qui modifie les index de la table, pour une réparation ou une analyse, les index FULLTEXT sont reconstruits en utilisant la configuration par défaut des index en texte plein, à moins que vous ne les spécifiiez autrement. Cela peut conduire à des requêtes qui échouent.

Le problème survient, car les valeurs de cette configuration ne sont connues que du serveur. Elles ne sont pas stockées dans les fichiers d'index MyISAM. Pour éviter ce problème si vous avez modifié la taille minimale ou maximale des mots, ou encore le fichier de mots interdits, spécifiez les options ft_min_word_len, ft_max_word_len et ft_stopword_file à myisamchk, en donnant les mêmes valeurs que pour mysqld. Par exemple, si vous avez donné une taille minimale de mot de 3, vous pouvez réparer votre table avec myisamchk :

shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI

Pour vous assurer que le serveur et myisamchk utilisent les mêmes valeurs pour les index, vous pouvez les placer dans les sections [mysqld] et [myisamchk] du fichier d'options :

[mysqld]
ft_min_word_len=3

[myisamchk]
ft_min_word_len=3

Une autre solution à l'utilisation de myisamchk est l'utilisation de REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE ou ALTER TABLE. Ces commandes sont effectuées par le serveur, qui connaît la configuration des index en texte plein.

12-6-5 - À faire dans la recherche Full-text

- Rendre toutes les opérations avec l'index FULLTEXT plus rapides.

- Opérateurs de proximité.

- Support de listes de mots à toujours indexer (« always-index words »). Ceux-ci pourraient être n'importe quelle chaîne de caractères que l'utilisateur voudrait traiter comme des mots : par exemple « C++ », « AS/400 », « TCP/IP », etc.

- Support de la recherche full-text sur les tables MERGE.

- Support des jeux de caractères multioctets.

- Rendre la liste des mots ignorés dépendante de la langue des données.

- Stemming (dépendante de la langue des données, bien sûr).

- Préprocesseur générique pour les UDF fournies par l'utilisateur.

- Rendre le modèle plus flexible (en ajoutant des valeurs paramétrables pour FULLTEXT dans CREATE/ALTER TABLE).

12-7 - Fonctions de transtypage

- CAST(expr AS type), CONVERT(expr,type), CONVERT(expr USING transcoding_name)

Les fonctions CAST() et CONVERT() peuvent être utilisées pour convertir une donnée d'un type en un autre. Leurs syntaxes sont les suivantes.

La valeur de type peut être l'une des suivantes :

- BINARY

- CHAR

- DATE

- DATETIME

- SIGNED {INTEGER}

- TIME

- UNSIGNED {INTEGER}

CAST() et CONVERT() sont disponibles depuis MySQL 4.0.2. La conversion de type CHAR est disponible depuis la version 4.0.6. La forme USING de CONVERT() est disponible depuis la version 4.1.0.

CAST() et CONVERT(... USING ...) sont des syntaxes SQL-99. La forme sans USING de CONVERT() est une syntaxe ODBC.

CONVERT() avec la clause USING sert à convertir des données entre différents jeux de caractères. Avec MySQL, les noms d'encodage sont les mêmes que les noms des jeux de caractères. Par exemple, cette commande convertit la chaîne 'abc' depuis le jeu de caractères par défaut du serveur vers utf8 :

SELECT CONVERT('abc' USING utf8);

La fonction de transtypage est très pratique lorsque vous voulez créer une colonne avec un type spécifique dans une requête CREATE ... SELECT :

CREATE TABLE nouvelle_table SELECT CAST('2000-01-01' AS DATE);

Les fonctions peuvent aussi être utilisées pour trier des colonnes de type ENUM en ordre lexical. Normalement, le tri sur les colonnes ENUM est fait avec les valeurs numériques internes. Pour trier les valeurs avec l'ordre lexical CHAR :

SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);

CAST(string AS BINARY) est l'équivalent de BINARY string. CAST(expr AS CHAR) traite l'expression comme une chaîne, avec le jeu de caractères par défaut.

Note : en MySQL 4.0 le CAST() en DATE, DATETIME ou TIME ne fait que marquer la colonne comme étant du type indiqué, mais n'en change pas la valeur.

En MySQL 4.1.0, la valeur est convertie dans le type de colonne demandé, puis il est envoyé à l'utilisateur. Cette fonctionnalité est une nouveauté du protocole 4.1, qui envoie les données au client :

mysql> SELECT CAST(NOW() AS DATE);
-> 2003-05-26

Dans les prochaines versions de MySQL (probablement 4.1.2 ou 5.0) nous allons corriger CAST pour qu'elle modifie le résultat si vous l'utilisez comme une partie d'une expression plus complexe, comme CONCAT("Date: ",CAST(NOW() AS DATE)).

N'utilisez pas CAST() pour extraire des données dans différents formats, mais utilisez plutôt LEFT ou EXTRACT(). Voir Section 12.5, « Fonctions de dates et d'heures ».

Pour transformer une chaîne de caractères en une valeur numérique, vous ne devez rien faire de particulier, juste utiliser la valeur de la chaîne en lieu et place de la valeur numérique :

mysql> SELECT 1+'1';
-> 2

Si vous utilisez un nombre dans un contexte de chaîne, le nombre sera automatiquement converti en une chaîne binaire.

mysql> SELECT concat("salut toi ",2);
->  "salut toi 2"

Si vous utilisez un nombre dans un contexte de chaîne, le nombre sera automatiquement converti en chaîne binaire (BINARY).

mysql> SELECT CONCAT("Salut vous ",2);
->  "Salut vous 2"

MySQL supporte l'arithmétique avec les valeurs 64 bits signées et non signées. Si vous utilisez une opération numérique (comme le signe +) et qu'un des opérandes est de type unsigned integer, alors, le résultat sera une valeur non signée. Vous pouvez corriger cela en utilisant les opérateurs de transtypage SIGNED et UNSIGNED, qui transformeront l'opération respectivement en un entier signé sur 64 bits et un entier non signé sur 64 bits.

mysql> SELECT CAST(1-2 AS UNSIGNED)
-> 18446744073709551615
mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
-> -1

Notez que si l'une ou l'autre opération est une valeur à virgule flottante (dans ce contexte, DECIMAL() est considéré comme une valeur à virgule flottante) le résultat devrait être une valeur à virgule flottante et ne sera pas affecté par la règle ci-dessus.

mysql> SELECT CAST(1 AS UNSIGNED) -2.0
-> -1.0

Si vous utilisez une chaîne dans une opération arithmétique, elle sera convertie en un nombre à virgule flottante.

Les fonctions CAST() et CONVERT() ont été ajoutées dans la version 4.0.2 de MySQL.

L'affichage des valeurs non signées a été modifié dans la version 4.0 de MySQL pour pouvoir supporter correctement les valeurs de type BIGINT. Si vous voulez utiliser du code fonctionnant dans la version 4.0 et la version 3.23 de MySQL (dans ce cas, vous ne pouvez probablement pas utiliser les fonctions de transtypage), vous pouvez utiliser l'astuce suivante pour avoir un résultat signé lorsque vous soustrayez deux colonnes d'entiers non signés :

SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);

L'idée est que les colonnes sont converties en un point mobile avant de faire la soustraction.

Si vous rencontrez un problème avec les colonnes UNSIGNED dans vos anciennes applications MySQL lorsque vous effectuez le port sous la version 4.0 de MySQL, vous pouvez utiliser l'option --sql-mode=NO_UNSIGNED_SUBTRACTION lorsque vous lancez mysqld. Notez cependant qu'aussi longtemps que vous employez ceci, vous ne serez pas capable d'utiliser efficacement les colonnes de type UNSIGNED BIGINT.

12-8 - Autres fonctions

12-8-1 - Fonctions sur les bits

MySQL utilise l'arithmétique des BIGINT (64 bits) pour les opérations sur les bits. Ces opérateurs travaillent donc sur 64 bits.

- |

OU bit à bit (OR)

mysql> SELECT 29 | 15;
-> 31

Le résultat est un entier de 64 bits non signé.

- &

ET bit à bit (AND)

mysql> SELECT 29 & 15;
-> 13

Le résultat est un entier de 64 bits non signé.

- ^

XOR bit à bit

mysql> SELECT 1 ^ 1;
-> 0
mysql> SELECT 1 ^ 0;
-> 1
mysql> SELECT 11 ^ 3;
-> 8

Le résultat est un entier de 64 bits non signé.

- <<

Décale les bits de l'entier (BIGINT) sur la gauche :

mysql> SELECT 1 << 2;
-> 4

Le résultat est un entier de 64 bits non signé.

- >>

Décale les bits de l'entier (BIGINT) sur la droite :

mysql> SELECT 4 >> 2;
-> 1

Le résultat est un entier de 64 bits non signé.

- ~

Inverse tous les bits :

mysql> SELECT 5 & ~1;
-> 4

Le résultat est un entier de 64 bits non signé.

- BIT_COUNT(N)

Retourne le nombre de bits non nuls de l'argument N :

mysql> SELECT BIT_COUNT(29);
-> 4

12-8-2 - Fonctions de chiffrements

Les fonctions de cette section chiffrent et déchiffrent des valeurs. Si vous voulez stocker le résultat d'un chiffrement qui peut contenir des valeurs arbitraires, vous devez utiliser une colonne BLOB plutôt que CHAR ou VARCHAR, afin d'éviter les problèmes potentiels de suppression d'espaces terminaux qui corrompraient les valeurs.

- AES_ENCRYPT(str,key_str), AES_DECRYPT(crypt_str,key_str)

Ces fonctions permettent le chiffrement/déchiffrement de données utilisant l'algorithme AES (Advanced Encryption Standard), anciennement connu sous le nom de Rijndael. Une clé de 128 bits est utilisée pour le chiffrement, mais vous pouvez l'étendre à 256 bits en modifiant les sources. Nous avons choisi 128 bits parce que c'est plus rapide et suffisamment sécurisé.

Les arguments peuvent être de n'importe quelle taille. Si l'un des arguments est NULL, le résultat de cette fonction sera NULL.

Vu que AES est un algorithme de niveau bloc, le capitonnage est utilisé pour chiffrer des chaînes de longueurs inégales et donc, la longueur de la chaîne résultante peut être calculée comme ceci : 16*(trunc(string_length/16)+1).

Si la fonction AES_DECRYPT() détecte des données invalides ou un capitonnage incorrect, elle retournera NULL. Il est également possible que la fonction AES_DECRYPT() retourne une valeur différente de NULL (valeur incohérente) si l'entrée de données ou la clé est invalide.

Vous pouvez utiliser les fonctions AES pour stocker des données sous une forme chiffrée en modifiant vos requêtes :

INSERT INTO t VALUES (1,AES_ENCRYPT("text","password"));

Vous pouvez obtenir encore plus de sécurité en évitant de transférer la clé pour chaque requête, en la stockant dans une variable sur le serveur au moment de la connexion :

SELECT @password:="my password";
INSERT INTO t VALUES (1,AES_ENCRYPT("text",@password));

Les fonctions AES_ENCRYPT() et AES_DECRYPT() ont été ajoutées dans la version 4.0.2 de MySQL et peuvent être considérées comme étant les fonctions de cryptographie les plus sûres disponibles actuellement dans MySQL.

- DECODE(crypt_str,pass_str)

Déchiffre la chaîne chiffrée crypt_str en utilisant la clé pass_str. crypt_str doit être une chaîne qui a été renvoyée par la fonction ENCODE().

- ENCODE(str,pass_str)

Chiffre la chaîne str en utilisant la clé pass_str. Pour déchiffrer le résultat, utilisez la fonction DECODE().

Le résultat est une chaîne binaire de la même longueur que string. Si vous voulez sauvegarder le résultat dans une colonne, utilisez une colonne de type BLOB.

- DES_DECRYPT(crypt_str[,key_str])

Déchiffre une chaîne chiffrée à l'aide de la fonction DES_ENCRYPT().

Notez que cette fonction fonctionne uniquement si vous avez configuré MySQL avec le support SSL. Voir Section 5.6.7, « Utilisation des connexions sécurisées ».

Si l'argument key_string n'est pas donné, la fonction DES_DECRYPT() examine le premier bit de la chaîne chiffrée pour déterminer le numéro de clé DES utilisé pour chiffrer la chaîne originale, alors la clé est lue dans le fichier des-key-file pour déchiffrer le message. Pour pouvoir utiliser cela, l'utilisateur doit avoir le privilège SUPER.

Si vous passez l'argument key_string à cette fonction, cette chaîne est utilisée comme clé pour déchiffrer le message.

Si la chaîne string_to_decrypt ne semble pas être une chaîne chiffrée, MySQL retournera la chaîne string_to_decrypt.

Si une erreur survient, cette fonction retourne NULL.

- DES_ENCRYPT(str[,(key_num|key_str)])

Chiffre la chaîne avec la clé donnée en utilisant l'algorithme DES.

Notez que cette fonction fonctionne uniquement si vous avez configuré MySQL avec le support SSL. Voir Section 5.6.7, « Utilisation des connexions sécurisées ».

La clé de hachage utilisée est choisie en suivant les recommandations suivantes :

Argument

Description

Un seul argument

La première clé de des-key-file est utilisée

Un numéro de clé

Le numéro de la clé donnée (0-9) de des-key-file est utilisé

Une chaîne

La chaîne donnée key_string doit être utilisée pour chiffrer string_to_encrypt

La chaîne retournée doit être une chaîne binaire où le premier caractère doit être CHAR(128 | key_number).

Le nombre 128 a été ajouté pour reconnaître facilement une clé de hachage. Si vous utilisez une chaîne comme clé, key_number doit être 127.

Si une erreur survient, la fonction retournera NULL.

La longueur de la chaîne de résultat doit être : new_length= org_length + (8-(org_length % 8))+1.

des-key-file a le format suivant :

key_number des_key_string
key_number des_key_string

Chaque key_number doit être un nombre dans l'intervalle 0 à 9. Les lignes dans le fichier peuvent être dans n'importe quel ordre. des_key_string est la chaîne qui permettra le chiffrage du message. Entre le nombre et la clé, il doit y avoir au moins un espace. La première clé est la clé par défaut qui sera utilisée si vous ne spécifiez pas d'autres clés en argument de la fonction DES_ENCRYPT().

Vous pouvez demander à MySQL de lire de nouvelles valeurs de clé dans le fichier de clés avec la commande FLUSH DES_KEY_FILE. Cela requiert le privilège Reload_priv.

Un des bénéfices d'avoir une liste de clés par défaut est que cela donne aux applications la possibilité de regarder l'existence de la valeur chiffrée de la colonne, sans pour autant donner la possibilité à l'utilisateur final de déchiffrer ces valeurs.

mysql> SELECT customer_address FROM customer_table WHERE
crypted_credit_card = DES_ENCRYPT("credit_card_number");

- ENCRYPT(str[,salt])

Chiffre la chaîne str en utilisant la fonction crypt(). L'argument salt doit être une chaîne de deux caractères. (À partir de la version 3.22.16, l'argument salt peut être plus long que deux caractères.) :

mysql> SELECT ENCRYPT("hello");
-> 'VxuFAJXVARROc'

Si la fonction crypt() n'est pas disponible sur votre système, la fonction ENCRYPT() retournera toujours NULL.

La fonction ENCRYPT() conserve uniquement les 8 premiers caractères de la chaîne str, au moins, sur certains système. Le comportement exact est directement déterminé par la fonction système crypt() sous-jacente.

- MD5(str)

Calcule la somme de vérification MD5 de la chaîne string. La valeur retournée est un entier hexadécimal de 32 caractères qui peut être utilisé, par exemple, comme clé de hachage :

mysql> SELECT MD5("testing");
-> 'ae2b1fca515949e5d54fb22b8ed95575'

C'est l'algorithme RSA (RSA Data Security, Inc. MD5 Message-Digest Algorithm).

- OLD_PASSWORD(str)

OLD_PASSWORD() est disponible depuis MySQL 4.1, lorsque l'implémentation de la fonction PASSWORD() a été modifiée pour améliorer la sécurité. OLD_PASSWORD() retourne la valeur pre-4.1 de PASSWORD(). Section 5.5.9, « Hashage de mots de passe en MySQL 4.1 ».

- PASSWORD(str)

Calcule un mot de passe chiffré à partir de la chaîne str. C'est cette fonction qui est utilisée pour chiffrer les mots de passe MySQL pour être stockés dans une colonne de type Password de la table user :

mysql> SELECT PASSWORD('badpwd');
-> '7f84554057dd964b'

Le chiffrage par PASSWORD() n'est pas réversible.

PASSWORD() n'est pas un chiffrage comparable à la fonction de chiffrage Unix. Voir ENCRYPT().

Note : la fonction PASSWORD() est utilisée durant l'identification au serveur MYSQL. Il est recommandé de ne pas l'utiliser pour vos applications. Utilisez plutôt MD5() ou SHA1(). Voyez aussi RFC-2195 pour plus d'informations sur comment gérer les mots de passe et l'identification de votre système.

- SHA1(str), SHA(str)

Calcule la somme de vérification SHA1 160 bits de la chaîne string, comme décrit dans la RFC 3174 (Secure Hash Algorithm). La valeur retournée est un entier hexadécimal de 40 caractères, ou bien NULL dans le cas où l'argument vaut NULL. Une des possibilités d'utilisation de cette fonction est le hachage de clé. Vous pouvez aussi l'utiliser comme fonction de cryptographie sûre pour stocker les mots de passe.

mysql> SELECT SHA1("abc");
-> 'a9993e364706816aba3e25717850c26c9cd0d89d'

La fonction SHA1() a été ajoutée dans la version 4.0.2 de MySQL et peut être considérée comme une méthode de cryptographie plus sûre que la fonction MD5(). La fonction SHA() est un alias de la fonction SHA1().

12-8-3 - Fonctions d'informations

- BENCHMARK(count,expr)

La fonction BENCHMARK() exécute l'expression expr de manière répétée count fois. Elle permet de tester la vélocité de MySQL lors du traitement d'une requête. Le résultat est toujours 0. L'objectif de cette fonction ne se voit que du côté client, qui permet à ce dernier d'afficher la durée d'exécution de la requête :

mysql> SELECT BENCHMARK(1000000,ENCODE("bonjour","au revoir"));
+--------------------------------------------------+
| BENCHMARK(1000000,ENCODE("bonjour","au revoir")) |
+--------------------------------------------------+
|                                                0 |
+--------------------------------------------------+
1 row in set (4.74 sec)

Le temps affiché est le temps côté client, et non pas les ressources processeur consommées. Il est conseillé d'utiliser BENCHMARK() plusieurs fois de suite pour interpréter un résultat, en dehors de charges ponctuelles sur le serveur.

- CHARSET(str)

Retourne le jeu de caractères de la chaîne argument.

mysql> SELECT CHARSET('abc');
-> 'latin1'
mysql> SELECT CHARSET(CONVERT('abc' USING utf8));
-> 'utf8'
mysql> SELECT CHARSET(USER());
-> 'utf8'

CHARSET() a été ajouté en MySQL version 4.1.0.

- COERCIBILITY(str)

Retourne la coercibilité de la collation de la chaîne argument.

mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);
-> 0
mysql> SELECT COERCIBILITY('abc');
-> 3
mysql> SELECT COERCIBILITY(USER());
-> 2

Les valeurs retournées possibles sont :

Coercibilité

Signification

0

Collation explicite

1

Pas de collation

2

Collation implicite

3

Coercible

Les valeurs les plus faibles ont la plus haute priorité.

COERCIBILITY() a été ajouté en MySQL version 4.1.1.

- COLLATION(str)

Retourne la collation du jeu de caractères de la chaîne argument.

mysql> SELECT COLLATION('abc');
-> 'latin1_swedish_ci'
mysql> SELECT COLLATION(_utf8'abc');
-> 'utf8_general_ci'

COLLATION() a été ajouté en MySQL version 4.1.0.

- CONNECTION_ID()

Retourne l'identifiant de connexion courant (thread_id). Chaque connexion a son propre identifiant unique.

mysql> SELECT CONNECTION_ID();
-> 23786

CONNECTION_ID() a été ajouté en MySQL version 3.23.14.

- CURRENT_USER()

Retourne le nom d'utilisateur et le nom d'hôte de la session courante. Cette valeur correspond au compte qui a été utilisé durant l'identification auprès du serveur. Cela peut être différent des valeurs de USER().

mysql> SELECT USER();
-> 'davida@localhost'
mysql> SELECT * FROM mysql.user;
ERROR 1044: Access denied for user: '@localhost' to
database 'mysql'
mysql> SELECT CURRENT_USER();
-> '@localhost'

Cet exemple montre que même si le client a indiqué le nom d'utilisateur davida (comme mentionné par la fonction USER()), le serveur a identifié le client comme un utilisateur anonyme (comme indiqué par la fonction CURRENT_USER()). Une situation qui arrive s'il n'y a aucun compte de listé dans les tables de droits pour davida.

CURRENT_USER() a été ajouté en MySQL version 4.0.6.

- DATABASE()

Retourne le nom de la base de données courante :

mysql> SELECT DATABASE();
-> 'test'

Si aucune base de données n'a été sélectionnée, DATABASE() retourne une chaîne vide. À partir de la version 4.1.1, elle retourne NULL.

- FOUND_ROWS()

Une commande SELECT peut inclure une clause LIMIT pour restreindre le nombre de lignes qui seront retournées par le client. Dans certains cas, il est mieux de savoir combien de lignes une commande aurait retournées, sans la clause LIMIT, mais sans lancer à nouveau le calcul. Pour cela, ajoutez l'option SQL_CALC_FOUND_ROWS dans la commande SELECT, puis appelez FOUND_ROWS() après :

mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
-> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();

Le second SELECT retourne un nombre indiquant combien de lignes le premier SELECT aurait retournées s'il n'avait pas été écrit avec une clause LIMIT.

Notez que si vous utilisez SELECT SQL_CALC_FOUND_ROWS ..., MySQL calcule toutes les lignes dans la liste des résultats. Ainsi, c'est plus rapide si vous n'utilisez pas de clause LIMIT et que la liste des résultats n'a pas besoin d'être envoyée au client. Si la commande SELECT précédente n'inclut pas l'option SQL_CALC_FOUND_ROWS, alors FOUND_ROWS() pourrait retourner une valeur différente suivant que LIMIT est utilisé ou pas.

SQL_CALC_FOUND_ROWS et FOUND_ROWS() peuvent être pratiques dans des situations où vous devez limiter le nombre de lignes que la requête retourne, mais que vous devez tout de même connaître le nombre de lignes total, sans exécuter une seconde requête. Un exemple classique est un script web qui présente des résultats de recherche. En utilisant FOUND_ROWS(), vous connaîtrez facilement le nombre de lignes de résultat.

L'utilisation de SQL_CALC_FOUND_ROWS et FOUND_ROWS() est plus complexe pour les requêtes UNION que pour les commandes SELECT simples, car LIMIT peut intervenir plusieurs fois dans une commande UNION. Elle sera appliquée à différentes commandes SELECT de la commande UNION, ou globalement à l'UNION.

Le but de SQL_CALC_FOUND_ROWS pour UNION est de retourner le nombre de lignes qui auraient été retournées sans la clause globale LIMIT. Les conditions d'utilisation de SQL_CALC_FOUND_ROWS avec UNION sont :

- Le mot-clé SQL_CALC_FOUND_ROWS doit apparaître dans le premier SELECT de l'UNION.

- La valeur de FOUND_ROWS() est exactement la même que si UNION ALL était utilisé. Si UNION sans ALL est utilisé, des réductions de doublons surviendront, et la valeur de FOUND_ROWS() sera approximative.

- Si aucune clause LIMIT n'est présente dans UNION, SQL_CALC_FOUND_ROWS est ignoré et retourne le nombre de lignes dans la table temporaire créée durant le traitement de l'UNION.

SQL_CALC_FOUND_ROWS et FOUND_ROWS() sont disponibles à partir de la version 4.0.0 de MySQL.

- LAST_INSERT_ID(), LAST_INSERT_ID(expr)

Retourne le dernier identifiant automatiquement généré par une colonne AUTO_INCREMENT.

mysql> SELECT LAST_INSERT_ID();
-> 195

Le dernier ID généré est conservé par le serveur pour chaque connexion. Un autre client ne la modifiera donc pas, même s'il génère une autre valeur AUTO_INCREMENT de son côté. Ce comportement permet de s'assurer que les actions des autres clients ne perturbent pas les actions du client en cours.

La valeur de LAST_INSERT_ID() ne sera pas modifiée non plus si vous modifiez directement la valeur d'une colonne AUTO_INCREMENT avec une valeur simple (c'est-à-dire, une valeur qui n'est ni NULL, ni 0).

Si vous insérez plusieurs lignes au même moment avec une requête INSERT, LAST_INSERT_ID() retourne la valeur de la première ligne insérée. La raison à cela est que cela rend possible la reproduction facilement la même requête INSERT sur d'autres serveurs.

Si vous utilisez une commande INSERT IGNORE et que la ligne est ignorée, le compteur AUTO_INCREMENT sera malgré tout incrémenté, et LAST_INSERT_ID() retournera une nouvelle valeur.

Si expr est donnée en argument à la fonction LAST_INSERT_ID(), alors la valeur de l'argument sera retournée par la fonction et sera enregistrée comme étant la prochaine valeur retournée par LAST_INSERT_ID(). Cela peut être utilisé pour simuler des séquences.

- Commencez par créer la table suivante :

mysql> CREATE TABLE sequence (id INT NOT NULL);
mysql> INSERT INTO sequence VALUES (0);

- Utilisez cette table pour générer des séquences de nombres comme ceci :

mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
mysql> SELECT LAST_INSERT_ID();

La commande UPDATE incrémente le compteur de séquence, et fait que le prochain appel à LAST_INSERT_ID() va retourner une valeur différente. La commande SELECT lit cette valeur. La fonction C mysql_insert_id() peut aussi être utilisée pour lire la valeur. Voir Section 24.2.3.33, « mysql_insert_id() ».

Vous pouvez générer des séquences sans appeler la fonction LAST_INSERT_ID(), mais l'utilité d'utiliser cette fonction cette fois-ci est que la valeur ID est gérée par le serveur comme étant la dernière valeur générée automatiquement. (Sécurité multiutilisateur.) Vous pouvez retrouver la nouvelle ID tout comme vous pouvez lire n'importe quelle valeur AUTO_INCREMENT dans MySQL. Par exemple, la fonction LAST_INSERT_ID() (sans argument) devrait retourner la nouvelle ID. La fonction C de l'API mysql_insert_id() peut être également utilisée pour trouver cette valeur.

Notez que la fonction mysql_insert_id() est incrémentée uniquement après des requêtes INSERT et UPDATE, donc, vous ne pouvez pas utiliser la fonction C de l'API pour trouver la valeur de LAST_INSERT_ID(expr) après avoir exécuté d'autres types de requêtes, comme SELECT ou bien SET.

- SESSION_USER()

SESSION_USER() est un synonyme de USER().

- SYSTEM_USER()

SYSTEM_USER() est un synonyme de USER().

- USER()

Retourne le nom d'utilisateur et le nom d'hôte courant MySQL :

mysql> SELECT USER();
-> 'davida@localhost'

La valeur indique le nom d'utilisateur qui a été spécifié lors de l'identification avec le serveur MySQL, et l'hôte client avec lequel il est connecté.

Avant la version 3.22.11, la fonction ne retournait pas le nom d'hôte. Vous pouvez extraire le nom d'utilisateur sans l'hôte avec la commande suivante :

mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
-> 'davida'

Depuis MySQL version 4.1, USER() retourne la valeur au format utf8. Assurez-vous que la chaîne '@' est bien interprétée dans ce jeu de caractères :

mysql> SELECT SUBSTRING_INDEX(USER(),_utf8'@',1);
-> 'davida'

- VERSION()

Retourne une chaîne indiquant la version courante du serveur MySQL :

mysql> SELECT VERSION();
-> '4.1.2-alpha-log'

Notez que si votre version se termine par -log, cela signifie que le système d'historique est actif.

12-8-4 - Fonctions diverses

- FORMAT(X,D)

Formate l'argument X en un format comme '#,###,###.##', arrondi à D décimales. Si D vaut 0, le résultat n'aura ni séparateur décimal ni partie décimale :

mysql> SELECT FORMAT(12332.123456, 4);
-> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
-> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
-> '12,332'

- GET_LOCK(str,timeout)

Tente de poser un verrou nommé str, avec un délai d'expiration (timeout) exprimé en secondes. Retourne 1 si le verrou a été posé avec succès, 0 s'il n'a pas pu être posé avant l'expiration du délai et NULL si une erreur est survenue (comme un manque de mémoire, ou la mort du thread lui-même, par mysqladmin kill). Un verrou sera levé lorsque vous exécuterez la commande RELEASE_LOCK(), GET_LOCK() ou si le thread se termine. Cette fonction peut être utilisée pour implémenter des verrous applicatifs ou pour simuler des verrous de lignes. Les requêtes concurrentes de même nom des autres clients seront bloquées ; les clients qui s'entendent sur un nom de verrou peuvent les utiliser pour effectuer des verrouillages coopératifs :

mysql> SELECT GET_LOCK("lock1",10);
-> 1
mysql> SELECT IS_FREE_LOCK("lock2");
-> 1
mysql> SELECT GET_LOCK("lock2",10);
-> 1
mysql> SELECT RELEASE_LOCK("lock2");
-> 1
mysql> SELECT RELEASE_LOCK("lock1");
-> NULL

Notez que le deuxième appel à RELEASE_LOCK() retourne NULL, car le verrou "lock1" a été automatiquement libéré par le deuxième appel à GET_LOCK().

- INET_ATON(expr)

Retourne un entier qui représente l'expression numérique de l'adresse réseau. Les adresses peuvent être des entiers de 4 ou 8 octets.

mysql> SELECT INET_ATON("209.207.224.40");
->  3520061480

Le nombre généré est toujours dans l'ordre des octets réseau, par exemple, le nombre précédent est calculé comme ceci : 209*256^3 + 207*256^2 + 224*256 +40.

Depuis MySQL 4.1.2, INET_ATON() comprend aussi les IP courtes :

mysql> SELECT INET_ATON('127.0.0.1'), INET_ATON('127.1');
-> 2130706433, 2130706433

INET_ATON() a été ajouté en MySQL 3.23.15.

- INET_NTOA(expr)

Retourne l'adresse réseau (4 ou 8 octets), de l'expression numérique exp :

mysql> SELECT INET_NTOA(3520061480);
->  "209.207.224.40"

- IS_FREE_LOCK(str)

Regarde si le verrou nommé str peut être librement utilisé (i.e., non verrouillé). Retourne 1 si le verrou est libre (personne ne l'utilise), 0 si le verrou est actuellement utilisé et NULL si une erreur survient (comme un argument incorrect).

- IS_USED_LOCK(str)

Vérifie si le verrou appelé str est actuellement posé ou pas. Si c'est le cas, la fonction retourne l'identifiant de connexion qui a le verrou. Sinon, elle retourne NULL.

IS_USED_LOCK() a été ajouté en MySQL version 4.1.0.

- MASTER_POS_WAIT(log_name, log_pos)

Bloque le maître jusqu'à ce que l'esclave atteigne une position donnée dans le fichier d'historique principal, durant une réplication. Si l'historique principal n'est pas initialisé, retourne NULL. Si l'esclave n'est pas démarré, le maître restera bloqué jusqu'à ce que l'esclave soit démarré et ait atteint la position demandée. Si l'esclave a déjà dépassé cette position, la fonction se termine immédiatement. La valeur retournée est le nombre d'évènements qui ont dû être traités pour atteindre la position demandée, ou NULL en cas d'erreur. Cette fonction est très utile pour contrôler la synchronisation maître-esclave, mais elle a été initialement écrite pour faciliter les tests de réplications.

- RELEASE_LOCK(str)

Libère le verrou nommé str, obtenu par la fonction GET_LOCK(). Retourne 1 si le verrou a bien été libéré, 0 si le verrou n'a pas été libéré par le thread (dans ce cas, le verrou reste posé) et NULL si le nom du verrou n'existe pas. Le verrou n'existe pas s'il n'a pas été obtenu par la fonction GET_LOCK() ou s'il a déjà été libéré.

La commande DO est utilisable avec RELEASE_LOCK(). Voir Section 13.1.2, « Syntaxe de DO ».

- UUID()

Retourne un Universal Unique Identifier (UUID) généré grâce à « DCE 1.1: Remote Procedure Call » (Appendix A) CAE (Common Applications Environment) Specifications, publié par le The Open Group en octobre 1997 (Document numéro C706).

Un UUID est conçu comme un numéro qui est globalement unique dans l'espace, et le temps. Deux appels à UUID() sont supposés générer deux valeurs différentes, même si ces appels sont faits sur deux ordinateurs séparés, qui ne sont pas connectés ensemble.

Un UUID est un nombre de 128 bits, représenté par une chaîne de 5 nombres hexadécimaux, au format aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee :

- les trois premiers nombres sont générés à partir d'un timestamp ;

- le quatrième nombre préserve l'unicité temporelle si le timestamp perd sa monotonie (par exemple, à cause du changement d'heure d'hiver/été) ;

- le cinquième nombre est un nombre IEEE 802 qui fournit l'unicité. Un nombre aléatoire est utilisé là si ce dernier n'est pas disponible (par exemple, comme l'hôte n'a pas de carte Ethernet, nous ne savons pas comment trouver une adresse matérielle sur le système d'exploitation). Dans ce cas, l'unicité spatiale ne peut être garantie. Néanmoins, une collision aura une très faible probabilité.

Actuellement, l'adresse MAC est une interface utilisée sur FreeBSD et Linux. Sur les autres systèmes d'exploitation, MySQL génère un nombre aléatoire de 48 bits.

mysql> SELECT UUID();
-> '6ccd780c-baba-1026-9564-0040f4311e29'

Notez que UUID() ne fonctionne pas encore avec la réplication.

UUID() a été ajoutée en MySQL 4.1.2.

12-9 - Fonctions et options à utiliser dans les clauses GROUP BY

12-9-1 - Fonctions avec GROUP BY

Si vous utilisez les fonctions de groupement avec une requête ne contenant pas de clause GROUP BY, cela revient à grouper toutes les lignes.

- AVG(expr)

Retourne la moyenne de l'expression expr :

mysql> SELECT student_name, AVG(test_score)
->        FROM student
->        GROUP BY student_name;

- BIT_AND(expr)

Retourne la combinaison AND bit à bit de expr. Le calcul est fait en précision de 64 bits (BIGINT).

Depuis MySQL 4.0.17, cette fonction retourne 18446744073709551615 s'il n'y avait pas de lignes. (C'est un entier BIGINT non signé, dont tous les bits sont à 1.) Avant 4.0.17, la fonction retournait -1 s'il n'y avait pas de ligne trouvée.

- BIT_OR(expr)

Retourne la combinaison OR bit à bit de expr. Le calcul est fait en précision de 64 bits (BIGINT).

Cette fonction retourne 0 s'il n'y a pas de ligne à traiter.

- BIT_XOR(expr)

Retourne la combinaison XOR bit à bit de expr. Le calcul est fait en précision de 64 bits (BIGINT).

Cette fonction retourne 0 s'il n'y a pas de ligne à traiter.

Cette fonction est disponible depuis MySQL 4.1.1.

- COUNT(expr)

Retourne le nombre de valeurs non NULL dans les lignes lues par la commande SELECT :

mysql> SELECT student.student_name,COUNT(*)
->        FROM student,course
->        WHERE student.student_id=course.student_id
->        GROUP BY student_name;

COUNT(*) est un peu différente dans son action, car elle retourne le nombre de lignes, même si elles contiennent NULL.

COUNT(*) est optimisée pour retourner très rapidement un résultat si SELECT travaille sur une table, qu'aucune autre colonne n'est lue, et qu'il n'y a pas de clause WHERE. Par exemple :

mysql> SELECT COUNT(*) FROM student;

Cette optimisation s'applique uniquement pour les tables MyISAM et ISAM, car un compte exact du nombre de lignes est stocké pour ces types de tables, et il peut être lu très rapidement. Pour les moteurs de tables transactionnelles, (InnodB, BDB), le stockage de cette valeur est plus problématique, car plusieurs transactions peuvent survenir en même temps, et affecter toutes ce compte.

- COUNT(DISTINCT expr,[expr...])

Retourne le nombre de valeurs non NULL distinctes :

mysql> SELECT COUNT(DISTINCT results) FROM student;

Avec MySQL, vous pouvez lire le nombre d'expressions distinctes qui ne contiennent pas NULL, en plaçant ici une liste d'expression. Avec SQL-99, vous devriez faire une concaténation de toutes les expressions dans COUNT(DISTINCT ...).

- GROUP_CONCAT(expr)

Syntaxe complète :

GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC] [,col ...]]
[SEPARATOR str_val])

Cette fonction a été ajoutée en MySQL version 4.1. Elle retourne la chaîne résultant de la concaténation de toutes les valeurs du groupe :

mysql> SELECT student_name,
->        GROUP_CONCAT(test_score)
->        FROM student
->        GROUP BY student_name;

ou :

mysql> SELECT student_name,
->        GROUP_CONCAT(DISTINCT test_score
->                     ORDER BY test_score DESC SEPARATOR " ")
->        FROM student
->        GROUP BY student_name;

Avec MySQL, vous pouvez obtenir la concaténation d'une série d'expressions. Vous pouvez éliminer les doublons en utilisant DISTINCT. Si vous voulez trier les valeurs du résultat, il faut utiliser ORDER BY. Pour trier en ordre inverse, ajoutez le mot-clé DESC (descendant) au nom de la colonne que vous triez dans la clause ORDER BY. Par défaut, l'ordre est ascendant. Cela peut être spécifié explicitement avec le mot-clé ASC. SEPARATOR est une chaîne qui sera insérée entre chaque valeur du résultat. La valeur par défaut est une virgule '","'. Vous pouvez supprimer le séparateur en spécifiant la chaîne vide SEPARATOR "".

Vous pouvez donner une taille maximale à la variable group_concat_max_len de votre configuration. La syntaxe pour faire cela durant l'exécution est :

SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;

Si une taille maximale a été atteinte, le résultat sera tronqué à cette taille maximale.

Note : il y a encore de petites limitations pour GROUP_CONCAT() lorsqu'il faut utiliser des valeurs DISTINCT avec ORDER BY et et en utilisant les valeurs BLOB. Voyez Section 1.5.7.4, « Bogues connus / limitations de MySQL ».

GROUP_CONCAT() a été ajoutée en MySQL 4.1.

- MIN(expr), MAX(expr)

Retourne le minimum ou le maximum de expr. MIN() et MAX() peuvent prendre des chaînes comme argument : dans ce cas, elles retournent la valeur minimale ou maximale de la valeur de la chaîne. Voir Section 7.4.5, « Comment MySQL utilise les index ».

mysql> SELECT student_name, MIN(test_score), MAX(test_score)
->        FROM student
->        GROUP BY student_name;

Actuellement, MIN(), MAX() et d'autres fonctions d'agrégation MySQL, le serveur compare les valeurs de type ENUM et SET avec leur valeur de chaîne, et non pas leur position relative dans l'ensemble. Ce sera corrigé.

- STD(expr), STDDEV(expr)

Retourne la déviation standard de expr (la racine carrée de la VARIANCE(). Ceci est une extension au standard SQL 99. La forme STDDEV() de cette fonction est fournie pour assurer la compatibilité Oracle.

- SUM(expr)

Retourne la somme de expr. Notez que si le résultat ne contient pas de ligne, cette fonction retournera NULL.

- VARIANCE(expr)

Retourne la variance standard de l'expression expr (en considérant que les lignes forment une population totale, et non pas un échantillon. Le nombre de lignes est le dénominateur. C'est une extension à la norme SQL-99 (disponible en version 4.1 ou plus récente).

12-9-2 - Options de GROUP BY

Depuis MySQL 4.1.1, la clause GROUP BY permet l'utilisation de l'option WITH ROLLUP qui fait que des lignes supplémentaires seront ajoutées lors de regroupements. Ces lignes représentent des regroupements de haut niveau (ou des super-agrégats). ROLLUP vous permet de répondre simultanément à plusieurs niveaux d'analyse avec une seule requête. Il peut être utilisé, par exemple, pour supporter des opérations OLAP (Online Analytical Processing).

Voici une illustration. Supposons que vous ayez une table de ventes sales, avec des colonnes pour l'année year, le pays country, le produit product et le profit profit :

CREATE TABLE sales
(
year    INT NOT NULL,
country VARCHAR(20) NOT NULL,
product VARCHAR(32) NOT NULL,
profit  INT
);

Le contenu de cette table peut être agrégé par année avec la clause GROUP BY :

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |        4525 |
| 2001 |        3010 |
+------+-------------+

Cette requête affiche le profit par année, mais si vous voulez déterminer le profit total de toutes les années, vous devez ajouter ces valeurs vous-même, ou faire une autre requête.

Ou alors, vous pouvez utiliser la clause ROLLUP, qui fournit les deux niveaux d'analyse dans la même requête. En ajoutant l'option WITH ROLLUP à la clause GROUP BY, la requête va produire une autre ligne, avec le grand total de toutes les années :

mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 |        4525 |
| 2001 |        3010 |
| NULL |        7535 |
+------+-------------+

La ligne du grand total est identifiée par la valeur NULL dans la colonne year.

ROLLUP a des effets plus complexes lorsqu'il y a plusieurs colonnes dans la clause GROUP BY. Dans ce cas, il a y un changement de valeur pour toutes sauf la dernière colonne de groupement, et la requête va produire les super-agrégats.

Par exemple, sans la clause ROLLUP, le résumé des ventes de la table sales basé sur l'année year, le pays country et le produit product peut ressembler à ceci :

mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
| 2000 | USA     | Calculator |          75 |
| 2000 | USA     | Computer   |        1500 |
| 2001 | Finland | Phone      |          10 |
| 2001 | USA     | Calculator |          50 |
| 2001 | USA     | Computer   |        2700 |
| 2001 | USA     | TV         |         250 |
+------+---------+------------+-------------+

Le résultat indique les valeurs résumées pour chaque triplet année/pays/produit. Si nous ajoutons la clause ROLLUP, la requête produit plusieurs nouvelles lignes :

mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | Finland | NULL       |        1600 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
| 2000 | India   | NULL       |        1350 |
| 2000 | USA     | Calculator |          75 |
| 2000 | USA     | Computer   |        1500 |
| 2000 | USA     | NULL       |        1575 |
| 2000 | NULL    | NULL       |        4525 |
| 2001 | Finland | Phone      |          10 |
| 2001 | Finland | NULL       |          10 |
| 2001 | USA     | Calculator |          50 |
| 2001 | USA     | Computer   |        2700 |
| 2001 | USA     | TV         |         250 |
| 2001 | USA     | NULL       |        3000 |
| 2001 | NULL    | NULL       |        3010 |
| NULL | NULL    | NULL       |        7535 |
+------+---------+------------+-------------+

Pour cette requête, ajouter ROLLUP fait que la requête ajoute les résumés de quatre niveaux d'analyse, et non pas un seul. Voici comment interpréter le résultat de la clause ROLLUP.

- Après chaque jeu de lignes sur les produits, pour une année et un pays donnés, un résumé est ajouté, indiquant le total de tous les produits. Ces lignes voient leur colonne product contenir la valeur NULL.

- Après chaque jeu de lignes couvrant une année particulière, une nouvelle ligne est ajoutée pour afficher le total de tous les pays et produits, pour cette année la. Ces lignes voient leurs colonnes country et products contenir NULL.

- Finalement, suivant toutes les autres lignes, un résumé général est produit, avec le grand total de toutes les années, pays et produits. Cette ligne contient la valeur NULL pour toutes les colonnes year, country et products.

Autres considérations avec ROLLUP

Voici quelques comportements spécifiques de MySQL et son implémentation de ROLLUP.

Lorsque vous utilisez ROLLUP, vous ne pouvez pas utiliser de clause ORDER BY pour trier les résultats. En d'autres termes, ROLLUP et ORDER BY sont mutuellement exclusives. Toutefois, vous avez toujours le contrôle sur l'ordre de tri avec la clause GROUP BY. Vous pouvez utiliser explicitement les mots ASC et DESC avec les colonnes listées dans GROUP BY pour spécifier les ordres de tri des colonnes individuelles. Les lignes de résumé de ROLLUP apparaissent toujours après les lignes pour lesquelles ils sont calculés, quel que soit le tri.

La clause LIMIT peut être utilisée pour restreindre le nombre de lignes retournées au client. LIMIT s'applique après ROLLUP, et la limite s'appliquera aux lignes ajoutées par ROLLUP. Par exemple :

mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP
-> LIMIT 5;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | Finland | NULL       |        1600 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
+------+---------+------------+-------------+

Notez qu'utiliser LIMIT avec ROLLUP peut conduire à des résultats plus difficiles à interpréter, car vous avez moins de contexte pour comprendre les résumés.

Les indicateurs NULL de chaque super-agrégat sont produits lorsque la ligne est envoyée au client. Le serveur recherche les colonnes citées dans la clause GROUP BY, en les prenant la plus à gauche, dont la valeur change. Toute colonne du jeu de résultat dont le nom ne correspond pas lexicalement à un de ces noms, verra sa valeur être NULL. Si vous spécifiez un groupement par numéro de colonne, le serveur identifiera aussi les colonnes qui devront recevoir NULL.

Comme les valeurs NULL des résumés sont placées dans le résultat aussi tard durant le traitement de la requête, nous ne pouvons pas les tester comme étant des valeurs NULL provenant de la requête elle-même. Par exemple, vous ne pourrez pas ajouter HAVING product IS NULL pour éliminer certains résumés qui ne vous intéressent pas.

D'un autre côté, les valeurs NULL apparaissent comme des valeurs NULL du côté du client, et peuvent être repérées en tant que telles par le client MySQL.

12-9-3 - GROUP BY avec les champs cachés

MySQL a étendu l'utilisation de la clause GROUP BY. Vous pouvez utiliser des colonnes ou des calculs de l'expression SELECT qui n'apparaissent pas dans la clause GROUP BY. Cela se dit n'importe quelle valeur pour ce groupe. Vous pouvez utiliser cela pour améliorer les performances en évitant les tris ou les regroupements inutiles de valeurs. Par exemple, vous n'avez pas besoin de faire un regroupement par nom de client customer.name dans la requête suivante :

mysql> SELECT order.custid,customer.name,MAX(payments)
->        FROM order,customer
->        WHERE order.custid = customer.custid
->        GROUP BY order.custid;

En SQL standard, vous devriez ajouter la colonne customer.name à la clause GROUP BY. Avec MySQL, ce nom est redondant si vous n'utilisez pas le mode ANSI.

N'utilisez pas cette fonctionnalité si les colonnes que vous omettez dans la clause GROUP BY ne sont pas uniques dans le groupe !! Vous auriez des résultats inattendus !

Dans certains cas, vous pouvez utiliser MIN() et MAX() pour obtenir une valeur spécifique d'une colonne, même si cette valeur n'est pas unique. L'exemple suivant donne la valeur de la colonne column issue de la ligne contenant la plus petite valeur de la colonne sort :

SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)

Voir Section 3.6.4, « La ligne contenant la plus grande valeur d'un certain champ par rapport à un groupe ».

Notez que si vous utilisez MySQL version 3.22 ou plus ancien, ou si vous essayez de suivre la norme SQL-99, vous ne pouvez pas utiliser les expressions dans GROUP BY ou ORDER BY. Vous pouvez contourner cette limitation en utilisant un alias pour l'expression :

mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
->        GROUP BY id,val ORDER BY val;

En MySQL version 3.23, vous pouvez faire :

mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();

13 - Syntaxe des commandes SQL

Ce chapitre décrit la syntaxe des commandes que MySQL supporte.

13-1 - Manipulation de données : SELECT, INSERT, UPDATE, DELETE

13-1-1 - Syntaxe de DELETE

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM table_name
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]

Syntaxe multitable :

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] table_name[.*] [, table_name[.*] ...]
FROM table-references
[WHERE where_definition]

ou :

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM table_name[.*] [, table_name[.*] ...]
USING table-references
[WHERE where_definition]

DELETE efface les enregistrements de nom_de_table qui satisfont la condition donnée par clause_where, et retourne le nombre d'enregistrements effacés.

Si vous exécutez un DELETE sans clause WHERE, tous les enregistrements sont effacés. Si vous le faites en mode AUTOCOMMIT cela aura le même effet qu'un TRUNCATE. Voir Section 13.1.9, « Syntaxe de TRUNCATE ».

Avec MySQL 3.23, DELETE sans clause WHERE retournera zéro comme nombre d'enregistrements affectés.

Si vous voulez vraiment savoir combien d'enregistrements ont été effacés quand vous videz une table, et que vous êtes prêts à souffrir d'un léger ralentissement, vous pouvez utiliser une requête DELETE de ce genre :

mysql> DELETE FROM nom_de_table WHERE 1>0;

Notez que c'est plus lent que DELETE FROM nom_de_table sans clause WHERE, parce que cela efface un enregistrement à la fois.

Si vous effacez des lignes contenant la valeur maximum d'une colonne AUTO_INCREMENT, la valeur sera réutilisée pour par une table ISAM ou BDB, mais pas pour une table MyISAM ou InnoDB. Si vous effacez toutes les lignes dans une table avec une commande DELETE FROM tbl_name (avec une clause WHERE) avec le mode AUTOCOMMIT, la séquence redémarre à zéro pour tous les types de tables sauf InnoDB et, depuis MySQL 4.0, MyISAM. Il y a des exceptions à ce comportement pour les tables InnoDB, qui sont présentées dans la Section 15.7.3, « Comment les colonnes AUTO_INCREMENT fonctionnent avec InnoDB ».

Pour les tables MyISAM et BDB, vous pouvez spécifier une autre colonne AUTO_INCREMENT dans une clé multicolonne. Dans ce cas, la réutilisation des clés à partir de la fin de la séquence se fait aussi pour les tables MyISAM. Voir Section 3.6.9, « Utiliser AUTO_INCREMENT ».

La commande DELETE supporte les clauses suivantes.

- Si vous spécifiez le mot-clé LOW_PRIORITY, l'exécution de la commande DELETE est repoussée jusqu'à ce qu'aucun client ne soit en train de lire la table.

- Pour les tables MyISAM, si vous spécifiez l'option QUICK, le moteur de stockage ne compacte pas les index durant l'effacement, ce qui peut accélérer certains effacements.

- L'option IGNORE fait que MySQL ignore les erreurs durant le traitement des lignes. Les erreurs rencontrées durant la phase d'analyse sont traitées comme d'habitude. Les erreurs qui sont ignorées grâce à cette option sont listées comme des alertes. Cette option a été ajoutée en MySQL 4.1.1.

La vitesse d'exécution des opérations de suppression peut être affectée par les facteurs présentés dans la Section 7.2.16, « Rapidité des requêtes DELETE ».

Dans les tables de type MyISAM, les enregistrements effacés sont maintenus dans une liste liée et les requêtes INSERT suivantes réutilisent les vieux emplacements. Pour recouvrir l'espace inutilisé ou réduire la taille des fichiers, utilisez la commande OPTIMIZE TABLE ou l'utilitaire myisamchk pour réorganiser les tables. OPTIMIZE TABLE est plus simple, mais myisamchk est plus rapide. Voyez Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE » et Section 5.7.3.10, « Optimisation de table ».

La clause spécifique MySQL LIMIT row_count de la commande DELETE indique au serveur le nombre maximal de lignes à supprimer avant de rendre le contrôle au client. Elle peut être utilisée pour s'assurer qu'une commande DELETE ne prend pas trop de temps. Vous pouvez simplement répéter la commande DELETE jusqu'à ce que le nombre de lignes effacées est inférieur à la valeur de LIMIT.

Si la commande DELETE inclut la clause ORDER BY, les lignes sont effacées dans l'ordre spécifié par cette clause. Elle n'est vraiment utile que lorsqu'elle est couplée avec la clause LIMIT. Par exemple, la commande suivante applique la condition WHERE, trie les lignes avec la colonne timestamp, et efface la ligne la plus ancienne :

DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp
LIMIT 1

ORDER BY peut être utilisée avec DELETE depuis MySQL version 4.0.0.

Depuis MySQL version 4.0, vous pouvez spécifier plusieurs tables dans la commande DELETE, pour effacer des lignes dans plusieurs tables, en fonction d'une condition de liaison. Cependant, vous ne pouvez pas utiliser les clauses ORDER BY et LIMIT dans une suppression DELETE multitable.

La première syntaxe de DELETE multitable est supportée depuis MySQL 4.0.0. La deuxième syntaxe de DELETE multitable est supportée depuis MySQL 4.0.2. La partie table_references liste les tables impliquées dans la jointure. Sa syntaxe est décrite dans la Section 13.1.7.1, « Syntaxe de JOIN ».

L'idée est que seules les lignes concordantes dans les tables énumérées avant le FROM ou avant la clause USING sont effacées. Le but est de pouvoir effacer des lignes de plusieurs tables en même temps tout en ayant d'autres tables pour les recherches.

Le code .* après les noms de tables n'est présent que pour assurer la compatibilité avec Access :

DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

ou :

DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

Dans les cas précédents, nous n'avons supprimé les lignes correspondantes que dans les tables t1 et t2.

Les exemples ci-dessus présentent des jointures internes, en utilisant l'opérateur virgule, mais les DELETE multitables peuvent utiliser n'importe quel type de jointure qu'une commande SELECT accepte, comme un LEFT JOIN.

La syntaxe autorise .* après le nom de la table pour assurer la compatibilité avec Access.

Si vous utilisez une commande DELETE multitable avec des tables InnoDB pour lesquelles il y a des contraintes de clés étrangères, l'optimiseur MySQL risque de traiter les tables dans un ordre qui diffère de celui des relations parent/enfant de la clé. Dans ce cas, la commande échouera, et s'annulera. Pour résoudre ce problème, effacez les lignes tables par table, et utilisez les fonctionnalités ON DELETE que InnoDB fournit pour que les autres tables soient correctement traitées.

Note : en MySQL 4.0, vous devez utiliser le véritable nom de table. En MySQL 4.1, vous devez utiliser l'alias éventuel, lorsque vous nommez la table.

En MySQL 4.0 :

DELETE test FROM test AS t1, test2 WHERE ...

En MySQL 4.1 :

DELETE t1 FROM test AS t1, test2 WHERE ...

La raison qui nous a poussés à ne pas faire ce changement en version 4.0, est la compatibilité ascendante avec les vieilles applications 4.0, qui utilisent la vieille syntaxe.

13-1-2 - Syntaxe de DO

DO expression, [expression, ...]

Exécute l'expression, mais ne retourne aucun résultat. C'est un alias de SELECT expression, expression, mais il a l'avantage d'être plus rapide quand on n'a pas besoin du résultat.

Cela s'avère très utile avec les fonctions qui ont des effets secondaires, comme RELEASE_LOCK.

13-1-3 - Syntaxe de HANDLER

HANDLER tbl_name OPEN [ AS alias ]
HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
[ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE ... ] [LIMIT ... ]
HANDLER tbl_name CLOSE

La commande HANDLER fournit un accès direct à l'interface de gestion de la table MyISAM.

La première forme de HANDLER ouvre la table, la rendant accessible via la requête HANDLER ... READ qui la suit. Cet objet table n'est pas partagé par les autres threads et ne sera refermé que si le thread appelle HANDLER nom_de_table CLOSE ou que celui-ci se termine.

La seconde forme récupère une ligne (ou plus, à spécifier dans la clause LIMIT) où l'index spécifié remplit les conditions et où la clause WHERE est répondue. Si l'index se compose de plusieurs parties, (s'étend sur plusieurs colonnes) les valeurs sont spécifiées dans une liste séparée par des virgules, fournir des valeurs pour quelques premières colonnes est possible. Par exemple :

HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
HANDLER ... index_name = (col_a_val,col_b_val) ...
HANDLER ... index_name = (col_a_val) ...

La troisième forme récupère une ligne (ou plus, à spécifier dans la clause LIMIT) de la table dans l'ordre de l'index, qui répond à la clause WHERE.

La quatrième forme (sans spécifications relatives à l'index) récupère une ligne (ou plus, à spécifier dans la clause LIMIT) de la table dans un ordre naturel des lignes (comme stocké dans le fichier de données) qui correspond à la condition WHERE. C'est plus rapide que HANDLER nom_de_table READ nom_index quand une lecture entière de la table est requise. Voir Section 13.1.7, « Syntaxe de SELECT ».

HANDLER ... CLOSE ferme une table qui a été ouverte avec HANDLER ... OPEN.

Note : pour utiliser l'interface HANDLER avec la clé primaire d'une table PRIMARY KEY, utilisez l'identifiant entre guillemets obliques `PRIMARY` :

HANDLER tbl_name READ `PRIMARY` > (...);

HANDLER est en quelque sorte une commande bas niveau. Par exemple, elle ne propose pas de consistance. En clair, HANDLER ... OPEN ne se base pas sur une image de la table, et ne verrouille pas la table. Cela signifie qu'après l'exécution d'une requête HANDLER ... OPEN, les données de la table peuvent être modifiées (par ce ou un autre thread) et ces modifications peuvent apparaître partiellement dans les lectures de HANDLER ... NEXT ou HANDLER ... PREV.

Les raisons d'utiliser cette interface plutôt que les commandes MySQL usuelles sont les suivantes.

- Plus rapide qu'un SELECT, car :

- un pointeur sur table dédié est alloué au thread dans HANDLER open ;

- il y a moins de traitements ;

- pas de perte de temps en optimisation ou vérifications de requêtes ;

- la table utilisée n'a pas besoin d'être verrouillée entre deux requêtes de gestion ;

- l'interface de gestion n'a pas à fournir une vue consistante des données (par exemple, les lectures corrompues sont autorisées), ce qui permet au gestionnaire d'effectuer des optimisations que SQL ne permet pas.

- Cela facilite le port des applications qui utilisent l'interface ISAM pour MySQL.

- Cela permet de traverser plus facilement la base de données qu'avec SQL (dans certains cas, cette opération est impossible avec SQL). L'interface de gestion amène une façon plus naturelle de manipuler les données lorsque vous travaillez avec des applications qui proposent une interface interactive entre l'utilisateur et la base de données.

13-1-4 - Syntaxe de INSERT

INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

ou :

INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

ou :

INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...

INSERT insère une nouvelle ligne dans une table existante. La syntaxe INSERT ... VALUES insère une ligne à partir de valeurs explicitement fournies. La syntaxe INSERT ... SELECT insère des valeurs à partir d'une autre table. La syntaxe INSERT ... VALUES avec plusieurs valeurs est supportée à partir de MySQL 3.22.5 ou supérieure. La syntaxe nom_colonne=expression est supportée à partir de la version 3.22.10 de MySQL.

INSERT ... SELECT est présenté plus en détail : Voir Section 13.1.4.1, « Syntaxe de INSERT ... SELECT ».

nom_de_table est le nom de la table dans laquelle les valeurs seront insérées. La liste de noms de colonne où la clause SET indique les colonnes qui seront affectées.

- La liste des noms de colonnes où la clause SET indique explicitement les colonnes utilisées.

- Si vous ne spécifiez pas de liste de colonnes avec INSERT ... VALUES ou INSERT ... SELECT, les valeurs pour toutes les colonnes doivent être fournies dans la clause VALUES() ou par la commande SELECT. Si vous ne connaissez pas l'ordre des colonnes, utilisez la commande DESCRIBE nom_de_table pour le connaître.

Les valeurs des colonnes peuvent être spécifiées de plusieurs façons.

- À chaque fois qu'on ne donne pas explicitement une valeur pour une colonne, celle prend la valeur par défaut. Par exemple, si on définit une liste de colonnes qui ne compte pas toutes les colonnes de la table, toutes les colonnes qui ne sont pas nommées prendront leur valeur par défaut. La définition de la valeur par défaut se fait avec Section 13.2.5, « Syntaxe de CREATE TABLE ».

MySQL a toujours une valeur par défaut pour chaque champ. C'est obligatoire pour MySQL pour pouvoir fonctionner aussi bien avec des tables supportant les transactions qu'avec des tables ne les supportant pas.

Nous pensons que le contrôle du contenu des champs devrait être fait par l'application et non par le serveur de base de données.

Note : si vous voulez que les commandes INSERT génèrent une erreur si vous ne spécifiez pas explicitement de valeur pour toutes les colonnes qui requièrent des valeurs non nulles (NULL), vous pouvez aussi configurer MySQL avec l'option DONT_USE_DEFAULT_FIELDS. Ce comportement n'est pas disponible si vous compilez MySQL depuis le source. Voir Section 2.4.2, « Options habituelles de configure ».

- Vous pouvez utiliser le mot-clé DEFAULT pour donner explicitement à une colonne sa valeur par défaut. Cette fonctionnalité a été ajoutée en MySQL version 4.0.3. Cela rend plus simple l'écriture de commandes INSERT lors de l'assignation de quelques colonnes, sans écrire de valeurs VALUES incomplètes. Sinon, il faut écrire la liste des colonnes utilisées pour chaque valeur de la liste VALUES.

- Si la liste de colonnes et de valeurs VALUES est vide, INSERT crée une ligne pour chaque colonne avec sa valeur par défaut :

mysql> INSERT INTO tbl_name () VALUES();

- Une expression peut faire référence à n'importe quelle colonne qui a été définie précédemment dans une liste de valeurs. Par exemple, on peut dire ceci :

mysql> INSERT INTO nom_de_table (col1,col2) VALUES(15,col1*2);

Mais vous ne pouvez pas faire cela, car la valeur de col1 fait référence à col2, qui est assigné après col1 :

mysql> INSERT INTO nom_de_table (col1,col2) VALUES(col2*2,15);

Les commandes INSERT supportent les options suivantes.

- Si vous spécifiez l'option DELAYED, le serveur met la ligne ou les lignes à insérer dans un tampon, et le client qui a émis la commande INSERT DELAYED est immédiatement libéré. Si la table est occupée, le serveur conserve les lignes. Lorsque la table se libère, il va insérer les lignes, tout en vérifiant périodiquement s'il n'y a pas de lectures dans la table. Si une lecture arrive, l'insertion est suspendue jusqu'à la prochaine libération. Voir Section 13.1.4.2, « Syntaxe de INSERT DELAYED ».

- Si on spécifie le mot LOW_PRIORITY, l'exécution de INSERT sera retardée jusqu'à ce qu'il n'y ait plus de clients qui lisent la table. Dans ce cas le client doit attendre jusqu'à la fin de l'opération d'insertion, ce qui peut prendre beaucoup de temps si la table est fréquemment accédée. C'est la grande différence avec INSERT DELAYED, qui laisse le client continuer tout de suite. Voir Section 13.1.4.2, « Syntaxe de INSERT DELAYED ». On peut remarquer que, en principe, LOW_PRIORITY ne devrait pas être utilisé avec des tables de type MyISAM, étant donné que celles-ci n'autorisent pas les insertions simultanées. Voir Section 14.1, « Le moteur de tables MyISAM ».

- Si on spécifie le mot IGNORE dans un INSERT avec les valeurs de plusieurs lignes, chaque ligne qui ferait doublon avec une clé PRIMARY ou UNIQUE existant dans la table sera ignorée et ne sera pas insérée. Si on ne spécifie pas IGNORE, l'insertion est abandonnée si quelque ligne que ce soit fait doublon avec une clé existante. La fonction mysql_info() de l'API C permet de savoir combien de lignes ont été insérées dans la table.

Si vous spécifiez la clause ON DUPLICATE KEY UPDATE (nouveau en MySQL 4.1.0), et qu'une ligne insérée engendre un doublon pour une clé PRIMARY ou UNIQUE, une commande UPDATE sera faite à la place de l'insertion. Par exemple, les commandes ont le même effet :

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=c+1;

mysql> UPDATE table SET c=c+1 WHERE a=1;

Note : si la colonne b est aussi unique, la commande UPDATE sera réécrite telle que

mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

Si a=1 OR b=2 trouve plusieurs lignes, uniquement une ligne sera mise à jour ! En général, il faut éviter d'utiliser la clause ON DUPLICATE KEY sur des tables avec des clés UNIQUE multiples.

Depuis MySQL version 4.1.1, on peut utiliser la fonction VALUES(col_name) pour faire référence à la valeur de la colonne dans la clause INSERT d'une commande INSERT ... UPDATE : c'est la valeur qui sera insérée s'il n'y a pas de conflit de clé. Cette valeur est particulièrement utile dans les commandes INSERT ... UPDATE et retourne NULL sinon.

Exemple :

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
-> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

La commande ci-dessus est identique à :

mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=3;
mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
-> ON DUPLICATE KEY UPDATE c=9;

Lors de l'utilisation de ON DUPLICATE KEY UPDATE, l'option DELAYED est ignorée.

Vous pouvez trouver la valeur utilisée pour une colonne AUTO_INCREMENT en utilisant la fonction LAST_INSERT_ID(). Depuis l'interface C, utilisez la fonction mysql_insert_id(). Cependant, notez que les deux fonctions ne se comportement pas de la même façon dans toutes les circonstances. Le comportement des commandes INSERT avec les colonnes AUTO_INCREMENT sont décrites dans la Section 12.8.3, « Fonctions d'informations » et Section 24.2.3.33, « mysql_insert_id() ».

Si vous utilisez une commande INSERT ... VALUES avec plusieurs listes de valeurs ou INSERT ... SELECT, la commande retourne les informations sous ce format :

Records: 100 Duplicates: 0 Warnings: 0

Records indique le nombre de lignes qui ont été traitées par cette commande. Ce n'est pas forcément le nombre de lignes insérées. Duplicates peut être non nulle. Duplicates indique le nombre de lignes qui n'ont pas peut être insérées pour cause de conflit avec une clé unique existante. Warnings indique le nombre de tentatives d'insertion de valeurs dans une colonne qui ont généré des problèmes. Les Warnings peuvent apparaître dans les conditions suivantes.

- Insertion de NULL dans une colonne déclarée NOT NULL. Pour les commandes d'insertions multiples INSERT ou les commandes INSERT ... SELECT, la colonne prend la valeur par défaut adaptée au type de colonne. C'est 0 pour les types numériques, la chaîne vide pour les textes et la valeur « zéro » pour les types temporels.

- Enregistrement dans une colonne numérique d'une valeur qui déborde de la taille de la colonne. Cette valeur a été tronquée à l'extrémité la plus adaptée de la colonne.

- Attribution à une colonne numérique d'une valeur telle que '10.34 a'. Celle valeur refusée est séparée, et la partie numérique résultante est insérée. Si cette valeur n'a pas une valeur numérique sensée, la valeur 0 est insérée.

- L'insertion d'une chaîne dans une colonne CHAR, VARCHAR, TEXT, ou BLOB qui dépasse la taille maximale de la colonne. La valeur est tronquée à la taille maximale de la colonne.

- L'insertion d'une valeur illégale pour une colonne de type DATE ou TIME. La colonne est alors enregistrée avec la valeur de zéro appropriée pour le type.

Si vous utilisez l'interface C, la chaîne d'information peut être obtenue en invoquant la fonction mysql_info(). Voir Section 24.2.3.31, « mysql_info() ».

13-1-4-1 - Syntaxe de INSERT ... SELECT

INSERT [LOW_PRIORITY] [IGNORE] [INTO] nom_de_la_table [(liste des colonnes)] SELECT ...

La requête INSERT ... SELECT permet de rapidement insérer dans une table un grand nombre de lignes d'une ou plusieurs autres tables.

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
tblTemp1.fldOrder_ID > 100;

Les conditions suivantes s'appliquent à la requête INSERT ... SELECT.

- Avant MySQL version 4.0.1, INSERT ... SELECT opérait implicitement en mode IGNORE. Depuis MySQL version 4.0.1, vous devez spécifier le mode IGNORE explicitement, pour ignorer les lignes qui causeront des erreurs de doublons pour les index uniques.

- N'utilisez pas DELAYED avec INSERT ... SELECT.

- Avant MySQL version 4.0.14, la table de destination de la requête INSERT ne peut apparaître dans la clause FROM de la partie SELECT de la requête, car il est interdit par le ANSI SQL de lire la table dans laquelle on est en train de faire un insert. (Le problème est que le SELECT pourrait trouver des enregistrements qui auraient été insérés auparavant dans la même exécution. L'utilisation de « subselect » peut rendre la situation confuse !)

- Les colonnes AUTO_INCREMENT fonctionnent comme d'habitude.

- Pour s'assurer que les journaux des modifications ou les journaux binaires puissent être utilisés pour recréer les tables originales, MySQL n'autorise pas les inserts concurrents pendant INSERT ... SELECT.

Il est bien sûr possible d'utiliser REPLACE à la place de INSERT pour remplacer les anciennes lignes.

13-1-4-2 - Syntaxe de INSERT DELAYED

INSERT DELAYED ...

L'option DELAYED de la commande INSERT est une option spécifique à MySQL très utile si vos clients ne peuvent pas attendre que INSERT se termine. C'est un problème fréquent quand on utilise MySQL pour des logs, mais aussi quand on utilise souvent des commandes SELECT ou UPDATE qui prennent beaucoup de temps. DELAYED a été ajouté à MySQL dans la version 3.22.15. C'est une extension de MySQL au ANSI SQL 92.

En utilisant INSERT DELAYED, le client reçoit immédiatement un acquittement, et la ligne sera insérée quand la table ne sera plus utilisée par un autre thread.

Un autre avantage de INSERT DELAYED est que les insertions des clients sont regroupées, et écrites d'un seul bloc. C'est beaucoup plus rapide que de faire des insertions séparées.

Il y a quelques contraintes à l'utilisation de DELAYED.

- INSERT DELAYED ne fonctionne qu'avec les tables MyISAM et ISAM. Pour les tables MyISAM, s'il n'y a plus de blocs libres au milieu du fichier de données, les SELECT et INSERT simultanés sont supportés. Dans ces circonstances, vous n'aurez que très rarement besoin de INSERT DELAYED avec MyISAM. Voir Section 14.1, « Le moteur de tables MyISAM ».

- INSERT DELAYED doit être utilisé uniquement avec les commandes INSERT qui spécifient une liste de valeurs. C'est le cas depuis MySQL 4.0.18. Le serveur ignore DELAYED pour les commandes INSERT DELAYED ... SELECT.

- Le serveur ignore DELAYED dans les commandes INSERT DELAYED ... ON DUPLICATE UPDATE.

- Comme la commande s'exécute immédiatement, sans que la ligne ne soit insérée, vous ne pouvez pas utiliser LAST_INSERT_ID() pour lire la valeur que la colonne AUTO_INCREMENT va générer.

- Les lignes DELAYED ne sont visibles par les commandes SELECT que lorsqu'elles ont été réellement insérées.

Actuellement, les lignes en attente sont uniquement stockées en mémoire tant qu'elles ne sont pas insérées dans la table. Cela signifie que si on tue mysqld violemment, (kill -9) ou si mysqld meurt accidentellement, toutes les lignes en attente qui n'auront pas été écrites sur le disque seront perdues !

Les paragraphes suivants décrivent en détail ce qu'il se passe quand on utilise l'option DELAYED dans une requête INSERT ou REPLACE. Dans cette description, « thread » est un thread qui reçoit une commande INSERT DELAYED et « handler » est un thread qui gère toutes les opérations de INSERT DELAYED pour une table donnée.

- Quand un thread exécute une opération DELAYED sur une table, un thread de gestion est créé pour exécuter toutes les opérations DELAYED pour cette table - si ce thread de gestion n'existe pas.

- Le thread vérifie que le thread de gestion a déjà reçu un verrou DELAYED; sinon, il dit au thread de gestion de le faire. Le verrou DELAYED peut être obtenu même si d'autres threads ont des verrous READ ou WRITE sur la table. Cependant le gestionnaire attendra que tous les verrous ALTER TABLE ou FLUSH TABLES soient finis pour s'assurer que la structure de la table est à jour.

- Le thread exécute une opération INSERT, mais plutôt que d'écrire la ligne dans la table, il va placer une copie de la ligne finale dans une file d'attente gérée par le thread de gestion. Le programme client est averti de toutes les erreurs de syntaxe.

- Le client ne peut pas faire de rapport sur le nombre de duplicata ou sur la valeur de AUTO_INCREMENT de la ligne enregistrée, il ne peut pas les obtenir du serveur, car le INSERT est validé avant que l'opération d'insert n'ait été effectuée. Si vous utilisez l'API C, la fonction mysql_info() ne retourne pas de valeur intéressante, pour la même raison.

- Le journal de modifications est mis à jour par le thread de gestion au moment où la ligne est insérée dans la table. Si plusieurs lignes sont insérées en même temps, le journal des modifications est mis à jour quand la première ligne est insérée.

- Une fois que toutes les lignes delayed_insert_limit sont écrites, le gestionnaire vérifie si des requêtes SELECT sont en attente, et si c'est le cas, il leur permet de s'exécuter avant de continuer.

- Quand le thread de gestion n'a plus de ligne dans sa file, la table est déverrouillée. Si aucun INSERT DELAYED n'est reçu avant delayed_insert_timeout secondes, le gestionnaire s'arrête.

- Si plus de delayed_queue_size lignes sont déjà en attente d'un gestionnaire de file donné, le thread qui demande le INSERT DELAYED doit attendre qu'il y ait une place dans la file. Cela permet d'être sûr que mysqld n'utilisera pas toute la mémoire pour la mémoire des files d'attente d'insertions retardées.

- Le thread de gestion apparaîtra dans la liste des processus de MySQL avec delayed_insert dans la colonne Command. Il sera tué si on exécute une commande FLUSH TABLES ou si on le tue avec KILL thread_id. Cependant, il commencera par stocker toutes les lignes en attente dans la table avant de sortir. Pendant ce temps, il n'acceptera aucune commande INSERT d'aucun autre thread. Si on exécute une commande INSERT DELAYED après cela, un nouveau thread de gestion sera créé.

Il faut noter que les commandes INSERT DELAYED ont une plus grande priorité que les commandes INSERT normales si un gestionnaire de INSERT DELAYED existe déjà ! les autres commandes de modification devront attendre que la file d'attente de INSERT DELAYED soit vide, que quelqu'un tue le gestionnaire (avec KILL thread_id), ou que quelqu'un exécute FLUSH TABLES..

- Les variables suivantes fournissent des informations relatives à la commande INSERT DELAYED :

Variable

Signification

Delayed_insert_threads

Nombre de threads de gestion

Delayed_writes

Nombre de lignes écrites avec INSERT DELAYED

Not_flushed_delayed_rows

Nombre de lignes en attente d'être écrites.

On peut voir ces variables avec la commande SHOW STATUS ou en exécutant la commande mysqladmin extended-status.

Il faut noter que INSERT DELAYED est plus lent qu'un INSERT normal si la table n'est pas utilisée. L'utilisation d'un thread de gestion séparé pour chaque table sur lesquelles on utilise INSERT DELAYED rajoute également une surcharge au serveur. Ce qui signifie qu'il vaut mieux utiliser INSERT DELAYED uniquement quand c'est vraiment nécessaire !

13-1-5 - Syntaxe de LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY '\t']
[[OPTIONALLY] ENCLOSED BY '']
[ESCAPED BY '\\' ]
]
[LINES
[STARTING BY '']
[TERMINATED BY '\n']
]
[IGNORE number LINES]
[(col_name,...)]

La commande LOAD DATA INFILE lit les lignes dans un fichier texte et les insère à très grande vitesse. Pour plus d'informations sur l'efficacité des commandes INSERT comparativement à LOAD DATA INFILE et pour accélérer les commandes LOAD DATA INFILE, voyez Section 7.2.14, « Vitesse des requêtes INSERT ».

Vous pouvez aussi charger des fichiers de données en utilisant l'utilitaire mysqlimport. Il opère en envoyant la commande LOAD DATA INFILE au serveur. L'option --local fait que mysqlimport lit les fichiers de données chez le client. Vous pouvez spécifier l'option --compress pour avoir de meilleures performances avec les connexions lentes si le client et le serveur supportent le protocole compressé. Voir Section 8.10, « mysqlimport, importer des données depuis des fichiers texte ».

Si vous spécifiez le mot-clé LOW_PRIORITY, l'exécution de la commande LOAD DATA est ajournée jusqu'à ce qu'aucun client n'utilise plus la table.

Si vous spécifiez le mot-clé CONCURRENT avec une table au format MyISAM, les autres threads pourront accéder à la table durant l'exécution de la commande LOAD DATA. L'utilisation de cette option ralentira un peu les performances de LOAD DATA même si aucun thread n'utilise la table en même si aucun autre thread n'accède à la table en même temps.

Si le mot-clé LOCAL est spécifié, il est interprété en suivant les règles suivantes.

- Si LOCAL est spécifié, le fichier est lu par le programme client, et envoyé vers l'hôte.

- Si LOCAL n'est pas spécifiée, le fichier doit être sur le serveur hôte, et sera lu directement par le serveur.

LOCAL est disponible depuis MySQL 3.22.6 ou plus récents.

Pour des raisons de sécurité, lorsque les fichiers sont lus sur le serveur, ils doivent se trouver dans le répertoire de la base de données courante, ou bien être lisibles par tous. Pour utiliser la commande LOAD DATA INFILE sur des fichiers du serveur, vous devez avoir le droit de FILE sur le serveur. Voir Section 5.5.3, « Droits fournis par MySQL ».

Utiliser LOCAL est plus lent que de laisser le serveur accéder directement aux fichiers, car le contenu du fichier doit être envoyé via le réseau au serveur. D'un autre côté, vous n'aurez pas besoin de droits de FILE pour faire un chargement local.

Depuis MySQL 3.23.49 et MySQL 4.0.2 (4.0.13 sur Windows), LOCAL fonctionne uniquement si votre serveur et votre client ont été configurés pour. Par exemple, si mysqld a été lancé avec --local-infile=0, LOCAL ne fonctionnera pas. Voir Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL ».

Si vous avez besoin de lire des données LOAD DATA depuis un pipe, vous devez utiliser la technique suivante :

mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /mysql/db/x/x
mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

Si vous utilisez une version de MySQL plus ancienne que 3.23.25, vous pouvez uniquement utiliser cette technique avec LOAD DATA LOCAL INFILE.

Si vous utilisez une version de MySQL antérieure à la 3.23.24 vous ne pouvez lire à partir d'un FIFO avec LOAD DATA INFILE. Si vous avez besoin de lire à partir d'un FIFO (par exemple la sortie de gunzip), utilisez LOAD DATA LOCAL INFILE.

Lorsque les fichiers de données sont sur le serveur, celui-ci utilise les règles suivantes.

- Si un chemin absolu est fourni, le serveur utilise le chemin tel quel.

- Si un chemin relatif est fourni, avec un ou plusieurs éléments de dossiers, le serveur recherche le fichier relativement à son dossier de données.

- Si le fichier n'a pas d'éléments de dossier, le serveur recherche les données dans le dossier de base de données courante.

Notez que ces règles font qu'un fichier tel que ./myfile.txt est lu dans le dossier de données du serveur, alors que s'il est nommé myfile.txt, il sera lu dans le dossier de base de données courante. Par exemple, la commande LOAD DATA suivante lit le fichier donnees.txt dans le dossier de la base db1, car db1 est la base de données courante, même si la commande charge explicitement le fichier dans la base de données db2 :

mysql> USE db1;
mysql> LOAD DATA INFILE "donnees.txt" INTO TABLE db2.ma_table;

Les mots réservés REPLACE et IGNORE contrôlent la méthode d'insertion de lignes lorsque des doublons apparaissent pour les clés uniques.

Si vous spécifiez REPLACE, les nouvelles lignes remplaceront les anciennes. Voir Section 13.1.6, « Syntaxe de REPLACE ».

Si vous spécifiez IGNORE, les nouvelles lignes seront ignorées. Si vous ne spécifiez pas cette option, une erreur sera générée à chaque doublon, et le reste du fichier sera ignoré. Avec l'option LOCAL, le comportement par défaut est le même que si IGNORE est spécifié : ceci est dû au fait que le serveur n'a pas moyen de stopper la transmission du fichier au milieu de l'opération.

Si vous chargez un fichier sur votre machine client avec l'option LOCAL, le serveur ne peut pas interrompre la transmission du fichier au milieu de l'opération : par défaut, il utilisera l'option IGNORE.

Si vous voulez ignorer les clés étrangères le temps du chargement du fichier, utilisez la commande SET FOREIGN_KEY_CHECKS=0 avant d'exécuter LOAD DATA.

Si vous utilisez LOAD DATA INFILE sur une table vide de type MyISAM, tous les index non uniques seront créés dans un processus séparé (tout comme REPAIR). Cela rend LOAD DATA INFILE beaucoup plus rapide si vous avez plusieurs index. Voir Section 5.7.3, « Utilisation de myisamchk pour la maintenance des tables et leur recouvrement ».

LOAD DATA INFILE est le complémentaire de SELECT ... INTO OUTFILE. Voir Section 13.1.7, « Syntaxe de SELECT ». Pour écrire des données depuis une table dans un fichier, utilisez SELECT ... INTO OUTFILE. Pour lire les données dans la table, utilisez LOAD DATA INFILE. La syntaxe des clauses FIELDS et LINES est la même pour les deux commandes. Ces deux clauses sont optionnelles, mais FIELDS doit précéder LINES, si les deux sont spécifiées.

Si vous spécifiez la clause FIELDS, les sous-clauses TERMINATED BY, [OPTIONALLY] ENCLOSED BY, et ESCAPED BY sont aussi optionnelles, mais vous devez en spécifier au moins une.

Si vous ne spécifiez pas de clause FIELDS, les valeurs par défaut sont :

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

Si vous ne spécifiez pas de clause LINES, les valeurs par défaut sont :

LINES TERMINATED BY '\n'

En d'autres termes, les valeurs par défaut font que LOAD DATA INFILE lit les données comme suit.

- Recherche des limites de lignes parmi les nouvelles lignes.

- Si LINES STARTING BY prefix est utilisé, lit jusqu'au préfixe, et commence à lire après le préfixe. Si la ligne n'inclut pas de préfixe, elle sera ignorée.

- Scinde les lignes en champs avec les tabulations.

- Ne suppose pas que les champs sont entourés de guillemets.

- Interprète les occurrences de tabulation, nouvelle ligne, ''\'' précédées par ''\'' comme des caractères littéraux qui font partie de la valeur d'un champ.

À l'inverse, les valeurs par défaut font que SELECT ... INTO OUTFILE écrit les données comme ceci :

- Écriture des tabulations entre les champs ;

- Les champs ne sont pas entourés de guillemets ;

- Utilisation de '\' pour échapper les occurrences de tabulation, nouvelle ligne, et '\' trouvées dans les valeurs ;

- Insertion d'une nouvelle ligne entre les lignes.

Notez que pour utiliser FIELDS ESCAPED BY '\\', vous devez spécifier deux antislashes pour que cette valeur soit interprétée comme un antislash simple.

Note : si vous avez généré le fichier sur Windows, vous devrez peut-être utiliser LINES TERMINATED BY '\r\n' pour lire le fichier correctement, car les programmes Windows utilisent généralement deux caractères comme fin de ligne. Certains programmes, comme WordPad, peuvent utiliser \r comme terminateur de ligne lors de l'écriture. Pour lire ces fichiers, utilisez LINES TERMINATED BY '\r.

L'option IGNORE nombre LINES sert à ignorer un en-tête de fichier, telle que des noms de colonnes, qui débutent parfois un fichier à charger :

mysql> LOAD DATA INFILE "/tmp/nom_fichier" INTO TABLE test IGNORE 1 LINES;

Lorsque vous utilisez SELECT ... INTO OUTFILE conjointement avec LOAD DATA INFILE pour écrire des données dans un fichier et les relire dans une table, les options de FIELDS et LINES doivent être identiques. Sinon, LOAD DATA INFILE ne pourra pas interpréter le contenu du fichier correctement. Supposez que la commande SELECT ... INTO OUTFILE a écrit un fichier délimité par des virgules :

mysql> SELECT * INTO OUTFILE 'donnees.txt'
->          FIELDS TERMINATED BY ','
->          FROM ...;

Pour lire ce fichier, la commande correcte serait :

mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE table2
->           FIELDS TERMINATED BY ',';

Si au contraire, vous essayez de lire le fichier avec la commande ci-dessous, cela ne fonctionnera pas, car la commande LOAD DATA INFILE essaie de lire des tabulations entre les champs :

mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE table2
->           FIELDS TERMINATED BY '\t';

Il est probable que chaque ligne d'entrée ne sera interprétée que comme un seul champ.

La commande LOAD DATA INFILE peut être utilisée pour lire des données issues d'autres sources. Par exemple, un fichier au format dBASE présente des champs séparés par des virgules, et entourés de guillemets doubles. Si les lignes sont terminées par de nouvelles lignes, la commande ci-dessous illustre la relecture d'un tel fichier avec MySQL :

mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE nom_de_table
->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
->           LINES TERMINATED BY '\n';

Les clauses FIELDS et LINES peuvent prendre des chaînes vides comme valeur. S'il la chaîne n'est pas vide, FIELDS [OPTIONALLY] ENCLOSED BY et FIELDS ESCAPED BY ne doivent avoir qu'un seul caractère. Les valeurs de FIELDS TERMINATED BY et LINES TERMINATED BY peuvent avoir plus d'un caractère. Par exemple, pour écrire des lignes terminées par le couple retour chariot/nouvelle ligne, ou pour lire un tel fichier, spécifiez la clause LINES TERMINATED BY '\r\n'.

Par exemple, pour charger un fichier de blagues, qui sont séparées par une ligne de %%, dans une table vous pouvez faire :

CREATE TABLE blagues (
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
blague TEXT NOT NULL
);
LOAD DATA INFILE "/tmp/blagues.txt" INTO TABLE blagues FIELDS TERMINATED BY ""
LINES TERMINATED BY "\n%%\n" (blague);

FIELDS [OPTIONALLY] ENCLOSED BY contrôle la mise entre guillemets des champs. Pour l'écriture de fichier (SELECT ... INTO OUTFILE), si vous omettez le mot OPTIONALLY, tous les champs seront entourés par le caractère spécifié dans la clause ENCLOSED BY. Par exemple, si la virgule est utilisée comme séparateur de champs :

"1","une chaîne","100.20"
"2","une chaîne contenant une , virgule","102.20"
"3","une chaîne contenant un \" guillemet","102.20"
"4","une chaîne contenant un \", guillemet et une virgule","102.20"

Si vous spécifiez OPTIONALLY, le caractère ENCLOSED BY n'est utilisé que pour protéger les colonnes de types CHAR et VARCHAR :

1,"une chaîne",100.20
2,"une chaîne contenant une , virgule",102.20
3,"une chaîne contenant un \" guillemet",102.20
4,"une chaîne contenant un \", guillemet et une virgule",102.20

Notez que les occurrences du caractère ENCLOSED BY dans un champ sont échappées en les préfixant avec le caractère ESCAPED BY. Notez aussi que si vous spécifiez un caractère d'échappement vide, il n'est pas possible de garantir que les champs seront correctement relus par LOAD DATA INFILE. L'exemple ci-dessus apparaîtra comme montré ci-dessous. Notez que le second champ de la quatrième ligne comporte une virgule suivant un guillemet qui semble (mais c'est faux) terminer la ligne :

1,"une chaîne",100.20
2,"une chaîne contenant une , virgule",102.20
3,"une chaîne contenant un " guillemet",102.20
4,"une chaîne contenant un ", guillemet et une virgule",102.20

Lors des lectures, le caractère ENCLOSED BY, s'il est présent, est supprimé des extrémités de la valeur du champ. (Ce qui est vrai, qu'il y ait l'option OPTIONALLY ou pas). Les occurrences du caractère ENCLOSED BY, précédées par le caractère ESCAPED BY sont interprétées comme faisant partie de la valeur du champ. Les caractères ENCLOSED BY doublés, apparaissant dans la chaîne, sont interprétés comme le caractère ENCLOSED BY lui-même. Par exemple, si ENCLOSED BY '"' est spécifié, les guillemets sont gérés comme ceci :

"Le ""GRAND"" chef"  -> Le "GRAND" chef
Le "GRAND" chef      -> Le "GRAND" chef
Le ""GRAND"" chef    -> Le ""GRAND"" chef

FIELDS ESCAPED BY contrôle les caractères spéciaux. Si le caractère FIELDS ESCAPED BY n'est pas vide, il est utilisé pour préfixer les caractères suivants en écriture :

- le caractère FIELDS ESCAPED BY ;

- le caractère FIELDS [OPTIONALLY] ENCLOSED BY ;

- le premier caractère des valeurs de FIELDS TERMINATED BY et LINES TERMINATED BY ;

- ASCII 0 (en fait, ce qui est écrit après le caractère d'échappement est le caractère ASCII '0', et non pas le code ASCII de zéro).

Si le caractère FIELDS ESCAPED BY est vide, aucun caractère ne sera échappé. Ce n'est probablement pas une bonne idée de spécifier un caractère d'échappement vide, en particulier si les valeurs dans vos champs risquent d'utiliser l'un des caractères de la liste ci-dessus.

En lecture, si le caractère FIELDS ESCAPED BY n'est pas vide, les occurrences de ce caractère sont supprimées, et le caractère suivant est lu littéralement. Les exceptions à cette règle sont '0' ou 'N' (par exemple, 0 ou \N si le caractère d'échappement est '\'). Ces séquences sont interprétées comme l'octet nul (ASCII 0) et la valeur NULL. Voyez plus bas pour la gestion des valeurs NULL.

Pour plus d'informations sur la syntaxe avec les caractères d'échappement '\', consultez Section 9.1, « Littéraux : comment écrire les chaînes et les nombres ».

Dans certains cas, les options de FIELDS et LINES interfèrent entre elles.

- Si le caractère de LINES TERMINATED BY est une chaîne vide et que celui de FIELDS TERMINATED BY ne l'est pas, ce dernier sera celui utilisé pour LINES TERMINATED BY.

- Si les valeurs FIELDS TERMINATED BY et FIELDS ENCLOSED BY sont vides toutes les deux (''), un format à taille de champ fixe est utilisé. Avec ce format, aucun délimiteur n'est utilisé entre les champs. Au lieu de cela, les valeurs des colonnes sont écrites avec leur configuration d'affichage. Par exemple, si une colonne a été déclarée INT(7), la valeur de cette colonne sera écrite avec 7 caractères. Lors de la relecture, la valeur de la colonne sera obtenue en lisant à nouveau 7 caractères. Ce format à taille fixe affecte la gestion de la valeur NULL; voyez plus loin pour cela. Notez que ce format ne fonctionne pas avec les jeux de caractères multioctets.

La gestion des valeurs NULL dépend des options FIELDS et LINES que vous utilisez.

- Pour les valeurs par défaut de FIELDS et LINES, NULL est écrit \N et \N est lu NULL (en supposant que le caractère d'échappement est '\').

- Si FIELDS ENCLOSED BY n'est pas vide, un champ contenant le mot NULL comme valeur sera lu comme la valeur NULL (ce qui diffère du mot NULL, entouré du caractère FIELDS ENCLOSED BY, qui sera lu comme le mot 'NULL').

- Si FIELDS ESCAPED BY est vide, NULL est écrit comme le mot 'NULL'.

- Avec le format à taille fixe (ce qui arrive si FIELDS TERMINATED BY et FIELDS ENCLOSED BY sont tous les deux vides), les valeurs NULL sont écrites sous forme de chaîne vide. Notez que cela fait que NULL et les chaînes vides seront représentées par une valeur qui ne les distingue pas l'une de l'autre. Si vous avez besoin de différencier entre les deux, n'utilisez par ce format !

Certains cas ne sont pas supportés par LOAD DATA INFILE.

- Lignes à tailles fixes (FIELDS TERMINATED BY et FIELDS ENCLOSED BY sont tous les deux vides) et les types de colonnes BLOB ou TEXT.

- Si vous spécifiez un séparateur qui est le même qu'un autre préfixe, LOAD DATA INFILE ne sera pas capable de relire proprement le résultat. Par exemple, la clause FIELDS suivante posera sûrement des problèmes :

FIELDS TERMINATED BY '"' ENCLOSED BY '"'

- Si FIELDS ESCAPED BY est vide, une valeur de colonne qui contient une occurrence de FIELDS ENCLOSED BY ou de LINES TERMINATED BY suivi du caractère FIELDS TERMINATED BY interrompra la lecture de LOAD DATA INFILE trop tôt. Cela est dû au fait que LOAD DATA INFILE ne peut pas faire la différence entre la valeur dans le champ et la fin de la ligne.

L'exemple suivant charge toutes les colonnes de la table persondata :

mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Aucun champ n'est spécifié, ce qui fait que LOAD DATA INFILE s'attend à ce que les lignes lues contiennent le bon nombre de champs. Les valeurs par défaut de FIELDS et LINES sont utilisées.

Si vous voulez charger uniquement quelques colonnes dans une table, spécifiez la liste des champs :

mysql> LOAD DATA INFILE 'persondata.txt'
->           INTO TABLE persondata (col1,col2,...);

Vous devez aussi spécifier les champs si l'ordre dans lequel ils seront lus diffère de l'ordre des colonnes dans la table. Sinon, MySQL ne pourra pas savoir à quelle colonne correspond une valeur.

Si une ligne a trop peu de champs, les colonnes omises prendront leur valeur par défaut. Les affectations de valeurs par défaut sont décrites dans Section 13.2.5, « Syntaxe de CREATE TABLE ».

Une valeur de champ vide et un champ manquant ne seront pas interprétés de la même façon.

- Pour les types chaîne, la colonne est remplie avec la chaîne vide.

- Pour les types numériques, la colonne est mise à 0.

- Pour les types dates et heures, la colonne est mise au zéro approprié pour le type. Voir Section 11.3, « Les types date et heure ».

Notez que vous obtiendrez le même résultat en assignant à ces différents types de champs la chaîne vide dans une commande INSERT ou UPDATE.

Les colonnes TIMESTAMP prendront la date et l'heure courante uniquement si on leur affecte la valeur NULL, ou (pour la première colonne TIMESTAMP seulement) si la colonne TIMESTAMP est ignorée de la liste des colonnes spécifiée.

Si une ligne d'entrée comporte trop de colonnes, les champs en trop sont ignorés, et le nombre d'alertes est incrémenté.

LOAD DATA INFILE considère toutes les valeurs lues comme des chaînes de caractères : vous ne pourrez donc pas utiliser la forme numérique des colonnes ENUM ou SET, comme d'habitude. Toutes les colonnes ENUM et SET doivent être spécifiées comme des chaînes ! Si vous utilisez l'API C, vous pouvez obtenir des informations à propos de la requête en utilisant la fonction mysql_info() quand LOAD DATA INFILE se termine. Le format de la chaîne d'informations est le suivant :

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Les alertes sont générées dans les mêmes circonstances que pour la commande INSERT (voir Section 13.1.4, « Syntaxe de INSERT »), excepté que LOAD DATA INFILE génère aussi des alertes s'il y a trop peu ou trop de champs dans une ligne. Les alertes ne sont pas stockées ; le nombre d'alertes est la seule indication. Si vous recevez des alertes et vous voulez savoir exactement ce qui s'est passé, exécutez une commande SELECT ... INTO OUTFILE dans un autre fichier et comparez-le avec le fichier original.

En MySQL version 4.1.1 vous pouvez utiliser SHOW WARNINGS pour obtenir la liste des premières max_error_count alertes. Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

Pour plus d'informations sur les performances de INSERT comparées à LOAD DATA INFILE et accélérer LOAD DATA INFILE : voir Section 7.2.14, « Vitesse des requêtes INSERT ».

13-1-6 - Syntaxe de REPLACE

REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...

ou :

REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...

ou :

REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
SELECT ...

REPLACE fonctionne exactement comme INSERT, sauf que si une vieille ligne dans la table à la même valeur qu'une nouvelle pour un index UNIQUE ou une PRIMARY KEY, la vielle ligne sera effacée avant que la nouvelle ne soit insérée. Voir Section 13.1.4, « Syntaxe de INSERT ».

En d'autres termes, vous ne pouvez pas accéder aux valeurs de l'ancienne ligne à partir d'une requête REPLACE. Dans quelques vieilles versions de MySQL, il apparaît que c'était possible, mais c'était un dysfonctionnement qui a été corrigé depuis.

Pour utiliser REPLACE vous devez avoir les privilèges INSERT et DELETE sur la table.

Quand vous utilisez une commande REPLACE, mysql_affected_rows() retournera 2 si une nouvelle ligne en remplace une existante, et cela parce qu'il y aura eu une insertion puis une suppression.

Cela aide à savoir si REPLACE a ajouté ou a remplacé une ligne : testez si le nombre de lignes affectées est égal à 1 (ajout) ou s'il est égal à 2 (remplacement).

Notez que si vous n'utilisez pas un index UNIQUE ou une PRIMARY KEY, utiliser un REPLACE n'a pas de sens vu que cela revient à utiliser un INSERT. Il devient équivalent à INSERT, car il n'y a pas d'index à utiliser pour déterminer si une nouvelle ligne est un double d'une autre.

Voici quelques détails sur l'algorithme utilisé : Il est aussi utilisé par LOAD DATA ... REPLACE.

1. Insertion de la ligne dans la table.

2. Si une erreur de clé dupliquée ou de clé unique ou de clé primaire survient :

1. annuler les changements de clés ;

2. essayer à nouveau d'insérer la clé primaire et unique dans la table.

13-1-7 - Syntaxe de SELECT

SELECT [STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
[DISTINCT | DISTINCTROW | ALL]
select_expression,...
[INTO {OUTFILE | DUMPFILE} 'nom_fichier' export_options]
[FROM table_references
[WHERE where_definition]
[GROUP BY {unsigned_integer | nom_de_colonne | formula} [ASC | DESC], ...
[HAVING where_definition]
[ORDER BY {unsigned_integer | nom_de_colonne | formula} [ASC | DESC] ,...]
[LIMIT [offset,] lignes]
[PROCEDURE procedure_name(argument_list)]
[FOR UPDATE | LOCK IN SHARE MODE]]

SELECT est utilisé pour obtenir des enregistrements venant d'une ou plusieurs tables. Le support des commandes UNION et des sous-requêtes est disponible depuis MySQL 4.0 et 4.1, respectivement. Voir Section 13.1.7.2, « Syntaxe de UNION » et Section 13.1.8, « Sous-sélections (SubSELECT) ».

- Chaque select_expr indique une colonne à lire.

- table_references indique la ou les tables à utiliser. La syntaxe est décrite dans Section 13.1.7.1, « Syntaxe de JOIN ».

- where_definition indique les conditions auxquelles les lignes sélectionnées doivent satisfaire.

SELECT peut aussi être utilisée pour lire des lignes calculées, sans référence à une table.

Par exemple :

mysql> SELECT 1 + 1;
-> 2

Tous les mots-clés utilisés doivent être donnés exactement dans le même ordre que ci-dessus. Par exemple, une clause HAVING doit être placée après toute clause GROUP BY et avant toute clause ORDER BY.

- Une expression SELECT peut recevoir un alias en utilisant AS. L'alias est utilisé de la même façon que le nom du champ et peut être employé avec des clauses ORDER BY ou HAVING. Par exemple :

mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
FROM mytable ORDER BY full_name;

Le mot-clé AS est optionnel lors de la création d'un alias pour une expression SELECT. L'exemple précédent aurait pu être écrit comme ceci :

mysql> SELECT CONCAT(last_name,', ',first_name) full_name
FROM mytable ORDER BY full_name;

Comme AS est optionnel, un problème subtil peut survenir si vous oubliez une virgule entre deux expressions de SELECT : MySQL va interpréter la seconde comme un alias de la première. Par exemple, dans la commande suivante, columnb est traité comme un nom d'alias :

mysql> SELECT columna columnb FROM mytable;

- Il n'est pas possible d'utiliser un alias de champ dans une clause WHERE, car la valeur du champ peut ne pas être définie lorsque la clause WHERE est exécutée. Voir Section A.5.4, « Problèmes avec les alias ».

- La clause FROM table_references indique les tables à partir desquelles nous allons obtenir les enregistrements. Si vous indiquez le nom de plusieurs tables, vous faites une jointure. Pour davantage d'informations sur la syntaxe des jointures, consultez Section 13.1.7.1, « Syntaxe de JOIN ». Pour chaque table spécifiée, vous pouvez éventuellement indiquer un alias.

tbl_name [[AS] alias]
[[USE INDEX (key_list)]
| [IGNORE INDEX (key_list)]
| [FORCE INDEX (key_list)]]

L'utilisation de USE INDEX, IGNORE INDEX, FORCE INDEX pour donner des conseils d'optimisation à l'optimiseur d'index. Section 13.1.7.1, « Syntaxe de JOIN ».

En MySQL 4.0.14, vous pouvez utiliser SET MAX_SEEKS_FOR_KEY=value comme une autre solution pour forcer MySQL à choisir un scan d'index, plutôt qu'un scan de table.

- Vous pouvez faire référence à une table avec nom_de_table (au sein de la base de données courante), ou avec dbname.nom_de_table pour expliciter le nom de la base de données. Vous pouvez vous référer à un champ avec nom_de_colonne, nom_de_table.nom_de_colonne, ou db_name.nom_de_table.nom_de_colonne. Vous n'êtes pas obligé d'indiquer de préfixe nom_de_table ou db_name.nom_de_table pour une référence à un champ dans un SELECT, à moins que la référence ne soit ambigüe. Consultez Section 9.2, « Noms de bases, tables, index, colonnes et alias », pour des exemples d'ambiguïtés qui nécessitent des formes plus explicites de référence à des champs.

- Depuis la version 4.1.0, vous êtes autorisé à spécifier DUAL comme nom de table, dans les situations où aucune table n'est référencée. C'est une fonctionnalité pure de compatibilité, car certains autres serveurs requièrent cette syntaxe.

mysql> SELECT 1 + 1 FROM DUAL;
-> 2

- Une référence à une table peut être « aliasée » en utilisant nom_de_table [AS] alias_name :

mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
->        WHERE t1.name = t2.name;
mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
->        WHERE t1.name = t2.name;

- Dans la clause WHERE, vous pouvez utiliser toutes les fonctions que MySQL supporte, hormis les fonctions d'agrégation. Voir Chapitre 12, Fonctions à utiliser dans les clauses SELECT et WHERE.

- Les colonnes sélectionnées dans le résultat peuvent être nommées dans les clauses ORDER BY et GROUP BY en utilisant leur nom de colonne, les alias ou leur position de colonne. Les positions commencent à 1 :

mysql> SELECT college, region, seed FROM tournament
->        ORDER BY region, seed;
mysql> SELECT college, region AS r, seed AS s FROM tournament
->        ORDER BY r, s;
mysql> SELECT college, region, seed FROM tournament
->        ORDER BY 2, 3;

Pour trier dans l'ordre inverse, ajoutez le mot-clé DESC (descendant) au nom du champ dans la clause ORDER BY qui vous permet de trier. Par défaut, l'ordre ascendant est utilisé; ceci peut être indiqué de façon explicite en utilisant le mot-clé ASC.

L'utilisation des positions de colonnes est obsolète, car la syntaxe a été supprimée du SQL standard.

- Si vous utilisez GROUP BY, les lignes sont triées en fonction des colonnes GROUP BY comme si on avait ajouté la clause ORDER BY pour ces colonnes. MySQL a amélioré la clause GROUP BY depuis la version 3.23.34 pour que vous puissiez aussi spécifier ASC et DESC après le nom de la colonne :

SELECT a, COUNT(b) FROM test_table GROUP BY a DESC

- MySQL améliore l'utilisation de GROUP BY en vous autorisant à l'utiliser avec des champs qui ne sont pas mentionnés dans la clause GROUP BY. Si vous n'obtenez pas les résultats que vous attendiez, lisez la description de GROUP BY. Voir Section 12.9, « Fonctions et options à utiliser dans les clauses GROUP BY ».

- Depuis MySQL 4.1.1, GROUP BY dispose de l'option WITH ROLLUP. Voir Section 12.9.2, « Options de GROUP BY ».

- La clause HAVING peut faire référence à n'importe quel champ ou alias définis dans select_expr. C'est évalué en dernier lieu, juste avant que les éléments ne soient envoyés au client, sans aucune optimisation.

- N'utilisez pas HAVING pour des éléments qui devraient être dans la clause WHERE. Par exemple, n'écrivez pas ceci :

mysql> SELECT nom_de_colonne FROM nom_de_table HAVING nom_de_colonne > 0;

Écrivez plutôt cela :

mysql> SELECT nom_de_colonne FROM nom_de_table WHERE nom_de_colonne > 0;

Dans les versions 3.22.5 et supérieures de MySQL, vous pouvez aussi écrire des requêtes ainsi :

mysql> SELECT user,MAX(salary) FROM users
->        GROUP BY user HAVING MAX(salary)>10;

Dans des versions plus anciennes de MySQL, vous pouvez écrire à la place :

mysql> SELECT user,MAX(salary) AS sum FROM users
->        group by user HAVING sum>10;

- La clause HAVING peut utiliser des fonctions d'agrégation, alors que la clause WHERE ne le peut pas :

mysql> SELECT user, MAX(salary) FROM users
->     GROUP BY user HAVING MAX(salary)>10;

Cependant, cela ne fonctionne pas dans les anciennes versions du serveur MySQL : avant la version 3.22.5. Au lieu de cela, ajoutez un alias de colonne dans la liste de colonnes, et faites référence à cet alias dans la colonne HAVING :

mysql> SELECT user, MAX(salary) AS max_salary FROM users
->     GROUP BY user HAVING max_salary>10;

- La clause LIMIT peut être utilisée pour limiter le nombre d'enregistrements retournés par la commande SELECT. LIMIT accepte un ou deux arguments numériques. Ces arguments doivent être des entiers constants.

Avec un argument, la valeur spécifie le nombre de lignes à retourner depuis le début du jeu de résultat. Si deux arguments sont donnés, le premier indique le décalage du premier enregistrement à retourner, le second donne le nombre maximum d'enregistrements à retourner. Le décalage du premier enregistrement est 0 (pas 1).

Pour être compatible avec PostgreSQL, MySQL supporte aussi la syntaxe : LIMIT row_count OFFSET offset.

mysql> SELECT * FROM table LIMIT 5,10;  # Retourne les enregistrements 6 à 15

Pour obtenir tous les enregistrements d'un certain décalage jusqu'à la fin du résultat, vous pouvez utiliser de grands entiers en tant que second paramètre :

mysql> SELECT * FROM table LIMIT 95,18446744073709551615; # Retourne les enregistrements de 96 jusqu'au dernier.

Si un seul argument est donné, il indique le nombre maximum d'enregistrements à retourner :

mysql> SELECT * FROM table LIMIT 5;     # Retourne les 5 premiers enregistrements

Autrement dit, LIMIT n est équivalent à LIMIT 0,n.

- La forme SELECT ... INTO OUTFILE 'nom_fichier' de SELECT écrit les lignes sélectionnées dans un fichier. Le fichier est créé sur le serveur et ne peut y être déjà présent (cela permet entre autres d'éviter la destruction des tables et de fichiers tels que /etc/passwd). Vous devez avoir le droit FILE sur le serveur pour utiliser cette forme de SELECT.

SELECT ... INTO OUTFILE a pour but principal de vous permettre de réaliser des dumps rapides des tables sur la machine serveur. Si vous voulez créer le fichier sur une autre machine, vous ne pouvez utiliser SELECT ... INTO OUTFILE. Dans ce cas-là, vous pouvez utiliser à la place un programme client comme mysqldump --tab ou mysql -e "SELECT ..." > fichier pour générer le fichier.

SELECT ... INTO OUTFILE est le complément de LOAD DATA INFILE. La syntaxe pour la partie export_options de la requête se compose des mêmes clauses FIELDS et LINES que celles utilisées avec la commande LOAD DATA INFILE. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

Dans le fichier résultant, seuls les caractères suivants sont protégés par le caractère ESCAPED BY :

- le caractère ESCAPED BY ;

- les premiers caractères de FIELDS TERMINATED BY ;

- les premiers caractères de LINES TERMINATED BY ;

- ASCII 0 est converti en ESCAPED BY suivi de 0 (ASCII 48).

Si le caractère FIELDS ESCAPED BY est vide, aucun caractère n'est protégé, et NULL vaut NULL, et non \N. Il est probable que ce ne soit pas une bonne idée de spécifier un caractère de protection vide, en particulier si les valeurs de vos champs peuvent être n'importe quoi.

La raison de ce qui précède est que vous devez impérativement protéger chaque caractère FIELDS TERMINATED BY, ESCAPED BY, ou LINES TERMINATED BY pour assurer une relecture fiable du fichier. Le caractère ASCII 0 est échappé pour assurer la lisibilité sur certains clients.

Comme le fichier résultant ne se doit pas d'être syntaxiquement conforme à SQL, vous n'avez pas besoin d'échapper autre chose.

Voici un exemple de relecture de fichier au format utilisé par plusieurs anciens programmes.

SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;

- Si vous utilisez INTO DUMPFILE au lieu de INTO OUTFILE, MySQL n'écrira qu'une seule ligne dans le fichier, sans aucun caractère de fin de ligne ou de colonne, ni d'échappement. Cela est utile lorsque vous voulez enregistrer un BLOB dans un fichier.

- Note : notez que les fichiers créés par INTO OUTFILE et INTO DUMPFILE seront lisibles par tous les utilisateurs ! La raison est que le serveur MySQL ne peut créer de fichier appartenant à autre que l'utilisateur qui l'a mis en route. (Vous devez éviter d'exécuter mysqld en tant que root.) Le fichier doit se composer de mots lisibles pour que les données puissent être récupérées.

- Une clause PROCEDURE indique une procédure qui doit traiter les lignes du jeu de résultat. Pour un exemple, voyez Section 27.3.1, « La procédure Analyse ».

- Si vous utilisez la clause FOR UPDATE avec un gestionnaire de tables qui gère les verrous de ligne ou de page, les lignes seront verrouillées.

Après le mot SELECT, vous pouvez ajouter certaines options qui affectent le comportement de la commande.

Les options DISTINCT, DISTINCTROW et ALL indiquent quels enregistrements avec doublons doivent être retournés. Par défaut, c'est (ALL), retournant ainsi tous les enregistrements. DISTINCT et DISTINCTROW sont synonymes et indiquent que les doublons doivent être éliminés du résultat.

HIGH_PRIORITY, STRAIGHT_JOIN, et les options commençant par SQL_ sont des extensions MySQL au standard SQL.

- HIGH_PRIORITY donne à une commande SELECT une plus grande priorité qu'une commande qui modifie une table. Vous devez l'utiliser seulement pour les requêtes qui sont très rapides et qui doivent être effectuées en premier lieu. Une requête SELECT HIGH_PRIORITY s'exécutera sur une table verrouillée en lecture même si une commande de mise à jour attend que la table soit libérée.

HIGH_PRIORITY ne peut être utilisée avec les commandes SELECT qui font partie d'une UNION.

- STRAIGHT_JOIN force l'optimiseur à joindre les tables dans l'ordre dans lequel elles sont listées dans la clause FROM. Vous pouvez utiliser cela pour accélérer la requête, si les tables sont réordonnées sub-optimalement par l'optimiseur. Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) ». STRAIGHT_JOIN peut aussi être utilisée dans la liste table_references. Voir Section 13.1.7.1, « Syntaxe de JOIN ».

- SQL_BIG_RESULT peut être utilisé avec GROUP BY ou DISTINCT pour indiquer à l'optimiseur que le résultat comportera beaucoup d'enregistrements. Dans ce cas, MySQL utilisera si besoin directement les bases temporaires stockées sur le disque. MySQL préférera, dans ce cas, trier que d'obtenir une table temporaire avec une clé sur les éléments du GROUP BY.

- SQL_BUFFER_RESULT forcera le résultat à être stocké dans une table temporaire. Ceci va aider MySQL à libérer plus tôt les verrous des tables et aidera aussi dans les cas ou l'envoi du résultat au client prend un temps assez important.

- SQL_SMALL_RESULT, une option spécifique à MySQL, peut être utilisée avec GROUP BY ou DISTINCT pour indiquer à l'optimiseur que le résultat sera petit. Dans ce cas, MySQL utilise des tables temporaires rapides pour stocker la table résultante plutôt que d'utiliser le tri. Dans MySQL 3.23, ceci n'est normalement pas nécessaire.

- SQL_CALC_FOUND_ROWS (version 4.0.0 et supérieures) indique à MySQL de calculer combien d'enregistrements seront dans le jeu de résultats, indépendamment de n'importe quelle clause LIMIT. Le nombre d'enregistrements peut alors être obtenu avec SELECT FOUND_ROWS(). Voir Section 12.8.4, « Fonctions diverses ».

Avant MySQL 4.1.0, cette option ne fonctionne pas avec LIMIT 0, qui est optimisée pour se terminer instantanément (le résultat ne contiendra pas de ligne). Voir Section 7.2.12, « Comment MySQL optimise LIMIT ».

- SQL_CACHE demande à MySQL de ne pas stocker le résultat de la requête si vous utilisez query_cache_type avec la valeur 2 ou DEMAND. Pour une requête qui utilise UNION ou une sous-requête, cette option prend effet si elle est utilisée dans n'importe quelle partie de la requête SELECT. Voir Section 5.11, « Cache de requêtes MySQL ».

- SQL_CACHE indique à MySQL de stocker le résultat de la requête dans le cache de requêtes si vous utilisez QUERY_CACHE_TYPE=2 (DEMAND). Voir Section 5.11, « Cache de requêtes MySQL ». Pour les requêtes qui utilisent UNION ou les sous-requêtes, cette option aura un effet sur toutes les parties de la requête SELECT.

13-1-7-1 - Syntaxe de JOIN

MySQL supporte les syntaxes suivantes de JOIN pour une utilisation dans les SELECT :

reference_table, reference_table
reference_table [CROSS] JOIN reference_table
reference_table INNER JOIN reference_table condition_jointure
reference_table STRAIGHT_JOIN reference_table
reference_table LEFT [OUTER] JOIN reference_table condition_jointure
reference_table LEFT [OUTER] JOIN reference_table
reference_table NATURAL [LEFT [OUTER]] JOIN reference_table
{ OJ reference_table LEFT OUTER JOIN reference_table ON expr_conditionnelle }
reference_table RIGHT [OUTER] JOIN reference_table condition_jointure
reference_table RIGHT [OUTER] JOIN reference_table
reference_table NATURAL [RIGHT [OUTER]] JOIN reference_table

où reference_table est définie de la manière suivante :

nom_de_table [[AS] alias] [USE INDEX (liste_de_cles)] [IGNORE INDEX (liste_de_cles)]

et condition_jointure est définie comme suit :

ON expr_conditionnelle |
USING (column_list)

Généralement, vous ne devez avoir aucune condition, dans la partie ON, qui soit utilisée pour spécifier les lignes que vous voulez obtenir en résultat. (Il y a des exceptions à cette règle.) Si vous voulez restreindre les lignes résultantes, vous devez le faire dans la clause WHERE.

Notez que dans les versions antérieures à la 3.23.17, INNER JOIN ne prenait pas en compte condition_jointure !

La dernière syntaxe de LEFT OUTER JOIN vue plus haut, n'existe que pour assurer la compatibilité avec ODBC.

- On peut créer un alias sur une référence de table en utilisant nom_de_table AS alias_name ou nom_de_table alias_name :

mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
->        WHERE t1.name = t2.name;

- La condition ON est de la même forme qu'une condition pouvant être utilisée dans la clause WHERE.

- Si aucune ligne ne correspond dans la table de droite dans la partie ON ou USING du LEFT JOIN, une ligne avec toutes les colonnes mises à NULL est utilisé en remplacement. Vous pouvez utiliser ce fait pour trouver les enregistrements dans une table qui n'ont pas de correspondances dans une autre :

mysql> SELECT table1.* FROM table1
->        LEFT JOIN table2 ON table1.id=table2.id
->        WHERE table2.id IS NULL;

Cet exemple retourne toutes les lignes trouvées dans table1 avec une valeur de id qui n'est pas présente dans table2 (autrement dit, toutes les lignes de table1 sans correspondance dans la table table2). Cela demande que table2.id soit déclaré NOT NULL, bien sûr. Voir Section 7.2.9, « Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN ».

- La clause USING (column_list) recense la liste des colonnes qui doivent exister dans les deux tables. Les clauses USING suivantes sont identiques :

a LEFT JOIN b USING (c1,c2,c3)
a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3

- La jointure de deux tables avec NATURAL [LEFT] JOIN est définie pour être sémantiquement équivalente à un INNER JOIN ou un LEFT JOIN avec une clause USING qui nomme toutes les colonnes qui existent dans les deux tables.

- INNER JOIN et , (virgule) sont sémantiquement équivalents. Les deux opèrent une jointure totale sur les tables utilisées. Normalement, vous spécifiez les conditions de jointure dans la clause WHERE.

- RIGHT JOIN fonctionne de façon analogue à LEFT JOIN. Pour garder un code facilement portable, il est recommandé d'utiliser les LEFT JOIN à la place des RIGHT JOIN.

- STRAIGHT_JOIN est identique à JOIN, sauf que la table de gauche est toujours lue avant celle de droite. Cela peut être utilisé dans les cas (rares) où l'optimiseur des jointures place les tables dans le mauvais ordre.

À partir de la version 3.23.12 de MySQL, vous pouvez donner des indications à propos de l'index à utiliser lors de la lecture d'informations d'une table. C'est utile si EXPLAIN montre que MySQL utilise un mauvais index de la liste de ceux disponibles. En spécifiant USE INDEX (liste_de_cles), vous pouvez forcer MySQL à utiliser un index spécifique pour trouver les enregistrements dans la table. Une variante réside dans l'utilisation de IGNORE INDEX (liste_de_cles) pour dire à MySQL de ne pas utiliser certains index.

En MySQL 4.0.9, vous pouvez aussi utiliser la clause FORCE INDEX. Elle se comporte comme USE INDEX (key_list), mais en supposant que les scans de tables seront très coûteux. En d'autres termes, les scans de tables ne seront utilisés que s'il n'y a pas d'autres méthodes pour trouver les lignes.

USE/IGNORE KEY sont des synonymes de USE/IGNORE INDEX.

Note : USE INDEX, IGNORE INDEX et FORCE INDEX affectent uniquement les index qui sont utilisés lors du choix de la méthode de sélection des lignes dans la table, et comment faire une jointure. Elles n'affectent pas l'utilisation finale de l'index dans les clauses ORDER BY ou GROUP BY.

Quelques exemples :

mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
->          LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
->          WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
->          WHERE key1=1 AND key2=2 AND key3=3;

Voir Section 7.2.9, « Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN ».

13-1-7-2 - Syntaxe de UNION

SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]

UNION est implémentée en MySQL 4.0.0.

UNION est utilisé pour combiner le résultat de plusieurs requêtes SELECT en un seul résultat.

Les colonnes listées dans la partie select_expression du SELECT doivent être du même type. Les noms de colonnes utilisés dans le premier SELECT seront utilisés comme noms de champ pour les résultats retournés.

Les commandes SELECT sont des sélections normales, mais avec les restrictions suivantes.

- Seule la dernière commande SELECT peut avoir une clause INTO OUTFILE.

- HIGH_PRIORITY ne peut être utilisée avec les commandes SELECT qui ne font pas partie de l'UNION. Si vous la spécifiez pour la première commande SELECT, elle n'aura pas d'effet. Si vous la spécifiez pour toute autre commande SELECT suivante, une erreur de syntaxe sera signalée.

Si vous n'utilisez pas le mot-clé ALL pour l'UNION, toutes les lignes retournées seront uniques, comme si vous aviez fait un DISTINCT pour l'ensemble du résultat. Si vous spécifiez ALL, vous aurez alors tous les résultats retournés par toutes les commandes SELECT.

Si vous voulez utiliser un ORDER BY pour le résultat final de UNION, vous devez utiliser des parenthèses :

(SELECT a FROM nom_de_table WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM nom_de_table WHERE a=11 AND B=2 ORDER BY a LIMIT 10)
ORDER BY a;

Note : vous ne pouvez pas mélanger les clauses UNION ALL et UNION DISTINCT dans la même requête. Si vous utilisez ALL dans une des UNION, alors elle devra être utilisée partout.

Les types et longueurs des colonnes du jeu de résultat de UNION prend en compte les valeurs lues dans tous les SELECT. Avant MySQL 4.1.1, une limitation de UNION est que seules les valeurs du premier SELECT étaient utilisées pour déterminer le type de résultats, et leur taille. Cela peut conduire à un raccourcissement de la valeur si, par exemple, le second SELECT trouvait des valeurs plus grandes que le premier SELECT :

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| b             |
+---------------+

Cette limitation a été supprimée en MySQL version 4.1.1 :

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a             |
| bbbbbbbbbb    |
+---------------+

13-1-8 - Sous-sélections (SubSELECT)

Une sous-requête est une commande SELECT dans une autre commande. Par exemple :

SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);

La requête externe (ou commande externe), et (SELECT column1 FROM t2) est la sous-requête. Nous disons que la sous-requête est imbriquée dans la requête externe, et en fait, il est possible d'imbriquer des requêtes dans des sous-requêtes, avec d'autres commandes. Une sous-requête doit toujours être entre parenthèses.

Depuis la version 4.1, MySQL supporte toutes les formes de sous-requêtes et opérations que le standard SQL requiert, ainsi que quelques fonctionnalités spécifiques. Les avantages des sous-requêtes sont les suivantes.

- Elles permettent aux requêtes d'être structurées pour que chaque partie puisse être isolée.

- Elles fournissent une méthode pour réaliser des opérations qui seraient complexes, et impliqueraient des unions et jointures.

- Elles sont, au dire de nombreuses personnes, lisibles. En fait, c'est les sous-requêtes qui ont donné aux inventeurs le nom original de SQL « Structured Query Language ».

Dans les versions plus anciennes de MySQL, il fallait trouver des palliatifs, et contourner les sous-requêtes. Il est bien plus facile de se mettre aux sous-requêtes.

Voici un exemple de commande qui montre les principaux avantages des sous-requêtes et de leur syntaxe, aussi bien pour celle qui est proposée par le standard, que celle de MySQL.

DELETE FROM t1
WHERE s11 > ANY
(SELECT COUNT(*) /* no hint */ FROM t2
WHERE NOT EXISTS
(SELECT * FROM t3
WHERE ROW(5*t2.s1,77)=
(SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
(SELECT * FROM t5) AS t5)));

Pour les versions de MySQL antérieure à la version 4.1, la plupart des sous-requêtes peuvent être réécrites avec des jointures et d'autres méthodes. Voir Section 13.1.8.11, « Se passer des sous-requêtes avec les premières versions de MySQL ».

13-1-8-1 - Les sous-requêtes comme opérateur scalaire

Dans forme la plus simple, une sous-requête scalaire, par opposition à une sous-requête de ligne ou de table qui seront présentées plus loin, est un simple opérande. Vous pouvez l'utiliser à chaque fois qu'une valeur de colonne ou qu'une valeur littérale est valide, et vous pouvez en attendre les mêmes caractéristiques : type de données, taille et indication de nullité, etc. Par exemple :

CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
SELECT (SELECT s2 FROM t1);

La sous-requête de la commande SELECT ci-dessus est de type CHAR, de longueur 5. Son jeu de caractères et sa collation sont ceux fournis par défaut, et elle porte une marque de nullité. En fait, toutes les sous-requêtes peuvent prendre la valeur NULL, car si la table est vide, la valeur de la sous-requête sera alors NULL. Il y a quelques restrictions.

- Une sous-requête peut être utilisée avec les commandes suivantes : SELECT, INSERT, UPDATE, DELETE, SET et DO.

- Une sous-requête peut contenir les mots-clés et les clauses qu'une commande SELECT peut contenir : DISTINCT, GROUP BY, ORDER BY, LIMIT, jointures, UNION, commentaires, fonctions, etc.

Ainsi, lorsque vous lirez les exemples des sections suivantes qui utilisent la commande spartiate (SELECT column1 FROM t1), imaginez que votre code pourra contenir des commandes bien plus diverses et complexes.

Par exemple, supposons que nous avons ces deux tables :

CREATE TABLE t1 (s1 INT);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (s1 INT);
INSERT INTO t2 VALUES (2);

Puis, que vous envoyons la commande suivante SELECT :

SELECT (SELECT s1 FROM t2) FROM t1;

Le résultat sera 2, car il y a une ligne dans t2, dont la colonne s1 a une valeur de 2.

La sous-requête peut faire partie d'une expression. Si c'est un opérande d'une fonction, n'oubliez pas les parenthèses.

Par exemple :

SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

13-1-8-2 - Comparaisons avec les sous-requêtes

L'utilisation la plus répandue des sous-requêtes est celle-ci :

<non-subquery operand> <comparison operator> (<subquery>)

où <comparison operator> est l'un des opérateurs suivants :

= > < >= <= <>

Par exemple :

... 'a' = (SELECT column1 FROM t1)

Il fut un temps où la seule place possible pour une sous-requête était à la droite de l'opérateur de comparaison, mais vous pourrez rencontrer de vieilles bases qui insisteront sur ce point.

Voici un exemple de comparaison classique, pour lequel vous ne pouvez pas utiliser de jointure : trouvez toutes les valeurs de la table t1 qui sont égales au maximum de la valeur dans la table t2.

SELECT column1 FROM t1
WHERE column1 = (SELECT MAX(column2) FROM t2);

Voici un autre exemple, qui est aussi impossible à réaliser avec une jointure, car elle impose l'agrégation de plusieurs tables : trouver toutes les lignes de la table t1 qui contiennent une valeur qui apparaît deux fois.

SELECT * FROM t1
WHERE 2 = (SELECT COUNT(column1) FROM t1);

13-1-8-3 - Sous-requêtes avec les clauses ANY, IN et SOME

Syntaxe :

<operand> <comparison operator> ANY (<subquery>)
<operand> IN (<subquery>)
<operand> <comparison operator> SOME (<subquery>)

Le mot ANY, qui doit suivre immédiatement un opérateur de comparaison, signifie : « retourne TRUE si la comparaison est TRUE pour UNE des lignes que la sous-requête retourne. » Par exemple :

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

Supposons qu'il y ait une ligne dans la table t1 qui contienne {10}. L'expression est TRUE si la table t2 contient {21,14,7}, car il y a une valeur de t2, 7, qui est inférieure à 10. Cette expression est FALSE si la table t2 contient {20,10}, ou si la table t2 est vide. L'expression est UNKNOWN si la table t2 contient {NULL,NULL,NULL}.

Le mot IN est un alias de = ANY. Les deux commandes suivantes sont identiques :

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

Le mot SOME est un alias de ANY. Les deux commandes suivantes sont identiques :

SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

L'utilisation du mot SOME est rare, mais les exemples ci-dessus montrent pourquoi il peut être utile. En langage parlé, « a n'est pas égal à aucun b » signifie pour la majorité des gens, « il n'y a pas de b qui est égal à a » : ce n'est pas la signification de la syntaxe SQL. En utilisant <> SOME, vous pouvez vous assurer que tout le monde comprend le véritable sens de la commande.

13-1-8-4 - Sous-requêtes avec ALL

Syntaxe :

<operand> <comparison operator> ALL (<subquery>)

Le mot ALL, qui doit suivre immédiatement l'opérateur de comparaison, signifie « retourne TRUE si la comparaison est TRUE pour TOUTES les lignes que la sous-requête retourne ».

Par exemple :

SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

Supposons qu'il y ait une ligne dans la table t1 contenant {10}. L'expression est TRUE si la table t2 contient {-5,0,+5}, car les trois valeurs de t2 sont inférieures à 10. L'expression est FALSE si la table t2 contient {12,6,NULL,-100}, car il y a une des valeurs de la table t2, ici 12, qui est plus grande que 10. L'expression est UNKNOWN si la table t2 contient {0,NULL,1}.

Finalement, si la table t2 est vide, le résultat est TRUE. Vous pouvez penser que le résultat doit être indéterminé (UNKNOWN), mais c'est bien TRUE. Ce qui fait que, bizarrement,

SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

est TRUE si la table t2 est vide, mais

SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

est UNKNOWN si la table t2 est vide. De plus,

SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

est UNKNOWN si la table t2 est vide. En général, les tables avec des NULL et les tables vides sont des cas particuliers : lorsque vous écrivez vos sous-requêtes, pensez bien à les prendre en compte.

13-1-8-5 - Sous-requêtes de ligne

Jusqu'ici, nous avons étudié les sous-requêtes scalaires, ou de colonnes : des sous-requêtes qui retournent une seule valeur dans une ligne. Une sous-requête de ligne est une variante qui retourne une seule ligne : elle peut donc retourner plusieurs colonnes. Voici deux exemples :

SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

Les requêtes ci-dessus sont toutes les deux TRUE si la table t2 a une ligne où column1 = 1 et column2 = 2.

L'expression (1,2) est parfois appelée un constructeur de ligne et est valide dans d'autres contextes. Par exemple, les deux commandes suivantes sont sémantiquement équivalentes, même si la précédente peut être optimisée :

SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

L'utilisation traditionnelle des constructeurs de ligne est lors des comparaisons avec des sous-requêtes qui retournent plusieurs colonnes. Par exemple, cette requête répond à la question : « trouve toutes les lignes de la table t1 qui sont dupliquées dans la table t2 »:

SELECT column1,column2,column3
FROM t1
WHERE (column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2);

13-1-8-6 - EXISTS et NOT EXISTS

Si une sous-requête ne retourne absolument aucune valeur, alors la clause EXISTS <subquery> est TRUE, et la clause NOT EXISTS <subquery> est FALSE. Par exemple :

SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

Traditionnellement, une sous-requête qui EXISTS commence avec SELECT * mais elle peut commencer aussi bien avec SELECT 5 ou SELECT column1 ou n'importe quoi d'autre encore : MySQL ignore la liste de colonnes du SELECT de cette requête, ce qui fait que cela n'a pas d'importance.

Dans l'exemple ci-dessus, si la table t2 ne contient aucune ligne, même pas de ligne avec uniquement des valeurs NULL, alors la condition EXISTS est TRUE. C'est un exemple plutôt exceptionnel, car il y a presque toujours une sous-requête [NOT] EXISTS qui contiendra des corrélations. Voici des exemples plus concrets.

- Quel type de magasin est le plus fréquent dans une ou plusieurs villes ?

SELECT DISTINCT store_type FROM Stores
WHERE EXISTS (SELECT * FROM Cities_Stores
WHERE Cities_Stores.store_type = Stores.store_type);

- Quel type de magasin n'est présent dans aucune ville ?

SELECT DISTINCT store_type FROM Stores
WHERE NOT EXISTS (SELECT * FROM Cities_Stores
WHERE Cities_Stores.store_type = Stores.store_type);

- Quel type de magasin est présent dans toutes les villes ?

SELECT DISTINCT store_type FROM Stores S1
WHERE NOT EXISTS (
SELECT * FROM Cities WHERE NOT EXISTS (
SELECT * FROM Cities_Stores
WHERE Cities_Stores.city = Cities.city
AND Cities_Stores.store_type = Stores.store_type));

Le dernier exemple est une double imbrication de requête NOT EXISTS : elle possède une clause NOT EXISTS à l'intérieur de la clause NOT EXISTS. Formellement, elle répond à la question : « Existe-t-il une ville avec un magasin qui n'est pas dans Stores ? ». Mais il est plus facile de dire qu'une clause NOT EXISTS imbriquée répond à la question « est-ce que x est vrai pour tous les y ? ».

13-1-8-7 - Sous-requêtes corrélées

Une sous-requête corrélée est une sous-requête qui contient une référence à une colonne qui est aussi dans une requête différente.

Par exemple :

SELECT * FROM t1 WHERE column1 = ANY
(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

Notez que dans notre exemple, la sous-requête contient une référence à une colonne de la table t1, même si la sous-requête de la clause FROM ne mentionne pas la table t1. MySQL recherche hors de la requête et trouve t1 dans la requête externe.

Supposez que la table t1 contienne une ligne où column1 = 5 et column2 = 6; alors que la table t2 continue une ligne où column1 = 5 et column2 = 7. L'expression ... WHERE column1 = ANY (SELECT column1 FROM t2) sera alors TRUE, mais dans cet exemple, la clause WHERE de la sous-requête est FALSE (car 7 <> 5), et donc, toute la sous-requête est FALSE.

Règles de contexte : MySQL fait les évaluations de l'intérieur vers l'extérieur. Par exemple :

SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));

Dans l'exemple ci-dessus, x.column2 doit être une colonne de la table t2, car SELECT column1 FROM t2 AS x ... prend le nom de t2. Ce n'est pas une colonne de la table t1, car SELECT column1 FROM t1 ... est une requête externe, qui est à venir.

Pour les sous-requêtes placées dans des clauses HAVING ou ORDER BY, MySQL recherche aussi les noms de colonnes dans la liste des sélections externes.

Dans certains cas, les sous-requêtes corrélées sont optimisées. Par exemple :

val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

Sinon, elles sont inefficaces et plutôt lentes. Réécrire une requête sous forme de jointure peut améliorer les performances.

13-1-8-8 - Sous-requêtes dans la clause FROM

Les sous-requêtes sont valides dans la clause FROM d'une commande SELECT. Voici une syntaxe que vous allez rencontrer :

SELECT ... FROM (<subquery>) AS <name> ...

La clause AS <name> est obligatoire, car les tables de la clause FROM doivent avoir un nom. Toutes les colonnes de la sous-requête <subquery> doivent avoir des noms distincts. Vous pourrez trouver cette syntaxe décrite ailleurs dans ce manuel, sous le nom de « tables dérivées ».

Par exemple, supposons que vous avons cette table :

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

Comment utiliser la fonctionnalité de sous-requêtes dans la clause FROM, avec cette table d'exemple :

INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;

Résultat : 2, '2', 4.0.

Voici un autre exemple : supposons que vous voulez connaître la moyenne de la somme pour un groupe de table. Ceci ne fonctionnera pas :

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

Mais cette requête-ci vous donnera les informations nécessaires :

SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;

Notez que les colonnes sont nommées à partir de la sous-requête : (sum_column1) est reconnue dans la requête externe.

Actuellement, les sous-requêtes en clause FROM ne peuvent pas être corrélées.

13-1-8-9 - Erreurs de sous-requêtes

Il y a de nouvelles erreurs qui ne s'appliquent qu'aux sous-requêtes. Cette section les rassemble, car elles vous aideront à garder en tête certains points importants.

- ERROR 1235 (ER_NOT_SUPPORTED_YET)
SQLSTATE = 42000
Message = "This version of MySQL doesn't yet support
'LIMIT & IN/ALL/ANY/SOME subquery'"

Cela signifie que

SELECT * FROM t1 WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)

ne fonctionnera pas, mais uniquement dans certaines versions d'origine, comme MySQL 4.1.1.

- ERROR 1240 (ER_CARDINALITY_COL)
SQLSTATE = 21000
Message = "Operand should contain 1 column(s)"

Cette erreur va survient dans des cas comme celui-ci :

SELECT (SELECT column1, column2 FROM t2) FROM t1;

Il est valide d'utiliser une sous-requête qui utilise plusieurs colonnes, dans le cadre d'une comparaison. Voir Section 13.1.8.5, « Sous-requêtes de ligne ». Mais dans d'autres contextes, la sous-requête doit être un opérande scalaire.

- ERROR 1241 (ER_SUBSELECT_NO_1_ROW)
SQLSTATE = 21000
Message = "Subquery returns more than 1 row"

Cette erreur survient dans des cas comme celui-ci :

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

mais uniquement lorsque plus d'une ligne est extraite de t2. Cela signifie que cette erreur peut survenir dans du code qui fonctionne depuis longtemps : quelqu'un vient de modifier le nombre de lignes que la requête retourne. N'oubliez pas que si votre but est de trouver un nombre arbitraire de lignes, et non pas juste une seule, la commande correcte aurait été :

SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);

- Error 1093 (ER_UPDATE_TABLE_USED)
SQLSTATE = HY000
Message = "You can't specify target table 'x' for update in FROM clause"

Cette erreur survient dans des cas comme celui-ci :

UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);

Il est valide d'utiliser une sous-requête lors d'une affectation dans une commande UPDATE, car les sous-requêtes sont valides avec les commandes UPDATE et DELETE, tout comme dans les commandes SELECT. Cependant, vous ne pouvez pas les utiliser sur la même table, qui est ici t1, car cette table est alors la cible de la clause FROM et de la commande UPDATE.

Généralement, l'échec d'une sous-requête entraîne l'échec de toute la commande.

13-1-8-10 - Optimisation des sous-requêtes

Le développement des sous-requêtes se poursuit, et aucun des conseils d'optimisation ne sera valable longtemps. Voici quelques astuces que vous voulez prendre en compte.

- Utiliser une clause de sous-requête pour affecter le nombre ou l'ordre des lignes dans une sous-requête, par exemple :

SELECT * FROM t1 WHERE t1.column1 IN
(SELECT column1 FROM t2 ORDER BY column1);
SELECT * FROM t1 WHERE t1.column1 IN
(SELECT DISTINCT column1 FROM t2);
SELECT * FROM t1 WHERE EXISTS
(SELECT * FROM t2 LIMIT 1);

- Remplacer une jointure par une sous-requête. Par exemple :

SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
SELECT column1 FROM t2);

au lieu de

SELECT DISTINCT t1.column1 FROM t1, t2
WHERE t1.column1 = t2.column1;

- Déplacer une clause FROM externe dans une sous-requête, comme ceci :

SELECT * FROM t1
WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);

au lieu de

SELECT * FROM t1
WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

Un autre exemple :

SELECT (SELECT column1 + 5 FROM t1) FROM t2;

au lieu de

SELECT (SELECT column1 FROM t1) + 5 FROM t2;

- Utiliser une sous-requête de ligne plutôt qu'une corrélation. Par exemple :

SELECT * FROM t1
WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);

au lieu de

SELECT * FROM t1
WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
AND t2.column2=t1.column2);

- Utiliser NOT (a = ANY (...)) au lieu de a <> ALL (...).

- Utiliser x = ANY (table containing {1,2}) plutôt que x=1 OR x=2.

- Utiliser = ANY de préférence à EXISTS.

Le truc ci-dessus peut accélérer certains programmes, et en ralentir d'autres. En utilisant la fonction utilitaire BENCHMARK(), vous pouvez obtenir une idée de votre cas. Ne vous attardez pas trop à transformer vos jointures, sauf si la compatibilité avec les anciennes versions est importante pour vous.

Quelques optimisations que MySQL va prendre en charge lui-même.

- MySQL va exécuter les sous-requêtes non corrélées une seule fois (utilisez la commande EXPLAIN pour vous assurer que les requêtes ne sont pas corrélées).

- MySQL va transformer les sous-requêtes IN/ALL/ANY/SOME pour essayer de profiter de la possibilité que les colonnes sélectionnées dans les sous-requêtes sont indexées.

- MySQL remplacera les sous-requêtes de la forme

... IN (SELECT indexed_column FROM single_table ...)

par une recherche dans un index, que EXPLAIN décrira comme une jointure de type spécial.

- MySQL va améliorer les expressions de la forme

valeur {ALL|ANY|SOME} {> | < | >= | <=} (sous-requête non corrélée)

avec une expression impliquant MIN ou MAX (à moins d'une valeur NULL ou d'ensembles SET vides). Par exemple,

WHERE 5 > ALL (SELECT x FROM t)

revient à

WHERE 5 > (SELECT MAX(x) FROM t)

Il y a un chapitre intitulé « Comment MySQL adapte les sous-requêtes » dans les manuels internes de MySQL, que vous pouvez trouver en téléchargeant les sources de MySQL : il est dans un fichier appelé internals.texi, dans le dossier Docs.

13-1-8-11 - Se passer des sous-requêtes avec les premières versions de MySQL

Jusqu'à la version 4.1, seules les requêtes imbriquées de la forme INSERT ... SELECT ... et REPLACE ... SELECT ... étaient supportées.

La clause IN() peut être utilisée dans certains contextes, pour tester la présence de valeur dans un ensemble de données.

Il est souvent possible de réécrire une requête sans sous-requête :

SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

Cela peut se réécrire :

SELECT t1.* FROM t1,t2 WHERE t1.id=t2.id;

Les requêtes :

SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

peuvent être réécrites :

SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
WHERE table2.id IS NULL;

Une clause LEFT [OUTER] JOIN peut être plus rapide qu'une sous-requête équivalente, car le serveur va pouvoir l'optimiser bien mieux : c'est un fait qui n'est pas spécifique à MySQL. Avant SQL-92, les jointures externes n'existaient pas, et les sous-requêtes étaient la seule méthode pour résoudre certains problèmes. Aujourd'hui, le serveur MySQL et d'autres bases de données modernes offrent toute une gamme de jointures externes.

Pour les sous-requêtes plus complexes, vous pouvez simplement créer des tables temporaires pour contenir les résultats intermédiaires. Dans certains cas, cela ne sera pas possible. C'est notamment le cas des commandes de type DELETE, pour lesquelles le standard SQL ne supporte pas les jointures, sauf pour les sous-requêtes. Dans ces situations, trois solutions s'offrent à vous :

- passer en MySQL version 4.1 ;

- utiliser un langage de programmation procédural, comme Perl ou PHP, pour envoyer la requête SELECT, lire les clés primaires à effacer, et utiliser ces valeurs pour soumettre des requêtes de type DELETE (DELETE FROM ... WHERE ... IN (key1, key2, ...)) ;

- la troisième option est d'utiliser le client interactif de mysql pour construire et exécuter une liste de commandes DELETE automatiquement, avec la fonction CONCAT() au lieu de l'opérateur ||. Par exemple :

SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';')
FROM tab1, tab2
WHERE tab1.col1 = tab2.col2;

Vous pouvez placer cette requête dans un fichier de scripts, et rediriger son résultat vers le client en ligne de commande mysql, pour que ce dernier lance une seconde instance de l'interpréteur :

shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb

MySQL 4.0 supporte les commandes DELETE multitables qui peuvent être utilisées pour effacer des lignes dans une table en fonction d'informations qui sont dans une autre table, ou même effacer des lignes simultanément dans plusieurs tables. Les commandes UPDATE multitables sont aussi supportées depuis la version 4.0.

13-1-9 - Syntaxe de TRUNCATE

TRUNCATE TABLE nom_de_table

Dans la version 3.23, TRUNCATE TABLE est équivalent à COMMIT ; DELETE FROM nom_de_table. Voir Section 13.1.1, « Syntaxe de DELETE ».

TRUNCATE TABLE diffère de DELETE FROM ... des façons suivantes.

- Implémentée comme une destruction/création de table, ce qui accélère la suppression des enregistrements.

- Ne respecte pas les transactions. Vous aurez des erreurs si vous avez une transaction active ou une table protégée en écriture.

- Ne retourne pas le nombre de lignes effacées.

- Tant que le fichier de définitions nom_de_table.frm est valide, la table peut être recréée, même si les données ou un index ont été corrompus.

- Le gestionnaire de tables ne se souvient pas de la dernière valeur AUTO_INCREMENT utilisée, mais peut commencer à compter depuis le début. C'est vrai pour les tables MyISAM, ISAM et BDB.

TRUNCATE est une extension Oracle SQL. Cette commande a été ajoutée en MySQL 3.23.28, même si dans les versions 3.23.28 à 3.23.32, le mot-clé TABLE devait être omis.

13-1-10 - Syntaxe de UPDATE

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]

Syntaxe multitable :

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...]
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]

UPDATE met à jour des enregistrements dans une table avec de nouvelles valeurs. La clause SET indique les colonnes à modifier et les valeurs à leur donner. La clause WHERE, si fournie, spécifie les enregistrements à mettre à jour. Sinon, tous les enregistrements sont mis à jour. Si la clause ORDER BY est fournie, les enregistrements seront mis à jour dans l'ordre spécifié.

La commande UPDATE accepte les options suivantes.

- Si vous spécifiez le mot-clé LOW_PRIORITY, l'exécution de l'UPDATE sera repoussé jusqu'à ce qu'aucun client ne lise plus de la table.

- Si vous spécifiez le mot-clé IGNORE, la mise à jour ne s'interrompra pas même si on rencontre des problèmes d'unicité de clés durant l'opération. Les enregistrements posant problème ne seront pas mis à jour.

Si vous accédez à une colonne d'une table tbl_name dans une expression, UPDATE utilisera la valeur courante de la colonne. Par exemple, la requête suivante ajoute une année à l'âge actuel de tout le monde :

mysql> UPDATE persondata SET age=age+1;

Les requêtes UPDATE sont évaluées de gauche à droite. Par exemple, la requête suivante double la valeur de la colonne âge, puis l'incrémente :

mysql> UPDATE persondata SET age=age*2, age=age+1;

Si vous changez la valeur d'une colonne en lui spécifiant sa valeur actuelle, MySQL s'en aperçoit et ne fait pas la mise à jour.

UPDATE retourne le nombre d'enregistrements ayant changé. Depuis la version 3.22 de MySQL, la fonction mysql_info() de l'API C retourne le nombre de colonnes qui correspondaient, le nombre de colonnes mises à jour et le nombre d'erreurs générées pendant l'UPDATE.

Dans la version 3.23 de MySQL, vous pouvez utiliser le code LIMIT # pour vous assurer que seul un nombre d'enregistrements bien précis sont changés.

- Avant MySQL 4.0.13, LIMIT est une restriction sur le nombre de lignes affectées. Cette clause stoppe dès que row_count ont été trouvées par la clause WHERE.

- Depuis la version 4.0.13, LIMIT est une restriction sur le nombre de lignes trouvées. La commande s'arrête une fois que row_count lignes ont été trouvées par la clause WHERE, qu'elles aient été changées ou pas.

Si une clause ORDER BY est utilisée (disponible depuis MySQL version 4.0.0), les lignes seront modifiées selon cet ordre. Ce n'est vraiment utile qu'en conjonction avec LIMIT.

Depuis MySQL version 4.0.4, vous pouvez aussi faire des opérations de UPDATE qui couvrent plusieurs tables :

UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

L'exemple ci-dessus montre une jointure interne, en utilisant la virgule comme séparateur, mais une commande UPDATE multitable peut utiliser n'importe quel type de jointure autorisée dans une commande SELECT, tel qu'un LEFT JOIN.

Note : vous ne pouvez pas utiliser ORDER BY ou LIMIT avec les UPDATE multitables.

13-2 - Définition de données : CREATE, DROP, ALTER

13-2-1 - Syntaxe de ALTER DATABASE

ALTER DATABASE db_name
alter_specification [, alter_specification] ...

alter_specification:
[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name

ALTER DATABASE vous permet de modifier les caractéristiques générales d'une base de données. Ces caractéristiques sont stockées dans le fichier db.opt du dossier de base. Pour utiliser ALTER DATABASE, vous avez besoin des droits de ALTER sur la base.

La clause CHARACTER SET modifie le jeu de caractères par défaut de la base. La clause COLLATE modifie la collation par défaut de la base. Les noms de jeu de caractères et de collation sont présentés dans la section Chapitre 10, Jeux de caractères et Unicode.

ALTER DATABASE a été ajoutée MySQL 4.1.1.

13-2-2 - Syntaxe de ALTER TABLE

ALTER [IGNORE] TABLE tbl_name
alter_specification [, alter_specification] ...

alter_specification:
ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
| ADD [COLUMN] (column_definition,...)
| ADD INDEX [index_name] [index_type] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
PRIMARY KEY [index_type] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
UNIQUE [index_name] [index_type] (index_col_name,...)
| ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
| ADD [CONSTRAINT [symbol]]
FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
| ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
| CHANGE [COLUMN] old_col_name column_definition
[FIRST|AFTER col_name]
| MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
| DROP [COLUMN] col_name
| DROP PRIMARY KEY
| DROP INDEX index_name
| DROP FOREIGN KEY fk_symbol
| DISABLE KEYS
| ENABLE KEYS
| RENAME [TO] new_tbl_name
| ORDER BY col_name
| CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
| [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
| DISCARD TABLESPACE
| IMPORT TABLESPACE
| table_options

ALTER TABLE vous permet de changer la structure d'une table existante. Par exemple, vous pouvez ajouter ou supprimer des colonnes, des index, changer le type des colonnes existantes, renommer ces colonnes, ou la table elle-même. Vous pouvez de même changer le commentaire sur la table, ou le type de celle-ci.

La syntaxe de nombreuses altérations est similaire aux clauses de la commande CREATE TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

Si vous utilisez ALTER TABLE pour modifier les spécifications d'une colonne, mais que DESCRIBE nom_de_table vous indique que cette colonne n'a pas été modifiée, il est possible que MySQL ait ignoré vos modifications pour une des raisons décrites dans Section 13.2.5.1, « Modification automatique du type de colonnes ». Par exemple, si vous essayez de changer une colonne de type VARCHAR en CHAR, MySQL continuera d'utiliser VARCHAR si la table contient d'autres colonnes de taille variable.

ALTER TABLE effectue une copie temporaire de la table originale. Les modifications sont faites sur cette copie, puis l'original est effacé, et enfin la copie est renommée pour remplacer l'originale. Cette méthode permet de rediriger toutes les commandes automatiquement vers la nouvelle table sans pertes. Durant l'exécution de ALTER TABLE, la table originale est lisible par d'autres clients. Les modifications et insertions sont reportées jusqu'à ce que la nouvelle table soit prête.

Notez que si vous utilisez une autre option que RENAME avec ALTER TABLE, MySQL créera toujours une table temporaire, même si les données n'ont pas besoin d'être copiées (comme quand vous changez le nom d'une colonne). Nous avons prévu de corriger cela dans les versions suivantes, mais comme la commande ALTER TABLE n'est pas utilisée très souvent, cette correction ne fait pas partie de nos priorités. Pour les tables MyISAM, vous pouvez accélérer la réindexation (qui est la partie la plus lente de la modification d'une table) en donnant à la variable système myisam_sort_buffer_size une valeur plus grande.

- Pour utiliser ALTER TABLE, vous devez avoir les droits ALTER, INSERT, et CREATE sur la table.

- IGNORE est une extension MySQL pour ANSI SQL92. Cette option contrôle la façon dont ALTER TABLE fonctionne s'il y a des duplications sur une clé unique de la nouvelle table. Si IGNORE n'est pas spécifiée, la copie est annulée et la table originale est restaurée. Si IGNORE est spécifiée, les lignes contenant les éléments doublons de la table seront effacées, hormis la première, qui sera conservée.

- Vous pouvez effectuer plusieurs opérations de ADD, ALTER, DROP, et CHANGE dans une même commande ALTER TABLE. C'est une extension de MySQL à la norme ANSI SQL92, qui n'autorise qu'une seule modification par commande ALTER TABLE.

- CHANGE nom_colonne, DROP nom_colonne, et DROP INDEX sont des extensions de MySQL à la norme ANSI SQL92.

- MODIFY est une extension Oracle à ALTER TABLE.

- Le mot optionnel COLUMN est purement de la fioriture et peut être ignoré.

- Si vous utilisez ALTER TABLE nom_de_table RENAME TO nouveau_nom sans autre option, MySQL va simplement renommer les fichiers qui correspondent à la table nom_de_table. Il n'y a pas de création de fichier temporaire. Voir Section 13.2.9, « Syntaxe de RENAME TABLE ».

- La définition create_definition utilise la même syntaxe pour les clauses ADD et CHANGE que dans CREATE TABLE. Notez que cette syntaxe inclut le nom de la colonne, et pas seulement son type Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

- Vous pouvez renommer une colonne avec la syntaxe CHANGE ancien_nom_de_colonne create_definition. Pour cela, indiquez l'ancien nom de la colonne, puis le nouveau nom et son type courant. Par exemple, pour renommer une colonne de type INTEGER, de a en b, vous pouvez faire ceci :

mysql> ALTER TABLE t1 CHANGE a b INTEGER;

Si vous ne voulez changer que le type de la colonne, avec la clause CHANGE vous devrez redonner le nom de la colonne. Par exemple :

mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;

Cependant, à partir de la version 3.22.16a de MySQL, vous pouvez aussi utiliser la clause MODIFY pour changer le type d'une colonne sans la renommer :

mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

- Si vous utilisez les clauses CHANGE ou MODIFY pour réduire la taille d'une colonne qui comportait un index sur une partie de la colonne (par exemple, si vous aviez un index sur 10 caractères d'une colonne de type VARCHAR), vous ne pouvez pas rendre la colonne plus petite que le nombre de caractères indexés.

- Quand vous changez le type d'une colonne avec CHANGE ou MODIFY, MySQL essaye de convertir les données au niveau type dans la mesure du possible.

- À partir de la version 3.22 de MySQL, vous pouvez utiliser FIRST ou ADD ... AFTER nom_colonne pour ajouter la colonne à un endroit spécifique dans la table. Par défaut, la colonne est ajoutée à la fin. À partir de la version 4.0.1, vous pouvez aussi utiliser les mots-clés FIRST et AFTER avec CHANGE ou MODIFY.

- ALTER COLUMN spécifie une nouvelle valeur par défaut pour une colonne ou enlève l'ancienne. Si l'ancienne valeur est effacée et que la colonne peut être NULL, la nouvelle valeur par défaut sera NULL. Si la colonne ne peut être NULL, MySQL assigne une valeur par défaut, comme défini dans Section 13.2.5, « Syntaxe de CREATE TABLE ».

- DROP INDEX supprime un index. C'est une extension MySQL à la norme ANSI SQL92. Voir Section 13.2.7, « Syntaxe de DROP INDEX ».

- Si des colonnes sont effacées d'une table, ces colonnes sont aussi supprimées des index dont elles font partie. Si toutes les colonnes qui forment un index sont effacées, l'index lui-même est supprimé.

- Si une table ne comporte qu'une seule colonne, la colonne ne peut être supprimée. Si vous voulez effacer la table, utilisez la commande DROP TABLE.

- DROP PRIMARY KEY supprime la clé primaire. Si cette clé n'existe pas, cette commande effacera le premier index UNIQUE de la table. (MySQL marque la première clé UNIQUE en tant que PRIMARY KEY si aucune PRIMARY KEY n'a été spécifiée explicitement.)

Si vous ajoutez un UNIQUE INDEX ou PRIMARY KEY à une table, c'est enregistré avant les index non UNIQUE pour que MySQL puisse détecter les valeurs dupliquées aussi vite que possible.

- ORDER BY vous permet de créer une nouvelle table tout en ordonnant les lignes par défaut. Notez que cet ordre ne sera pas conservé après les prochaines insertions et modifications. Dans certains cas, cela aide MySQL si les colonnes sont dans l'ordre dans lequel vous allez trier les valeurs. Cette option n'est vraiment utile que si vous savez à l'avance dans quel ordre vous effectuerez les tris : vous y gagnerez alors en performances.

- Si vous utilisez ALTER TABLE sur une table MyISAM, tous les index non uniques sont créés par des opérations séparées. (comme dans REPAIR). Cela devrait rendre ALTER TABLE plus rapide quand vous avez beaucoup d'index.

Depuis la version 4.0, la fonctionnalité ci-dessus peut être activée explicitement. ALTER TABLE ... DISABLE KEYS force MySQL à ne plus mettre à jour les index non uniques pour les tables au format MyISAM. ALTER TABLE ... ENABLE KEYS doit alors être utilisé pour recréer les index manquants. Comme MySQL le fait avec un algorithme spécial qui est plus rapide que le fait d'insérer les clés une par une, désactiver les clés peut vous faire gagner en performances.

- Les clauses FOREIGN KEY et REFERENCES sont supportées par le moteur de tables InnoDB, qui implémente les clauses ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...). Voir Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ». Pour les autres moteurs de stockage, ces clauses sont lues, mais ignorées. La clause CHECK est analysée, mais ignorée par tous les moteurs de stockage. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ». La raison pour accepter, mais ignorer ces clauses est que cela renforce la compatibilité avec le code des autres serveurs SQL, et qu'il est possible de créer des tables avec des références. Voir Section 1.5.5, « Différences entre MySQL et le standard SQL-92 ».

- Depuis MySQL 4.0.13, InnoDB supporte l'utilisation de ALTER TABLE pour effacer des clés étrangères :

ALTER TABLE yourtablename
DROP FOREIGN KEY fk_symbol

Pour plus d'informations, voyez Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ».

- ALTER TABLE ignore les options de tables DATA DIRECTORY et INDEX DIRECTORY.

- Depuis MySQL 4.1.2, si vous voulez changer dans toutes les colonnes de texte (CHAR, VARCHAR, TEXT) le jeu de caractères, vous pouvez utiliser la commande suivante :

ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

C'est pratique lorsque vous passez de MySQL 4.0.x en 4.1.x. Voir Section 10.10, « Préparer le passage de version 4.0 en 4.1 ».

Attention : l'opération précédente va convertir les valeurs des colonnes entre les deux jeux de caractères. Ce n'est pas ce que vous souhaitez faire si une colonne est de type latin1, mais que les valeurs sont en fait dans un autre jeu de caractères (comme utf8). Dans ce cas, vous devez faire ceci avec une telle colonne :

ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

La raison est que dans ce cas, il n'y aura pas de conversion lorsque vous passer en type BLOB.

Pour ne changer que le type de caractères par défaut, utilisez cette commande :

ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;

Le mot DEFAULT est optionnel. Le jeu de caractères par défaut est utilisé si vous ne spécifiez pas le jeu de caractères de la colonne explicitement, lorsque vous ajoutez une nouvelle colonne : par exemple, avec ALTER TABLE ... ADD column.

Attention : depuis MySQL 4.1.2 et plus récents, ALTER TABLE ... DEFAULT CHARACTER SET et ALTER TABLE ... CHARACTER SET sont équivalent et ne changent que le jeu de caractères par défaut. Dans les versions antérieures à MySQL 4.1.2, ALTER TABLE ... DEFAULT CHARACTER SET changeait le jeu de caractères par défaut, mais ALTER TABLE ... CHARACTER SET (sans DEFAULT) changeait le jeu de caractères par défaut, et convertissaient les colonnes dans le nouveau jeu.

- Pour une table InnoDB qui a été créée avec son propre espace de tables dans un fichier .ibd, ce fichier peut être supprimé et importé. Pour supprimer le fichier .ibd, utilisez la commande suivante :

ALTER TABLE tbl_name DISCARD TABLESPACE;

Elle efface le fichier .ibd courant, alors assurez-vous que vous avez une copie de sauvegarde. Si vous tentez d'accéder à un espace de table sans ce fichier, vous obtiendrez une erreur.

Pour importer un fichier de sauvegarde .ibd dans la table, copiez le nouveau fichier dans le dossier de la base, et utilisez cette commande :

ALTER TABLE tbl_name IMPORT TABLESPACE;

Voir Section 15.7.6, « Espaces de tables multiples : chaque table InnoDB a son fichier .ibd ».

- Avec la fonction mysql_info() de l'API C, vous pouvez savoir combien d'enregistrements ont été copiés, et (quand IGNORE est spécifié) combien d'enregistrements ont été effacés à cause de la clé unique. Voir Section 24.2.3.31, « mysql_info() ».

Voilà un exemple qui montre quelques utilisations de ALTER TABLE. On commence par une table t1 créée comme suit :

mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

Pour renommer la table de t1 à t2 :

mysql> ALTER TABLE t1 RENAME t2;

Pour changer une colonne a de INTEGER en TINYINT NOT NULL (en laissant le même nom), et pour changer une colonne b de CHAR(10) à CHAR(20) et la renommant de b en c :

mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

Pour ajouter une nouvelle colonne TIMESTAMP nommée d :

mysql> ALTER TABLE t2 ADD d TIMESTAMP;

Pour ajouter un index sur une colonne d, et rendre la colonne a la clé primaire :

mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

Pour effacer la colonne c :

mysql> ALTER TABLE t2 DROP COLUMN c;

Pour ajouter une nouvelle colonne AUTO_INCREMENT nommée c :

mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
ADD INDEX (c);

Notez que nous avons indexé c, car les colonnes AUTO_INCREMENT doivent être indexées, et que nous définissons aussi c en tant que NOT NULL, car les colonnes indexées ne peuvent être NULL.

Quand vous ajoutez une colonne AUTO_INCREMENT, les valeurs de la colonne sont remplies automatiquement pour vous. Vous pouvez choisir la valeur de départ pour l'indexation en utilisant SET INSERT_ID=# avant ALTER TABLE ou en utilisant l'option AUTO_INCREMENT = # de la table. Voir Section 13.5.2.8, « Syntaxe de SET ».

Avec les tables de type MyISAM, si vous ne changez pas la colonne AUTO_INCREMENT, l'indice d'autoincrémentation ne sera pas affecté. Si vous effacez une colonne AUTO_INCREMENT puis en ajoutez une autre, l'indexation recommencera à partir de 1.

Voir Section A.7.1, « Problèmes avec ALTER TABLE. ».

13-2-3 - Syntaxe de CREATE DATABASE

CREATE DATABASE [IF NOT EXISTS] db_name
[create_specification [, create_specification] ...]

create_specification:
[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name

CREATE DATABASE crée une base de données avec le nom donné.

Les règles de nommage des bases de données sont présentées dans la Section 9.2, « Noms de bases, tables, index, colonnes et alias ». Une erreur survient si une base de données de même nom existe déjà, si vous ne spécifiez pas l'option IF NOT EXISTS.

Depuis MySQL 4.1.1, les options create_specification peuvent être données pour spécifier des caractéristiques de la base. Les caractéristiques de la base sont stockées dans le fichier db.opt dans le dossier de la base. La clause CHARACTER SET spécifie le jeu de caractères par défaut pour les tables de cette base. La clause COLLATE spécifie la collation par défaut de la base de données. Les jeux de caractères et les collations sont présentés dans le Chapitre 10, Jeux de caractères et Unicode.

Les bases de données MySQL sont implémentées comme des répertoires contenant des fichiers qui correspondent aux tables dans les bases de données. Puisqu'il n'y a pas de tables dans une base de données lors de sa création, la requête CREATE DATABASE créera seulement le dossier dans le répertoire de données de MySQL (et le fichier db.opt, depuis MySQL 4.1.1).

Vous pouvez aussi créer des bases de données avec mysqladmin. Voir Section 8.4, « mysqladmin, administration d'un serveur MySQL ».

13-2-4 - Syntaxe de CREATE INDEX

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [index_type]
ON tbl_name (index_col_name,...)

index_col_name:
col_name [(length)] [ASC | DESC]

La requête CREATE INDEX n'effectue aucune action sur les versions de MySQL antérieures à la version 3.22. Dans les versions 3.22 et supérieures, CREATE INDEX est équivalent à une requête ALTER TABLE pour créer des index. Voir Section 13.2.2, « Syntaxe de ALTER TABLE ».

Normalement, tous les index sont créés en même temps que la table elle-même avec CREATE TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ». CREATE INDEX permet d'ajouter des index à une table existante.

Une liste de colonnes de la forme (col1, col2...) crée un index multicolonne. Les valeurs de l'index sont créées en concaténant la valeur deux colonnes données.

Pour les colonnes CHAR et VARCHAR, les index peuvent être créés sur uniquement une partie de la colonne, avec la syntaxe col_name(length). Pour les colonnes BLOB et TEXT la longueur d'index est obligatoire. La requête suivante crée un index en utilisant les 10 premiers caractères de la colonne name :

mysql> CREATE INDEX part_of_name ON customer (name(10));

Comme la plupart des noms ont en général des différences dans les 10 premiers caractères, l'index ne devrait pas être plus lent qu'un index créé à partir de la colonne name en entier. Ainsi, en n'utilisant qu'une partie de la colonne pour les index, on peut réduire la taille du fichier d'index, ce qui peut permettre d'économiser beaucoup d'espace disque, et peut aussi accélérer les opérations INSERT !

Il est important de savoir qu'on peut indexer une colonne qui peut avoir la valeur NULL ou une colonne BLOB/TEXT que si on utilise une version 3.23.2 ou supérieures de MySQL et en utilisant le type MyISAM.

Pour plus d'informations à propos de l'utilisation des index dans MySQL, voir Section 7.4.5, « Comment MySQL utilise les index ».

Les index FULLTEXT ne peuvent indexer que des colonnes VARCHAR ou TEXT, et seulement dans les tables MyISAM. Les index FULLTEXT sont disponibles dans les versions 3.23.23 et supérieures de MySQL. Section 12.6, « Recherche en texte intégral (Full-text) dans MySQL ».

Les index SPATIAL peuvent indexer les colonnes spatiales, et uniquement avec les tables MyISAM. Les index SPATIAL sont disponibles en MySQL 4.1 et plus récents. Les colonnes spatiales sont présentées dans le Chapitre 18, Données spatiales avec MySQL.

13-2-5 - Syntaxe de CREATE TABLE

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options] [select_statement]

ou :

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(] LIKE old_tbl_name [)];

create_definition:
column_definition
| [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
| KEY [index_name] [index_type] (index_col_name,...)
| INDEX [index_name] [index_type] (index_col_name,...)
| [CONSTRAINT [symbol]] UNIQUE [INDEX]
[index_name] [index_type] (index_col_name,...)
| [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...)
| [CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name,...) [reference_definition]
| CHECK (expr)

column_definition:
col_name type [NOT NULL | NULL] [DEFAULT default_value]
[AUTO_INCREMENT] [[PRIMARY] KEY] [COMMENT 'string']
[reference_definition]

type:
TINYINT[(length)] [UNSIGNED] [ZEROFILL]
| SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
| MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
| INT[(length)] [UNSIGNED] [ZEROFILL]
| INTEGER[(length)] [UNSIGNED] [ZEROFILL]
| BIGINT[(length)] [UNSIGNED] [ZEROFILL]
| REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
| DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
| FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
| DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
| NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
| DATE
| TIME
| TIMESTAMP
| DATETIME
| CHAR(length) [BINARY | ASCII | UNICODE]
| VARCHAR(length) [BINARY]
| TINYBLOB
| BLOB
| MEDIUMBLOB
| LONGBLOB
| TINYTEXT
| TEXT
| MEDIUMTEXT
| LONGTEXT
| ENUM(value1,value2,value3,...)
| SET(value1,value2,value3,...)
| spatial_type

index_col_name:
col_name [(length)] [ASC | DESC]

reference_definition:
REFERENCES tbl_name [(index_col_name,...)]
[MATCH FULL | MATCH PARTIAL]
[ON DELETE reference_option]
[ON UPDATE reference_option]

reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

table_options: table_option [table_option] ...

table_option:
{ENGINE|TYPE} = {BDB|HEAP|ISAM|InnoDB|MERGE|MRG_MYISAM|MYISAM}
| AUTO_INCREMENT = value
| AVG_ROW_LENGTH = value
| CHECKSUM = {0 | 1}
| COMMENT = 'string'
| MAX_ROWS = value
| MIN_ROWS = value
| PACK_KEYS = {0 | 1 | DEFAULT}
| PASSWORD = 'string'
| DELAY_KEY_WRITE = {0 | 1}
| ROW_FORMAT = { DEFAULT | DYNAMIC | FIXED | COMPRESSED }
| RAID_TYPE = { 1 | STRIPED | RAID0 }
RAID_CHUNKS = value
RAID_CHUNKSIZE = value
| UNION = (tbl_name[,tbl_name]...)
| INSERT_METHOD = { NO | FIRST | LAST }
| DATA DIRECTORY = 'absolute path to directory'
| INDEX DIRECTORY = 'absolute path to directory'
| [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]

select_statement:
[IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

CREATE TABLE Crée une table avec le nom donné, dans la base de données courante. Vous avez besoin des droits de CREATE pour créer une table.

Les règles de nommage des tables sont disponibles dans Section 9.2, « Noms de bases, tables, index, colonnes et alias ». Par défaut, une table est créée dans la base de données courante. Une erreur est affichée s'il n'y a pas de base courante, si la base de données n'existe pas ou si la table existe déjà.

En MySQL 3.22 et plus récents, le nom de la table peut être spécifié avec la syntaxe db_name.tbl_name, pour créer une table dans une base spécifique. Cela fonctionne même s'il n'y a pas de base courante. Si vous utilisez les identifiants protégez, et mettez le nom de la base et celui de la table entre guillemets, séparément. Par exemple, `madb`.`matbl` est valide, mais `madb.matbl` ne l'est pas.

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot réservé TEMPORARY lorsque vous créez une table. Une table temporaire sera immédiatement effacée dès que la connexion se termine. Cela signifie que vous pouvez utiliser le même nom de table temporaire depuis deux connexions différentes sans risque de conflit entre les connexions. Vous pouvez aussi utiliser une table temporaire qui a le même nom qu'une table existante (la table existante est alors cachée tant que dure la table temporaire). En MySQL version 4.0.2 ou plus récents, vous avez juste à avoir le privilège CREATE TEMPORARY TABLES pour créer des tables temporaires.

Depuis la version 3.23 de MySQL, vous pouvez utiliser le mot réservé IF NOT EXISTS, de façon à ce qu'aucune erreur ne soit affichée si la table que vous essayez de créer existe déjà. Notez qu'il n'y a pas de comparaison entre les structures de table lors du test d'existence.

MySQL représente chaque table par un fichier de définition de table .frm, placé dans le dossier de la base de données. Le moteur de la table peut créer d'autres fichiers complémentaires. Dans le cas des tables MyISAM, le moteur de stockage utilise trois fichiers, avec le nom nom_de_table :

Fichier

Rôle

nom_de_table.frm

Fichier de définition de la table

nom_de_table.MYD

Fichier de données

nom_de_table.MYI

Fichier d'index

Les fichiers créés par les moteurs de stockage pour représenter les tables sont décrits dans le Chapitre 14, Moteurs de tables MySQL et types de table.

Pour des informations générales sur les propriétés des différentes colonnes, voyez Chapitre 11, Types de colonnes. Pour des informations sur les types de données spatiaux, voyez Chapitre 18, Données spatiales avec MySQL.

- Si ni NULL, ni NOT NULL n'est spécifié, une colonne utilisera par défaut l'attribut NULL (elle acceptera les valeurs NULL).

- Une colonne de nombres entiers peut se voir attribuer l'attribut AUTO_INCREMENT. Lorsque vous insérez la valeur NULL (recommandée) ou 0 dans une colonne AUTO_INCREMENT, la colonne prendra automatiquement la valeur de value+1, où value est la plus grande valeur positive courante dans cette colonne. La série des valeurs AUTO_INCREMENT commence à 1. Voir Section 24.2.3.33, « mysql_insert_id() ».

Depuis MySQL 4.1.1, en spécifiant l'option NO_AUTO_VALUE_ON_ZERO pour le mode --sql-mode ou la variable serveur sql_mode permet de stocker la valeur 0 dans les colonnes de type AUTO_INCREMENT, au lieu de voir 0 prendre le prochain numéro de séquence. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Note : il ne peut y avoir qu'une seule colonne de type AUTO_INCREMENT dans une table, et elle doit être indexée. MySQL version 3.23 ne fonctionnera correctement que si cette colonne n'accueille que des valeurs positives. Insérer un nombre négatif sera considéré comme insérer un nombre de très grande taille, mais positif. Ceci est fait pour éviter les problèmes de précision lorsque les nombres passent de positif à négatif lorsqu'ils atteignent leur valeur maximale positive. C'est aussi pour éviter qu'une colonne de type AUTO_INCREMENT ne contienne de valeur 0.

Si vous effacez la ligne contenant la valeur maximale dans la colonne AUTO_INCREMENT, cette valeur sera réutilisée dans les tables de type ISAM, mais pas dans les tables de type MyISAM. Si vous effacez toutes les lignes dans la table avec la commande DELETE FROM nom_de_table (sans la clause WHERE) en mode AUTOCOMMIT, la série des valeurs AUTO_INCREMENT recommencera à 1.

Avec les tables MyISAM et BDB, vous pouvez spécifier une colonne secondaire d'AUTO_INCREMENT dans une clé multicolonne. Voir Section 3.6.9, « Utiliser AUTO_INCREMENT ».

Pour rendre MySQL avec certaines applications ODBC, vous pouvez retrouver la valeur de la dernière valeur automatiquement générée avec la requête suivante :

SELECT * FROM nom_de_table WHERE auto_col IS NULL

- Depuis MySQL 4.1, la définition des colonnes peut inclure un attribut CHARACTER SET pour spécifier le jeu de caractères, et éventuellement la collation de la colonne. Pour des détails, voyez Chapitre 10, Jeux de caractères et Unicode.

CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);

Depuis la version 4.1 aussi, MySQL interprète les spécifications de longueur de colonne en caractères. Les anciennes versions l'interprètent comme des octets.

- La valeur NULL est traitée différemment dans les colonnes de type TIMESTAMP. Vous ne pouvez pas stocker de valeur NULL littérale dans une colonne TIMESTAMP; insérer une valeur NULL dans une telle colonne revient à insérer la date et l'heure courante. Car les colonnes TIMESTAMP ignorent les attributs NULL et NOT NULL.

Cela facilite grandement l'utilisation des colonnes TIMESTAMP pour les clients MySQL : le serveur indique que ces colonnes peuvent se voir assigner une valeur NULL (ce qui est vrai), même si les colonnes TIMESTAMP ne contiendront jamais de valeur NULL. Vous pouvez le constater lorsque vous utilisez la commande DESCRIBE nom_de_table pour avoir une description de votre table.

Notez qu'affecter la valeur 0 à une colonne TIMESTAMP n'est pas la même chose que lui affecter la valeur NULL, car 0 est une valeur TIMESTAMP valide.

- Une valeur DEFAULT doit être une constante, ça ne peut être une fonction ou une expression. Cela signifie notamment que vous ne pouvez pas donner une valeur par défaut à une colonne de date, le résultat de la fonction NOW() ou CURRENT_DATE.

Si aucune valeur par défaut (attribut DEFAULT) n'est spécifiée, MySQL en assigne une automatiquement.

Si la colonne accepte la valeur NULL, la valeur par défaut sera la valeur NULL.

Si la colonne est déclarée comme NOT NULL (non nulle), la valeur par défaut dépendra du type de colonne.

- Pour les types numériques sans l'attribut AUTO_INCREMENT, la valeur sera 0. Pour une colonne AUTO_INCREMENT, la valeur par défaut sera la prochaine valeur de la série.

- Pour les types dates et heures autres que TIMESTAMP, la valeur par défaut est la date zéro appropriée. Pour les colonnes TIMESTAMP, la valeur par défaut est la date et l'heure courante. Voir Section 11.3, « Les types date et heure ».

- Pour les types de chaînes autres que ENUM, la valeur par défaut est la chaîne vide. Pour ENUM, la valeur par défaut est la première valeur de l'énumération.

Les colonnes BLOB et TEXT ne peuvent pas recevoir de valeur par défaut.

- Un commentaire pour une colonne peut être spécifié avec COMMENT. Le commentaire est affiché par la commande SHOW CREATE TABLE et par SHOW FULL COLUMNS. Cette option est disponible depuis MySQL 4.1. Elle était autorisée, mais ignorée dans les anciennes versions.

- Depuis MySQL version 4.1.0, l'attribut SERIAL peut être utilisé comme alias pour les colonnes BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE. C'est une fonctionnalité de compatibilité.

- KEY est un synonyme de INDEX. Depuis la version 4.1, l'attribut de clé PRIMARY KEY peut aussi être spécifié avec la clause KEY. Il a été implémenté pour assurer la compatibilité avec les autres bases.

- Avec MySQL, une clé UNIQUE peut avoir uniquement deux valeurs distinctes. Une erreur surviendra si vous essayez d'ajouter une ligne dont la clé correspond à une ligne existante.

- Une clé primaire (PRIMARY KEY) est un index UNIQUE avec la contrainte supplémentaire que toutes les colonnes utilisées doivent avoir l'attribut NOT NULL. En MySQL, cette clé est dite PRIMARY. Une table ne peut avoir qu'une seule clé primaire. Si vous n'avez pas de PRIMARY KEY et que des applications demandent la PRIMARY KEY dans vos tables, MySQL retournera la première clé UNIQUE, qui n'a aucune valeur NULL.

- Dans une table créée, la clé primaire PRIMARY KEY est placée en première, suivie de tous les index UNIQUE, et enfin, les index non uniques. Cela permet à l'optimiseur MySQL d'utiliser en priorité les index, et de détecter rapidement les doublons pour les clés UNIQUE.

- Une PRIMARY KEY peut être multicolonne. Cependant, vous ne pouvez pas créer d'index multicolonne avec l'attribut PRIMARY KEY dans une spécification de colonne. En faisant cela, le seul résultat sera que cette seule colonne sera marquée comme clé primaire. Vous devez absolument utiliser la syntaxe PRIMARY KEY(index_nom_de_colonne, ...).

- Si une clé primaire (PRIMARY) ou unique (UNIQUE) est établie sur une seule colonne, et que cette colonne est de type entier, vous pouvez aussi faire référence à cette colonne sous le nom _rowid (nouveau en version 3.23.11).

- Avec MySQL, le nom de la clé primaire PRIMARY KEY est PRIMARY. Si vous ne donnez pas de nom à un index, l'index prendra le nom de la première colonne qui le compose, avec éventuellement un suffixe (_2, _3...) pour le rendre unique. Vous pouvez voir les noms des index avec la commande SHOW INDEX FROM tbl_name. Voir Section 13.5.3.6, « Syntaxe de SHOW DATABASES ».

- Depuis MySQL 4.1.0, certains moteurs de stockage vous permettent de spécifier un type d'index lors de la création d'un index. La syntaxe de index_type est USING type_name. Les valeurs possibles de type_name qui sont supportées par les différents moteurs de stockage sont listées ci-dessous. Lorsque des index multiples sont listés, le premier rencontré est celui par défaut, si aucun index_type n'est spécifié.

Moteur de table

Types d'index

MyISAM

BTREE

InnoDB

BTREE

MEMORY/HEAP

HASH, BTREE

Exemple :

CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;

TYPE type_name peut être utilisé comme synonyme de USING type_name, pour spécifier un type d'index. Cependant, USING est la forme recommandée. De plus, le nom d'index qui précède le type d'index dans la syntaxe de spécification n'est pas optionnel avec TYPE. Ceci est dû au fait que contrairement à USING, TYPE n'est pas un mot réservé, et donc, il pourrait être interprété comme un nom d'index.

Si vous spécifiez un type d'index qui n'est pas légal pour le moteur de stockage, mais qu'il y a un autre type d'index que le moteur peut utiliser sans affecter les résultats de la requête, le moteur utilisera ce type en remplacement.

- Seuls, les formats de table MyISAM, InnoDB, et BDB supportent des index sur des colonnes qui peuvent contenir des valeurs NULL. Dans les autres situations, vous devez déclarer ces colonnes NOT NULL ou une erreur sera générée.

- Avec la syntaxe nom_de_colonne(longueur), vous pouvez spécifier un index qui n'utilise qu'une partie de la colonne CHAR ou VARCHAR. Cela peut réduire la taille des fichiers d'index. Voir Section 7.4.3, « Index de colonnes ».

Le format de table MyISAM, et depuis la version MySQL 4.0.14, InnoDB, supportent l'indexation des colonnes BLOB et TEXT. Lorsque vous ajoutez un index à une colonne BLOB ou TEXT, vous devez absolument spécifier une longueur d'index :

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Le préfixe peut valoir jusqu'à 255 octets de long (où 1000 octets pour les tables MyISAM et InnoDB depuis MySQL 4.1.2). Notez que le préfixe est mesuré en octets, alors que la longueur du préfixe de CREATE TABLE est interprétée comme un nombre de caractères. Prenez cela en compte lorsque vous spécifiez une longueur de préfixe pour une colonne dont le jeu de caractères est multioctet.

- Une spécification index_col_name peut se terminer avec ASC ou DESC. Ces mots-clés sont prévus pour des extensions futures qui permettront un stockage dans un ordre donné. Actuellement, ils sont reconnus, mais ignorés : les index sont stockés en ordre ascendant.

- Lorsque vous utilisez une clause ORDER BY ou GROUP BY sur une colonne de type TEXT ou BLOB, seuls, les max_sort_longueur premiers octets seront lus. Voir Section 11.4.3, « Les types BLOB et TEXT ».

- En MySQL version 3.23.23 ou plus récentes, vous pouvez aussi créer des index spéciaux FULLTEXT. Ils sont utilisés pour faire des recherches en texte plein. Seul, le format de table MyISAM supporte les index FULLTEXT. Ils peuvent être créés uniquement pour les colonnes de type VARCHAR et TEXT. L'indexation est alors exécutée sur toute la colonne, et les indexations partielles ne sont pas supportées. Voir Section 12.6, « Recherche en texte intégral (Full-text) dans MySQL » pour les détails.

- En MySQL version 4.1 ou plus récentes, vous pouvez créer les index spéciaux SPATIAL pour les colonnes géographiques. Les types spatiaux sont supportés par les tables MyISAM, et les colonnes indexées doivent être déclarées comme NOT NULL. Voyez Chapitre 18, Données spatiales avec MySQL.

- En MySQL version 3.23.44 et plus récentes, les tables InnoDB supportent la vérification de clés étrangères. Voir Chapitre 15, Le moteur de tables InnoDB. Notez que la syntaxe des clés étrangères FOREIGN KEY de InnoDB est plus restrictive que la syntaxe présentée ci-dessus. InnoDB ne permet pas la spécification d'un index_name, et les colonnes de la table référencée doivent être explicitement nommées. Depuis la version 4.0.8, InnoDB supporte les clauses ON DELETE et ON UPDATE avec les clés étrangères. Voyez le manuel InnoDB pour la syntaxe précise. Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ».

Pour les autres types de tables, le serveur MySQL n'analyse pas les clauses FOREIGN KEY, CHECK et REFERENCES dans les commandes CREATE TABLE, et aucune action n'est réalisée. Voir Section 1.5.5.5, « Les clés étrangères ».

- Pour les tables MyISAM et ISAM, chaque colonne NULL requiert un bit supplémentaire, arrondi à l'octet supérieur le plus proche.

La taille maximale d'enregistrement peut être calculée comme ceci :

row longueur = 1
+ (somme des longueurs de colonnes)
+ (nombre de colonnes NULL + 7)/8
+ (nombre de colonnes à taille variable)

delete_flag vaut 1 pour les tables avec un format fixe. Les tables à format fixe utilisent un bit dans les lignes pour un marqueur, qui indique si la ligne a été effacée. delete_flag vaut 0 pour les tables à ligne dynamique, car le marquer est stocké dans l'entête de la ligne.

Ces calculs ne s'appliquent pas aux tables InnoDB, qui ne font pas la différence entre les colonnes NULL et les colonnes NOT NULL.

Les options options_de_table et SELECT ne sont implémentées que dans MySQL version 3.23 et plus récents.

Les options ENGINE et TYPE spécifient le type de moteur de table. ENGINE a été ajouté en MySQL 4.0.18, pour la série des 4.0 et 4.1.2, pour la série des 4.1. C'est le nom d'attribut recommandé pour ces versions et TYPE est maintenant abandonné. TYPE sera supporté dans les séries 4.x, mais abandonnée probablement en MySQL 5.1.

Les différents types de tables sont :

Table type

Description

ARCHIVE

Le moteur d'archivage. Voir Section 14.7, « Le moteur de table ARCHIVE ».

BDB

Tables avec transactions. Voir Section 14.4, « Tables BDB ou BerkeleyDB ».

BerkeleyDB

Un alias de BDB.

CSV

Tables qui stockent les lignes au format valeurs séparées par des virgules. Voir Section 14.8, « Le moteur CSV ».

EXAMPLE

Un moteur d'exemple. Voir Section 14.5, « Le moteur de table EXAMPLE ».

FEDERATED

Un moteur qui accède à des tables distantes. Voir Section 14.6, « Le moteur de table FEDERATED ».

HEAP

Les données de ces tables ne sont stockées qu'en mémoire. Voir Section 14.3, « Le moteur de table MEMORY (HEAP) ».

ISAM

Le gestionnaire originel de tables. Voir Section 14.9, « Tables ISAM ».

InnoDB

Tables transactionnelles avec verrou de lignes. Voir Chapitre 15, Le moteur de tables InnoDB.

MEMORY

Un alias de HEAP. (En fait, depuis MySQL 4.1, MEMORY est le terme recommandé.)

MERGE

Un ensemble de tables MyISAM utilisées comme une seule et même table. Voir Section 14.2, « Tables assemblées MERGE ».

MRG_MyISAM

Un synonyme pour les tables MERGE.

MyISAM

Le nouveau gestionnaire de tables binaires et portable. Voir Section 14.1, « Le moteur de tables MyISAM ».

NDB

Alias de NDBCLUSTER.

NDBCLUSTER

Tables en grappe et en mémoire, tolérantes aux pannes. Voir Chapitre 16, Introduction à MySQL Cluster.

Voir Chapitre 14, Moteurs de tables MySQL et types de table.

Si un type de table est demandé, mais que ce type particulier n'est pas disponible, MySQL va choisir le type de table le plus proche de celui qui est spécifié. Par exemple, si TYPE=BDB est spécifié, et que la distribution de MySQL ne supporte pas les tables BDB, la table qui sera créée sera du type MyISAM.

Les autres options de tables sont utilisées pour optimiser le comportement de la table. Dans la plupart des cas, vous n'avez pas à les spécifier. Les options fonctionnent pour tous les types de tables (sauf contre-indication) :

- AUTO_INCREMENT

La prochaine valeur AUTO_INCREMENT de votre table (MyISAM). Ne fonctionne que pour les tables MyISAM. Pour donner la première valeur à une colonne AUTO_INCREMENT InnoDB, insérez une ligne bidon, avec la valeur désirée moins un, puis supprimez la ligne.

- AVG_ROW_LENGTH

La taille moyenne approchée des lignes de votre table. Vous ne devez fournir cette valeur que pour les tables à taille de ligne variable, de très grande taille.

Lorsque vous créez une table MyISAM, MySQL utilise le produit des options MAX_ROWS et AVG_ROW_LENGTH pour décider de la taille du résultat. Si vous ne spécifiez aucune option, la taille maximale de la table sera de 4 Go (ou 2 Go si votre système d'exploitation ne supporte que les tables de 2 Go). Ceci sert à conserver la taille des pointeurs d'index petite, et rapide, si nous n'avez pas besoin de gros fichiers. Si vous voulez que vos tables dépassent 4 Go de taille, et que vous voulez garder les tables de petite taille un peu plus lentes et grosses que nécessaire, vous pouvez augmenter la taille du pointeur d'index en modifiant la variable système globale myisam_data_pointer_size, qui a été ajoutée en MySQL 4.1.2. Voir Section 5.2.3, « Variables serveur système ».

- CHECKSUM

Passez 1 si vous voulez que MySQL génère une somme de vérification (ce qui facilite la recherche des lignes corrompues, mais ralentit les mises à jour). La commande CHECKSUM TABLE rapporte cette somme. MyISAM uniquement.

- COMMENT

Un commentaire pour votre table (60 caractères).

- MAX_ROWS

Nombre de lignes maximum que vous pensez stocker dans la table.

- MIN_ROWS

Nombre de minimum lignes que vous pensez stocker dans la table.

- PACK_KEYS

Spécifiez 1 si vous voulez un index plus compact. Généralement cela rend les mises à jour plus lentes, mais les lectures plus rapides.

Spécifier la valeur de 0 désactive tout le compactage de clé. Spécifier la valeur DEFAULT (MySQL 4.0) indique au moteur de stockage de ne stocker que les colonnes CHAR/VARCHAR. (MyISAM et ISAM uniquement).

Si vous n'utilisez pas PACK_KEYS, le comportement par défaut est de ne stocker que les chaînes, et non pas les nombres. Si vous utilisez PACK_KEYS=1, les nombres seront aussi compactés.

Lors du compactage, MySQL utilise une compression de préfixe.

- Chaque clé requiert un octet de plus pour indiquer combien d'octets sont identiques dans la clé précédente.

- Le pointeur de ligne est stocké au format grand-octet-en-premier, directement après la clé, pour améliorer la compression.

Cela signifie que si vous avez de nombreuses clés proches sur des lignes consécutives, les clés successives « identiques » ne prendront généralement que deux octets (incluant le pointeur de ligne). Comparez cela à la situation ordinaire, où les clés successives occupent taille_de_cle + taille_de_pointeur (où la taille du pointeur est généralement de 4). En conséquence, vous tirerez le meilleur parti de cette compression si vous avez plusieurs nombres identiques. Si toutes les clés sont totalement différentes, vous utiliserez un octet de plus par clé, si la clé n'accepte pas les valeurs NULL. Dans ce cas, la taille de la clé sera stockée dans le même octet que celui qui indique que la clé est NULL.)

- PASSWORD

Chiffre le fichier .frm avec un mot de passe. Cette option ne fait rien du tout pour la version standard de MySQL.

- DELAY_KEY_WRITE

Spécifiez 1 si vous voulez attendre la fermeture de la table pour mettre à jour les index. MyISAM uniquement.

- ROW_FORMAT

Définit la méthode de stockage des lignes (réservé pour le futur). Actuellement, cette option fonctionne uniquement avec des tables MyISAM qui supportent le DYNAMIC et FIXED en format de ligne. Voir Section 14.1.3, « Formats de table MyISAM ».

- RAID_TYPE

L'option RAID_TYPE vous permet de dépasser la limite de 2 Go/4 Go de votre fichier de données MyISAM (mais pas le fichier d'index), pour les systèmes d'exploitation qui ne supportent pas les grands fichiers. Cette option n'est pas recommandée pour les systèmes d'exploitation qui supportent les grands fichiers.

Vous pouvez réduire les ralentissements d'E/S en plaçant les dossiers RAID sur différents disques physiques. Actuellement, le seul type RAID_TYPE est STRIPED. 1 et RAID0 sont des alias de STRIPED.

Si vous spécifiez l'option RAID_TYPE pour une table MyISAM, spécifiez les options RAID_CHUNKS et RAID_CHUNKSIZE en même temps. La valeur maximale de RAID_CHUNKS est 255. MyISAM va créer RAID_CHUNKS sous-dossiers appelés 00, 01, 02, ... 09, 0a, 0b, ... dans le dossier de données. Dans chaque dossier, MyISAM va créer un fichier tbl_name.MYD. Lors de l'écriture dans le fichier de données, le gestionnaire RAID place les RAID_CHUNKSIZE*1024 premiers octets dans le premier fichier, les seconds RAID_CHUNKSIZE*1024 octets dans le fichier suivant, etc.

RAID_TYPE fonctionne sur tous les systèmes d'exploitation, tant que vous avez compilé MySQL avec --with-raid, avec le script configure. Pour déterminer si votre serveur a le support des tables RAID, utilisez SHOW VARIABLES LIKE 'have_raid' pour voir si sa valeur vaut YES.

- UNION

UNION sert lorsque vous voulez que plusieurs tables identiques se comportent comme une seule table. Cela fonctionne avec les tables MERGE. Voir Section 14.2, « Tables assemblées MERGE ».

Pour le moment, vous devez avoir les droits de SELECT, UPDATE et DELETE pour les tables intégrées dans la table MERGE. Originalement, toutes les tables utilisées devaient être dans la même base de données, que la table MERGE. Cette restriction a été levée depuis MySQL 4.1.1.

- INSERT_METHOD

Si vous voulez insérer des données dans une table MERGE, vous devez spécifier la table d'insertion avec l'attribut INSERT_METHOD. L'option INSERT_METHOD est utilisée uniquement avec les tables MERGE. Cette option a été introduite en MySQL 4.0.0. Voir Section 14.2, « Tables assemblées MERGE ».

- DATA DIRECTORY, INDEX DIRECTORY

En utilisant DATA DIRECTORY='directory' ou INDEX DIRECTORY='directory', vous pouvez spécifier où le moteur de stockage MyISAM doit placer les données de la table et le fichier d'index. Notez que vous devez donner un chemin absolu, et non un chemin relatif.

Ces options ne fonctionnent que pour les tables MyISAM depuis MySQL 4.0, lorsque vous n'utilisez pas l'option --skip-symlink. Votre système d'exploitation doit aussi disposer d'une fonction realpath() compatible avec les threads. Voir Section 7.6.1.2, « Utiliser les liens symboliques avec les tables sous Unix ».

Depuis MySQL 3.23, vous pouvez créer une table à partir d'une autre, en ajoutant une commande SELECT après la commande CREATE TABLE :

CREATE TABLE new_tbl SELECT * FROM orig_tbl;

MySQL va créer une nouvelle colonne pour chaque colonne de résultat de la commande SELECT. Par exemple :

mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
->        PRIMARY KEY (a), KEY(b))
->        TYPE=MyISAM SELECT b,c FROM test2;

Cela créer une table MyISAM avec trois colonnes a, b, et c. Notez que les colonnes de la commande SELECT sont ajoutées à droite de la table, et non dans la liste des colonnes. Par exemple :

mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+

mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM bar;
+------+---+
| m    | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)

Pour chaque ligne de la table foo, une ligne est insérée dans la colonne bar avec la valeur issue de foo et la valeur par défaut pour les nouvelles colonnes.

Si une erreur survient durant la copie de la table, la table est automatiquement effacée.

CREATE TABLE ... SELECT ne va pas créer automatiquement les index pour vous. Ceci est fait intentionnellement pour rendre la commande aussi souple que possible. Si vous voulez avoir les mêmes index, vous devez les spécifier dans la commande avant le SELECT :

mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

Certaines conversions de type pourraient avoir lieu. Par exemple, l'attribut AUTO_INCREMENT n'est pas préservé, et les colonnes VARCHAR peuvent devenir des colonnes CHAR.

Lors de la création de la table avec CREATE ... SELECT, assurez-vous de mettre un nom d'alias à toutes les fonctions ou expressions de la requête. Si vous ne le faites pas, la commande CREATE peut échouer ou donner des noms de colonnes inattendus.

CREATE TABLE artists_and_works
SELECT artist.name, COUNT(work.artist_id) AS number_of_works
FROM artist LEFT JOIN work ON artist.id = work.artist_id
GROUP BY artist.id;

Depuis MySQL 4.1, vous pouvez spécifier explicitement le type de colonne généré :

CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

En MySQL 4.1, vous pouvez aussi utiliser la clause LIKE pour créer une table basée sur la définition d'une autre table, y compris les attributs de colonnes et les index originaux :

CREATE TABLE new_tbl LIKE orig_tbl;

CREATE TABLE ... LIKE ne copie pas les options de tables DATA DIRECTORY et INDEX DIRECTORY qui étaient spécifiées dans la table originale.

Vous pouvez faire précéder SELECT par IGNORE ou REPLACE pour indiquer comment gérer les clés doublons. Avec IGNORE, les nouvelles lignes qui sont en double seront ignorées. Avec REPLACE, les nouvelles lignes remplaceront les lignes précédentes, qui avaient la même valeur d'index. Si ni IGNORE, ni REPLACE ne sont spécifiés, les doublons génèreront une erreur.

Pour s'assurer que le log binaire peut être réutilisé pour recréer la table originale, MySQL ne permettra pas les insertions concurrentes durant une commande CREATE TABLE ... SELECT.

13-2-5-1 - Modification automatique du type de colonnes

Dans certains cas, MySQL change automatiquement la spécification d'une colonne fournie dans la commande CREATE TABLE. (Cela peut aussi arriver avec ALTER TABLE).

- Les colonnes VARCHAR avec une taille inférieure à quatre (4) sont changées en CHAR.

- Si l'une des colonnes d'une table est de taille variable, toute la ligne est, par conséquent, de taille variable. Ainsi, si une ligne contient une colonne de taille variable (VARCHAR, TEXT ou BLOB) toutes les colonnes CHAR de plus de trois caractères sont transformées en VARCHAR. Cela ne change en rien la façon dont vous utilisez les colonnes. Pour MySQL, VARCHAR est simplement une autre façon de stocker les caractères. MySQL effectue cette conversion, car cela économise de la place, et rend les calculs sur les tables plus rapides. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- Depuis la version 4.1.0, si un champ CHAR ou VARCHAR est spécifié avec une taille supérieure à 255, il est converti en TEXT. C'est une fonctionnalité de compatibilité.

- La taille d'affichage de TIMESTAMP doit être un nombre pair et être compris entre 2 et 14. (2, 4, 6, 8, 10, 12 ou 14). Si vous spécifiez une taille plus grande que 14, ou inférieure à 2, celle-ci sera transformée en 14. Les valeurs impaires sont ramenées à la valeur paire supérieure la plus proche.

- Vous ne pouvez pas stocker de valeur littérale NULL dans une colonne de type TIMESTAMP. Cette valeur sera remplacée par la date et l'heure courante. De ce fait, les attributs NULL et NOT NULL n'ont pas de sens pour ces colonnes et sont ignorés. DESCRIBE nom_de_table indiquera toujours que la colonne TIMESTAMP accepte les valeurs NULL.

- Les colonnes qui font partie d'une PRIMARY KEY ont l'attribut NOT NULL même si elles ne sont pas déclarées comme telles.

- Depuis MySQL 3.23.51, les espaces terminaux sont automatiquement supprimés des valeurs ENUM et SET lors de la création de la table.

- MySQL change certains types de colonnes utilisés par d'autres serveurs SQL en types MySQL. Voir Section 11.7, « Utilisation des types de données issues d'autres SGBDR ».

- Si vous utilisez une clause USING pour spécifier un type d'index qui n'est pas légal pour un moteur de stockage, mais qu'un autre type d'index est disponible pour ce moteur sans affecter les résultats, le moteur utilisera le type disponible.

Si vous voulez voir si MySQL a utilisé un autre type que celui que vous avez spécifié, utilisez la commande DESCRIBE nom_de_table, après votre création ou modification de structure de table.

Certain types de colonnes peuvent être modifiés si vous compressez une table en utilisant l'utilitaire myisampack. Voir Section 14.1.3.3, « Caractéristiques des tables compressées ».

13-2-6 - Syntaxe de DROP DATABASE

DROP DATABASE [IF EXISTS] db_name

DROP DATABASE détruit toutes les tables dans la base de données et l'efface elle-même. Soyez très prudent avec cette commande ! Pour utiliser la commande DROP DATABASE, vous avez besoin du droit de DROP sur cette base.

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot-clé IF EXISTS pour éviter l'affichage d'erreur si la base n'existe pas.

Si vous utilisez la commande DROP DATABASE sur un lien symbolique pointant sur la base de données, le lien et la base seront effacés.

Depuis MySQL 4.1.2, DROP DATABASE retourne le nombre de tables qui ont été supprimés. Cela revient à compter le nombre de fichiers .frm qui ont été supprimées.

La commande DROP DATABASE efface tous les fichiers du dossier de la base de données, qui ont été créés par MySQL lui-même, durant ses opérations normales.

- Tous les fichiers avec les extensions suivantes :

.BAK

.DAT

.HSH

.ISD

.ISM

.ISM

.MRG

.MYD

.MYI

.db

.frm

- Tous les sous-dossiers qui consistent de 2 chiffres hexadécimaux 00-ff. Ce sont des dossiers RAID) qui sont aussi supprimés.

- Le fichier db.opt, s'il existe.

Si d'autres fichiers ou dossiers restent dans le dossier de base après que MySQL a supprimé ceux listés ci-dessus, le dossier de base ne pourra pas être supprimé. Dans ce cas, vous devez supprimer manuellement les fichiers restants, et lancer à nouveau la commande DROP DATABASE.

Vous pouvez aussi supprimer des bases de données avec mysqladmin. Voir Section 8.4, « mysqladmin, administration d'un serveur MySQL ».

13-2-7 - Syntaxe de DROP INDEX

DROP INDEX nom_de_l_index ON nom_de_table

DROP INDEX supprime l'index nommé nom_de_l_index de la table nom_de_table. DROP INDEX ne fait rien avec la version 3.22 et les précédentes. Depuis cette version, DROP INDEX est un alias d'ALTER TABLE supprimant l'index.

Voir Section 13.2.2, « Syntaxe de ALTER TABLE ».

13-2-8 - Syntaxe de DROP TABLE

DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]

DROP TABLE supprime une ou plusieurs tables. Toutes les données et la structure de la table sont perdues, alors soyez prudents avec cette commande !

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot réservé IF EXISTS pour éviter l'affichage des erreurs pour les tables qui n'existent pas. Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

RESTRICT et CASCADE sont autorisés pour faciliter le port. Pour le moment, elles ne font rien.

Note : DROP TABLE va automatiquement valider les transactions actives (hormis si vous utilisez la version 4.1 et le mot-clé TEMPORARY).

L'option TEMPORARY est ignorée en 4.0. En 4.1, cette option fonctionne comme suit.

- Détruit uniquement les tables temporaires.

- Ne termine pas les transactions en cours.

- Aucun droit d'accès n'est vérifié.

TEMPORARY est pour le moment ignoré. Dans un futur proche, il servira à s'assurer qu'on efface vraiment une table temporaire.

13-2-9 - Syntaxe de RENAME TABLE

RENAME TABLE nom_de_table TO nouveau_nom_de_table[, nom_de_table2 TO nouveau_nom_de_table2,...]

Le changement de nom se fait atomiquement ce qui signifie qu'aucun autre processus ne peut accéder à la table tant que l'opération est en cours. Cela rend possible de remplacer une vielle table avec une table vide :

CREATE TABLE nouvelle_table (...);
RENAME TABLE ancienne_table TO backup_table, nouvelle_table TO ancienne_table;

L'opération s'effectue de gauche à droite ce qui signifie que si vous voulez échanger deux noms de tables, vous devez :

RENAME TABLE ancienne_table    TO backup_table,
nouvelle_table    TO ancienne_table,
backup_table TO nouvelle_table;

Si les deux bases de données sont sur le même disque, vous pouvez renommer à travers les bases :

RENAME TABLE bdd_courante.nom_de_table TO autre_bdd.nom_de_table;

Quand vous exécutez RENAME, vous ne pouvez avoir aucune transaction active ou une table protégée en mode écriture. Vous devez avoir les privilèges ALTER et DROP sur l'ancienne table, et les privilèges CREATE et INSERT sur la nouvelle.

Si MySQL rencontre des erreurs dans un renommage multiple, il remettra les noms changés à leur valeur d'origine pour revenir à l'état d'origine.

RENAME TABLE a été ajouté à la version 3.23.23 de MySQL.

13-3 - Commandes de base de l'utilisateur de MySQL

13-3-1 - Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

{DESCRIBE | DESC} nom_de_table [nom_de_colonne | wild]

DESCRIBE fournit des informations à propos des colonnes de la table. DESCRIBE est un raccourci de SHOW COLUMNS FROM.

Voir Section 13.5.3.3, « Syntaxe de SHOW COLUMNS ».

nom_de_colonne peut être le nom d'une colonne ou une chaîne contenant les caractères spéciaux SQL '%' et '_'. Il n'est pas nécessaire de placer la chaîne entre guillemets, hormis s'il y a des espaces ou d'autres caractères spéciaux.

mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  |      | PRI | NULL    | auto_increment |
| Name       | char(35) |      |     |         |                |
| Country    | char(3)  |      | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  |      |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

La colonne Null indique si la valeur NULL peut être stockée dans la colonne. YES indique que c'est le cas.

La colonne Key indique si un champ est indexé. La valeur PRI indique que le champ fait partie de la clé primaire de la table. UNI indique que le champ fait partie d'un index UNIQUE. La valeur MUL indique que plusieurs occurrences d'une valeur sont autorisées dans le champ.

Un champ peut être désigné comme MUL même si l'index UNIQUE est utilisé, si les valeurs NULL sont autorisées, car une colonne UNIQUE peut contenir plusieurs valeurs NULL si la colonne est déclarée comme NOT NULL. Une autre cause pour MUL sur une colonne UNIQUE est lorsque deux colonnes forment un couple UNIQUE : même si la combinaison des deux colonnes est toujours unique, chaque colonne peut contenir des valeurs multiples. Notez que dans un index composé, seul le champ de gauche aura une entrée dans la colonne Key.

La colonne Default indique la valeur par défaut assignée à ce champ.

La colonne Extra indique des informations supplémentaires, disponibles sur le champ. Dans notre exemple, la colonne Extra indique que la colonne Id porte l'attribut AUTO_INCREMENT.

Si le type de colonne est différent de celui que vous pensiez avoir défini lors du CREATE TABLE, notez que MySQL change le type des colonnes de temps en temps. Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

Cette instruction est fournie pour une meilleure compatibilité avec Oracle.

L'instruction SHOW renvoie les mêmes informations. Voir Section 13.5.3, « Syntaxe de SHOW ».

13-3-2 - Syntaxe de USE

USE db_name

La commande USE db_name spécifie à MySQL d'utiliser la base db_name comme base par défaut pour les requêtes ne les mentionnant pas. La base choisie reste la même jusqu'à la fermeture de la session ou un nouvel appel à USE :

mysql> USE db1;
mysql> SELECT COUNT(*) FROM ma_table;      # sélectionne à partir de db1.ma_table
mysql> USE db2;
mysql> SELECT COUNT(*) FROM ma_table;      # sélectionne à partir de db2.ma_table

Rendre une base de données la base courante (en utilisant USE) ne vous interdit pas l'accès à d'autres tables dans d'autres bases. L'exemple suivant accède à la table author de la base db1 et à la table editor de la base db2 :

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
->        WHERE author.editor_id = db2.editor.editor_id;

La commande USE est fournie pour assurer la compatibilité Sybase.

13-4 - Commandes relatives aux verrous et aux transactions

13-4-1 - Syntaxes de START TRANSACTION, COMMIT et ROLLBACK

Par défaut, MySQL est lancé en mode autocommit. Cela signifie que chaque modification effectuée est enregistrée immédiatement sur le disque par MySQL.

Si vous utilisez des tables supportant les transactions (comme InnoDB, BDB), vous pouvez configurer MySQL en mode non autocommit grâce à la commande :

SET AUTOCOMMIT=0

À partir de là, vous devez utiliser COMMIT pour enregistrer les modifications sur le disque ou ROLLBACK pour ignorer les modifications apportées depuis le début de la transaction.

Si vous souhaitez sortir du mode AUTOCOMMIT pour une série d'opérations, vous pouvez utiliser les commandes BEGIN ou BEGIN WORK :

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

BEGIN et BEGIN WORK peuvent être utilisés à la place de START TRANSACTION pour initialiser une transaction. START TRANSACTION a été ajouté en MySQL 4.0.11. C'est une syntaxe SQL-99, et il est recommandé de l'utiliser pour lancer une transaction. BEGIN et BEGIN WORK sont disponibles pour MySQL 3.23.17 et 3.23.19, respectivement.

Notez que si vous n'utilisez pas de table transactionnelle, les modifications seront validées automatiquement, indépendamment du mode de validation.

Si vous faites un ROLLBACK après avoir modifié une table non transactionnelle, vous obtiendrez (ER_WARNING_NOT_COMPLETE_ROLLBACK) comme message d'alerte. Toutes les tables supportant les transactions seront restaurées, mais aucune des autres tables ne changera.

Si vous utilisez START TRANSACTION ou SET AUTOCOMMIT=0, il est recommandé d'utiliser les « binary log » de MySQL à la place des anciens logs de modifications pour les sauvegardes. Les transactions sont stockées dans les logs binaires en un seul bloc, après COMMIT, pour être sûr que les transactions qui ont été annulées ne soient pas enregistrées. Voir Section 5.9.4, « Le log binaire ».

Vous pouvez changer le niveau d'isolation des transactions avec SET TRANSACTION ISOLATION LEVEL .... Voir Section 13.4.6, « Syntaxe de SET TRANSACTION  ».

13-4-2 - Commandes qui ne peuvent pas être annulées

Certaines commandes ne peuvent pas être annulées. En général, elles incluent le langage de définition des données (DDL), comme les commandes qui créent ou effacent des bases de données, ou celles qui créent, modifient ou effacent des tables de données.

Il est recommandé de concevoir vos transactions pour éviter ces commandes. Si vous soumettez une commande qui ne peut pas être annulée, dès le début de votre transaction, et qu'une commande ultérieure échoue, vous ne pourrez pas annuler l'ensemble de la transaction avec ROLLBACK.

13-4-3 - Commandes qui peuvent causer une validation implicite

Les commandes suivantes valident implicitement une transaction, comme si vous aviez émis une commande COMMIT après :

ALTER TABLE

BEGIN

CREATE INDEX

DROP DATABASE

DROP INDEX

DROP TABLE

LOAD MASTER DATA

LOCK TABLES

RENAME TABLE

SET AUTOCOMMIT=1

START TRANSACTION

TRUNCATE

UNLOCK TABLES termine aussi une transaction si toutes les tables courantes sont verrouillées. Avant MySQL version 4.0.13, CREATE TABLE terminait une transaction si le log binaire était activé.

Les transactions ne peuvent pas être imbriquées. C'est la conséquence de cette validation COMMIT implicite pour toutes les transactions en cours, lorsque vous émettez une commande START TRANSACTION ou équivalent.

13-4-4 - Syntaxe de SAVEPOINT et ROLLBACK TO SAVEPOINT

Depuis MySQL 4.0.14 et 4.1.1, InnoDB supporte les commandes SQL SAVEPOINT et ROLLBACK TO SAVEPOINT.

SAVEPOINT identifier

Cette commande pose un jalon de transaction dont le nom est identifier. Si la transaction courante a déjà un jalon de ce nom, l'ancien jalon est effacé, et le nouveau est créé à la place.

Cette commande annule la transaction jusqu'au jalon. Les modifications que cette transaction a faites aux lignes depuis le jalon sont annulées, mais InnoDB ne libère pas les verrous posés en mémoire après le jalon. Notez que pour une nouvelle ligne insérée, l'information de verrou est conservée par l'identifiant de transaction de la ligne : le verrou n'est pas stocké en mémoire. Dans ce cas, le verrou sera levé par l'annulation. Les jalons qui ont été posés après celui-ci sont aussi annulés.

Si la commande retourne l'erreur suivante, c'est qu'aucun jalon de ce nom n'a pu être trouvé.

ERROR 1181: Got error 153 during ROLLBACK

Tous les jalons de la transaction courante sont annulés si vous exécutez les commandes COMMIT ou ROLLBACK, sans préciser de nom de jalon.

13-4-5 - Syntaxe de LOCK TABLES/UNLOCK TABLES

LOCK TABLES
tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
UNLOCK TABLES

LOCK TABLES verrouille une table pour le thread courant. UNLOCK TABLES déverrouillera automatiquement tous les verrous posés par le thread courant. Toutes les tables verrouillées par le thread courant sont automatiquement déverrouillées quand ce thread utilise à nouveau LOCK TABLES, ou quand la connexion au serveur est perdue.

Note : LOCK TABLES n'est pas compatible avec les transactions, et valide automatiquement toute transaction active avant de verrouiller une table.

L'utilisation de LOCK TABLES dans MySQL 4.0.2 nécessite le privilège LOCK TABLES global et un privilège de SELECT sur les tables impliquées. Dans MySQL 3.23, il faut les privilèges SELECT, INSERT, DELETE et UPDATE sur les tables.

Les principales raisons d'utiliser LOCK TABLES sont l'émulation de transactions ou l'accélération des processus de modification de tables. Cela sera détaillé plus loin.

Si un thread obtient un verrouillage READ sur une table, ce thread (et tous les autres threads) peut uniquement accéder à cette table en lecture. Si un thread obtient un verrouillage WRITE sur une table, alors seul le thread qui a posé le verrou peut lire ou écrire sur cette table. Tous les autres threads sont bloqués.

La différence entre READ LOCAL et READ est que READ LOCAL autorise des requêtes INSERT non conflictuelles à être exécutées alors que le verrou est posé. Ceci ne peut cependant pas être utilisé si vous souhaitez modifier les fichiers de la base de données en dehors de MySQL pendant que le verrou est posé.

Quand vous utilisez LOCK TABLES, vous devez verrouiller toutes les tables que vous allez utiliser, et vous devez utiliser les mêmes alias sur ce que vous utiliserez dans vos requêtes ! Si vous utilisez une table a plusieurs reprises dans une requête (avec des alias), vous devez verrouiller chacun des alias !

Si vos requêtes utilisent un alias pour une table, alors vous devez verrouiller la table avec l'alias. Le verrouillage ne fonctionnera pas si vous verrouillez la table sans spécifier l'alias :

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

De même, lorsque vous verrouillez une table avec un alias, vous devez utiliser le nom de l'alias dans vos requêtes :

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

Les verrous WRITE ont normalement des priorités supérieures aux verrous READ, afin de s'assurer que les modifications sont exécutées au plus vite. Cela signifie que si un thread demande un verrou READ et qu'un autre thread demande un verrou WRITE, la demande de verrou READ attendra que le thread WRITE ait abouti pour libérer le verrou. Vous pouvez utiliser le verrou LOW_PRIORITY WRITE pour permettre à d'autres threads d'obtenir des verrous READ pendant que le thread attend le verrou WRITE. Vous ne devriez utiliser les verrous LOW_PRIORITY WRITE que si vous êtes sûr qu'il y aura effectivement un moment où aucun thread ne posera de verrou READ.

LOCK TABLES fonctionne de la manière suivante.

1. Trie toutes les tables à verrouiller dans un ordre défini par MySQL (l'utilisateur ne définit pas d'ordre).

2. Si une table est verrouillée avec un verrou de lecture et un verrou d'écriture, il pose le verrou de lecture avant celui d'écriture.

3. Verrouille une table à la fois jusqu'à ce que le thread ait tous ses verrous.

Cette politique garantit le bon verrouillage des tables. Il faut cependant connaître certaines choses sur ce schéma.

Si vous utilisez un verrou LOW_PRIORITY WRITE pour une table, cela signifie seulement que MySQL attendra, pour poser ce verrou, qu'aucun autre thread ne réclame de verrou READ. Quand le thread aura le verrou WRITE et qu'il attendra que les verrous soient posés sur les autres tables de la liste, tous les autres threads attendront que le verrou WRITE soit libéré. Si cela devient un problème grave pour votre application, il est conseillé de convertir des tables en tables supportant les transactions.

Vous pouvez terminer un thread attendant un verrouillage de table en toute sécurité avec KILL. Voir Section 13.5.4.3, « Syntaxe de KILL ».

Il est déconseillé de verrouiller des tables utilisées avec INSERT DELAYED, car dans ce cas, la requête INSERT est exécutée dans un autre thread.

Normalement, vous n'avez pas besoin de verrouiller les tables puisque chaque requête UPDATE est atomique : aucun autre thread ne peut interférer avec une autre requête active. Il existe cependant quelques cas où vous aurez besoin de verrouiller les tables.

- Si vous allez exécuter plusieurs requêtes sur plusieurs tables, il est préférable, d'un point de vue rapidité, de verrouiller les tables dont vous aurez besoin. L'inconvénient, bien sûr, est que les autres threads ne pourront pas intervenir sur ces tables durant vos opérations, ni en extraire des informations si la table est verrouillée en WRITE.

La raison pour laquelle les requêtes sont plus rapides avec LOCK TABLES est que MySQL ne rafraîchît pas l'index des clés des tables verrouillées tant que UNLOCK TABLES n'est pas invoqué (normalement, le cache des clés est rafraîchi après chaque requête SQL). Cela accélère les insertions, les modifications et les suppressions de données dans les tables MyISAM.

- Si vous utilisez un type de table dans MySQL qui ne supporte pas les transactions, vous devez utiliser LOCK TABLES pour vous assurez qu'aucun autre thread ne s'intercale entre un SELECT et un UPDATE. L'exemple suivant nécessite LOCK TABLES pour s'exécuter en toute sécurité :

mysql> LOCK TABLES trans READ, customer WRITE;
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql> UPDATE customer SET total_value=sum_from_previous_statement
->        WHERE customer_id=some_id;
mysql> UNLOCK TABLES;

Sans LOCK TABLES, Il est possible qu'un autre thread ait inséré une nouvelle ligne dans la table trans entre l'exécution du SELECT et l'exécution de la requête UPDATE.

L'utilisation de modifications incrémentales (UPDATE customer SET value=value+nouvelle_valeur) ou de la fonction LAST_INSERT_ID() permet de se passer de LOCK TABLES dans de nombreuses situations. Voir Section 1.5.5.3, « Transactions et opérations atomiques ».

Il est aussi possible de résoudre de nombreux cas en utilisant un verrou utilisateur, avec les fonctions GET_LOCK() et RELEASE_LOCK(). Ces verrous sont stockés dans une table de hashage dans le serveur et utilisent les fonctions pthread_mutex_lock() et pthread_mutex_unlock() pour plus de vitesse. Voir Section 12.8.4, « Fonctions diverses ».

Voir Section 7.3.1, « Méthodes de verrouillage » pour plus de détails.

Il est possible de verrouiller toutes les tables de toutes les bases avec la commande FLUSH TABLES WITH READ LOCK.

Voir Section 13.5.4.2, « Syntaxe de FLUSH ». C'est une méthode très pratique pour effectuer des sauvegardes si vous utilisez un système de fichiers qui, comme Veritas, permet de créer des instantanés.

Note : LOCK TABLES ne fonctionne pas avec les transactions et validera automatiquement toutes les transactions actives avant de verrouiller la table. Voir Section A.7.1, « Problèmes avec ALTER TABLE. ».

13-4-6 - Syntaxe de SET TRANSACTION

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

Configuration du niveau d'isolation des transactions en général, pour la totalité de la session, ou pour la prochaine transaction.

Le comportement par défaut est de configurer le niveau d'isolation pour la transaction suivante (qui n'a pas encore été commencée). En utilisant le paramètre GLOBAL, on configure le niveau par défaut global pour toutes les nouvelles connexions. Cette commande requiert les privilèges SUPER. En utilisant le paramètre SESSION, on configure le niveau par défaut pour toutes les prochaines transactions effectuées durant la session actuelle.

Pour une description de chaque niveau d'isolation de transaction InnoDB, voyez Section 15.11.2, « InnoDB et SET ... TRANSACTION ISOLATION LEVEL ... ». InnoDB supporte chacun des niveaux depuis MySQL 4.0.5. Le niveau par défaut est REPEATABLE READ.

On peut configurer le niveau d'isolation global des transactions pour mysqld avec --transaction-isolation=.... Voir Section 4.3.1, « Options de ligne de commande de mysqld ».

13-5 - Référence de langage d'administration de la base de données

13-5-1 - Commande de gestion des comptes utilisateur

13-5-1-1 - Syntaxe de CREATE USER

CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...

La commande CREATE USER crée un nouveau compte MySQL. Pour l'utiliser, vous devez avoir les droits de CREATE USER ou les droits d'INSERT dans la table de droits de la base mysql. Pour chaque compte, CREATE USER crée un nouvel enregistrement dans la table mysql.user, sans aucun droit. Une erreur survient si le compte existe déjà. Le compte peut recevoir un mot de passe avec la clause optionnelle IDENTIFIED BY. La valeur user et le mot de passe sont donnés de la même manière que dans la commande GRANT.

La commande CREATE USER a été ajoutée en MySQL 5.0.2.

13-5-1-2 - Effacer des utilisateurs MySQL

DROP USER user_name

Cette commande a été ajoutée en MySQL 4.1.1.

Elle efface un utilisateur qui n'a aucun droit.

Pour effacer un utilisateur dans MySQL, vous devriez utiliser l'une des procédures suivantes, dans cet ordre :

1. Vérifiez les droits de l'utilisateur avec la commande SHOW PRIVILEGES. Voir Section 13.5.3.13, « SHOW PRIVILEGES » ;

2. Effacez tous les droits de l'utilisateur avec la commande REVOKE. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE » ;

3. Effacez l'utilisateur avec DROP USER.

Si vous utilisez une vieille version de MySQL, vous devriez commencer par effacer les droits, puis l'utilisateur avec :

DELETE FROM mysql.user WHERE user='username' and host='hostname';
FLUSH PRIVILEGES;

13-5-1-3 - Syntaxe de GRANT et REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON {tbl_name | * | *.* | db_name.*}
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
[REQUIRE
NONE |
[{SSL| X509}]
[CIPHER cipher [AND]]
[ISSUER issuer [AND]]
[SUBJECT subject]]
[WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR count |
MAX_UPDATES_PER_HOUR count |
MAX_CONNECTIONS_PER_HOUR count]]

REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON {tbl_name | * | *.* | db_name.*}
FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Les commandes GRANT et REVOKE permettent à l'administrateur système de créer et supprimer des comptes utilisateur et de leur donner ou retirer des droits. GRANT et REVOKE sont implémentées en MySQL 3.22.11 ou plus récents. Pour les anciennes versions de MySQL, ces commandes ne font rien.

Les informations sur les comptes MySQL sont stockées dans la base mysql. Cette base et son accès sont présentés en détail dans le Chapitre 5, Administration du serveur.

Les droits sont donnés à quatre niveaux.

- Niveau global

Les droits globaux s'appliquent à toutes les bases de données d'un serveur. Ces droits sont stockés dans la table mysql.user. REVOKE ALL ON *.* retirera seulement les privilèges globaux.

- Niveau base de données

Les droits de niveau de base de données s'appliquent à toutes les tables d'une base de données. Ces droits sont stockés dans les tables mysql.db et mysql.host. REVOKE ALL ON db.* retirera seulement les privilèges de base de données.

- Niveau table

Les droits de table s'appliquent à toutes les colonnes d'une table. Ces droits sont stockés dans la table mysql.tables_priv. REVOKE ALL ON db.table retirera seulement les privilèges de table.

- Niveau colonne

Les droits de niveau de colonnes s'appliquent à des colonnes dans une table. Ces droits sont stockés dans la table mysql.columns_priv. Quand vous utilisez REVOKE vous devez spécifier les mêmes colonnes qui s'étaient vu accorder des privilèges.

Pour faciliter la suppression de tous les droits d'un utilisateur, MySQL 4.1.2 a ajouté la syntaxe suivante, qui efface tous les droits de base, table et colonne pour un utilisateur donné :

REVOKE ALL PRIVILEGES,GRANT FROM user_name [, user_name ...]

Avant MySQL 4.1.2, tous les droits ne peuvent pas être effacés d'un coup. Il faut deux commandes pour cela :

REVOKE ALL PRIVILEGES FROM user [, user] ...
REVOKE GRANT OPTION FROM user [, user] ...

Pour les commandes GRANT et REVOKE, la clause priv_type peut être spécifiée par les constantes suivantes :

Droit

Signification

ALL [PRIVILEGES]

Tous les droits sauf WITH GRANT OPTION.

ALTER

Autorise l'utilisation de ALTER TABLE.

CREATE

Autorise l'utilisation de CREATE TABLE.

CREATE TEMPORARY TABLES

Autorise l'utilisation de CREATE TEMPORARY TABLE.

DELETE

Autorise l'utilisation de DELETE.

DROP

Autorise l'utilisation de DROP TABLE.

EXECUTE

Autorise l'utilisateur à exécuter des procédures stockées (pour MySQL 5.0).

FILE

Autorise l'utilisation de SELECT ... INTO OUTFILE et LOAD DATA INFILE.

INDEX

Autorise l'utilisation de CREATE INDEX et DROP INDEX.

INSERT

Autorise l'utilisation de INSERT.

LOCK TABLES

Autorise l'utilisation de LOCK TABLES sur les tables pour lesquelles l'utilisateur a les droits de SELECT.

PROCESS

Autorise l'utilisation de SHOW FULL PROCESSLIST.

REFERENCES

Réservé pour le futur.

RELOAD

Autorise l'utilisation de FLUSH.

REPLICATION CLIENT

Donne le droit à l'utilisateur de savoir où sont les maîtres et esclaves.

REPLICATION SLAVE

Nécessaire pour les esclaves de réplication (pour lire les historiques binaires du maître).

SELECT

Autorise l'utilisation de SELECT.

SHOW DATABASES

SHOW DATABASES affiche toutes les bases de données.

SHUTDOWN

Autorise l'utilisation de mysqladmin shutdown.

SUPER

Autorise une connexion unique même si max_connections est atteint, et l'exécution des commandes CHANGE MASTER, KILL thread, mysqladmin debug, PURGE MASTER LOGS et SET GLOBAL.

UPDATE

Autorise l'utilisation de UPDATE.

USAGE

Synonyme de « pas de droit ».

GRANT OPTION

Synonyme pour WITH GRANT OPTION

USAGE peut être utilisé lorsque vous voulez créer un utilisateur sans aucun droit.

Les droits de CREATE TEMPORARY TABLES, EXECUTE, LOCK TABLES, REPLICATION ..., SHOW DATABASES et SUPER sont nouveaux en version 4.0.2. Pour utiliser ces droits après mise à jour en 4.0.2, vous devez exécuter le script mysql_fix_privilege_tables. Voir Section 2.6.7, « Mise à jour des tables de droits ».

Dans les anciennes versions de MySQL, le droit de PROCESS donnait les mêmes droits que le nouveau droit SUPER.

Vous pouvez donner des droits globaux en utilisant la syntaxe ON *.*. Vous pouvez donner des droits de base en utilisant la syntaxe ON nom_base.*. Si vous spécifiez ON * et que vous avez une base de données qui est déjà sélectionnée, vous allez donner des droits pour la base de données courante. Attention : si vous spécifiez ON * et que vous n'avez pas de base courante, vous allez affecter les droits au niveau du serveur !

Les droits EXECUTION, FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWN et SUPER sont des droits d'administration, qui ne peuvent être donnés que globalement (avec la syntaxe ON *.*).

Les autres droits peuvent être donnés globalement ou à des niveaux plus spécifiques.

Les seuls droits priv_type que vous pouvez donner au niveau d'une table sont SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEX et ALTER.

Les seuls droits priv_type que vous pouvez donner au niveau d'une colonne (avec la clause column_list) sont SELECT, INSERT et UPDATE.

GRANT ALL assigne des droits que vous possédez au niveau où vous les possédez. Par exemple, si vous utilisez GRANT ALL ON db_name.*, qui est un droit de niveau de base de données, aucun des droits globaux, comme FILE ne sera donné.

MySQL vous permet de donner des droits au niveau d'une base de données, même si la base de données n'existe pas, pour vous aider à préparer l'utilisation de la base de données. Actuellement, MySQL ne vous permet pas de créer des droits pour une table si la table n'existe pas.

MySQL ne supprime pas les droits lorsqu'un utilisateur efface une table ou une base.

Notez bien : les caractères jokers '_' et '%' sont autorisés lors de la spécification de noms dans la commande GRANT. Cela signifie que si vous voulez utiliser par exemple le caractère littéral '_' comme nom de base, vous devez le spécifier sous la forme '\_' dans la commande GRANT, pour éviter à l'utilisateur d'accéder à d'autres bases, dont le nom pourrait correspondre au masque d'expression régulière ainsi créé. Utilisez plutôt GRANT ... ON `foo\_bar`.* TO ....

Afin de permettre l'identification des utilisateurs depuis des hôtes arbitraires, MySQL supporte la spécification du nom d'utilisateur nom_utilisateur sous la forme user@host. Si vous voulez spécifier un nom d'utilisateur user qui contient des caractères spéciaux tels que '-', ou une chaîne d'hôte host qui contient des caractères jokers (comme '%'), vous pouvez placer le nom de l'utilisateur ou de l'hôte entre guillemets (par exemple, 'test-utilisateur'@'test-nomdhote').

Vous pouvez spécifier des caractères jokers dans le nom d'hôte. Par exemple, user@'%.loc.gov' fait correspondre l'utilisateur user de n'importe quel hôte du domaine loc.gov, et user@'144.155.166.%' fait correspondre l'utilisateur user à n'importe quelle adresse de la classe C 144.155.166.

La forme simple de user est synonyme de user@"%".

MySQL ne supporte pas de caractères jokers dans les noms d'utilisateur. Les utilisateurs anonymes sont définis par l'insertion de ligne avec User='' dans la table mysql.user, ou en créant un utilisateur avec un nom vide, grâce à la commande GRANT.

mysql> GRANT ALL ON test.* TO ''@'localhost' ...

Attention : si vous autorisez des utilisateurs anonymes à se connecter à votre serveur, vous devriez aussi donner ces droits à tous les utilisateurs locaux user@localhost, car sinon, la ligne dans la table mysql.user sera utilisée lorsque l'utilisateur se connectera au serveur MySQL depuis la machine locale ! (Ce compte est créé durant l'installation de MySQL.)

Vous pouvez vérifier si cela s'applique à vous en exécutant la requête suivante :

mysql> SELECT Host,User FROM mysql.user WHERE User='';

Si vous voulez effacer les utilisateurs anonymes d'un serveur, utilisez ces commandes :

mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;

Actuellement, la commande GRANT supporte uniquement les noms d'hôte, colonne, table et base de données d'au plus 60 caractères. Un nom d'utilisateur peut être d'au plus 16 caractères.

Les droits pour les tables et colonnes sont combinés par OU logique, avec les quatre niveaux de droits. Par exemple, si la table mysql.user spécifie qu'un utilisateur a un droit global de SELECT, ce droit ne pourra pas être annulé au niveau base, table ou colonne.

Les droits d'une colonne sont calculés comme ceci :

droit global
OR (droit de base de données ET droit d'hôte)
OR droit de table
OR droit de colonne

Dans la plupart des cas, vous donnez des droits à un utilisateur en utilisant un seul des niveaux de droits ci-dessus, ce qui fait que la vie n'est pas aussi compliquée. Les détails de la procédure de vérification des droits sont disponibles dans Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

Si vous donnez des droits à une paire utilisateur/hôte qui n'existe pas dans la table mysql.user, une ligne sera créée et restera disponible jusqu'à son effacement avec la commande DELETE. En d'autres termes, GRANT crée une ligne dans la table user, mais REVOKE ne la supprime pas. Vous devez le faire explicitement avec la commande DELETE.

Avec MySQL version 3.22.12 ou plus récentes, si un nouvel utilisateur est créé, ou si vous avez les droits de GRANT globaux, le mot de passe sera configuré avec le mot de passe spécifié avec la clause IDENTIFIED BY, si elle est fournie. Si l'utilisateur a déjà un mot de passe, il sera remplacé par ce nouveau.

Attention : si vous créez un nouvel utilisateur, mais ne spécifiez pas de clause IDENTIFIED BY, l'utilisateur n'aura pas de mot de passe. Ce n'est pas sécuritaire.

Les mots de passe peuvent aussi être modifiés avec la commande SET PASSWORD. Voir Section 13.5.1.5, « Syntaxe de SET PASSWORD ».

Si vous ne voulez pas transmettre le mot de passe en texte clair, vous pouvez immédiatement utiliser l'option PASSWORD suivi du mot de passe déjà chiffré avec la fonction PASSWORD() ou l'API C make_scrambled_password(char *to, const char *password).

Si vous donnez les droits de base, une ligne sera ajoutée dans la table mysql.db. Lorsque les droits sur cette base seront supprimés avec la commande REVOKE, cette ligne disparaîtra.

Si un utilisateur n'a pas de droit sur une table, elle ne sera pas affichée lorsqu'il demandera la liste des tables avec la commande SHOW TABLES. Si un utilisateur n'a pas de droit dans une base, le nom de la base ne sera pas affiché par SHOW DATABASES à moins que l'utilisateur n'ait un droit de SHOW DATABASES.

La clause WITH GRANT OPTION donne à l'utilisateur le droit de donner les droits qu'il possède à d'autres utilisateurs. La plus grande prudence est recommandée pour cette commande, car il permettra à terme à deux utilisateurs de combiner les droits dont ils disposent.

Vous ne pouvez pas donner un droit que vous ne possédez pas. Le droit de GRANT OPTION ne vous donne le droit que de donner les droits que vous possédez.

Sachez que si vous donnez à quelqu'un le droit de GRANT OPTION, tous les droits que possède cet utilisateur seront distribuables. Supposez que vous donniez à un utilisateur le droit d'INSERT dans une base de données. Si vous donnez le droit de SELECT sur une base, et spécifiez l'option WITH GRANT OPTION, l'utilisateur peut distribuer non seulement son droit de SELECT, mais aussi son droit de INSERT. Si vous donnez ensuite le droit de UPDATE, il pourra alors distribuer INSERT, SELECT et UPDATE.

Il est recommandé de ne pas donner de droits de ALTER à un utilisateur normal. Si vous le faites, l'utilisateur pourra essayer de contourner le système de droits en renommant des tables.

MAX_QUERIES_PER_HOUR #, MAX_UPDATES_PER_HOUR # et MAX_CONNECTIONS_PER_HOUR # sont nouveaux en MySQL 4.0.2. Ces deux options limitent le nombre de requêtes et de modifications qu'un utilisateur peut réclamer dans une heure. Si # vaut 0 (valeur par défaut), alors cela signifie qu'il n'y a pas de limitations pour cet utilisateur. Voir Section 5.6.4, « Limiter les ressources utilisateur ». Note : pour spécifier l'une de ces options pour un utilisateur existant sans ajouter d'autres privilèges additionnels, utilisez GRANT USAGE ... WITH MAX_....

MySQL peut vérifier les attributs X509 en plus des éléments d'identifications habituels, comme le nom d'utilisateur et le mot de passe. Pour spécifier des options SSL pour un compte MySQL, utilisez la clause REQUIRE de la commande GRANT. Pour des informations générales sur SSL et MySQL, voyez Section 5.6.7, « Utilisation des connexions sécurisées ».

Il y a différentes possibilités pour limiter le type de connexions d'un compte.

- Si un compte ne doit pas utiliser SSL ou X509, les connexions sont autorisées si le mot de passe et le nom d'utilisateur sont valides. Cependant, les connexions non chiffrées peuvent aussi être utilisées par le client, si le client dispose des bons certificats et clés.

- L'option REQUIRE SSL limite le serveur aux connexions chiffrées avec SSL. Notez que cette option peut être omise s'il y a des lignes d'identifications qui autorisent les connexions non chiffrées.

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

- REQUIRE X509 signifie que le client doit avoir un certificat valide, mais que le certificat exact, l'émetteur et le sujet n'ont pas d'importance. La seule obligation est qu'il faut pouvoir vérifier la signature auprès d'une des autorités de certification.

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret' REQUIRE X509;

- REQUIRE ISSUER 'issuer' impose aux connexions l'utilisation d'un certificat X509 émis par l'autorité de certification 'issuer'. Si le client présente un certificat d'une autre autorité, le serveur rejette la connexion. L'utilisation des certificats X509 implique toujours un chiffrement, ce qui fait que l'option SSL est inutile.

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret'
-> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';

Notez que la valeur de ISSUER doit être saisie comme une seule chaîne.

- REQUIRE SUBJECT 'subject' impose à la connexion à la présentation d'un certificat X509 avec le sujet 'subject'. Si le client présente un certificat qui est valide, mais avec un autre sujet, le serveur rejette la connexion.

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret'
-> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
O=MySQL demo client certificate/
CN=Tonu Samuel/Email=tonu@example.com';

Notez que la valeur de SUBJECT doit être saisie comme une seule chaîne.

- REQUIRE CIPHER 'cipher' est nécessaire pour s'assurer que des tailles de clé et chiffrements suffisantes sont utilisées. SSL peut être faible si de vieux algorithmes avec des clés courtes sont utilisés. En utilisant cette option, vous pouvez spécifier un chiffrement spécifique.

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret'
-> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

Les clauses SUBJECT, ISSUER et CIPHER peuvent être combinées avec la clause REQUIRE comme ceci :

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
-> IDENTIFIED BY 'goodsecret'
-> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
O=MySQL demo client certificate/
CN=Tonu Samuel/Email=tonu@example.com'
-> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
-> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

Notez que les valeurs de SUBJECT et ISSUER doivent être saisies comme une seule chaîne.

Depuis MySQL 4.0.4, le mot-clé AND est optionnel entre les clauses de REQUIRE.

L'ordre des options est libre, mais les options doivent être spécifiées une seule fois.

Notez que si vous utilisez des droits de niveau table ou colonne même pour un utilisateur, le serveur vérifiera alors ces droits pour tous les utilisateurs, et cela ralentira un peu MySQL.

Lorsque mysqld démarre, tous les droits sont stockés en mémoire. Les droits de bases, tables et colonnes prennent aussitôt effet, et les droits des utilisateurs prendront effet dès leur prochaine configuration. Les modifications sur les tables de droits que vous effectuez avec les commandes GRANT et REVOKE sont prises en compte immédiatement par le serveur. Si vous modifiez manuellement les tables (avec INSERT, UPDATE, etc.), vous devez exécuter la commande FLUSH PRIVILEGES, ou la commande en ligne mysqladmin flush-privileges pour indiquer au serveur qu'il doit recharger les droits. Voir Section 5.5.7, « Quand les modifications de privilèges prennent-ils effets ? ».

Les différences notables entre l'ANSI SQL et MySQL pour la commande GRANT sont les suivantes.

- Les droits MySQL sont donnés pour une combinaison nom d'utilisateur + nom d'hôte, et non pas pour un nom d'hôte seulement.

- L'ANSI SQL n'a pas de droits globaux ou de niveau base de données, et l'ANSI SQL ne supporte pas tous les types de droits que MySQL supporte. MySQL ne supporte pas le droit ANSI SQL de TRIGGER ou UNDER.

- MySQL ne supporte pas les droits standard SQL TRIGGER et UNDER.

- Les droits ANSI SQL sont structurés de manière hiérarchique. Si vous supprimez un utilisateur, tous les droits donnés à cet utilisateur seront supprimés. Avec MySQL, les droits ne sont pas automatiquement supprimés, et vous devez les supprimer manuellement, si besoin.

- Avec MySQL, si vous avez le droit de INSERT sur uniquement quelques colonnes de la table, vous pourrez exécuter des insertions. Les colonnes pour lesquelles vous n'avez pas de droit prendront alors leur valeur par défaut. L'ANSI SQL vous impose d'avoir les droits d'INSERT sur toutes les colonnes.

- Lorsque vous détruisez une table avec ANSI SQL, tous les droits liés à la table sont supprimés. Si vous supprimez un droit en ANSI SQL, tous les droits qui étaient basés sur ce droit sont supprimés. Avec MySQL, les droits peuvent être abandonnés explicitement avec la commande REVOKE, ou en manipulant les tables de droits de MySQL.

13-5-1-4 - Syntaxe de RENAME USER

RENAME USER old_user TO new_user
[, old_user TO new_user] ...

La commande RENAME USER renomme un compte MySQL existant. Pour l'utiliser, vous devez avoir les droits globaux de CREATE USER ou les droits de UPDATE dans la base mysql. Une erreur survient si l'ancien compte n'existe pas, ou que le nouveau compte existe déjà. Les valeurs old_user et new_user sont données de la même façon que dans la commande GRANT.

La commande RENAME USER a été ajoutée en MySQL 5.0.2.

13-5-1-5 - Syntaxe de SET PASSWORD

SET PASSWORD = PASSWORD('some password')
SET PASSWORD FOR user = PASSWORD('some password')

La commande SET PASSWORD assigne un mot de passe à un compte utilisateur existant.

La première syntaxe modifie le mot de passe de l'utilisateur courant. Tout client qui s'est connecté avec un compte non anonyme peut changer le mot de passe pour ce compte.

La seconde syntaxe modifie le mot de passe pour un compte tiers, sur le serveur. Seuls les clients qui ont accès aux bases mysql peuvent faire cela. La valeur de user doit être donnée au format user_name@host_name, où user_name et host_name sont tels que listés dans les colonnes User et Host de la table mysql.user. Par exemple, si vous avez une ligne avec les champs User et Host qui valent 'bob' et '%.loc.gov', vous pouvez écrire la commande suivante :

mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');

C'est l'équivalent de la commande suivante :

mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
-> WHERE User='bob' AND Host='%.loc.gov';
mysql> FLUSH PRIVILEGES;

13-5-2 - Commandes d'entretien des tables

13-5-2-1 - Syntaxe de ANALYZE TABLE

ANALYZE TABLE nom_de_table[,nom_de_table...]

Cette commande analyse et stocke la clé de distribution de la table. Durant l'analyse, la table est verrouillée en lecture. Cette commande fonctionne avec les tables MyISAM et BDB.

C'est l'équivalent de la commande en ligne myisamchk -a.

MySQL utilise les clés de distribution pour décider dans quel ordre les tables doivent être rassemblées lors des jointures qui ne s'effectuent pas sur une constante.

La commande retourne une table avec les colonnes suivantes :

Colonne

Valeur

Table

Nom de la table

Op

« analyze » (toujours)

Msg_type

Un des status, error, info ou warning

Msg_text

Le message

Vous pouvez vérifier la clé de distribution stockée avec la commande SHOW INDEX. Voir Section 13.5.3.6, « Syntaxe de SHOW DATABASES ».

Si la table n'a pas changé depuis la dernière commande ANALYZE TABLE, elle ne sera pas analysée à nouveau.

13-5-2-2 - Syntaxe de BACKUP TABLE

BACKUP TABLE nom_de_table[,nom_de_table...] TO '/chemin/vers/le/dossier/de/sauvegardes'

Note : cette commande est obsolète. Nous travaillons à une solution de remplacement améliorée, qui proposera des sauvegardes à chaud. Durant ce temps, le script mysqlhotcopy peut être utilisé.

Cette commande copie le nombre minimal de fichiers de tables dont on a besoin pour la restaurer vers le dossier de sauvegardes après avoir rafraîchi les changements dans le disque. Cela ne fonctionne actuellement que pour les tables au format MyISAM. Pour les tables MyISAM, elle ne copie que les fichiers .frm (définition) et .MYD (données), le fichier d'index .MYD pouvant, lui, être reconstruit à partir des deux autres.

Avant d'utiliser cette commande, merci de lire Section 5.7.1, « Sauvegardes de base de données ».

Pendant la sauvegarde, un verrou de lecture est posé sur chaque table, une par une, lors de leur copie. Si vous voulez sauvegarder une image instantanée de plusieurs tables, vous devez d'abord exécuter un LOCK TABLES obtenant un verrou de lecture pour chaque table concernée.

La commande retourne une table avec les colonnes suivantes :

Colonne

Valeur

Table

Nom de la table

Op

Toujours « backup »

Msg_type

status, error, info ou encore warning

Msg_text

Le message

Notez que BACKUP TABLE n'est disponible en MySQL que depuis la version 3.23.25.

13-5-2-3 - Syntaxe de CHECK TABLE

CHECK TABLE tbl_name[,tbl_name...] [option [option...]]

option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED

CHECK TABLE ne fonctionne qu'avec les tables MyISAM et InnoDB. Avec les tables MyISAM, c'est l'équivalent de la commande myisamchk -m table_name sur la table.

Par défaut, l'option MEDIUM est utilisée.

Cette commande vérifie l'intégrité des tables. Pour les tables MyISAM, des statistiques importantes sont mises à jour. La commande retourne les informations suivantes sur la table dans les colonnes suivantes :

Colonne

Valeur

Table

Nom de la table

Op

Toujours « check »

Msg_type

Un des statuts status, error, info ou warning

Msg_text

Le message

Notez que vous pouvez obtenir de nombreuses lignes d'informations pour chaque table. La dernière ligne sera du type Msg_type status et doit être normalement OK. Si vous n'obtenez pas de statut OK ou Not checked, il vous faudra exécuter une réparation de la table. Voir Section 5.7.3, « Utilisation de myisamchk pour la maintenance des tables et leur recouvrement ». Not checked signifie que la table a indiqué qu'il n'y a pas de vérification à faire.

Les différents types de vérifications sont les suivants :

Type

Signification

QUICK

N'analyse pas les lignes pour vérifier les liens erronés.

FAST

Ne vérifie que les tables qui n'ont pas été correctement fermées.

CHANGED

Ne vérifie que les tables qui ont changé depuis la dernière vérification, ou bien qui n'ont pas été correctement fermées.

MEDIUM

Analyse les lignes pour s'assurer que les liens effacés sont corrects. Cette option calcule aussi la somme de contrôle des lignes, et la vérifie avec la somme de contrôle des clés.

EXTENDED

Fait une vérification complète des liens pour chaque ligne. Cela vérifie que la table est totalement cohérente, mais cela peut prendre beaucoup de temps.

Pour les tables à format dynamique de type MyISAM, une vérification de table sera toujours démarrée avec une option de niveau MEDIUM. Pour les tables à format de ligne statique, nous évitons les niveaux de QUICK et FAST, car les lignes sont rarement corrompues.

Vous pouvez combiner les options de vérification comme ceci :

CHECK TABLE test_table FAST QUICK;

L'exemple ci-dessus va simplement faire une vérification de la table, pour s'assurer qu'elle a été correctement fermée.

Note : dans certains cas, CHECK TABLE va modifier la table ! Cela arrive si la table a été marquée comme « corrupted » et « not closed properly », mais CHECK TABLE n'a trouvé aucun problème dans la table. Dans ce cas, CHECK TABLE va marquer la table comme correcte.

Si une table est corrompue, il est probable que les problèmes sont dans les fichiers d'index et non pas dans les données. Tous les types de vérifications présentés ci-dessus vérifient les index soigneusement, et ils devraient trouver la plupart des erreurs.

Si vous voulez simplement vérifier une table que vous supposez correcte, vous pouvez n'utiliser aucune option, ou l'option QUICK. Cette dernière peut aussi être utilisée si vous êtes pressé, et que vous pouvez prendre le risque minime que QUICK ne trouve pas d'erreur dans votre fichier. Dans la plupart des cas, MySQL doit trouver toutes les erreurs de données, pour un usage normal. Si cela arrive, alors la table est marquée comme « corrupted », auquel cas, la table ne pourra pas être utilisée tant qu'elle n'a pas été réparée).

FAST et CHANGED sont surtout destinées à être utilisées depuis un script : par exemple, il peut être exécuté depuis une tâche cron, si vous voulez vérifier la table de temps en temps. Dans la plupart des cas, l'option FAST doit être préférée à CHANGED : le seul cas ou vous pourriez préférez CHANGED est lorsque vous soupçonnez avoir trouvé un bogue dans les tables MyISAM.

EXTENDED ne doit être utilisé qu'après une vérification normale, et que vous obtenez toujours des erreurs étranges lorsque MySQL essaie de modifier une ligne ou trouve une ligne avec clé (ce qui est très rare, si une vérification a réussi).

Certains problèmes rapportés par la commande CHECK TABLE, ne peuvent être corrigés automatiquement.

- Found row where the auto_increment column has the value 0.

Cela signifie que vous avez dans votre table une ligne qui contient la valeur 0 alors qu'elle est de type AUTO_INCREMENT. (Il est possible de créer une ligne où la colonne AUTO_INCREMENT vaut 0 en spécifiant explicitement la valeur 0 dans la colonne avec la commande UPDATE.

Ce n'est pas une erreur en soi, mais cela peut poser des problèmes si vous décidez de sauver cette table dans un fichier texte, et de la restaurer, ou encore d'appliquer la commande ALTER TABLE sur la table. Dans ce cas, la colonne AUTO_INCREMENT va changer automatiquement de valeur, en suivant les règles des colonnes de type AUTO_INCREMENT, qui vont causer un problème de clé doublon.

Pour se débarrasser de cette alerte, vous devez utiliser une commande UPDATE sur la table, pour mettre une valeur différente de 0 dans cette colonne.

13-5-2-4 - Syntaxe de CHECKSUM TABLE

CHECKSUM TABLE tbl_name[,tbl_name ...] [ QUICK | EXTENDED ]

Calcule la somme de contrôle de la table.

Si QUICK est spécifié, la somme de contrôle instantanée est retournée, ou NULL si la table ne supporte pas les sommes de contrôle instantanées. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

En mode EXTENDED, toute la table est lue, ligne par ligne, et la somme de contrôle est calculée. Cela peut être très lent pour les tables de grande taille.

Par défaut, sans QUICK ni EXTENDED, MySQL retourne la somme de contrôle si la table le supporte, et sinon, scanne la table.

Cette commande a été ajoutée en MySQL 4.1.1.

13-5-2-5 - Syntaxe de OPTIMIZE TABLE

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

OPTIMIZE TABLE doit être utilisée si une grande partie de la base a été effacée, ou si vous avez fait de nombreuses modifications dans une table à format de ligne dynamique (des tables qui ont des colonnes de type VARCHAR, BLOB et TEXT). Les lignes effacées sont conservées dans une liste, et les prochaines opérations d'INSERT réutilisent les vieilles positions de lignes. Vous pouvez vous servir de la commande OPTIMIZE TABLE pour récupérer l'espace utilisé et défragmenter le fichier de données.

Dans la plupart des installations, vous n'avez pas à utiliser OPTIMIZE TABLE. Même si vous faites beaucoup de mises à jour sur des colonnes à taille dynamique, il n'est pas évident que vous ayez à passer cette commande plus d'une fois par semaine ou par mois, et uniquement sur quelques tables.

Pour le moment, OPTIMIZE TABLE fonctionne uniquement avec les tables de type MyISAM et BDB. Pour les tables BDB, OPTIMIZE TABLE est actuellement l'équivalent de ANALYZE TABLE. Voir Section 13.5.2.1, « Syntaxe de ANALYZE TABLE ».

Vous pouvez vous arranger pour que OPTIMIZE TABLE fonctionne sur d'autres types de tables, en démarrant mysqld avec --skip-new ou --safe-mode, mais dans ce cas, OPTIMIZE TABLE est simplement l'équivalent de ALTER TABLE.

OPTIMIZE TABLE fonctionne comme ceci :

1. Si la table contient des lignes effacées ou des lignes fragmentées, la table est compactée ;

2. Si les pages d'index ne sont pas triées, OPTIMIZE TABLE les trie ;

3. Si les statistiques ne sont pas à jour (et que la table n'a pas pu effectuer de réparation en triant l'index), elles sont mises à jour.

Notez que la table est verrouillée durant la commande OPTIMIZE TABLE.

Avant MySQL 4.1.1, OPTIMIZE n'était pas reportée dans le log binaire. Depuis MySQL 4.1.1 elles le sont, à moins que l'attribut optionnel NO_WRITE_TO_BINLOG ou son alias LOCAL ne soient utilisés.

13-5-2-6 - Syntaxe de REPAIR TABLE

REPAIR TABLE tbl_name[,tbl_name...] [QUICK] [EXTENDED] [USE_FRM]

REPAIR TABLE répare une table possiblement corrompue. Par défaut, elle a le même effet que myisamchk --recover tbl_name sur une table. REPAIR TABLE fonctionne uniquement avec les tables MyISAM.

Normalement, vous n'avez pas à exécuter cette commande, mais si une catastrophe vous frappe, vous êtes presque assuré de retrouver vos données dans les tables MyISAM, avec la commande REPAIR TABLE. Si vos tables sont souvent corrompues, vous devriez toutefois rechercher la cause de ce problème ! Voir Section A.4.2, « Que faire si MySQL plante constamment ? ». Voir Section 14.1.4, « Problèmes avec les tables MyISAM ».

REPAIR TABLE répare autant que possible les tables corrompues. La commande retourne la table suivante :

Colonne

Valeur

Table

Nom de la table

Op

Toujours repair

Msg_type

Un des statuts status, error, info ou warning

Msg_text

Le message

La commande REPAIR TABLE pourrait afficher plusieurs messages pour chaque table. La dernière ligne doit être du format Msg_type status et doit être normalement OK. Si vous n'obtenez pas OK, vous devez essayer de réparer votre table avec la commande myisamchk -o, car REPAIR TABLE ne supporte pas encore toutes les options de myisamchk. Dans un futur proche, nous allons rendre cette commande encore plus souple.

Si l'option QUICK est fournie, alors MySQL va essayer de ne réparer que le fichier d'index. Ce type de réparation est le même que myisamchk --recover --quick.

Si vous utilisez l'option EXTENDED, alors MySQL va essayer de créer l'index ligne par ligne, au lieu de créer un index à la fois, par tri. C'est une méthode qui peut s'avérer plus efficace que de trier sur des clés de taille fixe, si vous avez des clés CHAR longues qui se compressent bien. Ce type de réparation est l'équivalent de myisamchk --safe-recover.

Depuis MySQL 4.0.2, il existe le mode USE_FRM pour REPAIR. Utilisez-le si le fichier .MYI manque, ou si son entête est corrompu. Avec ce mode, MySQL va recréer le fichier .MYI, en utilisant les informations du fichier .frm. Ce type de réparation ne peut pas être fait avec myisamchk.

Attention : si le serveur s'arrête durant l'opération REPAIR TABLE, il est important d'exécuter à nouveau la commande REPAIR TABLE après le redémarrage (il est bon de faire une sauvegarde de toute manière). Dans le pire scénario, vous pourriez vous retrouver avec un nouvel index sans relation avec les données, et la prochaine opération risque d'écraser le fichier de données. C'est peu probable, mais possible.

Avant MySQL 4.1.1, les commandes REPAIR TABLE n'étaient pas écrites dans le log binaire. Depuis MySQL 4.1.1, elles sont écrites dans le log binaire à moins que la clause NO_WRITE_TO_BINLOG ne soit utilisée (aussi connue sous le nom de LOCAL).

13-5-2-7 - Syntaxe de RESTORE TABLE

RESTORE TABLE nom_de_table[,nom_de_table...] FROM '/chemin/vers/le/dossier/de/sauvegardes'

Restaure la ou les tables à partir d'une sauvegarde effectuée avec BACKUP TABLE. Les tables existantes ne seront pas écrasées et dans ce cas-là, vous obtiendrez une erreur. La restauration prendra plus de temps que la sauvegarde à cause de la reconstruction du fichier d'index. Plus vous avez de clés, plus la restauration sera longue. Tout comme BACKUP TABLE, RESTORE TABLE fonctionne seulement avec les tables MyISAM.

La sauvegarde de chaque table est constituée du fichier de format .frm et du fichier de données .MYD. L'opération de restauration restaure ces fichiers, puis les utilise pour reconstruire le fichier d'index .MYI. La restauration prend plus de temps que la sauvegarde, car il faut reconstituer l'index. Plus la table a d'index, plus cela prendra de temps.

Cette commande retourne un tableau avec les colonnes suivantes :

Colonne

Valeur

Table

Nom de la table

Op

Toujours « restore »

Msg_type

status, error, info ou encore warning

Msg_text

Le message.

13-5-2-8 - Syntaxe de SET

SET variable_assignment [, variable_assignment] ...

variable_assignment:
user_var_name = expr
| [GLOBAL | SESSION] system_var_name = expr
| @@[global. | session.]system_var_name = expr

SET permet de configurer plusieurs options qui affectent le comportement de votre serveur ou de votre client.

En MySQL 4.0.3, nous avons ajouté les options GLOBAL et SESSION et permis la modification des variables systèmes les plus importantes dynamiquement, durant l'exécution du serveur. Le système de variables que vous pouvez utiliser est décrit dans Section 5.2.3.1, « Variables système dynamiques ».

Dans les anciennes versions de MySQL, nous avions autorisé l'utilisation de la syntaxe SET OPTION, mais elle est maintenant abandonnée. Omettez simplement le mot OPTION.

Les exemples suivants montrent les différentes syntaxes qu'on peut utiliser pour configurer des variables.

Une variable utilisateur s'écrit sous la forme @var_name et peut être configurée comme ceci :

SET @var_name = expr;

Plus d'informations sur les variables utilisateur sont données dans Section 9.3, « Variables utilisateur ».

Les variables système peuvent être identifiées dans une commande SET sous la forme var_name. Le nom peut être optionnellement précédé par GLOBAL ou @@global. pour indiquer que cette variable est globale, ou par SESSION, @@session., ou @@ pour indiquer que cette variable est une variable de session. LOCAL et @@local. sont synonymes de SESSION et @@session.. Si aucune option n'est présente, SET spécifie une variable de session.

La syntaxe @@var_name pour les variables système est supportée pour rendre la syntaxe MySQL compatible avec les autres bases.

Si vous configurez plusieurs variables sur une seule ligne de commande, le dernier mode GLOBAL | SESSION utilisé est pris en compte.

SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;

Si vous utilisez SESSION (par défaut) l'option que vous configurez garde son effet jusqu'à ce que la session courante se termine, ou que vous modifiez à nouveau cette option. Si vous utilisez GLOBAL, qui requiert le privilège SUPER, l'option est gardée en mémoire et utilisée pour les nouvelles connexions jusqu'au redémarrage du serveur. Si vous voulez qu'un changement reste permanent, vous devez l'effectuer dans l'un des fichiers d'options de MySQL. Voir Section 4.3.2, « Fichier d'options my.cnf ».

Pour éviter un mauvais usage, MySQL donnera une erreur si vous utilisez SET GLOBAL avec une variable qui ne peut être utilisée que par SET SESSION ou si vous n'utilisez pas SET GLOBAL avec une variable globale.

Si vous voulez configurer une variable SESSION à une valeur GLOBAL ou une valeur GLOBAL à la valeur par défaut de MySQL, vous pouvez la configurer à DEFAULT.

SET max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;

Vous pouvez obtenir une liste de la plupart des variables avec SHOW VARIABLES. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ». Vous pouvez obtenir la valeur d'une variable spécifique avec la syntaxe @@[global.|local.]nom_variable :

SHOW VARIABLES LIKE 'max_join_size';
SHOW GLOBAL VARIABLES LIKE 'max_join_size';

Vous pouvez aussi obtenir une valeur spécifique d'une variable en utilisant la syntaxe @@[global.|local.]var_name avec SELECT :

SELECT @@max_join_size, @@global.max_join_size;

Lorsque vous lisez la valeur d'une variable avec la syntaxe SELECT @@var_name (c'est-à-dire, sans spécifier global., session. ou local.), MySQL retourne la valeur de SESSION si elle existe, et la valeur GLOBAL sinon.

Vous trouverez ici une description des variables qui utilisent une syntaxe non standard de SET. Les définitions des autres variables peuvent être trouvées dans la Section 5.2.3, « Variables serveur système », avec les options de démarrage ou dans la description de SHOW VARIABLES.

Même si ces variables ne sont pas affichées par SHOW VARIABLES, vous pouvez obtenir leur valeur avec la commande SELECT (à l'exception de CHARACTER SET). Par exemple :

mysql> SELECT @@AUTOCOMMIT;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+

- AUTOCOMMIT= {0 | 1}

Si définie à 1 tous les changements dans une table se feront en une seule fois. Pour démarrer une transaction multicommande, vous devez utiliser la commande BEGIN. Voir Section 13.4.1, « Syntaxes de START TRANSACTION, COMMIT et ROLLBACK ». Si définie à 0 vous devez utiliser COMMIT / ROLLBACK pour accepter/annuler cette transaction. Notez que quand vous passez du mode non AUTOCOMMIT vers le mode AUTOCOMMIT, MySQL fera un COMMIT automatique sur toutes les transactions en cours.

- BIG_TABLES = {0 | 1}

Si définie à 1, toutes les tables temporaires sont stockées sur le disque plutôt qu'en mémoire. Cela sera un peu plus lent, mais vous n'obtiendrez jamais l'erreur The table nom_de_table is full pour les grands SELECT qui requièrent une table temporaire. La valeur par défaut pour une nouvelle connexion est 0 (qui est d'utiliser la mémoire pour les tables temporaires). Cette option se nommait avant SQL_BIG_TABLES.

- CHARACTER SET {charset_name | DEFAULT}

Cela change le jeu de caractères dans toutes les chaînes du et vers le client avec le jeu donné. Jusqu'à maintenant, la seule option pour nom_jeu_de_caractères est cp1251_koi8, mais vous pouvez facilement ajouter d'autres possibilités en éditant le fichier sql/convert.cc dans la distribution des sources MySQL. Le jeu de caractères par défaut peut être restauré en utilisant la valeur DEFAULT de nom_jeu_de_caractères DEFAULT.

Notez que la syntaxe pour configurer l'option CHARACTER SET diffère de la syntaxe pour configurer les autres options.

- FOREIGN_KEY_CHECKS = {0 | 1}

Si cette option vaut 1 (par défaut), les contraintes de clés étrangères des tables InnoDB sont vérifiées. Si cette option vaut 0, elles sont ignorées. Désactiver les clés étrangères peut être pratique pour recharger des tables InnoDB dans un ordre différent que celui qu'imposent les relations de contraintes. Cette variable a été ajoutée en MySQL 3.23.52. Voir Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ».

- IDENTITY = valeur

Cette variable est un synonyme de la variable LAST_INSERT_ID. Elle existe pour des raisons de compatibilité avec les autres bases. Depuis MySQL 3.23.25, vous pouvez lire sa valeur avec SELECT @@IDENTITY. Depuis MySQL 4.0.3, vous pouvez aussi modifier cette valeur avec SET IDENTITY.

- INSERT_ID = valeur

Configure la valeur à utiliser par l'appel suivant à la commande INSERT ou ALTER TABLE lors de l'insertion d'une valeur AUTO_INCREMENT. Cela est souvent utilisé par le log des modifications.

- LAST_INSERT_ID = valeur

Configure la valeur qui doit être retournée par LAST_INSERT_ID(). C'est enregistré dans le log de mises à jour quand vous utilisez LAST_INSERT_ID() dans une commande qui met à jour une table.

- NAMES {'charset_name' | DEFAULT}

SET NAMES spécifie les valeurs des trois variables système de session character_set_client, character_set_connection et character_set_results avec le jeu de caractères donné.

La valeur par défaut de ces variables peut être rappelée avec DEFAULT.

Notez que la syntaxe de SET NAMES diffère en cela des autres options. Cette commande est disponible depuis MySQL 4.1.0.

- SQL_AUTO_IS_NULL = {0 | 1}

Si définie à 1 (par défaut) alors on peut trouver la dernière ligne insérée dans une table avec une colonne AUTO_INCREMENT avec la construction suivante :

WHERE auto_increment_column IS NULL

Ceci est utilisé par des programmes ODBC tels que Access. SQL_AUTO_IS_NULL a été ajouté en MySQL 3.23.52.

- SQL_BIG_SELECTS = {0 | 1}

Si configuré à 0, MySQL interrompra les requêtes SELECT qui prendront probablement trop de temps. C'est utile lorsqu'une clause WHERE déconseillée a été utilisée. Une grosse requête est définie comme étant un SELECT qui devra probablement étudier plus de max_join_size lignes. La valeur par défaut d'une nouvelle connexion est 1 (qui permet toutes les requêtes SELECT).

- SQL_BUFFER_RESULT = {0 | 1}

SQL_BUFFER_RESULT forcera les résultats des requêtes SELECT à être placés dans une table temporaire. Cela aidera MySQL à libérer les verrous sur table plus tôt et améliorera les cas où le jeu de résultats de la requête prend trop de temps à être envoyé au client.

- SQL_LOG_BIN = {0 | 1}

Si cette option vaut 0, aucun log n'est fait dans le log binaire du client, si le client a les droits de SUPER.

- SQL_LOG_OFF = {0 | 1}

Si cette option vaut 1, aucun log n'est fait dans le log standard du client, si le client a les droits de SUPER.

- SQL_LOG_UPDATE = {0 | 1}

Si définie à 0, aucune trace des requêtes ne sera gardée dans le log des mises à jour pour le client, si le client a le privilège SUPER. Cette variable est abandonnée depuis la version 5.0.0 et est remplacée par SQL_LOG_BIN (voir Section C.1.7, « Changements de la version 5.0.0 (22 décembre 2003 : Alpha) »).

- SQL_QUOTE_SHOW_CREATE = {0 | 1}

Si vous le configurez à 1, SHOW CREATE TABLE protégera les noms de tables et de colonnes. Ceci est activé par défaut, pour que la réplication des tables avec des noms à risques fonctionne. Section 13.5.3.5, « Syntaxe de SHOW CREATE TABLE ».

- SQL_SAFE_UPDATES = {0 | 1}

Si défini à 1, MySQL annulera si un UPDATE ou un DELETE sont exécutés alors qu'ils n'utilisent pas de clé ou de LIMIT dans la clause WHERE. Cela permet de bloquer les requêtes erronées créées à la main.

- SQL_SELECT_LIMIT = valeur | DEFAULT

Le nombre maximal des enregistrements que doivent retourner les requêtes SELECT. Si un SELECT possède une clause LIMIT, celle-ci est utilisée. La valeur par défaut pour une nouvelle connexion est « illimitée. » Si vous avez changé la limite, la valeur par défaut peut être retrouvée en utilisant la valeur DEFAULT avec SQL_SELECT_LIMIT.

- SQL_WARNINGS = {0 | 1}

Cette variable contrôle le fait que les insertions monolignes INSERT produisent une chaîne d'information si une alerte survient. La valeur par défaut est 0. Donnez la valeur de 1 pour avoir un message d'information. Cette variable a été ajoutée en MySQL 3.22.11.

- TIMESTAMP = valeur_timestamp | DEFAULT

Configure le temps pour ce client. C'est utilisé pour obtenir le timestamp d'origine si vous utilisez le log de mises à jour pour restaurer des lignes. valeur_timestamp doit être un timestamp Unix, et non un timestamp MySQL.

- UNIQUE_CHECKS = {0 | 1}

Si cette option vaut 1 (par défaut), les tests d'unicité sur les index secondaires des tables InnoDB sont effectués. Si l'option vaut 0, aucun test d'unicité n'est fait. Cette variable a été ajoutée en MySQL 3.23.52. Voir Section 15.7.4, « Contraintes de clés étrangères FOREIGN KEY ».

13-5-3 - Syntaxe de SHOW

SET vous permet de modifier des variables et options.

SHOW a de très nombreuses formes, pour donner des informations sur les bases, tables, colonnes ou le serveur. Cette section les décrit.

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW CREATE DATABASE db_name
SHOW CREATE TABLE tbl_name
SHOW DATABASES [LIKE 'pattern']
SHOW [STORAGE] ENGINES
SHOW ERRORS [LIMIT [offset,] row_count]
SHOW GRANTS FOR user
SHOW INDEX FROM tbl_name [FROM db_name]
SHOW INNODB STATUS
SHOW [BDB] LOGS
SHOW PRIVILEGES
SHOW [FULL] PROCESSLIST
SHOW STATUS [LIKE 'pattern']
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW WARNINGS [LIMIT [offset,] row_count]

Si la syntaxe d'une commande SHOW inclut la clause LIKE 'pattern', 'pattern' est une expression régulière qui peut contenir les jokers '%' et '_'. Cette expression est utile pour restreindre la commande à une partie des valeurs normalement retournées.

Notez qu'il y a d'autres formes pour ces commandes, décrites à d'autres endroits du manuel.

- La commande SET PASSWORD pour assigner un mot de passe à un compte est présentée dans Section 13.5.1.5, « Syntaxe de SET PASSWORD ».

- La commande SHOW a des formes pour afficher des informations sur la réplication, pour le maître et l'esclave :

SHOW BINLOG EVENTS
SHOW MASTER LOGS
SHOW MASTER STATUS
SHOW SLAVE HOSTS
SHOW SLAVE STATUS

Ces formes de SHOW sont décrites dans Section 13.6, « Commandes de réplication ».

13-5-3-1 - Commande SHOW CHARACTER SET

La commande SHOW CHARACTER SET montre tous les jeux de caractères disponibles. Il faut une clause facultative LIKE pour limiter les jeux de caractères à afficher.

Par exemple :

mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | ISO 8859-1 West European    | latin1_swedish_ci |      1 |
| latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
+---------+-----------------------------+-------------------+--------+
4 rows in set (0.00 sec)

Remarque sur la liste précédente :

- la colonne Maxlen affiche le nombre maximum d'octets utilisés pour stocker un caractère.

13-5-3-2 - Syntaxe de SHOW COLLATION

SHOW COLLATION [LIKE 'pattern']

Le résultat de SHOW COLLATION inclut tous les jeux de caractères disponibles. Vous pouvez utiliser optionnellement la clause LIKE pour limiter le nombre de réponses.

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          |       0 |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
| latin1_danish_ci  | latin1  | 15 |         |          |       0 |
| latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
| latin1_bin        | latin1  | 47 |         | Yes      |       0 |
| latin1_general_ci | latin1  | 48 |         |          |       0 |
| latin1_general_cs | latin1  | 49 |         |          |       0 |
| latin1_spanish_ci | latin1  | 94 |         |          |       0 |
+-------------------+---------+----+---------+----------+---------+
7 rows in set (0.00 sec)

La colonne Default indique si une collation est la collation par défaut pour son jeu de caractères. Compiled indique si le jeu de caractères est compilé dans le serveur ou non. Sortlen est en relation avec la quantité de mémoire nécessaire pour trier des chaînes exprimées dans le jeu de caractères.

13-5-3-3 - Syntaxe de SHOW COLUMNS

SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']

SHOW COLUMNS liste les colonnes de la table. Si les types de colonnes sont différents de ceux que vous avez utilisés avec la commande CREATE TABLE, c'est que MySQL a modifié silencieusement le type lors de la création. Les conditions de cette modification sont décrites dans Section 13.2.5.1, « Modification automatique du type de colonnes ».

Le mot-clé FULL peut être utilisé depuis MySQL 3.23.32. Il fait afficher les droits dont vous disposez pour chaque colonne. Depuis MySQL 4.1, FULL affiche aussi les commentaires par colonne.

Vous pouvez utiliser db_name.tbl_name comme autre syntaxe que tbl_name FROM db_name. Ces deux commandes sont équivalentes :

mysql> SHOW COLUMNS FROM mytable FROM mydb;
mysql> SHOW COLUMNS FROM mydb.mytable;

SHOW FIELDS est un synonyme de SHOW COLUMNS. Vous pouvez aussi lister les colonnes d'une table avec la commande mysqlshow db_name tbl_name.

La commande DESCRIBE fournit une information similaire à SHOW COLUMNS. Voir Section 13.3.1, « Syntaxe de DESCRIBE (obtenir des informations sur les colonnes) ».

13-5-3-4 - Syntaxe de SHOW CREATE DATABASE

SHOW CREATE DATABASE db_name

La requête suivante montre une commande CREATE DATABASE qui va créer une base de données. Commande ajoutée en MySQL 4.1.

mysql> SHOW CREATE DATABASE test\G
*************************** 1. row ***************************
Database: test
Create Database: CREATE DATABASE `test`
/*!40100 DEFAULT CHARACTER SET latin1 */

13-5-3-5 - Syntaxe de SHOW CREATE TABLE

SHOW CREATE TABLE tbl_name

Affiche la commande CREATE TABLE nécessaire pour créer une table donnée.

mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE t (
id int(11) default NULL auto_increment,
s char(60) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM

SHOW CREATE TABLE va protéger le nom de la table et des colonnes selon l'option SQL_QUOTE_SHOW_CREATE. Section 13.5.2.8, « Syntaxe de SET ».

13-5-3-6 - Syntaxe de SHOW DATABASES

SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']

SHOW DATABASES liste les bases de données disponibles sur le serveur MySQL. Vous pouvez aussi obtenir cette liste avec l'utilitaire mysqlshow. Depuis MySQL 4.0.2, vous ne verrez que les bases pour lesquelles vous avez des droits, à moins que vous n'ayez le droit de SHOW DATABASES.

Si le serveur a été lancé avec l'option --skip-show-database, vous ne pouvez pas utiliser cette commande à moins que vous n'ayez le droit de SHOW DATABASES.

SHOW SCHEMAS est disponible depuis MySQL 5.0.2.

13-5-3-7 - Syntaxe SHOW ENGINES

SHOW [STORAGE] ENGINES

SHOW ENGINES affiche les informations sur les moteurs de stockage du serveur. C'est particulièrement utile pour connaître les moteurs supportés par votre serveur, ou le moteur par défaut. Cette commande a été ajoutée en MySQL 4.1.2. SHOW TABLE TYPES est un synonyme, mais est abandonnée.

mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Type: MyISAM
Support: DEFAULT
Comment: Default type from 3.23 with great performance
*************************** 2. row ***************************
Type: HEAP
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
*************************** 3. row ***************************
Type: MEMORY
Support: YES
Comment: Alias for HEAP
*************************** 4. row ***************************
Type: MERGE
Support: YES
Comment: Collection of identical MyISAM tables
*************************** 5. row ***************************
Type: MRG_MYISAM
Support: YES
Comment: Alias for MERGE
*************************** 6. row ***************************
Type: ISAM
Support: NO
Comment: Obsolete table type; Is replaced by MyISAM
*************************** 7. row ***************************
Type: MRG_ISAM
Support: NO
Comment: Obsolete table type; Is replaced by MRG_MYISAM
*************************** 8. row ***************************
Type: InnoDB
Support: YES
Comment: Supports transactions, row-level locking and foreign keys
*************************** 9. row ***************************
Type: INNOBASE
Support: YES
Comment: Alias for INNODB
*************************** 10. row ***************************
Type: BDB
Support: YES
Comment: Supports transactions and page-level locking
*************************** 11. row ***************************
Type: BERKELEYDB
Support: YES
Comment: Alias for BDB

La valeur Support indique que le moteur est supporté, et si le moteur est le moteur par défaut. Par exemple, si le serveur est lancé avec l'option --default-table-type=InnoDB alors la valeur de la colonne Support de la ligne InnoDB contiendra DEFAULT.

13-5-3-8 - Syntaxe de SHOW ERRORS

SHOW ERRORS [LIMIT [offset,] row_count]
SHOW COUNT(*) ERRORS

Cette commande est similaire à SHOW WARNINGS, hormis le fait qu'au lieu d'afficher les erreurs, alertes et notes, elle n'affiche que les erreurs. SHOW ERRORS est disponible depuis MySQL 4.1.0.

La clause LIMIT a la même syntaxe que celle de la commande SELECT. Voir Section 13.1.7, « Syntaxe de SELECT ».

La commande SHOW COUNT(*) ERRORS affiche le nombre d'erreurs. Vous pouvez aussi connaître ce nombre en lisant la variable error_count :

SHOW COUNT(*) ERRORS;
SELECT @@error_count;

Pour plus d'informations, voyez Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

13-5-3-9 - SHOW GRANTS

SHOW GRANTS FOR user

SHOW GRANTS FOR user affiche la commande nécessaire pour donner les mêmes droits qu'un utilisateur existant.

mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+

Depuis MySQL 4.1.2, pour lister les droits de la session courante, vous pouvez connaître le nom d'utilisateur de la session avec ces commandes :

SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();

Avant MySQL 4.1.2, vous pouviez connaître le nom d'identification de l'utilisation avec la fonction CURRENT_USER() (nouveau en MySQL 4.0.6). Puis, utilisez cette valeur avec la commande SHOW GRANTS. Voir Section 12.8.3, « Fonctions d'informations ».

SHOW GRANTS est disponible depuis MySQL 3.23.4.

13-5-3-10 - Syntaxe de SHOW INDEX

SHOW INDEX FROM tbl_name [FROM db_name]

SHOW INDEX retourne les informations sur les index de la table, dans un format proche de celui de SQLStatistics en ODBC.

SHOW INDEX retourne les champs suivants.

- Table

Le nom de la table.

- Non_unique

0 si l'index ne peut pas contenir de doublons, et 1 s'il le peut.

- Key_name

Le nom de l'index.

- Seq_in_index

Le numéro de la colonne dans l'index, en commençant à 1.

- Column_name

Le nom de la colonne.

- Collation

Comment la colonne est triée dans l'index. Avec MySQL, les valeurs peuvent être 'A' (Ascendant) ou NULL (non trié).

- Cardinality

Le nombre de valeurs uniques dans l'index. C'est une valeur qui est mise à jour avec la commande ANALYZE TABLE ou myisamchk -a. Cardinality est compté en se basant sur des statistiques entières : il n'est pas toujours exact pour les petites tables.

- Sub_part

Le nombre de caractères indexés si la colonne n'est que partiellement indexée. NULL si la colonne entière est indexée.

- Packed

Indique comment la clé est compactée. NULL si elle ne l'est pas.

- Null

Contient YES si la colonne contient NULL, '' sinon.

- Index_type

La méthode d'indexation utilisée (BTREE, FULLTEXT, HASH, RTREE).

- Comment

Différentes remarques. Avant MySQL 4.0.2 lorsque la colonne Index_type a été ajoutée, Comment indiquait si un index était FULLTEXT.

Les colonnes Packed et Comment ont été ajoutées en MySQL 3.23.0. Les colonnes Null et Index_type ont été ajoutées en MySQL 4.0.2.

Vous pouvez utiliser la syntaxe db_name.tbl_name comme substitut à tbl_name FROM db_name. Ces deux commandes sont équivalentes :

mysql> SHOW INDEX FROM mytable FROM mydb;
mysql> SHOW INDEX FROM mydb.mytable;

SHOW KEYS est un synonyme SHOW INDEX. Vous pouvez aussi lister les index d'une table avec la commande en ligne mysqlshow -k db_name tbl_name.

13-5-3-11 - Syntaxe de SHOW INNODB STATUS

SHOW INNODB STATUS

Cette commande donne des informations exhaustives sur le moteur de stockage InnoDB.

13-5-3-12 - Syntaxe de SHOW LOGS

SHOW [BDB] LOGS

La commande SHOW LOGS affiche les informations d'état de vos fichiers de logs. Actuellement, elle n'affiche que les informations pour les fichiers de logs des tables Berkeley DB.

- File affiche le chemin complet jusqu'au fichier de logs.

- Type affiche le type de fichier de logs (BDB pour les tables de types Berkeley DB).

- Status affiche le statut du fichier de logs (FREE si le fichier peut être supprimé, ou IN USE si le fichier est utilisé par une transaction en cours).

13-5-3-13 - SHOW PRIVILEGES

SHOW PRIVILEGES

Cette commande est implémentée en MySQL 4.1.0.

SHOW PRIVILEGES affiche la liste des droits que le serveur MySQL supporte.

mysql> show privileges;
+------------+--------------------------+-------------------------------------------------------+
| Privilege  | Context                  | Comment                                               |
+------------+--------------------------+-------------------------------------------------------+
| Select     | Tables                   | Lire des lignes d'une table                           |
| Insert     | Tables                   | Insérer des lignes dans une table                     |
| Update     | Tables                   | Modifier les lignes existantes                        |
| Delete     | Tables                   | Effacer des lignes existantes                         |
| Index      | Tables                   | Créer ou effacer des index                            |
| Alter      | Tables                   | Modifier la structure d'une table                     |
| Create     | Databases,Tables,Indexes | Créer une nouvelle base ou table                      |
| Drop       | Databases,Tables         | Effacer une base ou table                             |
| Grant      | Databases,Tables         | Donner à d'autres les droits courants                 |
| References | Databases,Tables         | Avoir des références sur les tables                   |
| Reload     | Server Admin             | Rafraîchir les droits, tables et logs                 |
| Shutdown   | Server Admin             | Éteindre le serveur                                   |
| Process    | Server Admin             | Voir la version texte des requêtes en cours           |
| File       | File access on server    | Lire et écrire des fichiers sur le serveur            |
+------------+--------------------------+-------------------------------------------------------+
14 rows in set (0.00 sec)

13-5-3-14 - Syntaxe de SHOW PROCESSLIST

SHOW [FULL] PROCESSLIST

SHOW [FULL] PROCESSLIST affiche la liste de processus qui sont en cours d'exécution. Vous pouvez aussi obtenir ces informations avec la commande en ligne mysqladmin processlist. Si vous avez les droits de SUPER, vous pourrez aussi voir les autres threads. Sinon, vous ne pourrez voir que les vôtres. Voir Section 13.5.4.3, « Syntaxe de KILL ». Si vous n'utilisez pas l'option FULL, seuls les 100 premiers caractères de chaque requête seront affichés.

Cette commande est très pratique si vous obtenez trop d'erreurs 'too many connections' et que vous voulez savoir ce qui se passe. MySQL réserve une connexion supplémentaire pour un client ayant les droits de SUPER, de façon à ce qu'il ait toujours la possibilité de se connecter et de vérifier le système (en supposant que vous ne donnez pas ce droit à tous vos utilisateurs).

Certains états sont souvent disponibles dans le résultat de mysqladmin processlist.

- Checking table

Le thread fait une vérification (automatique) de la table.

- Closing tables

Le thread est en train d'écrire les données modifiées sur le disque, et il va fermer les tables. Cela doit être une opération très rapide. Si ce n'est pas le cas, vous devriez vérifier si vous n'avez pas un disque plein, ou que le disque est sous haute charge.

- Connect Out

Connexion d'un esclave sur le maître.

- Copying to tmp table on disk

Le résultat temporaire était plus grand que tmp_table_size et le thread passe d'une table en mémoire à une table sur disque.

- Creating tmp table

Le thread est en train de créer une table temporaire pour contenir le résultat d'une requête.

- deleting from main table

Lors de l'exécution de la première partie d'une requête d'effacement multitable, et que MySQL n'a commencé à effacer que dans la première table.

- deleting from reference tables

Lors de l'exécution de la deuxième partie d'une requête d'effacement multitable, et que MySQL a commencé à effacer dans les autres tables.

- Flushing tables

Le thread exécute la commande FLUSH TABLES et il attend que tous les threads ferment leurs tables.

- Killed

Quelqu'un a envoyé une commande KILL et le thread s'annulera la prochaine fois qu'il vérifie l'option de kill. Cette option est vérifiée dans chaque boucle majeure de MySQL, mais dans certains cas, il peut lui prendre un court instant avant de s'arrêter. Si le thread est verrouillé par un autre thread, l'arrêt va prendre effet aussitôt que l'autre thread lève son verrou.

- Sending data

Le thread traite des lignes pour une commande SELECT et il envoie les données au client.

- Sorting for group

Le thread est en train de faire un tri pour satisfaire une clause GROUP BY.

- Sorting for order

Le thread est en train de faire un tri pour satisfaire une clause ORDER BY.

- Opening tables

Cela signifie simplement que le thread essaie d'ouvrir une table. Ce doit être une opération très rapide, à moins que quelque chose ne retarde l'ouverture. Par exemple, une commande ALTER TABLE ou LOCK TABLE peut empêcher l'ouverture de table, jusqu'à l'achèvement de la commande.

- Removing duplicates

La requête utilisait SELECT DISTINCT de telle manière que MySQL ne pouvait pas optimiser les lignes distinctes au début du traitement. À cause de cela, MySQL doit effectuer une opération de plus pour supprimer toutes les lignes en double, avant d'envoyer les lignes au client.

- Reopen table

Le thread a reçu un verrou pour une table, mais a noté après l'avoir reçu que la structure de la table a changé. Il a libéré le verrou, fermé la table, et maintenant il essaie de la rouvrir.

- Repair by sorting

Le thread répare la table en utilisant la méthode de tri pour créer l'index.

- Repair with keycache

Le thread répare la table en utilisant la méthode de création des clés à partir du cache de clés. C'est bien plus lent que la réparation par tri.

- Searching rows for update

Le thread effectue une première phase pour trouver toutes les lignes qui satisfont les critères avant de les modifier. Cela doit être fait si UPDATE modifie l'index qui sera utilisé pour trouver les lignes.

- Sleeping

Le thread attend que le client envoie une nouvelle commande.

- System lock

Le thread attend le verrou externe pour la table. Si vous n'utilisez pas de serveurs MySQL multiples qui exploitent les mêmes tables, vous pouvez désactiver les verrous système avec l'option --skip-external-locking.

- Upgrading lock

Le gestionnaire de INSERT DELAYED essaie d'obtenir un verrou pour insérer des lignes.

- Updating

Le thread recherche des lignes pour les modifier.

- User Lock

Le thread attend un GET_LOCK().

- Waiting for tables

Le thread a reçu l'annonce que la structure de table a été modifiée, et il doit rouvrir la table pour obtenir une nouvelle structure. Pour être capable de rouvrir la table, il doit attendre que les autres threads aient fermé la table en question.

Cette annonce survient lorsqu'un autre thread a été utilisé avec la commande FLUSH TABLES ou une des commandes suivantes, appliquées à la table en question : FLUSH TABLES table_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE ou OPTIMIZE TABLE.

- waiting for handler insert

Le gestionnaire de INSERT DELAYED a traité toutes insertions, et en attend de nouvelles.

La plupart des états sont des opérations très rapides. Si le thread s'attarde dans un de ces états pour plusieurs secondes, il doit y avoir un problème qui mérite d'être étudié.

Il existe encore d'autres états qui ne sont pas mentionnés ci-dessus, mais la majorité sont utilisés pour trouver des bogues dans mysqld.

13-5-3-15 - Syntaxe de SHOW STATUS

SHOW STATUS [LIKE 'pattern']

SHOW STATUS affiche des informations sur le statut du serveur. Cette information est aussi accessible avec la commande la commande mysqladmin extended-status.

Un résultat partiel est présenté ci-dessous. La liste complète des variables dépend de votre serveur. Leur signification individuelle est présentée dans la section Voir Section 5.2.4, « Variables de statut du serveur  ».

mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| Aborted_clients          | 0          |
| Aborted_connects         | 0          |
| Bytes_received           | 155372598  |
| Bytes_sent               | 1176560426 |
| Connections              | 30023      |
| Created_tmp_disk_tables  | 0          |
| Created_tmp_tables       | 8340       |
| Created_tmp_files        | 60         |
...
| Open_tables              | 1          |
| Open_files               | 2          |
| Open_streams             | 0          |
| Opened_tables            | 44600      |
| Questions                | 2026873    |
...
| Table_locks_immediate    | 1920382    |
| Table_locks_waited       | 0          |
| Threads_cached           | 0          |
| Threads_created          | 30022      |
| Threads_connected        | 1          |
| Threads_running          | 1          |
| Uptime                   | 80380      |
+--------------------------+------------+

Avec la clause LIKE, la commande peut limiter l'affichage des variables à celles qui vérifient un masque :

mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| Key_blocks_used    | 14955    |
| Key_read_requests  | 96854827 |
| Key_reads          | 162040   |
| Key_write_requests | 7589728  |
| Key_writes         | 3813196  |
+--------------------+----------+

13-5-3-16 - SHOW TABLE STATUS

SHOW TABLE STATUS [FROM db_name] [LIKE wild]

SHOW TABLE STATUS (nouveau en version 3.23) fonctionne comme SHOW STATUS, mais fournit des informations sur les tables. Vous pouvez aussi obtenir ces informations en utilisant la commande en ligne mysqlshow --status db_name. Les données suivantes sont retournées.

- Name

Nom de la table.

- Type

Type de table. Voir Chapitre 14, Moteurs de tables MySQL et types de table.

- Row_format

Le format de stockage de ligne (Fixed, Dynamic ou Compressed).

- Rows

Nombre de lignes.

- Avg_row_length

Taille moyenne d'une ligne.

- Data_length

Taille du fichier de données.

- Max_data_length

Taille maximale du fichier de données. Pour les formats de lignes fixes, c'est le nombre maximal de lignes dans la table. Pour les formats de lignes dynamiques, c'est le nombre total d'octets qui peuvent être stockés dans la table, avec le pointeur de données utilisé.

- Index_length

Taille du fichier d'index.

- Data_free

Nombre d'octets alloués mais non utilisés.

- Auto_increment

Prochaine valeur d'auto_increment.

- Create_time

Date de création de la table.

- Update_time

Date de dernière modification de la table.

- Check_time

Date de dernier entretien de la table.

- Collation

Le jeu de caractères et la collation de la table (nouveau en 4.1.1).

- Checksum

La somme de contrôle en direct (si elle existe). (Nouveau en 4.1.1.)

- Create_options

Options supplémentaires utilisées avec CREATE TABLE.

- Comment

Le commentaire utilisé lors de la création de la table (ou des informations sur pourquoi MySQL n'a pu accéder aux informations de la table).

Les tables InnoDB indiqueront l'espace disque libre dans le commentaire de table.

13-5-3-17 - Syntaxe de SHOW TABLES

SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']

SHOW TABLES liste les tables permanentes (non TEMPORARY) dans une base de données. Vous pouvez obtenir cette liste avec la commande en ligne mysqlshow db_name.

Note : si vous n'avez pas les droits sur une table, la table n'apparaîtra pas dans le résultat de SHOW TABLES et mysqlshow db_name.

SHOW OPEN TABLES liste les tables qui sont actuellement ouvertes dans le cache de tables. Voir Section 7.4.8, « Quand MySQL ouvre et ferme les tables ». Le champ Comment du résultat indique le nombre d'ouvertures de la table en cache (cached) et le nombre d'utilisations (in_use). OPEN est disponible depuis MySQL 3.23.33.

13-5-3-18 - Syntaxe de SHOW VARIABLES

SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']

SHOW VARIABLES affiche les valeurs des variables système de MySQL. Vous pouvez aussi obtenir ces informations avec la commande mysqladmin variables.

Les options GLOBAL et SESSION ont été ajoutées en MySQL 4.0.3. Avec GLOBAL, vous obtiendrez les valeurs qui seront utilisées pour les nouvelles connexions au serveur MySQL. Avec SESSION, vous recevez les valeurs effectives pour la connexion en cours. Si vous ne précisez ni l'une ni l'autre, la valeur par défaut est SESSION. LOCAL est un synonyme de SESSION.

Si les valeurs par défaut ne vous conviennent pas, vous pouvez modifier la plupart de ces variables, en ligne de commande, lorsque mysqld est lancé. Voir Section 5.2.1, « Options de ligne de commande de mysqld » et Section 13.5.2.8, « Syntaxe de SET ».

Voici un extrait du résultat de la commande. La liste complète des variables et de leur valeur peut être différente pour votre serveur. La signification de chaque variable est présentée dans Section 5.2.3, « Variables serveur système ». Des informations sur comment optimiser ces valeurs sont disponibles dans la section Section 7.5.2, « Réglage des paramètres du serveur ».

mysql> SHOW VARIABLES;
+---------------------------------+------------------------------+
| Variable_name                   | Value                        |
+---------------------------------+------------------------------|
| back_log                        | 50                           |
| basedir                         | /usr/local/mysql             |
| bdb_cache_size                  | 8388572                      |
| bdb_log_buffer_size             | 32768                        |
| bdb_home                        | /usr/local/mysql             |
...
| max_connections                 | 100                          |
| max_connect_errors              | 10                           |
| max_delayed_threads             | 20                           |
| max_error_count                 | 64                           |
| max_heap_table_size             | 16777216                     |
| max_join_size                   | 4294967295                   |
| max_relay_log_size              | 0                            |
| max_sort_length                 | 1024                         |
...
| timezone                        | EEST                         |
| tmp_table_size                  | 33554432                     |
| tmpdir                          | /tmp/:/mnt/hd2/tmp/          |
| version                         | 4.0.4-beta                   |
| wait_timeout                    | 28800                        |
+---------------------------------+------------------------------+

Avec la clause LIKE, la commande n'affichera que les variables qui vérifient le masque fourni :

mysql> SHOW VARIABLES LIKE 'have%';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| have_bdb           | YES      |
| have_innodb        | YES      |
| have_isam          | YES      |
| have_raid          | NO       |
| have_symlink       | DISABLED |
| have_openssl       | YES      |
| have_query_cache   | YES      |
+--------------------+----------+

13-5-3-19 - SHOW WARNINGS | ERRORS

SHOW WARNINGS [LIMIT [offset,] row_count]
SHOW COUNT(*) WARNINGS

Cette commande affiche les erreurs, alertes et notes qui ont été générées par la dernière commande. Les erreurs et alertes sont remises à zéro pour chaque nouvelle commande qui utilise une table. Cette commande a été implémentée depuis MySQL 4.1.0. Une commande connexe, SHOW ERRORS, affiche uniquement les erreurs. Voir Section 13.5.3.8, « Syntaxe de SHOW ERRORS ».

La liste de messages est remise à zéro au début de chaque commande qui utilise la table.

La commande SHOW COUNT(*) WARNINGS affiche le nombre total d'erreurs, d'alertes et de notes. Vous pouvez aussi lire ce nombre avec la variable warning_count :

SHOW COUNT(*) WARNINGS;
SELECT @@warning_count;

La valeur de warning_count peut être plus grande que le nombre de messages affichés par SHOW WARNINGS si la variable système max_error_count est configurée assez bas pour que tous les messages ne soient pas stockés. Un exemple plus loin dans cette section montre ce qui arrive.

La clause LIMIT a la même syntaxe que la commande SELECT. Voir Section 13.1.7, « Syntaxe de SELECT ».

Le serveur MySQL retourne le nombre total d'alertes et d'erreurs que vous avez obtenues lors de la dernière commande. Ils sont disponibles avec la fonction mysql_warning_count(). Voir Section 24.2.3.61, « mysql_warning_count() ».

Jusqu'à max_error_count messages peuvent être stockés (variable globale et spécifique aux threads).

Vous pouvez lire le nombre d'erreurs dans @error_count et le nombre d'alertes dans @warning_count.

SHOW WARNINGS affiche aussi toutes les erreurs, alertes et notes de la dernière commande, alors que SHOW ERRORS ne montre que les erreurs.

mysql> DROP TABLE IF EXISTS no_such_table;
mysql> SHOW WARNINGS;

+-------+------+-------------------------------+
| Level | Code | Message                       |
+-------+------+-------------------------------+
| Note  | 1051 | Unknown table 'no_such_table' |
+-------+------+-------------------------------+

Notez que depuis MySQL 4.1.0, nous avons ajouté un nouveau système d'alertes, et peu de commandes MySQL génèrent des alertes. 4.1.1 supporte toutes sortes d'alertes pour LOAD DATA INFILE et les commandes DML telles que INSERT, UPDATE et ALTER.

Par exemple, voici une situation simple qui produit des alertes de conversions pour une commande d'insertion :

mysql> create table t1(a tinyint NOT NULL, b char(4));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(10,'mysql'),(NULL,'test'),(300,'open source');
Query OK, 3 rows affected, 4 warnings (0.15 sec)
Records: 3  Duplicates: 0  Warnings: 4

mysql> show warnings;
+---------+------+---------------------------------------------------------------+
| Level   | Code | Message                                                       |
+---------+------+---------------------------------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1                        |
| Warning | 1261 | Data truncated, NULL supplied to NOT NULL column 'a' at row 2 |
| Warning | 1262 | Data truncated, out of range for column 'a' at row 3          |
| Warning | 1263 | Data truncated for column 'b' at row 3                        |
+---------+------+---------------------------------------------------------------+
4 rows in set (0.00 sec)

Le nombre maximal d'alertes peut être spécifié en utilisant la variable de serveur 'max_error_count', SET max_error_count=[count]. Par défaut, c'est 64. Pour désactiver les alertes, donnez simplement la valeur de 0 à la variable. Si max_error_count vaut 0, alors le nombre d'alertes représente toujours le nombre d'alertes qui ont eu lieu, mais aucun message d'erreur n'est accessible.

Par exemple, observez la commande ALTER suivante, pour l'exemple ci-dessus, qui retourne uniquement une alerte, même si le nombre total d'alertes est de 3 lorsque 'max_error_count'=1.

mysql> show variables like 'max_error_count';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_error_count | 64    |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> set max_error_count=1;
Query OK, 0 rows affected (0.00 sec)

mysql> alter table t1 modify b char;
Query OK, 3 rows affected, 3 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 3

mysql> show warnings;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1263 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

mysql>

13-5-4 - Autres commandes d'administration

13-5-4-1 - Syntaxe de CACHE INDEX

CACHE INDEX
table_index_list [, table_index_list] ...
IN key_cache_name

table_index_list:
tbl_name [[INDEX] (index_name[, index_name] ...)]

La commande CACHE INDEX assigne un index de table à un cache de clé spécifique. Cette commande est uniquement disponible pour les tables MyISAM.

La commande suivante assigne les index des tables t1, t2 et t3 au cache de clés appelé hot_cache :

mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+

La syntaxe de CACHE INDEX vous permet de spécifier des index particuliers à un cache. Cependant, l'implémentation courante assigne tous les index de la table au cache, et il n'y a donc pas d'intérêt à spécifier autre chose que le nom de la table.

Le cache de clés utilisé dans une commande CACHE INDEX peut être créé en lui donnant une taille avec une commande de configuration, ou la configuration du serveur. Par exemple :

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

Les paramètres du cache de clés sont accessibles depuis une variable système structurée. Voir Section 9.4.1, « Variables système structurées ».

Un cache de clés doit exister avant que vous ne l'utilisiez :

mysql> CACHE INDEX t1 in non_existent_cache;
ERROR 1283 (HY000): Unknown key cache 'non_existent_cache'

Par défaut, les index de table sont assignés au cache de clés par défaut, créé au moment du démarrage du serveur. Lorsqu'un cache de clés est détruit, tous les index qui lui étaient assignés sont transmis au cache par défaut.

Les assignations d'index affectent le serveur globalement : si un client assigne un index à un cache donné, ce cache sera utilisé pour toutes les requêtes, quel que soit le client qui émet la requête.

CACHE INDEX a été ajouté en MySQL 4.1.1.

13-5-4-2 - Syntaxe de FLUSH

FLUSH flush_option [,flush_option] ...

Vous devez utiliser la commande FLUSH si vous voulez effacer certains caches internes de MySQL. Pour exécuter FLUSH, vous devez avoir le droit RELOAD.

flush_option peut être l'une des suivantes.

- HOSTS

Vide le cache des hôtes. Vous devez vider ce cache si certaines des adresses IP de vos clients changent, ou si vous obtenez des erreurs du type Host ... is blocked. Lorsque plus de max_connect_errors erreurs successives surviennent pour un hôte, lors des connexions au serveur MySQL, MySQL suppose qu'il y a un problème, et interdit l'accès à l'hôte. Voir Section A.2.5, « Erreur Host '...' is blocked ». Vous pouvez démarrer mysqld avec -O max_connect_errors=999999999 pour éviter ce message.

- DES_KEY_FILE

Recharge les clés DES depuis le fichier de stockage spécifié par --des-key-file lors du démarrage du serveur.

- LOGS

Ferme et rouvre tous les fichiers de logs. Si vous avez spécifié un fichier de logs de mises à jour, ou un fichier de logs binaire sans extension, le numéro d'extension du fichier de logs sera incrémenté d'une unité. Si vous avez utilisé une extension dans le nom du fichier, MySQL va fermer et rouvrir le même fichier. Voir Section 5.9.3, « Le log de modification ». Ceci est la même chose que d'envoyer le signal SIGHUP au serveur mysqld.

- PRIVILEGES

Recharge les privilèges des tables de droits dans la base mysql.

- QUERY CACHE

Défragmente le cache des requêtes pour mieux en utiliser la mémoire. Cette commande n'effacera aucune requête du cache, à la différence de RESET QUERY CACHE.

- TABLES

Ferme toutes les tables ouvertes, et force les tables utilisées à se refermer. Cela vide aussi le cache de requêtes.

- [TABLE | TABLES] nom_de_table [,nom_de_table...]

Vide du cache uniquement les tables nommées.

- TABLES WITH READ LOCK

Ferme toutes les tables ouvertes, et verrouille en lecture toutes les tables et bases, jusqu'à ce que vous exécutiez une commande UNLOCK TABLES. C'est très pratique pour générer des sauvegardes, si vous avez un système de fichiers comme Veritas, qui peut prendre des photos du système.

- STATUS

Remet la plupart des variables de statut à zéro. À n'utiliser que pour corriger une requête. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

- USER_RESOURCES

Remet toutes les ressources à zéro. Cela va autoriser de nouveau les utilisateurs qui ont été bloqués. Voir Section 5.6.4, « Limiter les ressources utilisateur ».

Vous pouvez aussi accéder à toutes les commandes décrites plus haut en les donnant en arguments à mysqladmin (exemple : flush-hosts, flush-logs, reload, ou encore flush-tables).

Reportez-vous aussi à la commande RESET avec la réplication. Voir Section 13.5.4.5, « Syntaxe de la commande RESET ».

13-5-4-3 - Syntaxe de KILL

KILL [CONNECTION | QUERY] thread_id

Chaque connexion à mysqld utilise un thread unique. Vous pouvez voir les threads en cours d'exécution en utilisant la commande SHOW PROCESSLIST et en terminer un avec la commande KILL thread_id.

Depuis MySQL 5.0.0, KILL autorise les options CONNECTION et QUERY.

- KILL CONNECTION est similaire à KILL sans option : elle termine la connexion associée avec le thread thread_id.

- KILL QUERY termine la requête que la connexion est actuellement en train de traiter, mais laisse la connexion ouverte.

Si vous avez le droit PROCESS, vous pouvez voir tous les threads. Si vous avez le droit SUPER, vous pouvez terminer tous les threads. Sinon, vous ne pouvez terminer que vos propres threads.

Vous pouvez aussi utiliser les commandes mysqladmin processlist et mysqladmin kill pour examiner et terminer les threads.

Note : vous ne pouvez actuellement pas utiliser KILL avec la bibliothèque du serveur embarqué, car celui-ci utilise les threads de l'application hôte, il ne crée pas ses propres threads.

Quand vous exécutez un KILL, un thread spécifique est créé pour ce thread.

Dans la plupart des cas, la terminaison du thread pourra prendre un certain temps vu que le thread de terminaison est invoqué à intervalles spécifiques.

- Pour les boucles de SELECT, ORDER BY et GROUP BY, le thread de terminaison est vérifié après avoir lu un enregistrement. S'il est activé, la requête est abandonnée.

- Lors d'un ALTER TABLE le thread de terminaison est vérifié avant la lecture de chacune des colonnes de la table d'origine. S'il est activé, la commande est abandonnée et la table temporaire effacée.

- Lors d'un UPDATE ou d'un DELETE, le thread de terminaison est vérifié après chaque lecture de bloc et chaque mise à jour ou suppression de ligne. S'il est activé, la requête est abandonnée. Notez que si vous utilisez les transactions, les modifications ne seront pas perdues !

- GET_LOCK() stoppera avec NULL.

- Un thread INSERT DELAYED videra rapidement toutes les lignes en mémoire et se terminera.

- Si le thread est dans le gestionnaire des verrous de tables (état : Locked), le verrou sur la table sera vite enlevé.

- Si le thread est en attente de libération d'espace disque lors d'un appel à write, l'opération est avortée avec un message d'erreur indiquant que le disque est plein.

13-5-4-4 - Syntaxe de LOAD INDEX INTO CACHE

LOAD INDEX INTO CACHE
table_index_list [, table_index_list] ...

table_index_list:
tbl_name
[[INDEX] (index_name[, index_name] ...)]
[IGNORE LEAVES]

La commande LOAD INDEX INTO CACHE précharge un index dans un cache de clés, qui est explicitement nommé dans la commande CACHE INDEX, ou dans le cache par défaut. LOAD INDEX INTO CACHE ne sert que pour les tables MyISAM.

L'option IGNORE LEAVES fait que les blocs terminaux de l'index ne sont pas lus.

La commande suivante précharge les nœuds des tables t1 et t2 :

mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table   | Op           | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status   | OK       |
| test.t2 | preload_keys | status   | OK       |
+---------+--------------+----------+----------+

Cette commande charge tous les index de t1. Elle ne charge que les index non terminaux de t2.

La syntaxe de LOAD INDEX INTO CACHE vous permet de spécifier seulement des index particuliers à charger dans la table. Cependant, l'implémentation courante charge tous les index : il n'y a pas de raison pour utiliser autre chose que le nom de la table.

LOAD INDEX INTO CACHE a été ajouté en MySQL 4.1.1.

13-5-4-5 - Syntaxe de la commande RESET

RESET reset_option [, reset_option] ...

La commande RESET sert à remettre à zéro des données. C'est aussi une version plus puissante de la commande FLUSH. Voir Section 13.5.4.2, « Syntaxe de FLUSH ».

Pour exécuter la commande RESET, vous devez avoir les droits RELOAD.

- MASTER

Efface tous les logs binaires listés dans le fichier d'index, et l'index binlog est vidé. Dans les versions antérieures à la version 3.23.26, cette commande s'appelait FLUSH MASTER (Master). Voir Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication ».

- QUERY CACHE

Supprime tous les résultats de requêtes du cache de requêtes.

- SLAVE

Annule la position de réplication de l'esclave dans les historiques du maître. Dans les versions antérieures à la version 3.23.26, cette commande s'appelait FLUSH SLAVE (Slave). Voir Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication ».

13-6 - Commandes de réplication

Cette section décrit les commandes liées à la réplication. Un groupe de commandes peut être utilisé pour contrôler le serveur. L'autre groupe sert avec les esclaves.

13-6-1 - Requêtes SQL pour contrôler les maîtres de réplication

La réplication est contrôlable via l'interface SQL. Cette section présente les commandes qui contrôlent les maîtres de réplication. La Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication » présente les commandes pour gérer les esclaves.

13-6-1-1 - PURGE MASTER LOGS

PURGE {MASTER | BINARY} LOGS TO 'log_name'
PURGE {MASTER | BINARY} LOGS BEFORE 'date'

Efface tous les logs binaires listés dans l'index de logs, qui sont antérieurs à la date ou au log indiqué. Les logs sont aussi supprimés de cette liste : le log donné en paramètre devient alors le premier de la liste.

Exemple :

PURGE MASTER LOGS TO 'mysql-bin.010';
PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';

La variante BEFORE est disponible en MySQL 4.1; son argument de date peut être au format 'YYYY-MM-DD hh:mm:ss'. MASTER et BINARY sont synonymes, mais BINARY ne peut être utilisé que depuis MySQL 4.1.1.

Si vous avez un esclave actif qui est actuellement en train de lire l'un des logs que vous voulez effacer, la commande ne fera rien, et échouera avec une erreur. Cependant, si l'esclave est inactif, et que vous effacez un des logs qu'il utilisait, l'esclave sera incapable de reprendre la réplication. Cette commande peut être utilisée sans problème durant la réplication : vous n'avez pas besoin d'arrêter les esclaves.

Pour purger les logs, suivez cette procédure :

1. Sur chaque esclave, utilisez la commande SHOW SLAVE STATUS pour vérifier quel log est lu ;

2. Faites une liste des logs sur le maître avec SHOW MASTER LOGS ;

3. Déterminez le plus ancien log parmi ceux utilisés par les esclaves. C'est votre limite. Si tous les esclaves sont à jour, alors ce sera le dernier log de la liste ;

4. Faites une sauvegarde de tous les logs que vous allez effacer. Cette étape est optionnelle, mais c'est une bonne idée ;

5. Purgez tous les logs jusqu'à celui qui précède votre limite.

13-6-1-2 - RESET MASTER

RESET MASTER

Efface tous les fichiers de logs binaires dans le fichier d'index, et vide le fichier d'index des logs.

Cette commande s'appelait FLUSH MASTER avant MySQL 3.23.26.

13-6-1-3 - SET SQL_LOG_BIN

SET SQL_LOG_BIN = {0|1}

Inactive ou active le log binaire de la connexion courante (SQL_LOG_BIN est une variable de session), si le client se connecte avec un compte qui a les droits de SUPER. La commande est ignorée si le client n'a pas de droits.

13-6-1-4 - SHOW BINLOG EVENTS

SHOW BINLOG EVENTS [ IN 'log_name' ] [ FROM pos ] [ LIMIT [offset,] row_count ]

Affiche les événements du log binaire. Si vous ne spécifiez pas 'log_name', le premier log binaire sera affiché.

La clause LIMIT a la même syntaxe que celle de la commande SELECT. Voir Section 13.1.7, « Syntaxe de SELECT ».

Cette commande est disponible en MySQL 4.0.

13-6-1-5 - SHOW MASTER LOGS

SHOW MASTER LOGS

Liste les logs binaires disponibles sur le maître. Vous devriez utiliser cette commande avant PURGE MASTER LOGS pour savoir jusqu'où vous pouvez aller.

13-6-1-6 - SHOW MASTER STATUS

SHOW MASTER STATUS

Affiche les informations d'état du log binaire du maître.

13-6-1-7 - SHOW SLAVE HOSTS

SHOW SLAVE HOSTS

Affiche la liste des esclaves actuellement enregistrée sur le maître. Notez que les esclaves qui ne sont pas lancés avec l'option --report-host=nom_d_esclave ne seront pas visibles dans cette liste.

13-6-2 - Commandes SQL de contrôle des esclaves de réplication

La réplication est contrôlable via l'interface SQL. Cette section présente les commandes qui contrôlent les esclaves de réplication. La Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication » présente les commandes pour gérer les maîtres.

13-6-2-1 - CHANGE MASTER TO

CHANGE MASTER TO master_def [, master_def] ...

master_def =
MASTER_HOST = 'host_name'
| MASTER_USER = 'user_name'
| MASTER_PASSWORD = 'password'
| MASTER_PORT = port_num
| MASTER_CONNECT_RETRY = count
| MASTER_LOG_FILE = 'master_log_name'
| MASTER_LOG_POS = master_log_pos
| RELAY_LOG_FILE = 'relay_log_name'
| RELAY_LOG_POS = relay_log_pos
| MASTER_SSL = {0|1}
| MASTER_SSL_CA = 'ca_file_name'
| MASTER_SSL_CAPATH = 'ca_directory_name'
| MASTER_SSL_CERT = 'cert_file_name'
| MASTER_SSL_KEY = 'key_file_name'
| MASTER_SSL_CIPHER = 'cipher_list'

Modifie les paramètres que l'esclave utilise pour se connecter et pour communiquer avec le serveur maître. Les valeurs possibles pour master_def sont présentées ci-dessus.

Les options de log de relais, RELAY_LOG_FILE et RELAY_LOG_POS, sont disponibles depuis MySQL 4.0.

Les options SSL, MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEY et MASTER_SSL_CIPHER, sont disponibles depuis MySQL 4.1.1. Vous pouvez changer ces options même sur les esclaves qui sont compilés sans le support SSL. Elles seront sauvées dans le fichier master.info, mais ignorées jusqu'à ce que le support SSL soit activé.

Par exemple :

mysql> CHANGE MASTER TO
->     MASTER_HOST='master2.mycompany.com',
->     MASTER_USER='replication',
->     MASTER_PASSWORD='bigs3cret',
->     MASTER_PORT=3306,
->     MASTER_LOG_FILE='master2-bin.001',
->     MASTER_LOG_POS=4,
->     MASTER_CONNECT_RETRY=10;
mysql> CHANGE MASTER TO
->     RELAY_LOG_FILE='slave-relay-bin.006',
->     RELAY_LOG_POS=4025;

MASTER_USER, MASTER_PASSWORD, MASTER_SSL, MASTER_SSL_CA, MASTER_SSL_CAPATH, MASTER_SSL_CERT, MASTER_SSL_KEY, et MASTER_SSL_CIPHER sont des informations qui permettent à l'esclave de se connecter au maître. Si vous omettez certains paramètres, les paramètres omis conserveront leur ancienne valeur. Par exemple, si le mot de passe sur le maître a changé, il suffit de faire :

mysql> STOP SLAVE; -- if replication was running
mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
mysql> START SLAVE; -- if you want to restart replication

pour indiquer à l'esclave le nouveau mot de passe : il n'y a pas besoin de spécifier les informations qui n'ont pas changé, comme l'hôte, le port, l'utilisateur, etc.

MASTER_HOST, MASTER_PORT sont le nom d'hôte ou l'adresse IP du maître, et son port TCP. Notez que si MASTER_HOST est égal à localhost, alors, comme généralement avec MySQL, le port sera ignoré si les sockets Unix sont utilisables.

Si vous spécifiez MASTER_HOST ou MASTER_PORT, l'esclave supposera que le serveur maître est différent du précédent, même si vous spécifiez les mêmes valeurs d'hôte et de port que précédemment. Dans ce cas, les anciennes valeurs et positions de l'historique binaire ne sont plus valides. Ainsi, si vous ne spécifiez pas MASTER_LOG_FILE et MASTER_LOG_POS dans la commande, MASTER_LOG_FILE='' et MASTER_LOG_POS=4 sont ajoutés silencieusement.

MASTER_LOG_FILE et MASTER_LOG_POS sont les coordonnées auxquelles le thread d'I/O doit commencer à lire chez le maître, lorsque le thread redémarrera. Si vous spécifiez l'un d'entre eux, vous ne pourrez pas spécifier RELAY_LOG_FILE ou RELAY_LOG_POS. Si MASTER_LOG_FILE ni MASTER_LOG_POS n'ont été spécifiés, alors les dernières coordonnées du thread esclave d'avant la commande CHANGE MASTER seront utilisées. Cela assure que la réplication ne connaît pas de discontinuité, même si le thread esclave était en retard sur le thread d'I/O, alors que vous ne voulez changer que le mot de passe. Ce comportement sécuritaire a été introduit à partir de MySQL versions 4.0.17 et 4.1.1. Avant ces versions, les coordonnées utilisées étaient celles du thread d'I/O, avant que la commande CHANGE MASTER soit émise, ce qui conduisait à des pertes d'événements au niveau du maître, et donc, la corruption de la réplication.

CHANGE MASTER efface tous les logs de relais (et en démarre de nouveaux), à moins que vous ne spécifiiez l'option RELAY_LOG_FILE ou RELAY_LOG_POS (dans ce cas, les logs de relais seront conservés, depuis MySQL 4.1.1 la variable globale RELAY_LOG_PURGE sera automatiquement mise à 0). CHANGE MASTER TO modifie master.info et relay-log.info.

CHANGE MASTER sert à configurer un esclave lorsque vous avez une sauvegarde du maître, son log et la position qui correspond à la sauvegarde du maître. Vous pouvez utiliser la commande CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master', MASTER_LOG_POS=log_offset_on_master sur l'esclave après la restauration de la sauvegarde.

Le premier exemple ci-dessus (CHANGE MASTER TO MASTER_HOST='master2.mycompany.com' etc) modifie les coordonnées du maître et de son log binaire. Cela est utile lorsque vous voulez que l'esclave réplique le maître. Le second exemple, moins fréquent, sert lorsque l'esclave a des logs de relais que vous voulez utiliser à nouveau. Pour cela, le maître n'a pas besoin d'être rejoint : il suffit d'utiliser la commande CHANGE MASTER TO et de lancer le thread SQL START SLAVE SQL_THREAD. Vous pouvez même utiliser cela dans une configuration de réplication, sur un serveur indépendant, pour assurer la restauration après crash. Supposez que votre serveur soit planté, et que vous avez restauré la sauvegarde. Vous voulez que le serveur exécute à nouveau ses propres logs (non pas des logs de relais, mais ses logs binaires), qui sont par exemple, stockés sous le nom myhost-bin.*. Tout d'abord, faites une copie des fichiers de logs dans un entrepôt, au cas où une erreur de manipulation surviendrait, et que le serveur vide ses logs. Si vous utilisez MySQL 4.1.1 ou plus récents, utilisez la commande suivante pour plus de sécurité : SET GLOBAL RELAY_LOG_PURGE=0.

Puis, lancez le serveur sans log-bin, et avec un nouvel identifiant (différent du précédent), avec l'option relay-log=myhost-bin (pour faire croire au serveur que ses propres logs sont des logs de relais), et skip-slave-start. Puis, envoyez cette commande :

mysql> CHANGE MASTER TO
->     RELAY_LOG_FILE='myhost-bin.153',
->     RELAY_LOG_POS=410,
->     MASTER_HOST='some_dummy_string';
mysql> START SLAVE SQL_THREAD;

Le serveur va alors lire et exécuter ses propres logs, et rattraper les données jusqu'au crash.

Une fois la restauration finie, faites STOP SLAVE, éteignez le serveur, supprimez master.info et relay-log.info, puis relancez le serveur avec ses options originales.

Pour le moment, spécifier MASTER_HOST (même avec une valeur insignifiante) est obligatoire pour que le serveur pense qu'il est un esclave. Donner au serveur un nouvel identifiant, différent du précédent, est aussi obligatoire, car sinon, le serveur va voir des événements avec son identifiant, et il va conclure que c'est une réplication circulaire, et il va les ignorer. Dans le futur, nous envisageons de nous débarrasser de ces petites contraintes.

13-6-2-2 - LOAD DATA FROM MASTER

LOAD DATA FROM MASTER

Fait une sauvegarde du maître et la copie vers l'esclave. Met à jour les valeurs de MASTER_LOG_FILE et MASTER_LOG_POS pour que la réplication reprenne à la bonne position. Respecte les interdictions de réplications de tables et de bases spécifiées par les options replicate-*.

L'utilisation de cette commande est sujette aux conditions suivantes.

- Fonctionne avec les tables MyISAM.

- Pose un verrou global en lecture sur le maître durant la sauvegarde, qui empêche les modifications sur le maître durant la phase de chargement.

Dans le futur, il est prévu de faire que cette commande fonctionne avec les tables InnoDB, et qu'elle se passe du verrou global en utilisant des fonctionnalités de sauvegarde à chaud non bloquantes.

Si vous chargez de très grosses tables, pensez à augmenter les valeurs des options net_read_timeout et net_write_timeout sur vos maître et esclave. Voir Section 5.2.3, « Variables serveur système ».

Notez que LOAD DATA FROM MASTER ne copie pas les tables de droits de la base mysql. C'est fait pour simplifier l'utilisation de droits et utilisateurs différents sur le maître et les esclaves.

Cette commande requiert les droits de RELOAD et SUPER sur le maître, et le droit de SELECT sur toutes les tables du maître qui seront lues. Toutes les tables du maître sur lesquelles l'utilisateur n'a pas de droits de SELECT seront ignorées par LOAD DATA FROM MASTER; ceci est dû au fait que le maître va masquer ces tables à l'utilisateur : LOAD DATA FROM MASTER utilise SHOW DATABASES pour connaître les tables à charger, mais SHOW DATABASES ne retourne que les bases pour lesquelles l'utilisateur a des droits. Voyez Section 13.5.3.6, « Syntaxe de SHOW DATABASES ». Sur l'esclave, l'utilisateur qui envoie la commande LOAD DATA FROM MASTER doit avoir les droits de création et d'effacement des tables et bases impliquées.

13-6-2-3 - Syntaxe de LOAD TABLE tbl_name FROM MASTER

LOAD TABLE tbl_name FROM MASTER

Télécharge une copie d'une table depuis le maître vers l'esclave. Cette commande est implémentée pour déboguer la commande LOAD DATA FROM MASTER. Elle requiert un compte pour se connecter au maître, avec les droits de RELOAD et SUPER, ainsi que les droits de SELECT sur la table à charger. Côté esclave, l'utilisateur qui émet la commande doit avoir les droits de LOAD TABLE FROM MASTER pour créer et effacer les tables. Lisez les informations sur les problèmes réseau dans LOAD DATA FROM MASTER, elles s'appliquent aussi ici. Notez aussi que les limitations de LOAD DATA FROM MASTER s'appliquent aussi (par exemple, LOAD TABLE FROM MASTER ne fonctionne que sur les tables de type MyISAM).

13-6-2-4 - MASTER_POS_WAIT()

SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)

C'est une fonction et non pas une commande. Elle sert à s'assurer que l'esclave a atteint (lu et exécuté) les événements du log binaire du maître jusqu'à une certaine position. Voyez la Section 12.8.4, « Fonctions diverses » pour une description complète.

13-6-2-5 - RESET SLAVE

RESET SLAVE

Force l'esclave à oublier toutes les positions de réplications dans les logs du maître. Cette commande permet de faire un démarrage propre : elle efface les fichiers master.info et relay-log.info, et les logs de relais, puis crée un nouveau log de relais.

Note : tous les logs de relais sont effacés, même s'ils n'ont pas été totalement exécutés par le thread SQL. (C'est un état qui est probable si l'esclave de réplication est fortement chargé, ou si vous avez lancé une commande STOP SLAVE.) Les informations de connexions stockées dans le fichier master.info reprennent immédiatement les valeurs spécifiées dans les options de démarrage, si elles étaient précisées. Ces informations incluent notamment le nom de l'hôte maître, le port, l'utilisateur et le mot de passe. Si le thread esclave était au milieu d'une réplication temporaire lorsqu'il a été arrêté, et que RESET SLAVE a été émise, ces tables temporaires sont aussi effacées.

Cette commande s'appelait FLUSH SLAVE avant MySQL 3.23.26.

13-6-2-6 - SET GLOBAL SQL_SLAVE_SKIP_COUNTER

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n

Ignore les n prochains événements du maître. C'est une commande pratique pour rattraper les arrêts de réplications causés par une commande.

Cette commande n'est valide que lorsque le thread esclave ne fonctionne pas. Sinon, elle produit une erreur.

Avant MySQL 4.0, omettez le mot-clé GLOBAL dans la commande.

13-6-2-7 - SHOW SLAVE STATUS

SHOW SLAVE STATUS

Affiche des informations sur les paramètres essentiels des threads esclaves. Si vous utilisez cette commande avec le client mysql, vous pouvez utiliser le terminateur de commande \G plutôt que le point-virgule pour avoir un format plus lisible :

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: localhost
Master_User: root
Master_Port: 3306
Connect_Retry: 3
Master_Log_File: gbichot-bin.005
Read_Master_Log_Pos: 79
Relay_Log_File: gbichot-relay-bin.005
Relay_Log_Pos: 548
Relay_Master_Log_File: gbichot-bin.005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 79
Relay_Log_Space: 552
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 8

Suivant votre version de MySQL, vous pourriez ne pas voir tous les champs qui sont dans cet exemple. Notamment, il y a plusieurs champs qui ne sont disponibles qu'avec MySQL 4.1.1.

Les champs affichés par SHOW SLAVE STATUS ont les définitions suivantes.

- Slave_IO_State

Une copie de la colonne State de la commande SHOW PROCESSLIST pour le thread d'I/O. Elle va vous indiquer si le thread essaye de se connecter au maître, attend des événements, se reconnecte, etc. Les différents états possibles sont listés dans la Section 6.3, « Détails d'implémentation de la réplication ». Étudier cette colonne est nécessaire, par exemple, car le thread peut fonctionner, mais ne pas réussir à se connecter au maître : seule cette colonne vous indiquera ce type de problèmes. D'un autre côté, l'état du thread SQL n'est pas indiqué, car les problèmes sont bien plus simples avec lui : soit il fonctionne, et il n'y a pas de problème ; soit il ne fonctionne pas, et vous trouverez les messages d'erreur dans la colonne Last_Error, décrite plus bas.

Ce champ a été ajouté en MySQL 4.1.1.

- Master_Host

L'hôte maître courant.

- Master_User

Le nom de l'utilisateur utilisé pour se connecter au maître.

- Master_Port

Le port courant sur le maître.

- Connect_Retry

La valeur courante de l'option master-connect-retry.

- Master_Log_File

Le nom du fichier de logs binaire que le thread d'I/O utilise sur le maître.

- Read_Master_Log_Pos

La position que le thread d'I/O a atteinte dans le fichier de logs binaire du maître.

- Relay_Log_File

Le nom du fichier de logs de relais dans lequel le thread SQL est actuellement en train de lire et de travailler.

- Relay_Log_Pos

La position à laquelle le thread SQL est en train de travailler.

- Relay_Master_Log_File

Le nom du fichier de logs binaire du maître qui contient le dernier événement exécuté par le thread SQL.

- Slave_IO_Running

Indique si le thread d'I/O est lancé ou pas.

- Slave_SQL_Running

Indique si le thread SQL est lancé ou pas.

- Replicate_Do_DB, Replicate_Ignore_DB

La liste des bases de données qui ont été spécifiées dans l'option --replicate-do-db et --replicate-ignore-db, éventuellement.

- Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table

La liste des tables qui ont été spécifiées respectivement dans les options --replicate-do-table, --replicate-ignore-table, --replicate-wild-do-table et --replicate-wild-ignore_table, éventuellement.

Ces champs ont été ajoutés en MySQL 4.1.1.

- Last_Errno, Last_Error

Last_Errno est le numéro d'erreur de la plus récente requête exécutée. La valeur de 0 signifie « pas d'erreur ». Last_Error est le message d'erreur de la plus récente requête exécutée. Par exemple :

Last_Errno: 1051
Last_Error: error 'Unknown table 'z'' on query 'drop table z'

Le message indique que la table z existait sur le maître et a été effacée, mais qu'elle n'existe pas sur l'esclave, et que DROP TABLE a échoué sur l'esclave. Cela peut arriver si vous avez oublié de copier une table dans l'esclave avant de lancer la réplication.

Une chaîne vide signifie « pas d'erreur ». Si Last_Error n'était pas vide, alors le même message apparaîtra dans le log d'erreur de l'esclave.

- Skip_Counter

La dernière valeur utilisée par SQL_SLAVE_SKIP_COUNTER.

- Exec_Master_Log_Pos

La position dans les logs binaires du maître (Relay_Master_Log_File) pour le dernier événement exécuté par le thread SQL. ((Relay_Master_Log_File,Exec_Master_Log_Pos) dans le log binaire du maître correspond à (Relay_Log_File,Relay_Log_Pos) dans le log de relais.

- Relay_Log_Space

La taille combinée de tous les logs de relais.

- Until_Condition, Until_Log_File, Until_Log_Pos

Les valeurs spécifiées dans la clause UNTIL de la commande START SLAVE.

Until_Condition peut prendre ces valeurs :

- None (aucune) si aucune clause UNTIL n'a été spécifiée ;

- Master (maître), si l'esclave lit depuis une position donnée, dans le log binaire du maître ;

- Relay (relais) si l'esclave lit dans une position donnée dans le log de relais.

Until_Log_File et Until_Log_Pos indiquent le nom du fichier de logs et la position qui définissent le point où le thread SQL va s'arrêter d'exécuter.

Ces champs ont été ajoutés en MySQL 4.1.1.

- Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key

Ces champs indiquent les paramètres SSL utilisés par l'esclave pour se connecter au maître, s'ils sont fournis.

Master_SSL_Allowed prend ses valeurs :

- Yes (oui) si la connexion SSL au maître est autorisée ;

- No (non) si la connexion SSL au maître est interdite ;

- Ignored (ignoré) si la connexion SSL au maître est autorisée par l'esclave, mais que le support de SSL n'est pas là.

Les valeurs des autres champs correspondent aux valeurs des options --master-ca, --master-capath, --master-cert, --master-cipher et --master-key.

Ces champs ont été ajoutés en MySQL 4.1.1.

- Seconds_Behind_Master

Le nombre de secondes qui se sont écoulées depuis le timestamp du dernier événement maître exécuté par le thread SQL. Ce sera NULL si aucun événement n'a été exécuté, ou après une commande CHANGE MASTER et RESET SLAVE. Cette colonne sert à mesurer le retard de l'esclave sur le maître. Cela fonctionne même si le maître et l'esclave ont des horloges réglées différemment.

Ce champ a été ajouté en MySQL 4.1.1.

13-6-2-8 - START SLAVE

START SLAVE [thread_name [, thread_name] ... ]
START SLAVE [SQL_THREAD] UNTIL
MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos

thread_name = IO_THREAD | SQL_THREAD

START SLAVE, appelé sans option, démarre les deux threads esclaves. Le thread I/O lit les requêtes du maître et les stocke dans le log de relais. Le thread SQL lit le log de relais, et exécute les requêtes. Notez que si START SLAVE réussit à lancer le thread esclave, elle se terminera sans erreur. Mais même dans ce cas, il se peut que le thread esclave se lance, puis s'arrête (car il n'a pas pu se connecter au maître, ou lire le log binaire ou tout autre problème). START SLAVE ne vous préviendra pas de cet événement. Vous devez vérifier le log d'erreur de l'esclave pour voir si des messages ont été générés, ou encore vérifier que tout fonctionne avec la commande SHOW SLAVE STATUS.

Depuis MySQL 4.0.2, vous pouvez ajouter les options IO_THREAD ou SQL_THREAD à la commande, pour nommer les threads que vous lancez.

Depuis MySQL 4.1.1, une clause UNTIL peut être ajoutée pour spécifier que l'esclave doit commencer à un certain point dans le log binaire, ou dans le log de relais. Lorsque le thread SQL atteint ce point, il s'arrête. Si l'option SQL_THREAD est spécifiée dans la commande, seul le thread SQL est lancé. Sinon, les deux threads sont lancés. Si le thread SQL est déjà lancé, la clause UNTIL est ignorée, et une alerte est émise.

Avec la clause UNTIL, vous devez spécifier à la fois un fichier de logs et une position. Ne confondez pas les options du maître et celles du log de relais.

Toute condition UNTIL est annulée par une commande STOP SLAVE, ou une commande START SLAVE qui n'inclut pas de condition UNTIL, ou encore un redémarrage serveur.

La clause UNTIL peut être utile pour déboguer la réplication, ou pour vous assurer que la réplication s'effectue jusqu'à un certain point. Par exemple, si une commande imprudente DROP TABLE a été exécutée sur le maître, vous pouvez utiliser la clause UNTIL pour dire à l'esclave de s'exécuter jusqu'à ce moment, puis de s'arrêter. Pour trouver cet événement, utilisez l'utilitaire mysqlbinlog sur le log du maître, ou sur le log de relais, ou encore utilisez la commande SHOW BINLOG EVENTS.

Si vous utilisez la clause UNTIL pour faire des réplications par portions, il est recommandé de lancer l'esclave avec l'option --skip-slave-start pour éviter que le thread SQL ne se lance lorsque l'esclave se lance. Il est probablement idéal d'utiliser cette option dans un fichier d'options plutôt qu'en ligne de commande, pour qu'un redémarrage intempestif ne l'oublie pas.

La commande SHOW SLAVE STATUS affiche un champ qui indique la valeur courante de la clause UNTIL.

13-6-2-9 - STOP SLAVE

STOP SLAVE [thread_name [, thread_name] ... ]

thread_name = IO_THREAD | SQL_THREAD

Arrête l'esclave. Tout comme START SLAVE, cette commande peut être utilisée avec les options IO_THREAD et SQL_THREAD pour identifier le thread par son nom.

Cette commande s'appelait SLAVE STOP avant MySQL 4.0.5. Actuellement, SLAVE STOP est toujours disponible pour assurer la compatibilité ascendante, mais c'est une commande abandonnée.

13-7 - Syntaxe SQL pour les commandes préparées

Le support des commandes préparées côté serveur a été ajouté en MySQL 4.1. Ce support tire profit du protocole client/serveur plus efficace, en supposant que vous utilisez la bonne interface client. Les interfaces correctes sont l'API C MySQL (pour les programmes en C), et MySQL Connector/J (pour les programmes Java). Par exemple, l'API C fournit un jeu de fonctions qui prépare les commandes. Voir Section 24.2.4, « Fonctions C de commandes préparées ». Les autres interfaces de langages peuvent fournir un support pour les commandes préparées, en utilisant le protocole binaire grâce à l'interface du client C. L'extension PHP 5 mysqli est un exemple.

Depuis MySQL 4.1.3, une autre interface pour les commandes préparées est disponible : la syntaxe SQL pour les commandes préparées. Cette interface n'est pas aussi efficace que le protocole binaire, mais elle n'impose aucune programmation, car elle est disponible directement au niveau SQL.

- Vous pouvez l'utiliser lorsqu'aucune interface de programmation n'est disponible.

- Vous pouvez l'utiliser depuis n'importe quel programme qui vous permet d'envoyer des commandes au serveur, comme le client mysql.

- Vous pouvez l'utiliser même si le client utilise une vieille version de la bibliothèque d'interface. La seule contrainte est que vous devez pouvoir vous connecter à un serveur suffisamment récent pour supporter cette syntaxe.

La syntaxe SQL pour les commandes préparées sert dans les situations suivantes.

- Vous voulez tester les commandes préparées avec votre application sans faire de codage. Ou bien, votre application a des problèmes avec les commandes préparées, et vous voulez déterminer ce problème interactivement.

- Vous voulez créer un cas de test qui décrit les problèmes que vous avez avec les commandes préparées, pour pouvoir envoyer un rapport de bogue.

- Vous devez utiliser les commandes préparées, mais vous n'avez pas accès à une interface qui les supporte.

La syntaxe SQL pour les commandes préparées est basée sur trois commandes SQL :

PREPARE stmt_name FROM preparable_stmt;

EXECUTE stmt_name [USING @var_name [, @var_name] ...];

DEALLOCATE PREPARE stmt_name;

La commande PREPARE prépare la commande, lui assigne le nom stmt_name, qui sera utilisé ultérieurement. preparable_stmt est soit une chaîne littérale, soit une variable utilisateur, qui contient le texte de la commande. Le texte doit représenter une seule commande SQL, et non pas plusieurs. Dans la commande, le caractère '?' sert de variable de requête : ils indiquent que les valeurs seront fournies à l'application ultérieurement. Le caractère '?' ne doit pas être placé entre guillemets, même si vous voulez leur donner des valeurs de chaînes de caractères.

Si une commande préparée existe déjà avec le même nom, elle sera détruite implicitement avant la préparation de la nouvelle commande. Cela signifie que si la nouvelle commande contient une erreur et ne peut pas être préparée, une erreur sera retournée, et la commande aura simplement été détruite.

Le contexte d'une commande préparée est celui de la session client dans laquelle elle est créée. Les autres clients ne peuvent y accéder.

Après avoir préparé une commande, vous l'exécutez avec la commande EXECUTE, qui fait référence au nom de la commande préparée. Si la commande préparée contient des variables, vous devez fournir leur valeur avec la clause USING qui liste les variables contenant les valeurs des paramètres. Les valeurs des paramètres doivent être aussi nombreuses que les paramètres de la commande.

Vous pouvez exécuter une commande préparée plusieurs fois, en lui passant différentes valeurs, ou différentes variables.

Pour détruire une commande préparée, utilisez la commande DEALLOCATE PREPARE. Tenter d'exécuter la commande préparée après destruction conduit à une erreur.

Si vous quittez la session client sans libérer les commandes préparées, le serveur le fera pour vous.

Les exemples suivants montrent deux méthodes équivalentes pour préparer les commandes qui calculent l'hypoténuse d'un triangle à partir de la taille de deux de ses côtés.

Le premier exemple montre comment créer la commande préparée avec une chaîne littérale :

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

Le second exemple est similaire, mais fournit le texte de la commande dans une variable utilisateur :

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|         10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;

La syntaxe SQL des commandes préparées ne peut pas être utilisée par imbrication. C'est-à-dire, une commande passée à PREPARE ne peut pas exécuter les commandes PREPARE, EXECUTE ou DEALLOCATE PREPARE.

De plus, la syntaxe SQL pour les commandes préparées est distincte de l'API des commandes préparées. Par exemple, vous pouvez utiliser la fonction C mysql_stmt_prepare() pour préparer une commande PREPARE, EXECUTE, or DEALLOCATE PREPARE.

14 - Moteurs de tables MySQL et types de table

MySQL supporte plusieurs moteurs de stockage, qui gèrent différents types de tables. Les moteurs de tables MySQL peuvent être transactionnels ou non transactionnels.

- Le moteur de tables original était ISAM, qui gérait des tables non transactionnelles. Ce moteur a été remplacé par le moteur MyISAM et ne doit plus être utilisé. Il est abandonné et ne doit plus être utilisé depuis MySQL 4.1 et il sera supprimé en MySQL 5.0.

- En MySQL 3.23.0, les moteurs MyISAM et HEAP ont été introduits. MyISAM est une version améliorée de ISAM. Le moteur HEAP propose des tables stockées en mémoire. Le moteur MERGE a été ajouté en MySQL 3.23.25. Il permet le regroupement de tables MyISAM identiques sous la forme d'une seule table. Les trois moteurs sont non transactionnels et sont tous inclus par défaut. Notez que le moteur HEAP est maintenant appelé MEMORY.

- Les moteurs InnoDB et BDB gèrent des tables transactionnelles et ont été introduits en MySQL 3.23. Les deux font partie de la distribution source de MySQL 3.23.34a. BDB est inclus dans les distributions MySQL-Max pour les systèmes d'exploitation qui le supportent. InnoDB est aussi inclus dans les distributions binaires MySQL-Max de MySQL 3.23. Depuis MySQL 4.0, InnoDB est inclus par défaut dans toutes les distributions binaires. Dans les distributions sources, vous pouvez l'activer ou pas en configurant la compilation.

- NDBCluster est le moteur de stockage du cluster MySQL qui implémente des tables réparties sur plusieurs serveurs. Il est disponible avec les distributions sources depuis MySQL 4.1.2.

Ce chapitre décrit les différents moteurs de tables MySQL, hormis InnoDB, qui est présenté dans le Chapitre 15, Le moteur de tables InnoDB et NDBCluster qui est présenté dans le Chapitre 16, Introduction à MySQL Cluster.

Lorsque vous créez une table, vous pouvez indiquer à MySQL le type de table avec la clause ENGINE ou TYPE lors de la commande de CREATE TABLE :

CREATE TABLE t (i INT) ENGINE = INNODB;
CREATE TABLE t (i INT) TYPE = MEMORY;

ENGINE est le terme recommandé mais il ne peut pas être utilisé avant MySQL 4.0.18. TYPE est disponible depuis MySQL 3.23.0, la première version de MySQL qui dispose de plusieurs moteurs de tables.

Si vous omettez l'option ENGINE ou TYPE, le type de table par défaut sera utilisé. C'est généralement MyISAM. Cela peut être changé en modifiant la variable système table_type.

Pour convertir une table d'un type à l'autre, utilisez la commande ALTER TABLE, pour indiquer le nouveau type :

ALTER TABLE t ENGINE = MYISAM;
ALTER TABLE t TYPE = BDB;

Voir Section 13.2.5, « Syntaxe de CREATE TABLE » et Section 13.2.2, « Syntaxe de ALTER TABLE ».

Si vous essayez d'utiliser un moteur de stockage qui n'est pas compilé ou qui est désactivé, MySQL créera une table de type MyISAM. Ce comportement est pratique pour copier des tables entre serveurs MySQL qui supportent différents moteurs. Par exemple, dans une architecture de réplication, votre serveur maître supporte des tables transactionnelles mais l'esclave n'utilise que des tables non transactionnelles, pour améliorer la vitesse.

Cette substitution automatique par une table de type MyISAM pour un type de moteur indisponible peut être gênant pour un nouvel utilisateur MySQL. En MySQL 4.1 et plus récent, une alerte est générée lorsque le type de la table est modifié.

MySQL crée toujours un fichier .frm pour stocker le type de la table et les informations de définition. Les données et les index de la table peuvent être stockés ailleurs, en fonction du type des tables. Le serveur crée le fichier .frm par dessus le moteur de stockage. Les moteurs peuvent créer des fichiers supplémentaires, en fonction de leurs besoins.

Les avantages des tables transactionnelles (TST) sont :

- elles sont plus sûres. Même si MySQL crashe ou que vous avez un problème matériel, vous pouvez récupérer vos données, soit par un recouvrement automatique, soit à partir d'une sauvegarde combinée avec le log des transactions ;

- vous pouvez combiner plusieurs commandes et les accepter toutes d'un seul coup avec la commande COMMIT ;

- vous pouvez utiliser ROLLBACK pour ignorer vos modifications (si vous n'êtes pas en mode autocommit) ;

- si une mise à jour échoue, tous vos changements seront annulés (avec les tables NTST tous les changements opérés sont permanents) ;

- elles gèrent mieux les accès concurrents si les tables reçoivent simultanément plusieurs lectures.

Notez que pour utiliser le moteur InnoDB en MySQL 3.23, vous devez configurer au moins l'option de démarrage innodb_data_file_path. En 4.0 et plus récent, InnoDB utilise les valeurs par défaut de la configuration, si vous ne les spécifiez pas. Voir Section 15.4, « Configuration InnoDB ».

Avantages des tables non transactionnelles (NTST) :

- elles sont plus rapides ;

- elles utilisent moins d'espace disque ;

- elles utilisent moins de mémoire pour exécuter les mises à jour.

Vous pouvez combiner les tables TST et NTST dans la même requête pour obtenir le meilleur des deux types. Cependant, dans une transaction sans autovalidation, les modifications d'une table non transactionnelles seront toujours immédiatement enregistrées et ne pourront pas être annulées.

14-1 - Le moteur de tables MyISAM

MyISAM est le type par défaut des tables en MySQL version 3.23. Il est basé sur ISAM et ajoute de nombreuses extensions pratiques.

Chaque table MyISAM est stockée en trois fichiers. Les fichiers portent le nom de la table et ont une extension qui spécifie le type de fichier. Le fichier .frm stocke la définition de la table. L'index est stocké dans un fichier avec l'extension .MYI (MYIndex) et les données sont stockées dans un fichier avec l'extension .MYD (MYData).

Pour spécifier explicitement que vous souhaitez une table MyISAM, indiquez-le avec l'option ENGINE ou TYPE lors de la création de la table :

CREATE TABLE t (i INT) ENGINE = MYISAM;
CREATE TABLE t (i INT) TYPE = MYISAM;

Normalement, les options ENGINE et TYPE sont inutiles : MyISAM est le type par défaut des tables en MySQL, à moins d'avoir été spécifié autrement.

Vous pouvez vérifier ou réparer une table MyISAM avec l'utilitaire myisamchk. Voir Section 5.7.3.7, « Utiliser myisamchk pour restaurer une table ». Vous pouvez aussi compresser les tables MyISAM avec l'utilitaire myisampack pour réduire leur taille sur le disque. Voir Section 8.2, « myisampack, le générateur de tables MySQL compressées en lecture seule ».

Voici les nouveautés des tables MyISAM :

- toutes les clés numériques sont stockées avec l'octet de poids fort en premier, pour améliorer la compression. Cela rend les données indépendantes du système d'exploitation et de la machine. La seule règle pour assurer la portabilité binaire des fichiers est que la machine doit utiliser des entiers signés pour le complément à 2 (c'est le cas de toutes les machines ces 20 dernières années) et un format de nombre à virgule flottante compatible IEEE (c'est aussi le format dominant). Le seul point où la portabilité n'est pas assurée concerne les machines portables, qui ont des processeurs originaux.

Il n'y a pas de coût spécifique à stocker les données dans ce format. Les octets dans la table sont généralement non alignés et cela ne prend pas longtemps d'aligner des octets. De plus, le code qui lit les valeurs des colonnes n'est pas critique par rapport au reste du code ;

- le support des grands fichiers (63 bits) sur les systèmes de fichiers et les systèmes d'exploitation qui supportent les grands fichiers ;

- les lignes de taille dynamique sont bien moins fragmentées lors de l'utilisation d'insertion et d'effacement. Cela se fait en combinant automatiquement les blocs adjacents libres et en étendant la taille des blocs avec le suivant s'il est vide ;

- le nombre maximal d'index par table est de 64 (32 avant MySQL 4.1.2). Cela peut être changé en recompilant. Le nombre de colonnes maximal par index est 16 ;

- la taille maximale d'une clé est de 1000 octets (500 avant MySQL 4.1.2). Cela peut être changé en recompilant MySQL. Dans le cas où la clé est plus longue que 250 octets, une taille de bloc de clé plus large est utilisée, en remplacement des 1024 octets par défaut ;

- les colonnes BLOB et TEXT peuvent être indexées ;

- les valeurs NULL sont autorisées dans une colonne indexée. Elles prennent 0 à 1 octets par clé ;

- les valeurs numériques sont stockées avec l'octet de poids fort en premier, pour permettre une meilleure compression ;

- les fichiers d'index sont généralement plus petits en MyISAM qu'en ISAM. Cela signifie que MyISAM va utiliser moins de ressources systèmes que ISAM, mais il prendra plus de processeur lors de l'insertion de données dans un index compressé ;

- lorsque les lignes sont insérées dans un ordre trié (comme lorsque vous utilisez une colonne de type AUTO_INCREMENT), l'arbre des clés sera scindé, pour que nœud principal ne contienne qu'une clé. Cela va améliorer l'utilisation d'espace dans l'arbre des clés ;

- la gestion interne des colonnes AUTO_INCREMENT. MyISAM va automatiquement modifier cette valeur lors d'une insertion ou d'une modification. La valeur courante d'AUTO_INCREMENT peut être modifiée avec myisamchk. Cela va rendre les colonnes AUTO_INCREMENT plus rapides (au moins 10 %) et les anciens nombres ne seront pas réutilisés, comme avec les vieilles tables ISAM. Notez que lorsqu'une clé AUTO_INCREMENT est définie à la fin d'une clé multiple, l'ancien comportement est toujours présent ;

- vous pouvez insérer de nouvelles lignes dans une table qui n'a aucun bloc vide dans le fichier de données, en même temps que d'autres threads lisent le fichier de données (insertion simultanée). Un bloc vide peut provenir d'une modification de ligne à format dynamique (les données sont maintenant plus petites). Lorsque tous les blocs vides sont à nouveau utilisés, les insertions suivantes peuvent être simultanées ;

- vous pouvez placer les fichiers de données et d'index dans différents dossiers pour obtenir plus de vitesse avec les options de table DATA DIRECTORY et INDEX DIRECTORY, dans la commande CREATE TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE » ;

- depuis MySQL version 4.1, chaque colonne de caractères peut avoir un jeu de caractères distinct ;

- il y a un indicateur dans le fichier MyISAM qui indique si la table a été correctement fermée. Si mysqld est lancé avec l'option --myisam-recover, les tables MyISAM vont automatiquement être vérifiées et réparées, si elles n'ont pas été correctement refermées ;

- myisamchk va marquer les tables comme vérifiées s'il est exécuté avec l'option --update-state. myisamchk --fast va uniquement vérifier les tables qui n'ont pas cette marque ;

- myisamchk -a stocke les statistiques pour les parties de clés (et non plus pour les clés complètes, comme avec ISAM) ;

- myisampack peut compresser des colonnes BLOB et VARCHAR. pack_isam ne le peut pas ;

MyISAM supporte aussi les fonctionnalités suivantes, dont MySQL pourra profiter sous peu :

- support du vrai type VARCHAR; une colonne VARCHAR commence avec une taille, stockée sur 2 octets ;

- les tables ayant des colonnes VARCHAR peuvent avoir un format de lignes fixe ou dynamique ;

- VARCHAR et CHAR peuvent prendre jusqu'à 64 ko ;

- un index de hashage peut être utilisé avec UNIQUE. Cela vous permettra d'avoir un index UNIQUE sur toute combinaison de colonnes de la table. Vous ne pourrez pas utiliser un index UNIQUE pour une recherche.

14-1-1 - Options de démarrage MyISAM

Les options suivantes de mysqld permettent de modifier le comportement des tables MyISAM :

- --myisam-recover=mode

Active le mode de restauration automatique des tables MyISAM corrompues ;

- --delay-key-write=ALL

N'écrit pas les buffers de clés entre deux écritures dans une table MyISAM.

Note : si vous faites cela, vous ne devez pas utiliser les tables MyISAM avec d'autres programmes (comme depuis un autre serveur MySQL ou avec myisamchk) lorsque la table est utilisée. Sinon, vous allez obtenir une corruption d'index.

Utiliser --external-locking n'aidera pas les tables qui utilisent --delay-key-write.

Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Les variables systèmes suivantes affectent le comportement des tables MyISAM :

- bulk_insert_buffer_size

La taille du cache d'index lors des insertions de masse. Note : c'est une limite par thread !

- myisam_max_extra_sort_file_size

Utilisée pour aider MySQL à décider quand utiliser le cache de clé lent mais sûr. Note : ce paramètre était donné en mégaoctets avant MySQL 4.0.3 et en octets depuis 4.0.3 ;

- myisam_max_sort_file_size

N'utilise pas la méthode de tri rapide pour créer un index, dans le cas où un fichier temporaire dépasserait cette taille. Note : ce paramètre était donné en mégaoctets avant MySQL 4.0.3 et en octets depuis 4.0.3 ;

- myisam_sort_buffer_size

La taille du buffer lors de la restauration de table.

Voir Section 5.2.3, « Variables serveur système ».

La restauration automatique est activée si vous lancez mysqld avec l'option --myisam-recover. Dans ce cas, lorsque le serveur ouvre la table MyISAM, il vérifie si la table a été marquée comme crashée ou si le compteur de tables ouvertes n'est pas zéro ou si le serveur utilise --skip-external-locking. Si une des conditions précédente est vraie, il arrive ceci :

- la table est analysée pour rechercher des erreurs ;

- si le serveur trouve une erreur, il essaie de faire une réparation rapide (avec le tri, sans recréer de données) ;

- si la réparation échoue à cause d'une erreur dans le fichier de données (par exemple une erreur de clé), le serveur essaie à nouveau, en recréant le fichier de données ;

- si la réparation échoue encore, le serveur essaie encore avec une ancienne méthode de réparation (écrire les lignes les unes après les autres, sans tri). Cette méthode devrait être capable de réparer tout les types d'erreurs et elle occupe peu de place sur le disque.

Si la restauration n'est toujours pas capable de retrouver toutes les lignes et que vous n'avez pas spécifié l'option FORCE dans la valeur de l'option --myisam-recover, la réparation automatique s'annule, avec le message d'erreur suivant :

Error: Couldn't repair table: test.g00pages

Si vous spécifiez la valeur FORCE, une alerte comme celle-ci sera écrite dans les logs :

Warning: Found 344 of 354 rows when repairing ./test/g00pages

Notez que si la valeur de restauration automatique inclut BACKUP, le processus de restauration créera des fichiers avec des noms de la forme tbl_name-datetime.BAK. Vous devriez avoir une tâche régulière avec cron pour supprimer automatiquement ces fichiers dans les bases de données pour nettoyer le volume.

14-1-2 - Espace nécessaire pour stocker les index

MySQL supporte plusieurs types d'index, mais le type normal est ISAM ou MyISAM. Ils utilisent un index B-tree et vous pouvez avoir une approximation de la taille du fichier d'index en faisant la somme de (longueur_clé+4)/0.67 pour toutes les clés. Cela est le pire des cas où les clés sont insérées dans l'ordre et qu'aucune n'est compressée.

Les index de chaînes de caractères sont compressés par rapport aux espaces. Si la première partie de l'index est une chaîne, son préfixe sera aussi compressé. La compression des espaces rend le fichier d'index plus petit que ce que nous avions calculé précédemment si la colonne chaîne possède beaucoup d'espaces invisibles en début et fin de chaîne ou est une colonne VARCHAR qui n'est pas toujours pleinement utilisée. La compression des préfixes est utilisée sur les clés qui commencent par une chaîne de caractères, s'il y a plusieurs chaînes avec des préfixes identiques.

Dans les tables MyISAM, vous pouvez aussi compresser les nombres en spécifiant PACK_KEYS=1 lors de la création de la table. Cela vous aidera lorsque vous aurez plusieurs clés de types entier qui auront un préfixe identique et que les nombres seront classés par ordre décroissant des grands octets.

14-1-3 - Formats de table MyISAM

MyISAM supporte 3 différents types de tables. Deux des trois sont choisis automatiquement selon le type de colonne que vous utilisez. Le troisième, tables compressées, ne peut être crée qu'avec l'outil myisampack.

Quand vous créez une table avec CREATE ou en modifiez la structure avec ALTER vous pouvez, pour les tables n'ayant pas de champ BLOB, forcer le type de table en DYNAMIC ou FIXED avec l'option ROW_FORMAT=# des tables. Bientôt, vous pourrez compresser/décompresser les tables en spécifiant ROW_FORMAT=compressed | default à ALTER TABLE. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

14-1-3-1 - Caractéristiques des tables statiques (taille fixée)

Ceci est le format par défaut. Il est utilisé lorsque la table ne contient pas de colonnes de type VARCHAR, BLOB, ou TEXT.

Ce format est le plus simple et le plus sûr. C'est aussi le format sur disque le plus rapide. La vitesse vient de la facilité avec laquelle les données peuvent être trouvées sur le disque. La recherche de quelque chose avec un index et un format statique est très simple. Multipliez juste le nombre de lignes par la longueur des lignes.

De même, lors du scannage d'une table, il est très facile de lire un nombre constant d'enregistrements avec chaque lecture du disque.

La sécurité est mise en évidence si votre ordinateur crashe lors de l'écriture dans un fichier de taille fixée MyISAM, dans ce cas, myisamchk peut facilement trouver où commence et finit chaque ligne. Il peut donc retrouver tous les enregistrements à part celui dont l'écriture a été interrompue. Notez qu'avec MySQL tous les index peuvent toujours être reconstruits.

Les tables statiques ont les caractéristiques suivantes :

- leurs colonnes CHAR, NUMERIC et DECIMAL sont complétées par des espaces jusqu'à atteindre la longueur totale de la colonne ;

- très rapides ;

- faciles à mettre en cache ;

- faciles à reconstruire après un crash, car les enregistrements sont localisés dans des positions fixées ;

- n'ont pas à être réorganisés (avec myisamchk) sauf si un grand nombre de lignes est effacé et que vous voulez retourner l'espace libéré au système d'exploitation ;

- ils requièrent usuellement plus d'espace disque que les tables dynamiques.

14-1-3-2 - Caractéristiques des tables à format de ligne dynamique

Ce format est utilisé avec les tables qui contiennent des colonnes de type VARCHAR, BLOB ou TEXT, ou si la table a été créée avec l'option ROW_FORMAT=DYNAMIC.

Ce format est un peu plus complexe car chaque ligne doit avoir un entête pour indiquer sa longueur. Une ligne peut aussi être répartie sur plusieurs blocs, lorsqu'elle est agrandie lors d'une modification.

Vous pouvez utiliser la commande SQL OPTIMIZE table ou myisamchk pour défragmenter une table. Si vous avez des données statiques que vous modifiez souvent dans la même table, avec des colonnes VARCHAR ou BLOB, il peut être judicieux de placer des colonnes dans une autre table, pour éviter la fragmentation :

- toutes les colonnes de type chaîne sont dynamiques (hormis celles qui sont de taille inférieure à 4) ;

- chaque ligne est précédée d'un octet qui indique quelles sont les lignes vides ('', bit à 1) et celles qui le ne sont pas (bit à 0). Une colonne vide n'est pas la même chose qu'une colonne qui contient NULL. Si une colonne a une taille de zéro après avoir supprimé les espaces finaux, ou un nombre a une valeur de zéro, il est marqué dans cet octet et la colonne sera ignorée sur le disque. Les chaînes non vides sont sauvées avec un octet de plus pour y stocker la taille ;

- ce format prend généralement moins de place que des tables à format fixe ;

- chaque ligne consomme autant d'espace que nécessaire. Si une ligne devient trop grande, elle sera coupée en blocs et écrite dans le fichier de données. Cela engendre la fragmentation du fichier de données. Par exemple, si vous modifiez une ligne avec des informations qui excèdent la capacité courante de la ligne, la ligne sera fragmentée. Dans ce cas, vous pouvez avoir à exécuter la commande myisamchk -r de temps en temps pour améliorer les performances. Utilisez myisamchk -ei tbl_name pour obtenir des statistiques ;

- ce format de table n'est pas toujours facile à reconstituer après un crash car une ligne peut être fragmentée en de nombreux blocs et un fragment peut manquer ;

- la taille d'une ligne de format variable se calcule avec :

3
+ (nombre de colonnes + 7) / 8
+ (nombre de colonnes de tailles chars)
+ taille compactée des colonnes numériques
+ taille des chaînes
+ (nombre de colonne de valeur NULL + 7) / 8

Il y a un aussi un supplément de 6 octets pour chaque lien. Une ligne de format dynamique utilise un lien à chaque fois qu'une modification cause un agrandissement de la ligne. Chaque nouveau bloc lié fait au moins 20 octets, pour que le prochain agrandissement utilise aussi ce bloc. Si ce n'est pas le cas, un nouveau bloc sera lié, avec un autre coût de 6 octets. Vous pouvez vérifier le nombre de liens dans une table avec la commande myisamchk -ed. Tous les liens sont supprimés avec la commande myisamchk -r.

14-1-3-3 - Caractéristiques des tables compressées

C'est un type en lecture seule qui est généré avec l'outil optionnel myisampack.

Toutes les distributions MySQL depuis la version 3.23.19 incluent myisampack par défaut (c'est le moment où MySQL a été mis sous GPL). Pour les versions plus anciennes myisampack n'était inclus qu'avec les licences ou contrats mais le serveur pouvait toujours lire les tables compressées myisampack. Les tables compressées peuvent être décompressées avec myisamchk. Pour le moteur de stockage ISAM, les tables compressées peuvent être compressées avec pack_isam et décompressées avec isamchk.

Les tables compressées ont les avantages suivants :

- elles prennent très peu d'espace disque. Cela réduit l'espace requis, ce qui est fort utile lors de l'utilisation de petits disques (comme les CD-ROM) ;

- chaque ligne est compressée séparément (optimisation des accès). L'entête d'un enregistrement est fixé (1-3 octets) selon le plus grand enregistrement dans la table. Chaque colonne est compressée différemment. Quelques-un des types de compressions sont :

- compression des espaces en suffixe ;

- compression des espaces en préfixe ;

- les nombres avec la valeur 0 sont stockés en utilisant 1 octet ;

- si les valeurs dans une colonne de type entier ont un petit intervalle, la colonne est stockée en utilisant le type le plus petit possible. Par exemple, une colonne BIGINT (8 octets) peut être stockée en tant que colonne TINYINT (1 octet) si toutes les valeurs sont entre 0 et 255 ;

- si une colonne n'a qu'un petit éventail de valeurs, son type est changé en ENUM ;

- une colonne peut utiliser une combinaison des compressions précédentes.

- elles peuvent gérer les enregistrements de taille fixe ou variable.

14-1-4 - Problèmes avec les tables MyISAM

Le format de fichier que MySQL utilise pour stocker les données a été testé à l'extrême, mais il y a toujours des circonstances qui peuvent corrompre les tables d'une base de données.

14-1-4-1 - Tables MyISAM corrompues

Même si le format des tables MyISAM est relativement sûr (tous les changements sont écrits avant que la requête SQL ne retourne quoi que ce soit), vous pouvez quand même vous trouver face à des tables corrompues si l'une des choses suivantes arrive :

- le processus mysqld est tué au milieu d'une écriture ;

- arrêt inattendu de la machine (par exemple, coupure de courant) ;

- un problème matériel ;

- vous utilisez un programme externe (comme myisamchk) sur une table active ;

- un bogue logiciel dans le code de MySQL ou de MyISAM.

Les symptômes typiques d'une table corrompue sont :

- vous obtenez l'erreur

Incorrect key file for table: '...'. Try to repair it

pendant la sélection de données à partir de cette table ;

- les requêtes ne trouvent pas de lignes dans la table ou retournent des données incomplètes.

Vous pouvez réparer une table corrompue avec REPAIR TABLE. Vous pouvez aussi réparer une table, lorsque mysqld ne fonctionne pas, avec la commande myisamchk. Lorsque mysqld est arrêté, vous pouvez vérifier une table avec la commande myisamchk. Voyez la section Section 13.5.2.3, « Syntaxe de CHECK TABLE », Section 13.5.2.6, « Syntaxe de REPAIR TABLE » et Section 5.7.3.1, « Syntaxe de l'utilitaire myisamchk ».

Si vos tables sont souvent corrompues, vous devez essayez de trouver d'où vient le problème ! Dans ce cas, la chose la plus importante à savoir est, si la table est corrompue, si le serveur mysqld s'est interrompu (cela peut être facilement vérifié en regardant s'il y a une entrée récente restarted mysqld dans le fichier d'erreurs de mysqld). Si ce n'est pas le cas, vous devez essayer d'effectuer une série de tests. Voyez Section A.4.2, « Que faire si MySQL plante constamment ? » et Section D.1.6, « Faire une batterie de tests lorsque vous faites face à un problème de table corrompue ».

14-1-4-2 - Des clients utilisent la table, ou bien elle n'a pas été fermée correctement

Chaque fichier MyISAM .MYI possède un compteur dans l'entête qui peut être utilisé pour savoir si une table a été fermée proprement.

Si vous obtenez l'avertissement suivant de la part de CHECK TABLE ou myisamchk :

# clients is using or hasn't closed the table properly

cela signifie que le compteur n'est plus synchrone. Cela ne signifie pas que la table est corrompue, mais que vous devez au moins effectuer une vérification sur la table pour vous assurer de son bon fonctionnement.

Le compteur fonctionne de la façon suivante :

- la première fois qu'une table est mise à jour dans MySQL, un compteur dans l'entête du fichier est incrémenté ;

- le compteur ne change pas pour les mises à jour suivantes ;

- lors de la fermeture de la dernière instance d'une table (à cause d'un FLUSH ou qu'il n'y a plus de place dans le cache de la table) le compteur est décrémenté si la table n'a pas été mise à jour ;

- lorsque vous réparez la table ou vérifiez qu'elle est en bon état, le compteur est remis à zéro ;

- pour éviter les problèmes d'interactions avec d'autres processus qui peuvent vérifier la table, le compteur n'est pas décrémenté à la fermeture si sa valeur était zéro.

En d'autres termes, les seuls moyens d'obtenir ce genre d'erreur sont :

- les tables MyISAM sont copiées sans LOCK et FLUSH TABLES ;

- MySQL a planté entre une mise à jour et la fermeture finale (notez que la table peut encore être bonne, vu que MySQL écrit toujours pour tout entre deux requêtes) ;

- quelqu'un a exécuté myisamchk --recover ou myisamchk --update-state sur une table qui était utilisée par mysqld ;

- plusieurs serveurs mysqld utilisent la table et l'un d'eux a exécuté dessus un REPAIR ou un CHECK pendant qu'elle était utilisée par un autre serveur. Dans ce cas-là, l'utilisation de CHECK n'est pas très grave (même si vous obtiendrez des avertissements sur les autres serveurs), mais REPAIR doit être évitée vu qu'elle remplace vraiment le fichier de données par un nouveau, ce qui n'est pas signalé aux autres serveurs.

En général, c'est une mauvaise idée que de partager un dossier de données avec plusieurs serveurs. Voyez la section Section 5.10, « Faire fonctionner plusieurs serveurs MySQL sur la même machine » pour plus de détails.

14-2 - Tables assemblées MERGE

Les tables MERGE ont été ajoutées en MySQL version 3.23.25. Ce type de table est aussi connu sous le nom de MRG_MyISAM. Le code est raisonnablement stable.

Une table MERGE est un groupe de tables MyISAM identiques qui est utilisé comme une seule. « Identique » signifie que toutes les tables ont la même structure de colonnes et d'index. Vous ne pouvez pas regrouper des tables qui ont des index dans un ordre différent. Toutefois, une ou plusieurs tables peuvent être compressées avec myisampack. Voir Section 8.2, « myisampack, le générateur de tables MySQL compressées en lecture seule ».

Lorsque vous créez une table MERGE, MySQL crée deux fichiers sur le disque. Les fichiers ont pour nom celui de la table et ont une extension qui indique le type de fichiers. Le fichier .frm stocke la définition de la table et le fichier .MRG contient les noms des tables qui doivent être utilisées. Originalement, toutes les tables utilisées dans la même table MERGE devaient être dans la même base que la table MERGE. Cette restriction a été levée en MySQL 4.1.1.

Pour le moment, vous avez simplement besoin des droits de SELECT, UPDATE et DELETE sur les tables que vous avez rassemblées dans la table MERGE.

L'exemple suivant vous montre comme utiliser les tables MERGE :

mysql> CREATE TABLE t1 (
->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->    message CHAR(20));
mysql> CREATE TABLE t2 (
->    a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->    message CHAR(20));
mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql> CREATE TABLE total (
->    a INT NOT NULL AUTO_INCREMENT,
->    message CHAR(20), INDEX(a))
->    TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;

Notez que la colonne a est indexée dans la table MERGE, mais elle n'est pas déclarée comme PRIMARY KEY comme elle peut l'être dans les tables MyISAM sous-jacentes. C'est nécessaire, car une table MERGE ne peut pas assurer l'unicité de valeurs à travers les tables.

Après la création de la table MERGE, vous pouvez faire des commandes comme :

mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

Notez que vous pouvez aussi manipuler le fichier .MRG directement, à l'extérieur du serveur MySQL :

shell> cd /mysql-data-directory/current-database
shell> ls -1 t1 t2 > total.MRG
shell> mysqladmin flush-tables

Pour redéfinir une table MERGE avec un autre groupe de tables MyISAM, vous pouvez faire ceci :

- effacez la table avec la commande DROP, puis recréez-la ;

- utilisez ALTER TABLE tbl_name UNION=(...) pour redéfinir les tables regroupées ;

- modifiez le fichier .MRG et utilisez la commande FLUSH TABLE sur la table MERGE et toutes les tables sous-jacentes, pour forcer le gestionnaire à relire la définition.

Les tables MERGE peuvent vous aider dans les situations suivantes.

- Gérer facilement un jeu de tables d'historique. Par exemple, vous pourriez placer les données de chaque mois dans un fichier séparé, en compresser certains avec myisampack puis créer une table MERGE pour les utiliser.

- Vous donner plus de vitesse. Vous pouvez répartir les grandes tables en lecture seule dans différentes parties du disque. Une table MERGE bâtie de cette façon peut être plus rapide qu'une grosse table (vous pouvez aussi bien sûr utiliser un système RAID pour arriver aux mêmes avantages).

- Effectuer des recherches plus efficaces. Si vous savez exactement ce que vous recherchez, vous pouvez faire des recherches dans une seule des tables individuelles pour les recherches et utiliser la table MERGE pour les autres opérations. Vous pouvez même avoir de nombreuses tables MERGE actives, qui partagent les mêmes fichiers.

- Des réparations plus efficaces. Il est plus facile de réparer les fichiers individuels qui sont rassemblés dans une table MERGE que de réparer une grande table.

- La fusion instantanée de plusieurs tables en une seule. Une table MERGE utilise les index des tables individuelles. Il n'y a pas besoin de gérer un seul index. Cela rend les tables MERGE très rapides à faire ou défaire. Notez que vous devez spécifier les définitions de clés lorsque vous créez la table MERGE !

- Si vous avez un jeu de tables que vous rassemblez dans une grande à la demande ou pour un traitement batch, vous devriez utiliser une table MERGE : c'est bien plus rapide et cela va vous faire économiser de l'espace disque.

- Contourner les limitations de taille du système d'exploitation.

- Vous pouvez créer un alias ou un synonyme pour une table en utilisant simplement MERGE sur une seule. Il n'y a pas de coûts particuliers en performance (hormis quelques appels de fonctions indirects et des memcpy() avant chaque lecture).

Les inconvénients des tables de type MERGE sont les suivants.

- Vous devez utiliser des tables MyISAM identiques pour faire une table MERGE.

- MERGE utilise plus de pointeurs de fichiers. Si vous utilisez une table MERGE qui couvre 10 tables et que 10 utilisateurs l'utilisent, vous consommez 10*10 + 10 pointeurs de fichiers (10 fichiers de données et 10 utilisateurs avec 10 fichiers d'index).

- Les lectures de clés sont plus lentes. Lorsque vous faites une lecture sur une clé, le gestionnaire MERGE doit faire une lecture dans tous les fichiers d'index des tables sous-jacentes, pour vérifier lequel est le plus proche de la valeur recherchée. Si vous faites une lecture du type « lit le suivant », le gestionnaire de tables assemblées doit rechercher dans tous les buffers de clés pour la trouver. Il doit lire le prochain bloc uniquement lorsqu'un buffer clé est complet. Cela rend l'accès aux clés MERGE bien plus lent que les recherches eq_ref mais pas aussi lent que les recherches de type ref. Voyez la section Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) » pour plus d'informations sur eq_ref et ref.

14-2-1 - Problèmes avec les tables MERGE

Voici ci-dessous une liste des problèmes connus avec les tables de type MERGE.

- Si vous utilisez la commande ALTER TABLE pour modifier une table de type MERGE en un autre type de table, la liste des tables sous-jacentes sera perdue. Au lieu de cela, les lignes des tables seront copiées dans la nouvelle table, puis on lui assignera le nouveau type.

- Avant MySQL 4.1.1, toutes les tables sous-jacentes et la table MERGE devaient être dans la même base de données.

- REPLACE ne fonctionne pas.

- Vous ne pouvez pas utiliser DROP TABLE, ALTER TABLE, DELETE FROM sans clause WHERE, REPAIR TABLE, TRUNCATE TABLE, OPTIMIZE TABLE, ou ANALYZE TABLE sur l'une des tables qui est dans une table MERGE « ouverte ». Si vous faites cela, la table MERGE va utiliser la table originale et vous obtiendrez des résultats étranges. Le plus simple est d'utiliser la commande FLUSH TABLES pour s'assurer qu'aucune table MERGE ne reste « ouverte. »

- Une table MERGE ne peut pas supporter de contrainte de type UNIQUE sur toute la table. Lorsque vous faites une insertion, les données vont dans la première ou la dernière table (suivant la méthode d'insertion INSERT_METHOD=xxx) et cette table MyISAM s'assure que les données sont uniques, mais rien n'est fait pour vérifier l'unicité auprès des autres tables MyISAM.

- Avant MySQL 3.23.49, DELETE FROM merge_table utilisé sans clause WHERE va uniquement détruire la table assemblée, mais ne va pas toucher les tables sous-jacentes. En fait, le fichier .MRG est effacé, mais pas les tables.

- RENAME TABLE utilisé sur une table de type MERGE peut corrompre la table. Cela sera corrigé en MySQL 4.1.x.

- La création d'une table de type MERGE ne vérifie pas si les tables sous-jacentes sont compatibles. Si vous utilisez une table MERGE de cette façon, vous devriez rencontrer des problèmes très étranges.

- L'ordre des index dans la table MERGE et ses tables sous-jacentes doit être le même. Si vous utilisez la commande ALTER TABLE pour ajouter un index de type UNIQUE à une table qui est utilisée dans une table assemblée MERGE, puis que vous utilisez ALTER TABLE pour ajouter un index normal dans la table MERGE, l'ordre des clés sera différent suivant les tables, si jamais il y avait une vieille clé non unique. Ceci est dû au fait que ALTER TABLE place les clés UNIQUE avant les clés normales, pour être capable de détecter les doublons le plus tôt possible.

- DROP TABLE sur une table qui est utilisée par une table MERGE ne fonctionne pas sous Windows, car le gestionnaire de MERGE garde les connexions vers les tables cachées sous la couche MySQL. Comme Windows ne vous permet pas d'effacer une table qui est ouverte, vous devez d'abord fermer toutes les tables MERGE (avec la commande FLUSH TABLES) ou effacer la table MERGE avant de pouvoir effacer la table désirée. Nous allons corriger lorsque nous introduirons les vues VIEWs.

14-3 - Le moteur de table MEMORY (HEAP)

Le moteur de stockage MEMORY crée des tables dont le contenu est stocké en mémoire. Avant MySQL 4.1, les tables MEMORY étaient appelées des tables HEAP. Depuis 4.1, HEAP est un synonyme de MEMORY et MEMORY est le terme recommandé.

Chaque table MEMORY est associée à un fichier sur le disque. Le fichier a le nom de la table et pour extension .frm pour indiquer la définition de la table.

Pour spécifier explicitement que vous voulez une table MEMORY, indiquez l'option ENGINE ou TYPE :

CREATE TABLE t (i INT) ENGINE = MEMORY;
CREATE TABLE t (i INT) TYPE = HEAP;

Les tables HEAP utilisent un index de hachage et sont stockées en mémoire. Elles sont très rapides, mais si MySQL plante, vous perdrez toutes vos données. La table continuera d'exister, car leur définition est stockée sur le serveur dans le fichier .frm, mais le contenu sera perdu au redémarrage du serveur. Les tables HEAP sont très pratiques pour être des tables temporaires.

Voici un exemple qui montre comment créer, utiliser et détruire une table MEMORY :

mysql> CREATE TABLE test TYPE=MEMORY
->     SELECT ip,SUM(downloads) AS down
->     FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;

Les tables MEMORY ont les caractéristiques suivantes.

- Les données pour les tables HEAP sont allouées par petits blocs. Les tables sont 100 % dynamiques (en insertion). Aucune zone de débordement ou d'espace de clé supplémentaire n'est nécessaire. Les lignes effacées sont placées dans une liste, prêtes à être réutilisées.

- Les tables MEMORY peuvent avoir jusqu'à 32 index par table, 16 colonnes par index et un maximum de 500 pour la taille des clés.

- Avant MySQL 4.1, le moteur MEMORY n'implémentait que des index hash. Depuis MySQL 4.1, Les index hash sont le type par défaut, mais vous pouvez spécifier explicitement que l'index MEMORY doit être de type HASH ou BTREE en ajoutant la clause USING :

CREATE TABLE lookup
(id INT, INDEX USING HASH (id))
ENGINE = MEMORY;
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;

Les caractéristiques générales des hash et B-tree sont décrites dans la section Section 7.4.5, « Comment MySQL utilise les index ».

- Vous pouvez avoir des clés non uniques dans une table MEMORY (c'est une fonctionnalité rare pour les index hash).

- Si vous avez un index hash sur une table HEAP avec un haut degré de duplication (de nombreuses valeurs d'index contiennent la même valeur), les modifications dans cette table peuvent affecter les valeurs des clés et toutes les suppressions seront plus lentes. Le facteur de ralentissement est proportionnel au degré de duplication (ou inversement proportionnel à la cardinalité). Depuis la version 4.1, MySQL supporte les index BTREE dans les tables HEAP, que vous pouvez utiliser pour éviter le problème.

- Les tables HEAP utilisent un format de ligne fixe.

- HEAP ne supporte pas les colonnes de type BLOB/TEXT.

- HEAP ne supporte pas les colonnes de type AUTO_INCREMENT.

- Avant MySQL 4.0.2, HEAP ne supportait les index sur les valeurs NULL.

- Les tables HEAP sont partagées entre tous les clients (comme les autres tables).

- La caractéristique des tables MEMORY qui fait que les tables sont stockées en mémoire est partagée avec les tables internes que le serveur crée à la volée lors du traitement des requêtes. Cependant, les tables internes ont aussi la capacité d'être converties en tables disques automatiquement, si elles deviennent trop grandes. La taille limite est déterminée par la valeur de tmp_table_size.

Les tables MEMORY ne peuvent pas être converties en tables disques. Pour vous assurer que vous ne faites rien de dangereux pour le serveur, vous pouvez utiliser la variable système max_heap_table_size pour imposer une taille maximale aux tables MEMORY. Pour des tables individuelles, vous pouvez utiliser l'option de table MAX_ROWS avec la commande CREATE TABLE.

- Vous avez besoin de suffisamment de mémoire pour accepter toutes les tables HEAP que vous allez utiliser simultanément.

- Pour libérer de la mémoire, vous devez exécuter la commande DELETE FROM heap_table, TRUNCATE heap_table ou DROP TABLE heap_table.

- Si vous voulez remplir les tables MEMORY au lancement du serveur MySQL, vous pouvez utiliser l'option --init-file. Par exemple, vous pouvez mettre des commandes telles que INSERT INTO ... SELECT et LOAD DATA INFILE pour lire des données dans une source de données persistantes. Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

- Si vous utilisez la réplication, les tables MEMORY du maître se vident à l'extinction. Cependant, un esclave peut ne pas s'apercevoir que ces tables ont été vidées et il risque de retourner des données invalides si vous l'utilisez. Depuis MySQL 4.0.18, lorsqu'une table MEMORY est utilisée sur le maître, il émet une commande DELETE FROM automatiquement, pour synchroniser l'esclave et le maître. Notez que même avec cette stratégie, l'esclave aura des données obsolètes entre le moment où le maître s'éteint et celui où il est redémarré. Mais si vous utilisez l'option --init-file pour remplir la table MEMORY au lancement du serveur, elle s'assurera que cet intervalle est bien nul.

- La mémoire nécessaire pour les tables HEAP est :

SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))

ALIGN() représente un facteur d'arrondi, car la taille de la ligne doit faire exactement un multiple de la taille du pointeur de char. sizeof(char*) vaut 4 sur les machines 32 bits et 8 sur une machine 64 bits.

14-4 - Tables BDB ou BerkeleyDB

Sleepycat Software fournit à MySQL le moteur de stockage transactionnel Berkeley DB. Ce moteur est généralement appelée BDB. Le support des tables BDB est inclus par la distribution des sources de MySQL à partir de la version 3.23.34 et est activé dans le binaire MySQL-Max.

En utilisant les tables DBD, vos tables ont plus de chances de survivre aux crashs et vous avez accès à COMMIT et ROLLBACK avec les transactions. La distribution des sources de MySQL fournit une distribution corrigée de BDB pour lui permettre de fonctionner d'une façon plus souple avec MySQL. Vous pouvez utiliser une version non corrigée de BDB avec MySQL.

Nous travaillons chez MySQL AB en coopération étroite avec Sleepycat pour garantir une bonne qualité d'interface MySQL/BDB. Même si Berkeley DB est très surveillée et fiable, l'interface MySQL est considérée de qualité Gamma. Nous y travaillons et l'optimisons.

Lorsqu'ils utilisent les tables BDB, nous aiderons nos utilisateurs à trouver les problèmes et à créer des batteries de tests reproductibles pour tout problème ayant trait aux tables BDB. De tels tests seront aussi envoyés à Sleepycat qui nous aidera à trouver et résoudre les problèmes. Vu qu'il s'agit d'une collaboration à deux niveaux, les problèmes concernant les tables BDB prendront un peu plus de temps à être résolus en comparaison avec les autres gestionnaires de tables. Toutefois, étant donné que le code de BerkeleyDB a lui-même été utilisé par plusieurs autres applications que MySQL, nous n'envisageons pas de rencontrer de gros problèmes avec.

Pour des informations générales sur Berkeley DB, visitez le site de Sleepycat Web, http://www.sleepycat.com/.

14-4-1 - Systèmes d'exploitation supportés par BDB

Actuellement, nous savons que le gestionnaire BDB fonctionne avec les systèmes d'exploitation suivants.

- Linux 2.x Intel

- Sun Solaris (SPARC et x86)

- FreeBSD 4.x/5.x (x86, sparc64)

- IBM AIX 4.3.x

- SCO OpenServer

- SCO UnixWare 7.1.x

Il ne fonctionne pas sur les systèmes d'exploitation suivants.

- Linux 2.x Alpha

- Linux 2.x AMD64

- Linux 2.x IA64

- Linux 2.x s390

- Max OS X

Note : la liste ci-dessus n'est pas complète ; nous la mettrons à jour au fur et à mesure que nous recevrons des informations à ce propos.

Si, après avoir compilé MySQL avec le support des tables BDB, vous obtenez l'erreur suivante dans le fichier de logs quand vous démarrez mysqld :

bdb: architecture lacks fast mutexes: applications cannot be threaded
Can't init databases

Cela signifie que les tables BDB ne sont pas supportées par votre architecture. Dans ce cas, vous devez recompiler MySQL sans le support des tables BDB.

14-4-2 - Installation de BDB

Si vous avez téléchargé une version binaire de MySQL qui inclut le support de BerkeleyDB, vous n'avez qu'à suivre les instructions classiques (MySQL-Max inclut le support BDB).

Si vous compilez MySQL depuis les sources, vous pouvez activer le support BDB en ajoutant au script configure l'option --with-berkeley-db. Téléchargez la distribution de MySQL 3.23.34 ou plus récent, allez dans la racine des sources et tapez :

shell> ./configure --with-berkeley-db [other-options]

Pour plus d'informations, voyez Section 2.3, « Installer MySQL sur d'autres systèmes type Linux », Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld » et Section 2.4, « Installation de MySQL avec une distribution source ».

14-4-3 - Options de démarrage BDB

Les options suivantes de mysqld peuvent être utilisées pour modifier le comportement des tables BDB.

- --bdb-home=répertoire

Répertoire de base des tables BDB. Cela doit être le même répertoire que vous avez utilisé pour --datadir.

- --bdb-lock-detect=#

Détection des verrouillages Berkeley (DEFAULT, OLDEST, RANDOM, ou YOUNGEST).

- --bdb-logdir=répertoire

Répertoire des fichiers de logs de Berkeley DB.

- --bdb-no-recover

Ne pas démarrer Berkeley DB en mode de restauration.

- --bdb-no-sync

Ne pas vider les tampons de manière synchrone.

- --bdb-shared-data

Démarrer Berkeley DB en mode multiprocessus (ne pas utiliser DB_PRIVATE lors de l'initialisation de Berkeley DB)

- --bdb-tmpdir=répertoire

Répertoire des fichiers temporaires de Berkeley DB.

- --skip-bdb

Désactive l'utilisation des tables BDB.

Voir Section 5.2.1, « Options de ligne de commande de mysqld ».

Les variables systèmes suivantes affectent le comportement des tables BDB.

- bdb_max_lock

Le nombre maximal de verrous actifs sur une table BDB.

Voir Section 5.2.3, « Variables serveur système ».

Si vous utilisez --skip-bdb, MySQL n'initialisera pas la bibliothèque Berkeley DB et cela économisera beaucoup de mémoire. Bien sûr, vous ne pouvez pas utiliser les tables BDB si vous utilisez cette option. Si vous essayez de créer une table BDB, MySQL créera une table MyISAM à la place.

Normalement, vous devez démarrer mysqld sans --bdb-no-recover si vous avez l'intention d'utiliser des tables BDB. Cela peut cependant vous poser des problèmes si vous essayez de démarrer mysqld alors que des fichiers de logs BDB sont corrompus. Voir Section 2.5.2.3, « Problèmes de démarrage du serveur MySQL ».

Vous pouvez spécifier le nombre maximal de verrous avec bdb_max_lock (10000 par défaut) que vous pouvez activer sur une table BDB. Vous devez l'augmenter si vous obtenez des erreurs du type :

bdb: Lock table is out of available locks
Got error 12 from ...

lorsque vous avez fait de longues transactions ou quand mysqld doit examiner beaucoup de lignes pour calculer la requête.

Vous pouvez aussi changer les options binlog_cache_size et max_binlog_cache_size si vous utilisez de grandes transactions multilignes. Voir Section 5.9.4, « Le log binaire ».

14-4-4 - Caractéristiques des tables BDB

Chaque table BDB est stockée sur le disque en deux fichiers. Les fichiers portent le nom de la table et ont des extensions qui indiquent le type de fichier. Un fichier .frm stocke la définition de la table et le fichier .db contient les données et les index.

Pour spécifier explicitement que vous voulez une table BDB, indiquez l'option de création de table ENGINE ou TYPE :

CREATE TABLE t (i INT) ENGINE = BDB;
CREATE TABLE t (i INT) TYPE = BDB;

BerkeleyDB est un synonyme de BDB pour les options ENGINE et TYPE.

Le moteur de tables BDB fournit un modèle transactionnel. La façon dont vous utilisez ces tables dépend du mode de validation :

- si vous utilisez le mot d'autovalidation (ce qui est le mode par défaut), les modifications dans les tables BDB sont validées immédiatement et ne peuvent pas être annulées ;

- si vous utilisez le mode de validation manuel, les modifications ne seront rendues permanentes que si vous envoyez la commande COMMIT. Au lieu de valider, vous pouvez aussi annuler avec la commande ROLLBACK pour détruire les modifications.

Vous pouvez démarrer une transaction avec la commande BEGIN WORK pour suspendre le mode d'autovalidation, ou avec SET AUTOCOMMIT=0 pour le désactiver explicitement.

Voir Section 13.4.1, « Syntaxes de START TRANSACTION, COMMIT et ROLLBACK ».

Le moteur de tables BDB a les caractéristiques suivantes.

- Les tables BDB peuvent avoir jusqu'à 31 index par table, 16 colonnes par index et une taille maximale de 1024 octets par index (500 octets avant MySQL 4.0).

- MySQL requiert une clé PRIMARY KEY dans chaque table BDB pour être capable de faire référence aux lignes précédemment lues. Si vous n'en créez pas, MySQL va gérer une telle clé de manière cachée. La clé cachée a une taille de 5 octets et est incrémentée à chaque nouvelle insertion.

- La clé PRIMARY KEY sera plus rapide que n'importe quelle autre clé, car la PRIMARY KEY est stockée avec les données. Comme les autres clés sont stockées sous la forme données + PRIMARY KEY, il est important de garder une clé PRIMARY KEY aussi courte que possible pour économiser de l'espace disque et améliorer la vitesse.

Ce comportement est similaire à celui d'InnoDB, où des clés primaires courtes économisent de l'espace pour la clé primaire et pour les index secondaires aussi.

- Si toutes les colonnes auxquelles vous accédez dans une table BDB font partie du même index dans la clé primaire, alors MySQL peut exécuter la requête sans avoir à lire la ligne elle-même. Dans une table MyISAM, ce qui précède n'est valable que si les colonnes font partie du même index.

- Scanner séquentiellement est plus lent qu'avec MyISAM, car les tables BDB stockent les données dans un fichier B-tree et non pas dans un fichier séparé.

- Les clés ne sont pas compressées avec les clés précédentes, comme pour les tables ISAM et MyISAM. En d'autres termes, les informations de clés prennent un peu plus d'espace pour les tables BDB, comparativement aux tables MyISAM qui n'utilisent pas l'option PACK_KEYS=0.

- Il y a souvent des trous dans les tables BDB pour vous permettre d'insérer de nouvelles lignes au milieu de l'arbre de données. Cela rend les tables BDB un peu plus grandes que les tables MyISAM.

- SELECT COUNT(*) FROM table_name est très lent, car les tables BDB ne maintiennent pas un compte de leurs lignes dans la table.

- L'optimiseur a besoin de connaître une approximation du nombre de lignes dans la table. MySQL résout ce problème en comptant les insertions et en conservant ce compte dans un segment séparé pour chaque table BDB. Si vous ne faites pas souvent de DELETE ou ROLLBACK, ce nombre sera plutôt précis pour l'optimiseur MySQL, mais comme MySQL ne stocke ce nombre qu'à la fermeture de la table, il peut être incorrect si MySQL s'interrompt inopinément. Cela ne doit pas être fatal si ce nombre n'est pas à 100 % correct. Vous pouvez forcer la mise à jour de ce nombre avec la commande ANALYZE TABLE ou OPTIMIZE TABLE. Section 13.5.2.1, « Syntaxe de ANALYZE TABLE » . Section 13.5.2.5, « Syntaxe de OPTIMIZE TABLE ».

- Le verrouillage interne des tables BDB est fait au niveau page.

- LOCK TABLES fonctionne avec les tables BDB sur les autres tables. Si vous n'utilisez pas le verrou LOCK TABLE, MySQL va poser un verrou interne multiple sur la table, pour s'assurer que la table est bien verrouillée, si un autre thread tente de poser un verrou.

- Pour permettre les annulations de transaction, BDB gère des fichiers de logs. Pour maximiser les performances, vous devriez placer ces fichiers sur un autre disque que celui de votre base, en utilisant l'option --bdb-logdir.

- MySQL fait un point de contrôle à chaque fois qu'un nouveau fichier de logs BDB est démarré et supprime les fichiers de logs anciens qui ne sont pas utiles. Si vous exécutez la commande FLUSH LOGS, vous placerez un nouveau point de contrôle pour les tables Berkeley DB.

Pour la restauration après crash, vous devez utiliser les sauvegardes et le log binaire de MySQL. Voir Section 5.7.1, « Sauvegardes de base de données ».

Attention : si vous effacez les anciens fichiers de logs qui sont en cours d'utilisation, BDB ne sera pas capable de faire la restauration et vous risquez de perdre des données.

- L'application doit toujours être prête à gérer des cas où une modification sur une table BDB peut être annulée, ou une lecture abandonnée pour cause de blocage de verrous.

- Si vous atteignez la capacité maximale du disque avec la table BDB, vous allez obtenir une erreur (probablement l'erreur 28) et la transaction va s'annuler. C'est un comportement différent des tables MyISAM et ISAM qui vont attendre que mysqld ait trouvé de l'espace disque avant de continuer.

14-4-5 - Ce que nous devons corriger dans BDB dans un futur proche :

- Il est très lent d'ouvrir de nombreuses tables BDB en même temps. Si vous utilisez des tables BDB, il ne faut pas avoir un cache de table trop grand (par exemple > 256) et vous devriez utiliser l'option --no-auto-rehash avec le client mysql. Nous envisageons de corriger cela en partie en version 4.0.

- SHOW TABLE STATUS ne fournit pas encore beaucoup d'informations pour les tables BDB.

- Optimiser les performances.

- Ne pas utiliser les verrous de pages lorsque l'on scanne les tables.

14-4-6 - Restrictions avec les tables BDB

Voilà les restrictions que vous pouvez rencontrer en travaillant avec les tables BDB.

- Les tables BDB enregistrent dans le fichier .db le chemin vers le fichier tel qu'il était lorsqu'il a été créé. Cela fait que les tables BDB ne peuvent être changées de répertoire !

- Lors de la sauvegarde de tables BDB, vous devez utiliser mysqldump ou effectuer des sauvegardes de tous les fichiers de tables (les fichiers .frm et .db) et les fichiers de logs BDB. Les fichiers de logs de BDB sont les fichiers dans le répertoire de base des données nommés log.XXXXXXXXXX (dix chiffres).

- Si une colonne accepte les valeurs NULL, avec un index unique, seule une valeur NULL est autorisée. Cela diffère du comportement des autres moteurs.

14-4-7 - Erreurs pouvant survenir lors de l'utilisation des tables BDB

- Si vous obtenez l'erreur suivante dans le fichier hostname.err log lors du démarrage de mysqld :

bdb:  Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #

cela signifie que la nouvelle version de BDB ne supporte pas l'ancien format de log. Dans ce cas, vous devez effacer tous les logs BDB du dossier des données (les fichiers dont le nom est au format log.XXXXXXXXXX) et redémarrer mysqld. Nous vous recommandons aussi d'exécuter un mysqldump --opt de vos vieilles tables BDB, de les effacer, puis de restaurer les copies.

- Si vous n'êtes pas en mode autocommit et que vous effacez une table qu'un autre thread utilise, vous obtiendrez le message d'erreur suivant dans le fichier d'erreurs de MySQL :

001119 23:43:56  bdb:  Missing log fileid entry
001119 23:43:56  bdb:  txn_abort: Log undo failed for LSN:
1 3644744: Invalid

Ce n'est pas une erreur très grave mais nous ne vous recommandons pas d'effacer vos tables si vous n'êtes pas en mode autocommit, tant que ce problème n'est pas résolu (la solution n'est pas triviale).

14-5 - Le moteur de table EXAMPLE

Le moteur de stockage EXAMPLE a été ajouté en MySQL 4.1.3. C'est un moteur « bidon » qui ne fait rien du tout. Son but est de fournir des exemples au niveau du code source de MySQL pour illustrer l'écriture d'un moteur de table. En tant que tel, il intéressera surtout les développeurs.

Pour examiner les codes source du moteur EXAMPLE, voyez le dossier sql/examples dans la distribution source de MySQL 4.1.3 ou plus récent.

Pour activer ce moteur de stockage, utilisez l'option --with-example-storage-engine de la commande configure lors de la compilation de MySQL.

Lorsque vous créez une table EXAMPLE, le serveur crée un fichier de définition dans le dossier de base de données. Le fichier porte le nom de la table et finit avec l'extension .frm. Aucun autre fichier n'est créé. Aucune donnée ne peut être stockée dans la table, ni même lue.

mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec)

mysql> INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table storage engine for 'test' doesn't have this option

mysql> SELECT * FROM test;
Empty set (0.31 sec)

Le moteur de table EXAMPLE ne supporte pas l'indexation.

14-6 - Le moteur de table FEDERATED

Le moteur de table FEDERATED a été ajouté en MySQL 5.0.3. C'est un moteur de table qui accède à des tables dans une base de données distante, plutôt que dans des fichiers locaux.

Pour examiner le code source pour le moteur FEDERATED, reportez-vous dans le dossier sql de la distribution source de MySQL 5.0.3 ou plus récent.

14-6-1 - Installation du moteur de table FEDERATED

Pour activer ce moteur de table, utilisez l'option --with-federated-storage-engine avec la commande configure lorsque vous compilez MySQL.

14-6-2 - Description du moteur de stockage FEDERATED

Lorsque vous créez une table FEDERATED, le serveur crée un fichier de définition de fichiers dans le dossier de données. Le fichier porte le nom de la table et l'extension .frm. Aucun autre fichier n'est créé car les données résident en fait sur un autre serveur. C'est la différence principale avec un moteur de table local.

Pour les tables locales, les fichiers de données sont locaux. Par exemple, si vous créez une table MyISAM du nom de users, le gestionnaire MyISAM crée un fichier de données appelé users.MYD. Un gestionnaire local lit, écrit et efface les données sur un fichier local et les données sont enregistrées dans un format particulier au gestionnaire. Pour lire les lignes, le gestionnaire doit analyser les colonnes des tables. Pour écrire les lignes, les valeurs des colonnes doivent être converties en un format linéaire.

Avec le moteur de table MySQL FEDERATED, il n'y a pas de données locales pour la table : par exemple, il n'y a pas de fichier .MYD. Au lieu de cela, un serveur de base de données distant se charge de stocker les données de la table. Cela impose l'utilisation du protocole client MySQL pour lire, écrire et effacer les données. La lecture des données est initiée via la commande SQL SELECT * FROM tbl_name. Pour lire le résultat, les lignes sont lues avec la fonction C mysql_fetch_row(), puis converties en colonnes telles que la commande SELECT les attend, au format demandé par le gestionnaire FEDERATED.

Le processus de base est le suivant :

1. les commandes SQL sont reçues localement ;

2. les commandes sont passées au gestionnaire MySQL (au format du gestionnaire) ;

3. les commandes sont passées à l'API client MySQL (les données sont converties en appel SQL) ;

4. les commandes sont reçues par la base de données distante, via l'API client ;

5. les résultats, s'il y en a, sont convertis au format du gestionnaire ;

6. les résultats sont reçus localement.

14-6-3 - Comment utiliser les tables FEDERATED

La procédure pour utiliser les tables FEDERATED est très simple. Normalement, vous devez avoir 2 serveurs en fonctionnement, sur le même hôte ou sur deux hôtes distincts. Il est aussi possible pour une table FEDERATED d'utiliser une autre table gérée par un autre serveur, mais il y a quelques limitations qui s'ajoutent.

D'abord vous devez avoir une table sur un serveur distant, à laquelle vous voulez accéder via la table FEDERATED. Supposez que la table distante dans la base federated est définie comme ceci :

CREATE TABLE test_table (
id     int(20) NOT NULL auto_increment,
name   varchar(32) NOT NULL default '',
other  int(20) NOT NULL default '0',
PRIMARY KEY  (id),
KEY name (name),
KEY other_key (other)
)
ENGINE=MyISAM
DEFAULT CHARSET=latin1 ;

La table ENGINE peut utiliser n'importe quel moteur de stockage ; la table n'est pas obligatoirement une table MyISAM.

Ensuite, créez une table FEDERATED pour accéder à la table distante. Le serveur où vous créez la table FEDERATED est le « client-serveur ». Sur ce serveur, créez une table comme ceci :

CREATE TABLE federated_table (
id     int(20) NOT NULL auto_increment,
name   varchar(32) NOT NULL default '',
other  int(20) NOT NULL default '0',
PRIMARY KEY  (id),
KEY name (name),
KEY other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=latin1
COMMENT='mysql://root@remote_host:9306/federated/test_table';

La structure de cette table doit être exactement la même que la table distante, hormis le moteur ENGINE qui doit valoir FEDERATED et l'option de table COMMENT qui contient la chaîne de connexion pour spécifier au moteur FEDERATED comment se connecter au serveur distant.

Le moteur FEDERATED ne crée que le fichier test_table.frm dans la base de données federated.

Les informations d'hôte distant représentent le serveur sur lequel votre serveur se connecte en tant que « client » et les informations de tables et de bases qui représentent les « données ». Dans l'exemple, le serveur distant va fonctionner en tant que remote_host sur le port 9306 : il est recommandé de lancer ce serveur pour qu'il soit en attente sur le port 9306.

La forme générale de la chaîne de connexion de l'option COMMENT est la suivante :

scheme://user_name[:password]@host_name[:port_num]:/db_name/tbl_name

Seul le protocole mysql est supporté comme valeur pour scheme actuellement et le numéro de port ainsi que le mot de passe sont optionnels.

Voici quelques exemples de chaînes de connexion :

COMMENT='mysql://username:password@hostname:port/database/tablename'
COMMENT='mysql://username@hostname/database/tablename'
COMMENT='mysql://username:password@hostname/database/tablename'

L'utilisation de COMMENT pour spécifier la chaîne de connexion n'est pas optimale et nous allons probablement changer cela en MySQL 5.1. Gardez cela en tête que lorsque vous utilisez les tables FEDERATED car cela vous obligera à faire des modifications dans un avenir proche.

De même, comme le mot de passe est stocké en texte clair dans la chaîne, il peut être vu par un autre utilisateur avec un accès à SHOW CREATE TABLE ou SHOW TABLE STATUS pour la table FEDERATED.

14-6-4 - Limitations du moteur de stockage FEDERATED

Voici ci-dessous ce que le moteur de stockage FEDERATED fait et ne fait pas.

- Dans la première version, le serveur distant doit être un serveur MySQL. Le support d'autres serveurs par le moteur FEDERATED est à l'étude actuellement.

- La table distante sur laquelle pointe la table FEDERATED doit exister avant que vous n'essayiez d'y accéder via la table FEDERATED.

- Il est possible pour une table FEDERATED de pointer sur une autre table mais vous devez être prudents et ne pas créer de boucle. Vous avez déjà entendu parler de l'effet Larsen ? Vous avez déjà vu ce que ça fait d'avoir deux miroirs face à face ? Cela devrait illustrer la situation à éviter.

- Il n'y a pas de support pour les transactions.

- Il n'y a pas de moyen pour que le moteur FEDERATED sache que la table distante a changé. La raison est que la table doit fonctionner comme un fichier de données qui n'est jamais écrit par autre chose que la base de données. L'intégrité des données dans la table locale pourrait être cassée s'il y a des modifications dans la table distante.

- Le moteur de stockage FEDERATED supporte les commandes SELECT, INSERT, UPDATE, DELETE et les index. Il ne supporte pas les commandes ALTER TABLE, DROP TABLE ou les autres commandes de Définition des données (Data Definition Language). Cette première implémentation n'utilise pas les commandes préparées. Nous étudions actuellement la possibilité d'ajouter le support de ces fonctionnalités au client.

- L'implémentation utilise SELECT, INSERT, UPDATE, DELETE et non pas HANDLER.

- Les tables FEDERATED ne fonctionnent pas avec le cache de requêtes.

Certaines limitations seront levées dans les futures versions du gestionnaire FEDERATED.

14-7 - Le moteur de table ARCHIVE

Le moteur de table ARCHIVE a été ajouté en MySQL 4.1.3. Il est utilisé pour stocker de grandes quantités de données, sans index et de manière très économique.

Pour activer ce moteur de table, utilisez l'option --with-archive-storage-engine avec la commande configure lors de la compilation de MySQL.

Lorsque vous créez une table de type ARCHIVE, le serveur crée un fichier de définition dans le dossier de données. Le fichier porte le nom de la table et l'extension .frm. Le moteur de table crée les autres fichiers, qui portent tous les noms de la table. Les données et les métadonnées portent les extensions .ARZ et .ARM, respectivement. Un fichier .ARN peut aussi apparaître durant les opérations d'optimisation.

Le moteur ARCHIVE ne supporte que les commandes INSERT et SELECT : aucun effacement, remplacement ou modification. Une commande SELECT effectue un scan de table complet. Les enregistrements sont compressés au moment de leur insertion. Vous pouvez utiliser la commande OPTIMIZE TABLE pour analyser la table et compresser encore plus.

Le moteur de table ARCHIVE utilise un verrouillage de ligne.

14-8 - Le moteur CSV

Le moteur CSV a été ajouté en MySQL 4.1.4. Ce moteur stocke les données dans un fichier texte, avec le format « valeurs séparées par des virgules ».

Pour activer ce moteur de stockage, utilisez l'option --with-csv-storage-engine lors de la configuration configure de la compilation de MySQL.

Lorsque vous créez une table CSV, le serveur créé un fichier de définition de tables dans le dossier de données. Le fichier commence avec le nom de la table et porte l'extension .frm. Le moteur de stockage crée aussi un fichier de données. Il porte le nom de la table et l'extension .CSV. Le fichier de données est un fichier texte simple. Lorsque vous stockez des données dans la table, le moteur les écrit au format CSV dans le fichier de données.

mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = CSV;
Query OK, 0 rows affected (0.12 sec)

mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM test;
+------+------------+
| i    | c          |
+------+------------+
|    1 | record one |
|    2 | record two |
+------+------------+
2 rows in set (0.00 sec)

Si vous ouvrez le fichier test.CSV issu du dossier de données, après avoir exécuté les commandes ci-dessus, vous trouverez le contenu suivant :

"1","record one"
"2","record two"

Le moteur CSV ne supporte pas l'indexation.

14-9 - Tables ISAM

Le moteur de table original de MySQL est le moteur ISAM. Il a été le seul moteur disponible jusqu'en MySQL 3.23, lorsque la version améliorée MyISAM a été inventée. ISAM est maintenant obsolète. Depuis MySQL 4.1, il est inclus dans le source, mais pas activé dans les versions binaires. Il disparaîtra en MySQL 5.0. Les versions embarquées de MySQL ne supportent pas les tables ISAM par défaut.

Étant donné l'obsolescence de ISAM et comme MyISAM est une version améliorée de ISAM, il est recommandé de convertir les tables ISAM en MySAM dès que possible. Pour convertir une table ISAM en MyISAM, utilisez la commande ALTER TABLE :

mysql> ALTER TABLE tbl_name TYPE = MYISAM;

Pour plus d'informations sur MyISAM, voyez Section 14.1, « Le moteur de tables MyISAM ».

Chaque table ISAM est stockée dans trois fichiers. Les fichiers portent le nom de la table et ont une extension qui indique leur type. Un fichier .frm stocke la définition de table. Le fichier de données a pour suffixe .ISD. Le fichier d'index a l'extension .ISM.

ISAM utilise les index B-tree.

Vous pouvez réparer ou vérifier une table ISAM avec l'utilitaire isamchk. Voir Section 5.7.3.7, « Utiliser myisamchk pour restaurer une table ».

ISAM possède les fonctionnalités/propriétés suivantes.

- Clefs compressées et de taille fixe.

- Enregistrements de taille fixée ou dynamique.

- 16 clés avec 16 parties de clés/clés.

- Taille maximale de la clé 256 (défaut).

- Les données sont enregistrées au format machine ; c'est rapide, mais c'est dépendant de la machine/système d'exploitation.

La plupart des choses vraies pour les tables MyISAM le sont pour les tables ISAM. Les différences majeures avec les tables MyISAM sont les suivantes.

- Les tables ISAM ne sont pas portables directement entre les plates-formes/systèmes d'exploitation.

- Elles ne peuvent pas gérer les tables de taille supérieure à 4 Go.

- Elles ne supportent que la compression des préfixes sur les chaînes de caractères.

- Les limites de clés sont plus basses.

- Les tables à taille de ligne dynamique sont plus fragmentées.

- Elles ne supportent pas les tables MERGE.

- Les tables sont vérifiées et réparées avec isamchk plutôt que myisamchk.

- Les tables sont compressées avec pack_isam plutôt que myisampack.

- Il est impossible d'utiliser les commandes BACKUP TABLE et RESTORE TABLE.

- Il est impossible d'utiliser les commandes d'entretien CHECK TABLE, REPAIR TABLE, OPTIMIZE TABLE et ANALYZE TABLE.

- Il n'y a pas de support pour les index en texte plein ou spatiaux.

- Il n'y a pas de support pour les jeux de caractères multiples.

- Les index ne peuvent pas être assignés à des caches de clés spécifiques.

15 - Le moteur de tables InnoDB

15-A - Présentation des tables InnoDB

InnoDB fournit à MySQL un gestionnaire de table transactionnelle (compatible ACID), avec validation (commits), annulations (rollback) et capacités de restauration après crash. InnoDB utilise un verrouillage de lignes, et fournit des lectures cohérentes comme Oracle, sans verrous. Ces fonctionnalités accroissent les possibilités d'utilisation simultanées des tables, et les performances. Il n'y a pas de problème de queue de verrous avec InnoDB, car les verrous de lignes utilisent très peu de place. Les tables InnoDB sont les premières tables MySQL qui supportent les contraintes de clés étrangères (FOREIGN KEY).

InnoDB a été conçu pour maximiser les performances lors du traitement de grandes quantités de données. Son efficacité processeur n'est égalée par aucun autre moteur de base de données.

Techniquement, InnoDB est un gestionnaire de table placé sous MySQL. InnoDB dispose de son propre buffer pour mettre en cache les données et les index en mémoire centrale. InnoDB stocke les tables et index dans un espace de table, qui peut être réparti dans plusieurs fichiers. Ceci diffère des tables comme, par exemple, MyISAM où chaque table est stockée dans un fichier différent. Les tables InnoDB peuvent prendre n'importe quelle taille, même sur les systèmes d'exploitation dont la limite est de 2 Go par fichier.

InnoDB est inclus dans les distributions binaires par défaut depuis MySQL 4.0. Pour des informations sur le support InnoDB en MySQL 3.23, voyez la section Section 15.3, « InnoDB avec MySQL version 3.23 ».

InnoDB est utilisé en production dans plusieurs sites où de grandes capacités de stockage et des performances accrues sont nécessaires. Le fameux site web Slashdot.org utilise InnoDB. Mytrix, Inc. stocke plus de 1 To de données dans une base InnoDB, et un autre site gère une moyenne de 800 insertions/modifications par secondes avec InnoDB.

InnoDB est sous licence GNU GPL License Version 2 (de juin 1991). Si vous distribuez MySQL et InnoDB, et que votre application ne satisfait pas les restrictions de la licence GPL, vous devez acheter une licence commerciale MySQL Pro sur https://order.mysql.com/?sub=pg&pg_no=1.

15-B - Informations de contact InnoDB

Informations de contact de Innobase Oy, producteur de InnoDB. Site web : http://www.innodb.com/. Courrier électronique : <Heikki.Tuuri@innodb.com>

phone: 358-9-6969 3250 (bureau) 358-40-5617367 (portable)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finland

15-C - InnoDB avec MySQL version 3.23

Depuis MySQL version 4.0, InnoDB est activé par défaut. Les informations suivantes ne s'appliquent qu'à la série 3.23.

Les tables InnoDB sont incluses dans la distribution source de MySQL depuis la version 3.23.34a et sont activées dans les exécutables MySQL-Max de la série 3.23. Pour Windows, les exécutables MySQL-Max sont inclus dans la distribution standard.

Si vous avez téléchargé la version binaire de MySQL qui inclut le support d'InnoDB, suivez simplement les instructions du manuel MySQL pour installer la version binaire de MySQL. Si vous avez déjà MySQL-3.23 d'installé, le plus simple pour installer MySQL-Max est de remplacer l'exécutable serveur mysqld avec l'exécutable correspondant de la distribution MySQL-Max. MySQL et MySQL-Max ne diffèrent qu'au niveau de ce programme. Voyez Section 2.3, « Installer MySQL sur d'autres systèmes type Linux » et Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld ».

Pour compiler MySQL avec le support InnoDB, téléchargez MySQL MySQL-3.23.34a ou plus récent sur le site de http://www.mysql.com/ et configurez MySQL avec l'option --with-innodb. Voyez le manuel MySQL pour les instructions d'installation de MySQL. Voir Section 2.4, « Installation de MySQL avec une distribution source ».

Pour utiliser les tables InnoDB dans MySQL-Max version 3.23, vous devez spécifier des paramètres dans la section [mysqld] du fichier de configuration my.cnf, ou, sous Windows, dans my.ini. Si vous ne configurez pas InnoDB dans le fichier d'options, InnoDB ne démarrera pas. Depuis MySQL 4.0, InnoDB utilise des valeurs par défaut pour ces paramètres si vous n'en spécifiez pas. Cependant, il est recommandé d'utiliser des valeurs appropriées pour votre système afin d'obtenir performances valables. Le paramétrage est détaillé dans la section Section 15.4, « Configuration InnoDB ».)

Au minimum, en version 3.23, vous devez spécifier avec innodb_data_file_path où seront les fichiers de données, et les tailles de fichiers. Si vous ne mentionnez pas innodb_data_home_dir dans my.cnf, le comportement par défaut est de créer ces fichiers dans le dossier de données datadir de MySQL. Si vous spécifiez innodb_data_home_dir comme une chaîne vide, vous pouvez donner des chemins absolus à vos fichiers de données dans innodb_data_file_path.

Le minimum est de modifier la section [mysqld] à la ligne :

innodb_data_file_path=ibdata:30M

Mais pour obtenir de bonnes performances, il est recommandé de spécifier des options supplémentaires. Voir Section 15.5, « Options de démarrage InnoDB ».

15-D - Configuration InnoDB

Pour utiliser les tables InnoDB en MySQL versions 3.23, voyez Section 15.3, « InnoDB avec MySQL version 3.23 ».

En MySQL 4.0, vous n'avez rien à faire pour obtenir le support des tables InnoDB. Si vous ne souhaitez pas utiliser les tables InnoDB, vous pouvez ajouter l'option skip-innodb dans votre fichier d'options MySQL.

Les deux ressources disques importantes gérées par InnoDB sont sa table de données et son fichier de logs.

Si vous ne spécifiez aucune option de configuration InnoDB, MySQL 4.0 et plus récent créera un fichier de données autocroissant appelé ibdata1 et deux fichiers de logs de 5 Mo appelés ib_logfile0 et ib_logfile1 dans le dossier de données MySQL. En MySQL 4.0.0 et 4.0.1, le fichier de données est de 64 Mo et pas autocroissant. En MySQL 3.23, InnoDB ne démarrera pas si vous ne fournissez pas d'options de configuration.

Note : pour obtenir les meilleures performances, vous devez explicitement configurer les paramètres InnoDB dans les exemples ci-dessous. Naturellement, il vous faudra adapter les configurations à votre architecture.

Pour configurer le fichier de données InnoDB, utilisez l'option innodb_data_file_path dans la section [mysqld] du fichier my.cnf. Sous Windows, vous pouvez utiliser my.ini à la place. La valeur de innodb_data_file_path doit être une liste d'un ou plusieurs fichiers. Si vous indiquez plusieurs fichiers, séparez les noms par des caractères points-virgules (';') :

innodb_data_file_path=datafile_spec1[;datafile_spec2]...

Par exemple, une configuration qui crée explicitement un espace de table, avec les mêmes caractéristiques que la configuration par défaut de MySQL 4.0 est :

[mysqld]
innodb_data_file_path=ibdata1:10M:autoextend

Cette configuration crée un fichier de données de 10 Mo ibdata1, autocroissant. Il n'y a pas de dossier de sauvegarde d'indiqué : par défaut, c'est le dossier de données de MySQL.

Les tailles sont spécifiées avec les suffixes M et G pour indiquer des mégaoctets et des gigaoctets.

Une table contenant 50 Mo de données, appelée ibdata1 et un fichier 50 Mo autocroissant, appelé ibdata2 dans le dossier de données est configuré comme ceci :

[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

La syntaxe complète de la spécification de fichier de données inclut le nom du fichier, sa taille, et différents attributs :

file_name:file_size[:autoextend[:max:max_file_size]]

L'attribut autoextend et ceux qui le suivent peuvent être utilisés uniquement pour le dernier fichier de données de la ligne innodb_data_file_path. autoextend est disponible depuis MySQL 3.23.50 et 4.0.2.

Si vous spécifiez le dernier fichier avec l'option autoextend, InnoDB va augmenter la taille du dernier fichier de données jusqu'à ce qu'il n'y ait plus de place dans l'espace de table. Les incréments se feront par bloc de 8 Mo.

Si le disque est plein, vous aurez à ajouter un autre fichier sur un autre disque. Les informations pour reconfigurer une table existante sont données dans la section Section 15.8, « Ajouter et retirer des données et des logs InnoDB ».

InnoDB ne connaît pas la taille maximale des fichiers sur votre système : il faut donc être prudent lorsque la taille des fichiers ne peut dépasser 2 Go. Pour spécifier la taille maximale des fichiers autocroissants, utilisez l'attribut max. La ligne de configuration suivante permet au fichier ibdata1 de croître jusqu'à 500 Mo :

[mysqld]
innodb_data_file_path=ibdata1:10M:autoextend:max:500M

InnoDB crée les fichiers de données dans le dossier de données de MySQL. Pour spécifier explicitement un dossier, utilisez l'option innodb_data_home_dir. Par exemple, pour créer deux fichiers appelés ibdata1 et ibdata2 mais pour les placer dans le dossier /ibdata, configurez InnoDB comme ceci :

[mysqld]
innodb_data_home_dir = /ibdata
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

Note : InnoDB ne crée pas les dossiers : assurez-vous que /ibdata existe avant de lancer le serveur. C'est aussi vrai pour les fichiers de logs. Utilisez la commande Unix et DOS mkdir pour créer les dossiers nécessaires.

InnoDB forme le chemin de chaque fichier en concaténant textuellement la valeur de innodb_data_home_dir devant le nom du fichier, en ajoutant un slash si nécessaire. Si l'option innodb_data_home_dir n'est pas mentionnée dans my.cnf, la valeur par défaut est le dossier « point » ./, c'est-à-dire le dossier de données de MySQL.

Si vous spécifiez l'option innodb_data_home_dir sous forme de chaîne vide, vous pouvez spécifier des noms de chemins absolus dans la valeur de innodb_data_file_path. L'exemple ci-dessous est équivalent au précédent :

[mysqld]
innodb_data_home_dir =
innodb_data_file_path=/ibdata/ibdata1:50M;/ibdata/ibdata2:50M:autoextend

Exemple de fichier my.cnf simple. Supposons que vous avez un serveur avec 128 Mo de RAM et un disque dur. Voici un exemple de configuration de fichier my.cnf ou my.ini pour InnoDB. Nous supposons que vous exécutez MySQL-Max-3.23.50 ou plus récent, ou MySQL-4.0.2 ou plus récent, qui utilisent l'attribut autoextend.

Cet exemple devrait convenir à une majorité d'utilisateurs, Unix et Windows, qui ne souhaitent pas répartir leurs fichiers de données InnoDB et leurs logs sur plusieurs disques. Cette configuration crée un fichier de données autocroissant, appelé ibdata1 et deux fichiers de logs InnoDB ib_logfile0 et ib_logfile1 dans le dossier de données MySQL. De plus, le petit fichier d'archive InnoDB ib_arch_log_0000000000 sera placé dans datadir.

[mysqld]
# Vous pouvez placer d'autres options MYSQL ici
# ...
# Le fichier de données doit contenir vos données et index.
# Assurez-vous que vous avez l'espace disque nécessaire.
innodb_data_file_path = ibdata1:10M:autoextend
#
# Utilisez un buffer de taille 50 à 80 % de votre mémoire serveur
set-variable = innodb_buffer_pool_size=70M
set-variable = innodb_additional_mem_pool_size=10M
#
# Utiisez un fichier de logs de taille 25 % du buffer mémoire
set-variable = innodb_log_file_size=20M
set-variable = innodb_log_buffer_size=8M
#
innodb_flush_log_at_trx_commit=1

Vérifiez que le serveur MySQL a les droits de créer ces fichiers dans le datadir. Plus généralement, le serveur doit avoir les droits d'accès dans les dossiers où il va créer des fichiers, de données ou de log.

Notez que le fichier de données doit être inférieur à 2 Go sur certains systèmes d'exploitation. La taille combinée des fichiers de logs doit être inférieure à 4 Go. La taille combinée des fichiers de données doit être inférieure à 10 Go.

Lorsque vous créez pour la première fois une base de données InnoDB, il est mieux de lancer le serveur depuis la commande en ligne. InnoDB va afficher des informations sur la création de la base, et vous verrez commence ça se passe. Voyez la section plus bas, pour une illustration. Par exemple, sous Windows, vous pouvez démarrer mysqld-max.exe, qui est stocké dans C:\mysql\bin, vous pouvez le démarrer comme ceci :

C:\> C:\mysql\bin\mysqld-max --console

Si vous n'envoyez par de données sur l'écran, vérifiez le fichier de logs pour savoir ce que InnoDB a indiqué durant le lancement.

Voyez Section 15.6, « Créer des bases InnoDB » pour un exemple des informations affichées par InnoDB.

Où mettre le fichier d'options sous Windows ? Les règles sous Windows sont les suivantes.

- Un seul des deux fichiers my.cnf ou my.ini doit être créé.

- Le fichier my.cnf doit être placé dans le dossier racine du disque C:.

- Le fichier my.ini doit être placé dans le dossier WINDIR, e.g, C:\WINDOWS ou C:\WINNT. Vous pouvez utiliser la commande SET de MS-DOS pour afficher la valeur de WINDIR :

C:\> SET WINDIR
windir=C:\WINNT

- Si votre PC utilise un gestionnaire de démarrage où le C: n'est pas votre disque de démarrage, alors votre seule option est d'utiliser le fichier my.ini.

Où placer les fichiers d'options sous Unix ? Sous Unix, mysqld lit les options dans les fichiers suivants, s'ils existent, et dans cet ordre :

- /etc/my.cnf Options globales.

- COMPILATION_DATADIR/my.cnf Options spécifiques au serveur.

- defaults-extra-file Le fichier spécifié avec --defaults-extra-file=....

- ~/.my.cnf Options spécifiques à l'utilisateur.

COMPILATION_DATADIR est le dossier de données de MySQL qui a été spécifié lors de l'utilisation du script ./configure, avant la compilation de mysqld (typiquement, /usr/local/mysql/data pour une installation binaire, ou /usr/local/var pour une installation source).

Si vous voulez vous assurer que mysqld lit les options uniquement depuis un fichier spécifique, vous pouvez utiliser l'option --defaults-option comme première option de ligne de commande, au démarrage du serveur :

mysqld --defaults-file=your_path_to_my_cnf

Exemple de fichier my.cnf complexe : supposons que vous avez un serveur Linux avec 2 Go de RAM et trois disques de 60 Go (situés dans les dossiers /, /dr2 et /dr3. Voici ci-dessous un exemple de configuration possible pour my.cnf, de InnoDB.

[mysqld]
# Vous pouvez placer d'autres options MYSQL ici
# ...
innodb_data_home_dir =
#
# Le fichier de données doit contenir vos données et index.
innodb_data_file_path = /ibdata/ibdata1:2000M;/dr2/ibdata/ibdata2:2000M:autoextend
#
# Utilisez un buffer de taille 50 à 80 % de votre mémoire serveur
# mais assurez-vous sous Linux que l'utilisation totale est inférieure à 2 Go
set-variable = innodb_buffer_pool_size=1G
set-variable = innodb_additional_mem_pool_size=20M
innodb_log_group_home_dir = /dr3/iblogs
#
# innodb_log_arch_dir doit être le même que  innodb_log_group_home_dir
# (starting from 4.0.6, you can omit it)
innodb_log_arch_dir = /dr3/iblogs
set-variable = innodb_log_files_in_group=2
#
# Utilisez un fichier de logs de taille 15 % du buffer mémoire
set-variable = innodb_log_file_size=250M
set-variable = innodb_log_buffer_size=8M
#
innodb_flush_log_at_trx_commit=1
set-variable = innodb_lock_wait_timeout=50
#
# Décommentez les prochaines lignes, si vous voulez les utiliser
#innodb_flush_method=fdatasync
#set-variable = innodb_thread_concurrency=5

Notez que nous avons placé deux fichiers de données sur des disques différents. InnoDB va remplir l'espace de tables jusqu'au maximum. Dans certains cas, les performances seront améliorées si les données ne sont pas toutes placées sur le même disque physique. Placer les fichiers de logs dans des disques séparés est souvent une bonne chose. Vous pouvez aussi utiliser des partitions de disques brutes (raw devices) comme fichier de données. Voir Section 15.15.2, « Utiliser les raw devices pour l'espace de tables ».

Attention : en Linux x86, vous devez être très prudent, et ne pas utiliser trop de mémoire. glibc va autoriser les processus à dépasser la pile de thread, et votre système va planter. Cela représente un risque réel si la valeur de 2 Go :

innodb_buffer_pool_size
+ key_buffer_size
+ max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size)
+ max_connections*2MB

Chaque thread va utiliser une pile (souvent 2 Mo, mais les exécutables MySQL uniquement 256 ko) et dans le pire des scénarios, sort_buffer + read_buffer_size de mémoire supplémentaire.

Depuis MySQL 4.1, vous pouvez utiliser 64 Go de mémoire physique sur Windows 32 bits. Voyez la description de innodb_buffer_pool_awe_mem_mb dans Section 15.5, « Options de démarrage InnoDB ».

Comment optimiser d'autres paramètres du serveur mysqld ? Les valeurs qui conviennent à la majorité des utilisateurs sont :

[mysqld]
skip-external-locking
set-variable = max_connections=200
set-variable = read_buffer_size=1M
set-variable = sort_buffer_size=1M
# key_buffer vaut de 5 à 50 %
# de la RAM disponible, suivant l'utilisation des
# tables MyISAM, mais gardez
# key_buffer + InnoDB en deça de < 80 % de votre RAM
set-variable = key_buffer_size=...

15-E - Options de démarrage InnoDB

Cette section décrit les options d'InnoDB. Depuis MySQL 4.0, toutes les options peuvent être spécifiées sous la forme --opt_name=value en ligne de commande, ou dans les fichiers d'options. Avant MySQL 4.0, les options numériques devaient être spécifiées avec --set-variable=opt_name=value ou la syntaxe -O opt_name=value.

- innodb_additional_mem_pool_size
La taille du buffer mémoire d'InnoDB, pour ses dictionnaires d'informations, et ses structures internes de données. Une valeur pratique est 2 Mo, mais plus vous aurez de tables dans votre application, plus vous devrez augmenter cette valeur. Si InnoDB est à court de mémoire, il va allouer de la mémoire auprès du système, et écrire des messages dans le fichier de logs MySQL.

- innodb_buffer_pool_awe_mem_mb
Taille du pool de buffer, en Mo, s'il est placé dans la mémoire AWE de Windows 32 bits. Disponible depuis MySQL version 4.1.0, et uniquement utile sur Windows 32 bits. Si votre système Windows 32 bits supporte plus de 4 Go de mémoire, dite aussi Address Windowing Extensions, vous pouvez allouer le pool de buffer InnoDB dans la mémoire physique AWE en utilisant ce paramètre. La valeur maximale est de 64 000. Si ce paramètre est spécifié, alors innodb_buffer_pool_size est la fenêtre dans l'espace d'adresse 32 bits de mysqld où InnoDB place la mémoire AWE. Une bonne valeur pour innodb_buffer_pool_size est alors 500M.

- innodb_buffer_pool_size
La taille de buffer mémoire que InnoDB utiliser pour mettre en cache les données et les index de tables. Plus cette valeur est grande, et moins vous ferez d'accès disques. Sur un serveur dédié, vous pouvez monter cette valeur jusqu'à 80 % de la mémoire physique de la machine. Ne lui donnez pas une valeur trop grande, car cela peut engendrer l'utilisation de mémoire sur le disque par votre serveur.

- innodb_data_file_path
Chemin individuel vers les fichiers de données, et leur taille. Le chemin complet de chaque fichier de données est créé en concaténant innodb_data_home_dir avec les chemins spécifiés ici. La taille du fichier est spécifiée en mégaoctets, ce qui explique la présence du 'M' après les spécifications ci-dessus. Depuis la version 3.23.44, vous pouvez donner au fichier une taille supérieure à 4 Go sur les systèmes d'exploitation qui acceptent les gros fichiers. Sur certains systèmes, la taille doit être inférieure à 2 Go. Si vous ne spécifiez pas innodb_data_file_path, le comportement par défaut depuis la version 4.0 est de créer un fichier autocroissant de 10 Mo, appelé ibdata1. Depuis la version 3.23.44, vous pouvez donner une taille de fichier de plus de 4 Go sur les systèmes d'exploitation qui supportent les grands fichiers. Vous pouvez aussi utiliser les partitions raw. Voir Section 15.15.2, « Utiliser les raw devices pour l'espace de tables ».

- innodb_data_home_dir
La partie commune du chemin de tous les fichiers de données InnoDB. Si vous ne mentionnez pas cette option, la valeur par défaut sera celle du dossier de données MySQL. Vous pouvez aussi spécifier une chaîne vide, et dans ce cas, les chemins spécifiés dans innodb_data_file_path seront des chemins absolus.

- innodb_fast_shutdown
Par défaut, InnoDB fait une purge complète et vide le buffer d'insertion avant une extinction. Ces opérations peuvent prendre beaucoup de temps. Si vous donnez à ce paramètre la valeur de 1, InnoDB ignore ces opérations d'extinction. Cette option est valable depuis MySQL 3.23.44 et 4.0.1. Sa valeur par défaut est 1 depuis la version 3.23.50.

- innodb_file_io_threads
Nombre de pointeurs de fichier de InnoDB. Normalement, cette valeur doit être de 4, mais sur des disques Windows, les accès peuvent être améliorés en augmentant cette valeur.

- innodb_file_per_table
Cette option fait que InnoDB va stocker chaque table dans un fichier .ibd indépendant. Voyez la section sur les espaces de tables multiples. Voir Section 15.7.6, « Espaces de tables multiples : chaque table InnoDB a son fichier .ibd ». Cette option a été ajoutée en MySQL 4.1.1.

- innodb_flush_log_at_trx_commit
Normalement, cette option vaut 1, ce qui signifie que lors de la validation de la transaction, les logs sont écrits sur le disque, et les modifications faites par la transaction deviennent permanentes, et survivront à un crash de base. Si vous souhaitez réduire la sécurité de vos données, et que vous exécutez de petites transactions, vous pouvez donner une valeur de 0 à cette option, pour réduire les accès disques.

- innodb_flush_method
(Disponible depuis 3.23.40 et plus récent) La valeur par défaut pour cette option est fdatasync. Une autre option est O_DSYNC.

- innodb_force_recovery
Attention : cette option ne doit être définie que dans les cas où vous voulez exporter les données d'une base corrompue, dans une situation d'urgence. Les valeurs possibles de cette option vont de 1 à 6. La signification des valeurs est décrite dans Section 15.9.1, « Forcer la restauration ». Par mesure de sécurité, InnoDB empêche les modifications de données si la valeur de cette option est supérieure à 0. Cette option est disponible depuis MySQL 3.23.44.

- innodb_lock_wait_timeout
Le délai d'expiration des transactions InnoDB, en cas de blocage de verrou, avant d'annuler. InnoDB détecte automatiquement les blocages de verrous et annule alors les transactions. Si vous utilisez la commande LOCK TABLES, ou un autre gestionnaire de table transactionnelle que InnoDB dans la même transaction, un blocage de verrou peut survenir, et InnoDB ne pourra pas le détecter. Ce délai est donc pratique pour résoudre ces situations.

- innodb_log_arch_dir
Le dossier où les logs complétés doivent être archivés, si nous utilisons l'archivage de logs. La valeur de ce paramètre doit être actuellement la même que la valeur de innodb_log_group_home_dir.

- innodb_log_archive
Cette valeur doit être actuellement de 0. Au moment de la restauration de données à partir d'une sauvegarde, à l'aide des logs binaires de MySQL, il n'y a actuellement pas besoin d'archiver les fichiers de logs InnoDB.

- innodb_log_buffer_size
La taille du buffer que InnoDB utilise pour écrire les logs dans les fichiers de logs, sur le disque. Les valeurs utiles vont de 1 Mo à 8 Mo. Un grand buffer de log permet aux grandes transactions de s'exécuter sans avoir à écrire de données dans le fichier de logs jusqu'à la validation. Par conséquent, si vous avez de grandes transactions, augmenter cette taille va réduire les accès disques.

- innodb_log_file_size
Taille de chaque fichier de logs dans un groupe de log, exprimé en mégaoctets. Les valeurs pratiques vont de 1 Mo à une fraction de la taille du buffer de log (1 / le nombre de logs, en fait). Plus la taille est grande, moins de points de contrôles seront utilisés, réduisant les accès disques. La taille combinée des logs doit être inférieure à 4 Go sur les systèmes 32 bits.

- innodb_log_files_in_group
Nombre de fichiers de logs dans le groupe de log. InnoDB écrit dans ces fichiers de manière circulaire. Une valeur de 2 est recommandée. C'est la valeur par défaut.

- innodb_log_group_home_dir
Le dossier pour les fichiers de logs. Il doit avoir la même valeur que innodb_log_arch_dir. Si vous ne spécifiez pas de paramètre de log InnoDB, la configuration par défaut va créer deux fichiers de logs de 5 Mo, appelés ib_logfile0 et ib_logfile1 dans le dossier de données MySQL.

- innodb_max_dirty_pages_pct
Cet entier va de 0 à 100. Par défaut, il vaut 90. Le thread principal de InnoDB essaie de transmettre les pages au pool de buffer, pour qu'un pourcentage maximal de innodb_max_dirty_pages_pct soit encore en attente de flush. Cette option est disponible depuis 4.0.13 et 4.1.1. Si vous avez le droit de SUPER, ce pourcentage peut être changé durant l'exécution du serveur :

SET GLOBAL innodb_max_dirty_pages_pct = value;

- innodb_mirrored_log_groups
Nombre de copies identiques de groupe de log que nous conservons. Actuellement, cette valeur doit être au minimum de 1.

- innodb_open_files
Ce n'est utile que si vous utilisez les espaces de tables multiples. Cette option spécifie que le nombre maximal de fichiers .ibd que InnoDB peut garder ouvert simultanément. La valeur minimum est de 10. La valeur maximum est de 300. Disponible depuis MySQL version 4.1.1.
Les pointeurs de fichiers utilisés par .ibd sont réservés pour InnoDB. Ils sont indépendants de ceux spécifiés par --open-files-limit, et n'affectent pas les opérations de cache.

- innodb_thread_concurrency
InnoDB essaie de garder le nombre de thread système concurrents inférieur à la limite de ce paramètre. La valeur par défaut est 8. Si vous avez des problèmes de performances, et que SHOW INNODB STATUS révèle que des threads attendent des sémaphores, essayez de diminuer ou augmenter ce paramètre. Si vous avez un serveur avec de nombreux processeurs et disques, vous pouvez essayer d'augmenter la valeur, pour utiliser au mieux les ressources disponibles. Une valeur recommandée est la somme du nombre de processeurs et de disques que vous avez. Une valeur de 500 ou supérieur, supprime la vérification de concurrence. Cette option a été ajoutée depuis MySQL 3.23.44 et 4.0.1.

15-F - Créer des bases InnoDB

Supposons que vous avez installé MySQL et que vous avez édité le fichier d'options de façon à ce qu'il contienne les paramètres de configuration nécessaires de InnoDB. Avant de démarrer MySQL, vous devez vérifier que les dossiers que vous avez spécifiés pour les fichiers de données InnoDB et les fichiers de logs existent, et que vous avez des accès suffisants dans ces dossiers. InnoDB ne peut pas créer de dossiers, uniquement des fichiers. Vérifiez aussi que vous avez assez d'espace disque pour les données et les logs.

Lorsque vous démarrez MySQL, InnoDB va commencer à créer vos fichiers de données et vos fichiers de logs. InnoDB va afficher ceci :

~/mysqlm/sql > mysqld
InnoDB: The first specified datafile /home/heikki/data/ibdata1
did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file /home/heikki/data/ibdata1 size to 134217728
InnoDB: Database physically writes the file full: wait...
InnoDB: datafile /home/heikki/data/ibdata2 did not exist:
new to be created
InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file /home/heikki/data/logs/ib_logfile0 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile2 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile2 size to 5242880
InnoDB: Started
mysqld: ready for connections

Une nouvelle base de données InnoDB a été créée. Vous pouvez vous connecter au serveur MySQL avec votre client MySQL habituel, comme mysql. Lorsque vous arrêtez le serveur MySQL avec mysqladmin shutdown, InnoDB va afficher :

010321 18:33:34  mysqld: Normal shutdown
010321 18:33:34  mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed

Vous pouvez observer vos fichiers de données et de logs, et vous apercevrez les fichiers créés. Le dossier de log va aussi contenir un petit fichier appelé ib_arch_log_0000000000. Ce fichier est le résultat de la création de base, à partir duquel InnoDB a désactivé l'archivage des logs. Lorsque MySQL va être redémarré, l'affichage sera :

~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections

15-F-1 - Si quelque chose se passe mal à la création de la base de données

Si InnoDB renvoie une erreur de système d'exploitation lors d'une opération sur fichier, habituellement le problème est l'un des suivants.

- Vous n'avez pas créé les dossiers de données ou de logs InnoDB.

- mysqld n'a pas le droit de créer des fichiers dans ces dossiers.

- mysqld ne lit pas le bon fichier my.cnf ou my.ini, et donc ne voit pas les options que vous spécifiez.

- Le disque ou l'espace disque alloué est plein.

- Vous avez créé un sous-dossier dont le nom est le même que celui d'un fichier de données que vous avez spécifié.

- Il y a une erreur de syntaxe dans innodb_data_home_dir ou innodb_data_file_path.

Si quelque chose se passe mal lors de la création d'une base de données InnoDB, vous devez effacer tous les fichiers créés par InnoDB. Cela inclut tous les fichiers de données, tous les journaux, les archives. Dans le cas où vous avez déjà créé des tables InnoDB, effacez aussi les fichiers .frm (et tous les fichiers .ibd si vous utilisez les espaces de tables multiples) concernés dans le dossier de données de MySQL. Vous pourrez alors essayer une nouvelle création de base de données InnoDB.

15-G - Créer des tables InnoDB

Supposons que vous avez démarré le client MySQL avec la commande mysql test. Pour créer une table au format InnoDB vous devez spécifier le type TYPE = InnoDB lors de la création de table, dans la commande SQL :

CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) TYPE = InnoDB;

Cette commande SQL va créer une table et un index sur la colonne A dans la base InnoDB constituée par les fichiers de données que vous avez spécifiés dans le fichier de configuration my.cnf. De plus, MySQL va créer un fichier CUSTOMER.frm dans le dossier de données de MySQL test. En interne, InnoDB va ajouter une entrée dans son propre dictionnaire de données, une entrée pour la table 'test/CUSTOMER'. De cette façon, vous pouvez créer plusieurs tables avec le même nom de CUSTOMER, mais dans d'autres bases MySQL, et les noms ne seront pas en conflit avec InnoDB.

Vous pouvez demander la quantité d'espace disponible dans l'espace de tables InnoDB avec la commande de statut de MySQL pour toutes les tables de type TYPE = InnoDB. La quantité d'espace disponible apparaît dans la section de commentaire de la commande SHOW. Par exemple :

SHOW TABLE STATUS FROM test LIKE 'CUSTOMER'

Notez que les statistiques que SHOW vous donne sur les tables InnoDB ne sont que des approximations : elles sont utilisées pour les optimisations SQL par MySQL. Les tailles réservées d'index et de table, exprimées en octets, sont précises.

15-G-1 - Comment utiliser les transactions de InnoDB avec différentes API

Par défaut, chaque client qui se connecte à MySQL commence avec le mode d'autovalidation activé, ce qui valide automatiquement toutes les requêtes que vous soumettez. Pour utiliser des requêtes multicommandes, vous pouvez désactiver l'autovalidation avec la commande SET AUTOCOMMIT = 0 et utiliser les commandes COMMIT et ROLLBACK pour valider ou annuler vos transactions. Si vous voulez laisser le mode d'autovalidation tranquille, vous pouvez placer vos commandes entre START TRANSACTION et COMMIT ou ROLLBACK. Avant MySQL 4.0.11, vous deviez utiliser la commande BEGIN au lieu de START TRANSACTION. L'exemple suivant montre deux transactions. La première est validée, et la seconde est annulée.

shell> mysql test
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5 to server version: 3.23.50-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A))
-> TYPE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO CUSTOMER VALUES (10, 'Heikki');
Query OK, 1 row affected (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SET AUTOCOMMIT=0;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO CUSTOMER VALUES (15, 'John');
Query OK, 1 row affected (0.00 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM CUSTOMER;
+------+--------+
| A    | B      |
+------+--------+
|   10 | Heikki |
+------+--------+
1 row in set (0.00 sec)
mysql>

Avec des interfaces comme PHP, Perl DBI/DBD, JDBC, ODBC ou l'interface C, vous pouvez envoyer des commandes de contrôle de transaction comme COMMIT au serveur sous la forme de chaîne, tout comme une autre commande SELECT et INSERT. Certaines interfaces proposent des fonctions spécifiques pour les validations et annulations de transactions.

15-G-2 - Convertir des tables MyISAM vers InnoDB

Important : vous ne devez pas convertir les tables de la base mysql, telles que user ou host en type InnoDB. Ces tables doivent conserver le moteur MyISAM.

Si vous voulez que toutes les tables non-système soient créées directement en MySQL, depuis MySQL 3.23.43, ajoutez la ligne default-table-type=innodb dans la section [mysqld] de votre fichier my.cnf ou my.ini.

InnoDB n'a pas d'optimisation particulière pour séparer la création d'index. Par conséquent, cela ne sert à rien d'exporter et de réimporter les données de la table pour créer les index après. Le moyen le plus rapide pour mettre la table au format InnoDB est d'insérer directement les lignes dans une table InnoDB, c'est-à-dire, utiliser ALTER TABLE ... TYPE=INNODB, ou créer une table InnoDB vide, avec la même définition et de faire l'insertion de toutes les lignes avec INSERT INTO ... SELECT * FROM ....

Si vous avez une contrainte UNIQUE sur des clés secondaires, depuis MySQL 3.23.52, vous pouvez accélérer l'importation dans les tables en désactivant la vérification de cette contrainte durant l'insertion : SET UNIQUE_CHECKS=0; Pour les grosses tables, cela économise beaucoup d'accès disques, car InnoDB peut alors utiliser un buffer d'insertion pour écrire les lignes par bloc.

Pour avoir un meilleur contrôle sur le processus d'insertion, il est mieux de faire les insertions des grosses tables par blocs :

INSERT INTO newtable SELECT * FROM oldtable
WHERE yourkey > something AND yourkey <= somethingelse;

Une fois que toutes les données ont été insérées dans la table, vous pouvez la renommer.

Durant la conversion des grosses tables, vous pouvez donner à InnoDB un gros buffer pour réduire les accès disques. Ne le portez pas au-delà de 80 % de votre mémoire physique. Donnez aussi de gros fichiers de logs, et un buffer de log important.

Assurez-vous que vous n'allez pas manquer d'espace : les tables InnoDB prennent beaucoup plus d'espace que les tables MyISAM. Si la commande ALTER TABLE manque d'espace, elle va lancer une annulation, et cela peut prendre des heures sur un disque plein. Durant les insertions, InnoDB utilise un buffer d'insertion pour rassembler les lignes d'index secondaires avec les index, en groupe. Cela économise beaucoup d'accès disques. Durant l'annulation, ce mécanisme n'est pas utilisé, et elle peut prendre jusqu'à 30 fois plus de temps.

Dans le cas d'une annulation immensément longue, si vous n'avez pas de données critiques dans votre base, il est mieux de tuer le processus, d'effacer tous les fichiers, et de recommencer, plutôt que d'attendre la fin de l'annulation. Pour la procédure complète, voyez Section 15.9.1, « Forcer la restauration ».

15-G-3 - Comment les colonnes AUTO_INCREMENT fonctionnent avec InnoDB

Si vous spécifiez une colonne AUTO_INCREMENT dans une table, la table InnoDB va ajouter dans le dictionnaire de données un compteur spécial appelé le compteur autoincrément, qui est utilisé pour assigner les nouvelles valeurs de la colonne. Le compteur est stocké uniquement en mémoire, et non pas sur le disque.

InnoDB utilise l'algorithme suivant pour initialiser le compteur autoincrément pour la table T qui contient la colonne de type AUTO_INCREMENT appelée ai_col : après le démarrage du serveur, lorsqu'un utilisateur fait une insertion dans la table T, InnoDB exécute la commande suivante :

SELECT MAX(ai_col) FROM T FOR UPDATE;

La valeur lue par la commande est incrémentée d'une unité, et assignée à la colonne autoincrément et au compteur de table. Si la table est vide, la valeur de 1 est assignée. Si le compteur n'est pas initialisé et que l'utilisateur appelle la commande SHOW TABLE STATUS qui affiche les informations de la table T, le compteur est initialisé mais pas incrémenté, et stocké pour être utilisé ultérieurement. Notez que dans cette initialisation, nous posons un verrou exclusif en lecture sur la table, et le verrou durera jusqu'à la fin de la transaction.

InnoDB suit la même procédure pour initialiser un compteur autoincrément avec une table fraîchement créée.

Notez que si l'utilisateur spécifie la valeur NULL ou 0 pour la colonne AUTO_INCREMENT dans la commande INSERT, InnoDB traitera la ligne comme si aucune valeur n'avait été spécifiée, et générera une nouvelle valeur.

Après l'initialisation du compteur d'autoincrémentation, si un utilisateur insère une ligne qui définit explicitement la valeur de la colonne, et que cette valeur est plus grande que la valeur courante du compteur, le compteur prend alors cette valeur. Si l'utilisateur ne spécifie pas de valeur, InnoDB incrémente le compteur d'une unité, et assigne une nouvelle valeur à cette colonne.

Lorsque vous accédez au compteur d'autoincrémentation, InnoDB utilise un verrou de table spécial, AUTO-INC, qui reste actif jusqu'à la fin de la commande SQL, et non pas la fin de la transaction. Le verrou spécial a été créé pour éviter les accès concurrents dans la table qui contient la colonne AUTO_INCREMENT. Deux transactions ne peuvent pas avoir le même verrou AUTO-INC simultanément.

Notez que vous pourriez voir des trous dans la séquence de valeur générée par AUTO_INCREMENT si vous annulez des transactions après avoir obtenu une valeur automatiquement.

Le comportement du mécanisme autoincrément n'est pas défini si vous assignez une valeur négative à la colonne, ou si cette dernière dépasse la capacité de la colonne.

15-G-4 - Contraintes de clés étrangères FOREIGN KEY

Depuis la version 3.23.43b, InnoDB respecte les contraintes de clés étrangères.

La syntaxe des définitions de contraintes de clés étrangères de InnoDB est la suivante :

[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]

Les deux tables doivent être de type InnoDB, dans la table, il doit y avoir un INDEX où les clés étrangères sont listées comme première colonne, dans le même ordre, et dans la table référencée, il doit y avoir un INDEX où les colonnes référencées sont listées comme premières colonnes, dans le même ordre. Les préfixes d'index ne sont pas supportés pour les clés de contrainte.

InnoDB ne crée pas automatiquement les index nécessaires pour les clés étrangères : vous devez les créer vous-même. Les index sont nécessaires pour accélérer les vérifications de contrainte, et éviter un scan de table.

Les colonnes correspondantes de la contrainte dans la table et la table de référence doivent avoir le même type, pour éviter les conversions lors des comparaisons. La taille et la présence du signe pour les entiers doivent être les mêmes. La taille des chaînes doit être la même. Si vous spécifiez une action SET NULL, assurez-vous que vous n'avez pas déclaré les colonnes de la table fille NOT NULL.

Si MySQL vous retourne un numéro d'erreur 1005 lors de la commande CREATE TABLE, et un message d'erreur de numéro 150, alors la création de la table a échoué à cause de la contrainte de clé étrangère, qui n'a pas été correctement formulée. Similairement, si une commande ALTER TABLE échoue et indique une erreur 150, c'est que la définition de la clé étrangère est incorrectement formulée dans la table modifiée. Depuis la version 4.0.13, vous pouvez utiliser la commande SHOW INNODB STATUS pour avoir une explication détaillée de la dernière erreur de clé étrangère InnoDB sur le serveur.

Depuis la version 3.23.50, InnoDB ne vérifie pas la clé étrangère pour les clés étrangères ou les clés référencées qui contiennent des valeurs NULL.

Une entorse aux standards : si dans la table parente, il y a plusieurs lignes qui ont la même valeur de clé référencée, alors InnoDB effectue les vérifications de clé étrangères comme si les autres parents avec la même valeur de clé n'existaient pas. Par exemple, si vous avez défini une contrainte de type RESTRICT et qu'il y a une ligne fille avec plusieurs lignes parentes, InnoDB n'acceptera pas l'effacement d'aucun des parents.

Depuis la version 3.23.50, vous pouvez aussi associer la clause ON DELETE CASCADE ou ON DELETE SET NULL avec la contrainte de clé étrangère. Les options correspondantes ON UPDATE sont disponibles depuis la version 4.0.8. Si ON DELETE CASCADE est spécifiée, et qu'une ligne de la table parente est effacée, alors InnoDB va automatiquement effacer toutes les lignes qui sont dans la table fille et dont les valeurs de clé étrangère sont celles référencées dans la ligne parente. Si ON DELETE SET NULL est spécifiée, les lignes filles sont automatiquement modifiées pour que la colonne de la clé étrangère prenne la valeur de NULL.

Une entorse aux standards : si ON UPDATE CASCADE ou ON UPDATE SET NULL cascade récursivement jusqu'à la même table, elle agira comme pour un RESTRICT. Cela est fait pour éviter les boucles infinies des modifications en cascade. Une clause ON DELETE SET NULL autoréférente, d'un autre côté, fonctionne depuis la version 4.0.13. La clause ON DELETE CASCADE autoréférente a toujours fonctionné.

Un exemple :

CREATE TABLE parent(id INT NOT NULL,
PRIMARY KEY (id)
) TYPE=INNODB;
CREATE TABLE child(id INT, parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE
) TYPE=INNODB;

Voici un exemple plus complexe où la table product_order a des clés étrangères sur deux tables. La première clé est un index à deux colonnes, dans la table product. Les autres clés sont monocolonnes, dans la table customer :

CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
price DECIMAL,
PRIMARY KEY(category, id)) TYPE=INNODB;
CREATE TABLE customer (id INT NOT NULL,
PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,
product_category INT NOT NULL,
product_id INT NOT NULL,
customer_id INT NOT NULL,
PRIMARY KEY(no),
INDEX (product_category, product_id),
FOREIGN KEY (product_category, product_id)
REFERENCES product(category, id)
ON UPDATE CASCADE ON DELETE RESTRICT,
INDEX (customer_id),
FOREIGN KEY (customer_id)
REFERENCES customer(id)) TYPE=INNODB;

Depuis la version 3.23.50, InnoDB vous permet d'ajouter une nouvelle clé à une table, grâce à la syntaxe

ALTER TABLE yourtablename
ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]

N'oubliez pas de commencer par créer les index nécessaires en premier !. Vous pouvez aussi ajouter des clés étrangères réflexives, en utilisant la commande ALTER TABLE.

Depuis la version 4.0.13, InnoDB supporte la syntaxe ALTER TABLE pour supprimer une clé étrangère :

ALTER TABLE yourtablename
DROP FOREIGN KEY fk_symbol

Si la clause FOREIGN KEY inclut un nom de contrainte CONSTRAINT lors de la création, vous pouvez utiliser ce nom pour effacer la clé. Les contraintes peuvent porter un nom depuis MySQL 4.0.18. Sinon, la valeur fk_symbol est générée en interne par InnoDB lorsque la clé étrangère est créée. Pour savoir quel symbole utiliser pour effacer une clé étrangère, utilisez la commande SHOW CREATE TABLE. Par exemple :

mysql> SHOW CREATE TABLE ibtest11c\G
*************************** 1. row ***************************
Table: ibtest11c
Create Table: CREATE TABLE `ibtest11c` (
`A` int(11) NOT NULL auto_increment,
`D` int(11) NOT NULL default '0',
`B` varchar(200) NOT NULL default '',
`C` varchar(175) default NULL,
PRIMARY KEY  (`A`,`D`,`B`),
KEY `B` (`B`,`C`),
KEY `C` (`C`),
CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`)
REFERENCES `ibtest11a` (`A`, `D`)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`)
REFERENCES `ibtest11a` (`B`, `C`)
ON DELETE CASCADE ON UPDATE CASCADE
) TYPE=InnoDB CHARSET=latin1
1 row in set (0.01 sec)

mysql> ALTER TABLE ibtest11c DROP FOREIGN KEY 0_38775;

Depuis MySQL version 3.23.50, l'analyseur InnoDB autorise l'utilisation des guillemets obliques autour des noms de tables et colonnes dans une clause FOREIGN KEY ... REFERENCES .... Depuis MySQL 4.0.5, l'analyseur InnoDB prend aussi en compte la variable système lower_case_table_names.

Dans InnoDB en versions < 3.23.50, ALTER TABLE et CREATE INDEX ne doivent pas être utilisés avec des tables qui ont des contraintes de clés étrangères, ou qui sont référencées dans des clés étrangères : une commande ALTER TABLE supprime toutes les clés étrangères qui sont définies pour cette table. Vous ne devriez pas utiliser ALTER TABLE sur la table référencée, mais utiliser DROP TABLE puis CREATE TABLE pour modifier le schéma. Lorsque MySQL exécute la commande ALTER TABLE, il risque d'utiliser en interne la commande RENAME TABLE, et cela va poser des problèmes pour les clés étrangères qui reposent sur cette table. Une commande CREATE INDEX est traitée par MySQL comme une commande ALTER TABLE, et ces restrictions s'appliquent aussi.

Lorsqu'il vérifie les clés étrangères, InnoDB pose des verrous de lignes partagées sur les lignes des tables qu'il utilise. InnoDB vérifie immédiatement les contraintes de clés étrangères : la vérification n'attend pas la validation de la transaction.

Si vous voulez ignorer les contraintes de clés étrangères durant, par exemple, une opération de LOAD DATA, vous pouvez utiliser la commande SET FOREIGN_KEY_CHECKS=0.

InnoDB vous permet d'effacer n'importe quelle table, même si cela va casser les contraintes de clés étrangères qui référencent cette table. Lorsque vous supprimez une table, la contrainte de clé étrangère qui y était attachée est aussi supprimée.

Si vous recréez une table qui a été supprimée, sa définition doit se conformer aux contraintes des clés étrangères qui la référencent. Elle doit avoir les bons types et noms de colonnes, et doit avoir les bonnes clés, comme indiqué ci-dessus. Si ces contraintes ne sont pas vérifiées, MySQL vous gratifiera d'une erreur 1005, et vous enverra lire le message numéro 150.

Depuis la version 3.23.50 InnoDB retourne la définition de clé étrangère lorsque vous utilisez la commande

SHOW CREATE TABLE tbl_name;

De plus, mysqldump produit aussi les définitions correctes de tables, sans oublier les clés étrangères.

Vous pouvez aussi lister les clés étrangères d'une table T avec

SHOW TABLE STATUS FROM db_name LIKE 'tbl_name'

Les contraintes de clés étrangères sont listées dans les commentaires de la table.

Lors des vérifications des contraintes, InnoDB pose des verrous de lignes sur les lignes parents ou enfants qu'il utilise. InnoDB vérifie immédiatement les contraintes de clés : la vérification n'est pas reportée jusqu'à la validation de la transaction.

Pour simplifier l'importation de données dans des tables qui ont des contraintes, mysqldump ajoute automatiquement la commande qui met la variable FOREIGN_KEY_CHECKS à 0, depuis MySQL version 4.1.1. Cela évite des problèmes spécifiques avec les tables qui doivent être chargées dans un ordre particulier. Pour les versions antérieures, vous pouvez désactiver manuellement la variable depuis mysql lors du chargement du fichier comme ceci :

mysql> SET FOREIGN_KEY_CHECKS = 0;
mysql> SOURCE dump_file_name;
mysql> SET FOREIGN_KEY_CHECKS = 1;

Cela vous permet de faire l'importation des données des tables dans n'importe quel ordre. Cela accélère aussi l'opération d'importation. FOREIGN_KEY_CHECKS est disponible depuis MySQL 3.23.52 et 4.0.3.

Mettre FOREIGN_KEY_CHECKS à 0 peut aussi être utile pour les opérations de LOAD DATA.

InnoDB permet l'effacement de n'importe quelle table, même si cela casse les contraintes de clés étrangères. Lorsque vous effacez une table, les contraintes définies sur cette table sont aussi effacées.

Si vous recréez une table qui a été effacée, elle doit avoir une définition qui est compatible avec les clés étrangères qui l'utilise. Elle doit avoir les bonnes colonnes et les index. Si cela n'est pas vrai, MySQL retourne une erreur 1005, et fait référence à un message d'erreur numéro 150.

15-G-5 - InnoDB et la réplication MySQL

La réplication MySQL fonctionne pour les tables InnoDB comme pour les tables MyISAM. Il est aussi possible d'utiliser la réplication pour que les tables de l'esclave ne soient pas les mêmes que les tables du maître. Par exemple, vous pouvez répliquer les modifications d'une table InnoDB sur le maître dans une table MyISAM sur l'esclave.

Pour configurer un nouvel esclave sur le maître, vous devez faire une copie de l'espace de table InnoDB, des fichiers de logs, ainsi que les fichiers .frm des tables InnoDB, et les placer sur l'esclave. Pour une procédure à suivre pour réaliser cela, voyez Section 15.10, « Transférer une base de données InnoDB vers une autre machine ».

Si vous pouvez arrêter le maître ou l'esclave, faites une sauvegarde à l'arrêt de l'espace de table InnoDB et des fichiers de logs, puis utilisez-les pour redémarrer l'esclave. Pour faire un nouvel esclave sans arrêter le serveur, utilisez le logiciel commercial InnoDB Hot Backup tool.

Il y a des limitations mineures à la réplication InnoDB :

- LOAD TABLE FROM MASTER ne fonctionne pas pour les tables InnoDB. Il y a des palliatifs : 1) exportez la table du maître, et envoyez-la sur l'esclave, ou, 2) utilisez ALTER TABLE tbl_name TYPE=MyISAM sur le maître avant de configurer la réplication avec LOAD TABLE tbl_name FROM MASTER, et ensuite, ALTER TABLE pour remettre les tables en mode InnoDB après cela.

- Avant MySQL 4.0.6, SLAVE STOP ne respectait pas la limite de transaction. Une transaction incomplète était annulée, et la prochaine commande SLAVE START n'exécutait que le reste de la transaction, ce qui conduisait à un échec.

- Avant MySQL 4.0.6, un crash de l'esclave au milieu d'une transaction multicommande causait le même problème que SLAVE STOP.

- Avant MySQL 4.0.11, la réplication de la commande SET FOREIGN_KEY_CHECKS=0 ne fonctionnait pas correctement.

La plupart de ces limitations peuvent être levées en utilisant un serveur récent, pour lequel les limitations n'existent pas.

Les transactions qui échouent sur le serveur n'affectent pas la réplication. La réplication MySQL est basée sur le log binaire où MySQL écrit les requêtes SQL qui modifient des données. Un esclave lit le log binaire du maître, et exécute les mêmes commandes SQLO. Cependant, les commandes d'une transaction ne sont pas écrites avant la fin de la transaction, où toutes les commandes sont écrites d'un coup. Si une transaction échoue, par exemple, à cause d'une clé étrangère, ou si la transaction est annulée, aucune requête ne sera écrite dans le log binaire, et la transaction ne sera pas du tout exécutée sur le serveur.

15-G-6 - Espaces de tables multiples : chaque table InnoDB a son fichier .ibd

Depuis MySQL 4.1.1, vous pouvez stocker chaque table InnoDB et ses index dans son propre fichier. Cette fonctionnalité est appelée « espaces de tables multiples », car chaque table dispose de son propre espace de table.

Note importante : si vous passez en version InnoDB 4.1.1 ou plus récent, il devient très difficile de retourner en versions 4.0 ou 4.1.0 ! Ceci est dû au fait que les versions antérieures de InnoDB ne sont pas compatibles avec les espaces de tables multiples.

Si vous devez revenir à une vieille version 4.0, vous devez faire des exports des tables, et recréer tout votre espace de tables InnoDB. Si vous n'avez pas créé de nouvelles tables sous InnoDB >= 4.1.1, et que vous devez revenir rapidement en arrière, vous pouvez passer directement en versions 4.0.18, ou plus récent. Avant de faire un retour en arrière direct en versions 4.0, vous devez terminer toutes les connexions, et laisser mysqld vider les buffers d'insertion, jusqu'à ce que SHOW INNODB STATUS indique que le thread principal soit dans un état de waiting for server activity. Alors, vous pouvez éteindre le serveur mysqld et démarrer votre version 4.0.18 ou plus récent. Un retour en arrière direct n'est pas recommandé, car il n'a pas été totalement testé.

Depuis MySQL version 4.1.1, vous pouvez stocker chaque table InnoDB et ses index dans son propre fichier. Cette fonctionnalité est appelée espaces de tables multiples, car chaque table a son propre espace de table.

Vous pouvez activer cette fonctionnalité en ajoutant une ligne dans le groupe [mysqld] du fichier my.cnf :

[mysqld]
innodb_file_per_table

Après redémarrage du serveur, InnoDB va stocker chaque table dans son propre fichier tablename.ibd du dossier de données, où les tables sont stockées. C'est la même méthode que MyISAM, mais si MySQL divise les tables en un fichier de données et un fichier d'index, tablename.MYD et tablename.MYI, InnoDB place les données et les index dans le même fichier .ibd. Le fichier tbl_name.frm est toujours créé, comme d'habitude.

Si vous supprimez la ligne innodb_file_per_table du fichier my.cnf, alors InnoDB créera les tables dans le fichier de données.

innodb_file_per_table affecte seulement la création de tables. Si vous démarrez le serveur avec cette option, les nouvelles tables sont créées avec le fichier .ibd, mais vous pouvez toujours accéder aux tables qui existent dans l'espace de tables partagées ibdata. Si vous supprimez cette option, les nouvelles tables seront créées dans l'espace de tables, mais vous pouvez toujours accéder aux tables qui ont été créées indépendamment.

InnoDB a toujours besoin du système d'espace de tables, les fichiers .ibd ne sont pas suffisants. Le système d'espaces de tables est constitué des fichiers classiques ibdata. InnoDB y place son dictionnaire de données interne, et ses historiques d'annulation.

Vous ne pouvez pas déplacer les fichiers .ibd librement, comme vous pouvez le faire avec les tables MyISAM. Ceci est dû au fait que les définitions de tables sont stockées dans le système d'espace de tables InnoDB, et aussi, parce que InnoDB doit préserver la cohérence des identifiants de transactions et les numéros de séquence des logs.

Vous pouvez déplacer le fichier .ibd et la table associée d'une base à l'autre (dans la même installation MySQL/InnoDB) avec la commande classique RENAME :

RENAME TABLE old_db_name.tbl_name TO new_db_name.tbl_name;

Si vous avez une sauvegarde « propre » du fichier .ibd, vous pouvez restaurer l'installation MySQL comme ceci :

1. Utilisez cette commande ALTER TABLE :

ALTER TABLE tbl_name DISCARD TABLESPACE;

Attention : cette commande efface le fichier .ibd.

2. Placez le fichier de sauvegarde .ibd dans le bon dossier de base de données.

3. Utilisez cette commande ALTER TABLE :

ALTER TABLE tbl_name IMPORT TABLESPACE;

Dans ce contexte, un fichier .ibd « propre » signifie :

- Il n'y a pas de modifications non validées par des transactions dans le fichier .ibd file.

- Il n'y a pas de buffer d'insertion non intégrés dans le fichier .ibd.

- La purge a supprimé toutes les lignes marquées pour l'effacement dans le fichier .ibd.

- mysqld a envoyé toutes les pages modifiées au fichier .ibd depuis le buffer de fichier.

Vous pouvez faire une sauvegarde propre du fichier .ibd en suivant la méthode :

1. Cessez toute activité sur le serveur mysqld et validez toutes les transactions.

2. Attendez que SHOW INNODB STATUS\G indique qu'il n'y a plus de transaction active dans la base, et que le thread principal de InnoDB est dans l'état Waiting for server activity. Vous pouvez alors faire une copie du fichier .ibd.

Une autre méthode (non libre) de faire une sauvegarde propre du fichier .ibd est de :

1. Utilisez InnoDB Hot Backup pour faire une sauvegarde de votre installation InnoDB.

2. Lancez un second serveur mysqld sur la sauvegarde, et laissez-le nettoyer les fichiers .ibd de la sauvegarde.

La liste de tâches inclut la possibilité de déplacer les fichiers .ibd vers une autre installation MySQL/InnoDB. Cela impose la remise à zéro des numéros de transactions et des séquences de fichiers de logs du fichier .ibd.

15-H - Ajouter et retirer des données et des logs InnoDB

Cette section décrit ce que vous pouvez faire lorsque votre espace de tables InnoDB n'a plus d'espace, ou que vous voulez changer la taille des fichiers de logs.

Depuis la version 3.23.50 et 4.0.2, le moyen le plus facile pour augmenter la taille de l'espace de tables InnoDB est de le configurer immédiatement comme autocroissant. Spécifiez l'attribut autoextend pour le dernier fichier de données dans la définition de l'espace de tables. InnoDB va augmenter la taille du fichier automatiquement de 8 Mo dès qu'il n'a plus d'espace dans le fichier.

Alternativement, vous pouvez augmenter la taille de votre espace de tables en ajoutant un autre fichier de données. Pour cela, vous devez éteindre le serveur MySQL, éditer le fichier my.cnf pour ajouter votre nouveau fichier de données à la fin de la ligne innodb_data_file_path, et relancer le serveur MySQL.

Si votre dernier fichier a déjà été configuré avec le mot-clé autoextend, la procédure d'édition du fichier my.cnf doit prendre en compte la taille que le fichier occupe actuellement. Vous devez lire la taille du fichier, l'arrondir au mégaoctet inférieur le plus proche (1024 x 1024 octets), et spécifier la taille arrondie dans la ligne d'options innodb_data_file_path. Puis, vous pouvez ajouter un autre fichier de données. N'oubliez pas que seul le dernier fichier de données de la ligne innodb_data_file_path peut être spécifié comme autocroissant.

Par exemple, supposons que l'espace de tables dispose juste d'un fichier de données autocroissant, appelé ibdata1 :

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:10M:autoextend

Supposons qu'au cours du temps, le fichier a atteint la taille de 988 Mo. Ci-dessous, la ligne de configuration va ajouter un autre fichier autocroissant après celui qui existe.

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

Lorsque vous ajoutez un nouveau fichier de données, assurez-vous qu'il n'existe pas, pour que InnoDB puisse le créer et l'initialiser, lorsque vous redémarrerez le serveur.

Actuellement, vous ne pouvez pas supprimer de fichiers de données. Pour réduire la taille de votre espace de tables, utilisez cette procédure.

1. Utilisez mysqldump pour exporter toutes vos tables InnoDB.

2. Stoppez le serveur.

3. Supprimez tous les fichiers de tables existants.

4. Configurez un nouvel espace de tables.

5. Relancez le serveur.

6. Importez les fichiers de vos tables.

Si vous voulez changer le nombre ou la taille de vos fichiers de logs InnoDB, vous devez éteindre le serveur MYSQL et vous assurer qu'il s'est arrêté sans erreur. Puis, copiez les anciens fichiers de logs dans une archive, car si vous rencontrez un problème ultérieurement, vous en aurez besoin pour restaurer votre base. Effacez les anciens fichiers de logs du dossier de logs, éditez le fichier my.cnf, et redémarrez le serveur MySQL. InnoDB vous indiquera au démarrage qu'il va créer de nouveaux fichiers de logs.

15-I - Sauver et restaurer une base InnoDB

La clé d'une gestion prudente de votre serveur est la sauvegarde régulière des données.

InnoDB Hot Backup est un utilitaire de sauvegarde en ligne, qui vous permet de faire des sauvegardes pendant que InnoDB fonctionne. InnoDB Hot Backup ne vous impose pas l'arrêt de votre serveur, et il ne pose pas de verrous qui vont perturber le fonctionnement normal de votre serveur. InnoDB Hot Backup est un utilitaire propriétaire, qui n'est pas inclus dans la distribution MySQL. Voyez le site web de InnoDB Hot Backup : http://www.innodb.com/manual.php, pour plus d'informations.

Si vous pouvez arrêter votre serveur MySQL, alors faites une sauvegarde binaire de votre base comme ceci :

1. Arrêtez le serveur MySQL et assurez-vous qu'il s'est bien arrêté sans erreur.

2. Copiez tous les fichiers de données dans votre entrepôt.

3. Copiez tous les fichiers de logs InnoDB dans votre entrepôt.

4. Copiez vos fichiers de configuration my.cnf dans l'entrepôt.

5. Copiez tous les fichiers .frm de vos tables InnoDB dans votre entrepôt.

En plus de prendre des sauvegardes binaires comme décrit ci-dessus, vous devriez aussi prendre des exports de vos tables avec mysqldump. La raison à cela est que le fichier binaire peut être corrompu sans que vous vous en rendiez compte. Les tables exportées sont stockées sous forme de fichier texte, lisible à l'œil, et bien plus simple à sauver que les fichiers binaires. Repérer la corruption d'une table dans les fichiers exportés est bien plus facile, et comme le format est bien plus simple, il y a moins de chances que les données soient corrompues.

En fait, c'est une bonne idée que de faire une exportation des tables au moment où vous sauvez les fichiers binaires des bases. Vous devez arrêter tous les clients qui utilisent le serveur. Puis, vous pouvez faire la sauvegarde binaire et l'export : vous aurez ainsi une archive cohérente en deux formats.

Pour restaurer une base InnoDB à partir d'une sauvegarde binaire, vous devez utiliser le serveur MySQL avec les logs général et d'archive activés. Par log général, nous entendons le log de MySQL, et non pas le log spécifique d'InnoDB.

mysqlbinlog yourhostname-bin.123 | mysql

Pour restaurer les données après un crash MySQL, la seule chose à faire est de relancer le serveur. InnoDB va automatiquement vérifier les historiques, et reprendre toutes les opérations qui ont eu lieu jusqu'à présent. InnoDB va automatiquement annuler les transactions qui n'ont pas été achevées. Durant la restauration, InnoDB va afficher des séquences semblables à celle-ci :

~/mysqlm/sql > mysqld
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections

Si votre base ou vos disques se corrompent, vous devez faire la restauration à partir de sauvegardes. En cas de corruption, vous devriez trouver une sauvegarde qui n'est pas corrompue. À partir de la sauvegarde, faites une restauration à partir des fichiers de logs généraux, en suivant les instructions du manuel.

15-I-1 - Forcer la restauration

S'il survient une corruption de base de données, vous souhaiterez exporter vos tables de la base avec SELECT INTO OUTFILE, et généralement, la plupart des données seront intactes et correctes. Mais la correction peut faire que SELECT * FROM table ou une opération en tâche de fond d'InnoDB crashe, ou même, que le processus de récupération de InnoDB crashe. Depuis InnoDB version 3.23.44, il y a une option du fichier d'options qui vous permet de forcer InnoDB à démarrer, et vous permet d'éviter le lancement des opérations en tâche de fond, pour que vous puissiez exporter vos tables. Par exemple, vous pouvez configurer :

[mysqld]
innodb_force_recovery = 4

Avant MySQL 4.0, utilisez cette syntaxe :

[mysqld]
set-variable = innodb_force_recovery=4

Les autres possibilités pour innodb_force_recovery sont listées ci-dessous. La base ne doit pas être utilisée lorsque vous utilisez ces options. Comme mesure de sécurité, InnoDB empêchera un utilisateur de faire des commandes INSERT, UPDATE et DELETE lorsque cette option est supérieure à 0.

Depuis la version 3.23.53 et 4.0.4, vous êtes autorisés à utiliser les commandes DROP et CREATE sur une table, même si la restauration forcée est active. Si vous savez qu'une table particulière vous pose des problèmes, vous pouvez l'effacer. Vous pouvez aussi utiliser cette commande pour stopper une annulation sauvage, qui serait causée par des importations de masse ou ALTER TABLE. Vous pouvez tuer le processus mysqld et utiliser l'option innodb_force_recovery=3 pour relancer votre base sans l'annulation. Alors, la suppression de la table avec DROP vous aidera.

Un nombre plus grand signifie que toutes les précautions des nombres inférieurs sont incluses. Si vous êtes capables d'exporter vos tables avec une option au maximum de 4, alors vous êtes sûr que très peu de données sont perdues. L'option 6 est plus dramatique, car les pages de la base de données sont laissées dans un état obsolète, et cela va introduire encore plus de corruption dans les arbres B-tree et les structures de la base.

- 1 (SRV_FORCE_IGNORE_CORRUPT) laisse le serveur fonctionner même s'il détecte une page corrompue. Essaie d'éviter les index et pages avec SELECT * FROM table, ce qui aide à l'export.

- 2 (SRV_FORCE_NO_BACKGROUND) empêche le thread principal de fonctionner. Si un crash survenait durant la purge, cela l'évitera.

- 3 (SRV_FORCE_NO_TRX_UNDO) ne lance pas les annulations de transactions après la restauration.

- 4 (SRV_FORCE_NO_IBUF_MERGE) empêche les opérations de vidange du buffer d'insertion. Si ce sont eux qui causent le crash, il vaut mieux les ignorer. Ne recalcule pas les statistiques de tables.

- 5 (SRV_FORCE_NO_UNDO_LOG_SCAN) ne regarde pas les logs d'annulations lors du lancement de la base. InnoDB va traiter les transactions, même incomplètes, comme validées.

- 6 (SRV_FORCE_NO_LOG_REDO) ne lance pas le rattrapage des opérations avec le log, après la restauration.

15-I-2 - Points de contrôle

InnoDB utilise un mécanisme de contrôle appelé points de contrôle flou. InnoDB va écrire des blocs de données modifiées depuis un buffer vers le disque par petits paquets : il n'y a pas besoin de tout écrire en une seule fois, ce qui en général, conduit à l'arrêt du traitement des autres instructions pour quelques instants.

Durant une restauration de base, InnoDB recherche un point de contrôle écrit dans les fichiers de logs. Il sait que toutes les modifications de la base placées avant ce point de contrôle sont aussi présentes sur le disque de la base. Puis, InnoDB analyse le fichier de logs, et applique les modifications qui ont eu lieu depuis le point de contrôle.

InnoDB écrit dans les fichiers de logs en mode circulaire. Toutes les modifications validées qui font que le buffer de MySQL est différent de la version sur le disque doivent être disponibles dans les fichiers de logs, au cas où InnoDB en aurait besoin pour une restauration. Cela signifie que lorsque InnoDB commence à réutiliser le fichier d'historique, il doit commencer par s'assurer que le disque a reçu les modifications qui sont dans le buffer. En d'autres termes, InnoDB doit placer un point de contrôle, et souvent, cela se traduit par l'écriture de données du buffer sur le disque.

Ceci explique pourquoi utiliser de grands fichiers de logs peut éviter des accès disques pour les points de contrôle. Il est recommandé d'utiliser une taille de fichier d'historique aussi grande que le buffer, voire même plus grande. L'inconvénient des grands fichiers est que la restauration dure alors plus longtemps, puisqu'il y a plus de modifications à appliquer.

15-J - Transférer une base de données InnoDB vers une autre machine

Sur Windows, InnoDB stocke les noms de bases et de tables en interne, et toujours en minuscules. Pour déplacer des bases au format binaire, entre Unix et Windows, ou le contraire, vous devez donner des noms en minuscules à toutes vos bases et tables. Un moyen simple de faire cela sous Unix est d'ajouter la ligne suivante dans la section [mysqld] de votre fichier d'options my.cnf avant de démarrer la création de tables.

set-variable=lower_case_table_names=1

Sous Windows, cette option vaut 1 par défaut.

Les fichiers de données et de logs de InnoDB sont compatibles en mode binaire sur toutes les plates-formes si le format des nombres à virgule flottante est le même. Vous pouvez déplacer une base de données InnoDB en copiant tous les fichiers concernés, que nous avons déjà listés dans la section Section 15.9, « Sauver et restaurer une base InnoDB ». Si les formats des nombres à virgules flottantes sont différents, mais que vous n'avez pas utilisé les types de données FLOAT ou DOUBLE dans vos tables alors la procédure est là même : copiez juste les fichiers concernés. Si les formats sont différents et que vous utilisez de tels types de données, vous devez utiliser mysqldump et mysqlimport pour transférer les tables.

Un bon moyen d'avoir de bonnes performances est de couper le mode autocommit quand vous importez des données dans votre base de données, en supposant que votre espace de tables possède assez d'espace pour la grande partie d'annulations (rollback) que la grande transaction importée génère. Ne faites le commit qu'après avoir importé une table entière, ou un segment de table.

15-K - Modèle de transactions et verrouillage InnoDB

Le modèle transactionnel d'InnoDB a pour but de combiner les avantages des bases de données multiversions aux verrouillages traditionnels en deux phases. InnoDB fait un verrouillage de ligne, et exécute les requêtes par défaut avec des lectures cohérentes non bloquantes, de la même façon qu'Oracle. Les verrous InnoDB sont stockés de manière efficace, pour que l'escalade de transaction ne soit pas nécessaire : typiquement, plusieurs utilisateurs sont autorisés à verrouiller toutes les lignes dans une base, ou un sous-ensemble aléatoire de lignes, sans que InnoDB ne soit à court de mémoire.

15-K-1 - InnoDB et AUTOCOMMIT

Avec InnoDB, toutes les opérations sont placées dans une transaction. Si le mode d'autovalidation est activé, chaque commande SQL est une transaction à part entière. MySQL démarre toujours une nouvelle transaction lorsque le mode d'autovalidation est activé.

Si l'autovalidation est désactivée avec SET AUTOCOMMIT = 0, alors nous pouvons considérer qu'une transaction est toujours commencée. Une commande SQL COMMIT ou ROLLBACK termine la transaction courante et en commence une autre. Ces deux commandes vont libérer tous les verrous InnoDB qui étaient posés durant la transaction. Un COMMIT signifie que les modifications durant la transaction seront enregistrées, et rendues visibles aux autres. Un ROLLBACK, d'un autre côté, annule toutes les modifications.

Si la connexion a activé l'autovalidation, l'utilisateur peut faire une transaction multicommande en commençant la transaction avec la commande START TRANSACTION ou BEGIN et en la terminant avec COMMIT ou ROLLBACK.

15-K-2 - InnoDB et SET ... TRANSACTION ISOLATION LEVEL ...

En termes de niveau d'isolation des transactions SQL-92, le comportement par défaut de InnoDB est REPEATABLE READ. Depuis la version 4.0.5, InnoDB offre quatre niveaux différents d'isolation de transactions, tels que décrit dans la norme SQL-92. Vous pouvez configurer le niveau d'isolation par défaut dans le groupe [mysqld] du fichier my.cnf:

transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED
| REPEATABLE-READ | SERIALIZABLE}

Un utilisateur peut changer le niveau d'isolation d'une session ou des nouvelles connexions avec la commande SET TRANSACTION. La syntaxe est la suivante :

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED
| REPEATABLE READ | SERIALIZABLE}

Notez qu'il n'y a pas de tiret dans les noms de niveaux de la syntaxe SQL.

Le comportement par défaut est de configurer le niveau d'isolation de la prochaine transaction non démarrée. Si vous utilisez le mot-clé GLOBAL, la commande configure le niveau d'isolation globalement, pour toutes les nouvelles connexions, mais pas pour les connexions existantes. Vous devez avoir les droits de SUPER pour faire cela. En utilisant le mot-clé SESSION, vous allez configurer le niveau d'isolation des prochaines transactions de la session courante. Tous les clients sont autorisés à changer le niveau d'isolation de la session, même au milieu d'une transaction, ainsi que le niveau d'isolation de la prochaine transaction. Dans les versions 3.23.50 et plus anciennes, SET TRANSACTION n'avait pas d'effet sur les tables InnoDB. Dans les versions < 4.0.5, seules REPEATABLE READ et SERIALIZABLE étaient disponibles.

Vous pouvez connaître les niveaux d'isolation de transaction de session et global avec ces commandes :

SELECT @@global.tx_isolation;
SELECT @@tx_isolation;

Pour le verrouillage de ligne, InnoDB utilise le système dit de verrouillage de la prochaine clé. Cela signifie qu'en plus des lignes d'index, InnoDB peut aussi verrouiller le « trou » après une ligne d'index pour éviter les insertions des autres utilisateurs. Un verrou de prochaine clé représente un verrou qui bloque la ligne d'index et le trou qui le précède. Un verrou de trou représente un verrou qui ne bloque que le trou avant la ligne.

Voici une description détaillée de chaque niveau d'isolation de InnoDB :

- READ UNCOMMITTED aussi appelé « dirty read » : les commandes SELECT non verrouillantes sont effectuées sans rechercher de versions plus récentes de la ligne. Elles sont donc non cohérentes, sous ce niveau d'isolation. Sinon, ce niveau fonctionne comme le niveau READ COMMITTED.

- READ COMMITTED Proche du niveau d'isolation d'Oracle. Toutes les commandes SELECT ... FOR UPDATE et SELECT ... LOCK IN SHARE MODE ne verrouillent que les lignes d'index, et non pas les trous entre elles, ce qui permet l'insertion de nouvelles lignes, adjacentes aux lignes verrouillées. UPDATE et DELETE qui utilisent un seul index avec une condition de recherche unique ne verrouillent que la ligne d'index trouvée, par le trou qui la précède. Mais, pour un intervalle de lignes traitées par UPDATE et DELETE, InnoDB doit mêler des verrous de prochaine clé ou des verrous de trous et bloquer les insertions des autres utilisateurs dans les espaces couverts par l'intervalle. Ceci est nécessaire, car les « lignes fantômes » doivent être bloquées pour la réplication MySQL et la restauration. La lecture cohérente se comporte comme avec Oracle : chaque lecture cohérente, même dans une transaction, lit et modifie son propre contexte. Voir Section 15.11.3, « Lecture cohérente non bloquante ».

- REPEATABLE READ
C'est le niveau d'isolation par défaut d'InnoDB. Les commandes SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE et DELETE qui utilisent un index unique dans une condition de recherche, ne verrouillent que la ligne d'index trouvée, et non pas le trou précédent. Sinon, ces opérations utilisent le verrouillage de prochaine clé, en verrouillant l'intervalle utilisé, et bloque les insertions des utilisateurs. Avec les lectures cohérentes, il y a une importante différence avec le niveau d'isolation précédent : dans ce mode, toutes les lectures cohérentes d'une même transaction liront les mêmes données, établies par la première lecture. Cette convention signifie que si vous émettez plusieurs commandes SELECT dans la même transaction, ces SELECT seront cohérents les uns avec les autres. Voir Section 15.11.3, « Lecture cohérente non bloquante ».

- SERIALIZABLE Ce niveau est identique au précédent, mais toutes les lectures SELECT sont implicitement converties en SELECT ... LOCK IN SHARE MODE.

15-K-3 - Lecture cohérente non bloquante

Une lecture cohérente signifie que InnoDB utilise son système de multiversionnage pour présenter à une requête, une photo de la base à un moment donné. La requête va alors voir les différentes modifications apportées par les transactions qui ont eu lieu avant cette date, et masquera les transactions qui ont eu lieu depuis, ou qui n'ont pas été archivées. L'exception à cette règle est que la requête verra les modifications apportées par la requête qui a émis cette commande.

Si vous utilisez le niveau d'isolation REPEATABLE READ, alors les lectures cohérentes dans une même transaction liront le même bilan. Vous pouvez obtenir un bilan plus récent pour vos requêtes en archivant la requête courante, et en démarrant une autre.

Les lectures cohérentes sont le mode par défaut de traitement des commandes SELECT par InnoDB avec les niveaux d'isolation READ COMMITTED et REPEATABLE READ. Une lecture cohérente ne pose aucun verrou sur les tables auxquelles elle accède, et par conséquent, les autres utilisateurs peuvent librement modifier ces tables en même temps qu'une lecture cohérente est exécutée.

15-K-4 - Verrous de lecture SELECT ... FOR UPDATE et SELECT ... LOCK IN SHARE MODE

Une lecture cohérente n'est pas toujours pratique, dans certaines circonstances. Supposons que vous voulez ajouter une ligne dans votre table CHILD, et vous assurer que l'enfant a déjà un parent dans la table PARENT.

Supposez que vous utilisiez une lecture cohérente, pour lire la table PARENT, et que vous découvrez le parent de l'enfant dans cette table. Pouvez-vous ajouter tranquillement la ligne fille dans la table CHILD ? Non, car il peut arriver que durant ce temps, un autre utilisateur a effacé la ligne parente dans la table PARENT, et vous n'en êtes pas conscient.

La solution est d'exécuter la commande SELECT en mode verrouillage, avec LOCK IN SHARE MODE.

SELECT * FROM PARENT WHERE NAME = 'Jones' LOCK IN SHARE MODE;

Effectuer une lecture en mode partagé signifie que nous allons lire les dernières données disponibles, et que nous allons poser un verrou sur les lignes que nous lisons. Si les dernières données appartiennent à une transaction non validée d'un autre utilisateur, nous allons attendre que ce soit fait. Un verrou partagé évite que les autres utilisateurs ne modifient ou n'effacent la ligne que nous lisons. Après que nous ayons obtenu le nom du parent, nous pouvons tranquillement ajouter le nom du fils dans la table CHILD, et valider notre transaction. Cet exemple montre comment implanter l'intégrité référentielle dans votre application.

Ajoutons un autre exemple : nous avons un champ compteur dans la table CHILD_CODES que nous utilisons pour assigner un identifiant unique à chaque enfant que nous ajoutons dans la table CHILD. Évidemment, en utilisant une lecture cohérente ou une lecture partagée pour lire la valeur courante du compteur n'est pas une bonne idée, car deux utilisateurs de la base peuvent simultanément lire la même valeur de compteur, et nous allons obtenir une erreur de clé doublon lorsque nous ajouterons le second des deux fils.

Ici, LOCK IN SHARE MODE n'est pas une bonne solution, car si deux utilisateurs lisent le compteur en même temps, au moins l'un des deux sera bloqué lorsqu'il tentera de modifier le compteur.

Dans ce cas, il y a deux bonnes méthodes pour implémenter la lecture et l'incrémentation du compteur : (1) modifiez le compteur d'une unité, et lisez-le après cela ou (2) lisez le compteur d'abord, avec un verrou en mode FOR UPDATE, puis incrémentez-le :

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;

Une commande SELECT ... FOR UPDATE va lire les dernières données disponibles pour chaque ligne, et pose un verrou dessus en même temps qu'il lit. De cette façon, il pose le même verrou que la commande UPDATE.

Notez que la commande ci-dessus est simplement un exemple de fonctionnement de SELECT ... FOR UPDATE. En MySQL, la tâche spécifique de création d'un identifiant unique peut être réalisée avec un seul accès à la table :

UPDATE child_codes
SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

La commande SELECT ne fait que lire l'identifiant spécifique à la connexion. Il ne fait aucun accès à la table.

15-K-5 - Verrou de clé suivante : éviter le problème des lignes fantômes

Avec le verrouillage de ligne, InnoDB utilise un algorithme appelé le verrouillage de la clé suivante. InnoDB fait un verrouillage de telle sorte que lorsqu'il fait une recherche ou un scan d'index, il pose des verrous partagés ou exclusifs sur les lignes d'index qu'il rencontre. Par conséquent, les verrous de lignes sont plus exactement appelés des verrous d'index.

Les verrous que InnoDB pose affectent aussi l'espace qui le sépare de la ligne suivante. Si un utilisateur a un verrou partagé ou exclusif sur une ligne L dans un index, alors un autre utilisateur ne peut faire d'insertion immédiatement avant la ligne L, dans l'ordre de l'index. Ce verrouillage est fait pour éviter le problème de la ligne fantôme. Supposons que je veuille lire et verrouiller tous les enfants ayant un identifiant supérieur à 100 dans la table CHILD, puis modifier certains champs des lignes ainsi identifiées :

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

Supposons qu'il y ait un index sur la table CHILD, sur la colonne ID. Notre requête va scanner l'index à partir de la première ligne où ID est plus grand que 100. Maintenant, si le verrou posé sur les lignes d'index n'empêche pas l'utilisation des intervalles entre les lignes d'index, un nouvel enfant peut être inséré dans la table durant la lecture. Et maintenant, si ma transaction exécute la commande :

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

je vais trouver un nouvel enfant dans le résultat de ma requête. Ceci va à l'encontre du principe d'isolation des transactions : une transaction doit être capable de s'exécuter sans que les lectures soient affectées durant ce temps. Si nous considérons un intervalle de données, alors la nouvelle ligne 'fantôme' va casser le principe d'isolation.

Lorsque InnoDB scanne un index, il va aussi verrouiller l'espace après la dernière ligne de l'index. C'est ce qui est arrivé dans l'exemple ci-dessus : le verrou posé par InnoDB va éviter qu'une insertion n'intervienne dans la table où ID serait plus grand que 100.

Vous pouvez utiliser le verrouillage de la clé suivante pour implémenter des vérifications d'unicité dans votre application : si vous lisez des données en mode partagé, et que vous ne voyez pas de duplicata de la ligne que vous allez insérer, alors vous pouvez l'insérer sans problème, en sachant que le verrou de clé suivante va vous garantir que durant ce temps, personne ne pourra insérer de ligne, qui déboucherait sur un duplicata de la vôtre. Le verrou de clé suivante permet de verrouiller aussi la non-existence de ligne dans votre table.

15-K-6 - Un exemple de lecture cohérente avec InnoDB

Supposons que vous exécutez MySQL avec le niveau d'isolation des transactions de REPEATABLE READ. Lorsque vous demandez une lecture cohérente avec une commande SELECT ordinaire, InnoDB va donner à votre transaction une date jalon, en fonction de laquelle votre requête va voir la base. Ainsi, si une transaction B efface une ligne après l'assignation de ce jalon, vous ne verrez pas cette ligne. De même pour une insertion ou une modification.

Vous pouvez faire avancer votre date jalon en validant votre transaction et en exécutant un autre SELECT.

Cela s'appelle le contrôle simultané multiversion.

User A                 User B

SET AUTOCOMMIT=0;      SET AUTOCOMMIT=0;
time
|             SELECT * FROM t;
|             empty set
|                                    INSERT INTO t VALUES (1, 2);
|
v             SELECT * FROM t;
empty set
COMMIT;

SELECT * FROM t;
empty set;

COMMIT;

SELECT * FROM t;
---------------------
|    1    |    2    |
---------------------

De cette façon, A voit la ligne insérée par B uniquement lorsque B a validé son insertion, et que A a validé sa propre transaction, de façon à ce que la date jalon soit plus récente que la validation de B.

Si vous voulez avoir une vision aussi « fraîche » que possible de votre base, vous devez utiliser le verrou en lecture :

SELECT * FROM t LOCK IN SHARE MODE;

15-K-7 - Les verrous posés par différentes requêtes SQL avec InnoDB

Un verrou de lecture, une commande UPDATE ou DELETE pose généralement des verrous sur toutes les lignes qui sont analysées durant l'opération. La présence d'une clause WHERE n'a pas d'importance. InnoDB ne se souvient pas de la condition WHERE exacte, mais sait quels intervalles d'index ont été scannés. Les verrous sont du type 'prochaine clé', et cela empêche aussi les insertions dans l'« espace » immédiatement après la ligne.

Si le verrou est exclusif, alors InnoDB essaie de lire les groupes d'index et de poser un verrou dessus.

Si vous n'avez pas d'index valable pour votre requête, et que MySQL scanne toute la table, chaque ligne sera verrouillée, et bloquera ainsi toutes les insertions. Il est important de bien configurer ses index, pour que les requêtes ne fassent pas de scan de table inutile.

- SELECT ... FROM ... : ceci est une lecture cohérente, qui lit un bilan de la base, et ne pose aucun verrou.

- SELECT ... FROM ... LOCK IN SHARE MODE : pose un verrou partagé sur la prochaine clé sur tous les index que la lecture rencontre.

- SELECT ... FROM ... FOR UPDATE : pose un verrou exclusif sur la prochaine clé sur tous les index que la lecture rencontre.

- INSERT INTO ... VALUES (...) : pose un verrou exclusif sur la ligne insérée. Notez que ce verrou n'est pas un verrou de clé, et il n'empêche pas les autres utilisateurs d'insérer des lignes. Si une erreur de clé double apparaît, un verrou partagé sera posé sur la ligne doublon.

- Durant l'initialisation d'une colonne AUTO_INCREMENT dans une table, InnoDB pose un verrou exclusif à la fin de l'index associé à la colonne AUTO_INCREMENT. Lors de l'accession au compteur d'incrémentation, InnoDB utilise un verrou spécifique, en mode AUTO-INC où le verrou ne dure que jusqu'à la fin de la requête SQL courante, au lieu de la fin de la transaction. Voir Section 15.11.1, « InnoDB et AUTOCOMMIT ».
Avant MySQL 3.23.50, SHOW TABLE STATUS posait aussi un verrou exclusif sur les tables ayant une colonne AUTO_INCREMENT. Cela signifie que la commande SHOW TABLE STATUS pouvait aussi causer un blocage de verrou, ce qui surprenait beaucoup les utilisateurs. Depuis MySQL 3.23.50, InnoDB lit la valeur d'une table dont la colonne AUTO_INCREMENT a été initialisée, sans poser de verrou.

- INSERT INTO T SELECT ... FROM S WHERE ... : pose un verrou exclusif sur chaque ligne insérée dans T. Effectue la recherche sur S sous la forme d'une lecture cohérente, mais pose un verrou partagé sur l'index de prochaine clé de S si MySQL a activé le log. InnoDB doit poser un verrou dans cette dernière situation, car en cas d'exécution des instructions dans une phase de restauration, toutes les requêtes doivent être exécutées dans le même ordre.

- CREATE TABLE ... SELECT ... effectue une commande SELECT sous la forme d'une lecture cohérente, ou avec des verrous partagés, comme précédemment.

- REPLACE est similaire à une insertion, s'il n'y a pas de collision sur la clé unique. Sinon, un verrou exclusif sur l'index de prochaine clé est posé sur la ligne qui sera modifiée.

- UPDATE ... SET ... WHERE ... : pose un verrou exclusif sur l'index de prochaine clé, à chaque ligne que la recherche trouve.

- DELETE FROM ... WHERE ... : pose un verrou exclusif sur l'index de prochaine clé à chaque ligne que la recherche trouve.

- Si la contrainte de FOREIGN KEY est définie sur une table, toute insertion, modification ou effacement qui requiert la vérification de la contrainte va poser un verrou de ligne sur la ligne dont il doit vérifier la contrainte. De plus, dans certains cas où la contrainte échoue, InnoDB pose ces verrous.

- LOCK TABLES ... : pose un verrou de table. L'implémentation de la couche MySQL pose ce verrou. La détection automatique des blocages de InnoDB ne peut détecter les blocages lorsque de tels verrous sont posés. Voyez la section suivante. Voir Section 15.11.9, « Détection des blocages et annulation ».
De plus, comme MySQL ne connaît pas le verrouillage de lignes, il est possible que vous posiez un verrou sur une table où un autre utilisateur a déjà posé un verrou. Mais cela ne pose pas de problème quant à l'intégrité de la requête. Voir Section 15.17, « Restrictions sur les tables InnoDB ».

15-K-8 - Quand est-ce que MySQL valide ou annule implicitement une transaction ?

MySQL ouvre les connexions des clients en mode d'autovalidation, par défaut. Lorsque l'autovalidation est activée, MySQL fait une validation après chaque commande SQL, si la commande n'a pas retourné d'erreur.

Si vous n'avez pas de mode d'autovalidation, et que vous fermez une connexion sans valider explicitement vos transactions, alors MySQL annule votre transaction.

Si une erreur est retournée par une commande SQL, le comportement de la transaction dépend de l'erreur. Voir Section 15.16, « Gestion des erreurs InnoDB ».

Les commandes SQL suivantes causent une validation implicite de la transaction courante :

- ALTER TABLE, BEGIN, CREATE INDEX, DROP DATABASE, DROP INDEX, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE, UNLOCK TABLES.

- CREATE TABLE (elle valide uniquement avant MySQL 4.0.13 et si le log binaire MySQL est utilisé).

- La commande CREATE TABLE de InnoDB est traitée comme une seule transaction. Cela signifie qu'une commande ROLLBACK ne va pas annuler la commande CREATE TABLE qui a été faite dans la transaction.

15-K-9 - Détection des blocages et annulation

InnoDB détecte automatiquement les blocages de transactions et annule une ou plusieurs transactions pour l'éviter. Depuis la version 4.0.5, InnoDB va essayer d'annuler les petites transactions. La taille de la transaction est déterminée par le nombre de lignes qu'elle a inséré, modifié ou effacé. Avant la version 4.0.5, InnoDB annulait toujours la transaction qui avait posé le dernier verrou avant le blocage, c'est-à-dire, un cycle dans le graphe des transactions.

InnoDB ne peut pas détecter les blocages causés par la commande MySQL LOCK TABLES, ou si un verrou est posé par un autre gestionnaire de table que InnoDB. Vous devez résoudre ces situations avec l'option innodb_lock_wait_timeout du fichier de configuration.

Lorsque InnoDB effectue une annulation de transaction, tous les verrous de cette transaction sont libérés. Cependant, si une commande SQL est annulée pour cause d'erreur, certains verrous de la transaction peuvent être conservés. Ceci est dû au fait que InnoDB enregistre les verrous dans un format qui ne permet pas de savoir qui l'a posé.

15-K-10 - Comment gérer les blocages de verrous ?

Les blocages de verrous sont un problème classique des bases de données transactionnelles, mais ils ne sont pas dangereux, à moins qu'ils ne se répètent si souvent que vous ne puissiez pas exécuter tranquillement certaines transactions. Normalement, vous devriez écrire vos applications de manière à ce qu'elles soient prêtes à tenter à nouveau une transaction si la transaction est annulée pour cause de blocage.

InnoDB utilise un verrouillage de lignes automatique. Vous pouvez obtenir des blocages sur une ligne, même si votre transaction ne fait que modifier ou insérer une seule ligne. Cela est dû au fait que les opérations ne sont pas réellement 'atomiques' : elles posent automatiquement des verrous (éventuellement plusieurs) sur les lignes d'index de l'enregistrement concerné.

Vous pouvez gérer ces blocages et réduire leur nombre avec les trucs suivants.

- Utilisez la commande SHOW INNODB STATUS avec MySQL version supérieure à 3.23.52 et 4.0.3, pour déterminer la cause du dernier blocage. Cela peut vous aider à optimiser votre application pour les éviter.

- Soyez toujours prêts à tenter une nouvelle fois une transaction si elle échoue à cause d'un blocage. Les verrous ne sont pas dangereux. Essayez juste une autre fois.

- Validez souvent vos transactions. Les petites transactions sont moins sujettes aux blocages.

- Si vous utilisez des verrous en lectures avec SELECT ... FOR UPDATE ou ... LOCK IN SHARE MODE, essayez d'utiliser un niveau d'isolation plus bas comme READ COMMITTED.

- Accédez à vos tables et lignes dans un ordre fixé. Les transactions vont alors former des queues, et non pas des blocages.

- Ajoutez de bons index à vos tables. Vos requêtes devront scanner moins souvent les tables, et poseront donc moins de verrous. Utilisez EXPLAIN SELECT pour déterminer si MySQL choisit les bons index pour vos requêtes.

- Limitez votre utilisation des verrous. Si vous pouvez vous permettre de faire retourner à une commande SELECT des données un peu anciennes, n'ajoutez pas la clause FOR UPDATE ou LOCK IN SHARE MODE. Utiliser le niveau d'isolation READ COMMITTED est bon ici, car chaque lecture cohérente dans la même transaction lira avec des données aussi fraîches que possible à chaque fois.

- En dernier recours, vous pouvez forcer les verrous avec la commande :

LOCK TABLES t1 WRITE, t2 READ, ...;
[faire quelque chose avec les tables t1 et t2];
UNLOCK TABLES;

Les verrous de niveau de table forcent les transactions à se mettre en ligne, et les blocages sont évités. Notez que LOCK TABLES démarre implicitement une transaction, tout comme BEGIN, et UNLOCK TABLES termine une transaction avec un COMMIT.

- Une dernière solution est de créer un sémaphore auxiliaire sous la forme d'une table avec une seule ligne. Chaque transaction modifie cette table avant d'accéder aux autres tables. Dans ce cas, toutes les transactions se font en ordre séquentiel. Notez que dans cette configuration, même l'algorithme InnoDB de détection des blocages fonctionne, car le sémaphore est un verrou de ligne. Avec les verrous de niveau de table de MySQL, nous devons nous résoudre à une méthode de délai d'expiration pour résoudre un verrou.

15-L - Conseils pour l'amélioration des performances InnoDB

- Si l'outil Unix top ou si le Task Manager de Windows montre que l'utilisation du CPU, lors de la charge de travail, est inférieure à 70 %, votre calcul est probablement limité par les disques. Vous faites peut-être trop d'écriture de transaction, ou le tampon de traitement (« buffer pool ») est peut-être trop petit. Augmenter la taille du tampon peut aider, mais il ne faut pas qu'il dépasse 80 % de la mémoire physique.

- Regrouper les modifications dans une seule transaction. InnoDB doit écrire les données de log sur le disque à chaque validation de transaction, si la transaction a fait des modifications dans la base. Comme la vitesse de rotation d'un disque est typiquement de 167 révolutions/seconde au mieux, cela réduit le nombre de validations à 167 par seconde, si le disque ne veut pas induire le système d'exploitation en erreur.

- Si vous pouvez accepter la perte des toutes dernières transactions validées, vous pouvez modifier dans le fichier my.cnf le paramètre innodb_flush_log_at_trx_commit à 0. InnoDB essaie d'écrire sur le disque au moins une fois par seconde, mais cette écriture n'est plus garantie.

- Utilisez de gros fichiers de logs, même aussi grands que le pool de buffer. Lorsque InnoDB a écrit les fichiers de logs, il doit écrire les contenus modifiés du pool de buffer sur le disque, avec un jalon. Les fichiers de logs de petites tailles imposeront des écritures inutiles. L'inconvénient d'un gros fichier de logs est que le temps de restauration sera plus long.

- Le buffer de logs doit être assez grand, au moins 8 Mo.

- Utilisez le type de colonne VARCHAR au lieu de CHAR si vous stockez des chaînes de taille variable, ou si une colonne peut contenir plusieurs valeurs NULL. Une colonne CHAR(N) prend toujours N octets pour stocker les données, même si la chaîne est plus petite, ou que sa valeur est NULL. Des tables plus petites rentrent plus facilement dans les buffers et réduisent les accès disques.

- (Valable depuis MySQL version 3.23.39 et plus récent) Dans certaines versions de MySQL et Unix, l'écriture des fichiers sur les disques avec fdatasync et d'autres commandes similaires sont étonnamment lentes. La méthode par défaut de InnoDB est la fonction fdatasync. Si vous n'êtes pas satisfaits avec les performances en écriture de la base, vous pouvez essayer d'utiliser l'option innodb_flush_method dans le fichier my.cnf avec la valeur O_DSYNC, même si O_DSYNC semble être la méthode la plus lente sur la plupart des systèmes.

- Lors de l'importation de données avec InnoDB, assurez-vous que MySQL n'a pas autocommit=1. Sinon, chaque insertion implique une écriture sur le disque. Ajoutez cette commande dans votre fichier SQL d'import :

SET AUTOCOMMIT=0;
/* commandes d'importation SQL ... */
COMMIT;

Si vous utilisez l'option --opt de l'utilitaire mysqldump, vous allez obtenir des fichiers d'export qui sont rapides à importer dans une table InnoDB, même sans utiliser l'astuce de la transaction ci-dessus : SET AUTOCOMMIT=0; ... COMMIT;.

- Attention aux annulations lors des insertions de masse : InnoDB utilise un buffer d'insertion pour éviter les accès disques, mais la fonction d'annulation correspondante n'utilise pas ce mécanisme. Une annulation qui utilise beaucoup d'accès disque est environ 30 fois plus lente que l'insertion équivalente. Interrompre la base ne va pas aider, car l'annulation reprendra lors du redémarrage de la base. La seule solution pour se débarrasser de cette annulation lénifiante est d'augmenter la taille du pool de buffer, pour que l'annulation soit limitée par le processeur et non plus par le disque. Ou alors, effacez toute la base InnoDB. Voir Section 15.9.1, « Forcer la restauration ».

- Attention aux opérations qui ont de gros impacts sur le disque : utilisez DROP TABLE ou TRUNCATE depuis MySQL 4.0 et, pour vider une table, et non pas DELETE FROM votre_table.

- Utilisez les INSERT multiples pour réduire les communications entre le client et le serveur, si vous devez insérer plusieurs lignes :

INSERT INTO yourtable VALUES (1, 2), (5, 5);

Ce conseil est valable pour tous les types des tables, pas seulement InnoDB.

- Si vous avez une contrainte UNIQUE sur les clés secondaires, depuis MySQL version 3.23.52 et 4.0.3, vous pouvez accélérer les imports de tables en désactivant temporairement les vérifications d'unicité durant l'importation :

SET UNIQUE_CHECKS=0;

Pour les grandes tables, cela économise de nombreux accès disques, car les tables InnoDB peuvent utiliser le buffer d'insertion pour écrire des index secondaires par paquets.

- Si vous avez des contraintes FOREIGN KEY dans vos tables, depuis MySQL 3.23.52 et 4.0.3, vous pouvez accélérer les imports de tables en désactivant temporairement les vérifications d'unicité durant l'importation :

SET FOREIGN_KEY_CHECKS=0;

Pour les grandes tables, cela économise beaucoup d'accès disques.

- Si vous avez des requêtes récurrentes dans vos tables, qui ne sont pas modifiées souvent, vous pouvez utiliser le cache de requêtes depuis MySQL 4.0 :

[mysqld]
query_cache_type = ON
query_cache_size = 10M

En MySQL 4.0, le cache temporaire fonctionne uniquement si l'autocommit est activé. Cette restriction a été levée depuis MySQL 4.1.1.

15-L-1 - Le moniteur InnoDB

Depuis la version 3.23.42, InnoDB inclut le moniteur InnoDB (InnoDB Monitor) qui affiche des informations sur l'état interne des tables InnoDB. Depuis les versions 3.23.52 et 4.0.3 vous pouvez aussi utiliser la commande SQL SHOW INNODB STATUS pour lire les informations de InnoDB Monitor depuis le client SQL. Les données lues sont importantes pour les réglages de performances. Si vous utilisez le client mysql interactif, le résultat est plus lisible si vous remplacez le point-virgule classique par \G :

SHOW INNODB STATUS\G

Une autre méthode pour utiliser le InnoDB Monitors est de le laisser écrire continuellement des données dans la sortie de mysqld : (note : le client MySQL n'affichera rien). Lorsqu'il est activé, InnoDB peut afficher des données toutes les 15 secondes. Si vous utilisez mysqld comme démon, alors ces données sont dirigées vers le fichier de logs .err dans le dossier datadir. Les données lues sont importantes pour les réglages de performances. Sous Windows, vous devez lancer mysqld-max depuis une fenêtre MS-DOS, avec l'option --console, si vous voulez voir le résultat affiché dans la fenêtre.

Il existe aussi innodb_lock_monitor qui affiche les mêmes informations que innodb_monitor, mais qui indique aussi les verrous posés par les transactions.

- Les verrous de tables et de ligne de chaque transaction,

- les attentes de verrous par les transactions,

- les attentes de sémaphores pour les threads,

- les requêtes en attente d'accès aux fichiers,

- les statistiques sur les buffers, et

- les statistiques sur les purges et buffers d'insertion sur le thread principal InnoDB.

Vous pouvez démarrer le moniteur InnoDB avec la commande SQL suivante :

CREATE TABLE innodb_monitor(a int) type = innodb;

et le stopper avec :

DROP TABLE innodb_monitor;

La syntaxe CREATE TABLE est simplement un moyen de passer une commande à une table InnoDB, via l'analyseur MySQL : la table créée n'est pas importante pour le moniteur InnoDB. Si vous interrompez le serveur lorsque le moniteur fonctionne, et que vous voulez redémarrer le moniteur, vous devez alors effacer la table avant de pouvoir exécuter la même commande CREATE TABLE pour démarrer le moniteur. Cette syntaxe est susceptible de changer dans le futur.

Un exemple de résultat du moniteur InnoDB :

mysql> SHOW INNODB STATUS\G
*************************** 1. row ***************************
Status:
=====================================
030709 13:00:59 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 18 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 413452, signal count 378357
--Thread 32782 has waited at btr0sea.c line 1477 for 0.00 seconds the semaphore:
X-lock on RW-latch at 41a28668 created in file btr0sea.c line 135
a writer (thread id 32782) has reserved it in mode wait exclusive
number of readers 1, waiters flag 1
Last time read locked in file btr0sea.c line 731
Last time write locked in file btr0sea.c line 1347
Mutex spin waits 0, rounds 0, OS waits 0
RW-shared spins 108462, OS waits 37964; RW-excl spins 681824, OS waits 375485
------------------------
LATEST FOREIGN KEY ERROR
------------------------
030709 13:00:59 Transaction:
TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 inser
ting
15 lock struct(s), heap size 2496, undo log entries 9
MySQL thread id 25, query id 4668733 localhost heikki update
insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk')
Foreign key constraint fails for table test/ibtest11a:
,
CONSTRAINT `0_219242` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11b` (`A`, `D`)
ON DELETE CASCADE ON UPDATE CASCADE
Trying to add in child table, in index PRIMARY tuple:
0: len 4; hex 80000101; asc ....;; 1: len 4; hex 80000005; asc ....;; 2: len 4;
hex 6b68446b; asc khDk;; 3: len 6; hex 0000114e0edc; asc ...N..;; 4: len 7; hex
00000000c3e0a7; asc .......;; 5: len 4; hex 6b68446b; asc khDk;;
But in parent table test/ibtest11b, in index PRIMARY,
the closest match we can find is record:
RECORD: info bits 0 0: len 4; hex 8000015b; asc ...[;; 1: len 4; hex 80000005; a
sc ....;; 2: len 3; hex 6b6864; asc khd;; 3: len 6; hex 0000111ef3eb; asc ......
;; 4: len 7; hex 800001001e0084; asc .......;; 5: len 3; hex 6b6864; asc khd;;
------------------------
LATEST DETECTED DEADLOCK
------------------------
030709 12:59:58
*** (1) TRANSACTION:
TRANSACTION 0 290252780, ACTIVE 1 sec, process no 3185, OS thread id 30733 inser
ting
LOCK WAIT 3 lock struct(s), heap size 320, undo log entries 146
MySQL thread id 21, query id 4553379 localhost heikki update
INSERT INTO alex1 VALUES(86, 86, 794,'aA35818','bb','c79166','d4766t','e187358f'
,'g84586','h794',date_format('2001-04-03 12:54:22','%Y-%m-%d %H:%i'),7
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole
trx id 0 290252780 lock mode S waiting
Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a
a35818;; 1:
*** (2) TRANSACTION:
TRANSACTION 0 290251546, ACTIVE 2 sec, process no 3190, OS thread id 32782 inser
ting
130 lock struct(s), heap size 11584, undo log entries 437
MySQL thread id 23, query id 4554396 localhost heikki update
REPLACE INTO alex1 VALUES(NULL, 32, NULL,'aa3572','','c3572','d6012t','', NULL,'
h396', NULL, NULL, 7.31,7.31,7.31,200)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole
trx id 0 290251546 lock_mode X locks rec but not gap
Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a
a35818;; 1:
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole
trx id 0 290251546 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 82 RECORD: info bits 0 0: len 7; hex 61613335373230; asc aa
35720;; 1:
*** WE ROLL BACK TRANSACTION (1)
------------
TRANSACTIONS
------------
Trx id counter 0 290328385
Purge done for trx's n:o < 0 290315608 undo n:o < 0 17
Total number of lock structs in row lock hash table 70
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 3491, OS thread id 42002
MySQL thread id 32, query id 4668737 localhost heikki
show innodb status
---TRANSACTION 0 290328384, ACTIVE 0 sec, process no 3205, OS thread id 38929 in
serting
1 lock struct(s), heap size 320
MySQL thread id 29, query id 4668736 localhost heikki update
insert into speedc values (1519229,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlhh
gghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjfh
---TRANSACTION 0 290328383, ACTIVE 0 sec, process no 3180, OS thread id 28684 co
mmitting
1 lock struct(s), heap size 320, undo log entries 1
MySQL thread id 19, query id 4668734 localhost heikki update
insert into speedcm values (1603393,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlh
hgghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjf
---TRANSACTION 0 290328327, ACTIVE 0 sec, process no 3200, OS thread id 36880 st
arting index read
LOCK WAIT 2 lock struct(s), heap size 320
MySQL thread id 27, query id 4668644 localhost heikki Searching rows for update
update ibtest11a set B = 'kHdkkkk' where A = 89572
------- TRX HAS BEEN WAITING 0 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65556 n bits 232 table test/ibtest11a index PRIM
ARY trx id 0 290328327 lock_mode X waiting
Record lock, heap no 1 RECORD: info bits 0 0: len 9; hex 73757072656d756d00; asc
supremum.;;
------------------
---TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 ro
llback of SQL statement
ROLLING BACK 14 lock struct(s), heap size 2496, undo log entries 9
MySQL thread id 25, query id 4668733 localhost heikki update
insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk')
---TRANSACTION 0 290327208, ACTIVE 1 sec, process no 3190, OS thread id 32782
58 lock struct(s), heap size 5504, undo log entries 159
MySQL thread id 23, query id 4668732 localhost heikki update
REPLACE INTO alex1 VALUES(86, 46, 538,'aa95666','bb','c95666','d9486t','e200498f
','g86814','h538',date_format('2001-04-03 12:54:22','%Y-%m-%d %H:%i'),
---TRANSACTION 0 290323325, ACTIVE 3 sec, process no 3185, OS thread id 30733 in
serting
4 lock struct(s), heap size 1024, undo log entries 165
MySQL thread id 21, query id 4668735 localhost heikki update
INSERT INTO alex1 VALUES(NULL, 49, NULL,'aa42837','','c56319','d1719t','', NULL,
'h321', NULL, NULL, 7.31,7.31,7.31,200)
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
151671 OS file reads, 94747 OS file writes, 8750 OS fsyncs
25.44 reads/s, 18494 avg bytes/read, 17.55 writes/s, 2.33 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf for space 0: size 1, free list len 19, seg size 21,
85004 inserts, 85004 merged recs, 26669 merges
Hash table size 207619, used cells 14461, node heap has 16 buffer(s)
1877.67 hash searches/s, 5121.10 non-hash searches/s
---
LOG
---
Log sequence number 18 1212842764
Log flushed up to   18 1212665295
Last checkpoint at  18 1135877290
0 pending log writes, 0 pending chkp writes
4341 log i/o's done, 1.22 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 84966343; in additional pool allocated 1402624
Buffer pool size   3200
Free buffers       110
Database pages     3074
Modified db pages  2674
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 171380, created 51968, written 194688
28.72 reads/s, 20.72 creates/s, 47.55 writes/s
Buffer pool hit rate 999 / 1000
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
Main thread process no. 3004, id 7176, state: purging
Number of rows inserted 3738558, updated 127415, deleted 33707, read 755779
1586.13 inserts/s, 50.89 updates/s, 28.44 deletes/s, 107.88 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
1 row in set (0.05 sec)

Quelques notes sur le résultat :

- Si la section TRANSACTIONS rapporte des attentes de verrous, alors votre application a des problèmes de rétention de verrous. Le rapport peut vous aider à trouver les blocages de verrous, et les transactions bloquantes.

- La section SEMAPHORES rapporte les threads en attente d'un sémaphore, et les statistiques d'attentes pour un mutex ou un verrou en lecture/écriture. Les longues attentes peuvent être dues à des requêtes parallèles, ou des problèmes avec la programmation des threads. Donner à la variable innodb_thread_concurrency une valeur plus petite que le 8 par défaut peut réduire ce type de situations.

- La section BUFFER POOL AND MEMORY vous donne des statistiques sur les pages qui ont été lues et écrites. Vous pouvez calculer depuis ces nombres combien d'accès disques vos requêtes réalisent actuellement.

- La section ROW OPERATIONS montre ce que le thread principal fait.

15-M - Implémentation du multiversionnage

Comme InnoDB est une base de donnes multiversionnée, elle doit conserver des informations des vieilles versions des lignes dans l'espace de tables. Cette information est stockée dans la structure de données que nous appelons un segment d'annulation, d'après la structure similaire d'Oracle.

En interne, InnoDB ajoute deux champs à chaque ligne stockée dans la base. Un champ de 6 octets note l'identifiant de la dernière transaction qui a inséré ou modifié la ligne. De plus, un effacement est traité en interne comme une modification, où un bit spécial dans la ligne sert à marquer la ligne comme effacée. Chaque ligne contient aussi une colonne de 7 octets appelée un pointeur d'annulation. Ce pointeur fait référence à une ligne dans un fichier d'annulation qui contient les informations nécessaires pour reconstruire le contenu de la ligne qui a été modifiée.

InnoDB utilise les informations dans le segment d'annulation pour effectuer les opérations d'annulation nécessaires dans une annulation de transaction. Il utilise aussi ces informations pour reconstruire les anciennes versions d'une ligne lors d'une lecture cohérente.

Le log d'annulation dans le segment d'annulation est divisé entre les insertions et les modifications. Le log d'insertion n'est nécessaire que lors des annulations de transactions, et peut être vidé dès que la requête est validée. Le log de modification est utilisé lors des lectures cohérentes, et les informations y sont supprimées une fois que toutes les transactions qui font une lecture cohérente sont terminées.

Vous devez vous rappeler que valider vos transactions régulièrement, même ces transactions qui ne font que des lectures cohérentes. Sinon, InnoDB ne peut pas vider le log de modification, et le segment d'annulation va grossir énormément.

La taille physique d'une ligne du log d'annulation dans le segment d'annulation est typiquement plus petite que la ligne correspondante insérée ou modifiée. Vous pouvez utiliser ces informations pour calculer l'espace nécessaire à vos segments d'annulation.

Dans nos schémas de multiversionnage, une ligne n'est pas physiquement supprimée de la table immédiatement lorsque vous l'effacez avec une requête SQL. Uniquement lorsque InnoDB va supprimer les lignes du log de modification, il vaut aussi supprimer physiquement la ligne, et les index. Cette opération d'effacement est appelée une purge, et elle est plutôt rapide, et aussi rapide que la requête SQL elle-même.

15-N - Structures de tables et d'index

MySQL enregistre la structure de table dans le fichier .frm, du dossier de données. Mais les tables InnoDB ont aussi leur propre entrée dans les tables internes InnoDB. Lorsque MySQL efface une table ou une base, il efface le ou les fichiers .frm et aussi les lignes correspondantes dans les tables d'administration InnoDB. C'est la raison qui fait que vous ne pouvez pas déplacer les tables InnoDB entre les bases simplement en déplaçant le fichier .frm, et pourquoi DROP DATABASE ne fonctionnait pas sous InnoDB en MySQL versions <= 3.23.43.

Chaque table InnoDB a un index spécial appelé un index en grappe, où les données des lignes sont enregistrées. Si vous définissez une clé primaire pour votre table PRIMARY KEY, alors l'index de la clé primaire de la table sera un index en grappe.

Si vous ne définissez pas de clé primaire pour votre table, InnoDB va générer un index en grappe, ou les lignes sont ordonnées dans l'ordre des identifiants que InnoDB assigne aux lignes de la table. L'identifiant de ligne vaut 6 octets, et s'accroît au fur et à mesure que les lignes sont ajoutées. Les lignes sont alors ordonnées dans leur ordre d'insertion.

Accéder à une ligne via l'index en grappe est rapide, car la ligne de données sera dans la même page que l'index. Dans de nombreuses bases, les données sont traditionnellement stockées dans un autre endroit. Si la table est grande, l'index en grappe économise de nombreux accès disques, comparativement aux solutions traditionnelles.

Les lignes des index qui ne sont pas en grappe (ce sont les index secondaires) dans InnoDB, contiennent la valeur de la clé primaire de la ligne. InnoDB utilise cette clé primaire pour rechercher la valeur de la ligne dans l'index en grappe. Notez que si la clé primaire est longue, les index secondaires utiliseront plus de place.

InnoDB compare les chaînes CHAR et VARCHAR de différentes longueurs en complétant la chaîne la plus courte avec des espaces.

15-N-1 - Structure physique d'un index

Tous les index de InnoDB sont des index B-tree où les lignes d'index sont stockées dans un nœud terminal de l'arbre. La taille par défaut d'une page d'index est de 16 ko. Lorsque de nouvelles lignes sont insérées, InnoDB essaie de laisser 1/16 de la page de libre pour les prochaines insertions et modifications dans les lignes d'index.

Si les lignes d'index sont insérées dans un ordre séquentiel (croissant ou décroissant), les pages d'index résultantes seront environ pleines à 15/16. Si les lignes sont insérées dans un ordre aléatoire, les pages seront pleines de 1/2 à 15/16. Si le taux de remplissage d'une page d'index tombe à 1/2, InnoDB va essayer de contracter l'arbre d'index pour libérer la page.

15-N-2 - Bufferisation des insertions

Une situation courante dans les applications de base de données apparaît lorsque la clé primaire est un identifiant unique, et que les nouvelles lignes sont insérées dans un ordre ascendant. Par conséquent, les insertions dans l'index en grappe ne nécessitent pas de lectures aléatoires dans le disque.

D'un autre côté, les index secondaires sont généralement non uniques, et les insertions surviennent dans un ordre aléatoire. Cela causerait de nombreux accès disques aléatoires, si InnoDB ne disposait pas d'un mécanisme spécial.

Si une ligne doit être insérée dans un index secondaire non unique, InnoDB vérifie si la page d'index fait partie du buffer. Dans ce cas, InnoDB va faire directement l'insertion dans une structure de buffer destinée à l'insertion. Le buffer d'insertion est conservé petit, pour qu'il reste dans le buffer général, et les insertions sont faites très vite.

Le buffer d'insertion est périodiquement fusionné avec l'arbre d'index secondaires dans la base. Souvent, nous fusionnons plusieurs insertions dans la même page de l'arbre d'index, et donc, nous économisons des accès disques. Il a été mesuré que les insertions sont jusqu'à 15 fois plus rapides de cette façon.

15-N-3 - Index hash adaptatifs

Si une base de données est suffisamment petite pour tenir en mémoire, alors le plus rapide pour faire des requêtes est d'utiliser les index hash. InnoDB a un mécanisme automatique pour surveiller les recherches utilisant les index d'une table, et si InnoDB remarque que la requête pourrait profiter d'un index hash, un tel index est automatiquement constitué.

Mais notez que les index hash sont toujours bâtis à partir d'un index B-tree existant. InnoDB peut bâtir un index hash sur un préfixe de taille arbitraire de clé B-tree, suivant le modèle de recherche que InnoDB remarque dans l'index B-tree. Un index hash peut être partiel : il n'est pas obligatoire que tout l'index B-tree soit mis en cache dans le pool. InnoDB va bâtir des index hash à la demande pour les tables dont les index sont souvent sollicités.

En un sens, grâce au mécanisme d'index hash adaptatif, InnoDB s'adapte tout seul à la mémoire interne, et se rapproche des architectures de bases en mémoire vive.

15-N-4 - Structure physique d'une ligne

- Chaque ligne d'index de InnoDB contient un entête de 6 octets. L'entête est utilisé pour lier des lignes consécutives ensemble, et aussi pour le verrouillage de ligne.

- Les lignes dans un index en grappe contiennent des champs pour toutes les colonnes définies par l'utilisateur. De plus, il y a un champ de 6 octets pour l'identification de transaction, et un champ de 7 octets pour le pointeur d'annulation.

- Si l'utilisateur n'a pas défini de clé primaire pour la table, chaque ligne de l'index en grappe contient aussi une colonne supplémentaire de 6 octets, qui sert d'identification.

- Chaque ligne d'index secondaire contient aussi les champs définis pour la clé de l'index en grappe.

- Une ligne contient aussi un pointeur pour chaque champ de la ligne. Si la taille totale des champs représente moins de 128 octets, alors le pointeur fait 1 octet, sinon 2.

- En interne, InnoDB stocke les colonnes de taille fixe comme CHAR(10) dans un format à taille fixe. InnoDB supprime les espaces terminaux des colonnes VARCHAR. Notez que MySQL peut convertir en interne les colonnes CHAR en VARCHAR. Voir Section 13.2.5.1, « Modification automatique du type de colonnes ».

- Une valeur SQL NULL réserve 0 octet si elle est stockée dans une colonne à taille variable. Dans une colonne à taille fixe, elle utilise toute la largeur de la colonne. La raison de la réservation de toute la colonne pour les valeurs NULL est que lors de la mise à jour de la colonne depuis la valeur NULL vers une valeur non nulle, il n'y aura pas de fragmentation sur le disque.

15-O - Gestion de l'espace fichiers et des entrées/sorties disque

15-O-1 - Accès disques

InnoDB utilise des accès disques asynchrones : InnoDB crée quelques threads pour s'occuper des opérations de lecture, notamment les lectures anticipées.

Voici deux heuristiques de lectures anticipées de InnoDB :

- Dans une lecture anticipée séquentielle, si InnoDB remarque que l'accès à une partie de l'espace de tables est séquentiel, il fait plusieurs lectures à l'avance.

- Dans une lecture aléatoire, si InnoDB remarque qu'une partie de l'espace de tables semble être totalement lu dans le buffer, il va aussi faire une lecture à l'avance.

Depuis la version 3.23.40b, InnoDB utilise une nouvelle technique de flush de fichier, appelée doublewrite. Elle apporte de la sécurité lors de la restauration après crash du système d'exploitation, ou un problème électrique, et améliore les performances sous Unix, pour plusieurs distributions, en réduisant le besoin de synchronisation.

Doublewrite (Double écriture, en français) signifie que InnoDB, avant d'écrire les pages dans le fichier de données, les écrit dans une zone continue d'espace, appelée un buffer de double écriture. Une fois que cette écriture est faite, que le buffer de double écriture a été vidé, InnoDB écrit les pages à leur destination finale. Si le système d'exploitation crashe entre temps, InnoDB va trouver une bonne copie des données dans le buffer, lors de la restauration.

15-O-2 - Utiliser les raw devices pour l'espace de tables

Depuis MySQL 3.23.41, vous pouvez utiliser des partitions raw disk pour stocker les fichiers d'espace de tables. En utilisant un raw disk, vous pouvez faire des E/S non bufferisées sous Windows et sans couche de contrôle sous Unix, ce qui améliore les performances.

Lorsque vous créez un nouveau fichier de données, vous devez mettre le mot newraw immédiatement après la taille du fichier de données dans innodb_data_file_path. La partition doit être aussi grande que la taille que vous spécifiez. Notez que 1 Mo avec InnoDB vaut 1024 x 1024 octets, alors que 1 Mo signifie généralement 1 000 000 d'octets pour un disque.

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw

Lors de votre prochain redémarrage du serveur, InnoDB remarque le mot newraw et initialise une nouvelle partition. Cependant, ne créez ou ne modifiez pas les tables InnoDB pour le moment. Sinon, lors de votre prochain redémarrage serveur, InnoDB va réinitialiser la partition et vous aurez tout perdu. Depuis la version 3.23.44, par mesure de sécurité, InnoDB empêche les utilisateurs de modifier des données dans une partition newraw.

Une fois que InnoDB a initialisé la nouvelle partition, stoppez le serveur, remplacez newraw dans le fichier d'options par raw :

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:5Graw;/dev/hdd2:2Graw

Puis relancez le serveur et InnoDB va permettre les modifications dans cet espace de tables.

Sous Windows, depuis la version 4.1.1, vous pouvez allouer une partition de disque comme ceci :

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=//./D::10Gnewraw

Le //./ correspond à la syntaxe Windows de \\.\, pour accéder aux disques physiques.

Lorsque vous utilisez une partition raw disque, assurez-vous que vous avez les permissions qui permettent de lire et écrire avec le compte qui fait tourner le serveur.

15-O-3 - Gestion de l'espace fichier

Les fichiers de données que vous définissez dans le fichier de configuration forment l'espace de données InnoDB. Les fichiers sont simplement concaténés pour former un espace de données, et il n'y a pas de parallélisme utilisé. Actuellement, vous ne pouvez pas spécifier où l'espace est alloué pour vos tables, hormis en utilisant la méthode suivante : pour chaque nouvel espace de données créé, InnoDB va allouer de l'espace en partant depuis la fin.

L'espace de tables est constitué de pages de taille 16 ko. Les pages sont groupées en ensembles de 64 pages consécutives. Les 'fichiers' dans un espace de tables sont appelés des segments en InnoDB. Le nom du segment d'annulation est un peu trompeur, car il contient en fait de nombreux segments dans l'espace de table.

Pour chaque index de InnoDB, nous allons créer deux segments : un pour les nœuds non terminaux du B tree, et un autre pour les nœuds terminaux. L'idée ici est d'améliorer la séquence des nœuds terminaux, qui contiennent les données.

Lorsqu'un segment croît dans un espace de tables, InnoDB alloue les 32 premières pages spécifiquement pour un segment. Après cela, InnoDB commence à allouer des extensions au segment. InnoDB peut ajouter aux grands segments jusqu'à 4 extensions en même temps, pour améliorer la séquence de données.

Certaines pages dans l'espace de table contiennent des cartes des autres pages, et donc, quelques extensions dans un espace de tables InnoDB ne pourront pas être allouées en tant que segment, mais comme pages individuelles.

Lorsque vous exécutez une commande SHOW TABLE STATUS FROM ... LIKE ... pour demander quel est l'espace libre dans la table, InnoDB va rapporter les extensions qui sont encore totalement libres. InnoDB se réserve toujours quelques extensions pour la gestion interne. Ces extensions réservées ne sont pas incluses dans l'espace libre.

Lorsque vous effacez des donnes d'une table, InnoDB va contracter les index B-tree correspondants. Suivant les effacements qui vont libérer des pages individuelles ou des extensions, de l'espace sera rendu aux autres tables. Effacer une table ou en effacer toutes les lignes va rendre obligatoirement de l'espace aux autres tables, mais souvenez-vous que les lignes effacées ne pourront être physiquement effacées qu'après une opération de purge, si aucune transaction n'en a plus besoin.

15-O-4 - Défragmentation des tables

S'il y a plusieurs insertions et suppressions dans les index d'une table, les index peuvent devenir fragmentés. Par fragmentation, nous voulons dire que l'ordre physique de la page d'index n'est pas proche de l'ordre alphabétique des enregistrements dans les pages, ou qu'il y a plusieurs pages non utilisées dans le bloc de 64 pages qui ont été allouées à l'index.

Une manière d'accélérer les index est d'extraire périodiquement les données de la table dans un fichier avec mysqldump, d'effacer la table puis de la recréer.

Une autre manière de défragmenter consiste à exécuter un ALTER sur le type de la table pour le changer en MyISAM puis de le repasser en InnoDB.

ALTER TABLE tbl_name TYPE=InnoDB

Cela fait que MySQL va reconstruire la table. Un autre moyen de réaliser la défragmentation est d'utiliser l'utilitaire mysqldump pour exporter la table vers un fichier texte, effacer la table, la recréer et importer le fichier de données.

Si les insertions dans un index sont toujours ascendantes et que les lignes supprimées le sont à la fin du fichier, alors l'algorithme de gestion de l'espace fichiers de InnoDB garantit qu'aucune fragmentation n'aura lieu dans l'index.

15-P - Gestion des erreurs InnoDB

La gestion des erreurs avec InnoDB n'est pas toujours la même que celle spécifiée par les standards ANSI SQL. En accord avec les standards ANSI, toute erreur survenant durant une commande SQL devrait provoquer l'annulation de celle-ci. InnoDB n'annule qu'une partie de la commande de temps en temps, ou la totalité de la transaction. La liste suivante spécifie la gestion des erreurs de InnoDB.

- Si vous dépassez l'espace d'un fichier dans l'espace des tables, vous obtiendrez l'erreur MySQL 'Table is full' et InnoDB annulera la requête SQL.

- Un deadlock de transaction ou un dépassement de temps dans une attente de verrouillage fait annuler toute la transaction à InnoDB.

- Une erreur de clé dupliquée annule l'insertion de la ligne concernée, même dans une requête du genre INSERT INTO ... SELECT .... Cela fera probablement en sorte que la commande SQL sera annulée si vous n'avez pas spécifié l'option IGNORE dans votre requête.

- Une erreur « row too long » annule la commande SQL.

- Les autres erreurs sont la plupart du temps détectées au niveau de la couche MySQL du code et annulent la commande SQL correspondante.

15-P-1 - Codes d'erreurs InnoDB

Voici une liste non exhaustive des erreurs courantes et spécifiques à InnoDB que vous pouvez rencontrer, avec des détails pour les corriger.

- 1005 (ER_CANT_CREATE_TABLE)
Impossible de créer la table. Si le message d'erreur fait référence à une erreur de code errno 150, la création de la table a échoué à cause d'une contrainte de clé étrangère, qui n'est pas correctement formée.

- 1016 (ER_CANT_OPEN_FILE)
Impossible de trouver le fichier de tables InnoDB dans les fichiers de données InnoDB alors que le fichier .frms. Voir Section 15.18.1, « Solutions pour le dictionnaire de données InnoDB ».

- 1114 (ER_RECORD_FILE_FULL)
InnoDB n'a plus d'espace libre dans l'espace de tables. Essayez de reconfigurer l'espace de tables, et d'ajouter un nouveau fichier de données.

- 1205 (ER_LOCK_WAIT_TIMEOUT)
Le délai d'expiration du verrou a été dépassé. La transaction a été annulée.

- 1213 (ER_LOCK_DEADLOCK)
Blocage de transactions. Vous devriez relancer la transaction.

- 1216 (ER_NO_REFERENCED_ROW)
Vous essayez d'ajouter une ligne, mais il n'y a pas de ligne parente, et une contrainte de clé étrangère échoue. Vous devez ajouter le parent en premier.

- 1217 (ER_ROW_IS_REFERENCED)
Vous essayez d'effacer une ligne parente qui a des enfants, et une contrainte de clé étrangère échoue. Vous devez effacer la ligne fille en premier.

15-P-2 - Codes d'erreur système

Sous Unix, pour connaître la signification d'un message d'erreur système, utilisez le programme perror qui est livré avec la distribution MySQL.

La table suivante fournit une liste de certains codes d'erreur système Linux. Pour une version complète, voyez Linux source code (http://www.iglu.org.il/lxr/source/include/asm-i386/errno.h lien mort).

- 1 (EPERM)
Cette operation ne peut pas être effectuée.

- 2 (ENOENT)
Le répertoire ou le fichier n'a pas été trouvé.

- 3 (ESRCH)
Processus invalide.

- 4 (EINTR)
L'accès au système a été interrompu.

- 5 (EIO)
Erreur d'I/O.

- 6 (ENXIO)
Le périphérique ou l'adresse est invalide.

- 7 (E2BIG)
La liste des arguments est trop longue.

- 8 (ENOEXEC)
Erreur de format de l'exécutable.

- 9 (EBADF)
Le numéro du fichier est invalide.

- 10 (ECHILD)
Il n'y a pas de processus enfant.

- 11 (EAGAIN)
Relancer un essai.

- 12 (ENOMEM)
La mémoire est saturée.

- 13 (EACCES)
Accès refusé.

- 14 (EFAULT)
L'adresse est invalide.

- 15 (ENOTBLK)
Un périphérique de bloc est nécessaire.

- 16 (EBUSY)
Le périphérique n'est pas disponible.

- 17 (EEXIST)
Le fichier est déjà présent.

- 18 (EXDEV)
Erreur de lien sur les périphériques croisés.

- 19 (ENODEV)
Le périphérique n'existe pas.

- 20 (ENOTDIR)
Le répertoire n'existe pas.

- 21 (EISDIR)
Un répertoire du même nom existe déjà.

- 22 (EINVAL)
Argument invalide.

- 23 (ENFILE)
Le fichier tableau n'a plus d'espace libre.

- 24 (EMFILE)
Trop de fichiers ouverts simultanément.

- 25 (ENOTTY)
Cet ioctl est inactif pour ce périphérique.

- 26 (ETXTBSY)
Le fichier texte est déjà ouvert.

- 27 (EFBIG)
Le fichier est trop volumineux

- 28 (ENOSPC)
Plus d'espace libre sur le périphérique.

- 29 (ESPIPE)
Recherche interdite.

- 30 (EROFS)
Fichier système en mode lecture seule.

- 31 (EMLINK)
Trop de liens dans ce fichier.

La table suivante fournit une liste de certains codes d'erreur système Windows. Pour une version complète, voyez Microsoft website (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp lien mort).

- 1 (ERROR_INVALID_FUNCTION)
La fonction est incorrecte.

- 2 (ERROR_FILE_NOT_FOUND)
Le système ne trouve pas le fichier demandé.

- 3 (ERROR_PATH_NOT_FOUND)
Le système ne trouve pas le répertoire demandé.

- 4 (ERROR_TOO_MANY_OPEN_FILES)
Le système ne peut pas ouvrir le fichier.

- 5 (ERROR_ACCESS_DENIED)
Accès refusé.

- 6 (ERROR_INVALID_HANDLE)
Action demandée est invalide.

- 7 (ERROR_ARENA_TRASHED)
Les blocs de contrôle de stockage ont été détruits.

- 8 (ERROR_NOT_ENOUGH_MEMORY)
L'espace de stockage n'est pas suffisant pour lancer cette commande.

- 9 (ERROR_INVALID_BLOCK)
L'adresse du bloc de contrôle de stockage est invalide.

- 10 (ERROR_BAD_ENVIRONMENT)
L'environnement est mal défini.

- 11 (ERROR_BAD_FORMAT)
Tentative de chargement du programme sous un format invalide.

- 12 (ERROR_INVALID_ACCESS)
Le code d'accès est invalide.

- 13 (ERROR_INVALID_DATA)
Les données sont invalides.

- 14 (ERROR_OUTOFMEMORY)
L'espace de stockage disponible n'est pas suffisant pour réaliser cette opération.

- 15 (ERROR_INVALID_DRIVE)
Le système ne trouve pas le disque demandé.

- 16 (ERROR_CURRENT_DIRECTORY)
Le répertoire ne peut pas être supprimé.

- 17 (ERROR_NOT_SAME_DEVICE)
Le système ne peut pas déplacer le fichier vers un autre disque.

- 18 (ERROR_NO_MORE_FILES)
Pas de fichier disponible.

- 19 (ERROR_WRITE_PROTECT)
Écriture impossible sur ce média protégé.

- 20 (ERROR_BAD_UNIT)
Le système ne trouve pas le périphérique.

- 21 (ERROR_NOT_READY)
Le périphérique n'est pas prêt.

- 22 (ERROR_BAD_COMMAND)
Commande inconnue de ce périphérique.

- 23 (ERROR_CRC)
Erreur de données (problème de redondance cyclique).

- 24 (ERROR_BAD_LENGTH)
Commande trop longue pour ce programme.

- 25 (ERROR_SEEK)
La commande ne trouve pas la zone ou piste sur le disque.

- 26 (ERROR_NOT_DOS_DISK)
Disque ou disquette inaccessible.

- 27 (ERROR_SECTOR_NOT_FOUND)
Secteur disque introuvable.

- 28 (ERROR_OUT_OF_PAPER)
L'imprimante n'a plus de papier.

- 29 (ERROR_WRITE_FAULT)
Le système ne peut pas écrire dans ce périphérique.

- 30 (ERROR_READ_FAULT)
Le système ne peut pas accéder au périphérique.

- 31 (ERROR_GEN_FAILURE)
Un périphérique relié au système ne fonctionne pas.

- 32 (ERROR_SHARING_VIOLATION)
Le processus ne peut accéder au fichier : celui-ci est actuellement en cours d'utilisation par un autre processus.

- 33 (ERROR_LOCK_VIOLATION)
Le processus ne peut accéder au fichier : le fichier est actuellement verrouillé par un autre processus.

- 34 (ERROR_WRONG_DISK)
Erreur de disque demandé. Insérer le disque %2 (Numéro de série : %3) dans le lecteur %1.

- 36 (ERROR_SHARING_BUFFER_EXCEEDED)
Trop de fichiers ouverts en partage.

- 38 (ERROR_HANDLE_EOF)
La fin du fichier a été atteinte.

- 39 (ERROR_HANDLE_DISK_FULL)
Espace disque rempli.

- 112 (ERROR_DISK_FULL)
Espace disque rempli.

- 123 (ERROR_INVALID_NAME)
Le nom de fichier, nom de répertoire ou la syntaxe descriptive du volume est incorrecte.

- 1450 (ERROR_NO_SYSTEM_RESOURCES)
Ressources systèmes insuffisantes pour compléter la requête.

15-Q - Restrictions sur les tables InnoDB

- Une table ne peut pas contenir plus de 1000 colonnes.

- La taille maximale d'une clé est de 1024 octets.

- La taille maximale d'une ligne, hormis pour les colonnes de type BLOB et TEXT, et légèrement inférieure à la moitié d'une page de base, c'est-à-dire, que la taille maximale d'une ligne est d'environ 8000 octets. Les colonnes LONGBLOB et LONGTEXT doivent être un peu plus petite que 4 Go, et la taille totale d'une ligne, incluant les colonnes BLOB et TEXT doivent être de 4 Go. InnoDB stocke les 512 premiers octets des valeurs BLOB et TEXT dans la ligne, et le reste dans une page séparée.

- Sur certains systèmes d'exploitation, le fichier de données est limité à 2 Go.

- La taille combinée des fichiers de logs doit être inférieure à 4 Go.

- La taille minimale d'un espace de tables est de 10 Mo. La taille maximale d'un espace de tables est de 4 milliards de pages de bases (64 To). C'est aussi la taille maximale d'une table.

- Les tables InnoDB ne supportent pas les index FULLTEXT.

- Sous Windows, InnoDB stocke les noms de bases de données et les noms de tables en interne, et en minuscule. Pour passer une base au format binaire de Unix à Windows, ou le contraire, vous devez créer toutes vos bases et tables en minuscules.

- Attention : NE convertissez PAS les tables de droits du format MyISAM en InnoDB ! Cela n'est pas supporté. Si vous faites cela, MySQL ne va pas redémarrer jusqu'à ce que vous restauriez vos données avec une vieille sauvegarde, ou que vous régénériez ces tables avec le script mysql_install_db.

- InnoDB ne conserve pas de compte interne de ligne pour une table. Cela serait en fait compliqué, à cause du multiversionnage. Pour traiter une commande SELECT COUNT(*) FROM T, InnoDB doit scanner l'index de la table, ce qui prendra du temps si la table n'est pas enregistrée dans le buffer. Pour accélérer le compte, vous devez créer un compteur de table vous-même, et votre application le modifiera à chaque ajout ou suppression. Si votre table ne change pas souvent, l'utilisation du cache sera une bonne solution. SHOW TABLE STATUS peut aussi être utilisé pour obtenir un décompte approximatif des lignes. Voir Section 15.12, « Conseils pour l'amélioration des performances InnoDB ».

- Pour une colonne AUTO_INCREMENT, vous devez toujours définir un index pour la table, et cet index doit contenir uniquement la colonne AUTO_INCREMENT. Dans les tables MyISAM, la colonne AUTO_INCREMENT peut faire partie d'un index multicolonne.

- InnoDB ne supporte pas l'option de configuration initiale des colonnes AUTO_INCREMENT dans les commandes CREATE TABLE ou ALTER TABLE. Pour configurer cette valeur avec une table InnoDB, insérez une ligne avec une valeur inférieure d'une unité à votre valeur de départ, ou bien insérez la première ligne en spécifiant la première valeur.

- Lorsque vous redémarrez le serveur MySQL, InnoDB peut réutiliser une ancienne valeur de la séquence AUTO_INCREMENT (c'est-à-dire, une valeur qui a été assignée à une transaction annulée).

- Lorsque la colonne AUTO_INCREMENT n'a plus de valeurs, InnoDB passe le BIGINT à -9223372036854775808 et les BIGINT UNSIGNED à 1. Cependant, les valeurs BIGINT sont codées sur 64 bits, alors même si vous insérez 1 million lignes par seconde, cela vous prendra un million d'années avant d'atteindre la limite des BIGINT. Avec les autres types de colonnes, une erreur de clé doublon sera émise. C'est identique au fonctionnement des tables MyISAM, le comportement général de MySQL, et ce n'est pas caractéristique d'un moteur spécifique.

- DELETE FROM TABLE ne régénère pas la table, mais au lieu de cela, il efface les lignes une à une, ce qui est bien plus lent. Dans les prochaines versions, MySQL va pouvoir utiliser la commande TRUNCATE qui est très rapide.

- TRUNCATE tbl_name est synonyme de DELETE FROM tbl_name pour InnoDB et ne remet pas à zéro le compteur de AUTO_INCREMENT.

- SHOW TABLE STATUS ne donne pas de statistiques exactes pour les tables InnoDB, hormis pour la taille physique réservée par la table. Le nombre de lignes n'est qu'une estimation utilisée pour les optimisations SQL.

- Si vous essayez de créer un index unique sur un préfixe d'une colonne, vous allez obtenir une erreur :

CREATE TABLE T (A CHAR(20), B INT, UNIQUE (A(5))) TYPE = InnoDB;

Si vous créez un index non unique sur un préfixe de colonne, InnoDB va créer un index pour toute la colonne.

Ces restrictions sont levées depuis les versions 4.0.14 et 4.1.1.

- INSERT DELAYED n'est pas supporté par les tables InnoDB.

- La commande MySQL LOCK TABLES ne reconnaît pas le verrouillage de ligne InnoDB réalisé dans les commandes SQL achevées : cela signifie que vous pouvez poser un verrou sur une table même s'il existe une transaction qui a été posée par un autre utilisateur. Par conséquent, votre opération doit attendre que les autres tables soient libres, et elle peut aussi entrer en conflit avec une autre requête. De plus, un blocage de verrous est possible, mais il ne met pas en danger l'intégrité des transactions, car le verrou de ligne posé par InnoDB se charge toujours de l'intégrité. Enfin, un verrou de table évite aux autres transactions de poser un verrou de ligne (en conflit avec le mode de verrous) sur la table.

- Avant MySQL 3.23.52, la réplication fonctionnait toujours en mode d'autovalidation. Par conséquent, les lectures cohérentes de l'esclave voyaient aussi les transactions partiellement traitées, et la cohérence n'était pas assurée. Cette restriction a été levée en MySQL 3.23.52.

- La commande LOAD TABLE FROM MASTER de configuration de la réplication ne fonctionne pas pour les tables InnoDB. Un palliatif consiste à modifier la table en MyISAM sur le maître, faire la configuration, puis repasser la table en format InnoDB.

- La taille par défaut d'une page de base avec InnoDB est de 16 ko. En recompilant le code, vous pouvez donner une valeur allant de 8 ko à 64 ko. Vous pouvez mettre à jour les valeurs des constantes UNIV_PAGE_SIZE et UNIV_PAGE_SIZE_SHIFT dans le fichier univ.i.

15-R - Résolution de problèmes avec InnoDB

- Une règle générale est que lorsqu'une opération échoue ou que vous soupçonnez un bogue, vous devez lire le fichier de logs d'erreurs de MySQL, qui porte généralement le nom de hostname.err, ou, sous Windows, mysql.err.

- Lorsque vous recherchez une solution, il est généralement bon de faire tourner le serveur depuis la ligne de commande, et non pas avec le script mysqld_safe ou comme service Windows. Vous verrez ce que mysqld affiche directement dans le terminal, et vous aurez une meilleure idée de ce qui se passe. Sous Windows, vous devez lancer le serveur avec --console pour voir le résultat dans la console.

- Utilisez le moniteur InnoDB pour avoir des informations sur un problème. Si le problème est lié aux performances, ou si votre serveur semble gelé, vous devriez utiliser innodb_monitor pour afficher les informations sur l'état interne de InnoDB. Si le problème est lié aux verrous, utilisez innodb_lock_monitor. Si le problème est lié à la création de table ou lié aux dictionnaires de données, utilisez innodb_table_monitor pour voir le contenu du dictionnaire de données internes d'InnoDB.

- Si vous suspectez qu'une table est corrompue, utilisez la commande CHECK TABLE sur cette table.

15-R-1 - Solutions pour le dictionnaire de données InnoDB

Un problème spécifique avec les tables est que le serveur MySQL garde les données dans un dictionnaire de données .frm, qu'il stocke dans le dossier de base de données, alors que InnoDB stocke aussi les informations dans son propre dossier de données dans l'espace de tables. Si vous déplacez le fichier .frm, ou si vous utilisez DROP DATABASE en MySQL versions 3.23.44 et plus anciennes, ou si le serveur crashe au milieu d'une opération dans le dictionnaire de données, le fichier .frm peut être déconnecté du dictionnaire de données interne InnoDB.

Un symptôme de ce déphasage est que les commandes CREATE TABLE échouent. Si cela arrive, vous devez lire le fichier de logs d'erreurs. Si le fichier de logs dit que la table existe déjà dans le dictionnaire interne d'InnoDB, vous avez un fichier de tables orphelin dans l'espace de tables InnoDB, qui n'a plus de fichier .frm correspondant. Le message d'erreur ressemble à ceci :

InnoDB: Error: table test/parent already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? Have you used DROP DATABASE
InnoDB: for InnoDB tables in MySQL version <= 3.23.43?
InnoDB: See the Restrictions section of the InnoDB manual.
InnoDB: You can drop the orphaned table inside InnoDB by
InnoDB: creating an InnoDB table with the same name in another
InnoDB: database and moving the .frm file to the current database.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.

Vous pouvez effacer le fichier orphelin en suivant les instructions du message d'erreur.

Un autre symptôme de déphasage est que MySQL affiche une erreur qui dit qu'il ne peut pas ouvrir le fichier .InnoDB :

ERROR 1016: Can't open file: 'child2.InnoDB'. (errno: 1)

Dans les logs d'erreurs, vous trouverez le message suivant :

InnoDB: Cannot find table test/child2 from the internal data dictionary
InnoDB: of InnoDB though the .frm file for the table exists. Maybe you
InnoDB: have deleted and recreated InnoDB data files but have forgotten
InnoDB: to delete the corresponding .frm files of InnoDB tables?

Cela signifie qu'il y a un fichier .frm orphelin sans table correspondante dans les données InnoDB. Vous pouvez effacer simplement le fichier orphelin .frm.

Si MySQL crashe au milieu d'une opération ALTER TABLE, vous pouvez vous retrouver avec un fichier temporaire de table, orphelin, dans le code InnoDB. Avec innodb_table_monitor vous pouvez voir une table dont le nom est #sql..., mais comme MySQL ne vous permet pas d'accéder à une table avec un tel nom vous ne pouvez ni l'effacer, ni la détruire. La solution est d'utiliser un mécanisme spécial, disponible depuis MySQL 3.23.48.

Lorsque vous avez une table orpheline #sql_id dans un espace de tables, vous pouvez faire que InnoDB le renomme en rsql_id_recover_innodb_tmp_table avec la commande :

CREATE TABLE `rsql_id_recover_innodb_tmp_table`(...) TYPE=InnoDB;

Les guillemets obliques autour du nom de table sont nécessaires, car une table temporaire contient un tiret '-'.

La définition de la table doit être similaire à celle de la table temporaire. Si vous ne connaissez pas la définition de la table temporaire, vous pouvez utiliser une définition arbitraire dans la commande CREATE TABLE précédente, et ensuite, remplacer le fichier rsql_id.frm par le fichier #sql_id.frm de la table temporaire. Notez que pour copier ou pour renommer un fichier dans le shell, vous devez mettre le nom du fichier entre guillemets, car le nom du fichier contient '#'. Alors, vous pouvez exporter et effacer la table renommée.

16 - Introduction à MySQL Cluster

MySQL Cluster utilise le nouveau moteur de table NDB Cluster pour faire fonctionner plusieurs serveurs MySQL en cluster. Le code du moteur NDB Cluster est disponible dans le serveur BitKeeper de MySQL depuis la version 4.1.2 et avec les distributions binaires depuis MySQL-Max 4.1.3.

Actuellement, les systèmes d'exploitation supportés sont Linux, Mac OS X et Solaris. Nous travaillons à rendre NDB Cluster disponible sur toutes les plateformes que supporte MySQL, y compris Windows.

Ce chapitre est en cours de rédaction. Les autres documents décrivant le cluster MySQL sont disponibles à http://www.mysql.com/cluster et http://dev.mysql.com/doc.

Vous pouvez aussi vous inscrire sur la liste de diffusion du cluster MySQL. Voyez http://lists.mysql.com/.

16-1 - Présentation de MySQL Cluster

Un Cluster MySQL est un groupe de processus qui s'exécutent sur plusieurs serveurs MySQL, des nœuds NDBCluster, et des processus d'administration, ainsi que des processus d'accès spécialisés. Tous ces programmes fonctionnent ensemble pour former un Cluster MySQL. Lorsque les données sont stockées dans le moteur NDBCluster, les tables sont réparties sur les nœuds NDBCluster. Ces tables sont directement accessibles depuis tous les autres serveurs MySQL faisant partie du Cluster. Par conséquent, si une application met à jour une ligne, tous les autres serveurs le verront immédiatement.

Les données stockées dans le moteur de table de MySQL Cluster peuvent être dupliquées, et sont capables de gérer une indisponibilité d'un nœud sans autre impact que l'annulation des transactions qui utilisaient ces données. Cela ne devrait pas être un problème, car les applications transactionnelles sont écrites pour gérer les échecs de transaction.

En plaçant MySQL Cluster en Open Source, MySQL rend les hautes performances, haute disponibilité et grands trafics accessibles à tous ceux qui en ont besoin.

16-2 - Concepts de base de MySQL Cluster

MySQL Cluster est constitué de trois types de programmes différents :

- premièrement, un jeu de processus serveur MySQL. Ce sont des serveurs MySQL traditionnels, avec le nouveau moteur de table NDBCluster qui autorise l'accès aux tables en cluster ;

- le second type de processus est représenté par les nœuds de stockage de NDBCluster. Ces processus contiennent les données stockées dans MySQL Cluster. Les données de MySQL Cluster sont réparties entre les différents nœuds du cluster, et sont aussi doublées dans le cluster ;

- le troisième type de processus est les processus d'administration. Ces processus sont utilisés pour gérer la configuration du cluster.

Nous appelons ces processus de cluster les nœuds du cluster. Mettre en place la configuration du cluster implique la configuration de chaque nœud dans le cluster, et la configuration de chaque moyen de communication entre les nœuds du cluster. MySQL Cluster est actuellement configuré avec le prérequis que les nœuds sont homogènes en termes de puissance processeur, espace mémoire et largeur de bande. De plus, pour activer un point de configuration, il a été décidé de placer toute la configuration du cluster dans un seul fichier de configuration.

Les processus d'administration gèrent le fichier de configuration du cluster, et les logs. Tous les nœuds dans le cluster contactent le serveur d'administration pour lire leur configuration : ils doivent donc savoir où le serveur d'administration réside en premier lieu. Lorsqu'un événement pertinent survient dans un moteur de stockage, il est transféré au serveur d'administration qui l'écrit dans le log.

De plus, il y a un nombre arbitraire de clients connectés au cluster. Ils sont de deux types. D'abord, les clients MySQL normaux, qui ne sont pas spécifiques à MySQL Cluster. MySQL Cluster est accessible à partir des applications MySQL écrites en PHP, Perl, C, C++, Java, Ruby, etc. Deuxièmement, les clients d'administration. Ces clients accèdent au serveur d'administration, et émettent des commandes pour lancer ou arrêter correctement des nœuds, lancer ou arrêter la trace serveur (pour les versions de débogage), pour afficher la configuration courante, voir l'état des nœuds du cluster, afficher les versions et nœuds, lancer les sauvegardes, etc.

16-3 - Configuration simple multiserveur

Cette section est un guide qui décrit comment planifier l'installation, configurer et faire fonctionner un cluster MySQL viable. Contrairement aux exemples de la section Section 16.4, « Configuration de MySQL Cluster », le résultat de ces procédures est un cluster MySQL fonctionnel, qui dispose des fonctionnalités minimales pour assurer la disponibilité et la sauvegarde des données.

Dans cette section, nous allons couvrir : le matériel et les logiciels nécessaires ; les problèmes réseau ; l'installation de MySQL et du cluster ; la configuration ; le démarrage, l'arrêt et le redémarrage du cluster MySQL ; le chargement de données dans une base d'exemple ; l'exécution de requêtes.

Hypothèses de base

Ce guide part des hypothèses suivantes.

1. Nous allons configurer un cluster de quatre nœuds, chacun sur un hôte distinct, et chacun des hôtes étant relié au réseau avec une adresse IP fixe, via une carte Ethernet classique, comme ceci :

Nœud

Adresse IP

nœud de gestion (MGM)

192.168.0.10

Serveur MySQL (SQL)

192.168.0.20

Serveur de stockage (NDBD) « A »

192.168.0.30

Serveur de stockage (NDBD) « B »

192.168.0.40

Cela est peut-être plus clair sur le schéma suivant :

Note : par souci de simplicité et de robustesse, nous allons utiliser les adresses IP numériques dans ce guide. Cependant, si la résolution DNS est disponible sur votre réseau, il est aussi possible d'utiliser les noms d'hôtes plutôt que les IP lors de la configuration du cluster. Alternativement, vous pouvez aussi utiliser le fichier /etc/hosts de votre système d'exploitation ou son équivalent pour fournir un système de résolution de noms.

2. Chaque hôte est un ordinateur de bureau Intel, avec une distribution générique Linux sur le disque, dans une configuration standard, et sans aucun service inutile. Le cœur du système et un client standard TCP/IP doivent être suffisants. De même, par souci de simplicité, nous allons supposer que les systèmes de fichiers des hôtes sont tous identiques. Dans le cas où ils ne le sont pas, vous devrez adapter les instructions en fonction des situations.

3. Des cartes 100 mégabits ou gigabits Ethernet sont installées sur chaque machine, avec les bons pilotes pour les cartes, et chaque hôte est connecté au réseau via un routeur standard, comme un switch. Toutes les machines doivent utiliser des cartes avec le même débit, c'est-à-dire que toutes les machines du cluster sont en 100 mégabits, ou bien en gigabit. Le cluster MySQL fonctionnera sur un réseau 100 mégabits, mais les cartes gigabit fourniront de meilleures performances.
Notez que le cluster MySQL n'est pas prévu pour fonctionner sur un réseau avec une connectivité inférieure à 100 mégabits. Pour cette raison, entre autres, faire fonctionner un cluster MySQL sur un réseau public ou via Internet risque de ne pas réussir, et n'est pas recommandé.

4. Pour les données de tests, nous allons utiliser la base de données world qui est disponible en téléchargement sur le site de MySQL AB. Comme cette base de données prend peu d'espace, nous pouvons fonctionner avec des machines ayant 256 Mo de RAM, ce qui doit être suffisant pour le système d'exploitation, les processus NDB et le stockage dans les nœuds.

Même si nous faisons référence à Linux comme système d'exploitation dans ce guide, les instructions et les procédures sont faciles à adapter pour Solaris ou Mac OS X. Nous supposons aussi que vous savez faire une installation minimale et la configuration du système d'exploitation en réseau, ou que vous disposez d'assistance pour ce faire.

Nous allons présenter les besoins en matériel, logiciels et réseau pour le cluster MySQL dans la prochaine section. Voyez Section 16.3.1, « Matériel, logiciels et réseau ».

16-3-1 - Matériel, logiciels et réseau

Une des forces du Cluster MySQL est qu'il peut fonctionner sur n'importe quel serveur, et n'a pas de prérequis particulier, en dehors d'une grande quantité de mémoire vive, due au fait que toutes les données sont stockées en mémoire. Notez que cela pourrait changer à l'avenir, et que nous travaillons à avoir un stockage sur disque dans les prochaines versions du Cluster MySQL. Naturellement, les machines multiprocesseurs et celles aux fréquences supérieures seront plus rapides. Les besoins en RAM des processus du Cluster MySQL sont relativement raisonnables.

Les besoins en logiciels pour le Cluster MySQL sont aussi modestes. Les systèmes d'exploitation hôtes n'ont pas besoin de modules particuliers, ni services, ni applications ou configurations pour supporter Cluster MySQL. Pour Mac OS X ou Solaris, l'installation standard est suffisante. Pour Linux, une installation standard de base doit être suffisante. Les prérequis pour MySQL sont simples : tout ce qui est nécessaire pour faire fonctionner MySQL-max 4.1.3 ou plus récent ; vous devez utiliser la version -max de MySQL pour avoir le support du Cluster MySQL. Il n'est pas nécessaire de compiler MySQL vous-même pour être en mesure d'exécuter le Cluster MySQL. Dans cette documentation, nous allons supposer que vous utilisez le binaire -max adapté à votre système, disponible via la page de téléchargements de MySQL : http://dev.mysql.com/downloads.

Pour les communications entre les nœuds, Cluster MySQL supporte le protocole TCP/IP pour toutes les topologies, et le minimum attendu pour chaque hôte est une carte Ethernet 100 mégabits, plus un switch, hub ou routeur pour fournir la connectivité entre les parties du Cluster. Nous recommandons vivement que le Cluster MySQL dispose de son propre masque de sous-réseau pour les raisons suivantes.

- Sécurité : les communications entre les nœuds du Cluster MySQL ne sont pas chiffrées ou protégées de quelque manière que ce soit. La seule solution pour protéger les transmissions à l'intérieur du Cluster MySQL est de placer le Cluster MySQL dans un réseau protégé. Si vous envisagez d'utiliser le Cluster MySQL pour une application Web, il est recommandé que le Cluster MySQL soit placé derrière un pare-feu, et non pas dans la zone démilitarisée (DMZ) ou ailleurs.

- Efficacité : configurer un Cluster MySQL sur un réseau privé ou protégé donne au Cluster MySQL l'exclusivité de la bande passante. En utilisant un switch dédié au Cluster MySQL aide à la protection contre les accès non autorisés, et il protège les nœuds des interférences causées par les autres machines sur le réseau. Pour une stabilité accrue, vous pouvez utiliser des switchs redondants et des cartes réseau doubles pour supprimer du réseau les points de panne : de nombreux pilotes réseau savent s'adapter si une panne survient sur un brin de réseau.

Il est aussi possible d'utiliser l'interface SCI (Scalable Coherent Interface à haute vitesse, avec le Cluster MySQL, mais ce n'est pas nécessaire. Voyez Section 16.7, « Utilisation d'interconnexions haute vitesse avec MySQL Cluster » pour plus d'informations sur ce protocole et ses utilisations avec Cluster MySQL.

16-3-2 - Installation

Chaque hôte du cluster MySQL qui héberge un nœud de stockage ou un nœud SQL doit être installé avec MySQL-max. Pour les nœuds de gestion, il n'est pas nécessaire d'installer un serveur MySQL, mais vous devez installer un démon MGM et les clients ndb_mgmd et ndb_mgm, respectivement. Dans cette section, nous allons voir les étapes nécessaires pour installer correctement chaque serveur pour un nœud du cluster.

Au moment de l'écriture de cette section, les versions les plus récentes étaient MySQL 4.1.10a ; si une version plus récente est disponible, il est recommandé de l'installer et d'utiliser ce numéro de version dans tout le reste de la section. MySQL fournit des serveurs précompilés, et il n'y a généralement pas besoin de compiler par vous-même. Si vous voulez faire une compilation personnalisée, voyez Section 2.4.3, « Installer à partir de l'arbre source de développement ». Par conséquent, la première étape de l'installation de chaque hôte du cluster est de télécharger le fichier mysql-max-4.1.10a-pc-linux-gnu-i686.tar.gz depuis MySQL downloads area. Nous supposons que vous l'avez fait, et installé dans le dossier /var/tmp de chaque machine.

Des RPM sont aussi disponibles pour les plateformes 32 et 62 bits; depuis MySQL 4.1.10a, les serveurs MySQL-max installés via RPM supportent les clusters NDB. Si vous choisissez d'utiliser ces outils plutôt que les fichiers binaires, assurez-vous d'installer à la fois les paquets -serveur et -max sur toutes les machines qui hébergent des nœuds du cluster. Voyez Linux pour plus d'informations sur l'installation de MySQL en RPM. Après l'installation des RPM, vous devez toujours configurer le cluster, tel que présenté dans Section 16.3.3, « Configuration ».

Note : après l'installation, ne lancez pas encore les logiciels. Nous allons vous montrer comment le faire, alors suivez d'abord la configuration des nœuds.

Installation des nœuds de stockage et SQL

Pour chacune des machines désignées pour être des hôtes de stockage ou des hôtes SQL, suivez les étapes suivantes, en tant que super utilisateur :

1. Vérifiez vos fichiers /etc/passwd et /etc/group ou utilisez les outils systèmes dont vous disposez pour gérer les groupes et utilisateurs pour vérifier si vous avez un groupe mysql et un utilisateur mysql sur votre système : certaines distributions les créent automatiquement lors de leur installation. Si ces comptes n'existent pas, alors créez un groupe mysql et un utilisateur mysql, comme ceci :

groupadd mysql
useradd -g mysql mysql

2. Placez-vous dans le dossier qui contient le fichier téléchargé; décompressez l'archive ; créez un lien symbolique vers l'exécutable mysql-max :

cd /var/tmp
tar -xzvf -C /usr/local/bin mysql-max-4.1.10a-pc-linux-gnu-i686.tar.gz
ln -s /usr/local/bin/mysql-max-4.1.10a-pc-linux-gnu-i686 mysql

3. Placez-vous dans le dossier mysql, et exécutez le script fourni pour la création des bases de données système :

cd mysql
scripts/mysql_install_db --user=mysql

4. Donnez les droits nécessaires au serveur MySQL et au dossier de données :

chown -R root .
chown -R mysql data
chgrp -R mysql .

Notez que le dossier de données de chaque machine qui héberge un nœud de stockage est /usr/local/mysql/data. Nous allons utiliser cette information lors de la configuration du nœud de gestion. Voyez Section 16.3.3, « Configuration » ;

5. Copiez le script de démarrage MySQL dans le dossier approprié, rendez-le exécutable, et configurez-le pour qu'il s'exécute lorsque le système d'exploitation démarre :

cp support-files/mysql.server /etc/rc.d/init.d/
chmod +x /etc/rc.d/init.d/mysql.server
chkconfig --add mysql.server

Ici, nous utilisons la commande de Red Hat chkconfig pour créer les liens vers les scripts de démarrage ; utilisez les moyens appropriés pour faire la même chose sur votre système d'exploitation, tel que update-rc.d sur Debian.

N'oubliez pas que ces listes d'instructions doivent être exécutées séparément sur chaque machine qui sera un nœud de stockage ou un nœud SQL.

Installation du nœud de gestion

Pour le nœud MGM (serveur de gestion), il n'est pas nécessaire d'installer mysqld, mais seulement le serveur MGM et les clients, qui sont disponibles dans l'archive -max. Encore une fois, nous supposons que vous avez placé de fichier dans le dossier /var/tmp. En tant que root (c'est-à-dire, après avoir exécuté la commande su root ou l'équivalent sur votre système pour se faire attribuer les droits de super utilisateur), effectuez les commandes suivantes pour installer ndb_mgmd et ndb_mgm sur l'hôte de gestion :

1. Allez dans le dossier /var/tmp et décompressez ndb_mgm et ndb_mgmd de l'archive, dans un dossier approprié, comme /usr/local/bin :

cd /var/tmp
tar -zxvf mysql-max-4.1.10a-pc-linux-gnu-i686.tar.gz /usr/local/bin '*/bin/ndb_mgm*'

2. Placez-vous dans le dossier où vous avez décompressé les fichiers, puis rendez-les tous les deux exécutables :

cd /usr/local/bin
chmod +x ndb_mgm*

Dans Section 16.3.3, « Configuration », nous allons créer et configurer les fichiers pour tous les nœuds du cluster d'exemple.

16-3-3 - Configuration

Pour notre MySQL Cluster de quatre nœuds et quatre hôtes, nous aurons besoin de préparer quatre fichiers de configuration, un par hôte/nœud.

- Chaque nœud de stockage ou nœud SQL a besoin d'un fichier my.cnf qui fournit deux informations : une chaîne connectstring qui indique au nœud où trouver le nœud MGM, et une ligne indiquant au serveur MySQL de cet hôte de fonctionner en mode NDB.
Pour plus d'informations sur les chaînes de connexion, voyez Section 16.4.4.2, « La chaîne connectstring du Cluster MySQL ».

- Le nœud de gestion a besoin d'un fichier config.ini qui indique combien de répliques doivent être gérées, combien de mémoire allouer pour les données et les index sur chaque nœud de stockage, où trouver les nœuds de stockage, où les données seront sauvées sur le disque, et où trouver les nœuds SQL.

Configurer les nœuds de stockage et SQL

Le fichier my.cnf destiné aux nœuds de stockage est plutôt simple. Le fichier de configuration doit être placé dans le dossier /etc et peut être édité ou créé avec n'importe quel éditeur fichier. Par exemple :

vi /etc/my.cnf

Pour chaque nœud de stockage et chaque nœud SQL de notre exemple, le fichier my.cnf doit ressembler à ceci :

[MYSQLD]                        # Options du processus mysqld
ndbcluster                      # Fonctionne en mode NDB
ndb-connectstring=192.168.0.10  # Situation du nœud MGM

[MYSQL_CLUSTER]                 # Options pour le processus ndbd
ndb-connectstring=192.168.0.10  # Situation du nœud MGM

Après la saisie des données ci-dessus, sauvez ce fichier et quittez l'éditeur de texte. Faites cela pour les nœuds de stockages « A » et « B », et le nœud SQL.

Configuration du nœud de gestion

La première étape de configuration du nœud MGM est la création du dossier dans lequel le fichier de configuration sera placé, et d'y créer le fichier lui-même. Par exemple, lors d'un fonctionnement root :

mkdir /var/lib/mysql-cluster
cd /var/lib/mysql-cluster
vi config.ini

Nous présentons ici la commande vi utilisée pour créer le fichier, mais n'importe quel autre éditeur texte fonctionne aussi bien.

Pour notre configuration d'exemple, config.ini doit contenir les informations suivantes.

[NDBD DEFAULT]    # Options affectant les processus ndbd processes sur tous les nœuds
NoOfReplicas=2    # Nombre de répliques
DataMemory=80M    # Mémoire à allouer pour le stockage des données
IndexMemory=52M   # Mémoire à allouer pour le stockage des index
# Pour DataMemory et IndexMemory, nous avons utilisé les
# valeurs par défaut. Comme la base de données "world"
# ne prend que 500KB, cela devrait être suffisant pour notre
# exemple de Cluster

[TCP DEFAULT]     # Options TCP/IP
portnumber=2202   # Ceci est la valeur par défaut. Cependant, nous pourrions
# utiliser un port libre pour les autres hôtes du cluster.
# Note : il est recommandé avec MySQL 5.0 de ne pas spécifier
# de port, et de laisser la valeur par défaut.

[NDB_MGMD]                      # Options de gestion des processus :
hostname=192.168.0.10           # Nom d'hôte ou adresse IP du nœud MGM
datadir=/var/lib/mysql-cluster  # Dossier des fichiers de logs du nœud MGM

[NDBD]                          # Options pour le stockage du nœud "A" :
# (une section [NDBD] par nœud de stockage)
hostname=192.168.0.30           # Nom d'hôte ou adresse IP
datadir=/usr/local/mysql/data   # Dossier pour les fichiers de données du nœud

[NDBD]                          # Options pour le stockage du nœud "B" :
hostname=192.168.0.40           # Nom d'hôte ou adresse IP
datadir=/usr/local/mysql/data   # Dossier pour les fichiers de données du nœud

[MYSQLD]                        # Options des nœuds SQL :
hostname=192.168.0.20           # Nom d'hôte ou adresse IP
datadir=/usr/local/mysql/data   # Dossier pour les fichiers SQL du nœud
# (Les connexions mysqld supplémentaires peuvent
# être spécifiées pour ce nœud pour différents
# objectifs, comme l'exécution de ndb_restore)

NOTE : la base de données « world » peut être téléchargée sur le site http://dev.mysql.com/doc/, rangé dans la section d'exemples : Examples.

Une fois que tous les fichiers de configuration ont été créés et que ces options minimales ont été spécifiées, vous êtes prêts à lancer le cluster MySQL et à vérifier que les processus fonctionnent. La présentation de cette étape est faite dans Section 16.3.4, « Démarrage initial ».

Pour plus de détails sur les paramètres de configuration du cluster MySQL, voyez Section 16.4.4, « Fichier de configuration » et Section 16.4, « Configuration de MySQL Cluster ». Pour la configuration du Cluster MySQL au sujet des sauvegardes, voyez Section 16.6.4.4, « Configuration pour la sauvegarde du Cluster ».

Note : le port par défaut pour le nœud de gestion du Cluster MySQL est le 1186, le port par défaut pour les nœuds de stockage est 2202.

16-3-4 - Démarrage initial

Démarrer le cluster n'est pas très difficile une fois qu'il a été configuré. Chaque nœud doit être lancé séparément, et depuis l'hôte sur lequel il réside. Même s'il est possible de lancer les nœuds dans n'importe quel ordre, il est recommandé de lancer le serveur d'administration en premier, puis les nœuds de stockage et enfin, les nœuds SQL :

1. Sur l'hôte de gestion, utilisez la commande suivante depuis le Shell pour lancer le processus de gestion :

shell> ndb_mgmd -f /var/lib/mysql-cluster/config.ini

Notez que ndb_mgmd doit recevoir le nom et chemin du fichier de configuration, avec l'option -f ou --config-file. Voyez Section 16.5.3, « ndb_mgmd, le serveur de gestion » pour plus de détails ;

2. Sur chaque hôte de stockage, exécutez cette commande pour lancer les processus NDBD :

shell> ndbd --initial

Notez qu'il est très important d'utiliser le paramètre --initial uniquement lors du premier démarrage de ndbd, ou lors du redémarrage après une opération de restauration des données ou de modification de configuration. En effet, ce paramètre va forcer le nœud à effacer les fichiers créés par les anciennes instances de ndbd, y compris les fichiers de log ;

3. Sur les hôtes SQL, exécutez une commande mysqld classique :

shell> mysqld &

Si tout se passe bien, et que le cluster a été correctement configuré, il devrait être opérationnel à nouveau. Vous pouvez tester cela en utilisant la commande ndb_mgm, c'est-à-dire le client de gestion ; le résultat devrait être similaire à celui-ci :

shell> ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=2    @192.168.0.30  (Version: 4.1.11, Nodegroup: 0, Master)
id=3    @192.168.0.40  (Version: 4.1.11, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @192.168.0.10  (Version: 4.1.11)

[mysqld(SQL)]   1 node(s)
id=4   (Version: 4.1.11)

Vous pouvez rencontrer diverses adaptations en fonction des versions exactes de MySQL que vous utilisez.

Note : si vous utilisez une ancienne version de MySQL, vous pourriez voir les nœuds SQL référencés sous le nom '[mysqld(API)]'. C'est une ancienne pratique qui n'a plus cours.

Vous êtes maintenant prêts à utiliser vos bases de données, vos tables et vos données dans le cluster MySQL. Voyez Section 16.3.5, « Charger les données d'exemple et exécuter des requêtes » pour aller plus loin.

16-3-5 - Charger les données d'exemple et exécuter des requêtes

Travailler avec le cluster MySQL n'est pas différent de travailler avec un serveur MySQL classique. Il y a deux points importants à garder en tête.

- Les tables doivent être créées avec le moteur ENGINE=NDB ou ENGINE=NDBCLUSTER, ou doivent être modifiées avec ALTER TABLE pour qu'elles utilisent le moteur NDB, afin qu'elles soient gérées par le cluster. Si vous importez des tables depuis une base de données existante en utilisant le résultat de mysqldump, vous pouvez ouvrir le script SQL dans un éditeur de texte, et ajoutez cette option à toutes les créations de tables, ou bien remplacez les options ENGINE ou TYPE) avec l'une des valeurs ci-dessous. Par exemple, en supposant que vous utilisez la base world dans un autre serveur MySQL, qui ne supporte pas le cluster MySQL, et que vous voulez exporter la définition de la table CITY :

shell> mysqldump --add-drop-table world City > city_table.sql

Le résultat du fichier city_table.sql contient la commande de création de la table et les commandes d'insertion INSERT pour importer les données dans la table :

DROP TABLE IF EXISTS City;
CREATE TABLE City (
ID int(11) NOT NULL auto_increment,
Name char(35) NOT NULL default '',
CountryCode char(3) NOT NULL default '',
District char(20) NOT NULL default '',
Population int(11) NOT NULL default '0',
PRIMARY KEY  (ID)
) TYPE=MyISAM;

INSERT INTO City VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO City VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO City VALUES (3,'Herat','AFG','Herat',186800);
# (remaining INSERT statements omitted)

Vous devez vous assurer que MySQL utilise le moteur NBD pour cette table. Il y a deux moyens pour le faire. L'un d'eux, avant l'importation des données dans la table, consiste à modifier la définition de la table pour qu'elle corresponde à ceci (toujours en utilisant la table City) :

DROP TABLE IF EXISTS City;
CREATE TABLE City (
ID int(11) NOT NULL auto_increment,
Name char(35) NOT NULL default '',
CountryCode char(3) NOT NULL default '',
District char(20) NOT NULL default '',
Population int(11) NOT NULL default '0',
PRIMARY KEY  (ID)
) ENGINE=NDBCLUSTER;

INSERT INTO City VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO City VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO City VALUES (3,'Herat','AFG','Herat',186800);
# (etc.)

Cela doit être fait pour la définition de chaque table qui fait partie de la base de données en cluster. Le plus simple pour faire cela est de faire un rechercher/remplacer dans le fichier world.sql et de remplacer toutes les instances de TYPE=MyISAM par ENGINE=NDBCLUSTER. Si vous ne voulez pas modifier ce fichier, vous pouvez aussi utiliser la commande ALTER TABLE; voyez plus bas pour les spécificités.

En supposant que vous avez déjà créé la base de données appelée world sur le nœud SQL du cluster, vous pouvez utiliser l'utilitaire de ligne de commande mysql pour lire le fichier city_table.sql, et créer puis remplir la table, comme ceci :

shell> mysql world < city_table.sql

Il est très important de garder en tête que les commandes ci-dessus doivent être exécutées sur l'hôte où le nœud SQL tourne : dans ce cas, sur la machine avec l'adresse IP 192.168.0.20.

Pour créer une copie de la base de données world sur le nœud SQL, sauvez le fichier dans /usr/local/mysql/data, puis exécutez ces commandes :

shell> cd /usr/local/mysql/data
shell> mysql world < world.sql

Bien sûr, le script SQL doit être lisible par l'utilisateur mysql. Si vous sauvez le fichier à un autre endroit, ajustez les chemins dans les commandes ci-dessus.

Exécuter les commandes SELECT sur un nœud SQL n'est pas différent de les exécuter sur une autre instance de serveur MySQL. Pour exécuter les requêtes SQL en ligne de commande, vous devez vous identifier sur le serveur, comme d'habitude :

shell> mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.1.9-max

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

Si vous n'avez pas modifié les clauses ENGINE= dans les définitions de tables, vous pouvez alors utiliser ces commandes :

mysql> USE world;
mysql> ALTER TABLE City ENGINE=NDBCLUSTER;
mysql> ALTER TABLE Country ENGINE=NDBCLUSTER;
mysql> ALTER TABLE CountryLanguage ENGINE=NDBCLUSTER;

Notez que nous avons simplement utilisé le compte d'administrateur par défaut, sans mot de passe. Bien entendu, dans un environnement de production, il est recommandé de toujours suivre les précautions de sécurité, y compris l'utilisation d'un mot de passe robuste pour le super utilisateur, et la création d'un compte spécifique, avec uniquement les droits nécessaires aux tâches incombantes. Pour plus de détails, voyez la section Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

Il est à noter que les nœuds du cluster n'utilisent pas les droits d'accès MySQL lorsqu'ils se connectent l'un à l'autre : modifier ces droits n'a pas d'effet sur les communications entre les nœuds.

Sélectionner la base de données et exécuter une requête SELECT sur une table se fait comme d'habitude :

mysql> USE world;
mysql> SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5;
+-----------+------------+
| Name      | Population |
+-----------+------------+
| Bombay    |   10500000 |
| Seoul     |    9981619 |
| SÃ£o Paulo |    9968485 |
| Shanghai  |    9696300 |
| Jakarta   |    9604900 |
+-----------+------------+
5 rows in set (0.34 sec)

mysql> \q
Bye

shell>

Les applications qui reposent sur MySQL peuvent utiliser l'API standard. Il est important de penser à ce que votre application doit se connecter à un nœud SQL, et non pas aux nœuds de stockage ou au serveur de gestion. Cet exemple montre comment vous pourriez exécuter une requête en utilisant l'extension mysqli de PHP 5, sur un serveur Web :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<title>Sélection de données avec mysqli</title>
</head>
<body>
<?php
# Connexion au nœud SQL :
$link = new mysqli('192.168.0.20', 'root', '', 'world');
# Les paramètres pour le constructeur mysqli sont :
#   hote, utilisateur, mot de passe, base de données

if( mysqli_connect_errno() ) {
die("Connexion échouée : " . mysqli_connect_error());
}

$query = "SELECT Name, Population
FROM City
ORDER BY Population DESC
LIMIT 5";

# s'il n'y a pas d'erreur
if( $result = $link->query($query) )
{
?>
<table border="1" width="40%" cellpadding="4" cellspacing ="1">
<tbody>
<tr>
<th width="10%">Ville</th>
<th>Population</th>
</tr>
<?php
// Affichage du résultat
while($row = $result->fetch_object())
printf(<tr>\n  <td align=\"center\">%s</td><td>%d</td>\n</tr>\n",
$row->Name, $row->Population);
?>
</tbody
</table>
<?php
// Vérification du nombre de lignes lues
printf("<p>Lignes affectées : %d</p>\n", $link->affected_rows);
}
else
# Sinon, affichage de l'erreur
echo mysqli_error();

// Libération du résultat et de l'objet de connexion
$result->close();
$link->close();
?>
</body>
</html>

Nous supposons que le processus du serveur Web peut atteindre l'IP du nœud SQL.

De manière similaire, vous pouvez utiliser l'API C de MySQL, ou les interfaces Perl-DBI, Python-mysql ou encore les connecteurs de MySQL AB pour effectuer les tâches de définition de données et de manipulations, comme vous le faites habituellement avec un serveur MySQL.

- N'oubliez pas que toutes les tables NDB doivent avoir une clé primaire. Si aucune clé primaire n'est définie par l'utilisateur lors de la création de la table, le moteur de stockage NDB va en générer une automatiquement. Note : cette clé cachée prend de l'espace, comme tout autre index. Il n'est pas rare de rencontrer des problèmes de mémoire lorsque vous devez prendre en compte ces clés automatiques.

16-3-6 - Arrêt et redémarrage du cluster

Pour arrêter le cluster, utilisez simplement cette commande dans le Shell sur la machine qui héberge le serveur de gestion MGM :

shell> ndb_mgm -e shutdown

Cela va forcer les processus ndb_mgm, ndb_mgm et ndbd à s'arrêter proprement. Tous les nœuds SQL peuvent alors être arrêtés avec la commande mysqladmin shutdown classique ou par d'autres moyens.

Pour relancer le cluster, lancez simplement ces commandes :

- sur l'hôte de gestion (192.168.0.10 dans notre cas) :

shell> ndb_mgmd -f /var/lib/mysql-cluster/config.ini

- sur chaque nœud de stockage (192.168.0.30 et 192.168.0.40) :

shell> ndbd

N'oubliez pas d'invoquer cette commande avec l'option --initial lorsque vous redémarrez un nœud NDBD normalement.

- Et les hôtes SQL (192.168.0.20) :

shell> mysqld &

Pour des informations sur les sauvegardes, voyez Section 16.6.4.2, « Utilisation du serveur de gestion pour une sauvegarde de cluster ».

Pour restaurer le cluster à partir de sauvegardes, il faut utiliser la commande ndb_restore. Vous pouvez vous informer là-dessus sur Section 16.6.4.3, « Comment restaurer une sauvegarde du cluster ».

Plus d'informations sur la configuration du cluster MySQL sont disponibles dans Section 16.4, « Configuration de MySQL Cluster ».

16-4 - Configuration de MySQL Cluster

Un serveur MySQL est une partie d'un cluster MySQL, et il ne diffère d'un serveur classique que d'un seul aspect : il dispose d'un moteur de stockage supplémentaire, à savoir : NDB ou NDBCLUSTER.

À part cela, le serveur MySQL n'est pas très différent de ceux que nous utilisons traditionnellement. Par défaut, le serveur est configuré sans le moteur NDB (pour éviter d'allouer des ressources inutiles). Pour activer NDB, vous devez modifier my.cnf.

De plus, comme le serveur MySQL est une partie du cluster, il doit savoir comment accéder au nœud MGM, pour connaître la configuration du cluster. Il y a un comportement par défaut qui recherche le nœud MGM sur le serveur local. Mais si vous devez le placer ailleurs, vous pouvez le taper en ligne de commande ou bien dans le fichier my.cnf. Avant que le moteur de stockage NDB ne soit utilisé, un nœud MGM est une base de nœud qui doit être active et accessible. Le seul nœud MGM est suffisant pour démarrer.

16-4-1 - Compilation du cluster

NDB Cluster est disponible en distribution binaire depuis MySQL-Max 4.1.3.

Si vous décidez de compiler le cluster depuis les sources ou depuis MySQL 4.1 BitKeeper, assurez-vous d'utiliser l'option --with-ndbcluster avec la commande configure.

Vous pouvez aussi utiliser simplement le script BUILD/compile-pentium-max. Ce script inclut aussi OpenSSL, ce qui vous impose d'avoir OpenSSL installé ou de modifier le script de compilation pour l'exclure.

À part cela, vous pouvez suivre les instructions standard de compilation pour créer vos propres programmes, effectuer les tests et l'installation. Voir Section 2.4.3, « Installer à partir de l'arbre source de développement ».

16-4-2 - Installation du logiciel

Il est plus facile de faire l'installation si vous avez déjà installé les serveurs de gestion (MGM) et les nœuds de bases (DB), et qu'ils sont actifs : cela sera sûrement la partie la plus longue de l'installation, en supposant que vous êtes déjà maitre de MySQL. Comme pour les fichiers de configuration et my.cnf, la structure du fichier est très claire, et cette section ne couvre que les différences spécifiques du cluster, par rapport à MySQL classique.

16-4-3 - Vérification rapide du fonctionnement du cluster

Cette section montre comment configurer rapidement puis démarrer l'architecture la plus simple d'un cluster MySQL. Vous serez alors familiers avec les concepts de base. Puis, lisez les autres sections pour adapter plus finement votre installation.

Un dossier doit être créé. L'exemple utilise /var/lib/mysql-cluster. Exécutez la commande suivante, en tant que root :

shell> mkdir /var/lib/mysql-cluster

Dans ce dossier, créez un fichier config.ini avec le contenu suivant. Remplacez HostName et DataDir par les valeurs de votre installation.

# file "config.ini" - showing minimal setup consisting of 1 DB node,
# 1 management server, and 3 MySQL servers.
# The empty default sections are not needed, and are shown only for clarity.
# Storage nodes are required to provide a host name but MySQL Servers
# are not. Thus the configuration can be dynamic as to setting up the
# MySQL Servers.
# If you don't know the host name of your machine, use localhost.
# The DataDir parameter also has a default value, but it is recommended to
# set it explicitly.
# NDBD, MYSQLD, and NDB_MGMD are aliases for DB, API, and MGM respectively
#
[NDBD DEFAULT]
NoOfReplicas= 1

[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]

[NDB_MGMD]
HostName= myhost.example.com

[NDBD]
HostName= myhost.example.com
DataDir= /var/lib/mysql-cluster

[MYSQLD]
[MYSQLD]
[MYSQLD]

Vous pouvez maintenant lancer le serveur de gestion. Pour cela, faites :

shell> cd /var/lib/mysql-cluster
shell> ndb_mgmd

Puis, lancez un nœud de base, grâce au programme ndbd. Si c'est la toute première fois que vous lancez ndbd, utilisez l'option --initial :

shell> ndbd --initial

Lors des prochains appels à ndbd, ne l'utilisez plus.

shell> ndbd

Par défaut, ndbd va rechercher le serveur de gestion sur localhost, port 2200.

Notez que si vous avez installé une distribution binaire, vous aurez besoin de spécifier explicitement le chemin des commandes ndb_mgmd et ndbd. Ils se trouvent dans le dossier /usr/local/mysql/bin.

Finalement, allez dans le dossier de données MySQL (il sera probablement dans /var/lib/mysql ou /usr/local/mysql/data). Assurez-vous que le fichier my.cnf contient les options nécessaires pour activer le moteur NDB Cluster :

[mysqld]
ndbcluster

Vous pouvez maintenant lancer le serveur MySQL comme d'habitude :

shell> mysqld_safe --user=mysql &

Attendez un moment, et assurez-vous que le serveur fonctionne correctement. Si vous voyez un message « mysql ended », vérifiez le fichier d'erreur du serveur .err pour savoir ce qui se passe.

Si tout est bien allé, vous pouvez lancer le cluster :

shell> mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.1.7-gamma

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> SHOW STORAGE ENGINES;
+------------+---------+------------------------------------------------------------+
| Engine     | Support | Comment                                                    |
+------------+---------+------------------------------------------------------------+
...
| NDBCLUSTER | DEFAULT | Clustered, fault-tolerant, memory-based tables             |
| NDB        | YES     | Alias for NDBCLUSTER                                       |
...

mysql> USE test;
Database changed

mysql> CREATE TABLE ctest (i INT) ENGINE=NDBCLUSTER;
Query OK, 0 rows affected (0.09 sec)

mysql> show create table ctest \G
*************************** 1. row ***************************
Table: ctest
Create Table: CREATE TABLE `ctest` (
`i` int(11) default NULL
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Si vous voulez vérifier que vos nœuds ont été correctement configurés, vous pouvez lancer le client de gestion :

shell> ndb_mgm

Essayez d'utiliser la commande SHOW pour avoir un aperçu du cluster :

NDB> show
Cluster Configuration
---------------------
[ndbd(NDB)]     1 node(s)
id=2    @127.0.0.1  (Version: 3.5.3, Nodegroup: 0, Master)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @127.0.0.1  (Version: 3.5.3)

[mysqld(API)]   3 node(s)
id=3    @127.0.0.1  (Version: 3.5.3)
id=4 (not connected, accepting connect from any host)
id=5 (not connected, accepting connect from any host)

Le cluster est à vous !

16-4-4 - Fichier de configuration

La configuration d'un cluster MySQL est placée dans un fichier de configuration. Ce fichier est lu par le serveur de gestion, puis distribué à tous les processus qui sont impliqués dans le cluster. Ce fichier contient la description de toutes machines impliquées dans le cluster, les paramètres de configuration pour les nœuds de stockage et les paramètres de configuration entre les nœuds.

16-4-4-1 - Exemple de configuration d'un cluster MySQL

Actuellement, le fichier de configuration est au format INI, et il s'appelle config.ini par défaut. Il est placé dans le dossier de démarrage de ndb_mgmd, le serveur de gestion.

Les options préconfigurées sont disponibles pour la plupart des paramètres, et les valeurs par défaut peuvent être définies dans le fichier config.ini. Pour créer une section de valeurs par défaut, ajoutez le mot DEFAULT au nom de la section. Par exemple, les nœuds DB sont configurés avec la section [DB]. Si tous les nœuds DB utilisent la même quantité de mémoire, et que cette valeur n'est pas la valeur par défaut, alors créez une section [DB DEFAULT] qui contient le paramètre DataMemory, et qui spécifiera la valeur par défaut de la taille de mémoire des nœuds DB.

Le format INI est constitué de sections, précédées par des entêtes de sections (entourées de crochets), suivis de paramètres et leur valeur. Un changement par rapport au format standard est que le paramètre et sa valeur peuvent être séparés par un deux-points ':' en plus du signe égal '=', et un autre est que les sections ne sont pas uniques. Au lieu de cela, les entrées uniques comme deux nœuds du même type sont identifiées par un ID distinct.

Un fichier de configuration minimal doit définir les ordinateurs du cluster, et les nœuds impliqués, ainsi que les ordinateurs sur lesquels ces nœuds sont installés.

Un exemple de fichier de configuration minimal pour un cluster avec un serveur de gestion, deux serveurs de stockage et deux serveurs MySQL est présenté ci-dessous :

# file "config.ini" - 2 DB nodes and 2 mysqld
# This file is placed in the start directory of ndb_mgmd,
# the management server.
# The first MySQL Server can be started from any host and the second
# can only be started at the host mysqld_5.mysql.com
# NDBD, MYSQLD, and NDB_MGMD are aliases for DB, API, and MGM respectively
#
[NDBD DEFAULT]
NoOfReplicas= 2
DataDir= /var/lib/mysql-cluster

[NDB_MGMD]
Hostname= ndb_mgmd.mysql.com
DataDir= /var/lib/mysql-cluster

[NDBD]
HostName= ndbd_2.mysql.com

[NDBD]
HostName= ndbd_3.mysql.com

[MYSQLD]
[MYSQLD]
HostName= mysqld_5.mysql.com

Il y a ici six sections dans le fichier. [COMPUTER] définit les ordinateurs du cluster. [API|MYSQLD] définit les nœuds de serveur MySQL du cluster. [MGM|NDB_MGMD] définit le serveur de gestion du cluster. [TCP] définit les connexions TCP/IP entre les nœuds du cluster, TCP/IP est le mécanisme de connexion par défaut entre deux nœuds. [SHM] définit les connexions par mémoire partagée entre les nœuds. Ce n'est possible que si les nœuds ont été compilés avec l'option --with-ndb-shm.

Pour chaque section, il est possible de définir un comportement par défaut, DEFAULT. Les paramètres sont insensibles à la casse depuis MySQL 4.1.5.

16-4-4-2 - La chaîne connectstring du Cluster MySQL

À l'exception du serveur de gestion du cluster MySQL (ndb_mgmd), chaque nœud du cluster MySQL a besoin d'une chaîne connectstring qui pointe sur le serveur de gestion. Elle sert à établir la connexion avec le serveur de gestion, ainsi qu'à réaliser d'autres tâches en fonction du rôle du nœud dans le cluster. La syntaxe pour la chaîne connectstring est la suivante :

<connectstring> :=
[<nodeid-specification>,]<host-specification>[,<host-specification>]
<nodeid-specification> := nodeid=<id>
<host-specification> := <host>[:<port>]

<id> est un entier plus grand que 1 qui identifie un nœud dans le fichier config.ini. <port> est un entier qui représente le port Unix. <host> est une chaîne qui est une adresse valide d'hôte Internet.

example 1 (long):    "nodeid=2,myhost1:1100,myhost2:1100,192.168.0.3:1200"
example 2 (short):   "myhost1"

Tous les nœuds vont utiliser localhost:1186 comme chaîne par défaut, si elle n'est pas spécifiée. Si <port> est omis dans la chaîne, le port par défaut est 1186. (Note : avant MySQL 4.1.8, le port par défaut était 2200.) Ce port doit toujours être disponible sur le réseau, car il a été assigné par l'IANA pour cela (voyez http://www.iana.org/assignments/port-numbers pour les détails).

En listant plusieurs valeurs <host-specification>, il est possible de désigner plusieurs serveurs de gestion redondants. Un nœud de cluster va tenter de contacter successivement chaque serveur, dans l'ordre spécifié, jusqu'à ce qu'une connexion soit établie.

Il y existe plusieurs moyens de spécifier la chaîne connectstring :

- chaque programme a sa propre option de ligne de commande qui permet de spécifier le serveur de gestion au démarrage. Voyez la documentation respective de chaque programme ;

- depuis MySQL 4.1.8, il est aussi possible de configurer connectstring pour chaque nœud du cluster en plaçant une section [mysql_cluster] dans le fichier de configuration du serveur de gestion my.cnf ;

- pour la compatibilité ascendante, deux autres options sont disponibles en utilisant la même syntaxe :

1. Configurer la variable d'environnement NDB_CONNECTSTRING pour qu'elle contienne connectstring,

2. Placez la chaîne connectstring pour chaque programme dans un fichier texte appelé Ndb.cfg et placez de fichier dans le dossier de démarrage.

La méthode recommandée pour spécifier la chaîne connectstring est de passer par la ligne de commande ou par le fichier my.cnf.

16-4-4-3 - Définition des ordinateurs dans un cluster MySQL

La section [COMPUTER] n'a pas d'autre signification que de système de noms pour les nœuds du système. Tous les paramètres cités ici sont obligatoires.

- [COMPUTER]Id
C'est l'identité interne dans le fichier de configuration. Ultérieurement, on appellera cette entité un identifiant. C'est un entier.

- [COMPUTER]HostName
Ceci est le nom d'hôte de l'ordinateur. Il est possible d'utiliser une adresse IP plutôt que son nom d'hôte.

16-4-4-4 - Définition du serveur de gestion du cluster

La section [MGM] (et son alias [NDB_MGMD]) sert à configurer le comportement du serveur de gestion. Le paramètre obligatoire est soit ExecuteOnComputer, soit HostName. Tous les autres paramètres peuvent être omis, et ils prendront leur valeur par défaut.

- [MGM]Id
C'est l'identité du nœud, utilisée comme adresse dans les messages internes. C'est un entier compris entre 1 et 63. Chaque nœud du cluster a une identité unique.

- [MGM]ExecuteOnComputer
Fait référence à un des ordinateurs définis dans la section COMPUTEUR.

- [MGM]PortNumber
C'est le numéro de port que le serveur de gestion utilisera pour attendre les demandes de configuration et les commandes de gestion.

- [MGM]LogDestination
Ce paramètre spécifie la destination du log du cluster. Il y a plusieurs destinations possibles, et elles peuvent être utilisées en parallèle. Les valeurs possibles sont CONSOLE, SYSLOG et FILE. Pour les configurer, il faut les mettre sur une même ligne, séparés par des points-virgules ';'.
CONSOLE envoie sur la sortie standard, et aucun autre paramètre n'est nécessaire.

CONSOLE

SYSLOG correspond à l'envoi log système. Il est nécessaire d'indiquer une méthode ici. Les méthodes possibles sont : auth, authpriv, cron, daemon, ftp, kern, lpr, mail, news, syslog, user, uucp, local0, local1, local2, local3, local4, local5, local6, local7. Notez que toutes ces options ne sont pas forcément supportées par tous les systèmes d'exploitation.

SYSLOG:facility=syslog

FILE représente un fichier standard sur la machine. Il est nécessaire de spécifier un nom de fichier, la taille maximale du fichier avant l'ouverture d'un nouveau fichier. L'ancien sera alors renommé avec l'extension .x où x est le prochain nombre libre. Il est aussi nécessaire de spécifier le nombre maximal de fichiers utilisés.

FILE:filename=cluster.log,maxsize=1000000,maxfiles=6

Il est possible de spécifier plusieurs destinations de logs comme ceci :

CONSOLE;SYSLOG:facility=local0;FILE:filename=/var/log/mgmd

La valeur par défaut de ce paramètre est FILE:filename=cluster.log,maxsize=1000000,maxfiles=6.

- [MGM]ArbitrationRank
Ce paramètre est utilisé pour définir les nœuds qui servent d'arbitre. Les nœuds de gestion MGM et les nœuds API peuvent être utilisés comme arbitre. 0 signifie que le nœud n'est pas utilisé comme arbitre, 1 est la priorité haute, et 2 la priorité basse. Une configuration normale utilise les serveurs de gestion comme arbitre avec ArbitrationRank à 1 (c'est la valeur par défaut) et les nœuds d'API à 0 (ce n'est pas le défaut en MySQL 4.1.3).

- [MGM]ArbitrationDelay
Si vous donnez une valeur différente de 0 à cette option, cela signifie que le serveur de gestion retarde ses réponses d'autant, lorsqu'il reçoit des demandes d'arbitrage. Par défaut, il n'y a pas de délai, et c'est très bien comme ça.

- [MGM]DataDir
C'est le dossier où les fichiers de résultats du serveur de gestion seront placés. Ces fichiers sont les fichiers de logs, les affichages de processus et le PID pour le démon.

16-4-4-5 - Définitions des nœuds de stockage dans un cluster MySQL

La section [DB] et son alias [NDBD] servent à configurer le comportement des nœuds de stockage. Il y a de nombreux paramètres spécifiés qui contrôlent les tailles de buffer, les tailles de files ou les délais d'expiration, etc. Le seul paramètre obligatoire est soit ExecuteOnComputer ou HostName et le paramètre NoOfReplicas qui doit être défini dans la section [DB DEFAULT]. La plupart des paramètres doivent être dans la section [DB DEFAULT]. Seuls les paramètres explicitement présentés comme ayant une valeur locale peuvent être modifiés dans la section [DB]. HostName, Id et ExecuteOnComputer doivent être définies dans la section [DB].

La valeur de Id, ou l'identité d'un nœud de stockage peut être allouée au démarrage du nœud. Il est toujours possible d'assigner un identifiant dans un fichier de configuration.

Pour chaque paramètre, il est possible d'utiliser les suffixes k, M ou G, pour indiquer des multiples 1024, (1024*1024) et (1024* 1024*1024) de l'unité. Par exemple, 100 k représente 102 400. Les paramètres et leur valeur sont actuellement sensibles à la casse.

- [DB]Id
Cet identifiant est l'identité du nœud, utilisé pour référencer le nœud dans le cluster. C'est un entier compris entre 1 et 63. Chaque nœud du cluster doit avoir une identité distincte.

- [DB]ExecuteOnComputer
Cela fait référence à un des ordinateurs définis dans la section 'Computer'.

- [DB]HostName
Ce paramètre revient à spécifier un ordinateur sur lequel placer l'exécution. Il définit un nom d'hôte sur lequel réside le nœud de stockage. Ce paramètre ou ExecuteOnComputer est obligatoire.

- [DB]ServerPort
Chaque nœud dans le cluster utilise un port pour se connecter avec les autres nœuds du cluster. Ce port est aussi utilisé pour les connexions lors de la phase de mise en place. Ce port par défaut sera utilisé pour s'assurer qu'aucun nœud sur le même ordinateur ne reçoit le même numéro de port. Le numéro de port minimum est 2202.

- [DB]NoOfReplicas
Ce paramètre ne peut être configuré que dans la section [DB DEFAULT], car c'est un paramètre global. Il définit le nombre de répliques de chaque table stockée dans le cluster. Ce paramètre spécifie aussi la taille du groupe de nœuds. Un groupe de nœuds est un ensemble de nœuds qui stockent les mêmes informations.
Les groupes de nœuds sont formés implicitement. Le premier groupe est formé par les nœuds de stockage avec les identités les plus petites, puis par ordre d'identité croissante. Par exemple, supposons que nous avons quatre nœuds de stockage et que NoOfReplicas vaut 2. Les quatre nœuds de stockage ont les identifiants 2, 3, 4 et 5. Le premier groupe de nœuds sera formé par les nœuds 2 et 3, et le second groupe sera formé de 4 et 5. Il est important de configurer le cluster pour que les nœuds d'un même groupe ne soient pas placés sur le même ordinateur. Sinon, cela pourrait conduire à avoir un point de faiblesse : un seul ordinateur peut planter le cluster.
Si aucune identité n'est spécifiée, alors l'ordre des nœuds de stockage va être le facteur déterminant du groupe de nœuds. Le groupe de nœuds ainsi généré peut être affiché avec la commande SHOW dans le client de gestion.
Il n'y a pas de valeur par défaut, et la valeur maximale est 4.

- [DB]DataDir
Ce paramètre spécifie le dossier où les fichiers de traces, les fichiers de logs, et les fichiers d'erreurs sont rangés.

- [DB]FileSystemPath
Ce paramètre spécifie le dossier où tous les fichiers créés pour stocker les métadonnées, les logs de REDO, les logs de UNDO et les fichiers de données sont rangés. La valeur par défaut est DataDir. Le dossier doit être créé avant de lancer le processus ndbd.
Si vous utilisez la hiérarchie de dossiers recommandée, vous utiliserez le dossier /var/lib/mysql-cluster. Sous ce dossier, un autre dossier ndb_2_fs sera créé (si l'identifiant de nœud est 2), pour servir de fichier système pour le nœud.

- [DB]BackupDataDir
Il est possible de spécifier le dossier où les sauvegardes seront placées. Par défaut, le dossier FileSystemPath/BACKUP sera utilisé.

DataMemory et IndexMemory sont les paramètres qui spécifient la taille des segments de mémoire utilisés pour stocker les lignes et leur index. Il est important de comprendre comment DataMemory et IndexMemory sont utilisés pour comprendre comment choisir ces paramètres. Pour la majorité des cas, ils doivent être mis à jour pour refléter leur utilisation dans le cluster.

- [DB]DataMemory
Ce paramètre est l'un des paramètres les plus importants, car il définit l'espace disponible pour stocker les lignes dans la base de données. Tout l'espace DataMemory sera alloué en mémoire : il est donc important que la machine contienne assez de mémoire pour stocker DataMemory.
DataMemory sert à stocker deux choses. Il stocke les lignes de données. Chaque ligne est de taille fixe. Les colonnes VARCHAR sont stockées sous forme de colonnes à taille fixe. De plus, chaque enregistrement est stocké dans une page de 32 ko avec 128 octets d'entête. Il y a donc un peu de pertes pour chaque page, car chaque ligne n'est stockée que sur une seule page. La taille maximale d'une colonne est actuellement de 8052 octets.
DataMemory sert aussi à stocker les index ordonnés. Les index ordonnés prennent environ 10 octets par ligne. Chaque ligne dans une table est représentée par un index ordonné.
DataMemory est constitué de pages de 32 ko. Ces pages sont allouées comme partitions pour les tables. Chaque table est généralement répartie en autant de partitions qu'il y a de nœuds dans le cluster. Par conséquent, il y a le même nombre de partitions (fragments) que la valeur de NoOfReplicas. Une fois qu'une page a été allouée, il n'est pas possible actuellement de la libérer. La méthode pour récupérer cet espace est d'effacer la table. Effectuer une restauration de nœuds va aussi compresser la partition, car toutes les lignes seront insérées dans une partition vide, depuis un autre nœud.
Un autre aspect important est que DataMemory contient aussi les informations de UNDO (annulation) pour chaque ligne. Pour chaque modification d'une ligne, une copie de la ligne est faite dans l'espace DataMemory. De plus, chaque copie va aussi avoir une instance dans l'index ordonné. Les index Hash unique sont modifiés uniquement lorsque les colonnes uniques sont modifiées dans ce cas, une nouvelle entrée est insérée dans la table. Au moment de l'archivage (commit), l'ancienne valeur est effacée. Il est donc nécessaire de pouvoir allouer la mémoire nécessaire pour gérer les plus grosses transactions effectuées dans le cluster.
Effectuer une transaction de grande taille n'a pas d'autre intérêt avec le Cluster MySQL que la cohérence, ce qui est la base des transactions. Les transactions ne sont pas plus rapides, et consomment beaucoup de mémoire.
La taille par défaut de DataMemory est 80 MB. La taille minimum est de 1 MB. Il n'y a pas de taille maximum, mais en réalité, il faut adapter la valeur pour éviter que le système n'utilise la mémoire sur le disque, par ce que la mémoire physique a été dépassée.

- [DB]IndexMemory
IndexMemory est le paramètre qui contrôle la quantité d'espace utilisée pour les index hash de MySQL Cluster. Les index hash sont toujours utilisés pour les clés primaires, les index uniques et les contraintes d'unicité. En fait, lors de la définition d'une clé primaire et d'une clé unique, deux index distincts seront créés par MySQL Cluster. Un index sera un hash utilisé pour les accès aux lignes, et pour le verrouillage. Il est aussi utilisé pour les contraintes d'unicité.
La taille d'un index hash est de 25 octets plus la taille de la clé primaire. Pour les clés primaires dont la taille dépasse 32 octets, ajoutez un autre 8 octets pour des références internes.
Par exemple, observons la table suivante.

CREATE TABLE example
(
a INT NOT NULL,
b INT NOT NULL,
c INT NOT NULL,
PRIMARY KEY(a),
UNIQUE(b)
) ENGINE=NDBCLUSTER;

Nous avons ici 12 octets d'entête (puisque des colonnes non nulles économisent 4 octets), plus 12 octets par ligne. De plus, nous avons deux index ordonnés sur les colonnes a et b, qui utilisent chacun 10 octets par ligne. Nous aurons aussi une clé primaire hash avec environ 29 octets par ligne. La contrainte unique est implémentée par une table séparée, avec b comme clé primaire et a comme colonne. Cette table va donc consommer encore 29 autres octets en mémoire par ligne, plus 12 octets d'entête et 8 octets pour les données.

Pour une table d'un million de lignes, nous aurons besoin de 58 Mo de mémoire pour gérer les index en mémoire, la clé primaire et la contrainte d'unicité. Pour DataMemory, nous aurons besoin de 64 Mo de mémoire, pour gérer les lignes de la table de base et celles de la table d'index, plus les deux tables d'index ordonnés.

En conclusion, les index hash consomment beaucoup d'espace en mémoire vive, mais fournissent un accès accéléré aux données. Ils sont aussi utilisés dans les clusters MySQL pour gérer les contraintes d'unicité.

Actuellement, les seuls algorithmes de partitionnement sont le hashage et les index ordonnés, qui sont locaux à chaque nœud, et ne peuvent pas prendre en compte les contraintes d'unicité en général.

Un point important pour les deux options IndexMemory et DataMemory est que le total de la base de données est la taille de DataMemory et IndexMemory dans chaque groupe. Chaque groupe est utilisé pour stocker les informations répliquées, ce qui fait que si vous avez 4 nœuds avec 2 répliques, cela fait 2 groupes de nœuds, et le total de DataMemory disponible est 2*DataMemory dans chaque nœud.

Un autre aspect important est les modifications de DataMemory et IndexMemory. Tout d'abord, il est fortement recommandé d'avoir la même quantité de DataMemory et IndexMemory sur tous les nœuds. Comme les données sont distribuées équitablement entre les nœuds du cluster, l'espace disponible n'est pas supérieur à la plus petite quantité d'espace disponible sur un des nœuds du cluster, multiplié par le nombre de groupe de nœuds.

DataMemory et IndexMemory peuvent être modifiés, mais il est dangereux de le réduire, car cela peut conduire à des problèmes de redémarrage pour un nœud, ou même pour le cluster, car il n'y aura plus assez de mémoire pour restaurer les tables. Accroître les valeurs doit être facile à faire, mais il est recommandé, pour ce type de mise à jour, de faire une modification comparable à une mise à jour du logiciel : modification du fichier de configuration, puis redémarrage du serveur de gestion, et chaque serveur est relancé manuellement, un à la fois.

IndexMemory n'est pas utilisé à cause des modifications, mais à cause des insertions : ces dernières sont insérées immédiatement, alors que les effacements ne sont pris en compte que lorsque la transaction est archivée.

La valeur par défaut de IndexMemory est 18 Mo. La taille minimale est de 1 Mo.

Les trois paramètres suivants sont importants, car ils affectent le nombre de transactions simultanées et la taille des transactions qui peuvent être gérées par le système. MaxNoOfConcurrentTransactions fixe le nombre de transactions simultanées dans un nœud, et MaxNoOfConcurrentOperations fixe le nombre de lignes qui peuvent être en phase de modification ou de verrouillage simultanément.

Ces deux paramètres, et particulièrement MaxNoOfConcurrentOperations seront étudiés de près par les utilisateurs qui choisissent des valeurs particulières, et évitent les valeurs par défaut. La valeur par défaut est configurée pour les systèmes ayant de petites transactions, et s'assure que la mémoire n'est pas trop sollicitée.

- [DB]MaxNoOfConcurrentTransactions
Pour chaque transaction active dans le cluster, il y a besoin d'une ligne de transaction dans l'un des nœuds du cluster. Le rôle de cette coordination de transaction est réparti entre tous les nœuds et ainsi, le nombre de lignes de transactions dans le cluster est le nombre de nœuds dans le cluster.
En fait, les lignes de transactions sont allouées aux serveurs MySQL. Normalement, il y a au moins une ligne de transaction allouée dans le cluster par connexion qui utilise ou a utilisé une table dans le cluster. Par conséquent, il faut s'assurer qu'il y a plus de lignes de transaction dans le cluster qu'il n'y a de connexions simultanées à tous les serveurs du cluster MySQL.
Ce paramètre doit être le même pour tous les nœuds du serveur.
Modifier ce paramètre n'est jamais facile, et peut conduire à un crash du système. Lorsqu'un nœud crashe, le nœud le plus ancien va prendre en charge l'état des transactions qui avaient lieu dans le nœud perdu. Il est donc important que ce nœud ait autant de lignes de transactions que le nœud perdu.
La valeur par défaut pour ce paramètre est 4096.

- [DB]MaxNoOfConcurrentOperations
Ce paramètre est sujet à modifications par les utilisateurs. Les utilisateurs qui effectuent des transactions courtes et rapides n'ont pas besoin de lui donner une valeur trop haute. Les applications qui veulent utiliser des transactions de grande taille impliquant de nombreuses lignes devront accroître sa valeur.
Pour chaque transaction qui modifie des données dans le cluster, il faut allouer des lignes d'opération. Il y a des lignes d'opération au niveau de la coordination de transaction, et dans les nœuds où les transformations ont lieu.
Les lignes d'opération contiennent des informations d'état qui doivent être capables de retrouver des lignes d'annulation, des files de verrous et toutes les autres informations d'état.
Pour dimensionner le cluster afin de gérer des transactions où un million de lignes doivent être mises à jour simultanément, il faut donner à ce paramètre la valeur d'un million divisé par le nombre de nœuds. Pour un cluster ayant 4 nœuds de stockage, la valeur sera donc de 250 000.
De plus, les lectures qui posent des verrous utilisent aussi des lignes d'opération. De la mémoire supplémentaire est allouée dans les nœuds locaux pour gérer les cas où la distribution n'est pas parfaite entre les nœuds.
Lorsqu'une requête impose l'utilisation d'un index hash unique, il y aura automatiquement deux lignes d'opération pour chaque ligne de la transaction. La première représente la lecture dans la table d'index, et la seconde gère l'opération dans la table de base.
La valeur par défaut pour ce paramètre est 32 768.
Ce paramètre gère en fait deux aspects qui peuvent être configurés séparément. Le premier aspect spécifie le nombre de lignes d'opération qui peuvent être placées dans la coordination de transaction. Le second aspect spécifie le nombre de lignes d'opération qui seront utilisées dans la base de données locale.
Si une très grande transaction est effectuée sur un cluster de 8 nœuds, elle aura besoin d'autant de lignes d'opération pour la coordination de transactions qu'il y a de lectures, modifications et effacements impliqués dans la transaction. La transaction va répartir les lignes d'opération entre les 8 nœuds. Par conséquent, s'il est nécessaire de configurer le système pour une grosse transaction, il est recommandé de configurer les nœuds séparément. MaxNoOfConcurrentOperations va toujours être utilisé pour calculer le nombre de lignes d'opération dans la coordination de transaction.
Il est aussi important d'avoir une idée des contraintes de mémoire pour ces lignes d'opération. En MySQL 4.1.5, les lignes d'opération consomment 1 Ko par ligne. Ce chiffre est appelé à réduire dans les versions 5.x.

- [DB]MaxNoOfLocalOperations
Par défaut, ce paramètre est calculé comme 1,1 fois MaxNoOfConcurrentOperations ce qui est bon pour les systèmes avec de nombreuses requêtes simultanées, de petite taille. Si la configuration doit gérer une très grande transaction une fois de temps en temps, et qu'il y a de beaucoup de nœuds, il est alors recommandé de configurer cette valeur séparément.

Le jeu de paramètres suivant est utilisé pour le stockage temporaire durant l'exécution d'une requête dans le cluster. Toute cette mémoire sera libérée lorsque la requête sera terminée, et que la transaction attendra l'archivage ou l'annulation.

La plupart des valeurs par défaut de ces paramètres seront valables pour la plupart des utilisateurs. Certains utilisateurs exigeants pourront augmenter ces valeurs pour améliorer le parallélisme du système, et les utilisateurs plus contraints pourront réduire les valeurs pour économiser de la mémoire.

- [DB]MaxNoOfConcurrentIndexOperations
Pour les requêtes utilisant un index unique hash, un autre jeu de lignes d'opération sont temporairement utilisés durant la phase d'exécution de la requête. Ce paramètre configure la taille de la file qui accueille ces lignes. Par conséquent, cette mémoire n'est utilisée que lors de l'exécution d'une requête, et dès la fin de l'exécution, les lignes sont libérées. L'état nécessaire pour gérer les annulations et archivages est géré par les lignes d'opération permanentes, où la taille de la file est gérée par MaxNoOfConcurrentOperations.
La valeur par défaut pour ce paramètre est 8192. Seules les situations où un très haut niveau de parallélisme utilisant des index uniques hash doivent augmenter cette valeur. La réduction de cette valeur permet d'économiser de la mémoire, si l'administrateur est certain que le parallélisme reste rare dans le cluster.

- [DB]MaxNoOfFiredTriggers
La valeur par défaut pour MaxNoOfFiredTriggers est 4000. Normalement, cette valeur doit être suffisante pour la plupart des systèmes. Dans certains cas, il est possible de réduire cette valeur si le parallélisme n'est pas trop haut dans le cluster.
Cette option est utilisée lorsqu'une opération est effectuée, et affecte un index hash unique. Modifier une colonne qui fait partie d'un index unique hash ou insérer/effacer une ligne dans une table avec un index unique hash va déclencher une insertion ou un effacement dans l'index de la table. Cette ligne est utilisée durant l'attente de la fin de l'exécution de cette opération. C'est une ligne qui ne dure pas longtemps, mais elle peut malgré tout réclamer plusieurs lignes pour des situations temporaires d'écritures parallèles sur la table de base, contenant les index uniques.

- [DB]TransactionBufferMemory
Ce paramètre est aussi utilisé pour lister les opérations de modifications d'index. Elle garde les informations de clé et colonne de l'opération en cours. Il doit être exceptionnel de modifier ce paramètre.
De plus, les opérations de lecture et écriture utilisent un buffer similaire. Ce buffer est encore plus temporaire dans son utilisation, ce qui fait que c'est un paramètre de compilation, qui vaut 4000*128 octets (500Ko). Le paramètre st ZATTRBUF_FILESIZE dans Dbtc.hpp. Un buffer similaire pour les informations de clé, qui représente 4000*16 octets, soit 62.5 ko d'espace. Ce paramètre est ZDATABUF_FILESIZE dans Dbtc.hpp. Dbtc est le module qui gère la coordination de transaction.
Des paramètres similaires existent dans le module Dblqh pour gérer les lectures et modifications lorsque les données ont été localisées. Dans Dblqh.hpp avec ZATTRINBUF_FILESIZE qui vaut 10000*128 octets (1250 ko) et ZDATABUF_FILE_SIZE, qui vaut 10000*16 octets (environ 156 ko). Nous n'avons aucune connaissance de situation qui soit limitée par ces valeurs.
La valeur par défaut de TransactionBufferMemory est 1 Mo.

- [DB]MaxNoOfConcurrentScans
Ce paramètre est utilisé pour contrôler la quantité de scans parallèles qui sont effectués dans le cluster. Chaque coordination de transaction peut gérer un certain nombre de scans de tables simultanément, et ce nombre est limité par cette option. Chaque partition va utiliser une ligne de scan dans le nœud où la partition est située. Le nombre de lignes est la taille de ce paramètre multiplié par le nombre de nœuds, ce qui fait que le cluster peut supporter le nombre maximal de scans, multiplié par le nombre de nœuds du cluster.
Les scans sont effectués dans deux situations. La première est lorsqu'aucun index hash ou ordonné n'a pu être trouvé pour gérer la requête. Dans ce cas, la requête est exécutée avec un scan de table. La seconde est lorsqu'il n'y a pas d'index hash, mais seulement un index ordonné. Utiliser l'index ordonné, revient à faire un scan de tables parallèles. Comme l'ordre n'est conservé que dans les partitions locales, il est nécessaire de faire le scan dans toutes les partitions.
La valeur par défaut de MaxNoOfConcurrentScans est 256. La valeur maximale est de 500.
Ce paramètre va toujours spécifier le nombre de scans possibles dans la coordination de transaction. Si le nombre local de scans n'est pas fourni, il est calculé comme le produit de MaxNoOfConcurrentScans et du nombre de nœuds de stockages du système.

- [DB]MaxNoOfLocalScans
Il est possible de spécifier le nombre de lignes de scan locaux, si les scans ne sont pas totalement parallèles.

- [DB]BatchSizePerLocalScan
Ce paramètre est utilisé pour calculer le nombre de lignes de verrous qui est nécessaire pour gérer les opérations de scan courantes.
La valeur par défaut est 64 et cette valeur est très liée au paramètre ScanBatchSize défini dans l'interface des nœuds.

- [DB]LongMessageBuffer
Ceci est un buffer interne utilisé pour passer des messages aux nœuds, et entre les nœuds. Il est hautement improbable que quiconque veuille modifier cette valeur, mais il est malgré tout disponible. Par défaut, ce paramètre vaut 1 Mo.

- [DB]NoOfFragmentLogFiles
Ceci est un paramètre important qui indique la taille du fichier de logs de REDO. Les logs REDO sont organisés en boucle, et il est important que la fin et le début ne se chevauchent pas. Lorsque la queue et la tête se rapprochent dangereusement l'un de l'autre, le nœud va commencer à annuler les modifications, car il n'y a plus de place pour les lignes de modifications.
Le log de REDO n'est supprimé que lorsque trois jalons locaux sont passés depuis l'insertion dans le log. La vitesse d'apparition d'un jalon est contrôlée par un jeu de paramètres : tous ces paramètres sont donc liés.
La valeur par défaut de ce paramètre est 8, ce qui signifie que 8 jeux de 4*16 Mo fichiers. Cela représente un total de 512 Mo. L'unité de stockage est de 64 Mo pour le log de REDO. Dans les serveurs à fort taux de modification, il faut augmenter considérablement cette valeur. Nous avons vu des cas de test où il a fallu mettre cette valeur à plus de 300.
Si les jalons sont lents à venir, et qu'il y a tellement d'écritures dans la base que les fichiers de logs sont remplis, que le fichier de logs de queue ne peut pas être supprimé pour assurer la restauration, les transactions de modification seront interrompues avec une erreur interne 410, qui sera transformée en message : Out of log file space temporarily. Cette condition restera en place jusqu'à ce qu'un jalon soit atteint, et que la queue du log puisse avancer.

- [DB]MaxNoOfSavedMessages
Ce paramètre limite le nombre de fichiers de trace qui seront conservés sur le serveur, avant de remplacer un ancien fichier de trace. Les fichiers de trace sont générés lorsque le nœud crashe pour une raison donnée.
La valeur par défaut est de 25 fichiers de trace.

Le jeu de paramètres suivant définit la taille du buffer d'objets de métadonnées. Il est nécessaire de définir le nombre maximal d'objets, d'attributs, d'index et d'objets triggers utilisés par les index, les événements, et la réplication entre clusters.

- [DB]MaxNoOfAttributes
Ce paramètre définit le nombre d'attributs qui peuvent être définis dans le cluster.
La valeur par défaut pour ce paramètre est 1000. La valeur minimale est 32 et il n'y a pas de maximum. Chaque attribut consomme environ 200 octets d'espace, car les métadonnées sont totalement répliquées entre les nœuds.

- [DB]MaxNoOfTables
Un objet de table est alloué pour chaque table, pour chaque index hash unique et pour chaque index ordonné. Ce paramètre fixe le nombre maximal d'objets de table qui soit alloué.
Pour chaque attribut qui contient un type de données BLOB, une autre table est utilisée pour stocker la partie principale des données BLOB. Ces tables doivent aussi être prises en compte lorsque vous définissez les tables.
La valeur par défaut pour ce paramètre est 128. La valeur minimale est de 8, et il n'y a pas de maximum. Il y a des limitations internes, qui empêchent d'aller au-delà de 1600. Chaque objet de table consomme environ 20 ko de mémoire par nœud.

- [DB]MaxNoOfOrderedIndexes
Pour chaque index ordonné dans le cluster, des objets sont alloués pour décrire ce qu'ils indexent et leur stockage. Par défaut, chaque index défini aura un index ordonné associé. Les index uniques et les clés primaires ont tous deux un index ordonné et un index hash.
La valeur par défaut pour ce paramètre est 128. Chaque objet consomme environ 10 ko par nœud.

- [DB]MaxNoOfUniqueHashIndexes
Pour chaque index unique (pas pour les index primaires), une table spéciale est allouée pour assurer la correspondance entre la clé primaire et la clé unique de la table indexée. Par défaut, il y aura un index ordonné de défini pour chaque index unique. Pour éviter cela, utilisez l'option USING HASH.
La valeur par défaut de 64. Chaque index va consommer environ 15 ko par nœud.

- [DB]MaxNoOfTriggers
Pour chaque index hash unique, un trigger interne de modification, insertion ou effacement est alloué. Cela fait 3 triggers pour chaque index hash unique. Les index ordonnés utilisent un seul objet trigger. Les sauvegardes utilisent aussi trois objets trigger pour chaque table normale dans le cluster. Lorsque la réplication entre cluster est supportée, elle va aussi utiliser un trigger interne.
Ce paramètre limite le nombre d'objets trigger dans le cluster.
La valeur par défaut pour ce paramètre est 768.

- [DB]MaxNoOfIndexes
Ce paramètre est abandonné depuis MySQL 4.1.5. Il faut désormais utiliser MaxNoOfOrderedIndexes et MaxNoOfUniqueHashIndexes à la place.
Ce paramètre ne sert que pour les index hash uniques. Il faut une ligne dans ce buffer pour chaque index hash unique défini dans le cluster.
La valeur par défaut pour ce paramètre est 128.

Il y a un jeu de paramètres booléens qui affectent le comportement des nœuds de stockage. Les paramètres booléens peuvent être spécifiés à true avec Y (pour Yes, c'est-à-dire oui) ou 1, et à false avec N (pour non) ou 0.

- [DB]LockPagesInMainMemory
Pour certains systèmes d'explications tels que Solaris et Linux, il est possible de verrouiller un processus en mémoire et éviter les problèmes de swap. C'est une fonctionnalité importante pour améliorer le temps réel du cluster.
Par défaut, cette fonctionnalité n'est pas activée.

- [DB]StopOnError
Ce paramètre indique si le processus doit s'arrêter sur une erreur, ou s'il doit faire un redémarrage automatique.
Par défaut, cette fonctionnalité est activée.

- [DB]Diskless
Dans les interfaces internes, il est possible de configurer les tables comme sans disque (littéralement, diskless), ce qui signifie que les tables ne sont pas enregistrées sur le disque, et qu'aucun log n'est fait. Ces tables existent uniquement en mémoire. Ces tables existeront encore après un crash, mais pas leur contenu.
Cette fonctionnalité fait que le cluster entier devient Diskless, ce qui fait que les tables n'existent plus après un crash. Activer cette fonctionnalité de fait avec Y ou 1.
Lorsque cette fonctionnalité est activée, les sauvegardes sont faites, mais elles ne seront pas stockées, car il n'y a pas de disque. Dans les versions futures, il est probable que les sauvegardes sans disques soient une option séparée.
Par défaut, cette fonctionnalité n'est pas activée.

- [DB]RestartOnErrorInsert
Cette fonctionnalité n'est possible que lorsque la version de débogage a été compilée, pour pouvoir insérer des erreurs à différents points de l'exécution, afin de tester les cas d'erreurs.
Par défaut, cette fonctionnalité n'est pas activée.

Il y a plusieurs paramètres pour tester les délais d'expiration et les intervalles entre différentes actions des nœuds de stockage. Plusieurs délais d'expiration sont spécifiés en millisecondes, à quelques exceptions qui sont explicitement indiquées.

- [DB]TimeBetweenWatchDogCheck
Pour s'assurer que le thread principal ne reste back éternellement bloqué dans une boucle infinie, il existe un garde-fou qui vérifie le fonctionnement de ce thread. Ce paramètre indique le nombre de millisecondes entre deux vérifications. Après trois essais où le processus est dans le même état, le thread est arrêté par le garde-fou.
Ce paramètre peut être facilement modifié, et peut différer de nœud en nœud, même s'il y a peu de raison pour faire des traitements différents.
La durée par défaut est de 4000 millisecondes (4 secondes).

- [DB]StartPartialTimeout
Ce paramètre spécifie le temps durant lequel le cluster attend les nœuds de stockage avant que l'algorithme de cluster soit appelé. Cette durée est appelée pour éviter de démarrer un cluster partiel.
La valeur par défaut de 30 000 millisecondes (30 secondes). 0 signifie l'éternité, c'est-à-dire que tous les nœuds doivent être là pour démarrer.

- [DB]StartPartitionedTimeout
Si le cluster est prêt à démarrer après avoir attendu StartPartialTimeout, mais qu'il est possible qu'il soit dans un état de partitionnement, alors le cluster attend encore ce délai supplémentaire.
Le délai par défaut est de 60 000 millisecondes (60 secondes).

- [DB]StartFailureTimeout
Si le démarrage n'est pas réalisé dans le délai spécifié par ce paramètre, le démarrage du nœud échouera. En donnant la valeur de 0 à ce paramètre, il n'y a pas de délai appliqué.
La valeur par défaut de 60 000 millisecondes (60 secondes). Pour les nœuds de stockage avec de grandes bases de données, il faut augmenter cette valeur, car le nœud peut demander jusqu'à 15 minutes pour effectuer le démarrage de plusieurs gigaoctets de données.

- [DB]HeartbeatIntervalDbDb
Une des méthodes qui permettent de découvrir les nœuds morts est la tachycardie (littéralement, heartbeats, battements de cœur). Ce paramètre indique le nombre de signaux qui sont envoyés, et la fréquence supposée de réception. Après avoir sauté 3 intervalles de signaux d'affilée, le nœud est déclaré mort. Par conséquent, le temps maximal de détection d'un nœud est de 4 battements.
L'intervalle par défaut est de 1500 millisecondes (1,5 seconde). Ce paramètre ne doit pas être modifié de trop. Si vous utilisez 5000 millisecondes et que le nœud observé utiliser une valeur de 1000 millisecondes alors ce dernier sera rapidement déclaré mort. Ce paramètre peut être modifié progressivement, mais pas trop d'un coup.

- [DB]HeartbeatIntervalDbApi
Similairement, chaque nœud de stockage émet des signaux de vie pour chaque serveur MySQL connecté, pour s'assurer qu'ils fonctionnent correctement. Si un serveur MySQL ne renvoie pas un signal dans le temps escompté, avec le même algorithme que pour la surveillance des nœuds de stockage, il est alors déclaré mort, et les transactions sont alors terminées, les ressources libérées, et le serveur ne pourra pas se reconnecter avant la fin des opérations de nettoyage.
La valeur par défaut pour cet intervalle est 1500 millisecondes. Cet intervalle peut être différent pour le nœud de stockage, car chaque nœud de stockage fonctionne indépendamment des autres nœuds de stockage qui surveillent le serveur connecté.

- [DB]TimeBetweenLocalCheckpoints
Ce paramètre est une exception, en ce sens qu'il ne définit pas un délai avant de poser un jalon local. Ce paramètre sert à s'assurer que dans un cluster, le niveau de modification des tables n'est pas trop faible pour empêcher la pose de jalon. Dans la plupart des clusters avec un taux de modification important, il est probable que les jalons locaux soient posés immédiatement après la fin du précédent.
La taille de toutes les opérations d'écriture exécutées depuis le début du jalon précédent est sommée. Ce paramètre est spécifié comme le logarithme du nombre de mots. Par exemple, la valeur par défaut de 20 signifie que 4 Mo d'opérations d'écriture ont été faites ; 21 représente 8 Mo, et ainsi de suite. La valeur maximale de 31 représente 8 Go d'opérations.
Toutes les opérations d'écritures dans le cluster sont additionnées ensemble. En lui donnant une valeur de 6 ou moins, cela va forcer les écritures de jalons continuellement, sans aucune attente entre deux jalons, et indépendamment de la charge du cluster.

- [DB]TimeBetweenGlobalCheckpoints
Lorsqu'une transaction est archivée, elle est placée en mémoire principale de tous les nœuds où des données miroirs existent. Les lignes de logs de la transaction ne sont pas forcées sur le disque lors de l'archivage. L'idée ici est que pour que la transaction soit archivée sans problème, il faut qu'elle soit archivée dans 2 nœuds indépendants.
Dans le même temps, il est important de s'assurer que dans le pire cas de crash, le cluster se comporte correctement. Pour s'assurer que les transactions dans un intervalle de temps donné sont placées dans un jalon global. Un groupe entier de transactions est envoyé sur le disque. Par conséquent, la transaction a été placée dans un groupe de jalon, en tant que partie d'un archivage. Ultérieurement, ce groupe de log sera placé sur le disque, et le groupe entier de transactions sera archivé sur tous les serveurs.
Ce paramètre spécifie l'intervalle entre les jalons globaux. La valeur par défaut est de 2000 millisecondes.

- [DB]TimeBetweenInactiveTransactionAbortCheck
Un délai d'expiration est appliqué pour chaque transaction en fonction de ce paramètre. Par conséquent, si ce paramètre vaut 1000 millisecondes, alors chaque transaction sera vérifiée une fois par seconde.
La valeur par défaut pour ce paramètre est 1000 millisecondes (1 seconde).

- [DB]TransactionInactiveTimeout
Si la transaction n'est pas en exécution de requête, mais attend d'autres données, ce paramètre spécifie le temps maximum d'attente des données avant d'annuler la transaction.
Par défaut, ce paramètre ne limite pas l'arrivée des données. Pour des clusters en production, qui doivent s'assurer qu'aucune transaction ne bloque le serveur durant trop longtemps, il faut utiliser une valeur basse. L'unité est la milliseconde.

- [DB]TransactionDeadlockDetectionTimeout
Lorsqu'une transaction est impliquée dans l'exécution d'une requête, elle attend les autres nœuds. Si les autres nœuds ne répondent pas, il peut se passer 3 choses. Premièrement, le nœud peut être mort ; deuxièmement, l'opération peut être placée dans une file d'attente de verrous ; troisièmement, le nœud impliqué peut être surchargé. Ce paramètre limite la durée de l'attente avant d'annuler la transaction.
Ce paramètre est important pour la détection d'échec de nœud et le blocage de verrou. En le configurant trop haut, il est possible de laisser passer des blocages.
La durée par défaut est de 1200 millisecondes (1.2 seconde).

- [DB]NoOfDiskPagesToDiskAfterRestartTUP
Lors de l'exécution d'un jalon local, l'algorithme envoie toutes les pages de données au disque. Les envoyer aussi rapidement que possible cause des charges inutiles sur le processeur, le réseau et le disque. Cette option contrôle le nombre de pages à écrire par 100 millisecondes. Une page est définie ici comme faisant 8 ko. C'est l'unité de ce paramètre est de 80 ko par seconde. En lui donnant la valeur de 20, cela représente 1.6 Mo de données envoyées sur le disque par seconde, durant un jalon local. De plus, l'écriture des logs de UNDO est incluse dans cette somme. L'écriture des pages d'index (voir IndexMemory pour comprendre comment les pages d'index sont utilisées), et leurs logs d'UNDO sont gérés par le paramètre NoOfDiskPagesToDiskAfterRestartACC. Ce paramètre gère les limitations d'écriture de DataMemory.
Ainsi, ce paramètre spécifie la vitesse d'écriture des jalons. Ce paramètre est important et est corrélé à NoOfFragmentLogFiles, DataMemory, IndexMemory.
La valeur par défaut de 40 (3.2 Mo de pages de données par seconde).

- [DB]NoOfDiskPagesToDiskAfterRestartACC
Ce paramètre a la même unité que NoOfDiskPagesToDiskAfterRestartTUP, mais limite la vitesse d'écriture des pages d'index depuis IndexMemory.
La valeur par défaut pour ce paramètre est 20 (1.6 Mo par seconde).

- [DB]NoOfDiskPagesToDiskDuringRestartTUP
Ce paramètre spécifie les mêmes limitations que NoOfDiskPagesToDiskAfterRestartTUP et NoOfDiskPagesToDiskAfterRestartACC, mais s'applique aux jalons locaux, exécutés sur un nœud comme une partie de jalon lors du redémarrage. Faisant partie du redémarrage, un jalon local est toujours effectué. Il est possible d'utiliser une vitesse accrue durant le redémarrage du nœud, car les activités sont alors limitées sur le serveur.
Ce paramètre gère la partie de DataMemory.
La valeur par défaut de 40 (3.2 Mo par seconde).

- [DB]NoOfDiskPagesToDiskDuringRestartACC
Durant le redémarrage de la partie locale de IndexMemory pour un jalon local.
La valeur par défaut de 20 (1.6 Mo par seconde).

- [DB]ArbitrationTimeout
Ce paramètre spécifie le temps que le nœud de stockage va attendre un message de l'arbitre lors d'un fractionnement du réseau.
La valeur par défaut de 1000 millisecondes (1 seconde).

De nombreux nouveaux paramètres de configuration ont été introduits en MySQL 4.1.5. Ils correspondent à des valeurs qui étaient auparavant configurées durant la compilation. La raison principale à cela est qu'elles permettent aux utilisateurs experts de contrôler la taille du processus et d'ajuster les différentes tailles de buffer, en fonction de ses besoins.

Tous ces buffers sont utilisés comme interface avec le système de fichiers lors de l'écriture des lignes de log sur le disque. Si le nœud fonctionne en mode sans disque, ces paramètres peuvent prendre leur valeur minimale, car les écritures sur le disque sont simulées et toujours validées par la couche d'abstraction du moteur NDB.

- [DB]UndoIndexBuffer
Ce buffer est utilisé durant les jalons locaux. Le moteur de stockage NDB utilise un mécanisme de restauration basé sur des jalons cohérents avec le log de REDO. Afin de produire un jalon valide sans bloquer le système, l'enregistrement des UNDO est fait durant l'exécution des jalons locaux. Le log de UNDO n'est activé que pour un fragment de table à chaque fois. Cette optimisation est rendue possible, car les tables sont entièrement stockées en mémoire principale.
Ce buffer est utilisé pour les modifications dans les index hash de clé primaire. Les insertions et les effacements réarrangent les index hash, et le moteur NDB écrit les logs d'UNDO qui associent les modifications physiques avec un index de page pour qu'ils puissent être appliqués même après un redémarrage. Toutes les insertions actives sont aussi enregistrées au début d'un jalon local, pour chaque fragment.
Les lectures et modifications ne font que poser des bits de verrouillage, et altèrent un entête dans la ligne d'index. Ces modifications sont gérées par l'algorithme d'écriture des pages, pour s'assurer que ces opérations n'ont pas besoin du log d'UNDO.
Ce buffer vaut 2 Mo par défaut. La valeur minimale est 1 Mo. Pour la plupart des applications, c'est suffisant. Les applications qui font beaucoup d'insertions et d'effacement avec de grandes transactions en exploitant intensivement leurs clés primaires devront agrandir ce buffer.
Si le buffer est trop petit, le moteur NDB émet une erreur de code 677 qui se traduit par « Index UNDO buffers overloaded ».

- [DB]UndoDataBuffer
Ce buffer a exactement le même rôle que UndoIndexBuffer, mais est utilisé pour les données. Ce buffer est utilisé durant l'exécution d'un jalon local pour un fragment de table, et les insertions, les effacements et les modifications utilisent ce buffer.
Comme les lignes du log d'UNDO tendent à être plus grandes et que plus d'informations sont stockées, ce buffer doit être aussi de plus grande taille. Par défaut, il vaut 16 Mo. Pour certaines applications, cela peut être surdimensionné, et il est alors recommandé de réduire cette valeur. La taille minimale est de 1 Mo. Il sera rare d'avoir à augmenter cette valeur. Si cette valeur doit être augmentée, commencez par vérifier vos disques et leurs performances. Si ce sont les disques qui limitent le débit, le buffer sera alors bien dimensionné.
Si ce buffer est trop petit et se remplit, le moteur NDB émet une erreur de code 891 qui se traduit par "Data UNDO buffers overloaded".

- [DB]RedoBuffer
Toutes les activités de modification doivent être enregistrées. Cela permet de repasser ces opérations au redémarrage du système. L'algorithme de restauration utilise un jalon cohérent, produit par un jalon « flou » produit par les données couplées aux pages de log d'UNDO. Puis, le log de REDO est appliqué pour rejouer toutes les modifications qui ont eu lieu depuis le redémarrage du système.
Ce buffer fait 8 Mo par défaut. Sa taille minimale est de 1 Mo.
Si ce buffer est trop petit, le moteur NDB émet une erreur de code 1221 qui se traduit par : "REDO log buffers overloaded".

Pour la gestion du cluster, il est important de pouvoir contrôler la quantité de messages de logs qui sont envoyés à stdout par les différents événements qui surviennent. Les événements seront bientôt listés dans ce manuel. Il y a 16 niveaux possibles, allant de 0 à 15. En utilisant un niveau de rapport d'erreur de 15, toutes les erreurs seront rapportées. Un niveau de rapport d'erreur nul (0) bloquera toutes les erreurs.

La raison qui fait que la plupart des valeurs par défaut sont à 0, et qu'elles ne causent aucun affichage sûr est que le même message est envoyé au log du cluster sur le serveur de gestion. Seul le message de démarrage est envoyé à stdout.

Un jeu de niveau d'erreur similaire peut être configuré dans le client de gestion, pour définir les niveaux d'erreurs qui doivent rejoindre le log du cluster.

- [DB]LogLevelStartup
Événements générés durant le démarrage du processus.
Le niveau par défaut est 1.

- [DB]LogLevelShutdown
Événements générés durant l'extinction programmée d'un nœud.
Le niveau par défaut est 0.

- [DB]LogLevelStatistic
Événements statistiques tels que le nombre de clés primaires lues, le nombre d'insertions, modifications et de nombreuses autres informations statistiques sur l'utilisation des buffers.
Le niveau par défaut est 0.

- [DB]LogLevelCheckpoint
Événements générés par les jalons locaux et globaux.
Le niveau par défaut est 0.

- [DB]LogLevelNodeRestart
Événements générés par un redémarrage de nœud.
Le niveau par défaut est 0.

- [DB]LogLevelConnection
Événements générés par les connexions entre les nœuds dans le cluster.
Le niveau par défaut est 0.

- [DB]LogLevelError
Événements générés par les erreurs et alertes dans le cluster. Ces erreurs ne sont pas causées par un échec de nœud, mais sont suffisamment importantes pour être rapportées.
Le niveau par défaut est 0.

- [DB]LogLevelInfo
Événements générés pour informer sur l'état du cluster.
Le niveau par défaut est 0.

Il existe un jeu de paramètres qui définissent les buffers mémoire qui sont utilisés pour l'exécution des sauvegardes en ligne.

- [DB]BackupDataBufferSize
Lors de l'exécution d'une sauvegarde, il y a deux buffers utilisés pour envoyer des données au disque. Ce buffer sert à rassembler des données obtenues par le scan des tables du nœud. Lorsque le regroupement atteint un certain niveau, ces pages sont envoyées au disque. Ce niveau est spécifié par le paramètre BackupWriteSize. Lors de l'envoi des données sur le disque, la sauvegarde continue de remplir ce buffer, jusqu'à ce qu'il n'y ait plus de place. Lorsque la place manque, la sauvegarde marque une pause, et attend que l'écriture ait libéré de la mémoire avant de poursuivre.
La valeur par défaut de 2 Mo.

- [DB]BackupLogBufferSize
Ce paramètre a un rôle similaire, mais sert à écrire un log de toutes les écritures dans la table durant l'exécution de la sauvegarde. Le même principe s'applique à l'écriture de ces pages que pour BackupDataBufferSize, hormis le fait que lorsque la place manque, la sauvegarde échoue par manque de place. Par conséquent, la taille de ce buffer doit être assez grande pour encaisser la charge causée par les activités d'écriture durant l'exécution de la sauvegarde.
La valeur par défaut de ce paramètre doit être assez grande. En fait, il est plus probable qu'une erreur de sauvegarde soit causée par le disque qui ne peut suivre la vitesse d'écriture. Si le disque est sous-dimensionné pour cette opération, le cluster aura du mal à satisfaire les besoins des autres opérations.
Il est important de dimensionner les nœuds pour que les processeurs deviennent les facteurs limitant, bien plus que les disques ou le réseau.
La valeur par défaut de 2 Mo.

- [DB]BackupMemory
Ce paramètre est simplement la somme des deux précédents : BackupDataBufferSize et BackupLogBufferSize.
La valeur par défaut de 4 Mo.

- [DB]BackupWriteSize
Ce paramètre spécifie la taille des messages d'écriture sur le disque, pour le log, ainsi que le buffer utilisé pour les sauvegardes.
La valeur par défaut de 32 ko.

16-4-4-6 - Définition des serveurs MySQL dans un Cluster MySQL

La section [API] (et son alias [MYSQLD]) définit le comportement du serveur MySQL. Aucun paramètre n'est obligatoire. Si aucun ordinateur ou nom d'hôte n'est fourni, alors tous les hôtes pourront utiliser ce nœud.

- [API]Id
Cet identifiant est celui du nœud, qui sert comme adresse pour les messages internes du cluster. C'est un entier compris entre 1 et 63. Chaque nœud du cluster doit avoir une identité distincte.

- [API]ExecuteOnComputer
Cette valeur fait référence à un des ordinateurs définis dans la section computer.

- [API]ArbitrationRank
Ce paramètre sert à définir les nœuds qui jouent le rôle d'arbitre. Les nœuds MGM et les nœuds API peuvent être des arbitres. 0 signifie qu'il n'est pas utilisé comme arbitre, 1 est la priorité haute, et 2 la priorité basse. Une configuration normale utilise un serveur de gestion comme arbitre, en lui donnant un ArbitrationRank de 1 (ce qui est le défaut), et en mettant tous les nœuds API à 0 (ce n'est pas le comportement par défaut en MySQL 4.1.3).

- [API]ArbitrationDelay
En donnant une valeur différente de 0 à cette option, le serveur de gestion va retarder ses réponses d'arbitrage. Par défaut, le délai est nul, et c'est très bien comme cela.

- [API]BatchByteSize
Pour les requêtes qui deviennent des analyses complètes de table ou des analyses d'intervalle, il est important pour les performances de lire les lignes par groupe. Il est possible de configurer la taille de ce groupe en termes de nombre de lignes et de taille de données (en octets). La taille réelle du groupe sera limitée par les deux paramètres.
La vitesse des requêtes peut varier de près de 40 % en fonction de la valeur de ce paramètre. Dans les versions futures, le serveur MySQL fera les estimations nécessaires pour configurer ces paramètres lui-même.
Ce paramètre est mesuré en octets, et par défaut, il vaut 32 KB.

- [API]BatchSize
Ce paramètre est le nombre de lignes et il vaut par défaut 64. La valeur maximale est 992.

- [API]MaxScanBatchSize
La taille du groupe est la taille de chaque groupe envoyé par chaque nœud de stockage. La plupart des analyses sont effectuées en parallèle : pour protéger le serveur MySQL d'un afflux monstrueux de données, ce paramètre permet de limiter le nombre total de groupes sur tous les nœuds.
La valeur par défaut de ce paramètre est de 256 Ko. Sa taille maximale est 16 Mo.

16-4-4-7 - Définition des connexions TCP/IP dans un cluster MySQL

TCP/IP est le mécanisme de transport par défaut pour établir des connexions dans le cluster MySQL. Il n'est pas nécessaire de définir une connexion, car il y aura une connexion automatique entre chaque nœud de stockage, entre chaque nœud MySQL et un nœud de stockage, et entre chaque nœud de gestion et les nœuds de stockage.

Il est uniquement nécessaire de définir une connexion que si vous devez modifier les valeurs par défaut de la connexion. Dans ce cas, il est nécessaire de définir au moins NodeId1, NodeId2 et les paramètres modifiés.

Il est aussi possible de modifier les valeurs par défaut en modifiant les valeurs de la section [TCP DEFAULT].

- [TCP]NodeId1, [TCP]NodeId2
Pour identifier une connexion entre deux nœuds, il est nécessaire de fournir un identifiant de nœud pour chacun d'entre eux dans NodeId1 et NodeId2.

- [TCP]SendBufferMemory
Le transporteur TCP utilise un buffer pour tous les messages avant de les transférer au système d'exploitation. Lorsque le buffer atteint 64 ko, il est envoyé. Le buffer est aussi envoyé lorsque les messages ont été exécutés. Pour gérer les situations temporaires de surcharge, il est possible de définir un sur-buffer. La taille par défaut de ce buffer est 256 ko.

- [TCP]SendSignalId
Pour être capable de suivre le diagramme de message distribué, il est nécessaire d'identifier chaque message avec un marqueur. En activant ce paramètre, le marqueur sera aussi transféré sur le réseau. Cette fonctionnalité n'est pas activée par défaut.

- [TCP]Checksum
Ce paramètre est aussi un paramètre Y/N (oui/non), qui n'est pas activé par défaut. Lorsqu'il est activé, tous les messages sont munis d'une somme de contrôle avant d'être envoyés au buffer. Les vérifications contre les corruptions sont aussi renforcées.

- [TCP]PortNumber
Ceci est le numéro de port à utiliser pour attendre les connexions des autres nœuds. Ce port doit être spécifié dans la section [TCP DEFAULT].
Ce paramètre ne doit plus être utilisé. Utilisez plutôt le paramètre ServerPort sur les nœuds de stockage.

- [TCP]ReceiveBufferMemory
Ce paramètre spécifie la taille du buffer utilisé lors de la réception des données dans la socket TCP/IP. Il y a peu de raisons pour modifier ce paramètre, dont la valeur par défaut est 64 ko. Il permettrait uniquement d'économiser de la mémoire.

16-4-4-8 - Définition des connexions par mémoire partagée dans un cluster MySQL

Les segments de mémoire partagée sont supportés uniquement pour certaines compilations spécifiques du cluster MySQL, avec l'option de configure --with-ndb-shm. Son implémentation va sûrement évoluer. Lorsque vous définissez un segment de mémoire partagée, il est nécessaire de définir au moins NodeId1, NodeId2 et ShmKey. Tous les autres paramètres ont des valeurs par défaut qui fonctionneront dans la plupart des cas.

- [SHM]NodeId1, [SHM]NodeId2
Pour identifier une connexion entre deux nœuds, il est nécessaire de fournir l'identité des deux nœuds dans NodeId1 et NodeId2.

- [SHM]ShmKey
Lors de la configuration de segments de mémoire partagée, un identifiant est utilisé pour définir de manière unique le segment à utiliser pour les communications. C'est un entier qui n'a pas de valeur par défaut.

- [SHM]ShmSize
Chaque connexion a un segment de mémoire où les messages ont été stockés par l'envoyeur, et lus par le lecteur. Ce segment a une taille définie par ce paramètre. Par défaut, il vaut 1 Mo.

- [SHM]SendSignalId
Pour être capable de suivre le diagramme de message distribué, il est nécessaire d'identifier chaque message avec un marqueur. En activant ce paramètre, le marqueur sera aussi transféré sur le réseau. Cette fonctionnalité n'est pas activée par défaut.

- [SCI]Checksum
Ce paramètre est aussi un paramètre Y/N (oui/non), qui n'est pas activé par défaut. Lorsqu'il est activé, tous les messages sont munis d'une somme de contrôle avant d'être envoyés au buffer. Les vérifications contre les corruptions sont aussi renforcées.

16-4-4-9 - Définition d'un transporteur SCI dans un cluster

Les transporteurs SCI sont des connexions entre nœuds dans un cluster MySQL, si ce dernier a été compilé avec l'option --with-ndb-sci=/your/path/to/SCI de la commande configure. Le chemin doit pointer sur le dossier qui contient les bibliothèques SCI et leurs fichiers d'entête.

Il est fortement recommandé d'utiliser les transporteurs SCI pour les communications entre les nœuds ndbd. De plus, utiliser les transporteurs SCI signifie que les processus ndbd ne seront jamais inactifs : utilisez ces transporteurs sur des machines qui ont au moins 2 processeurs, dont un est dédié à ndbd. Il faut au moins un processeur par processus ndbd, et un autre pour gérer les activités du système d'exploitation.

- [SCI]NodeId1, [SCI]NodeId2
Pour identifier une connexion entre deux nœuds, il est nécessaire de fournir un identifiant de nœud pour chacun d'entre eux dans NodeId1 et NodeId2.

- [SCI]Host1SciId0
Identifie le nœud SCI du premier nœud identifié par NodeId1.

- [SCI]Host1SciId1
Il est possible de configurer les transporteurs SCI avec reprise sur incident entre deux cartes SCI qui utilisent deux réseaux distincts. Ce paramètre identifie l'identifiant de nœud et la seconde carte à utiliser sur le premier nœud.

- [SCI]Host2SciId0
Identifie le nœud SCI du premier nœud identifié par NodeId2.

- [SCI]Host2SciId1
Il est possible de configurer les transporteurs SCI avec reprise sur incident entre deux cartes SCI qui utilisent deux réseaux distincts. Ce paramètre identifie l'identifiant de nœud et la seconde carte à utiliser sur le second nœud.

- [SCI]SharedBufferSize
Chaque transporteur dispose d'un segment de mémoire partagée entre deux nœuds. Avec ce segment de taille par défaut 1 Mo, la plupart des applications seront satisfaites. Les tailles inférieures (vers 256 ko) posent des problèmes pour les insertions simultanées. Si le buffer est trop petit, il peut conduire à des crashs de ndbd.

- [SCI]SendLimit
Un petit buffer devant le media SCI temporise les messages avant de les envoyer sur le réseau SCI. Par défaut, sa taille est de 8 ko. La plupart des tests de vitesse montrent que l'amélioration de vitesse est la meilleure à 64 ko, mais que 16 ko arrive presque au même résultat : il n'y avait plus de différence mesurable après 8 ko au niveau du Cluster.

- [SCI]SendSignalId
Pour être capable de suivre le diagramme de message distribué, il est nécessaire d'identifier chaque message avec un marqueur. En activant ce paramètre, le marqueur sera aussi transféré sur le réseau. Cette fonctionnalité n'est pas activée par défaut.

- [SCI]Checksum
Ce paramètre est aussi un paramètre Y/N (oui/non), qui n'est pas activé par défaut. Lorsqu'il est activé, tous les messages sont munis d'une somme de contrôle avant d'être envoyés au buffer. Les vérifications contre les corruptions sont aussi renforcées.

16-5 - Serveur de gestion du cluster MySQL

Il y a quatre processus à bien connaître lorsque vous utilisez le cluster MySQL. Nous allons voir leur fonctionnement, et leurs options.

16-5-1 - Utilisation des processus serveurs MySQL par MySQL Cluster

mysqld est le processus traditionnel du serveur MySQL. Pour être utilisé avec MySQL Cluster, il doit être compilé avec le support des tables NDB. Si le binaire mysqld a été compilé correctement, le moteur de tables NDB Cluster est désactivé par défaut.

Pour activer le moteur NDB, il y a deux méthodes. Soit vous utilisez l'option --ndbcluster au démarrage, lorsque vous utilisez la commande mysqld ou bien, insérez une ligne avec ndbcluster dans la section [mysqld] de votre fichier my.cnf.

Un moyen facile pour vérifier que votre serveur supporte le moteur NDB Cluster est d'utiliser la commande SHOW ENGINES depuis un client mysql. Vous devriez voir la valeur YES dans la ligne de NDBCLUSTER. Si vous voyez NO, c'est que vous n'utilisez pas le programme mysqld compilé avec le support de NDB Cluster. Si vous voyez DISABLED, alors vous devez simplement activer le moteur dans votre fichier de configuration my.cnf.

Le serveur MySQL doit savoir comment lire la configuration du cluster. Pour accéder à cette configuration, il doit connaître trois choses :

- son propre numéro d'identifiant de nœud dans le cluster ;

- le nom d'hôte ou l'adresse IP où le serveur de gestion réside ;

- le port sur lequel se connecter au serveur de gestion.

L'identifiant peut être omis en MySQL version 4.1.5 et plus récent, car les identifiants de nœuds sont dynamiquement alloués.

Il y a actuellement trois moyens pour donner ces informations au processus mysqld. La méthode recommandée est de spécifier la chaîne de connexion de mysqld appelée ndb-connectstring, soit au démarrage de mysqld ou dans le fichier my.cnf. Vous pouvez aussi inclure cette information dans un fichier appelé Ndb.cfg. Ce fichier doit résider dans le dossier de données de MySQL. Une autre solution est de configurer la variable d'environnement appelée NDB_CONNECTSTRING. La chaîne sera la même dans tous les cas : "[nodeid=<id>;][host=]<host>:<port>". Si aucune information n'est fournie, cette chaîne vaudra par défaut "host=localhost:2200".

shell> mysqld --ndb-connectstring=ndb_mgmd.mysql.com:2200

ndb_mgmd.mysql.com est l'hôte où le serveur de gestion réside : il attend sur le port 2200.

Avec cette configuration, le serveur MySQL sera partie prenante du cluster MySQL, et accédera à la liste complète de tous les nœuds du cluster ainsi que leur statut. Il va se connecter à tous les nœuds de stockage, et sera capable d'utiliser chacun d'entre eux comme coordinateur de transactions, ainsi que pour accéder aux données.

16-5-2 - ndbd, le processus de stockage du cluster

ndbd est le processus qui gère les données dans les tables basées sur le moteur NDB Cluster. C'est ce processus qui contient la logique de gestion des transactions distribuées, la restauration des nœuds, la pose des jalons sur le disque, la sauvegarde en ligne, et de nombreuses autres fonctionnalités.

Dans un cluster, il y a un groupe de processus ndbd qui coopèrent pour gérer les données. Ces processus peuvent s'exécuter sur la même machine ou sur des ordinateurs différents, de manière complètement configurable.

Avant MySQL version 4.1.5, le processus ndbd se lançait dans un dossier différent. La raison à cela est que ndbd génère son propre jeu de log dans le dossier de démarrage.

Depuis MySQL 4.1.5, cela a été modifié pour que les fichiers soient placés dans un dossier spécifié par DataDir dans le fichier de configuration. ndbd peut maintenant être lancé depuis n'importe où.

Ces fichiers de logs sont les suivants (le 2 est l'identifiant de nœud).

- ndb_2_error.log (anciennement error.log en version 4.1.3) est le fichier qui contient les informations sur tous les plantages que ndbd a rencontrés, et un message d'erreur court ainsi qu'une référence vers le fichier de trace pour le dernier crash. Une telle ligne peut être :

Date/Time: Saturday 31 January 2004 - 00:20:01
Type of error: error
Message: Internal program error (failed ndbrequire)
Fault ID: 2341
Problem data: DbtupFixAlloc.cpp
Object of reference: DBTUP (Line: 173)
ProgramName: NDB Kernel
ProcessID: 14909
TraceFile: ndb_2_trace.log.2
***EOM***

- ndb_2_trace.log.1 (anciennement NDB_TraceFile_1.trace en version 4.1.3) est un fichier de trace, décrivant exactement ce qui est arrivé avant l'erreur. Cette information est utile pour l'équipe d'administration du cluster MySQL. Les informations de ce fichier sont décrites dans la section MySQL Cluster Troubleshooting. Le nombre de fichiers de trace est configurable, de manière à maîtriser l'écrasement des anciens fichiers par les nouveaux. 1, dans ce contexte, est le numéro du fichier de trace.

- ndb_2_trace.log.next (anciennement NextTraceFileNo.log en version 4.1.3) est le fichier qui garde trace du prochain numéro de fichier de trace.

- ndb_2_out.log est le fichier qui contient les données affichées par le processus ndbd. 2, dans ce contexte, est l'identifiant de nœud. Ce fichier n'existe que si ndbd est lancé en mode démon, ce qui est le défaut en 4.1.5; anciennement node2.out en version 4.1.3)

- ndb_2.pid est le fichier qui contient l'identifiant de processus lorsque ndbd est lancé en mode démon (c'est le comportement par défaut depuis la version 4.1.5 et s'appelait node2.pid en version 4.1.3). Il fonctionne aussi comme un verrou, pour éviter de lancer des nœuds avec le même identifiant.

- ndb_2_signal.log (anciennement Signal.log en version 4.1.3) est le fichier qui ne sert que pour les versions de débogage de ndbd : il est alors possible de suivre les messages entrants, sortants et internes dans le processus ndbd.

Il est recommandé de ne pas utiliser de dossier monté en NFS, car dans certains environnements, il y a des problèmes de verrouillage sur le fichier de PID, même si le processus s'est arrêté.

De même, lorsque vous lancez le processus ndbd, il peut être nécessaire de spécifier le nom d'hôte du serveur de gestion ainsi que son port. Optionnellement, il faut aussi ajouter le numéro d'identification de nœud. Encore une fois, il y a trois façons de spécifier ces informations. Soit une chaîne de connexion qui doit être stockée dans le fichier Ndb.cfg, et ce fichier doit être stocké dans le dossier de démarrage de ndbd. La seconde option est de configurer la variable d'environnement NDB_CONNECTSTRING avant le démarrage du processus. La troisième option est d'utiliser la ligne de commande et l'option ci-dessous. Voyez les sections précédentes pour connaître le format exact de la chaîne.

shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:2200"

Lorsque ndbd se lance, il va lancer en fait deux processus. Le processus de lancement s'appelle « angel » et sa seule tâche est de surveiller la fin du processus d'exécution, et de relancer le processus ndbd s'il est configuré pour cela. Par conséquent, si vous tentez de terminer ndbd avec la commande kill d'Unix, il sera nécessaire de terminer les deux processus. Une solution plus élégante pour gérer la terminaison des processus ndbd est d'utiliser le client de gestion et d'arrêter les processus depuis ce client.

Le processus d'exécution utilise un thread pour toutes ses activités de lecture, écriture et analyse des données, ainsi que pour ses autres activités. Ce thread est conçu pour être asynchrone, et gérer facilement des milliers d'actions simultanées. En plus, il y a un garde-fou qui supervise le thread d'exécution, pour s'assurer que ce dernier ne se bloque pas dans une boucle infinie ou dans un autre problème du même genre. Il y a un pool de thread qui assurent les entrées/sorties. Chaque thread gère un fichier. En plus, d'autres threads peuvent être utilisés pour les activités de transport du processus ndbd. Par conséquent, un processus qui effectue un grand nombre d'activités verra le processus ndbd utiliser deux processeurs, s'il en a la possibilité. Sur une machine avec de nombreux processeurs, il est recommandé d'utiliser plusieurs processus ndbd, qui seront configurés pour représenter différents groupes de nœuds.

16-5-3 - ndb_mgmd, le serveur de gestion

Le serveur de gestion est le processus qui lit le fichier de configuration du cluster, et distribue cette information à tous les nœuds qui le demandent. Il gère aussi le log d'activité du cluster. Les clients de gestion s'y connectent et peuvent l'utiliser pour envoyer des commandes d'analyse et d'administration.

Depuis MySQL version 4.1.5, il n'est plus nécessaire de spécifier une chaîne de connexion lors du démarrage du serveur. Si vous utilisez plusieurs serveurs de gestion, une chaîne de connexion doit être fournie, et tous les nœuds du cluster doivent explicitement spécifier leur identifiant.

Les fichiers suivants sont créés ou utilisés par ndb_mgmd dans son dossier de démarrage de ndb_mgmd. Depuis MySQL version 4.1.5, les fichiers de logs et de PID seront placés dans le dossier de données DataDir spécifié dans le fichier de configuration :

- config.ini est le fichier de configuration du cluster. Il est créé par l'utilisateur et lu par le serveur de gestion. Comment écrire ce fichier est décrit dans la section Section 16.4, « Configuration de MySQL Cluster » ;

- ndb_1_cluster.log (anciennement cluster.log en version 4.1.3) est le fichier où les événements du cluster sont consignés. Les événements du cluster sont, par exemple : les jalons commencés ou complétés, les incidents de nœuds, les démarrages de nœuds, les niveaux d'utilisation de mémoire, etc. Les événements rapportés sont décrits dans la section Section 16.6, « Administration de MySQL Cluster » ;

- ndb_1_out.log (anciennement node1.out en version 4.1.3) est le fichier utilisé pour les entrées et sorties (stdout et stderr) lors de l'exécution du serveur de gestion comme démon. 1, dans ce contexte, est l'identifiant de nœud ;

- ndb_1.pid (anciennement node1.pid en version 4.1.3) est le fichier de PID utilisé lors de l'exécution du serveur de gestion comme démon. 1, dans ce contexte, est l'identifiant de nœud ;

- ndb_1_cluster.log.1 (anciennement cluster.log.1 en version 4.1.3), lorsque le log de cluster dépasse un million d'octets, alors le fichier de logs prend le nom indiqué ici, où 1 est le nombre de fichiers de logs : si 1, 2 et 3 existent déjà, le suivant sera le numéro 4.

16-5-4 - ndb_mgm, le client de gestion du cluster

Le dernier processus important à connaître est le client de gestion. Ce processus n'est pas nécessaire pour faire fonctionner le cluster. Son intérêt est que pouvoir vérifier le statut du cluster, de lancer les sauvegardes, et effectuer les autres activités d'administration. Il fournit un moyen d'accès et un jeu de commandes.

En fait, le client de gestion utilise une interface C qui donne l'accès au serveur de gestion : pour les utilisateurs experts, il est possible de programmer des processus spécifiques qui pourront effectuer des tâches d'administration automatisées.

Lorsque vous lancez le client de gestion, il est nécessaire d'indiquer le nom d'hôte et le port du serveur de gestion, comme dans l'exemple ci-dessous. Par défaut, c'est l'hôte local et le port 2200.

shell> ndb_mgm localhost 2200

16-5-5 - Options des commandes pour le cluster MySQL

16-5-5-1 - Options de cluster de mysqld

- --ndbcluster
Si le binaire supporte le moteur de table NDB Cluster, le comportement par défaut est de désactiver son support. Vous pouvez changer ce comportement avec cette option. Utiliser le moteur NDB Cluster est obligatoire pour pouvoir utiliser MySQL Cluster.

- --skip-ndbcluster
Désactive le moteur de table NDB Cluster. C'est le comportement par défaut pour les applications où il est inclus. Cette option peut s'appliquer uniquement si le serveur a été configuré pour utiliser le moteur de table NDB Cluster.

- --ndb-connectstring=connect_string
Lorsque de l'utilisation du moteur de table NDB, il est possible de désigner le serveur de gestion qui distribue les configurations du cluster en lui assignant une chaîne de connexion.

16-5-5-2 - Options de la commande ndbd

- -?, --usage
Ces options ne font qu'afficher l'aide du programme.

- -c connect_string, --connect-string connect_string
Pour ndbd, il est aussi possible de spécifier la chaîne de connexion au serveur de commande, sous forme d'option.

shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:2200"

- -d, --daemon
Indique à ndbd qu'il doit s'exécuter comme démon. Depuis MySQL version 4.1.5, c'est le comportement par défaut.

- --nodaemon
Indique à ndbd qu'il ne doit pas se lancer comme un démon. C'est pratique lors du débogage de ndbd et que vous voulez avoir l'affichage des résultats du programme.

- --initial
Demande à ndbd de faire un démarrage initial. Un démarrage initial efface tous les fichiers créés par d'anciens ndbd durant la restauration. Il va aussi créer le fichier de logs de restauration, ce qui peut prendre beaucoup de temps sur certains systèmes d'exploitation.
Un démarrage initial ne sert qu'au tout premier démarrage du processus ndbd. Il supprime tous les fichiers du système de fichiers, et crée tous les fichiers de logs REDO. Lorsque vous faites une mise à jour logicielle qui modifie le contenu de ces fichiers, il est aussi nécessaire d'utiliser cette option au redémarrage de ndbd. Enfin, cette option peut être utile en dernier recours, si votre système n'arrive pas à redémarrer. Dans ce cas, soyez conscients que détruire le contenu du système de fichiers signifie que ce nœud ne peut plus être utilisé pour restaurer des données.
Cette option n'affecte pas les fichiers de sauvegarde créés.
L'ancienne fonctionnalité représentée par -i pour cette option a été supprimée pour s'assurer qu'elle n'est pas confondue avec celle-ci par mégarde.

- --nostart
Indique à ndbd de ne pas démarrer automatiquement. ndbd va se connecter au serveur de gestion, obtiendra le fichier de configuration, et initialisera les communications avec les nœuds. Mais il ne va pas lancer le moteur d'exécution jusqu'à ce qu'il en reçoive l'ordre manuel du serveur de gestion. Le serveur de gestion peut émettre cette commande sur ordre du client de gestion.

- -v, --version
Affiche le numéro de version du processus ndbd. Le numéro de version est celui du cluster MySQL. Il est important, car au moment du lancement du cluster, MySQL vérifie si les versions des serveurs des nœuds peuvent cohabiter dans le cluster. Il est aussi important durant les mises à jour logicielles du cluster (voyez la section Software Upgrade of MySQL Cluster).

- --debug=options
Cette option peut être utilisée avec les versions compilées en mode débogage. Elle sert à activer l'affichage des appels de débogage, de la même manière que pour mysqld.

- -? --usage
Affiche une description rapide des options disponibles.

16-5-5-3 - Options de commande pour ndb_mgmd

- -?, --usage
Ces options font afficher l'aide du programme.

- -c filename, --config-file=filename
Indique au serveur de gestion quel fichier de configuration utiliser. Cette option est obligatoire. Le nom par défaut du fichier est config.ini.

- -d, --daemon
Indique au client ndb_mgmd de se lancer sous forme de démon. C'est le comportement par défaut.

- -nodaemon
Indique au serveur de gestion de ne pas se lancer comme un démon.

- -v, --version
Affiche le numéro de version du serveur de gestion. Le numéro de version est celui du cluster MySQL. Le serveur de gestion peut s'assurer que seules les versions compatibles avec lui sont acceptées et utilisées dans le cluster.

- --debug=options
Cette option ne peut être utilisée que dans les versions compilées en mode débogage. Elle est utilisée pour afficher plus d'informations de fonctionnement et accepter les appels de fonctions de débogages de mysqld.

16-5-5-4 - Options de commande pour ndb_mgm

- -?, --usage
Ces options ne font qu'afficher l'aide du programme.

- [host_name [port_num]]
Pour lancer le client de gestion, il est nécessaire de spécifier où le serveur de gestion réside. Cela signifie qu'il faut spécifier le nom d'hôte et le port de communication. Par défaut, l'hôte est localhost et le port par défaut est 2200.

- --try-reconnect=number
Si la connexion au serveur de gestion se perd, il est possible de spécifier le nombre de tentatives avant de conclure à une erreur. Par défaut, le client va réessayer toutes les 5 secondes jusqu'à ce qu'il réussisse.

16-6 - Administration de MySQL Cluster

Gérer un cluster MySQL implique différentes opérations. La première est celle de configurer et de démarrer le cluster MySQL : elle est couverte par les sections Section 16.4, « Configuration de MySQL Cluster » et Section 16.5, « Serveur de gestion du cluster MySQL ». Cette section couvre la gestion d'un cluster MySQL en fonctionnement.

Il y a essentiellement deux moyens pour gérer activement un cluster MySQL en fonctionnement. La première est l'utilisation des commandes dans le client de gestion, qui surveille le statut du cluster, les niveaux de logs, les sauvegardes en cours et les nœuds qui peuvent être arrêtés ou relancés. La seconde méthode utilise le résultat du log du cluster. Le log du cluster est envoyé dans le fichier ndb_2_cluster.log dans le dossier DataDir du serveur de gestion. Le log du cluster contient les rapports d'événements du moteur ndbd et de ses processus dans le cluster. Il est possible aussi d'envoyer le log dans le log système Unix.

16-6-1 - Commandes du client de gestion du Cluster

En plus du fichier de configuration central, le cluster peut aussi être contrôlé avec une interface en ligne de commande. La ligne de commande est disponible via un processus séparé de client de gestion du cluster. C'est l'interface principale de gestion du cluster.

Le client de gestion a les commandes suivantes de base. Ci-dessous, <id> indique un nœud de base de données (i.e. 21) ou le mot-clé ALL qui indique que la commande doit être appliquée à tous les nœuds dans le cluster.

- HELP
Affiche les informations sur toutes les commandes disponibles.

- SHOW
Affiche les informations sur le statut du cluster.

- <id> START
Lance le nœud de base de données identifié par <id>, ou bien tous les nœuds.

- <id> STOP
Stoppe le nœud de base de données identifié par <id>, ou bien tous les nœuds.

- <id> RESTART [-N] [-I]
Relance le nœud de base de données identifié par <id>, ou bien tous les nœuds.

- <id> STATUS
Affiche les informations de statut du nœud de base de données identifié par <id> (ou de tous les nœuds avec ALL).

- ENTER SINGLE USER MODE <id>
Active le mode d'utilisateur unique, où seule l'API avec le nœud <id> est autorisée pour accéder au système de base de données.

- EXIT SINGLE USER MODE
Quitte le mode d'utilisateur unique.

- QUIT
Quitte le client de gestion du cluster.

- SHUTDOWN
Arrête tous les nœuds du cluster, hormis les serveurs MySQL, puis s'arrête.

Les commandes des logs d'événements sont listées dans la prochaine section, et les commandes de sauvegarde sont données dans une section séparée.

16-6-2 - Rapport d'événements générés par le cluster MySQL

Le cluster MySQL a deux logs d'événements : le log de cluster et le log de nœuds.

- Le log de cluster est un log pour le cluster entier, et il peut avoir différentes destinations (fichiers, console du serveur de gestion, ou log système).

- Le log de nœuds est un log local à chaque nœud, et il est envoyé vers la console. Les deux logs peuvent être configurés pour recevoir des sous-ensembles de tous les événements.

Note : le log du cluster est le log recommandé. Le log de nœuds ne sert que pour le développement d'application ou le débogage.

Chaque événement a les propriétés suivantes :

- Catégorie (STARTUP, SHUTDOWN, STATISTICS, CHECKPOINT, NODERESTART, CONNECTION, ERROR, INFO) ;

- Priorité (1-15 où 1 est le plus important, et 15 le moins important) ;

- Sévérité (ALERT, CRITICAL, ERROR, WARNING, INFO, DEBUG).

Les deux logs (celui du cluster et celui du nœud) peuvent être filtrés en fonction de ces propriétés.

16-6-2-1 - Historique des commandes de gestion

Les commandes suivantes sont liées au log du cluster :

- CLUSTERLOG ON
Activation du log du cluster

- CLUSTERLOG OFF
Désactivation du log du cluster.

- CLUSTERLOG INFO
Informations sur la configuration du log.

- <id> CLUSTERLOG <category>=<threshold>
Enregistre les catégories d'événements ayant une priorité inférieure ou égale au seuil indiqué, dans le log du cluster.

- CLUSTERLOG FILTER <severity>
Active/désactive l'enregistrement des types de sévérités indiquées.

La table suivante décrit les configurations par défaut pour tous les nœuds de bases de données dans le cluster. Si un événement a une priorité dont la valeur est inférieure ou égale à seuil de priorité, il est alors enregistré dans le log du cluster.

Notez que les événements sont rapportés pour chaque nœud de base de données, et que les seuils peuvent être différents sur chaque nœud.

Catégorie

seuil par défaut (toutes les bases)

STARTUP

7

SHUTDOWN

7

STATISTICS

7

CHECKPOINT

7

NODERESTART

7

CONNECTION

7

ERROR

15

INFO

7

Un seuil permet de filtrer les événements par catégorie. Par exemple, un événement STARTUP avec une priorité de 3 n'est jamais émis à moins que le seuil de STARTUP ne soit changé à 3 ou plus bas. Seuls les événements avec des priorités de 3 ou plus bas sont émis si le seuil est de 3. Les sévérités d'événements correspondent au niveau du log système d'UNIX. Ce sont :

1

ALERT

Un problème qui doit être corrigé immédiatement, comme une base de données corrompue

2

CRITICAL

Problèmes critiques, comme une erreur de volume ou un manque de ressources

3

ERROR

Problèmes qui doivent être corrigés, comme un problème de configuration

4

WARNING

Problèmes qui ne sont pas des erreurs, mais requièrent un traitement

5

INFO

Message d'information

6

DEBUG

Messages pour le développement de NDB Cluster

Les niveaux syslog de LOG_EMERG et LOG_NOTICE ne sont pas utilisés.

Les sévérités d'événements peuvent être activées ou pas. Si la sévérité est active, alors tous les événements avec une priorité inférieure ou égale au seuil seront enregistrés. Si la sévérité est éteinte, alors aucun événement de cette sévérité ne sera enregistré.

Les commandes suivantes sont liées au log du nœud :

- <id> LOGLEVEL <levelnumber> Active le niveau de log pour le processus de base de données id, avec le niveau <levelnumber>.

16-6-2-2 - Événements

Tous les événements rapportés sont listés ici.

Événements

Catégorie

Priorité

Sévérité

Description

DB nodes connected

CONNECTION

8

INFO

DB nodes disconnected

CONNECTION

8

INFO

Communication closed

CONNECTION

8

INFO

Connexion aux nœuds API & DB fermée

Communication opened

CONNECTION

8

INFO

Connexion aux nœuds API & DB fermée

Global checkpoint started

CHECKPOINT

9

INFO

Début de GCP, i.e., le log REDO est écrit sur le disque

Global checkpoint completed

CHECKPOINT

10

INFO

GCP terminé

Local checkpoint started

CHECKPOINT

7

INFO

Début d'une vérification de jalon local, i.e., les données sont écrites sur le disque. LCP Id et GCI Id

Local checkpoint completed

CHECKPOINT

8

INFO

LCP terminé

LCP stopped in calc keep GCI

CHECKPOINT

0

ALERT

LCP arrêté !

Local checkpoint fragment completed

CHECKPOINT

11

INFO

Un LCP sur un fragment a été terminé

Report undo log blocked

CHECKPOINT

7

INFO

Le log d'annulation est bloqué, car le buffer est presque plein

DB node start phases initiated

STARTUP

1

INFO

NDB Cluster démarre

DB node all start phases completed

STARTUP

1

INFO

NDB Cluster démarré

Internal start signal received STTORRY

STARTUP

15

INFO

Signal interne pour bloquer la réception après la fin du redémarrage

DB node start phase X completed

STARTUP

4

INFO

La phase de démarrage est finie

Node has been successfully included into the cluster

STARTUP

3

INFO

Le nœud président, le nœud courant et l'identifiant dynamique sont affichés

Node has been refused to be included into the cluster

STARTUP

8

INFO

DB node neighbours

STARTUP

8

INFO

Affichage des nœuds voisins à gauche et à droite

DB node shutdown initiated

STARTUP

1

INFO

DB node shutdown aborted

STARTUP

1

INFO

New REDO log started

STARTUP

10

INFO

GCI garde X, dernier jalon accessible GCI Y

New log started

STARTUP

10

INFO

Log termine X, démarre MB Y, stoppe MB Z

Undo records executed

STARTUP

15

INFO

Completed copying of dictionary information

NODERESTART

8

INFO

Completed copying distribution information

NODERESTART

8

INFO

Starting to copy fragments

NODERESTART

8

INFO

Completed copying a fragment

NODERESTART

10

INFO

Completed copying all fragments

NODERESTART

8

INFO

Node failure phase completed

NODERESTART

8

ALERT

Indique un échec de nœud

Node has failed, node state was X

NODERESTART

8

ALERT

Indique qu'un nœud a échoué

Report whether an arbitrator is found or not

NODERESTART

6

INFO

7 résultats différents

- Président relance le thread d'arbitrage [state=X]

- Préparation de l'arbitrage, nœud X [ticket=Y]

- Reçoit l'arbitrage, nœud X [ticket=Y]

- Démarre l'arbitrage X [ticket=Y]

- Perte de l'arbitrage, nœud X - echec de traitement [state=Y]

- Perte de l'arbitrage, nœud X - fin de traitement [state=Y]

- Perte de l'arbitrage, nœud X <error msg>[state=Y]

Report arbitrator results

NODERESTART

2

ALERT

8 résultats différents

- Arbitrage perdu - moins de la moitié des nœuds dispo

- Arbitrage gagné - majorité du groupe de nœuds

- Arbitrage perdu - plus de groupe de nœuds

- Partage du réseau - arbitrage demandé

- Arbitrage gagné - réponse positive du nœud X

- Arbitrage perçus - réponse négative du nœud X

- Partage du réseau - pas d'arbitre disponible

- Partage du réseau - par d'arbitre configuré

GCP take over started

NODERESTART

7

INFO

GCP take over completed

NODERESTART

7

INFO

LCP take over started

NODERESTART

7

INFO

LCP take completed (state = X)

NODERESTART

7

INFO

Report transaction statistics

STATISTICS

8

INFO

nombre de transactions, archivages, lectures, lectures simples, écritures, opérations simultanées, attributs, annulations

Report operations

STATISTICS

8

INFO

nombre d'opérations

Report table create

STATISTICS

7

INFO

Report job scheduling statistics

STATISTICS

9

INFO

Statistiques internes de programmation de tâches

Sent # of bytes

STATISTICS

9

INFO

Moyenne de nombre d'octets envoyés au nœud X

Received # of bytes

STATISTICS

9

INFO

Moyenne de nombre d'octets reçus au nœud X

Memory usage

STATISTICS

5

INFO

Uitlisation de la mémoire pour les données et les index(80 %, 90 % et 100 %)

Transporter errors

ERROR

2

ERROR

Transporter warnings

ERROR

8

WARNING

Missed heartbeats

ERROR

8

WARNING

Le nœud X a raté une pulsation # Y

Dead due to missed heartbeat

ERROR

8

ALERT

Le nœud X est déclaré mort à cause des pulsations manquées

General warning events

ERROR

2

WARNING

Sent heartbeat

INFO

12

INFO

Pulsation envoyée au nœud X

Create log bytes

INFO

11

INFO

Partie de log, fichier de logs, taille

General info events

INFO

2

INFO

Un événement a le format suivant dans le log :

<date & time in GMT> [<any string>] <event severity> -- <log message>

09:19:30 2003-04-24 [NDB] INFO -- Node 4 Start phase 4 completed

16-6-3 - Utilisateur unique du cluster

Le mode d'utilisateur unique permet à l'administrateur de restreindre l'accès au système de base de données à une seule application (un nœud API). Lorsque vous passez en mode utilisateur unique, toutes les connexions aux nœuds d'API seront refermées et aucune transaction ne sera autorisée. Toutes les transactions en cours sont annulées.

Lorsque le cluster entre en mode d'utilisateur unique (utilisez la commande de statut pour voir si l'état est activé), seul le nœud autorisé dispose d'un accès à la base de données.

Exemple :

ENTER SINGLE USER MODE 5

Après avoir exécuté cette commande, et après que le cluster est entré en mode d'utilisateur unique, le nœud d'API d'identifiant 5 devient le seul utilisateur du cluster.

Le nœud spécifié dans la commande ci-dessus doit être un nœud MySQL. Toute tentative de spécifier un autre type de nœud sera rejetée.

Note : si le nœud avec l'identifiant 5 est exécuté avec le mode ENTER SINGLE USER MODE 5, toutes les transactions du nœud 5 seront annulées, les connexions fermées et le serveur devra redémarrer.

La commande EXIT SINGLE USER MODE fait passer le cluster de mode « single user mode » à « started ». Les serveurs MySQL en attente de connexion seront autorisés à se connecter. Le serveur identifié comme utilisateur unique sera autorisé à continuer durant et après la phase de transition.

Exemple :

EXIT SINGLE USER MODE

La meilleure pratique dans le cas des incidents de nœuds en mode d'utilisateur unique est de :

1. Finir toutes les transactions d'utilisateur unique ;

2. Quitter le mode d'utilisateur unique ;

3. Redémarrer les nœuds de bases de données.

Ou redémarrer les nœuds de bases avant de passer en mode utilisateur unique.

16-6-4 - Sauvegarde en ligne de MySQL Cluster

Cette section décrit comment créer une sauvegarde et restaurer ultérieurement une base de données.

16-6-4-1 - Sauvegarde du cluster

Une sauvegarde représente le contenu d'une base de données, à un moment donné. La sauvegarde contient trois parties principales :

1. Les métadonnées (quelles tables existent, etc.) ;

2. Les lignes des tables(les données) ;

3. Un historique des transactions archivées.

Chaque partie est stockée sur tous les nœuds qui participent à la sauvegarde.

Durant une sauvegarde, chaque nœud sauve ses données sur le disque, en trois fichiers :

- BACKUP-<BackupId>.<NodeId>.ctl
Le fichier de contrôle, qui contient les données de contrôle et les métadonnées ;

- BACKUP-<BackupId>-0.<NodeId>.data
Le fichier de données qui contient les lignes des tables ;

- BACKUP-<BackupId>.<NodeId>.log
Le fichier de logs, qui contient les transactions archivées.

Dans les lignes ci-dessus, <BackupId> est un identifiant pour la sauvegarde, et <NodeId> est l'identifiant du nœud qui a créé le fichier.

- Meta data
Les métadonnées sont constituées des définitions de table. Tous les nœuds ont la même définition de table, sauvée sur le disque.

- Table records
Les lignes sont sauvées par fragment. Chaque fragment contient un entête qui décrit à quelle table appartiennent les lignes. Après un groupe de lignes, il y a pied-de-page qui contient une somme de contrôle. Différents nœuds sauvent différents fragments durant la sauvegarde.

- Committed log
L'historique contient les transactions archivées, effectuées durant la sauvegarde. Seules les transactions impliquant les tables stockées sur le nœud sont stockées dans le log. Les différents nœuds de la sauvegarde sauvent différents logs, car ils abritent différents fragments de bases de données.

16-6-4-2 - Utilisation du serveur de gestion pour une sauvegarde de cluster

Avant de lancer la sauvegarde, assurez-vous que le cluster est correctement configuré pour les sauvegardes.

1. Lancez le serveur de gestion.

2. Exécutez la commande START BACKUP.

3. Le serveur de gestion vous indiquera « Start of backup ordered ». Cela signifie que le serveur de gestion a envoyé la requête au cluster, mais qu'il n'a pas encore reçu de réponse.

4. Le serveur de gestion va indiquer « Backup <BackupId> started », où <BackupId> est l'identifiant de la sauvegarde. Cette information sera aussi enregistrée dans le log du cluster (à moins que cela ne soit configuré autrement). Cela signifie que le serveur a reçu des réponses, et que la sauvegarde a été faite. Cela ne signifie pas que la sauvegarde est complète.

5. Le serveur de gestion va indiquer que la sauvegarde est finie avec le message « Backup <BackupId> completed ».

Utilisation du serveur pour annuler une sauvegarde :

1. Lancez le serveur de gestion ;

2. Exécutez la commande ABORT BACKUP <BACKUPID>. Le numéro <BackupId> est l'identifiant de la sauvegarde, qui est inclus dans la réponse du serveur de gestion au moment de la création de la sauvegarde : « Backup <BackupId> started ». L'identifiant est aussi sauvé dans le log du cluster (cluster.log) ;

3. Le serveur de gestion répond « Abort of backup <BackupId> ordered ». Cela signifie qu'il a envoyé la requête au cluster, mais n'a pas encore reçu de réponse ;

4. Le serveur de gestion répond « Backup <BackupId> has been aborted reason XYZ ». Cela signifie que le cluster a annulé la sauvegarde, et supprimé toutes les ressources reliées, y compris les fichiers.

Notez que s'il n'y a pas de sauvegarde en cours avec l'identifiant <BackupId> lors de l'annulation, le serveur de gestion ne répondra rien du tout. Cependant, une ligne sera enregistrée dans le log du cluster mentionnant « invalid ».

16-6-4-3 - Comment restaurer une sauvegarde du cluster

Le programme de restauration est une commande distincte. Il lit les fichiers de sauvegarde créés, et insère les informations dans la base. Le programme de restauration doit être exécuté pour chaque fichier de sauvegarde, c'est-à-dire aussi souvent qu'il y a de nœuds dans le cluster au moment de la création de la sauvegarde.

La première fois que vous exécutez le programme de restauration, vous devez aussi restaurer les métadonnées, c'est-à-dire créer les tables. Le programme de restauration sert d'API avec le cluster, et il a donc besoin d'une connexion libre pour ce faire. Vous pouvez le vérifier avec la commande SHOW de ndb_mgm. De la même manière que pour les autres nœuds API, c'est-à-dire mysqld,le fichier Ndb.cfg, la variable d'environnement NDB_CONNECTSTRING ou l'option de démarrage -c <connectstring> sert à situer le serveur de gestion. Les fichiers de sauvegarde doivent être présents dans le dossier indiqué comme argument du programme. La sauvegarde peut être restaurée vers une base ayant une configuration différente de celle qui a créé la sauvegarde. Par exemple, la sauvegarde 12, créée avec deux nœuds de bases d'identifiants 2 et 3, peut être restaurée sur un cluster de 4 nœuds. Le programme doit alors être exécuté 2 fois : une fois pour chaque nœud du cluster où la sauvegarde a été faite, tel que décrit ci-dessous.

Note : pour une restauration rapide, les données peuvent être relues en parallèle, tant qu'il y a suffisamment de connexions API libres. Notez que les fichiers de données doivent toujours être appliqués avant les logs.

Note : le cluster doit toujours être vide lors du démarrage d'une restauration.

16-6-4-4 - Configuration pour la sauvegarde du Cluster

Il y a quatre paramètres de configuration pour la sauvegarde :

- BackupDataBufferSize
La quantité de mémoire utilisée pour les buffers avant que les données soient écrites sur le disque ;

- BackupLogBufferSize
La quantité de mémoire utilisée pour les buffers de logs, avant qu'ils ne soient écrits sur le disque ;

- BackupMemory
La quantité totale de mémoire allouée pour effectuer les sauvegardes. Cela doit être la somme des deux options précédentes ;

- BackupWriteSize
La taille des blocs écrits sur le disque. Cela s'applique aussi bien aux buffers de données qu'aux buffers de log.

16-6-4-5 - Résolution de problèmes avec la sauvegarde du cluster

Si un code d'erreur est retourné lors de la sauvegarde, alors vérifiez s'il y a assez de mémoire allouée pour la sauvegarde (i.e. les paramètres de configuration). Vérifiez aussi s'il y a assez d'espace sur le disque pour tout accueillir.

16-7 - Utilisation d'interconnexions haute vitesse avec MySQL Cluster

Bien avant de concevoir le cluster NDB en 1996, il est apparu que l'un des problèmes majeurs dans l'architecture d'une base de données parallèle est la communication entre les nœuds via un réseau. Par conséquent, dès le début, le cluster NBD a été conçu pour supporter le concept de transporteur, et pour en supporter différentes sortes.

Actuellement, le code de base inclut 4 transporteurs différents, dont 3 d'entre eux sont déjà fonctionnels. La majorité des utilisateurs exploitent TCP/IP aujourd'hui, via Ethernet, car ces technologies sont disponibles sur toutes les machines. C'est aussi le transporteur le mieux testé du MySQL Cluster.

Chez MySQL, nous travaillons fort pour nous assurer que les communications entre les processus ndbd sont faites avec des paquets aussi gros que possible, car cela profitera à tous les médias de communication : tous les modes de transports gagnent à envoyer des messages de grande taille par rapport à des messages de petite taille.

Pour les utilisateurs qui recherchent les performances absolues, il est aussi possible d'utiliser des interconnexions de cluster pour améliorer encore les performances. Il y a deux moyens pour cela, soit en utilisant un transporteur qui a été conçu pour cela, soit en utilisant des sockets qui évitent le recours aux piles TCP/IP.

Nous avons fait des expériences avec les variantes de ces techniques, et avec la technologie SCI, développée par Dolphin (www.dolphinics.no).

16-7-1 - Configurer le cluster MySQL avec les sockets SCI

Dans cette section, nous allons vous montrer comment utiliser un cluster TCP/IP normal avec les sockets SCI. Le prérequis pour cela est que les machines doivent être capables de communiquer avec des cartes SCI. Cette documentation est basée sur les sockets SCI version 2.3.0, du 1er octobre 2004.

Pour utiliser les sockets SCI, vous pouvez utiliser n'importe quelle version du cluster MySQL. Les tests ont été faits sur la version 4.1.6. Aucune compilation particulière n'est nécessaire, car il utilise les appels normaux aux sockets, ce qui est la configuration de MySQL Cluster. Les sockets SCI ne sont supportées que sur les noyaux Linux 2.4 et 2.6 pour le moment. Les transporteurs SCI fonctionnent sur d'autres systèmes d'exploitation, même si seul Linux 2.4 a été vérifié.

Il y a essentiellement 4 choses nécessaires pour activer les sockets SCI. La première est de compiler les bibliothèques de sockets SCI. La seconde est d'installer les bibliothèques SCI dans le noyau. La troisième est d'installer les fichiers de configuration. Enfin, la bibliothèque SCI du noyau doit être activée pour toute la machine, ou pour le shell d'où le cluster MySQL est lancé. Ce processus doit être répété pour chaque machine du cluster qui utilisera les sockets SCI pour communiquer.

Deux paquets doivent être installés pour faire fonctionner les sockets SCI. Le premier paquet compile les bibliothèques avec lesquelles les bibliothèques SCI sont compilées. Actuellement, la distribution est uniquement au format code source.

Les dernières versions de ces paquets sont actuellement disponibles à :

http://www.dolphinics.no/support/downloads.html

http://www.dolphinics.no/ftp/source/DIS_GPL_2_5_0_SEP_10_2004.tar.gz
http://www.dolphinics.no/ftp/source/SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz

La prochaine étape est de décompresser ces dossiers. Les sockets SCI sont décompressées sous le code DIS. Puis, le code de base est compilé. L'exemple ci-dessous montre les commandes utilisées sur Linux/x86 pour ce faire.

shell> tar xzf DIS_GPL_2_5_0_SEP_10_2004.tar.gz
shell> cd DIS_GPL_2_5_0_SEP_10_2004/src/
shell> tar xzf ../../SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz
shell> cd ../adm/bin/Linux_pkgs
shell> ./make_PSB_66_release

Si la compilation se passe sur une machine Opteron, et doit utiliser l'extension 64 bits, alors utilisez make_PSB_66_X86_64_release à la place. Si la compilation a lieu sur Itanium, utilisez make_PSB_66_IA64_release. Les variantes X86-64 devraient fonctionner pour les architectures Intel EM64T, mais aucun test n'est connu pour cela.

Après avoir compilé le code de base, il est placé dans une archive compressée. Il est temps d'installer le paquet au bon endroit. Dans cet exemple, nous allons placer l'installation dans le dossier /opt/DIS. Ces actions vous imposeront de vous identifier comme super-utilisateur.

shell> cp DIS_Linux_2.4.20-8_181004.tar.gz /opt/
shell> cd /opt
shell> tar xzf DIS_Linux_2.4.20-8_181004.tar.gz
shell> mv DIS_Linux_2.4.20-8_181004 DIS

Maintenant que les bibliothèques et les binaires sont en place, nous devons nous assurer que les cartes SCI reçoivent les bons identifiants de nœuds dans l'espace SCI. Comme SCI est un élément réseau, nous devons commencer par décider de la structure du réseau.

Il y a trois types de structure de réseau : la première est un simple anneau unidimensionnel, le second utilise les hubs SCI, avec un anneau par hub, et finalement, il y a des tores 2D et 3D. Chaque type a sa technique pour attribuer les identifiants.

Un anneau simple utilise des identifiants espacés de 4 :

4, 8, 12, …

La deuxième méthode utilise des hubs. Le hub SCI a 8 ports. Sur chaque port, il est possible de placer un anneau. Il est nécessaire de s'assurer que les anneaux des hubs utilisent des espaces d'identifiants différents. Le premier port utilisera les identifiants inférieurs à 64, et les 64 identifiants suivants seront attribués au prochain port, etc.

4,8, 12, …, 60  Anneau du premier port
68, 72, …, 124 Anneau du deuxième port
132, 136, …, 188 Anneau du troisième port
…
452, 456, …, 508 Anneau du huitième port

Les structures de réseaux en tore 2D/3D prennent en compte la position de chaque nœud dans chaque dimension. La première dimension est incrémentée de 4, la deuxième de 64 et la troisième de 1024. Regardez dans le dauphin pour plus d'informations dessus.

Durant nos tests, nous avons utilisé des hubs. La majorité des très gros clusters utilisent des installations à Tore 2D/3D. La fonctionnalité supplémentaire que permettent les hubs est qu'avec des doubles cartes SCI, nous pouvons facilement construire un réseau redondant, où les erreurs de réseau sont aussitôt reprises en 100 microsecondes. Cette fonctionnalité est supportée par le transporteur SCI, et est actuellement en développement pour les sockets SCI.

La reprise sur échec est aussi possible avec les tores 2D/3D, mais elle impose l'envoi de nouveaux index de routages à tous les nœuds. Cela prend environ 100 millisecondes et sera probablement acceptable pour les situations de haute disponibilité.

En agençant correctement les nœuds NDB dans l'architecture, il est possible d'utiliser deux hubs pour monter une architecture de 16 ordinateurs interconnectés, sans aucun point d'interruption. Avec 32 ordinateurs et 2 hubs, il est possible de configurer le cluster de telle manière qu'un incident ne perturbera pas plus de 2 nœuds, et dans ce cas, on saura même quelle paire sera touchée. Par conséquent, en plaçant ces serveurs dans des groupes NDB séparés, il est possible de construire un cluster MySQL sécurisé. Nous n'entrerons pas dans les détails de cette architecture, car seuls ceux qui le souhaitent auront la patience de lire ce niveau de détails.

Pour configurer l'identifiant de nœud sur une carte SCI, utilisez l'une des commandes disponibles dans le dossier /opt/DIS/sbin. -c 1 fait référence à la carte SCI, où 1 est son numéro s'il y a une seule carte sur la machine. Dans ce cas, utilisez toujours l'adapteur 0 (avec -a 0). 68 est l'identifiant de nœud choisi comme exemple :

shell> ./sciconfig -c 1 -a 0 -n 68

Dans ce cas, nous avons plusieurs cartes SCI dans notre machine, et la seule solution sécuritaire pour savoir quelle carte est dans quel emplacement est d'utiliser la commande suivante :

shell> ./sciconfig -c 1 -gsn

Elle vous retournera le numéro de série de la carte, qui peut être trouvée sur son dos. Répétez cette manipulation avec -c 2, etc., en fonction du nombre de cartes que vous avez sur la machine. Vous pourrez ainsi identifier les cartes de la machine.

Maintenant, nous avons installé les bibliothèques et les exécutables. Nous avons aussi configuré les identifiants de nœuds. L'étape d'après est d'effectuer le plan de noms ou d'adresses IP pour les nœuds SCI.

Le fichier de configuration des sockets SCI doit être placé dans le fichier /etc/sci/scisock.conf. Ce fichier contient la carte des noms d'hôtes et leur correspondance avec les nœuds SCI. L'identifiant de nœud SCI correspond avec un autre via la carte SCI. Ci-dessous, voici un fichier de configuration très simple :

#host           #nodeId
alpha           8
beta            12
192.168.10.20   16

Il est aussi possible de limiter cette configuration pour qu'elle ne s'applique qu'à une sous-partie des ports des hôtes. Pour cela, une autre configuration est utilisée, et placée dans /etc/sci/scisock_opt.conf.

#-key                        -type        -values
EnablePortsByDefault                  yes
EnablePort                  tcp           2200
DisablePort                 tcp           2201
EnablePortRange             tcp           2202 2219
DisablePortRange            tcp           2220 2231

Maintenant, nous sommes prêts à installer les pilotes. Nous devons installer d'abord les pilotes bas-niveau, puis les pilotes SCI sockets.

shell> cd DIS/sbin/
shell> ./drv-install add PSB66
shell> ./scisocket-install add

Si vous voulez, vous pouvez maintenant tester votre installation en appelant le script qui teste tous les nœuds SCI.

shell> cd /opt/DIS/sbin/
shell> ./status.sh

Si vous rencontrez une erreur et que vous devez changer les fichiers de configuration SCI, alors il faudra utiliser le programme ksocketconfig pour adapter les configurations.

shell> cd /opt/DIS/util
shell> ./ksocketconfig -f

Pour vérifier que les sockets SCI sont fonctionnels, vous pouvez utiliser le programme latency_bench qui a besoin d'un composant serveur et d'un client qui se connecte au serveur, pour tester les délais : l'activation de SCI est évidente en lisant les délais de latence. Avant d'utiliser ces programmes, vous devrez configurer la variable LD_PRELOAD telle que ci-dessous.

To set up a server use the command

shell> cd /opt/DIS/bin/socket
shell> ./latency_bench -server

Pour exécuter le client, utilisez cette commande :

shell> cd /opt/DIS/bin/socket
shell> ./latency_bench -client hostname_of_server

Maintenant, la configuration des sockets SCI est complète. Le cluster MySQL est prêt à s'exécuter avec les sockets SCI et le transporteur SCI, documenté dans Section 16.4.4.9, « Définition d'un transporteur SCI dans un cluster ».

La prochaine étape est de lancer le cluster MysQL. Pour activer l'utilisation des sockets SCI, il est nécessaire de configurer la variable d'environnement LD_PRELOAD avant de lancer ndbd, mysqld et ndb_mgmd. La variable LD_PRELOAD doit pointer sur la bibliothèque du noyau qui supporte les sockets SCI.

Voici un exemple pour lancer ndbd depuis un bash :

bash-shell> export LD_PRELOAD=/opt/DIS/lib/libkscisock.so
bash-shell> ndbd

Depuis un environnement tcsh, la même chose se fait avec les commandes suivantes.

tcsh-shell> setenv LD_PRELOAD=/opt/DIS/lib/libkscisock.so
tcsh-shell> ndbd

Notez bien que le cluster MySQL ne peut utiliser que les variantes du noyau des sockets SCI.

16-7-2 - Mesures de vitesses pour comprendre les impacts sur le cluster

Le processus ndbd dispose de nombreuses structures simples qui sont utilisées pour accéder aux données du cluster MySQL. Voici quelques indicateurs de performances pour mesurer les performances des commandes et les effets des interconnexions sur les performances.

Il existe 4 méthodes d'accès :

- Accès par clé primaire
C'est un accès simple à une ligne, via sa clé primaire. Dans le cas le plus simple, une seule ligne est lue en même temps. Cela signifie que le coût total des messages TCP/IP et des changements de contexte est pris en charge par cette seule opération. Dans un mode par lots, où les clés primaires sont distribuées par groupe de 32, chaque groupe va partager le coût des messages TCP/IP et les coûts de changement de contexte (si les messages sont destinés à différents nœuds, il faudra construire les messages nécessaires) ;

- Accès par clé unique
Les accès par clé unique sont très similaires aux accès par clé primaire, hormis le fait qu'ils sont exécutés sous forme de lecture de l'index, suivi par un accès de clé primaire. Cependant, une seule requête est envoyée par le serveur MySQL, et la lecture de l'index est gérée par le processus ndbd. Par conséquent, ces requêtes gagnent à être réalisées en groupe ;

- Analyse complète de table
Lorsqu'aucun index n'existe pour une table, cette dernière est entièrement analysée. C'est une seule requête qui est envoyée au processus ndbd, qui la divise en analyses parallèles dans les nœuds du cluster. Dans les futures versions du cluster, MySQL sera capable de filtrer un peu mieux ces analyses ;

- Analyse d'intervalle avec un index ordonné
Lorsqu'un index ordonné est utilisé, il va faire une analyse de la même manière qu'une analyse de table, mais il ne traitera que les lignes qui sont dans l'intervalle indiqué par la requête. Dans les futures versions, une optimisation spéciale aura lieu pour s'assurer que tous les attributs de l'index qui sont liés incluent les attributs de la clé, pour que seule une partie de l'index soit analysé, et non pas analysé en parallèle.

Pour vérifier les performances de base de ces méthodes d'accès, nous avons développé un jeu de tests. Un des tests, testReadPerf, effectue des accès via clé primaire, clé unique, en batch ou non. Les tests mesurent aussi le coût des analyses par intervalles, en effectuant des tests qui retournent une seule ligne, et finalement, des variantes qui utilisent des analyses d'intervalle pour lire des groupes de lignes.

Dans cette manière, il est possible de mesurer le coût d'un accès à une clé, et le coût de l'analyse d'une ligne, puis de mesurer l'impact des médias de communication.

Nous avons exécuté ces tests avec des sockets TCP/IP classiques et des sockets SCI. Les chiffres indiqués ci-dessous correspondent à des petits accès de 20 lignes par accès aux données. La différence entre les accès de série et par groupe diminue d'un facteur de 3-4 lorsque les lignes font 2 ko. Les sockets SCI ne sont pas testés pour les lignes de 2 ko. Les tests ont été effectués sur des clusters de 2 nœuds, avec des machines biprocesseurs, équipées de AMD 1900+.

type d'accès:         Sockets TCP/IP           Sockets SCI
Serial pk access:    400 microsecondes         160 microsecondes
Batched pk access:    28 microsecondes          22 microsecondes
Serial uk access:    500 microsecondes         250 microsecondes
Batched uk access:    70 microsecondes          36 microsecondes
Indexed eq-bound:   1250 microsecondes         750 microsecondes
Index range:          24 microsecondes          12 microsecondes

Nous avons aussi un autre jeu de tests pour comparer les performances des sockets SCI, en utilisant le transport SCI ou le transport TCP/IP. Ces tests utilisent des accès par clé primaire, en série, multithread ou multithread en groupe, simultanément.

Presque tous les tests ont montré que les sockets SCI sont 100 % plus rapides que les sockets TCP/IP. Le transporteur SCI était plus rapide dans la plupart des cas, comparés aux sockets SCI. Un cas notable : les multithreads ont montré que le transporteur SCI pouvait se comporter de très mauvaise manière, s'il est utilisé dans le processus mysqld.

Dans l'ensemble, notre conclusion est que pour les tests de performances, les sockets SCI ont amélioré la vitesse de 100 % par rapport aux sockets TCP/IP, sauf dans les rares cas où les performances ne sont pas un problème comme lors des analyses par filtres qui prennent beaucoup de temps, où lorsque de très grands groupes de clés primaires sont en jeu. Dans ce cas, le temps de calcul processeur de ndbd prend une forte part du temps de calcul.

Utiliser le transporteur SCI au lieu des sockets SCI ne sert vraiment qu'entre les processus ndbd. Utiliser le transporteur SCI ne sert que si un processeur peut être dédié à un processus ndbd, car le transporteur SCI s'assure que le processus ndbd ne reste pas inactif. Il est aussi important de s'assurer que le processus ndbd a une priorité suffisamment haute pour ne pas être rétrogradé s'il fonctionne durant un long moment (comme cela se fait en verrouillant les processus sur un processeur en Linux 2.6). Si c'est possible, alors le processus ndbd gagnera 10 à 70 % de performances, par rapport aux sockets SCI : les gains les plus importants interviennent lors des modifications, et probablement sur les analyses parallèles).

Il y a d'autres implémentations de sockets optimisées pour les clusters, indiquées dans différents articles. Elles incluent les sockets optimisées pour Myrinet, Gigabit Ethernet, Infiniband et interfaces VIA. Nous n'avons testé le cluster MySQL qu'avec les sockets SCI, et nous incluons aussi la documentation ci-dessus sur comment configurer les sockets SCI en utilisant une configuration TCP/IP ordinaire sur un cluster MySQL.

16-8 - Limitations du cluster dans MySQL 4.1

Cette section est consacrée à la liste des limitations identifiées sur la version du cluster mysql sortie en version 4.1.x, en comparaison avec les fonctionnalités connues lors de l'utilisation des moteurs de stockage MyISAM et InnoDB. À l'heure actuelle, il n'est pas prévu de remédier à ces limitations dans les futures sorties de 4.1. ; cependant nous tenterons de les traiter à travers des correctifs pour ces limitations implémentées dans MySQL 5.0 et ses prochaines versions. Si vous consultez la catégorie Cluster sur la base de données des erreurs MySQL http://bugs.mysql.com, vous trouverez la liste des erreurs connues que nous prévoyons de corriger dans les prochaines versions de MySQL 4.1 (si celles-ci sont marquées en 4.1).

- Non-conformité de syntaxe (en découlent des erreurs lorsque les applications existantes sont en cours de fonctionnement) :

- les séries de caractères et les modes de collations ne sont pas tous pris en charge ; voir Section C.10.6, « MySQL Cluster-4.1.6, 10 octobre 2004 » pour une liste de celles qui le sont ;

- pas de préfixe d'index ; seuls les champs entiers peuvent être indexés ;

- les index de texte ne sont pas pris en charge ;

- les types de données « Géométrie » (WKT et WKB) ne sont pas pris en charge.

- Non-conformité sur les limites / le comportement (peut mener à des erreurs lorsque les applications existantes sont en cours de fonctionnement) :

- pas de retour en arrière partiel sur les transactions. Une clé en doublon ou une erreur similaire va amener à un retour en arrière complet de la transaction ;

- un certain nombre de limites liées au disque existent, qui peuvent être configurées, mais la mémoire principale disponible dans le cluster définit la limite. Voir la liste complète des paramètres de configuration dans la Section 16.4.4, « Fichier de configuration ». La plupart des paramètres de configuration peuvent être améliorés en ligne. Ces limites disque incluent :

- taille mémoire de la base de données et taille mémoire de l'index (respectivement DataMemory et IndexMemory),

- nombre maximal de transactions qui peuvent être réalisées est défini en utilisant le paramètre de configuration MaxNoOfConcurrentOperations. On remarquera qu'après le chargement de masse, TRUNCATE TABLE, et ALTER TABLE sont manipulés comme des cas particuliers qui opèrent sur de multiples transactions, et qu'ils ne sont donc pas sujets à cette limitation,

- limites relatives aux tables et index. Par exemple, le nombre maximal d'index ordonnés par table est déterminé par MaxNoOfOrderedIndexes ;

- noms de bases de données, noms de tableaux et noms d'attributs ne peuvent pas être aussi longs dans les tableaux NDB que pour d'autres gestionnaires de tableaux. Les noms d'attributs sont tronqués à 31 caractères, et s'ils ne sont pas uniques après troncature, amènent à des erreurs. Les noms de bases de données et les noms des tableaux peuvent présenter au maximum 122 caractères (c'est-à-dire, la longueur maximale pour un nom de cluster NDB est de 122 caractères, moins le nombre de caractères associé au nom de la base de données à laquelle il appartient) ;

- dans MySQL 4.1 et 5.0, toutes les lignes de tableaux du cluster sont de longueur fixe. Cela signifie (par exemple) que si une table a un ou plusieurs champs VARCHAR qui contiennent uniquement de relativement petites valeurs, plus de mémoire et d'espace disque seront nécessaires lors de l'utilisation du moteur de stockage NDB en comparaison avec le même tableau et les mêmes données stockées dans le moteur MyISAM. Nous travaillons aujourd'hui à certifier ce point dans MySQL 5.1 ;

- le nombre maximal d'objets de métadata est limité à 1600, en comptant les tableaux de bases de données, les index et les BLOB ;

- le nombre maximal d'attributs par tableau est limité à 128 ;

- la talle maximale de toute ligne est de 8 k, sans compter les données stockées dans les colonnes BLOB ;

- le nombre maximal d'attributs par clé est de 32.

- Fonctionnalités non prises en charge (n'amènent pas d'erreur, mais ne sont pas prises en charge et n'ont pas d'application) :

- la clé de construction étrangère est ignorée, tout comme dans les tableaux MyISAM ;

- les points de sauvegarde et de restauration sont ignorés, tout comme dans MyISAM.

- Questions de performance et liées à la limitation :

- le cache de requête est désactivé, puisqu'il n'est pas invalidé si une mise à jour a lieu sur un autre serveur MySQL ;

- questions de performance de requête liées à l'accès séquentiel du moteur de stockage NDB ; il est également plus cher de réaliser plusieurs lectures d'intervalles par cette méthode qu'avec par exemple MyISAM ou bien InnoDB ;

- la statistique de Records in range n'est pas prise en charge, ce qui résulte en des plans de requête non optimaux dans certains cas. Utiliser USE INDEX ou bien FORCE INDEXcomme solution de contournement ;

- les index uniques de restes crées avec USING HASH ne peuvent pas être utilisés pour accéder à une table si NULL est donné comme une partie de la clé.

- Fonctionnalités manquantes :

- le seul niveau d'isolation pris en charge est READ_COMMITTED (InnoDB prend en charge READ_COMMITTED, REPEATABLE_READ, et SERIALIZABLE). Voir Résolution d'erreur du cluster MySQL pour les informations sur comment ceci impacte sur les sauvegardes/restaurations de la base de données du cluster ;

- pas d'engagement solide sur le disque. Les engagements sont répliqués, mais il n'y a pas de garantie que les logs soient inscrits sur le disque à l'engagement.

- Problèmes associés aux serveurs MySQL multiples (sans rapport avec MyISAM ou InnoDB) :

- ALTER TABLE ne verrouille pas complètement lorsque plusieurs serveurs MySQL sont en fonctionnement (pas de verrou réparti sur les tableaux) ;

- la réplication MySQL ne fonctionnera pas correctement si les mises à jour sont réalisées sur de multiples serveurs MySQL. Cependant, si la base de données est partitionnée selon un schéma défini au niveau des applications et s'il n'y a pas de transaction qui se passe entre ces partitions, alors la réplication peut être rendue effective ;

- la découverte automatique de bases de données n'est pas prise en charge pour les serveurs MySQL multiples qui accèdent à un même cluster MySQL. Cependant, la découverte automatique de tableaux est prise en charge dans ces cas. Cela signifie qu'après qu'une base de données nommée db_name est créée ou importée en utilisant un serveur MySQL, vous devriez adresser une déclaration CREATE DATABASE db_name; sur chaque serveur MySQL additionnel qui accède à un même cluster MySQL. (Dans le cas du MySQL 5.0.2 vous devriez également utiliser un CREATE SCHEMA db_name;.) Ceci fait pour un serveur MySQL donné, ce serveur devrait être en mesure de détecter les tableaux de bases de données sans erreur.

- Sujets exclusivement en rapport avec le Cluster MySQL (non associé à MyISAM ou bien à InnoDB) :

- toutes les machines utilisées dans le cluster doivent avoir la même architecture ; c'est-à-dire, toutes les machines qui hébergent des nœuds doivent être soit en long-endian ou bien little-endian, et vous ne pouvez pas utiliser un mélange des deux types. Par exemple, on ne peut pas avoir un nœud de gestion qui opère sur un PPC et qui dirige un nœud de stockage qui fonctionne sur une machine x86. Cette restriction ne s'applique pas aux machines qui font simplement tourner mysql ou d'autres clients qui pourraient accéder aux nœuds du cluster SQL ;

- il n'est pas possible de faire des modifications de schéma en ligne telles que celles accomplies en utilisant ALTER TABLE ou bien CREATE INDEX. (Cependant on peut importer ou créer un tableau qui utilise un autre moteur de stockage, puis le convertir en NDB avec ALTER TABLE tbl_name ENGINE=NDBCLUSTER;.) ;

- ajout ou écrasement de nœuds n'est pas permis (le cluster doit être redémarré dans ces cas-là) ;

- lorsque l'on utilise de multiples serveurs de gestion, on doit donner des Id explicites aux nœuds dans des connectstrings puisque l'allocation automatique d'ID aux nœuds ne fonctionne pas simultanément sur de multiples serveurs de gestion ;

- lorsque l'on utilise de multiples serveurs de gestion, on doit être extrêmement attentif à utiliser la même configuration pour tous les serveurs de management. Le cluster n'effectuera pas de vérification particulière dans ce cas ;

- le nombre maximal de nœuds de stockage est de 48 ;

- le nombre total de nœuds dans un cluster MySQL est de 63 au maximum. Ce nombre inclut tous les serveurs MySQL (nœuds SQL), nœuds de stockage, et serveurs de gestion.

Cette liste se veut complète considérant les conditions présentées auparavant au début de la section. Vous pouvez rapporter tout écart rencontré sur la base de données des bogues MySQL http://bugs.mysql.com/. Si nous ne planifions pas de résoudre le problème dans MySQL 4.1, nous l'ajouterons à la liste ci-dessus.

16-9 - Cluster MySQL en 5.0 et 5.1

Dans cette section, nous allons présenter les modifications de l'implémentation du cluster MySQL dans la version MySQL 5.0 comparée à la version MySQL 4.1. Nous allons aussi discuter de notre plan de développement pour les futures améliorations du cluster MySQL telles que prévues actuellement pour MySQL 5.1.

Dans le passé, nous avons recommandé aux utilisateurs du cluster MySQL de ne pas utiliser la version 5.0, car le cluster MySQL dans les versions 5.0 n'était pas encore totalement testé. Depuis la version 5.0.3-beta, nous avons produit une version de MySQL 5.0 avec des fonctionnalités de cluster comparables à celles de MySQL 4.1. MySQL 4.1 est toujours recommandé en production, cependant, MySQL 5.0 est de bonne qualité, et nous vous encourageons à commencer les tests avec le Cluster et MySQL 5.0 si vous pensez que vous aurez à l'utiliser en production dans le courant de l'année 2005. Il y a relativement peu de modifications entre les implémentations du cluster NDB en MySQL 4.1 et 5.0, ce qui fait que la migration devrait être rapide et sans douleur.

Depuis MySQL 5.0.3-beta, presque toutes les nouvelles fonctionnalités développées pour le cluster MySQL sont maintenant prévues dans la version 5.1. Nous vous donnerons des indications sur les futures fonctionnalités plus loin dans cette section.

16-9-1 - Évolutions de MySQL Cluster en MySQL 5.0

MySQL 5.0.3 beta contient de nombreuses fonctionnalités :

- conditions de Push-Down : une requête telle que

SELECT * FROM t1 WHERE non_indexed_attribute = 1;

va utiliser un scan de table complet, et la condition sera évaluée dans chaque nœud du cluster. Par conséquent, il n'est pas nécessaire d'envoyer les lignes à travers le réseau pour qu'elles soient évaluées : on utilise le transport de fonctions, et non pas le transport de données. Pour ce type de requête, la vitesse d'exécution s'améliore d'un facteur de 5 à 10. Notez que ce type de fonctionnalité est actuellement désactivé par défaut, en attente de plus de tests, mais il devrait fonctionner dans la plupart des cas. Cette fonctionnalité peut être activée via la commande SET engine-condition-pushdown=On;.

Autrement, vous pouvez exécuter le serveur mysqld avec cette fonctionnalité active par défaut en lançant le logiciel avec l'option de démarrage --engine-condition-pushdown.

Vous pouvez utiliser EXPLAIN pour savoir si ces conditions sont remplies.

Un avantage majeur de cette modification est que les requêtes sont maintenant exécutées en parallèle. Cela signifie que les requêtes effectuées sur des colonnes non indexées s'exécutent 5 à 10 fois, multiplié par le nombre de nœuds de stockage, plus vite que précédemment, car plusieurs processeurs sont utilisés en parallèle ;

- économie de IndexMemory : en MySQL 5.0, chaque enregistrement consomme environ 25 octets en mémoire d'index, et chaque index unique utilise 25 octets par ligne en mémoire, en plus de la mémoire nécessaire au stockage dans une table séparée. Ceci est lié au fait qu'il n'y a pas de stockage de la clé primaire dans la mémoire de l'index ;

- activation du cache de requête pour MySQL Cluster : voyez Section 5.11, « Cache de requêtes MySQL » pour des informations sur la configuration et l'utilisation du cache de requête ;

- nouvelles optimisations : une optimisation qui mérite l'attention est que l'interface de lectures en groupe est maintenant utilisée dans certaines requêtes. Par exemple, observez la requête suivante :

SELECT * FROM t1 WHERE primary_key IN (1,2,3,4,5,6,7,8,9,10);

Cette requête sera exécutée 2 à 3 fois plus vite que dans les versions précédentes du MySQL Cluster, car les recherches d'index sont envoyées en groupe et non plus de manière unitaire.

16-9-2 - Plans de développement de MySQL 5.1 pour le cluster MySQL

Ce qui est présenté ici est basé sur les récents ajouts dans les sources de MySQL 5.1. Il faut noter que tous les développements de la version 5.1 sont sujets à changement sans préavis.

Il y a actuellement quatre fonctionnalités majeures en cours de développement pour MySQL 5.1 :

- intégration du cluster MySQL dans la réplication : cela permettra de faire des modifications de données depuis n'importe quel serveur MySQL dans le cluster, et de voir la réplication gérée par un autre serveur MySQL du cluster ;

- support des enregistrements sur disques : les enregistrements sur le disque seront supportés. Les fichiers indexés, y compris les clés primaires seront toujours stockés en mémoire, mais les autres champs seront sur le disque ;

- lignes à taille variable : Une colonne définie comme VARCHAR(255) occupe aujourd'hui 260 octets de stockage, indépendamment de la quantité de données réellement enregistrées. En MySQL 5.1, seule quantité utile de mémoire sera utilisée. Cela permettra de réduire considérablement les besoins en espace, par un facteur de 5 dans la plupart des cas ;

- partitionnement paramétrable : les utilisateurs seront capables de définir des partitions basées sur la clé primaire. Le serveur MySQL sera capable d'ignorer certaines partitions à partir des clauses WHERE. Le partitionnement basé sur KEY, HASH, RANGE et LIST sera possible, de même que le sous-partitionnement. Cette fonctionnalité sera aussi possible avec les autres gestionnaires.

16-10 - FAQ MySQL Cluster

- Quelle est la différence entre utiliser un cluster et utiliser une réplication ?
Dans l'installation d'un cluster, un serveur maitre mysql met à jour un ou plusieurs esclaves. Les transactions sont engagées en séquence, et une lente transaction peut amener l'esclave à trainer en suivant du maitre. Ceci signifie que si le maitre arrive en erreur, il est possible que l'esclave n'ait pas enregistré quelques-unes des dernières transactions. Si un engin de transaction sécurisée tel que InnoDB est utilisé, alors une transaction sera soit complète sur l'esclave ou bien n'aura pas lieu, mais la réplication ne garantit pas que toutes les données du maitre comme de l'esclave seront cohérentes (consistent) à chaque instant. Dans le cluster MySQL, tous les nœuds de stockage sont maintenus en synch, et une transaction engagée par n'importe lequel des nœuds de stockage engage par la suite tous les nœuds de stockage. Dans le cas d'un échec d'un nœud de stockage, les autres nœuds de stockage restants resteront dans un état cohérent.

- En résumé, alors que la réplication est asynchrone, MySQL Cluster est synchrone.

- Ai-je besoin d'implémenter un protocole réseau particulier pour activer les Cluster ? (Comment les ordinateurs communiquent-ils dans un cluster ?)
MySQL Cluster est destiné à être utilisé dans un environnement de large bande passante, avec des ordinateurs connectés via TCP/IP. Sa performance dépend directement de la vitesse de connexion entre le cluster d'ordinateurs. La connectivité minimum requise pour un cluster inclut un réseau passant par un Ethernet 100 mégabits ou son équivalent. Nous vous recommanderons d'utiliser un Ethernet gigabit tant que faire se peut.
Le plus rapide protocole SCI est également pris en charge, mais demande un (hardware) particulier. Voir MySQL Cluster Interconnects pour plus d'informations sur les SCI.

- De combien d'ordinateurs ai-je besoin pour démarrer un cluster, et pourquoi ?
Un minimum de trois ordinateurs est attendu pour faire tourner un cluster viable. Cependant, le minimum recommandé d'ordinateurs dans un cluster mysql est de quatre : deux d'entre eux pour respectivement héberger la gestion et les nœuds SQL, et deux ordinateurs pour servir de nœuds de stockage. L'intérêt d'avoir deux nœuds de stockage est de procurer la redondance ; le nœud de gestion doit tourner sur une machine séparée afin de garantir un arbitrage continu des services dans le cas où l'un des nœuds de stockage se met en échec.

- Que font les différents ordinateurs dans un cluster ?
Un cluster MySQL présente à la fois une organisation physique et une organisation logique, dans laquelle les ordinateurs sont les éléments physiques. Les éléments logiques ou fonctionnels d'un cluster sont référencés en tant que nœuds, et un ordinateur qui héberge un nœud de cluster est parfois référencé en tant qu'hôte de cluster. Idéalement, il devrait y avoir un nœud par hôte de cluster, bien qu'il soit possible de faire tourner de multiples nœuds sur un unique hôte. Il y a trois types de nœuds, chacun correspondant à un rôle spécifique au sein du cluster. Ce sont :

1. Nœud de Gestion (nœud MGM): Ce nœud procure les services de gestion pour l'ensemble du cluster, y compris le démarrage, la fermeture, les backups et la configuration de données pour les autres nœuds. Le nœud de gestion serveur est implémenté dans l'application ndb_mgmd, le nœud de gestion client utilisé pour contrôler le cluster MySQL à travers le nœud de MGM est le ndb_mgm ;

2. Nœud d'empilement (nœud de données) : empile et réplique les données. La fonctionnalité de nœud d'empilement est gérée par une instance process du nœud de stockage NDB ndbd ;

3. Nœud SQL : Il s'agit simplement d'une instance de MySQL Server (mysqld) qui a démarré avec l'option --ndb-cluster.

- Avec quel système d'exploitation puis-je utiliser le Cluster ?
En version 4.1.10, le cluster MySQL est officiellement pris en charge sous Linux, Mac OS X, et Solaris. Nous travaillons actuellement à l'ajout de support pour le Cluster sous d'autres plateformes, y compris sous Windows (le support Windows devrait être opérationnel pour MySQL 5.0), et notre objectif est finalement de rendre le cluster opérationnel sur toutes les plateformes pour lesquelles MySQL est lui-même pris en charge.
Il devrait être possible d'utiliser les process cluster sur d'autres systèmes d'exploitation (y compris Windows), mais pour ceux-ci, mis à part pour les trois précédemment cités, les process cluster doivent être considérés comme des logiciels « alpha » et pas comme outils de production en tant que tels.

- Quelle est la configuration matérielle nécessaire pour utiliser le Cluster MySQL ?
Le Cluster devrait être utilisable sur toute plateforme qui est en mesure de faire tourner les binaires actifs-NDB. Il est évident que les CPU les plus rapides et une grande capacité mémoire amélioreront la performance, et les CPU de 64 bits seront probablement plus efficaces que les processeurs 32 bits. Les machines utilisées pour les nœuds de stockage doivent posséder une quantité suffisante de mémoire afin de pouvoir effectuer tous les partages pour tous les nœuds de la base de données puissent tous avoir lieu (voir la question « Combien de RAM pour le Cluster ? » pour plus informations). Les nœuds peuvent communiquer via un réseau et un matériel TCP/IP standard. Pour la prise en charge de SCI, un matériel réseau dédié sera requis.

- Puisque le Cluster MySQL utilise le TCP/IP, est-ce que je peux le faire tourner en passant par Intenet, avec un ou plusieurs nœuds positionnés à l'extérieur ?
Il faut garder à l'esprit que la communication entre les nœuds d'un Cluster MySQL ne sont pas sécurisés ; ils ne sont ni encryptés ni protégés par une autre sorte de mécanisme. La configuration la plus sécurisée pour un Cluster est définie par un réseau privé protégé sous un pare-feu, sans accès direct de l'extérieur à aucune donnée du Cluster ni à l'un des nœuds de gestion.

- Il y a peu de chances dans tous les cas qu'un cluster fonctionne de façon fiable dans de telles conditions, étant donné que le cluster MySQL a été conçu et implémenté suivant l'hypothèse qu'il tournerait dans des conditions qui garantissent une connectivité à haut débit réservée à ses échanges, similaires à celles que l'on trouve dans les installations LAN à base de 100 Mbps ou bien en Ethernet gigabit. La performance de cluster n'a jamais été testée ni garantie en cas de connectivité inférieure à ces débits.

- Dois-je apprendre un nouveau langage de programmation ou de commande pour utiliser le Cluster ?
Non. Tandis que certaines commandes spécialisées sont utilisées pour gérer et configurer le cluster en lui-même, seules des requêtes et commandes MySQM standard sont requises pour :

- créer, modifier et tomber les tableaux ;

- insérer, mettre à jour et effacer les données des tableaux ;

- créer, changer et laisser tomber des index uniques et primaires ;

- configurer et gérer les nœuds MySQL (serveurs MySQL).

- Comment faire pour trouver la signification d'un message d'avertissement ou d'erreur lorsque j'utilise le Cluster ?
Il y a deux manières de procéder pour cela :

1. Au sein même du Moniteur MySQL, utiliser la fonctionnalité AFFICHER ERREUR ou respectivement AFFICHER AVERTISSEMENT immédiatement après la notification d'erreur ou d'avertissement. Les messages peuvent également être affichés dans le navigateur de requêtes MySQL ;

2. À partir d'une fenêtre de commande, utiliser le code d'erreur perror --ndb error-code.

- Est-ce que le Cluster MySQL effectue des transactions sécurisées ? Quels types de tableaux le Cluster prend-il en charge ?
Oui. Le Cluster MySQL est mis en place pour des tableaux créés avec le moteur de stockage NDB, qui prend en charge les transactions. NDB est le seul moteur de stockage NDB qui prend en charge les structures de cluster.

- Que signifie le terme « NDB » ?
Cela signifie « Base de données Réseau », en anglais « Network Database ».

- Quelle(s) version(s) du logiciel MySQL prend en charge le Cluster ? Dois-je le compiler à la source ?
Le Cluster est pris en charge dans les binaires MySQL-max à partir de la version 4.1.3. À vous de déterminer si votre serveur binaire prend en charge le NDB grâce aux commandes SHOW VARIABLES LIKE 'have_%'; ou bien SHOW ENGINES;. (Voir Section 5.1.2, « mysqld-max, la version étendue du serveur mysqld » pour un complément d'information.)
Pour les utilisateurs sous Linux, veuillez considérer que le NDB n'est pas inclus dans les RPM ; il est recommandé en revanche d'utiliser les binaires fournis en tant qu'archives .tar.gz dans la zone de téléchargement MySQL Downloads area . Vous pouvez également obtenir la prise en charge de NDB en compilant les binaires -max à partir de la source, mais ce n'est pas nécessaire pour simplement utiliser le Cluster MySQL.

- Quelle est la quantité de RAM nécessaire ? Est-il éventuellement envisageable d'avoir recours à la mémoire disque ?
À l'heure actuelle, le Cluster est uniquement en mémoire. Cela signifie que toutes les données des tableaux (index inclus) sont stockés dans la RAM. Par conséquent ; si vos données occupent jusqu'à 1 gigabyte d'espace et que vous voulez les répliquer une fois dans le cluster, vous aurez besoin de 2 gigabytes de mémoire pour que ce soit faisable. Ceci s'ajoute à la mémoire requise par le système exploitation et celle occupée par toutes les applications qui fonctionnent sur les ordinateurs du cluster.
Vous pouvez utiliser la formule suivante pour obtenir une estimation approchée de la quantité de RAM requise pour chaque nœud de stockage dans le cluster :

(SizeofDatabase * NumberOfReplicas * 1.1 ) / NumberOfStorageNodes

Pour calculer plus précisément la mémoire nécessaire, on aura besoin de déterminer, pour chaque tableau de la base de données du cluster, l'espace de stockage requis par ligne (voir Section 11.5, « Capacités des colonnes » pour une méthode détaillée), puis multiplier cette valeur par le nombre de lignes. Vous devez également vous rappeler de prendre en compte tous les index de colonnes selon :

- dans MySQL 4.1., chaque clé primaire ou index de règle créé pour un tableau de cluster NDB requiert 25 bytes de stockage par enregistrement, en plus de l'espace associé à la clé. Dans My SQL 5.0, cette quantité est réduite de 21 à 25 bytes par enregistrement. Ces index utilisent IndexMemory ;

- chaque index ordonné requiert 10 bytes de stockage par enregistrement, en utilisant DataMemory ;

- créer une clé primaire ou un index unique crée également un index ordonné, à moins que cet index soit créé avec USING HASH. En d'autres termes, s'il est créé sans USING HASH, une clé primaire ou un unique index sur un tableau de cluster occupera 35 bytes (en plus de la taille de la clé)par enregistrement pour MySQL 4.1, et 31-35 bytes par enregistrement pour MySQL 5.0.
On remarquera que créer des tableaux de Cluster MySQL avec USING HASH pour toutes les clés primaires et les index uniques va généralement amener à des mises à jour de tableaux pour fonctionner plus rapidement. Ceci résulte du fait que moins de mémoire est requise (puisqu'aucun index ordonné n'est créé) et que l'on a besoin de moins utiliser le CPU (puisque moins d'index sont à lire et probablement à mettre à jour).
Il est tout particulièrement important de garder à l'esprit que tous les tableaux de Cluster MySQL doivent avoir une clé primaire, et que le moteur de stockage NDB va créer une clé primaire automatiquement si aucune n'est explicitement spécifiée, sachant que cette clé est créée sans le USING HASH.
On voit souvent des questions d'utilisateurs qui rapportent que, lorsqu'ils essaient de remplir une base de données cluster, le processus de chargement se termine prématurément et qu'un message d'erreur semblable à celui ci-dessous s'affiche alors :

ERROR 1114: The table 'my_cluster_table' is full

Lorsque cela se produit, la source provient très probablement du fait que votre installation ne possède pas de suffisamment de mémoire RAM pour toutes les données des tableaux et tous les index, y compris la clé primaire requise par le NDB.

It is also worth noting that all storage nodes should have the same amount of RAM, as no storage node in a cluster can use more memory than the least amount available to any individual storage node. In other words, if there are three computers hosting Cluster storage nodes, with two of these having three gigabytes of RAM available to store Cluster data, and one having only one GB RAM, then each storage node can devote only one GB for Cluster.

- Dans un cas de défaillance catastrophique - disons par exemple, une coupure de courant dans la ville entière ET mon alimentation de secours ne fonctionne pas - est-ce que je perdrais mes données ?
Toutes les transactions engagées sont tracées. Par conséquent, bien qu'il soit envisageable qu'une partie des données soit perdue dans un cas de catastrophe, ce phénomène devrait tout de même être relativement réduit. Les risques de pertes de données peuvent être encore réduits par la minimisation du nombre d'opérations par transaction.

- Est-il possible d'utiliser des index FULLTEXT avec le Cluster?
L'indexation par FULLTEXT n'est pas actuellement (en MySQL 4.1.9) prise en charge par le moteur de stockage NDB. L'ajout de cette fonctionnalité est prévu pour les prochaines versions.

- Puis-je faire tourner plusieurs nœuds sur un même ordinateur ?
C'est en effet réalisable, mais pas recommandé. L'une des raisons majeures de travailler avec un cluster est de disposer d'une redondance ; et afin de profiter au mieux des apports de cette redondance, chaque nœud devrait être placé sur une machine séparée. Si l'on place plusieurs nœuds sur une même machine et que cette machine est défaillante, on perd tous les nœuds qu'elle contenait. Étant donné que le Cluser MYSQL peut fonctionner sur du matériel partagé, et chargé sur un système d'exploitation peu cher ou même gratuit, il est préférable pour des raisons d'économies d'acheter une ou deux machines de plus pour sauvegarder les données critiques de la mission. Il est également important de remarquer que la configuration système pour un hôte de cluster qui héberge un nœud de gestion est presque minimaliste ; cette tâche peut être réalisée avec un simple processeur Pentium à 200 MHz et suffisamment de RAM pour le système d'exploitation, en plus d'un simple surplus pour les process ndb_mgmd et ndb_mgm.

- Puis-je ajouter des nœuds à un cluster sans le redémarrer ?
Pas à l'heure actuelle. Un simple redémarrage suffit pour ajouter de nouveaux nœuds de gestion à un Cluster. Lorsqu'on ajoute des nœuds de stockage, le processus est plus complexe et nécessite les étapes suivantes :

- effectuer une sauvegarde complète de toutes les données du cluster ;

- fermeture totale du cluster et de tous les process de nœuds de cluster en cours ;

- redémarrer le cluster, en utilisant l'option de démarrage -initial ;

- restaurer toutes les données de cluster à partir de la sauvegarde.

Dans le futur, l'implémentation d'une capacité de reconfiguration « à chaud » du Cluster MySQL est prévue afin de minimiser, à défaut d'éliminer ces requis pour le redémarrage du Cluster lors de l'ajout de nouveaux nœuds.

- Quelles sont les limitations dont je devrais être informé dans le cadre de l'utilisation du Cluster ?
Les tableaux NDB de MySQL 4.1 sont soumis aux limitations suivantes :

- certains ensembles de caractères et de collations ne sont pas pris en charge. (Pour une liste complète de ceux qui sont pris en charge, voir Section C.10.6, « MySQL Cluster-4.1.6, 10 octobre 2004 ») ;

- les index et préfixes FULLTEXT ne sont pas pris en charge. Seules les colonnes complètes peuvent être indexées ;

- les données spatiales MySQL ne sont pas prises en charge (voir Chapitre 18, Données spatiales avec MySQL) ;

- seules les restaurations complètes sont prises en charge pour les transactions. Les restaurations partielles et restaurations à partir de points de sauvegarde ne sont pas prises en charge ;

- se nombre maximal d'attributs autorisés par tableau est de 128, et les noms d'attributs ne peuvent pas excéder la longueur de 31 caractères. Pour chaque tableau, la longueur maximale combinée des noms du tableau et de la base de données est de 122 caractères ;

- la taille maximale d'une ligne de tableau est de 8 kilobytes, sans compter les BLOB. Il n'y a pas de limite définie pour le nombre de lignes par tableau ; la taille limite du tableau dépend d'un certain nombre de paramètres, et en particulier la taille de la RAM disponible pour chaque nœud de données ;

- le moteur NDB ne prend pas en charge les contraintes de clés étrangères. De même qu'avec les tableaux MyISAM, ces clés sont ignorées ;

- le cache de requête n'est pas pris en charge.

Il est prévu de remédier à ces restrictions dans le MySQL 5.0. Pour un complément d'information sur les limitations actuelles, voir Section 16.8, « Cluster Limitations in MySQL 4.1 ».

- Comment puis-je importer une base de données MySQL existante dans un cluster ?
On peut importer des bases de données dans le Cluster MySQL à peu près de la même manière que l'on ferait pour une autre version de MySQL. En dehors des limitations mentionnées précédemment, la seule particularité est que tout tableau qui est destiné à être inclus dans le cluster doit utiliser le moteur de stockage NDB. Ceci signifie que les tableaux doivent être créés avec l'option ENGINE=NDB ou bien ENGINE=NDBCLUSTER.

- Comment les nœuds de cluster communiquent-ils entre eux ?
Les nœuds de cluster peuvent communiquer selon trois protocoles distincts: TCP/IP, SHM (mémoire partagée, « shared memory » en anglais), et SCI (Interface ajustable cohérente, ou bien « Scalable Coherent Interface » en anglais). Lorsqu'il est utilisable, le protocole SHM est utilisé par défaut entre les nœuds qui partagent le même hôte de cluster. Le SCI est un protocole à haut débit (1 gigabit par seconde et plus), et à grande capacité, largement utilisé dans la construction de systèmes à multiprocesseurs ajustables ; il requiert l'installation de matériel et de drivers adaptés. Voir la Section 16.7, « Utilisation d'interconnexions haute vitesse avec MySQL Cluster » pour en savoir plus sur l'utilisation du SCI comme support de transfert dans le Cluster MySQL.

- Qu'est-ce qu'un arbitre ?
Si un ou plusieurs nœuds d'un cluster se trouvent défaillants, il est possible que les nœuds du cluster n'étaient pas en mesure de se « voir » tous les uns les autres. En fait, il est possible que deux ensembles de nœuds s'isolent l'un de l'autre au sein de la partition réseau, un phénomène aussi connu sous le terme de scénario du « cerveau divisé ». Ce type de situation est indésirable parce que chaque ensemble de nœuds tente de se comporter comme s'il constituait le cluster en entier.
Lorsque les nœuds de cluster se séparent, on a deux options. Si plus de 50 % des nœuds restants continuent à communiquer entre eux, alors il s'agit d'une situation appelée parfois « règle du plus grand nombre », et cet ensemble de nœuds est considéré comme le nouveau cluster. L'arbitre entre en jeu lorsqu'il y a un nombre égal de nœuds de chaque côté : dans ce cas, l'ensemble de nœuds auquel l'arbitre est lié est considéré comme le cluster ; et les nœuds qui n'appartiennent pas à cet ensemble sont éteints par le système.
La situation précédente est parfois simplifiée ; une explication plus complète qui prend en compte les groupes de nœuds suit ci-dessous :
Lorsque tous les nœuds dans au moins un nœud de groupe sont actifs, la partition réseau n'est pas un problème, parce qu'une unique portion du cluster ne peut constituer un cluster fonctionnel. Le problème se pose lorsque dans les nœuds de groupe individuel, tous les nœuds ne sont pas actifs, et dans ce cas la partition réseau devient possible (scénario du « cerveau divisé »). Alors un arbitre est nécessaire. Tous les nœuds du cluster reconnaissent le même nœud comme arbitre, ce qui est normalement le serveur de gestion ; cependant il est possible de configurer n'importe lequel des serveurs MySQL du cluster pour agir en tant qu'arbitre au lieu de serveur. L'arbitre accepte le premier des ensembles de nœuds de cluster qui le contacte, et ordonne au restant des nœuds de s'éteindre. La sélection de l'arbitre est contrôlée par le paramètre de configuration ArbitrationRank pour le serveur MySQL et pour les nœuds de gestion du serveur. (Voir Section 16.4.4.4, « Définition du serveur de gestion du cluster » pour les détails complémentaires.) Il faut également remarquer que le rôle de l'arbitre n'est pas de liquider les nœuds ni d'imposer lui-même une demande forte sur l'hôte qui l'a désigné, et donc l'arbitre ne nécessite pas particulièrement un haut débit de communication ou de mémoire additionnelle spécialement dédiée à cette tâche.

- Quels sont les types de colonnes prises en charge par le Cluster MySQL ?
Le Cluster MySQL prend en charge tous les types de colles habituels de MySQL, à l'exception de celles mentionnées dans le Chapitre 18, Données spatiales avec MySQL. De plus, il y a quelques différences pour ce qui concerne les index en comparaison avec les tableaux NDB. Remarque : Dans MySQL 4.1 et 5.0, les tableaux de Cluster (c'est-à-dire, les tableaux créés avec ENGINE=NDBCLUSTER) ont uniquement des lignes de largeur fixe. Ceci signifie que (par exemple), chaque enregistrement qui contient une colonne VARCHAR(255) va demander 256 bytes de stockage pour cette colonne, indépendamment de la taille des données contenues dans la colonne. Il est prévu de traiter ce point dans le MySQL 5.1.
Voir Section 16.8, « Cluster Limitations in MySQL 4.1 » pour plus d'informations sur ces questions.

- Comment démarrer et arrêter le Cluster MySQL ?
Il est nécessaire de démarrer chaque nœud du cluster séparément, dans un ordre donné :

1. Démarrer le nœud de gestion avec la commande ndb_mgmd ;

2. Démarrer chaque nœud de stockage avec la commande ndbd ;

3. Démarrer chaque serveur MySQL (nœud SQL) avec mysqld_safe --user=mysql &.

Chacune de ces commandes doit être lancée à partir de la cellule sur la machine hôte du nœud concerné. On peut vérifier que le cluster est fonctionnel en démarrant la gestion client MGM ndb_mgm sur la machine du nœud de gestion MGM.

- Qu'arrive-t-il aux données du cluster lorsque le cluster est éteint ?
Les données contenues en mémoire par les nœuds de stockage du cluster sont écrites sur le disque, et seront rappelées en mémoire lorsque le cluster démarre la fois suivante.
Pour éteindre le cluster, entrer le code suivant dans une fenêtre de commande sur la machinque hôte pour le nœud de gestion :

shell> ndb_mgm -e shutdown

Cette action va amener le ndb_mgm, ndb_mgm, et tous les process ndbd à se fermer progressivement. Les serveurs MySQL qui fonctionnent en tant que nœuds de Cluster SQL peuvent être éteints avec la commande mysqladmin shutdown.

Pour plus d'informations, voir la Section 16.6.1, « Commandes du client de gestion du Cluster » et la Section 16.3.6, « Arrêt et redémarrage du cluster ».

- Est-ce utile d'avoir plus d'un nœud de gestion pour un cluster ?
Cela peut être un recours en tant que soutien en cas d'erreur. Un unique nœud de gestion MGM contrôle à lui seul le cluster à un moment donné du temps, mais il est possible de configurer un nœud de gestion comme source principale de commande, et un second ou plusieurs autres nœuds destinés à prendre le relais dans le cas où le nœud principal vient à l'erreur.

- Puis-je recourir à plusieurs types de matériel et de systèmes d'exploitation dans un Cluster ?
Oui, tant que toutes les machines et tous les systèmes d'exploitation sont du même type endian. Il est également possible d'utiliser plusieurs types de versions de cluster MySQL Cluster sur des nœuds distincts (par exemple, 4.1.8 sur certains nœuds et 4.1.9 sur d'autres). Cependant, cette configuration n'est recommandée que dans le cadre d'une mise à jour glissante.

- Puis-je utiliser deux nœuds de stockage sur un même hôte ? Et deux nœuds SQL ?
Oui, cette configuration est réalisable. Dans le cas de nombreux nœuds de stockage, chaque nœud doit utiliser un répertoire de données distinct. Si l'on veut utiliser plusieurs nœuds SQL sur une même machine, alors chaque cas de mysqld doit utiliser un port TCP/IP distinct.

- Puis-je nommer les hôtes dans le Cluster MySQL ?
Oui, il est envisageable d'utiliser des DNS et DHCP en tant qu'hôtes de cluster. Cependant, si votre application requiert une disponibilité « 24 heures sur 24 », il est recommandé d'utiliser des adresses IP fixes. Ceci vient du type de communication entre les hôtes de cluster pour lesquels il existe une dépendance à ces services ; cette architecture a tendance à créer des points de rupture additionnels dont on préfère se passer.

16-11 - MySQL Cluster Glossary

Les termes suivants sont utiles lorsqu'on veut comprendre le MySQL Cluster ou bien connaître le sens particulier des expressions qu'il utilise.

- Cluster : dans son sens générique, un cluster est un ensemble d'ordinateurs qui fonctionnent comme une même unité et qui travaillent ensemble pour réaliser une tâche unique. NDB Cluster est la machine d'empilement utilisée par MySQL pour implémenter le stockage des données, le renvoi des données, et la gestion distribuée entre plusieurs ordinateurs. MySQL Cluster fait référence à un groupe d'ordinateurs qui travaillent ensemble en utilisant la machine NDB en tant que support à une base de données distribuée MySQL dans une architecture de non-partage utilisant un empilement dans un empilement en mémoire.

- Fichiers de configuration : fichiers texte qui contiennent les directives et l'information en rapport avec le cluster, ses hôtes, et ses nœuds. Ceux-ci sont lus par les nœuds de gestion du cluster lorsque le cluster démarre. Voir Section 16.4.4, « Fichier de configuration » pour les détails.

- Sauvegarde : une copie complète de toutes les données du cluster, les transactions et les logs, sauvegardés sur le disque ou tout autre type de stockage à long terme.

- Restauration : retour du cluster dans un état précédent, stocké préalablement en sauvegarde.

- Point de contrôle : de manière générale, lorsque les données sont sauvegardées sur le disque, on dit qu'un point de contrôle a été atteint. Plus spécifiquement dans le cas du cluster, il s'agit d'un point dans le temps auquel tous les engagements de transactions sont stockés sur le disque. Dans le cas du moteur de stockage DB, deux sortes de points de contrôle travaillent simultanément pour assurer que la cohésion d'ensemble du cluster est maintenue :

- point de contrôle local (LCP): ce point de contrôle est spécifique à un nœud donné ; cependant les LCP sont mis en place pour tous les nœuds du cluster plus ou moins simultanément. Un LCP implique la sauvegarde de toutes les données d'un nœud sur le disque , et sera donc faite à des intervalles séparés de quelques minutes. La durée exacte de l'intervalle varie, et dépend de la quantité de données contenue dans le nœud, du niveau d'activité du cluster, et d'autres facteurs ;

- point de contrôle global (GCP): un point de contrôle global prend place à des intervalles de quelques secondes, lorsque les transactions pour tous les nœuds sont synchronisées et lorsque le redo-log est inscrit en mémoire.

- Hôte cluster : un ordinateur qui fait partie du cluster MySQL. Un cluster possède à la fois une structure physique et une structure logique. Physiquement, le cluster comporte un certain nombre d'ordinateurs, appelés hôtes de cluster (ou plus simplement hôtes). Voir aussi nœuds, groupes de nœuds.

- Nœud : ce terme fait référence à une unité logique ou fonctionnelle du cluster MySQL, parfois aussi appelé nœud de cluster. Dans le cadre d'un cluster MySQL, on utilise le terme nœud pour désigner un processus plutôt qu'un élément physique du cluster. Trois types de nœuds sont nécessaires pour mettre en place un MySQL Cluster fonctionnel :

- nœuds de Gestion (MGM) : gère les autres nœuds du cluster MySQL. Fournit les données de configuration aux autres nœuds ; démarre et ferme les nœuds ; organise le partitionnement du réseau ; crée des sauvegardes et des restaurations de données ; etc. ;

- nœuds MySQL (serveur MySQL) : cas de serveur MySQL utilisés en tant que face avant aux données conservées dans les nœuds de stockage du cluster. Les clients qui désirent stocker, récupérer, ou mettre à jour des données peuvent accéder aux nœuds d'un SQL de même qu'à tout autre Serveur MySQL, en employant les méthodes usuelles d'authentification et d'API ; la distribution sous-jacente des données entre les groupes de nœuds est transparente pour les utilisateurs et pour les applications. Les nœuds SQL accèdent aux bases de données du cluster dans leur ensemble sans faire de distinction sur la distribution de données entre les différents points de stockage ou entre les hôtes du cluster ;

- nœuds de données (ou encore nœuds de stockage) : ces nœuds stockent les données de travail. Les fragments de tableaux de données sont stockés dans un ensemble de groupes de nœuds ; chaque groupe de nœuds contient une des sous-parties du tableau de données. Chacun des nœuds qui forment un groupe de nœuds emmagasine une réplique du fragment dont il est en charge. À l'heure actuelle, un seul cluster peut prendre en charge un total de plus de 48 nœuds.

Il peut arriver que plusieurs nœuds coexistent sur une même machine. (En fait, il est même possible d'installer un cluster complet sur une seule machine, bien que ce ne soit pas désirable dans un environnement de production.) Il peut être utile de se rappeler que, lorsqu'on travaille avec un cluster MySQL, le terme d'hôte fait référence à un composant physique du cluster tandis que le terme nœud désigne un composant logique ou fonctionnel (c'est-à-dire, un processus).
Remarque concernant les termes obsolètes : dans les anciennes versions de la documentation du cluster MySQL, les nœuds de données étaient parfois désignés comme des « nœuds de la base de données », ou bien « nœuds de DB ». De plus, les nœuds SQL étaient parfois définis comme des « nœuds clients » ou bien « nœuds d'API ». Cette ancienne terminologie a été abandonnée pour des raisons de clarté, et il est donc conseillé d'éviter de l'utiliser.

- Nœud de groupe : ensemble de nœuds de données. Tous les nœuds de données d'un même nœud de groupe contiennent les mêmes données (fragments), et tous les nœuds dans un même groupe devraient se situer sur des hôtes distincts. Il est possible de contrôler l'appartenance des nœuds de données à un nœud de groupe particulier.

- Échec de nœud : le cluster mysql n'est pas uniquement dépendant du fonctionnement d'un unique nœud le composant ; le cluster peut continuer à tourner si l'un ou plusieurs de ses nœuds entrent en échec. Le nombre précis d'échecs de nœuds tolérables pour le cluster dépend du nombre de nœuds qu'il contient ainsi que de la configuration du cluster.

- Redémarrage de nœud : procédure de redémarrage d'un nœud de cluster.

- Redémarrage de nœud initial : procédure de démarrage d'un nœud de cluster en retirant son filesystem. Parfois utilisé au cours d'une mise à jour logicielle et dans d'autres circonstances particulières.

- Crash Système (ou bien Échec Système) : arrive lorsqu'une trop grande quantité de nœuds de cluster sont en échec et que l'état du cluster ne peut plus être considéré comme fonctionnel.

- Redémarrage système : procédure de redémarrage du cluster et de réinitialisation de son état sur la base de log disque ou de points de contrôle. Nécessaire après une fermeture planifiée ou pas du cluster.

- Fragment : partie d'un tableau de base de données ; dans le moteur de stockage NDB, un tableau est ainsi découpé et stocké en un certain nombre de fragments. Un fragment est aussi parfois appelé une partition. Cependant on préférera le terme de « fragment ». Les tableaux sont fragmentés dans un cluster mysql de façon à faciliter la répartition du poids des données entre les machines et les nœuds.

- Réplique : sous le moteur de stockage NDB, chaque fragment de tableau possède un certain nombre de répliques réparties sur des nœuds de stockage distincts afin de produire la redondance. Aujourd'hui, chaque fragment est de capacité de contenir au maximum 4 répliques.

- Transporteur : protocole qui assure le transfert de données entre les nœuds. À l'heure actuelle, le cluster mysql gère quatre types distincts de connexions par transporteur : TCP/IP (en local), TCP/IP (à distance), SCI et SHM (encore en test dans Mysql 4.1.) :

- TTCP/IP est bien sûr le protocole réseau bien connu qui transmet les HTTP, FTP, etc., sur l'Internet ;

- SCI (« Scalable Coherent Interface », ou Interface Cohérente Evolutive) est un protocole de haut débit utilisé pour construire des systèmes de multiprocesseurs et les applications de process parallèles. L'utilisation d'un SCI avec le cluster mysql demande un matériel spécialisé et est détaillé dans la Section 16.7.1, « Configurer le cluster MySQL avec les sockets SCI ». Pour des notions de base en utilisation du SCI, voir l'essai sur dolphinics.cominics.cominics.com ;

- SHM traduit la fragmentation des segments de la mémoire en écriture Unix (« shared memory segments »). Lorsqu'on peut l'appliquer, SHM est utilisé automatiquement pour connecter les nœuds hébergés sur un même hôte. Cette fonctionnalité est encore en test sur MySQL 4.1, mais une implémentation complète est planifiée en MySQL 5.0. La page Unix pour shmop(2) est un bon début pour des informations complémentaires à ce sujet.

Nœud : le transporteur de cluster est à l'intérieur du cluster. Les applications qui utilisent le cluster mysql communiquent avec les nœuds sql de la même façon qu'elles le feraient avec d'autres versions du serveur mysql (via un TCP/IP ou un canal de noms windows/prises unix). Les requêtes peuvent être envoyées et les résultats récupérés en utilisant les API standards.

- NDB (Base de données réseau ou « Network Database ») : référence au moteur de stockage utilisé pour activer le cluster mysql. Le stockage NDB travaille avec tous les types usuels de colonnes mysql, les déclarations mysql et se conforme à l'ACID. Ce moteur fournit également le support pour les transactions (engagements et retour en arrière).

- Architecture de non-partage : architecture idéale pour un cluster mysql. Dans une installation réellement sans partage, chaque nœud fonctionne sur un hôte distinct. L'avantage d'une telle organisation est qu'un unique hôte ou nœud qui se trouve en échec n'amène pas à un point de défaillance unique ni à une perte de performance pour l'ensemble du système.

- Stockage en mémoire interne : toutes les données stockées dans un nœud donné sont gardées en mémoire sur l'ordinateur qui héberge le nœud. Pour chaque nœud de données dans le cluster, vous devez posséder une quantité de RAM disponible égale à celle de la base de données multipliée par le nombre de répliques et divisée par le nombre de nœuds de données. Par exemple, si une base de données occupe un espace mémoire de 1 gigabyte, et que vous voulez installer le cluster avec 4 répliques et 8 nœuds de données, un minimum de 500 MB de mémoire par nœud sera nécessaire. On remarquera que cette contrainte s'ajoute à toutes celles précédemment définies pour la configuration système, en plus des applications en cours de fonctionnement sur l'hôte des nœuds.

- Tableau : ainsi qu'attendu dans les contextes d'une base de données relationnelle, le terme de « tableau » fait référence à un ensemble ordonné d'enregistrements structurés à l'identique. Dans le Cluster MySQL, un tableau de base de données est stocké dans un nœud de données en tant qu'ensemble de fragments, dont chacun est répliqué sur des nœuds de données additionnels. L'ensemble des nœuds de données qui répliquent le même fragment ou bien ensemble de fragments est nommé nœud de groupe.

- Programmes de Clusters : il s'agit de programmes de lignes de commande utilisés dans le fonctionnement, la configuration et l'administration du Cluster MySQL. Ils incluent les deux daemons serveurs :

- ndbd: le nœud de données daemon (fait tourner les process de nœuds de données) ;

- ndb_mgmd: serveur de gestion daemon (fait tourner les process de gestion de serveur).

Et les programmes clients :

- ndb_mgm: la gestion de client (amène une interface pour exécuter les commandes de gestion) ;

- ndb_waiter: utilisé pour vérifier les statuts de tous les nœuds d'un cluster ;

- ndb_restore: restore les données de cluster à partir d'un backup.

Pour en savoir plus sur ces programmes et leurs utilisations, voir la Section 16.5, « Serveur de gestion du cluster MySQL ».

- Rapport d'événement : le Cluster MySQL reporte les événements par catégorie (démarrage, fermeture, erreurs, points de vérification, etc. ), par priorité et par criticité. Une liste complète de l'ensemble des événements reportés est disponible dans la Section 16.6.2, « Rapport d'événements générés par le cluster MySQL ». Les rapports d'événements sont de deux types :

- rapport de Cluster : garde un enregistrement d'ensemble de tous les événements intéressants à reporter pour le Cluster ;

- rapport de nœud : un rapport individuel est également enregistré pour chaque nœud.

Dans des circonstances normales, il est nécessaire et suffisant de garder et d'examiner uniquement le rapport de cluster. Le rapport de nœuds est à consulter uniquement pour les développements d'applications et pour le débogage.

17 - Introduction à MaxDB

MaxDB est une base de données au niveau de l'entreprise. MaxDB est le nouveau nom d'un système de gestion de bases de données, anciennement appelé SAP DB.

17-1 - Historique de MaxDB

L'histoire de SAP DB commence au début des années 1980 lorsqu'il était développé en tant que produit commercial (Adabas). La base de données a changé de nom plusieurs fois durant sa vie. Lorsque SAP AG, une société allemande de Walldorf, a pris en main le développement de ce système de base de données, il portait le nom SAP DB.

SAP a développé ce système de base de données pour servir de système de stockage pour toutes les applications SAP lourdes, à savoir SAP R/3. SAP DB avait pour objectif de fournir une autre solution aux systèmes de base de données d'éditeurs tiers comme Oracle, Microsoft SQL Server, ou DB2 d'IBM. En octobre 2000, SAP a publié SAP DB sous licence GNU GPL (voir Annexe G, Licence Publique Générale GNU), et en a fait ainsi un logiciel Open Source. En octobre 2003, plus de 2 000 clients l'utilisaient comme système de base de données séparé, en dehors de leur base de données principale, faisant partie de la solution APO/LiveCache.

En mai 2003, un partenariat technologique a été conclu entre MySQL AB et SAP AG. Ce partenariat autorise MySQL AB à développer davantage SAP DB, à changer son nom et à vendre des licences commerciales de SAP DB aux clients qui ne veulent pas être limités par les restrictions découlant de la licence GNU GPL (voir Annexe G, Licence Publique Générale GNU). En août 2003, MySQL AB a rebaptisé SAP DB : MaxDB.

17-2 - Licence et support MaxDB

MaxDB peut être utilisé sous les mêmes licences que celles qui sont disponibles pour les autres produits distribués par MySQL AB. Par conséquent, MaxDB est disponible sous licence GNU General Public, et sous licence commerciale. Pour plus d'informations sur les licences, voyez http://www.mysql.com/company/legal/licensing/.

MySQL fournira un support sur MaxDB à ceux qui ne sont pas clients de SAP.

La première version sous bannière MySQL AB est MaxDB 7.5.00 qui sortira à la fin 2003.

17-3 - Liens traitant de MaxDB

Le site officiel où trouver des informations sur MaxDB est http://www.mysql.com/maxdb. À terme, toutes les informations disponibles sur http://www.sapdb.org y seront placées.

17-4 - Concepts de base de MaxDB

MaxDB agit en mode client/serveur. Il a été développé pour répondre aux exigences d'installations répondant à un grand nombre de transactions en ligne. Il supporte à la fois la sauvegarde en ligne et l'extension de base de données. Microsoft Clustered Server est supporté directement pour les implémentations à serveurs multiples ; les autres solutions de cluster doivent être programmées manuellement. Les outils d'administration de base de données sont fournis à la fois en version native Windows et en version navigateur web.

17-5 - Différences de fonctionnalités entre MaxDB et MySQL

La liste suivante est un court résumé des principales différences entre MaxDB et MySQL. Elle n'est pas complète.

- MaxDB fonctionne comme un système client/serveur. MySQL peut fonctionner comme un système client/serveur ou comme un système intégré.

- Il est possible que MaxDB ne fonctionne pas sur toutes les plates-formes supportées par MySQL. Par exemple, MaxDB ne fonctionne pas sur OS/2 d'IBM.

- MaxDB utilise un protocole réseau propriétaire pour la communication client/serveur alors que MySQL utilise soit TCP/IP (avec ou sans chiffrage SSL), soit des interfaces de connexion, ou des canaux de communication nommés (sous les systèmes de la famille Windows NT).

- MaxDB supporte les procédures stockées. Avec MySQL, les procédures stockées sont implémentées en version 5.0. Max DB supporte aussi les triggers par une extension SQL qui est prévue pour MySQL 5.1. MaxDB contient un débogueur pour les langages de procédures stockées, peut déclencher sous-programmes imbriqués en cascade, et supporte les triggers multiples sur action et par ligne.

- MaxDB est livré avec des interfaces utilisateur en mode texte ou graphique, ou encore sur le web. MySQL est livré avec des interfaces utilisateur en mode texte uniquement ; une interface utilisateur graphique (MySQL Control Center) est distribuée séparément. Les interfaces utilisateur sur le web pour MySQL sont offertes par des éditeurs tiers.

- MaxDB supporte un certain nombre d'interfaces de programmation qui sont aussi supportées par MySQL. Toutefois, MaxDB ne supporte ni RDO, ni ADO, ni .NET qui sont toutes supportées par MySQL. MaxDB peut uniquement être intégré dans des applications C/C++.

- MaxDB contient des fonctionnalités administratives que MySQL n'a pas : la planification de tâches, les événements et alertes, et l'envoi de messages à une base de données administrateur sur signal d'alerte.

17-6 - Interopérabilité entre MaxDB et MySQL

Les fonctionnalités suivantes seront incluses dans les versions MaxDB qui doivent sortir peu après la première version 7.5.00. Ces fonctionnalités assureront l'interopérabilité entre MaxDB et MySQL.

- Il y aura un proxy MySQL qui permettra de se connecter à MaxDB en utilisant le protocole MySQL. Cela rend possible l'utilisation de programmes clients MySQL avec MaxDB, comme le client en ligne de commande mysql, l'utilitaire d'exportation ou le programme d'import mysqlimport. En utilisant mysqldump, on peut facilement exporter des données d'une base de données vers un autre système de base de données.

- La réplication entre MySQL et MaxDB sera supportée dans les deux sens. C'est-à-dire que MySQL ou MaxDB pourra être utilisé comme serveur maître de réplication. Le but à long terme est de faire converger et d'étendre la syntaxe de réplication de façon à ce que les deux systèmes de base de données utilisent la même syntaxe.

Voir Section 6.1, « Introduction à la réplication ».

17-7 - Mots réservés de MaxDB

Comme MySQL, MaxDB a un certain nombre de mots réservés qui ont une signification particulière. Normalement, ils ne peuvent pas être utilisés comme noms d'identifiants, comme les noms de tables ou de bases de données. Le tableau suivant liste les mots réservés dans MaxDB, et indique le contexte dans lequel ces mots sont utilisés. Il indique aussi s'ils ont une équivalence en MySQL ou non. Si une telle équivalence existe, la signification avec MySQL peut être identique ou différente par certains aspects. L'objectif principal est de montrer dans quelle mesure MaxDB diffère de MySQL ; par conséquent cette liste n'est pas complète.

Pour la liste de mots réservés dans MySQL, consultez Section 9.6, « Cas des mots réservés MySQL ».

Réservé par MaxDB

Contexte d'utilisation dans MaxDB

équivalent MySQL

@

Peut être préfixe à un identifiant, comme « @table »

Non autorisé

ADDDATE()

fonction SQL

ADDDATE() ; nouveau en MySQL version 4.1.1

ADDTIME()

fonction SQL

ADDTIME() ; nouveau en MySQL version 4.1.1

ALPHA

fonction SQL

Rien de comparable

ARRAY

Type de données

Non implémenté

ASCII()

fonction SQL

ASCII(), mais implémenté avec une signification différente

AUTOCOMMIT

Transactions ; ON par défaut

Transactions ; OFF par défaut

BOOLEAN

types colonne ; BOOLEAN n'accepte comme valeur que TRUE, FALSE, et NULL

BOOLEAN a été ajouté en MySQL version 4.1.0 ; c'est un synonyme de BOOL qui équivaut à TINYINT(1). Il accepte les valeurs entières dans la même plage que TINYINT ainsi que la valeur NULL. TRUE et FALSE peuvent être utilisés comme alias de 1 et 0.

CHECK

CHECK TABLE

CHECK TABLE ; similaire, mais utilisation différente

COLUMN

type colonne

COLUMN ; mot parasite

CHAR()

fonction SQL

CHAR() ; syntaxe identique ; similaire, utilisation différente

COMMIT

Des validations implicites de transactions se produisent quand les requêtes de définition de données sont publiées

Des validations implicites de transactions se produisent quand les requêtes de définition de données sont publiées, mais aussi avec d'autres commandes.

COSH()

fonction SQL

Rien de comparable

COT()

fonction SQL

COT() ; syntaxe et implémentation identiques

CREATE

SQL, langage de définition des données

CREATE

DATABASE

fonction SQL

DATABASE() ; DATABASE est utilisé dans un contexte différent, par exemple CREATE DATABASE

DATE()

fonction SQL

CURRENT_DATE

DATEDIFF()

fonction SQL

DATEDIFF() ; nouveau en MySQL version 4.1.1

DAY()

fonction SQL

rien de comparable

DAYOFWEEK()

fonction SQL

DAYOFWEEK() ; le premier jour (1) par défaut est lundi avec MaxDB, et dimanche avec MySQL

DISTINCT

fonctions SQL AVG, MAX, MIN, SUM

DISTINCT ; mais utilisé dans un contexte différent : SELECT DISTINCT

DROP

alias de DROP INDEX

DROP INDEX ; similaire, mais utilisation différente

EBCDIC()

fonction SQL

Rien de comparable

EXPAND()

fonction SQL

Rien de comparable

EXPLAIN

optimisation

EXPLAIN ; similaire, mais utilisation différente

FIXED()

fonction SQL

rien de comparable

FLOAT()

fonction SQL

Rien de comparable

HEX()

fonction SQL

HEX() ; similaire, mais utilisation différente

INDEX()

fonction SQL

INSTR() ou LOCATE() ; similaire, mais syntaxe et signification différentes

INDEX

USE INDEX, IGNORE INDEX et des optimisations similaires sont utilisées juste après SELECT, comme SELECT ... USE INDEX

USE INDEX, IGNORE INDEX et des optimisations similaires sont utilisées dans la clause FROM d'une requête SELECT, comme dans SELECT ... FROM ... USE INDEX

INITCAP()

fonction SQL

Rien de comparable

LENGTH()

fonction SQL

LENGTH() ; syntaxe identique, mais implémentation légèrement différente

LFILL()

fonction SQL

Rien de comparable

LIKE

comparaisons

LIKE ; mais LIKE que MaxDB fournit se rapproche plutôt du REGEX de MySQL

LIKE caractères de rapprochement

MaxDB supporte « % », « _ », « contrôle+souligné », « contrôle+flèche vers le haut », « * », et « ? » comme caractères de remplacement dans une comparaison LIKE

MySQL supporte « % », et « _ » comme caractères de remplacement dans une comparaison LIKE

LPAD()

fonction SQL

LPAD() ; implémentation légèrement différente

LTRIM()

fonction SQL

LTRIM() ; implémentation légèrement différente

MAKEDATE()

fonction SQL

MAKEDATE() ; nouveau en MySQL version 4.1.1

MAKETIME()

fonction SQL

MAKETIME() ; nouveau en MySQL version 4.1.1

MAPCHAR()

fonction SQL

Rien de comparable

MICROSECOND()

fonction SQL

MICROSECOND() ; nouveau en MySQL version 4.1.1

NOROUND()

fonction SQL

Rien de comparable

NULL

types colonnes ; comparaisons

NULL ; MaxDB supporte les valeurs spéciales NULL qui sont renvoyées par des opérations arithmétiques lors de dépassement de capacité ou lors des divisions par zéro ; MySQL ne supporte pas de telles valeurs spéciales

PI

fonction SQL

PI() ; syntaxe et implémentation identiques, mais les parenthèses sont obligatoires

REF

type de données

Rien de comparable

RFILL()

fonction SQL

Rien de comparable

ROWNO

Prédicat dans la clause WHERE

Similaire à la clause LIMIT

RPAD()

fonction SQL

RPAD() ; implémentation légèrement différente

RTRIM()

fonction SQL

RTRIM() ; implémentation légèrement différente

SEQUENCE

CREATE SEQUENCE, DROP SEQUENCE

AUTO_INCREMENT ; concept similaire, mais implémentation différente

SINH()

fonction SQL

Rien de comparable

SOUNDS()

fonction SQL

SOUNDEX() ; syntaxe légèrement différente

STATISTICS

UPDATE STATISTICS

ANALYZE ; concept similaire, mais implémentation différente

SUBSTR()

fonction SQL

SUBSTRING() ; implémentation légèrement différente

SUBTIME()

fonction SQL

SUBTIME() ; nouveau en MySQL version 4.1.1

SYNONYM

langage de définition de données : CREATE [PUBLIC] SYNONYM, RENAME SYNONYM, DROP SYNONYM

Rien de comparable

TANH()

fonction SQL

Rien de comparable

TIME()

fonction SQL

CURRENT_TIME

TIMEDIFF()

fonction SQL

TIMEDIFF() ; nouveau en MySQL version 4.1.1

TIMESTAMP()

fonction SQL

TIMESTAMP() ; nouveau en MySQL version 4.1.1

TIMESTAMP() comme argument de DAYOFMONTH() et DAYOFYEAR()

fonction SQL

Rien de comparable

TIMEZONE()

fonction SQL

Rien de comparable

TRANSACTION()

Renvoie l'identité de la transaction en cours

Rien de comparable

TRANSLATE()

fonction SQL

REPLACE() ; syntaxe et implémentation identiques

TRIM()

fonction SQL

TRIM() ; implémentation légèrement différente

TRUNC()

fonction SQL

TRUNCATE() ; syntaxe et implémentation légèrement différentes

USE

mysql interface en ligne de commande

USE

USER

fonction SQL

USER() ; syntaxe identique, mais implémentation légèrement différente, et les parenthèses sont obligatoires

UTC_DIFF()

fonction SQL

UTC_DATE() ; fournit un moyen de calculer le résultat de UTC_DIFF()

VALUE()

fonction SQL, alias pour COALESCE()

COALESCE() ; syntaxe et implémentation identiques

VARIANCE()

fonction SQL

Rien de comparable

WEEKOFYEAR()

fonction SQL

WEEKOFYEAR() ; nouveau en MySQL version 4.1.1

18 - Données spatiales avec MySQL

MySQL 4.1 propose une extension de gestion des données spatiales, et des capacités de génération, stockage et analyse des données spatiales. Actuellement, ces fonctionnalités ne sont possibles qu'avec les tables MyISAM.

Ce chapitre couvre les sujets suivants :

- la base de l'extension de gestion des données spatiales est le modèle géométrique OpenGIS ;

- formats de données pour représenter les données spatiales ;

- comment manipuler les données spatiales avec MySQL ;

- indexer les données spatiales avec MySQL ;

- différences avec les spécifications OpenGIS.

18-A - Introduction à GIS

MySQL implémente l'extension spatiale en suivant les spécifications de l'Open GIS Consortium (OGC). C'est un consortium international de plus de 250 personnes, agences et universités qui participent au développement public des concepts de gestion des données spatiales. L'OGC dispose d'un site web http://www.opengis.org/.

En 1997, l'Open GIS Consortium a publié un document intitulé OpenGIS (R) Simple Features Specifications For SQL : ce document propose plusieurs concepts pour ajouter le support des données spatiales aux serveurs de base de données SQL. Ces spécifications sont disponibles sur le site de l'Open GIS à l'adresse http://www.opengis.org/techno/implementation.htm : elle contient encore d'autres informations connexes à ce chapitre.

MySQL implémente une sous-partie de l'environnement SQL avec des types géométriques, proposé par OGC. Ce terme fait référence à un environnement SQL, disposant d'un jeu de types géométriques. Une colonne SQL géométrique est une colonne avec un type de données géométrique. Ces spécifications décrivent l'ensemble des types géométriques, ainsi que des fonctions permettant leur création et leur analyse.

Un lieu géographique représente tout ce qui dispose d'une localisation dans le monde. Un lieu peut être :

- une entité. Par exemple, une montagne, un lac, une ville ;

- une région. Par exemple, les tropiques, une zone postale ;

- un endroit définissable. Par exemple, un carrefour, une place à la rencontre de deux rues.

Vous pouvez aussi rencontrer des documents qui utilisent le terme de lieu géospatial pour désigner les lieux géographiques.

Géométrie est un autre mot qui décrit un lieu géographique. Le sens original du mot géométrie se rapporte à une branche des mathématiques. Un autre sens se rapporte à la cartographie, désignant les lieux géométriques que les cartographes utilisent pour dessiner le monde.

Ce chapitre utilise tous ces termes de manière synonyme : lieu géographique, lieu géospatial, lieu, or géométrie. Le terme le plus couramment utilisé ici sera géométrie.

Nous définirons une géométrie comme un point ou un ensemble de points représentant un endroit dans le monde.

18-B - Le modèle géométrique OpenGIS

Le jeu de types géométriques proposé par OGC dans ses spécifications SQL with Geometry Types, est basé sur le modèle géométrique OpenGIS. Dans ce modèle, chaque objet géométrique dispose des propriétés générales suivantes :

- il est associé à un système de référence spatiales (Spatial Reference System), qui décrit l'origine des coordonnées de l'espace ;

- il appartient à une classe géométrique.

18-B-1 - La hiérarchie des classes géométriques

La hiérarchie des classes géométriques est définie comme ceci :

- Geometry (non instanciable) ;

- Point (instanciable) ;

- Curve (non instanciable) ;

- LineString (instanciable) ;

- Line ;

- LinearRing ;

- Surface (non instanciable) ;

- Polygon (instanciable) ;

- GeometryCollection (instanciable) ;

- MultiPoint (instanciable) ;

- MultiCurve (non instanciable) ;

- MultiLineString (instanciable) ;

- MultiSurface (non instanciable) ;

- MultiPolygon (instanciable).

Certaines classes sont abstraites et non instanciables. C'est-à-dire, il n'est pas possible de créer un objet de cette classe. Les autres classes sont instanciables, et on peut en créer des objets. Chaque classe a des propriétés, et les classes instanciables ont des assertions (des règles qui définissent des instances valides).

Geometry est la classe de base. C'est une classe abstraite. Les sous-classes instanciables de Geometry sont limitées à des objets de zéro, une ou deux dimensions, qui existent dans un espace bidimensionnel. Toutes les classes géométriques instanciables sont définies de façon à ce que les instances valides d'une classe géométrique soient topologiquement fermées (c'est-à-dire que l'objet géométrique inclut ses frontières).

La classe Geometry a les sous-classes de Point, Curve, Surface et GeometryCollection.

- Point représente un objet sans dimension.

- Curve représente un objet à une dimension, et a pour sous-classe LineString, avec les sous-classes Line et LinearRing.

- Surface représente les objets bidimensionnels, et a pour sous-classe Polygon.

- GeometryCollection dispose des classes de regroupement MultiPoint, MultiLineString et MultiPolygon, destinées aux groupes d'objets de zéro, une ou deux dimensions. Elle permet de modéliser les groupes de points Points, de lignes LineStrings et de polygones Polygons, respectivement. MultiCurve et MultiSurface sont présentées comme des super-classes abstraites, qui généralisent les interfaces de regroupements, pour gérer les courbes Curves et les surfaces Surfaces.

Geometry, Curve, Surface, MultiCurve, et MultiSurface sont définies comme non instanciables. Elles définissent un jeu de méthodes communes à leurs sous-classes, et sont incluses ici pour des raisons d'extensibilité.

Point, LineString, Polygon, GeometryCollection, MultiPoint, MultiLineString et MultiPolygon sont des classes instanciables.

18-B-2 - Classe Geometry

Geometry est la classe racine de la hiérarchie. C'est une classe non instanciable, mais elle dispose d'un grand nombre de propriétés qui sont communes à toutes les formes géométriques, dérivées de Geometry. Ces propriétés sont décrites dans la liste suivante. Les sous-classes ont leur propres propriétés spécifiques, définies ultérieurement.

propriétés de la classe Geometry

Un objet Geometry a les propriétés suivantes :

- son type. Chaque objet Geometry appartient à une des classes instanciables de la hiérarchie ;

- son SRID, ou identifiant de référence spatiale : Spatial Reference Identifier. Cette valeur spécifie le système de référence spatial (Spatial Reference System), qui décrit l'espace de coordonnées dans lequel l'objet est défini ;

- ses coordonnées coordinates dans le système de référence spatiale, représentées par des nombres à virgule flottante en double précision (8 octets). Tous les objets non vides contiennent au moins une paire de coordonnées (X,Y). Les formes géométriques vides ne contiennent pas de coordonnées.
Les coordonnées sont relatives au SRID. Par exemple, dans différents systèmes de coordonnées, la distance entre deux objets peut varier même si les objets ont les mêmes coordonnées, car les distances planes et les distances géocentriques (système de coordonnées à la surface de la Terre) suivent deux géométries différentes ;

- son intérieur interior, sa frontière boundary et son extérieur exterior.
Toutes les formes géométriques occupent une position dans l'espace. L'extérieur de la forme est l'espace qui n'est pas occupé par la forme. L'intérieur de la géométrie est l'espace occupé par la géométrie. La frontière est l'interface entre l'extérieur de la forme et son intérieur ;

- son MBR (Rectangle minimal d'enveloppe, Minimum Bounding Rectangle), appelé aussi enveloppe. C'est la forme géométrique la plus petite, formée par les coordonnées minimales et maximales (X,Y) :

((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

- l'attribut simple ou non simple. Les objets géométriques de certains types, comme LineString, MultiPoint, MultiLineString sont simples ou non simples. Chaque type dispose de ses propres assertions ;

- l'attribut fermé (closed) ou non fermé (not closedLineStringMultiString). Les objets géométriques de certains types, comme LineString, MultiString sont fermés ou non fermés. Chaque type dispose de ses propres assertions ;

- l'attribut vide (empty) ou non vide(not empty). Une forme est vide si elle ne contient aucun point. L'extérieur, l'intérieur et la frontière d'une forme vide ne sont pas définis (ils sont représentés par la valeur NULL). Une forme vide est toujours simple, et a une surface de 0 ;

- sa dimension. Une forme a une dimension de -1, 0, 1, ou 2 :

- -1 représente une forme vide,

- 0 représente les formes sans surface ni dimension,

- 1 représente les formes avec une dimension non nulle, mais sans surface,

- 2 représente les formes avec une dimension et une surface non nulles.

Les Points sont de dimension zéro. Les lignes LineString sont de dimension un. Les polygones Polygon sont de dimension deux. Les dimensions des objets MultiPoint, MultiLineString et MultiPolygon sont les mêmes que les dimensions des objets dont ils sont composés.

18-B-3 - Classe Point

Un Point est une forme géométrique qui représente un endroit dans un espace de coordonnées.

Exemples de Point

- Imaginez une carte à grande échelle, avec de nombreuses villes. Un point représentera une ville.

- Sur une carte de ville, un point peut représenter un arrêt de bus.

Propriété du Point

- Abscisse, ou coordonnées X.

- Ordonnée, ou coordonnée Y.

- Un point Point est défini comme une forme avec zéro dimension.

- Le rectangle d'encadrement d'un Point est un rectangle vide.

18-B-4 - Classe Curve

Une courbe Curve est une forme géométrique à une dimension, qui représente généralement une séquence de points. Une sous-classe particulière de Curve est l'interpolation entre deux points. Curve est une classe non instanciable.

Propriétés de la classe Curve

- Les coordonnées de ses points.

- Curve est définie comme une forme à une dimension.

- Un objet Curve est simple si elle ne passe pas par le même point deux fois.

- Un objet Curve est fermé si son point de départ est le même que son point d'arrivée.

- La frontière d'un objet Curve est vide.

- La frontière d'un objet Curve non fermé correspond à ses deux points terminaux.

- Un objet Curve qui est simple et fermé est un objet LinearRing.

18-B-5 - Classe LineString

Un objet LineString est un objet Curve avec une interpolation linéaire entre ses points.

Exemples de LineString

- Sur une carte du monde, un objet LineString peut représenter les rivières.

- Sur une carte de ville, un objet LineString peut représenter les rues.

Propriété des objets LineString

- Coordonnées des segments de LineString, définis par des paires de points consécutifs.

- Un objet LineString est un objet Line s'il est constitué de deux points.

- Un objet LineString est un objet LinearRing s'il est fermé et simple.

18-B-6 - Classe Surface

Un objet Surface est une forme géométrique à deux dimensions. C'est une classe non instanciable. Sa seule sous-classe instanciable est la classe Polygon.

Propriété de Surface

- Un objet Surface est défini comme une forme géométrique à deux dimensions.

- Les spécifications OpenGIS définissent un objet Surface comme une forme géométrique simple si elle est d'un seul tenant, qui est associé avec un seul extérieur, et aucune frontière intérieure.

- La frontière d'un objet Surface est l'ensemble des courbes fermées qui correspondent à ses frontières extérieures et intérieures.

18-B-7 - Classe Polygon

Un polygone Polygon est une surface Surface plane avec plusieurs côtés. Il est défini par une seule frontière extérieure, aucune ou plusieurs frontières intérieures. Chaque frontière intérieure définit un trou dans le polygone Polygon.

Exemple avec Polygon

- Sur une carte régionale, un objet Polygon peut représenter une forêt, un département, etc.

Assertions de Polygon

- La frontière d'un Polygon est constituée d'un ensemble d'objets LinearRing (c'est dire, des objets LineString qui sont simples et fermés), et qui forme sa frontière intérieure et extérieure.

- Deux frontières intérieures ne se coupent pas. Les courbes d'une frontière d'un objet Polygon peuvent se couper en un Point, mais uniquement en un point de tangence.

- Un polygone Polygon ne peut pas avoir de lignes coupées, d'extrusions ou de trous.

- L'intérieur de tous les Polygon est un ensemble de points connectés.

- L'extérieur d'un objet Polygon ayant un ou plusieurs trous n'est pas connecté. Chaque trou définit un composant connecté de l'extérieur.

Dans les assertions ci-dessus, les polygones sont des formes géométriques simples. Ces assertions font d'un objet Polygon une forme simple.

18-B-8 - Classe GeometryCollection

Un objet GeometryCollection est une forme géométrique, représentée par le regroupement d'autres formes géométriques.

Tous les éléments dans un objet GeometryCollection doivent être placés dans le même système de référence spatiale (c'est-à-dire dans le même système de coordonnées). GeometryCollection n'impose aucune autre contrainte à ses éléments, même si ses sous-classes décrites plus loin, en imposent d'autres. Les restrictions peuvent être basées sur :

- le type d'élément (par exemple, un objet MultiPoint ne peut contenir que des objets Point) ;

- dimension ;

- contraintes sur le degré de recouvrement entre deux éléments.

18-B-9 - Classe MultiPoint

Un objet MultiPoint est un regroupement d'objets de type Point. Les points ne sont pas connectés ou ordonnés de quelque manière que ce soit.

Exemples avec MultiPoint

- Sur une carte du monde, un objet Multipoint peut représenter un archipel.

- Sur une carte de ville, un objet Multipoint peut représenter les différentes succursales d'une entreprise.

Propriétés de MultiPoint

- Un objet MultiPoint est un objet sans dimension.

- Un objet MultiPoint est simple si tous les points Point sont tous distincts (les paires de coordonnées sont toutes distinctes).

- La frontière d'un objet MultiPoint est vide.

18-B-10 - Classe MultiCurve

Un objet MultiCurve est une forme géométrique composée d'objets Curve. MultiCurve est une classe non instanciable.

Propriété de MultiCurve

- Un objet MultiCurve est défini comme une forme géométrique à une dimension.

- Un objet MultiCurve est dit simple si et seulement si tous ses éléments sont simples, et que les seules intersections entre deux éléments interviennent sur les frontières des deux éléments.

- La frontière d'un objet MultiCurve est obtenue en appliquant la « règle de l'union modulo 2 » (dite aussi, règle pair/impair) : un point est une frontière d'un objet MultiCurve s'il fait partie d'un nombre impair de frontière d'élément de l'objet MultiCurve.

- Un objet MultiCurve est fermé si tous ses éléments sont fermés.

- La frontière d'un objet MultiCurve fermé est toujours vide.

18-B-11 - Classe MultiLineString

Un objet MultiLineString est une forme géométrique de classe MultiCurve, composée uniquement d'objets LineString.

Exemples avec MultiLineString

- Sur une carte régionale, un objet MultiLineString représente un système de rivières, ou une autoroute.

18-B-12 - Classe MultiSurface

Un objet MultiSurface est un groupe de surfaces. MultiSurface est une classe non instanciable. Sa seule sous-classe instanciable est la classe MultiPolygon.

Assertions MultiSurface

- Les intérieurs de deux surfaces d'un objet MultiSurface doivent avoir des intersections nulles.

- La frontière de deux éléments de l'objet MultiSurface doivent avoir en commun un nombre fini de points.

18-B-13 - Classe MultiPolygon

Un objet MultiPolygon est un objet MultiSurface composé d'objets Polygon.

Exemple avec MultiPolygon

- Sur une carte régionale, un objet MultiPolygon peut représenter un système de lacs.

Assertions MultiPolygon

- Les intérieurs de deux objets Polygon qui sont éléments d'un même objet MultiPolygon n'ont pas d'intersection.

- Les frontières de deux objets Polygon qui sont éléments d'un objet MultiPolygon ne peuvent que se toucher en un nombre fini de points, et non pas se recouvrir. Le recouvrement est déjà interdit par l'assertion précédente.

- Un objet MultiPolygon ne peut pas avoir de lignes coupées, d'extrusions ou de trous. Un objet MultiPolygon est un ensemble de points réguliers et fermés.

- L'intérieur d'un objet MultiPolygon composé de plus d'un objet Polygon n'est pas connecté. Le nombre de composants connectés de l'intérieur d'un objet MultiPolygon est égal au nombre d'objets Polygon dans l'objet MultiPolygon.

Propriétés MultiPolygon

- Un objet MultiPolygon est défini comme une forme géométrique à deux dimensions.

- La frontière d'un objet MultiPolygon est un ensemble de courbes fermées (des objets LineString) correspondants aux limites de ses objets Polygon composants.

- Chaque objet Curve de la frontière de l'objet MultiPolygon est dans la frontière d'un seul objet Polygon.

- Chaque objet Curve de la frontière d'un élément Polygon est dans la frontière de l'objet MultiPolygon.

18-C - Formats géométriques supportés

Cette section décrit les formats de données géométriques standards qui sont utilisés pour représenter des objets géométriques dans les requêtes. Il s'agit :

- du format Well-Known Text (WKT) ;

- du format Well-Known Binary (WKB).

En interne, MySQL stocke les valeurs géométriques dans un format indépendant des formats WKT et WKB.

18-C-1 - Format Well-Known Text (WKT)

La représentation Well-Known Text (WKT) est conçue pour faire des échanges au format ASCII.

Exemple de représentation d'objets WKT :

- un Point :

POINT(15 20)

Notez que les coordonnées du point n'ont pas de séparateur virgule.

- une ligne LineString de quatre points :

LINESTRING(0 0, 10 10, 20 25, 50 60)

- un polygone Polygon avec un anneau extérieur et un anneau intérieur :

POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))

- un groupe de points MultiPoint avec trois Point :

MULTIPOINT(0 0, 20 20, 60 60)

- un groupe de lignes MultiLineString avec deux lignes LineString :

MULTILINESTRING((10 10, 20 20), (15 15, 30 15))

- un groupe de polygones MultiPolygon avec deux polygones Polygon :

MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))

- un groupe géométrique GeometryCollection constitué de deux Point et d'une ligne LineString :

GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

Une grammaire Backus-Naur qui spécifie les règles de générations formelles pour écrire des valeurs WKT est disponible dans les spécifications OGC, qui sont référencées au début de ce chapitre.

18-C-2 - Le format Well-Known Binary (WKB)

La représentation Well-Known Binary (WKB) des valeurs géométriques est définie par les spécifications OpenGIS. Elle est aussi définie comme le standard ISO « SQL/MM Part 3: Spatial ».

WKB sert à échanger des données géométriques sous forme de flux binaires représentés par des BLOB contenant des données WKB.

WKB utilise des entiers non signés d'un octet, de quatre octets et des nombres à virgules flottantes de précision double (IEEE 754 format). Un octet fait 8 bits.

Par exemple, la valeur WKB qui correspond à POINT(1 1) est constituée de la séquence suivante de 21 octets, représentée ici en code hexadécimal :

0101000000000000000000F03F000000000000F03F

La séquence peut être décomposée comme suit :

Byte order : 01
WKB type   : 01000000
X          : 000000000000F03F
Y          : 000000000000F03F

Voici le détail des composants :

- l'ordre des octets peut être 0 ou 1, pour indiquer un stockage little-endian ou big-endian. Les ordres little-endian et big-endian sont aussi connus sous le nom de Network Data Representation (NDR) et External Data Representation (XDR), respectivement ;

le type WKB est un code qui indique le type géométrique. Les valeurs de 1 à 7 indiquent : Point, ligne LineString, polygone Polygon, plusieurs points MultiPoint, plusieurs lignes MultiLineString, plusieurs polygones MultiPolygon, et groupe géométrique GeometryCollection ;

- une valeur Point a des coordonnées X et Y, représentées par un nombre à virgule flottante, en double précision.

Les valeurs WKB des formes géométriques plus complexes sont représentées par des structures bien plus complexes, comme présenté dans les spécifications OpenGIS.

18-D - Créer une base de données avec les fonctionnalités géographiques

Cette section décrit les types de données que vous pouvez utiliser pour représenter des données géographiques dans MySQL, et les fonctions disponibles pour créer et lire les données spatiales.

18-D-1 - Types de données géographiques MySQL

MySQL fournit un jeu de types de données qui correspondent aux classes du modèle géométrique OpenGIS. Certains de ces types contiennent des valeurs géométriques simples :

- GEOMETRY ;

- POINT ;

- LINESTRING ;

- POLYGON.

GEOMETRY est le type le plus général. Il peut stocker une forme géométrique de n'importe quel type. Les autres types se restreignent à un type particulier de forme.

Les autres types de données permettent de gérer les groupes de formes géométriques :

- MULTIPOINT ;

- MULTILINESTRING ;

- MULTIPOLYGON ;

- GEOMETRYCOLLECTION.

GEOMETRYCOLLECTION peut stocker un groupe quelconque de formes géométriques. Les autres types se restreignent à des formes géométriques particulières.

18-D-2 - Créer des objets géographiques

Cette section décrit comment créer des valeurs en utilisant les fonctions Well-Known Text et Well-Known Binary qui sont définies dans le standard OpenGIS, et les fonctions spécifiques de MySQL.

18-D-2-a - Créer des objets géométriques avec les fonctions WKT

MySQL fournit de nombreuses fonctions qui prennent en argument un BLOB contenant la représentation au format Well-Known Text et optionnellement, un système de référence (SRID), et retourne la forme géométrique correspondante.

GeomFromText() accepte des données WKT de n'importe quel type de données géométriques comme premier argument. L'implémentation fournit aussi des fonctions de construction spécifiques à chaque forme géométrique.

- GeomFromText(wkt[,srid]), GeometryFromText(wkt[,srid])
Construit une forme géométrique à partir de sa représentation WKT et du SRID.

- PointFromText(wkt[,srid])
Construit un objet POINT à partir de sa représentation WKT et du SRID.

- LineFromText(wkt[,srid]), LineStringFromText(wkt[,srid])
Construit un objet LINESTRING à partir de sa représentation WKT et du SRID.

- PolyFromText(wkt[,srid]), PolygonFromText(wkt[,srid])
Construit un objet POLYGON à partir de sa représentation WKT et du SRID.

- MPointFromText(wkt[,srid]), MultiPointFromText(wkt[,srid])
Construit un objet MULTIPOINT à partir de sa représentation WKT et du SRID.

- MLineFromText(wkt[,srid]), MultiLineStringFromText(wkt[,srid])
Construit un objet MULTILINESTRING à partir de sa représentation WKT et du SRID.

- MPolyFromText(wkt[,srid]), MultiPolygonFromText(wkt[,srid])
Construit un objet MULTIPOLYGON à partir de sa représentation WKT et du SRID.

- GeomCollFromText(wkt[,srid]), GeometryCollectionFromText(wkt[,srid])
Construit un objet GEOMETRYCOLLECTION à partir de sa représentation WKT et du SRID.

Les spécifications OpenGIS décrivent aussi des fonctions optionnelles pour construire des Polygon et MultiPolygon basées sur les représentations WKT d'une collection d'anneaux ou d'objets LineString fermés. Ces objets peuvent avoir des intersections non vides. MySQL ne supporte pas encore ces fonctions.

- BdPolyFromText(wkt,srid)
Construit un objet Polygon à partir de la représentation WKT d'un objet MultiLineString, contenant un ensemble d'objets LineString fermés.

- BdMPolyFromText(wkt,srid)
Construit un objet MultiPolygon à partir de la représentation WKT d'un objet MultiLineString, contenant un ensemble d'objets LineString fermés.

18-D-2-b - Créer des objets géométriques avec les fonctions WKB

MySQL fournit de nombreuses fonctions qui prennent en arguments un BLOB contenant la représentation au format Well-Known Binary et optionnellement, un système de référence (SRID), et retourne la forme géométrique correspondante.

GeomFromWKT() accepte des données WKB de n'importe quel type de données géométriques comme premier argument. L'implémentation fournit aussi des fonctions de construction spécifiques à chaque forme géométrique.

- GeomFromWKB(wkb[,srid]), GeometryFromWKB(wkt[,srid])
Construit une forme géométrique à partir de sa représentation WKB et du SRID.

- PointFromWKB(wkb[,srid])
Construit un objet POINT à partir de sa représentation WKB et du SRID.

- LineFromWKB(wkb[,srid]), LineStringFromWKB(wkb[,srid])
Construit un objet LINESTRING à partir de sa représentation WKB et du SRID.

- PolyFromWKB(wkb[,srid]), PolygonFromWKB(wkb[,srid])
Construit un objet POLYGON à partir de sa représentation WKB et du SRID.

- MPointFromWKB(wkb[,srid]), MultiPointFromWKB(wkb[,srid])
Construit un objet MULTIPOINT à partir de sa représentation WKB et du SRID.

- MLineFromWKB(wkb[,srid]), MultiLineStringFromWKB(wkb[,srid])
Construit un objet MULTILINESTRING à partir de sa représentation WKB et du SRID.

- MPolyFromWKB(wkb[,srid]), MultiPolygonFromWKB(wkb[,srid])
Construit un objet MULTIPOLYGON à partir de sa représentation WKB et du SRID.

- GeomCollFromWKB(wkb[,srid]), GeometryCollectionFromWKB(wkt[,srid])
Construit un objet GEOMETRYCOLLECTION à partir de sa représentation WKB et du SRID.

Les spécifications OpenGIS décrivent aussi des fonctions optionnelles pour construire des Polygon et MultiPolygon basés sur les représentations WKB d'une collection d'anneaux ou d'objets LineString fermés. Ces objets peuvent avoir des intersections non vides. MySQL ne supporte pas encore ces fonctions.

- BdPolyFromWKB(wkb,srid)
Construit un objet Polygon à partir de la représentation WKB d'un objet MultiLineString, contenant un ensemble d'objets LineString fermés.

- BdMPolyFromWKB(wkb,srid)
Construit un objet MultiPolygon à partir de la représentation WKB d'un objet MultiLineString, contenant un ensemble d'objets LineString fermés.

18-D-2-c - Création de formes géométriques avec les fonctions spécifiques de MySQL

Note : MySQL ne dispose pas encore de toutes les fonctions listées dans cette section.

MySQL fournit un jeu de fonctions pratiques pour créer des représentations WKB. Ces fonctions sont décrites dans cette section, et sont spécifiques à MySQL : ce sont des extensions aux spécifications OpenGIS. Le résultat de ces fonctions est représenté par des valeurs de type BLOB qui contiennent la représentation au format WKB des objets géométriques, sans leur SRID. Le résultat de ces fonctions peut être utilisé comme premier argument de toute fonction de la famille GeomFromWKB().

- Point(x,y)
Construit un Point au format WKB, en utilisant ses coordonnées.

- MultiPoint(pt1,pt2,...)
Construit un objet MultiPoint au format WKB, en utilisant les arguments Point WKB. Si aucun argument n'est au format WKBPoint, la valeur retournée est NULL.

- LineString(pt1,pt2,...)
Construit un objet LineString au format WKB, à partir d'arguments Point WKB. Si aucun argument n'est au format WKBPoint, la valeur retournée est NULL. Si moins de deux arguments est fourni, la valeur retournée est NULL.

- MultiLineString(ls1,ls2,...)
Construit un objet MultiLineString au format WKB, en utilisant les objets LineString WBK. Si aucun argument n'est de classe LineString, la valeur retournée alors NULL.

- Polygon(ls1,ls2,...)
Construit un objet Polygon au format WKB, en utilisant les objets LineString WBK. Si aucun argument n'est de classe LinearRing, (c'est-à-dire, un objet LineString fermé et simple), la valeur retournée est alors NULL.

- MultiPolygon(poly1,poly2,...)
Construit un objet MultiPolygon au format WKB, en utilisant les objets Polygon WBK. Si aucun argument n'est de classe Polygon, la valeur retournée est alors NULL.

- GeometryCollection(g1,g2,...)
Construit un objet GeometryCollection au format WKB. Si aucun argument n'est au format valide WBK, la valeur retournée est alors NULL.

18-D-3 - Créer des colonnes géométriques

MySQL fournit une méthode standard pour créer des colonnes géographiques, avec les commandes CREATE TABLE ou ALTER TABLE, etc. Actuellement, les colonnes géométriques ne sont supportées que par les tables MyISAM.

- Utilisez la commande CREATE TABLE pour créer une colonne géométrique :

mysql> CREATE TABLE geom (g GEOMETRY);
Query OK, 0 rows affected (0.02 sec)

- Utilisez la commande ALTER TABLE pour ajouter ou effacer une colonne géométrique dans une table existante :

mysql> ALTER TABLE geom ADD pt POINT;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> ALTER TABLE geom DROP pt;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

18-D-4 - Remplir des colonnes géométriques

Une fois que vous avez créé des colonnes géométriques, vous pouvez les remplir avec des données géographiques.

Les valeurs doivent être stockées dans un format géométrique interne, mais vous pouvez les convertir à ce format à partir des formats Well-Known Text (WKT) et Well-Known Binary (WKB). Les exemples suivants vous montrent comment insérer des valeurs géométriques dans une table, en convertissant des valeurs WKT en un format géométrique.

Vous pouvez faire la conversion directement avec la commande INSERT :

INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'));

SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (GeomFromText(@g));

Au besoin, la conversion peut avoir lieu avant la commande INSERT :

SET @g = GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);

Les exemples suivants illustrent l'insertion de données plus complexes dans la table :

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (GeomFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (GeomFromText(@g));

SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (GeomFromText(@g));

Les exemples précédents utilisent tous la fonction GeomFromText() pour créer des valeurs géométriques. Vous pouvez aussi utiliser des fonctions spécifiques à chaque forme géométrique :

SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (PointFromText(@g));

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (LineStringFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (PolygonFromText(@g));

SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (GeomCollFromText(@g));

Notez que si une application cliente veut utiliser des représentations WKB de valeur géométrique, elle est responsable d'envoyer des requêtes avec des valeurs WKB valides au serveur. Sinon, il y a de nombreux moyens de passer cette contrainte. Par exemple :

- Insertion d'un point POINT(1 1) avec sa valeur littérale hexadécimale :

mysql> INSERT INTO geom VALUES
-> (GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));

- Une application ODBC veut envoyer une représentation WKB, en l'associant à une variable de requête en utilisant un argument de type BLOB :

INSERT INTO geom VALUES (GeomFromWKB(?))

D'autres interfaces de programmation peuvent supporter des mécanismes similaires.

- Dans un programme C, vous pouvez protéger les valeurs binaires en utilisant la fonction mysql_real_escape_string() et inclure le résultat dans une chaîne de requête, qui sera envoyée au serveur. Voir Section 24.2.3.47, « mysql_real_escape_string() ».

18-D-5 - Lire des données géométriques

Les formes géométriques sont stockées dans une table, et peuvent être lues dans différents formats. Vous pouvez les convertir au format interne, WBK ou WBT.

18-D-5-a - Lire des données géométriques au format interne

Lire des données géométriques au format interne peut être utile lors des transferts de table en table :

CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;

18-D-5-b - Lire des données géométriques au format WBT

La fonction AsText() fournit une représentation textuelle d'une forme géométrique. Elle convertit la forme depuis le format interne en une chaîne au format WKT.

mysql> SELECT AsText(g) FROM geom;
+-------------------------+
| AsText(p1)              |
+-------------------------+
| POINT(1 1)              |
| LINESTRING(0 0,1 1,2 2) |
+-------------------------+

18-D-5-c - Lire des données géométriques au format WBK

La fonction AsBinary() fournit l'accès binaire aux formes géométriques. Elle convertit une forme géométrique, depuis le format interne en un BLOB contenant la représentation WKB.

SELECT AsBinary(g) FROM geom;

18-E - Analyser des données géographiques

Après avoir rempli les colonnes géographiques avec des valeurs, vous êtes prêts à les analyser. MySQL propose un jeu de fonctions pour effectuer différentes opérations sur des données géographiques. Ces fonctions peuvent être regroupées en plusieurs catégories principales, suivant le type de manipulations :

- les fonctions qui convertissent les données géométriques en différents formats ;

- les fonctions qui fournissent des accès aux données qualitatives ou quantitatives d'un objet géométrique ;

- les fonctions qui décrivent les relations entre deux objets géométriques ;

- les fonctions qui créent des objets à partir d'autres objets existants.

Les fonctions d'analyse de données géographiques peuvent être utilisées dans plusieurs contextes, comme :

- un programme SQL interactif, comme MySQL ou MySQLCC ;

- une application écrite dans un langage qui dispose du support des bibliothèques clientes MySQL.

18-E-1 - Fonctions pour convertir les formes de format

MySQL supporte les fonctions suivantes pour convertir des formes géométriques entre les formats internes, WKT et WKB.

- GeomFromText(wkt[,srid])
Convertit une chaîne au format WKT vers le format interne, et retourne le résultat. Des fonctions adaptées au type sont supportées comme PointFromText() et LineFromText() ; voyez Section 18.4.2.1 : « Créer des objets géométriques avec les fonctions WKT ».

- GeomFromWKB(wkb[,srid])
Convertit une chaîne au format WKB vers le format interne, et retourne le résultat. Des fonctions adaptées au type sont supportées comme PointFromWKB() et LineFromWKB(); voyez Section 18.4.2.2, « Créer des objets géométriques avec les fonctions WKB ».

- AsText(g)
Convertit une chaîne au format interne vers le format WKT, et retourne le résultat.

mysql> SET @g = 'LineString(1 1,2 2,3 3)';
mysql> SELECT AsText(GeomFromText(@g));
+--------------------------+
| AsText(GeomFromText(@G)) |
+--------------------------+
| LINESTRING(1 1,2 2,3 3)  |
+--------------------------+

- AsBinary(g)
Convertit une chaîne au format interne vers le format WKB, et retourne le résultat.

18-E-2 - Fonction d'analyse des propriétés des formes Geometry

Chaque fonction de ce groupe prend une forme géométrique comme argument et représente un attribut qualitatif ou quantitatif de cette forme. Certaines fonctions sont spécifiques à une forme particulière. Certaines fonctions retournent NULL si l'argument n'est pas d'un type valide. Par exemple, Area() retourne NULL si le type de l'objet n'est ni Polygon ni MultiPolygon.

18-E-2-a - Fonctions générales d'analyse géométrique

Les fonctions de cette section n'ont pas de restriction sur les arguments, et acceptent toutes sortes de formes.

- GeometryType(g)
Retourne le type de forme de g, sous forme de chaîne. Le nom correspond à l'une des sous-classes instanciable Geometry.

mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));
+------------------------------------------+
| GeometryType(GeomFromText('POINT(1 1)')) |
+------------------------------------------+
| POINT                                    |
+------------------------------------------+

- Dimension(g)
Retourne le nombre de dimensions de l'objet g. Le résultat peut être -1, 0, 1 ou 2. La signification de ces valeurs est expliquée dans la section Section 18.2.2, « Classe Geometry ».

mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));
+------------------------------------------------+
| Dimension(GeomFromText('LineString(1 1,2 2)')) |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+

- SRID(g)
Retourne un entier indiquant l'identifiant du système de coordonnées de la forme g.

mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
+-----------------------------------------------+
| SRID(GeomFromText('LineString(1 1,2 2)',101)) |
+-----------------------------------------------+
|                                           101 |
+-----------------------------------------------+

- Envelope(g)
Retourne le rectangle enveloppe (Minimum Bounding Rectangle, ou MBR) de la forme g. Le résultat est retourné sous forme de polygone.

mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)')));
+-------------------------------------------------------+
| AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) |
+-------------------------------------------------------+
| POLYGON((1 1,2 1,2 2,1 2,1 1))                        |
+-------------------------------------------------------+

Le polygone est défini par ses sommets :

POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

Les spécifications OpenGIS définissent les fonctions suivantes, que MySQL n'implémente pas :

- Boundary(g)
Retourne une forme qui représente la frontière de g.

- IsEmpty(g)
Retourne 1 si la forme g est vide, et 0 si elle n'est pas vide. Elle retourne -1 si l'argument est NULL. Si la forme est vide, elle représente un ensemble de points vide.

- IsSimple(g)
Actuellement, cette fonction est inutilisable et ne doit pas être employée. Lorsqu'elle sera fonctionnelle, elle suivra la définition du prochain paragraphe.
Retourne 1 si la forme géométrique g n'a aucune anomalie géométrique, telle que l'auto-intersection ou l'auto-tangence. IsSimple() retourne 0 si l'argument n'est pas simple, -1 si l'objet est NULL.
La description de chaque classe géométrique instanciable est donnée plus tôt dans ce chapitre, et inclut les conditions qui font qu'une forme est considérée comme simple ou pas.

18-E-2-b - Fonctions d'analyse des Points

Un objet Point est constitué de ses coordonnées X et Y, qui peuvent être obtenues comme ceci :

- X(p)
Retourne l'abcisse du point p sous forme d'un nombre à virgule en double précision.

mysql> SELECT X(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| X(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                 56.7 |
+--------------------------------------+

- Y(p)
Retourne l'ordonnée du point p sous forme d'un nombre à virgule en double précision.

mysql> SELECT Y(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| Y(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                53.34 |
+--------------------------------------+

18-E-2-c - Fonctions d'analyse des lignes LineString

Une ligne LineString est constituée de Point. Vous pouvez extraire des points particuliers d'une ligne LineString, compter le nombre de points qu'elle contient, ou encore calculer sa longueur.

- EndPoint(ls)
Retourne le Point terminal de la ligne LineString ls.

mysql> SELECT AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+------------------------------------------------------------+
| AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')))  |
+------------------------------------------------------------+
| POINT(3 3)                                                 |
+------------------------------------------------------------+

- GLength(ls)
Retourne la longueur de la ligne ls sous forme d'un nombre à virgule et double précision.

mysql> SELECT GLength(GeomFromText('LineString(1 1,2 2,3 3)'));
+--------------------------------------------------+
| GLength(GeomFromText('LineString(1 1,2 2,3 3)')) |
+--------------------------------------------------+
|                                  2.8284271247462 |
+--------------------------------------------------+

- IsClosed(ls)
Retourne 1 si ls est fermée : c'est-à-dire si StartPoint() et EndPoint() sont identiques. Retourne 0 si ls n'est pas fermée, et -1 si l'argument passé est NULL.

mysql> SELECT IsClosed(GeomFromText('LineString(1 1,2 2,3 3)'));
+---------------------------------------------------+
| IsClosed(GeomFromText('LineString(1 1,2 2,3 3)')) |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+

- NumPoints(ls)
Retourne le nombre de points dans la ligne ls.

mysql> SELECT NumPoints(GeomFromText('LineString(1 1,2 2,3 3)'));
+----------------------------------------------------+
| NumPoints(GeomFromText('LineString(1 1,2 2,3 3)')) |
+----------------------------------------------------+
|                                                  3 |
+----------------------------------------------------+

- PointN(ls,n)
Retourne le nième point de la ligne ls. La numérotation des points commence à 1.

mysql> SELECT AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2));
+-----------------------------------------------------------+
| AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2)) |
+-----------------------------------------------------------+
| POINT(2 2)                                                |
+-----------------------------------------------------------+

- StartPoint(ls)
Retourne le premier Point de la ligne ls.

mysql> SELECT AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+-------------------------------------------------------------+
| AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)'))) |
+-------------------------------------------------------------+
| POINT(1 1)                                                  |
+-------------------------------------------------------------+

Les spécifications OpenGIS définissent aussi les fonctions suivantes, que MySQL n'implémente pas encore :

- IsRing(ls)
Retourne 1 si ls est un anneau : il faut que ls soit fermée (c'est-à-dire que StartPoint() et EndPoint() sont identiques), et qu'elle soit simple (ne passe pas par le même point plusieurs fois). Retourne 0 si ls n'est pas un anneau, et -1 si elle vaut NULL.

18-E-2-d - Fonctions d'analyse des lignes MultiLineString

- GLength(mls)
Retourne la longueur de l'objet mls. La longueur de l'objet mls est égale à la somme des longueurs de ses éléments.

mysql> SELECT GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+-------------------------------------------------------------------+
| GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+-------------------------------------------------------------------+
|                                                   4.2426406871193 |
+-------------------------------------------------------------------+

- IsClosed(mls)
Retourne 1 si mls est fermée (c'est-à-dire que StartPoint() et EndPoint() sont identiques pour chaque objet LineString de mls). Retourne 0 si mls n'est pas fermée et -1 si l'objet est NULL.

mysql> SELECT IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+--------------------------------------------------------------------+
| IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+--------------------------------------------------------------------+
|                                                                  0 |
+--------------------------------------------------------------------+

18-E-2-e - Fonctions d'analyse des lignes Polygon

- Area(poly)
Retourne un nombre à virgule en double précision représentant l'aire de l'objet Polygon poly, tel que mesuré dans son référentiel.

mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';
mysql> SELECT Area(GeomFromText(@poly));
+---------------------------+
| Area(GeomFromText(@poly)) |
+---------------------------+
|                         4 |
+---------------------------+

- NumInteriorRings(poly)
Retourne le nombre d'anneaux intérieurs de poly.

mysql> SET @poly =
-> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly)));
+-------------------------------------------+
| AsText(ExteriorRing(GeomFromText(@poly))) |
+-------------------------------------------+
| LINESTRING(0 0,0 3,3 3,3 0,0 0)           |
+-------------------------------------------+

- InteriorRingN(poly,n)
Retourne le nième anneau intérieur de l'objet Polygon poly sous forme d'un objet LineString. Ring numbers begin at 1.

mysql> SET @poly =
-> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));
+----------------------------------------------+
| AsText(InteriorRingN(GeomFromText(@poly),1)) |
+----------------------------------------------+
| LINESTRING(1 1,1 2,2 2,2 1,1 1)              |
+----------------------------------------------+

- InteriorRingN(poly,n)
Retourne le nombre d'anneaux intérieurs dans l'objet Polygon poly.

mysql> SET @poly =
-> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql> SELECT NumInteriorRings(GeomFromText(@poly));
+---------------------------------------+
| NumInteriorRings(GeomFromText(@poly)) |
+---------------------------------------+
|                                     1 |
+---------------------------------------+

18-E-2-f - Fonctions d'analyse des lignes MultiPolygon

- Area(mpoly)
Retourne la surface de l'objet MultiPolygon mpoly, mesurée dans son référentiel.

mysql> SELECT Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'));
+-----------------------------------------------------------------------------------+
| Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))')) |
+-----------------------------------------------------------------------------------+
|                                                                                 8 |
+-----------------------------------------------------------------------------------+

Les spécifications OpenGIS définissent aussi les fonctions suivantes, que MySQL n'implémente pas encore :

- Centroid(mpoly)
Retourne le centre mathématique de l'objet MultiPolygon mpoly, sous la forme d'un Point. Le résultat n'est pas forcément dans l'objet MultiPolygon ;

- PointOnSurface(mpoly)
Retourne un point Point qui est dans l'objet MultiPolygon mpoly.

18-E-2-g - Fonctions d'analyse des lignes GeometryCollection

- NumGeometries(gc)
Retourne le nombre de formes géométriques qui constituent l'objet GeometryCollection gc.

mysql> SELECT NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'));
+------------------------------------------------------------------------------------+
| NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))')) |
+------------------------------------------------------------------------------------+
|                                                                                  2 |
+------------------------------------------------------------------------------------+

- GeometryN(gc,n)
Retourne le nième objet constituant l'objet GeometryCollection gc. La numérotation commence à 1.

mysql> SELECT AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1));
+------------------------------------------------------------------------------------------+
| AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1)) |
+------------------------------------------------------------------------------------------+
| POINT(1 1)                                                                               |
+------------------------------------------------------------------------------------------+

18-E-3 - Fonctions qui génèrent des formes géométriques à partir d'autres formes

18-E-3-a - Fonctions géométriques qui génèrent de nouvelles formes

Dans la section Section 18.5.2 : « Fonction d'analyse des propriétés des formes Geometry », nous avons déjà discuté de certaines fonctions qui génèrent de nouvelles formes à partir de formes existantes :

- Envelope(g) ;

- StartPoint(ls) ;

- EndPoint(ls) ;

- PointN(ls,n) ;

- ExteriorRing(poly) ;

- InteriorRingN(poly,n) ;

- GeometryN(gc,n).

18-E-3-b - Opérateurs géométriques

OpenGIS propose d'autres fonctions qui génèrent des formes géométriques. Elles sont conçues pour servir d'opérateurs géométriques.

Ces fonctions ne sont pas encore implémentées par MySQL. Elles devraient arriver dans les prochaines versions.

- Intersection(g1,g2)
Retourne l'ensemble des points qui représentent l'intersection des deux formes g1 et g2.

- Union(g1,g2)
Retourne l'ensemble des points qui représentent l'union des deux formes g1 et g2.

- Difference(g1,g2)
Retourne l'ensemble des points qui représentent la différence des deux formes g1 et g2.

- SymDifference(g1,g2)
Retourne l'ensemble des points qui représentent la différence symétrique des deux formes g1 et g2.

- Buffer(g,d)
Retourne l'ensemble des points dont la distance à la forme g est inférieure ou égale à d.

- ConvexHull(g)
Retourne l'enveloppe convexe de la forme géométrique g.

18-E-4 - Fonctions de tests des relations géométriques entre les formes

Les fonctions décrites dans ces fonctions prennent deux formes géométriques comme argument, et retournent des informations qualitatives ou quantitatives sur leurs relations.

18-E-5 - Relations avec les Rectangles enveloppes (MBRs)

MySQL fournit des fonctions qui permettent de tester les relations entre les rectangles enveloppes de deux formes géométriques g1 et g2. Il s'agit de :

- MBRContains(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 contient celui de g2.

mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
mysql> SET @g2 = GeomFromText('Point(1 1)');
mysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);
----------------------+----------------------+
| MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |
+----------------------+----------------------+
|                    1 |                    0 |
+----------------------+----------------------+

- MBRWithin(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 est à l'intérieur de g2.

mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');
mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);
+--------------------+--------------------+
| MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |
+--------------------+--------------------+
|                  1 |                  0 |
+--------------------+--------------------+

- MBRDisjoint(g1,g2)
Retourne 1 ou 0 pour indiquer que les rectangles enveloppes de g1 et g2 sont disjoints (ils n'ont pas d'intersection) ;

- MBREquals(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 est le même que celui de g2.

- MBRIntersects(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 et celui de g2 ont une intersection non vide ;

- MBROverlaps(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 recouvre une partie de celui de g2 ;

- MBRTouches(g1,g2)
Retourne 1 ou 0 pour indiquer que le rectangle enveloppe de g1 touche celui de g2.

18-E-6 - Fonctions qui testent les relations géométriques entre les formes

Les spécifications OpenGIS définissent les fonctions suivantes, que MySQL n'implémente pas encore. Elles devraient apparaître prochainement, dans les prochaines versions. Lorsqu'elles seront implémentées, elles fourniront le support complet des fonctions d'analyse spatiales, et non pas un simple support de la géométrie des enveloppes.

Ces fonctions opèrent toujours sur deux formes géométriques g1 et g2.

- Contains(g1,g2)
Retourne 1 ou 0 suivant que g1 contienne complètement g2 ou pas.

- Crosses(g1,g2)
Retourne 1 si g1 rencontre g2. Retourne NULL si g1 est un Polygon ou un MultiPolygon, ou si g2 est un Point ou un groupe MultiPoint. Otherwise, returns 0.
« rencontre » indique une relation entre deux formes, ayant les propriétés suivantes :

- les deux formes ont une intersection non vide ;

- leur intersection est une forme géométrique qui a une dimension de moins que le nombre maximum de dimensions des deux formes g1 et g2 ;

- l'intersection n'est pas égale à g1 ou g2.

- Disjoint(g1,g2)
Retourne 1 ou 0 pour indiquer si g1 est géométriquement disjoint de g2 ou non.

- Equals(g1,g2)
Retourne 1 ou 0 pour indiquer que g1 est géométriquement égal à g2, ou non.

- Intersects(g1,g2)
Retourne 1 ou 0, pour indiquer si g1 a une intersection non vide avec g2 ou pas.

- Overlaps(g1,g2)
Retourne 1 ou 0 pour indiquer si g1 recouvre g2 ou pas. Le terme recouvre signifie que deux formes géométriques ont une intersection de même dimension que les formes initiales, mais différentes de ces formes.

- Touches(g1,g2)
Retourne 1 ou 0 pour indiquer si g1 touche g2 ou pas. Deux formes se touchent si leurs intérieurs ont une intersection vide, mais que l'une des deux frontières a une intersection non vide avec la frontière ou l'intérieur de l'autre.

- Within(g1,g2)
Retourne 1 ou 0 pour indiquer si g1 est à l'intérieur de g2.

- Distance(g1,g2)
Retourne la distance la plus faible entre deux points des deux formes, sous forme d'un nombre à virgule et double précision.

- Related(g1,g2,pattern_matrix)
Retourne 1 ou 0, pour indiquer si la relation géométrique spécifiée par pattern_matrix existe entre les formes g1 et g2. Retourne -1 si les arguments sont NULL. Le paramètre pattern_matrix est une chaîne. Ses spécifications seront détaillées lorsque la fonction sera codée.

18-F - Optimiser l'analyse géographique

Il est connu que les index accélèrent les recherches dans les bases de données non géographiques. C'est aussi vrai avec les bases de données géographiques. Avec l'aide d'une grande variété d'index multidimensionnels qui ont été conçus pour cela, il est possible d'optimiser les recherches avec des index. Le plus classique est :

- les requêtes de point, où on recherche les objets qui contiennent un point donné ;

- les requêtes de région, qui recherchent tous les objets qui ont des zones communes.

MySQL utilise des R-Trees avec répartition quadratique pour indexer les colonnes géographiques. Un index géographique est constitué en utilisant le MBR d'une forme géométrique. Dans la plupart des cas, le MBR est le rectangle minimum qui entoure une région. Pour les lignes horizontales ou verticales, le MBR est un rectangle généré dans les chaînes. Pour un point, le MBR est un rectangle dégénéré en un point.

18-F-1 - Créer un index géométrique

MySQL peut créer des index géométriques en utilisant une syntaxe similaire à celle utilisée avec les index classiques, mais étendue avec l'attribut SPATIAL. Les colonnes géographiques doivent être déclarées comme NOT NULL. L'exemple suivant montre comment créer un index géographique.

- Avec CREATE TABLE :

mysql> CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));

- Avec ALTER TABLE :

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);

- Avec CREATE INDEX :

mysql> CREATE SPATIAL INDEX sp_index ON geom (g);

Pour effacer un index géométrique, utilisez ALTER TABLE ou DROP INDEX :

- Avec ALTER TABLE :

mysql> ALTER TABLE geom DROP INDEX g;

- Avec DROP INDEX :

mysql> DROP INDEX sp_index ON geom;

Exemple : supposons que la table geom contient plus de 32 000 formes, qui sont stockées dans la colonne g, avec le type GEOMETRY. La table dispose aussi d'une colonne d'identifiant fid, de type AUTO_INCREMENT pour stocker des identifiants d'objets.

mysql> SHOW FIELDS FROM geom;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| fid   | int(11)  |      | PRI | NULL    | auto_increment |
| g     | geometry |      |     |         |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT COUNT(*) FROM geom;
+----------+
| count(*) |
+----------+
|    32376 |
+----------+
1 row in set (0.00 sec)

Pour ajouter un index géométrique à la colonne g, utilisez cette commande :

mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376  Duplicates: 0  Warnings: 0

18-F-2 - Utiliser un index géométrique

L'optimiseur vérifie si un index géométrique est disponible et peut être utilisé pour accélérer les requêtes qui utilisent des fonctions comme MBRContains() ou MBRWithin() dans les clauses WHERE. Par exemple, imaginons que vous devez trouver les objets qui sont dans un rectangle donné :

mysql> SELECT fid,AsText(g) FROM geom WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+-----+-----------------------------------------------------------------------------+
| fid | AsText(g)                                                                   |
+-----+-----------------------------------------------------------------------------+
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
+-----+-----------------------------------------------------------------------------+
20 rows in set (0.00 sec)

Maintenant, vérifions comment cette requête est exécutée, avec la commande EXPLAIN :

mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | geom  | range | g             | g    |      32 | NULL |   50 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

Voyons ce qui se passe si nous n'avions pas utilisé d'index spatial :

mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | geom  | ALL  | NULL          | NULL |    NULL | NULL | 32376 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

Exécutons la requête ci-dessus, en ignorant l'index spatial disponible :

mysql> SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+-----+-----------------------------------------------------------------------------+
| fid | AsText(g)                                                                   |
+-----+-----------------------------------------------------------------------------+
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
+-----+-----------------------------------------------------------------------------+
20 rows in set (0.46 sec)

Lorsque l'index n'est pas utilisé, le temps d'exécution de la requête passe de 0.00 seconde à 0.46 second.

Dans les prochaines versions, les index spatiaux seront aussi utilisés pour optimiser d'autres fonctions. Voir Section 18.5.4 : « Fonctions de tests des relations géométriques entre les formes ».

18-G - MySQL compatibilité avec GIS

18-G-1 - Les fonctionnalités de GIS que nous n'avons pas encore implémentées

- Vues de métadonnées
Les spécifications OpenGIS proposent plusieurs métadonnées supplémentaires. Par exemple, un système de vue appelé GEOMETRY_COLUMNS contient une description des colonnes géométriques, une ligne pour chaque colonne géométrique dans la base.

- Les fonctions OpenGIS Length() sur les LineString et MultiLineString sont appelées GLength() en MySQL.
Le problème est que ce nom est en conflit avec la fonction SQL existante Length() qui calcule la taille d'une chaîne de caractères, et il n'est pas possible de faire la différence entre le contexte géographique ou textuel. Nous devons résoudre ce problème, ou trouver un autre nom à cette fonction.

19 - Procédures stockées et fonctions

Les procédures stockées et les fonctions sont de nouvelles fonctionnalités de MySQL version 5.0. Une procédure stockées est un jeu de commandes SQL qui réside sur le serveur. Une fois qu'elles sont enregistrées, les clients n'ont pas besoin de soumettre chaque commande individuellement, mais peuvent les lancer d'un seul coup.

Les procédures stockées fournissent un gain de performances, car moins d'informations sont échangées entre le serveur et le client. En échange, cela augmente la charge du serveur, car ce dernier doit réaliser plus de travail. Souvent, il y a de nombreux clients, mais peu de serveurs.

Les procédures stockées permettent aussi l'utilisation de bibliothèques et de fonctions sur le serveur. Les langages de programmation modernes ont déjà intégré ce type de concept, et l'utilisation de ces langages de programmation externes reste valable et utile en dehors de la base de données.

Quelques situations où les procédures stockées sont utiles :

- lorsque plusieurs applications clientes sont écrites dans différents langages sur différentes plates-formes, et utilisent le serveur comme point d'interaction ;

- lorsque la sécurité est prioritaire. Les banques, par exemple, utilisent les procédures stockées pour toutes les opérations standards. Cela conduit à un environnement cohérent et sécurisé, car les procédures s'assurent que les opérations sont correctement faites et enregistrées. Dans une telle configuration, les applications et les utilisateurs n'ont aucun accès direct aux tables, mais passent par des procédures stockées prédéfinies.

MySQL suit la syntaxe de la norme SQL:2003 pour les procédures stockées, qui est aussi utilisée par IBM dans DB2. La compatibilité avec les autres langages de procédures stockées, comme PL/SQL ou T-SQL, sera ajoutée ultérieurement.

L'implémentation des procédures stockées de MySQL est en cours de développement. Toutes les syntaxes décrites dans ce chapitre sont supportées, et les limitations ou extensions sont documentées lorsque c'est nécessaire.

Les procédures stockées requièrent la table proc dans la base mysql. Cette table est créée durant l'installation de MySQL 5.0. Si vous passez à MySQL 5.0 depuis une ancienne version, assurez-vous de bien mettre à jour vos tables de droits, et que la table proc existe. Voir Section 2.6.7 : « Mise à jour des tables de droits ».

19-A - Procédures stockées et tables de droits

Les procédures stockées requièrent la table proc dans la base mysql. Cette table est créée durant la procédure d'installation de MySQL 5.0. Si vous faîtes la mise à jour vers MySQL 5.0 depuis une ancienne installation, pensez à mettre à jour les tables de droits pour que la table proc existe. Voir Section 2.6.7 : « Mise à jour des tables de droits ».

Depuis MySQL 5.0.3, le système de droits a été modifié pour prendre en compte les procédures stockées comme ceci :

- le droit de CREATE ROUTINE est nécessaire pour créer une procédure stockée ;

- le droit de ALTER ROUTINE est nécessaire pour pouvoir modifier ou effacer une procédure stockée. Le droit est fourni automatiquement au créateur d'une routine ;

- le droit de EXECUTE est requis pour exécuter une procédure stockée. Cependant, ce droit est fourni automatiquement au créateur d'une routine. De plus, la caractéristique par défaut SQL SECURITY est définie (DEFINER), ce qui fait que les utilisateurs qui ont accès à une base de données associée à une routine ont le droit d'exécuter la routine.

19-B - Syntaxe des procédures stockées

Les procédures stockées et les fonctions sont créées avec les commandes CREATE PROCEDURE et CREATE FUNCTION. Une procédure est appelée avec la commande CALL, et ne peut retourner de valeur que via les variables de retour. Les fonctions peuvent retourner une valeur scalaire, et être appelées depuis une commande, tout comme toute autre fonction. Les procédures stockées peuvent appeler une autre routine stockée. Une routine est une procédure stockée ou une fonction.

Actuellement, MySQL préserve uniquement le contexte de la base par défaut. C'est-à-dire que si vous utilisez la commande USE dbname dans une procédure, le contexte initial sera restauré à la fin de la procédure.

Une routine hérite de la base de données par défaut de l'utilisateur appelant, et donc, il est recommandé de commencer les routines avec la commande USE dbname, ou de spécifier explicitement les tables et les bases de données qui sont utilisées : i.e. base.table.

MySQL supporte une extension très pratique qui permet d'utiliser des expressions régulières dans les commandes SELECT (c'est-à-dire, sans utiliser de curseur ou de variables locales). Le résultat d'une telle requête est simplement envoyé directement au client.

Plusieurs commandes SELECT généreront plusieurs jeux de résultats, et le client doit utiliser la bibliothèque qui supporte les résultats multiples. Cela signifie que vous devez utiliser une bibliothèque cliente de version 4.1 ou plus récente.

La section suivante décrit la syntaxe à utiliser pour créer, modifier, détruire et appeler des procédures stockées.

19-B-1 - CREATE PROCEDURE et CREATE FUNCTION

CREATE PROCEDURE sp_name ([parameter[,...]])
[characteristic ...] routine_body

CREATE FUNCTION sp_name ([parameter[,...]])
[RETURNS type]
[characteristic ...] routine_body

paramètre :
[ IN | OUT | INOUT ] param_name type

type :
Any valid MySQL data type

characteristic:
LANGUAGE SQL
| [NOT] DETERMINISTIC
| SQL SECURITY {DEFINER | INVOKER}
| COMMENT string

routine_body :
Commande(s) SQL valide(s)

La clause RETURNS peut être spécifiée uniquement pour une FUNCTION. Elle sert à indiquer le type de retour de la fonction, et le corps de la fonction doit contenir une instruction RETURN value.

La liste de paramètres entre parenthèses est obligatoire. S'il n'y a pas de paramètres, une liste vide sous la forme () doit être utilisée. Chaque paramètre est un paramètre de type IN par défaut. Pour spécifier un autre type, utilisez les mots OUT ou INOUT avant le nom du paramètre. Spécifier IN, OUT ou INOUT n'est valable que pour une PROCEDURE.

L'instruction CREATE FUNCTION est utilisée dans les anciennes versions de MySQL pour créer des UDF (User Defined Functions, fonctions utilisateur). Voir Section 27.2 : « Ajouter des fonctions à MySQL ». Les UDF sont toujours supportées, même avec la présence des procédures stockées. Une UDF peut être considérée comme une fonction stockée. Cependant, notez que les UDF et les fonctions stockées partagent le même espace de noms.

Un framework pour développer des procédures stockées externes sera prochainement présenté. Il permettra d'écrire des procédures stockées dans des langages autre que SQL. Il est probable que l'un des premiers langages supportés sera PHP, car le moteur PHP est compact, compatible avec les threads et peut être facilement intégré. Comme ce framework sera public, il est probable que bien d'autres langages soient supportés.

Une fonction est considérée comme « déterministe » si elle retourne toujours le même résultat pour les mêmes paramètres d'entrée. Sinon, elle est considérée comme « non déterministe ». L'optimiseur peut utiliser cette propriété. Actuellement, l'attribut DETERMINISTIC est accepté, mais il n'est pas encore utilisé.

L'attribut SQL SECURITY peut être utilisé pour spécifier si la routine doit être exécutée avec les droits de l'utilisateur qui l'a créé ou avec ceux de celui qui appelle la fonction. La valeur par défaut est DEFINER. Cette fonctionnalité est nouvelle en SQL:2003.

MySQL n'utilise pas le droit GRANT EXECUTE. Pour le moment, si une procédure p1() utilise la table t1, l'appelant doit avoir les droits sur la table t1 afin que la procédure p1() puisse réussir.

MySQL stocke la configuration SQL_MODE en effet au moment de la création de la procédure, et l'utilisera toujours lors de l'exécution de la procédure.

La clause COMMENT est une extension MySQL, et peut servir à décrire la procédure stockée. Cette information est affichée par les commandes SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION.

MySQL permet aux routines de contenir des commandes DDL, telles que CREATE et DROP, et des transactions SQL, comme COMMIT. Ce n'est pas obligatoire selon le standard et c'est donc une extension spécifique.

Note : actuellement, les fonctions stockées FUNCTION ne doivent pas contenir de références aux tables. Notez que cela inclut aussi les commandes SET, mais pas les commandes SELECT. Cette limitation sera supprimée aussitôt que possible.

L'exemple suivant est une procédure stockée simple, qui utilise un paramètre de sortie OUT. L'exemple utilise la commande delimiter du client mysql pour modifier le délimiteur de commande avant de définir la procédure. Cela permet au délimiteur ; d'être utilisé dans le corps de la procédure, plutôt que d'être interprété par le client mysql.

mysql> delimiter |

mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
->   SELECT COUNT(*) INTO param1 FROM t;
-> END
-> |
Query OK, 0 rows affected (0.00 sec)

mysql> CALL simpleproc(@a)|
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @a|
+------+
| @a   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

L'exemple suivant est une fonction qui prend un paramètre, effectue une opération avec une fonction SQL, et retourne le résultat :

mysql> delimiter |

mysql> CREATE FUNCTION bonjour (s CHAR(20)) RETURNS CHAR(50)
-> RETURN CONCAT('Bonjour, ',s,'!');
-> |
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT bonjour('le monde')|
+---------------------+
| bonjour('le monde') |
+---------------------+
| Bonjour, le monde!  |
+---------------------+
1 row in set (0.00 sec)

19-B-2 - ALTER PROCEDURE et ALTER FUNCTION

ALTER PROCEDURE | FUNCTION sp_name [characteristic ...]

characteristic:
NAME newname
| SQL SECURITY {DEFINER | INVOKER}
| COMMENT string

Cette commande peut être utilisée pour renommer une procédure stockée ou une fonction, et pour en changer les caractéristiques. Plusieurs modifications peut être spécifiées dans une commande ALTER PROCEDURE et ALTER FUNCTION.

19-B-3 - DROP PROCEDURE et DROP FUNCTION

DROP PROCEDURE | FUNCTION [IF EXISTS] sp_name

Cette commande sert à effacer une procédure stockée ou une fonction. C'est-à-dire que la routine spécifiée est supprimée du serveur.

La clause IF EXISTS est une extension de MySQL. Elle permet d'éviter une erreur si la routine n'existe pas. Une alerte est alors produite, et peut être lue avec SHOW WARNINGS.

19-B-4 - SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION

SHOW CREATE PROCEDURE | FUNCTION sp_name

Cette commande est une extension MySQL. Similaire à SHOW CREATE TABLE, elle retourne la chaîne exacte qui permet de recréer la procédure.

mysql> SHOW CREATE FUNCTION test.hello\G
*************************** 1. row ***************************
Function: hello
sql_mode:
Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hello, ',s,'!')

19-B-5 - SHOW PROCEDURE STATUS et SHOW FUNCTION STATUS

SHOW PROCEDURE | FUNCTION STATUS [LIKE pattern]

Cette commande est une extension MySQL. Elle retourne les caractéristiques de la routine, comme son nom, type, créateur, ainsi que les dates de création et de modification. Si le paramètre pattern n'est pas fourni, les informations sur toutes les procédures stockées ou fonctions sont listées, en fonction de la commande exacte que vous utilisez.

mysql> SHOW FUNCTION STATUS LIKE 'hello'\G
*************************** 1. row ***************************
Db: test
Name: hello
Type: FUNCTION
Definer: testuser@localhost
Modified: 2004-08-03 15:29:37
Created: 2004-08-03 15:29:37
Security_type: DEFINER
Comment:

Vous pouvez aussi vous reporter aux informations sur les procédures stockées dans la table ROUTINES, de la base INFORMATION_SCHEMA. Voir Section 22.1.14 : « La table INFORMATION_SCHEMA ROUTINES ».

19-B-6 - CALL

CALL sp_name([parameter[,...]])

La commande CALL sert à appeler une routine qui a été définie précédemment avec CREATE PROCEDURE.

19-B-7 - La commande composée BEGIN... END

[begin_label:] BEGIN
statement(s)
END [end_label]

Les routines peuvent contenir des commandes multiples, en utilisant le bloc de commande BEGIN ... END.

begin_label et end_label doivent être identiques, s'ils sont spécifiés.

Notez bien que la clause optionnelle [NOT] ATOMIC n'est pas encore supportée. Cela signifie qu'il n'y a pas de début de transaction au début du bloc, et que la clause BEGIN sera utilisée sans affecter la transaction courante.

Les commandes multiples requièrent un client capable d'envoyer des requêtes contenant le caractère ';'. C'est géré dans le client en ligne de commande mysql, avec la commande delimiter. Le changement du caractère de fin de requête ';' pour le remplacer par '|' permet à ';' d'être utilisé dans le corps de la routine.

19-B-8 - La commande DECLARE

La commande DECLARE sert à définir différents objets locaux dans une routine : variables locales (voir Section 19.2.9 : « Les variables dans les procédures stockées »), conditions et gestionnaires (voir Section 19.2.10 : « Conditions et gestionnaires »), curseurs (voir Section 19.2.11 : « Curseurs »). Les commandes SIGNAL et RESIGNAL ne sont pas supportées pour le moment.

DECLARE ne peut être utilisée dans un bloc BEGIN ... END, et doit intervenir au début de la routine, avant toute autre commande.

19-B-9 - Les variables dans les procédures stockées

Vous pouvez déclarer et utiliser des variables dans une routine.

19-B-9-a - DECLARE : déclarer une variable locale

DECLARE var_name[,...] type [DEFAULT value]

Cette commande sert à déclarer des variables globales. Le scope des variables est le bloc BEGIN ... END.

19-B-9-b - Commande d'affectation de variables SET

SET variable = expression [,...]

La commande SET des procédures stockées est une version étendue de la commande SET classique. Les variables référencées peuvent être déclarées dans le contexte de la routine ou comme variables globales.

La commande SET des procédures stockées est implémentée comme une sous-partie de la syntaxe SET. Cela permet la syntaxe étendue SET a=x, b=y, ..., où plusieurs types de variables (locales, serveurs, globales ou sessions) sont mélangés. Cela permet aussi la combinaison de variables locales et d'option système qui n'ont de sens qu'au niveau global du serveur : dans ce cas, les options sont acceptées, mais ignorées.

19-B-9-c - Syntaxe de SELECT... INTO

SELECT column[,...] INTO variable[,...] table_expression

Cette syntaxe de SELECT stocke les colonnes sélectionnées dans des variables. Par conséquent, une seule ligne doit être lue. Cette commande est aussi extrêmement utile lorsqu'elle est utilisée avec des curseurs.

SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

19-B-10 - Conditions et gestionnaires

Certaines conditions peuvent exiger des gestions spécifiques. Ces conditions peuvent être liées à des erreurs, ou au déroulement de la routine.

19-B-10-a - DECLARE une condition

DECLARE condition_name CONDITION FOR condition_value

condition_value:
SQLSTATE [VALUE] sqlstate_value
| mysql_error_code

Cette commande spécifie les conditions qui demandent une gestion spécifique. Elle associe un nom avec une erreur spécifique. Ce nom peut être utilisé ultérieurement dans une commande DECLARE HANDLER. Voir Section 19.2.10.2 : « DECLARE un gestionnaire ».

En plus des valeurs SQLSTATE, les codes d'erreur MySQL sont aussi supportés.

19-B-10-b - DECLARE un gestionnaire

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement

handler_type:
CONTINUE
| EXIT
| UNDO

condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
| mysql_error_code

Cette commande spécifie les gestionnaires qui vont traiter une ou plusieurs conditions. Si une de ces conditions survient, le gestionnaire associé est appelé.

Pour un gestionnaire CONTINUE, l'exécution de la routine courante continue après l'exécution du gestionnaire. Pour un gestionnaire EXIT, l'exécution de la routine est terminée. Le gestionnaire UNDO n'est pas encore supporté. Actuellement, UNDO se comporte comme CONTINUE.

- SQLWARNING est un raccourci pour tous les codes SQLSTATE qui commencent par 01.

- NOT FOUND est un raccourci pour tous les codes SQLSTATE qui commencent par 02.

- EXCEPTION est un raccourci pour tous les codes SQLSTATE qui ne sont pas représentés par SQLWARNING ou NOT FOUND.

En plus des valeurs SQLSTATE, les codes d'erreur MySQL sont aussi supportés.

Par exemple :

mysql> CREATE TABLE test.t (s1 int,primary key (s1));
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter |

mysql> CREATE PROCEDURE handlerdemo ()
-> BEGIN
->   DECLARE CONTINUE HANDLER FOR '23000' SET @x2 = 1;
->   set @x = 1;
->   INSERT INTO test.t VALUES (1);
->   set @x = 2;
->   INSERT INTO test.t VALUES (1);
->   SET @x = 3;
-> END;
-> |
Query OK, 0 rows affected (0.00 sec)

mysql> CALL handlerdemo()|
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x|
+------+
| @x   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

Notez que @x vaut 3, ce qui signifie que MySQL a exécuté la procédure jusqu'à la fin. Si la ligne DECLARE CONTINUE HANDLER FOR '23000' SET @x2 = 1; était absente, MySQL aurait pris le chemin par défaut (EXIT) après l'échec du second INSERT, dû à la contrainte de PRIMARY KEY, et SELECT @x aurait retourné 2.

19-B-11 - Curseurs

Des curseurs simples sont supportés dans les routines. La syntaxe est la même que dans le SQL intégré. Les curseurs sont actuellement assensibles, sans scroll et en lecture seule. Un curseur est dit assensible s'il peut ou non faire une copie de la table de résultat.

Par exemple :

CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE a CHAR(16);
DECLARE b,c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN cur1;
OPEN cur2;

REPEAT
FETCH cur1 INTO a, b;
FETCH cur2 INTO c;
IF NOT done THEN
IF b < c THEN
INSERT INTO test.t3 VALUES (a,b);
ELSE
INSERT INTO test.t3 VALUES (a,c);
END IF;
END IF;
UNTIL done END REPEAT;

CLOSE cur1;
CLOSE cur2;
END

19-B-11-a - Déclaration des curseurs

DECLARE cursor_name CURSOR FOR sql_statement

Plusieurs curseurs peuvent être définis dans une routine, mais chacun doit avoir un nom distinct.

19-B-11-b - Commande de curseur OPEN

OPEN cursor_name

Cette commande ouvre un curseur déclaré précédemment.

19-B-11-c - Commande de curseur FETCH

FETCH cursor_name

Cette commande lit la prochaine ligne (si elle existe), en utilisant un curseur ouvert, et avance le pointeur de curseur.

19-B-11-d - Commande de curseur CLOSE

CLOSE cursor_name

Cette commande clôt le curseur précédemment ouvert.

19-B-12 - Instructions de contrôle

Les instructions IF, CASE, LOOP, WHILE, ITERATE et LEAVE sont toutes supportées.

Ces instructions peuvent contenir des commandes simples, ou des blocs de commandes BEGIN ... END. Les instructions peuvent être imbriquées.

Les boucles FOR ne sont pas supportées actuellement.

19-B-12-a - Commande IF

IF search_condition THEN statement(s)
[ELSEIF search_condition THEN statement(s)]
...
[ELSE statement(s)]
END IF

IF implémente une instruction de condition simple. Si search_condition est vrai, la commande SQL correspondante est exécutée. Si search_condition est faux, la commande dans la clause ELSE est exécutée.

Notez aussi qu'il y a une fonction IF(). Voir Section 12.2 : « Les fonctions de contrôle ».

19-B-12-b - Commande CASE

CASE case_value
WHEN when_value THEN statement
[WHEN when_value THEN statement ...]
[ELSE statement]
END CASE

ou :

CASE
WHEN search_condition THEN statement
[WHEN search_condition THEN statement ...]
[ELSE statement]
END CASE

CASE implémente une structure conditionnelle complexe. Si une des conditions search_condition est vraie, la commande SQL correspondante est exécutée. Si aucune condition n'est vérifiée, la commande SQL de la clause ELSE est exécutée.

Note : la syntaxe de la commande CASE à l'intérieure d'une procédure stockée diffère légèrement de l'expression SQL CASE. La commande CASE ne peut pas avoir de clause ELSE NULL, et l'instruction se termine avec END CASE au lieu de END. Voir Section 12.2 : « Les fonctions de contrôle ».

19-B-12-c - Commande LOOP

[begin_label:] LOOP
statement(s)
END LOOP [end_label]

LOOP implémente une boucle, permettant l'exécution répétée d'un groupe de commandes. Les commandes à l'intérieur de la boucle sont exécutée jusqu'à ce que la boucle se termine, généralement lorsqu'elle atteint la commande LEAVE.

begin_label et end_label doivent être identiques, si les deux sont spécifiés.

19-B-12-d - Commande LEAVE

LEAVE label

Cette commande sert à sortir d'une instruction de contrôle.

19-B-12-e - Commande ITERATE

ITERATE label

ITERATE ne peut être utilisée qu'à l'intérieur d'une boucle LOOP, REPEAT ou WHILE. ITERATE signifie « exécute encore une fois la boucle. »

Par exemple :

CREATE PROCEDURE doiterate(p1 INT)
BEGIN
label1: LOOP
SET p1 = p1 + 1;
IF p1 < 10 THEN ITERATE label1; END IF;
LEAVE label1;
END LOOP label1;
SET @x = p1;
END

19-B-12-f - Commande REPEAT

[begin_label:] REPEAT
statement(s)
UNTIL search_condition
END REPEAT [end_label]

Les commandes à l'intérieur d'une commande REPEAT sont répétées jusqu'à ce que la condition search_condition soit vraie.

begin_label et end_label doivent être identiques, si elles sont fournies.

Par exemple :

mysql> delimiter |

mysql> CREATE PROCEDURE dorepeat(p1 INT)
-> BEGIN
->   SET @x = 0;
->   REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
-> END
-> |
Query OK, 0 rows affected (0.00 sec)

mysql> CALL dorepeat(1000)|
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x|
+------+
| @x   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)

19-B-12-g - Syntaxe WHILE

[begin_label:] WHILE search_condition DO
statement(s)
END WHILE [end_label]

Les commandes dans l'instruction WHILE sont répétées tant que la condition search_condition est vraie.

begin_label et end_label doivent être identiques, si elles sont spécifiées.

Par exemple :

CREATE PROCEDURE dowhile()
BEGIN
DECLARE v1 INT DEFAULT 5;

WHILE v1 > 0 DO
...
SET v1 = v1 - 1;
END WHILE;
END

20 - Déclencheurs

Le support rudimentaire des déclencheurs (triggers) est inclus dans les versions de MySQL à partir de la version 5.0.2. Un déclencheur est un objet de base de données nommé, qui est associé à une table et qui s'active lorsqu'un événement particulier survient dans une table. Par exemple, les commandes suivantes configurent une table, ainsi qu'un déclencheur pour les commandes INSERT sur cette table. Le déclencheur va effectuer la somme des valeurs insérées dans une des colonnes :

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
-> FOR EACH ROW SET @sum = @sum + NEW.amount;

Ce chapitre décrit la syntaxe pour créer et détruire des déclencheurs, et quelques exemples pour les utiliser.

20-A - Syntaxe de CREATE TRIGGER

CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt

Un déclencheur est un objet de base de données associé à une table, qui s'active lorsqu'un événement particulier survient.

Le déclencheur est associé à la table appelée tbl_name. tbl_name qui doit faire référence à une table permanente. Vous ne pouvez pas associer un déclencheur à une table TEMPORARY ou une vue.

trigger_time est le moment d'action du déclencheur. Il peut être BEFORE (avant) ou AFTER (après), pour indiquer que le déclencheur s'active avant ou après la commande qui le déclenche.

trigger_event indique le type de commande qui active le déclencheur. Il peut valoir INSERT, UPDATE ou DELETE. Par exemple, un déclencheur BEFORE pour une commande INSERT peut être utilisé pour vérifier les valeurs avant leur insertion dans la table.

Il ne peut pas y avoir deux déclencheurs pour une même table avec les mêmes configurations de moment et de commande. Par exemple, vous ne pouvez pas avoir deux déclencheurs BEFORE UPDATE pour la même table. Mais vous pouvez avoir un déclencheur BEFORE UPDATE et un déclencheur BEFORE INSERT, ou un déclencheur BEFORE UPDATE et un déclencheur AFTER UPDATE.

trigger_stmt est la commande à exécuter lorsque le déclencheur s'active. Si vous voulez utiliser plusieurs commandes, utilisez les agrégateurs BEGIN ... END. Cela vous permet aussi d'utiliser les mêmes codes que ceux utilisés dans des procédures stockées. Voir Section 19.2.7 : « La commande composée BEGIN ... END ».

Note : actuellement, les déclencheurs ont les mêmes limitations que les procédures stockées : ils ne peuvent pas contenir de références directes aux tables via leurs noms. Cette limitation sera levée dès que possible.

Cependant, dans la commande d'activation d'un déclencheur, vous pouvez faire référence aux colonnes dan la table associée au déclencheur en utilisant les mots OLD et NEW. OLD.col_name faire référence à une colonne d'une ligne existante avant sa modification ou son effacement. NEW.col_name fait référence à une colonne d'une ligne après insertion ou modification.

L'utilisation de SET NEW.col_name = value requiert le droit de UPDATE sur la colonne. L'utilisation de SET value = NEW.col_name requiert le droit de SELECT sur la colonne.

La commande CREATE TRIGGER requiert le droit de SUPER. Elle a été ajoutée en MySQL 5.0.2.

20-B - Syntaxe de DROP TRIGGER

DROP TRIGGER tbl_name.trigger_name

Supprime un déclencheur. Le nom du déclencheur doit inclure le nom de la table, car chaque déclencheur est associé à une table particulière.

La commande DROP TRIGGER requiert le droit de SUPER. Il a été ajouté en MySQL 5.0.2.

20-C - Utiliser les déclencheurs

Le support des déclencheurs (aussi appelés trigger) a commencé avec MySQL 5.0.2. Actuellement, le support des déclencheurs est rudimentaire, et il existe des limitations dans les fonctionnalités. Cette section présente comment utiliser les déclencheurs et quelles sont leurs limitations actuelles.

Un déclencheur est un objet de base de données qui est associé à une table, et qui s'active lorsqu'un événement spécifié survient dans la table. Il est possible d'utiliser les déclencheurs pour effectuer des vérifications de valeurs avant insertion, ou pour effectuer des calculs de macrodonnées après une modification d'une table.

Un déclencheur est associé à une table, et est défini pour s'activer lorsqu'une commande INSERT, DELETE ou UPDATE s'exécute sur la table. Un déclencheur peut être configuré pour s'activer avant ou après l'événement. Par exemple, déclencheur peut être appelé avant que la ligne soit effacée ou modifié dans la table.

Pour créer un déclencheur ou l'effacer, utilisez les commandes CREATE TRIGGER ou DROP TRIGGER. La syntaxe de ces commandes est décrite dans les sections Section 20.1 : « Syntaxe de CREATE TRIGGER » et Section 20.2 : « Syntaxe de DROP TRIGGER ».

Voici un exemple simple qui associe un déclencheur à une table pour les commandes INSERT. Il sert d'accumulateur des sommes insérées dans une des colonnes de la table.

La commande suivante crée la table et le déclencheur :

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
-> FOR EACH ROW SET @sum = @sum + NEW.amount;

La commande CREATE TRIGGER crée un déclencheur appelé ins_sum qui est associé avec la table account. Il inclut aussi des clauses pour spécifier le moment d'activation, l'événement et l'action du déclencheur :

- le mot réservé BEFORE (avant, en anglais) indique le moment d'activation. Dans ce cas, le déclencheur sera activé avant l'insertion des lignes dans la table. L'autre mot réservé est AFTER (Après, en anglais) ;

- le mot réservé INSERT indique l'événement qui active le déclencheur. Dans l'exemple, le déclencheur s'active lors des commandes INSERT. Vous pouvez créer des déclencheur pour les commandes DELETE et UPDATE ;

- la commande qui suit le mot clé FOR EACH ROW définit la commande à exécuter à chaque fois que le déclencheur s'active, ce qui arrive dès qu'une ligne est insérée. Dans l'exemple, la commande du déclencheur est un simple SET qui accumule la somme des valeurs insérées dans les colonnes amount. La commande utilise la valeur de la colonne avec la syntaxe NEW.amount (en anglais, nouvelle.montant) ce qui signifie « la valeur de la colonne amount qui va être insérée ».

Pour utiliser le déclencheur, initialisez l'accumulateur à zéro, puis exécutez une commande INSERT et voyez la valeur finale de l'accumulateur :

mysql> SET @sum = 0;
mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql> SELECT @sum AS 'Total amount inserted';
+-----------------------+
| Total amount inserted |
+-----------------------+
| 1852.48               |
+-----------------------+

Dans ce cas, la valeur de @sum après la commande INSERT est 14.98 + 1937.50 - 100 soit 1852.48.

Pour détruire un déclencheur, utilisez la commande DROP TRIGGER. Le nom du déclencheur doit inclure le nom de la table :

mysql> DROP TRIGGER account.ins_sum;

Comme le déclencheur est associé à une table, vous ne pouvez pas avoir plusieurs déclencheurs sur une même table qui portent le même nom. Soyez aussi conscients que l'espace de noms des déclencheurs risque de changer à l'avenir. C'est-à-dire que l'unicité des noms de déclencheurs par table risque d'être étendue à l'unicité de déclencheurs au niveau du serveur. Pour faciliter la compatibilité ascendante, essayez d'utiliser des noms de déclencheurs qui soient uniques dans toute la base.

En plus du fait que les noms de déclencheurs doivent être uniques pour une table, il y a d'autres limitations sur le type de déclencheurs que vous pouvez mettre en place. En particulier, vous ne pouvez pas avoir deux déclencheurs qui ont le même moment d'activation et le même événement d'activation. Par exemple, vous ne pouvez pas définir deux déclencheurs BEFORE INSERT et deux déclencheurs AFTER UPDATE pour la même table. Ce n'est probablement pas une limitation importante, car il est possible de définir un déclencheur qui exécute plusieurs commandes en utilisant une commande complexe, encadrée par les mots BEGIN ... END, après le mot clé FOR EACH ROW. Un exemple vous est présenté ultérieurement dans cette section.

Il y a aussi des limitations dans ce qui peut apparaître dans la commande que le déclencheur peut exécuter lorsqu'il est activé :

- le déclencheur ne peut pas faire référence directe aux tables par leur nom, y compris la table à laquelle il est associé. Par contre, vous pouvez utiliser les mots clés OLD (ancien en anglais) et NEW (nouveau en anglais). OLD fait référence à la ligne existante avant la modification ou l'effacement. NEW faire référence à la nouvelle ligne insérée ou à la ligne modifiée ;

- le déclencheur ne peut pas exécuter de procédures avec la commande CALL. Cela signifie que vous ne pouvez pas contourner le problèmes des noms de tables en appelant une procédure stockée qui utilise les noms de tables ;

- le déclencheur ne peut pas utiliser de commande qui ouvre ou ferme une transaction avec START TRANSACTION, COMMIT ou ROLLBACK.

Les mots clé OLD et NEW vous permette d'accéder aux colonnes dans les lignes affectées par le déclencheur. OLD et NEW ne sont pas sensibles à la casse. Dans un déclencheur INSERT, seul NEW.col_name peut être utilisée : il n'y a pas d'ancienne ligne. Dans un déclencheur DELETE, seule la valeur OLD.col_name peut être utilisée : il n'y a pas de nouvelle ligne. Dans un déclencheur UPDATE, vous pouvez utiliser OLD.col_name pour faire référence aux colonnes dans leur état avant la modification, et NEW.col_name pour faire référence à la valeur après la modification.

Une colonne identifiée par OLD est en lecture seule. Vous pouvez lire sa valeur, mais vous ne pouvez pas la modifier. Une colonne identifiée avec la valeur NEW peut être lue si vous avez les droits de SELECT dessus. Dans un déclencheur BEFORE, vous pouvez aussi changer la valeur avec la commande SET NEW.col_name = value si vous avez les droits de UPDATE. Cela signifie que vous pouvez utiliser un déclencheur pour modifier les valeurs insérées dans une nouvelle ligne ou les valeurs modifiées.

Dans un déclencheur BEFORE, la valeur NEW d'une colonne AUTO_INCREMENT vaut 0, et non pas le nombre séquentiel automatiquement généré, car ce nombre sera généré lorsque la ligne sera réellement insérée.

OLD et NEW sont des extensions de MySQL aux déclencheurs.

En utilisant la syntaxe BEGIN ... END, vous pouvez définir un déclencheur qui exécute plusieurs commandes. À l'intérieur d'un bloc BEGIN, vous pouvez aussi utiliser les autres syntaxes autorisées dans les routines stockées, telles que les conditions et les boucles. Cependant, tout comme pour les procédures stockées, lorsque vous définissez un déclencheur qui s'exécute sur plusieurs commandes, il est nécessaire de redéfinir le délimiteur de commandes si vous saisissez le déclencheur en ligne de commande tel que mysql pour que vous puissiez utiliser le caractère ';' à l'intérieur de la définition. L'exemple ci-dessous illustre ces points. Il définit un déclencheur UPDATE qui vérifie la valeur d'une ligne avant sa modification, et s'arrange pour que les valeurs soient dans l'intervalle de 0 à 100. Cela doit être fait avant (BEFORE) la modification, pour que la valeur soit vérifiée avant d'être utilisée :

mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
-> FOR EACH ROW
-> BEGIN
->     IF NEW.amount < 0 THEN
->         SET NEW.amount = 0;
->     ELSEIF NEW.amount > 100 THEN
->         SET NEW.amount = 100;
->     END IF;
-> END//
mysql> delimiter ;

Il vous viendra sûrement à l'esprit qu'il serait plus facile de définir une procédure stockée séparément, pour l'invoquer depuis le déclencheur grâce à un simple appel à CALL. Cela serait sûrement avantageux si vous voulez appeler la même routine depuis plusieurs déclencheurs. Cependant, les déclencheurs ne peuvent pas utiliser la commande CALL. Vous devez absolument réécrire les commandes composées de chaque commande CREATE TRIGGER que vous voulez utiliser.

21 - Vues

Les vues (y compris les vues modifiables) sont implémentées dans la version 5 de MySQL. Les vues sont disponibles dans les versions binaires depuis la version 5.0.1 et plus récentes.

Ce chapitre présente les sujets suivants :

- création ou modification de vues avec les commandes CREATE VIEW ou ALTER VIEW ;

- destruction de vues avec DROP VIEW ;

- affichage des métadonnées de vues avec SHOW CREATE VIEW.

Pour utiliser les vues, lorsque vous êtes passés en version 5.0.1 depuis une ancienne version, il faut mettre à jour la table de droits, car elle contient des informations destinées aux vues. Voir Section 2.6.7 : « Mise à jour des tables de droits ».

21-A - Syntaxe ALTER VIEW

ALTER VIEW view_name [(column_list)] AS select_statement

Cette commande modifie la définition d'une vue. La clause select_statement est identique à CREATE VIEW. Voir Section 21.2 : « Syntaxe de CREATE VIEW ».

Cette commande a été ajoutée dans MySQL 5.0.1.

21-B - Syntaxe de CREATE VIEW

CREATE [OR REPLACE] [ALGORITHM = {MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]

Cette commande crée une nouvelle vue, ou remplace une vue existante si la clause OR REPLACE est fournie. La clause select_statement est une commande SELECT qui fournit la définition de la vue. La liste optionnelle de colonnes peut être fournie pour définir explicitement les noms des colonnes.

WITH CHECK OPTION, si utilisées, sont analysées, mais ignorées.

Une vue peut être créée par différents types de commandes SELECT. Par exemple, SELECT peut faire référence à une table seule, une jointure ou une UNION. La commande SELECT peut ne pas faire de référence à une table. Les exemples suivants définissent une vue qui sélectionne deux colonnes dans une table, et leur applique une transformation :

mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+------+-------+-------+
| qty  | price | value |
+------+-------+-------+
|    3 |    50 |   150 |
+------+-------+-------+

Par défaut, la vue est placée dans la base de données par défaut. Pour créer une vue explicitement dans une base de données, spécifiez le nom de la base de données lors de la création : db_name.view_name.

mysql> CREATE VIEW test.v AS SELECT * FROM t;

Cette commande a été ajoutée dans MySQL 5.0.1.

21-C - Syntaxe DROP VIEW

DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]

DROP VIEW supprime une ou plusieurs vues. Vous devez avoir les droits de DROP pour chaque vue.

Vous pouvez utiliser le mot clé IF EXISTS pour éviter l'affichage d'un message d'alerte lorsque les vues n'existent pas. Lorsque cette clause est utilisée, une NOTE est générée pour chaque vue inexistante. Voir Section 13.5.3.19 : « SHOW WARNINGS | ERRORS ».

RESTRICT et CASCADE, si utilisées, sont analysées, mais ignorées.

Cette commande a été ajoutée dans MySQL 5.0.1.

21-D - Syntaxe SHOW CREATE VIEW

SHOW CREATE VIEW view_name

Cette commande montre la commande CREATE VIEW qui créera la vue spécifiée.

mysql> SHOW CREATE VIEW v;
+-------+----------------------------------------------------+
| Table | Create Table                                       |
+-------+----------------------------------------------------+
| v     | CREATE VIEW `test`.`v` AS select 1 AS `a`,2 AS `b` |
+-------+----------------------------------------------------+

Cette commande a été ajoutée dans MySQL 5.0.1.

22 - La base de données d'informations INFORMATION_SCHEMA

Le support de la base INFORMATION_SCHEMA est disponible dans MySQL 5.0.2 et les versions les plus récentes. Il fournit un accès aux métadonnées sur les bases de données.

Les « métadonnées » sont des informations sur les données, telles que le nom des bases de données, des tables, le type de données des colonnes ou les droits d'accès. On appelle aussi ces données le « dictionnaire de données » ou le « catalogue système ».

Voici un exemple :

mysql> SELECT table_name, table_type, engine
-> FROM information_schema.tables
-> WHERE table_schema = 'db5'
-> ORDER BY table_name DESC;
+------------+------------+--------+
| table_name | table_type | engine |
+------------+------------+--------+
| v56        | VIEW       | NULL   |
| v3         | VIEW       | NULL   |
| v2         | VIEW       | NULL   |
| v          | VIEW       | NULL   |
| tables     | BASE TABLE | MyISAM |
| t7         | BASE TABLE | MyISAM |
| t3         | BASE TABLE | MyISAM |
| t2         | BASE TABLE | MyISAM |
| t          | BASE TABLE | MyISAM |
| pk         | BASE TABLE | InnoDB |
| loop       | BASE TABLE | MyISAM |
| kurs       | BASE TABLE | MyISAM |
| k          | BASE TABLE | MyISAM |
| into       | BASE TABLE | MyISAM |
| goto       | BASE TABLE | MyISAM |
| fk2        | BASE TABLE | InnoDB |
| fk         | BASE TABLE | InnoDB |
+------------+------------+--------+
17 rows in set (0.01 sec)

Explication : la commande requiert la liste de toutes les tables de la base de données db5, en ordre anti-alphabétique, avec trois informations : le nom de la table, son type et le moteur de table.

INFORMATION_SCHEMA est la « base de données d'informations », la base qui stocke les informations à propos des autres bases que le serveur MySQL entretient. Dans INFORMATION_SCHEMA, il existe plusieurs tables en lecture seule. Ce sont en fait des vues, et non pas des tables, ce qui fait que vous ne verrez pas de fichiers associés.

Chaque utilisateur MySQL a le droit d'accéder à ces tables, mais seules les lignes concernant des objets pour lesquels il a des droits seront visibles.

Avantages de SELECT

La commande SELECT ... FROM INFORMATION_SCHEMA a pour but d'être une méthode cohérente d'accéder aux informations fournies par les différentes commandes SHOW que MySQL supporte (SHOW DATABASES, SHOW TABLES, etc.). En utilisant SELECT, vous avez plusieurs avantages comparés à SHOW :

- il est conforme aux règles de Codd. C'est-à-dire que tous les accès sont faits sur des tables ;

- personne n'a besoin d'apprendre une nouvelle syntaxe. Comme tout le monde connaît déjà les commandes SELECT, il suffit d'apprendre les noms des objets ;

- l'implémenteur n'a pas besoin d'ajouter de nouveaux mots-clés ;

- il y a des millions de formats de résultats possibles, au lieu d'un seul. Cela apporte de la flexibilité aux applications qui ont des spécifications variables sur les métadonnées qu'elles recherchent ;

- la migration est plus facile, car toutes les autres bases de données fonctionnent sur ce schéma.

Cependant, comme SHOW est une commande populaire auprès des employés et utilisateurs de MySQL, et que cela mettrait la pagaille si cette dernière venait à disparaître, les avantages de cette convention ne sont pas suffisants pour supprimer SHOW. En fait, il y a des améliorations à la commande SHOW en MySQL 5.0. Elles sont présentées dans la section Section 22.2 : « Extensions à la commande SHOW ».

Standards

L'implémentation des structures des tables de la base INFORMATION_SCHEMA suit le standard ANSI/ISO SQL:2003 standard Part 11 « Schemata ». Notre intention est d'atteindre une compatibilité partielle avec SQL:2003 core feature F021 « Basic information schema ».

Les utilisateurs de SQL Server 2000 (qui suit aussi ce standard) noteront une similarité importante. Cependant, MySQL a omis certaines colonnes qui ne sont pas pertinentes dans notre implémentation, et a ajouté des colonnes qui lui sont spécifiques. Par exemple, la colonne du moteur de stockage pour les tables dans la table INFORMATION_SCHEMA.TABLES.

Même si les autres serveurs de base de données utilisent différents noms, comme syscat ou system, le nom standard est INFORMATION_SCHEMA.

En effet, nous avons une nouvelle « base de données » appelée information_schema, même s'il n'y a pas besoin de faire un fichier qui porte ce nom. Il est possible de sélectionner la base INFORMATION_SCHEMA comme base par défaut avec la commande USE, mais la seule solution pour accéder au contenu de ces tables est la commande SELECT. Vous ne pouvez pas insérer des données ou modifier le contenu des tables.

Droits

Il n'y a pas de différence entre les prérequis de droits actuels pour la commande SHOW et les commandes SELECT. Dans chaque cas, vous avez les mêmes droits sur un objet, et vous en aurez besoin pour accéder aux informations le concernant.

22-A - Les tables INFORMATION_SCHEMA

Présentation des sections suivantes

Dans les prochaines sections, nous allons détailler les tables et colonnes de INFORMATION_SCHEMA. Pour chaque colonne, on présente deux informations :

- le « Nom standard » indique le nom standard SQL de la colonne ;

- Le « Nom SHOW » indique son équivalent dans le résultat de la commande SHOW, s'il existe ;

- « Remarques » fournit des informations supplémentaires, éventuellement. Nous avons marqué avec « omis » les colonnes dont MySQL ne fait aucun usage pour le moment. Nous avons omis ces colonnes : elles apparaissent dans les standards, mais pas dans MySQL. Leur présence est donc inutile ici.

Pour éviter d'utiliser des mots qui soient réservés par le standard, par DB2, par SQL server ou Oracle, nous avons changé le nom des colonnes qui portent la mention « extension MySQL ». Par exemple, nous avons changé COLLATION en TABLE_COLLATION dans la table TABLES. Voyez la liste des mots à la fin de cet article : http://www.dbazine.com/gulutzan5.shtml.

La définition des colonnes, comme TABLES.TABLE_NAME), est généralement VARCHAR(N) CHARACTER SET utf8 où N vaut au moins 64.

Chaque section indique l'équivalent dans le résultat de la commande SHOW : c'est un équivalent à la commande SELECT qui lit les informations dans la table INFORMATION_SCHEMA, ou bien il n'y a pas d'équivalent.

Note : à l'heure actuelle, il manque des colonnes et certaines autres sont sans objets. Nous travaillons dessus et nous mettrons à jour la documentation lorsque ces modifications seront faites.

22-A-1 - La table INFORMATION_SCHEMA SCHEMATA

Un schéma est une base de données. La table SCHEMATA fournit des informations sur les bases de données.

Standard Name

SHOW name

Remarks

CATALOG_NAME

-

NULL

SCHEMA_NAME

base de données

SCHEMA_OWNER

omis

DEFAULT_CHARACTER_SET_CATALOG

omis

DEFAULT_CHARACTER_SET_SCHEMA

omis

DEFAULT_CHARACTER_SET_NAME

SQL_PATH

NULL

Notes :

- pour SQL_PATH, nous aurons peut-être quelque chose de fonctionnelle en MySQL 5.x. Pour le moment, il vaut toujours NULL.

Les commandes suivantes sont équivalentes :

SELECT SCHEMA_NAME AS `Database`
FROM INFORMATION_SCHEMA.SCHEMATA
[WHERE SCHEMA_NAME LIKE 'wild']

SHOW DATABASES
[LIKE 'wild']

22-A-2 - La table INFORMATION_SCHEMA TABLES

La table TABLES fournit des informations sur les bases de données.

Nom standard

Nom SHOW

Remarques

TABLE_CATALOG

NULL

TABLE_SCHEMA

Table_...

TABLE_NAME

Table_...

TABLE_TYPE

SELF_REFERENCING_COLUMN_NAME

omis

REFERENCE_GENERATION

omis

USER_DEFINED_TYPE_NAME

omis

IS_INSERTABLE_INTO

omis

IS_TYPED

omis

COMMIT_ACTION

omis

ENGINE

Engine

extension MySQL

VERSION

Version

extension MySQL

ROW_FORMAT

Row_format

extension MySQL

TABLE_ROWS

Rows

extension MySQL

AVG_ROW_LENGTH

Avg_row_length

extension MySQL

DATA_LENGTH

Data_length

extension MySQL

MAX_DATA_LENGTH

Max_data_length

extension MySQL

INDEX_LENGTH

Index_length

extension MySQL

DATA_FREE

Data_free

extension MySQL

AUTO_INCREMENT

Auto_increment

extension MySQL

CREATE_TIME

Create_time

extension MySQL

UPDATE_TIME

Update_time

extension MySQL

CHECK_TIME

Check_time

extension MySQL

TABLE_COLLATION

Collation

extension MySQL

CHECKSUM

Checksum

extension MySQL

CREATE_OPTIONS

Create_options

extension MySQL

TABLE_COMMENT

Comment

extension MySQL

Notes :

- TABLE_SCHEMA et TABLE_NAME sont un seul champ dans le résultat de SHOW, par exemple Table_in_db1 ;

- TABLE_TYPE doit être BASE TABLE ou VIEW. Si la table est temporaire, alors TABLE_TYPE = TEMPORARY. Il n'y a pas de vues temporaires, alors il ne peut pas y avoir d'ambiguïté ;

- nous n'avons rien pour les jeux de caractères par défaut des tables. TABLE_COLLATION s'en approche, car les noms des collations commencent avec un nom de jeu de caractères.

Les commandes suivantes sont équivalentes :

SELECT table_name FROM INFORMATION_SCHEMA.TABLES
[WHERE table_schema = 'db_name']
[WHERE|AND table_name LIKE 'wild']

SHOW TABLES
[FROM db_name]
[LIKE 'wild']

22-A-3 - La table INFORMATION_SCHEMA COLUMNS

La table COLUMNS fournit des informations sur les colonnes dans les tables.

Nom standard

Nom dans SHOW

Remarques

TABLE_CATALOG

NULL

TABLE_SCHEMA

TABLE_NAME

COLUMN_NAME

Field

ORDINAL_POSITION

see notes

COLUMN_DEFAULT

Default

IS_NULLABLE

Null

DATA_TYPE

Type

CHARACTER_MAXIMUM_LENGTH

Type

CHARACTER_OCTET_LENGTH

NUMERIC_PRECISION

Type

NUMERIC_PRECISION_RADIX

omis

NUMERIC_SCALE

Type

DATETIME_PRECISION

omis

INTERVAL_TYPE

omis

INTERVAL_PRECISION

omis

CHARACTER_SET_CATALOG

omis

CHARACTER_SET_SCHEMA

omis

CHARACTER_SET_NAME

COLLATION_CATALOG

omis

COLLATION_SCHEMA

omis

COLLATION_NAME

Collation

DOMAIN_NAME

omis

UDT_CATALOG

omis

UDT_SCHEMA

omis

UDT_NAME

omis

SCOPE_CATALOG

omis

SCOPE_SCHEMA

omis

SCOPE_NAME

omis

MAXIMUM_CARDINALITY

omis

DTD_IDENTIFIER

omis

IS_SELF_REFERENCING

omis

IS_IDENTITY

omis

IDENTITY_GENERATION

omis

IDENTITY_START

omis

IDENTITY_INCREMENT

omis

IDENTITY_MAXIMUM

omis

IDENTITY_MINIMUM

omis

IDENTITY_CYCLE

omis

IS_GENERATED

omis

GENERATION_EXPRESSION

omis

COLUMN_KEY

Key

extension MySQL

EXTRA

Extra

extension MySQL

COLUMN_COMMENT

Comment

extension MySQL

Notes :

- dans SHOW, la colonne Type inclut les valeurs de différentes colonnes COLUMNS ;

- ORDINAL_POSITION est obligatoire, car il faudra peut-être un jour indiquer ORDER BY ORDINAL_POSITION. Contrairement à SHOW, SELECT n'a pas de classement par défaut ;

- CHARACTER_OCTET_LENGTH doit être le même que CHARACTER_MAXIMUM_LENGTH, sauf pour les jeux de caractères multi-octets ;

- CHARACTER_SET_NAME peut être dérivé de Collation. Par exemple, si vous indiquez SHOW FULL COLUMNS FROM t, et que vous pouvez voir dans la colonne Collation la valeur latin1_swedish_ci, alors le jeu de caractères est la partie placée avant le premier caractère souligné : latin1.

Les commandes suivantes sont presque équivalentes :

SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
[AND table_schema = 'db_name']
[AND column_name LIKE 'wild']

SHOW COLUMNS
FROM tbl_name
[FROM db_name]
[LIKE wild]

22-A-4 - La table INFORMATION_SCHEMA STATISTICS

La table STATISTICS fournit des informations sur les tables d'index.

Nom standard

Nom SHOW

Remarques

TABLE_CATALOG

NULL

TABLE_SCHEMA

= Database

TABLE_NAME

Table

NON_UNIQUE

Non_unique

INDEX_SCHEMA

= Database

INDEX_NAME

Key_name

TYPE

omis

SEQ_IN_INDEX

Seq_in_index

COLUMN_NAME

Column_name

COLLATION

Collation

CARDINALITY

Cardinality

PAGES

omis

FILTER_CONDITION

omis

SUB_PART

Sub_part

extension MySQL

PACKED

Packed

extension MySQL

NULLABLE

Null

extension MySQL

INDEX_TYPE

Index_type

extension MySQL

COMMENT

Comment

extension MySQL

Notes :

- il n'y a pas de table standard pour les index. La liste précédente est similaire au résultat que retourne SQL Server 2000 pour sp_statistics, mais nous avons remplacé le nom QUALIFIER par CATALOG et nous avons remplacé le nom OWNER par SCHEMA.
En fait, la table précédente et le résultat de SHOW INDEX sont dérivés du même parent. La corrélation est très bonne.

Les commandes suivantes sont équivalentes :

SELECT * FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_name = 'tbl_name'
[AND schema_name = 'db_name'

SHOW INDEX
FROM tbl_name
[FROM db_name]

22-A-5 - La table INFORMATION_SCHEMA USER_PRIVILEGES

La table USER_PRIVILEGES fournit les informations sur les droits globaux. Cette information provient des tables mysql.user.

Non standard

Nom SHOW

Remarques

GRANTEE

i.e. 'utilisateur'@'hote'

TABLE_CATALOG

NULL

PRIVILEGE_TYPE

IS_GRANTABLE

Notes :

- c'est une table non standard. Elle prend ses valeurs dans les tables mysql.user.

22-A-6 - La table INFORMATION_SCHEMA SCHEMA_PRIVILEGES

La table SCHEMA_PRIVILEGES fournit des informations sur les droits des schémas (l'autre nom des bases de données). Ces informations proviennent de la table mysql.db.

Nom standard

Nom SHOW

Remarques

GRANTEE

i.e.g. 'utilisateur'@'hote'

TABLE_CATALOG

NULL

TABLE_SCHEMA

PRIVILEGE_TYPE

IS_GRANTABLE

Notes :

- ceci est une table non standard. Elle prend ses valeurs dans la table mysql.db.

22-A-7 - La table INFORMATION_SCHEMA TABLE_PRIVILEGES

La table TABLE_PRIVILEGES affiche les informations sur les droits des tables. Ces informations proviennent de mysql.tables_priv.

Nom standard

Nom SHOW

Remarques

GRANTOR

omis

GRANTEE

i.e. 'utilisateur'@'hote'

TABLE_CATALOG

NULL

TABLE_SCHEMA

TABLE_NAME

PRIVILEGE_TYPE

IS_GRANTABLE

WITH_HIERARCHY

omit

Les requêtes suivantes ne sont pas équivalentes :

SELECT ... FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES

SHOW GRANTS ...

PRIVILEGE_TYPE peut contenir l'une des valeurs suivantes : SELECT, INSERT, UPDATE, REFERENCES, ALTER, INDEX, DROP et CREATE VIEW.

22-A-8 - La table INFORMATION_SCHEMA COLUMN_PRIVILEGES

La table COLUMN_PRIVILEGES fournit les informations sur les droits reliés aux colonnes. Ces informations proviennent de la table de droits mysql.columns_priv.

Nom standard

Nom SHOW

Remarques

GRANTOR

omis

GRANTEE

e.g. 'utilisateur'@'hote'

TABLE_CATALOG

NULL

TABLE_SCHEMA

TABLE_NAME

COLUMN_NAME

PRIVILEGE_TYPE

IS_GRANTABLE

Notes :

- dans le résultat de SHOW FULL COLUMNS, les droits sont toujours affichés dans un champ, en minuscules, comme select, insert, update, references. Dans COLUMN_PRIVILEGES, il y a une ligne par droit, et la valeur est en majuscules ;

- PRIVILEGE_TYPE peut contenir une et une seule de ces valeurs : SELECT, INSERT, UPDATE, REFERENCES ;

- si l'utilisateur a le droit de GRANT OPTION, le droit IS_GRANTABLE doit valoir YES. Sinon, IS_GRANTABLE doit valoir NO. Le résultat ne présente pas GRANT OPTION comme un droit séparé.

Les commandes suivantes ne sont pas équivalentes :

SELECT ... FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES

SHOW GRANTS ...

22-A-9 - La table INFORMATION_SCHEMA CHARACTER_SETS

La table CHARACTER_SETS fournit des informations sur les jeux de caractères disponibles.

Nom standard

Nom SHOW

Remarques

CHARACTER_SET_CATALOG

omis

CHARACTER_SET_SCHEMA

omis

CHARACTER_SET_NAME

Charset

CHARACTER_REPERTOIRE

omis

FORM_OF_USE

omis

NUMBER_OF_CHARACTERS

omis

DEFAULT_COLLATE_CATALOG

omis

DEFAULT_COLLATE_SCHEMA

omis

DEFAULT_COLLATE_NAME

Default collation

DESCRIPION

Description

Extension MySQL

MAXLEN

Maxlen

Extension MySQL

Notes :

- nous avons ajouté deux colonnes non standards que sont Description et Maxlen, dans la commande SHOW CHARACTER SET.

Les commandes suivantes sont équivalentes :

SELECT * FROM INFORMATION_SCHEMA.CHARACTER_SETS
[WHERE name LIKE 'wild']

SHOW CHARACTER SET
[LIKE 'wild']

22-A-10 - La table INFORMATION_SCHEMA COLLATIONS

La table COLLATIONS fournit des informations sur les collations de chaque jeu de caractères.

Nom standard

Nom SHOW

Remarques

COLLATION_CATALOG

omis

COLLATION_SCHEMA

omis

COLLATION_NAME

Collation

PAD_ATTRIBUTE

omis

COLLATION_TYPE

omis

COLLATION_DEFINITION

omis

COLLATION_DICTIONARY

omis

CHARACTER_SET_NAME

omis ; extension de MySQL

ID

omis ; extension de MySQL

IS_DEFAULT

omis ; extension de MySQL

IS_COMPILED

omis ; extension de MySQL

SORTLEN

omis ; extension de MySQL

Notes :

- nous avons ajouté cinq colonnes non standards qui correspondent au Charset, Id, Default, Compiled et Sortlen dans le résultat de SHOW COLLATION.

Les commandes suivantes sont équivalentes :

SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS
[WHERE collation_name LIKE 'wild']

SHOW COLLATION
[LIKE 'wild']

22-A-11 - La table INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY

La table COLLATION_CHARACTER_SET_APPLICABILITY indique les jeux de caractères et les collations associées. Les colonnes sont équivalentes aux deux premières colonnes du résultat de la commande SHOW COLLATION.

Nom standard

Nom SHOW

Remarques

COLLATION_CATALOG

omis

COLLATION_SCHEMA

omis

COLLATION_NAME

Collation

CHARACTER_SET_CATALOG

omis

CHARACTER_SET_SCHEMA

omis

CHARACTER_SET_NAME

Charset

22-A-12 - La table INFORMATION_SCHEMA TABLE_CONSTRAINTS

La table TABLE_CONSTRAINTS décrit les tables qui ont des contraintes.

Nom standard

Nom SHOW

Remarques

CONSTRAINT_CATALOG

NULL

CONSTRAINT_SCHEMA

CONSTRAINT_NAME

TABLE_CATALOG

omis

TABLE_SCHEMA

TABLE_NAME

CONSTRAINT_TYPE

IS_DEFERRABLE

omis

INITIALLY_DEFERRED

omis

Notes :

- la valeur CONSTRAINT_TYPE peut être UNIQUE, PRIMARY KEY ou FOREIGN KEY ;

- les informations de UNIQUE et PRIMARY KEY sont les mêmes que celles que vous obtenez dans le champ Key_name du résultat de SHOW INDEX où le champ Non_unique vaut 0 ;

- la colonne CONSTRAINT_TYPE peut contenir l'une de ces valeurs : UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK. C'est une colonne de type CHAR et non pas ENUM. La valeur de CHECK n'est pas valable jusqu'à ce que nous supportions CHECK.

22-A-13 - La table INFORMATION_SCHEMA KEY_COLUMN_USAGE

La table KEY_COLUMN_USAGE décrit les contraintes sur les colonnes.

Nom standard

Nom SHOW

Remarques

CONSTRAINT_CATALOG

NULL

CONSTRAINT_SCHEMA

CONSTRAINT_NAME

TABLE_CATALOG

TABLE_SCHEMA

TABLE_NAME

COLUMN_NAME

ORDINAL_POSITION

POSITION_IN_UNIQUE_CONSTRAINT

Notes :

- si la contrainte est une clé étrangère, alors c'est la colonne de la clé étrangère, et non pas la colonne que la clé étrangère référence ;

- la valeur de ORDINAL_POSITION est la position de la colonne dans la contrainte, et non pas la position de la colonne dans la table. Les positions des colonnes commencent à 1 ;

- la valeur de POSITION_IN_UNIQUE_CONSTRAINT est NULL pour les contraintes uniques et les clés primaires. Pour les contraintes de clé étrangère, c'est la position ordinale dans la clé de la table qui est référencée.
Par exemple, supposez que vous ayez les deux tables t1 et t3, avec les définitions suivantes :

CREATE TABLE t1
(
s1 INT,
s2 INT,
s3 INT,
PRIMARY KEY(s3)
) ENGINE=InnoDB;

CREATE TABLE t3
(
s1 INT,
s2 INT,
s3 INT,
KEY(s1),
CONSTRAINT CO FOREIGN KEY (s2) REFERENCES t1(s3)
) ENGINE=InnoDB;

Pour ces deux tables, la table KEY_COLUMN_USAGE a deux lignes :

- une ligne avec CONSTRAINT_NAME='PRIMARY', TABLE_NAME='t1', COLUMN_NAME='s3', ORDINAL_POSITION=1, POSITION_IN_UNIQUE_CONSTRAINT=NULL ;

- une ligne avec CONSTRAINT_NAME='CO', TABLE_NAME='t3', COLUMN_NAME='s2', ORDINAL_POSITION=1, POSITION_IN_UNIQUE_CONSTRAINT=1.

22-A-14 - La table INFORMATION_SCHEMA ROUTINES

La table ROUTINES fournit des informations sur les procédures stockées (sur les procédures et les fonctions). La table ROUTINES n'inclut pas les fonctions utilisateurs (dites UDF) actuellement.

La colonne appelée « mysql.proc name » indique la colonne de la table mysql.proc qui correspond à la colonne de la table INFORMATION_SCHEMA.ROUTINES, si elle existe.

Nom standard

Nom mysql.proc

Remarques

SPECIFIC_CATALOG

omis

SPECIFIC_SCHEMA

db

omis

SPECIFIC_NAME

specific_name

ROUTINE_CATALOG

NULL

ROUTINE_SCHEMA

db

ROUTINE_NAME

name

MODULE_CATALOG

omis

MODULE_SCHEMA

omis

MODULE_NAME

omis

USER_DEFINED_TYPE_CATALOG

omis

USER_DEFINED_TYPE_SCHEMA

omis

USER_DEFINED_TYPE_NAME

omis

ROUTINE_TYPE

type

{PROCEDURE|FUNCTION}

DTD_IDENTIFIER

(data type descriptor)

ROUTINE_BODY

SQL

ROUTINE_DEFINITION

body

EXTERNAL_NAME

NULL

EXTERNAL_LANGUAGE

language

NULL

PARAMETER_STYLE

SQL

IS_DETERMINISTIC

is_deterministic

SQL_DATA_ACCESS

sql_data_access

IS_NULL_CALL

omis

SQL_PATH

NULL

SCHEMA_LEVEL_ROUTINE

omis

MAX_DYNAMIC_RESULT_SETS

omis

IS_USER_DEFINED_CAST

omis

IS_IMPLICITLY_INVOCABLE

omis

SECURITY_TYPE

security_type

TO_SQL_SPECIFIC_CATALOG

omis

TO_SQL_SPECIFIC_SCHEMA

omis

TO_SQL_SPECIFIC_NAME

omis

AS_LOCATOR

omis

CREATED

created

LAST_ALTERED

modified

NEW_SAVEPOINT_LEVEL

omis

IS_UDT_DEPENDENT

omis

RESULT_CAST_FROM_DTD_IDENTIFIER

omis

RESULT_CAST_AS_LOCATOR

omis

SQL_MODE

sql_mode

extension MySQL

ROUTINE_COMMENT

comment

extension MySQL

DEFINER

definer

extension MySQL

Notes :

- MySQL calcule EXTERNAL_LANGUAGE comme suit :

- si mysql.proc.language='SQL', alors EXTERNAL_LANGUAGE vaut NULL ;

- sinon, EXTERNAL_LANGUAGE prend la valeur de mysql.proc.language. Cependant, nous n'avons pas de langage externe pour le moment, ce qui fait que cette valeur est toujours NULL.

22-A-15 - La table INFORMATION_SCHEMA VIEWS

La table VIEWS fournit des informations sur les vues dans les bases.

Nom standard

SHOW

Remarques

TABLE_CATALOG

NULL

TABLE_SCHEMA

TABLE_NAME

VIEW_DEFINITION

CHECK_OPTION

IS_UPDATABLE

INSERTABLE_INTO

omis

Notes :

- il existe un nouveau droit, SHOW VIEW, sans lequel vous ne pourrez pas voir la table VIEWS ;

- la colonne VIEW_DEFINITION contient l'essentiel de ce que vous voyez dans le champ Create Table que la commande SHOW CREATE VIEW produit. Omettez les mots avant SELECT et omettez les mots après WITH CHECK OPTION. Par exemple, si la commande initiale était :

CREATE VIEW v AS
SELECT s2,s1 FROM t
WHERE s1 > 5
ORDER BY s1
WITH CHECK OPTION;

alors la définition de la vue serait:

SELECT s2,s1 FROM t WHERE s1 > 5 ORDER BY s1

- la colonne CHECK_OPTION contient toujours la valeur NONE ;

- la colonne IS_UPDATABLE vaut YES si la vue est modifiable, et NO dans le cas contraire.

22-A-16 - Autres tables INFORMATION_SCHEMA

Nous allons ajouter d'autres tables dans la base INFORMATION_SCHEMA prochainement. Notamment, nous avons identifié le besoin de tables telles que INFORMATION_SCHEMA.PARAMETERS, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS et INFORMATION_SCHEMA.TRIGGERS.

22-B - Extensions à la commande SHOW

Plusieurs extensions de la commande SHOW accompagnent l'implémentation de la base INFORMATION_SCHEMA :

- SHOW peut être utilisé pour lire des informations sur la structure de la base INFORMATION_SCHEMA elle-même ;

- plusieurs commandes SHOW acceptent une clause WHERE qui fournit plus de souplesse pour spécifier les lignes à afficher.

Ces extensions sont disponibles depuis MySQL 5.0.3.

INFORMATION_SCHEMA est une base de données d'informations, ce qui fait que son nom est inclus dans le résultat de SHOW DATABASES. Similairement, SHOW TABLES peut servir avec INFORMATION_SCHEMA pour lire la liste des tables disponibles :

mysql> SHOW TABLES FROM INFORMATION_SCHEMA;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| SCHEMATA                              |
| TABLES                                |
| COLUMNS                               |
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| ROUTINES                              |
| STATISTICS                            |
| VIEWS                                 |
| USER_PRIVILEGES                       |
| SCHEMA_PRIVILEGES                     |
| TABLE_PRIVILEGES                      |
| COLUMN_PRIVILEGES                     |
| TABLE_CONSTRAINTS                     |
| KEY_COLUMN_USAGE                      |
+---------------------------------------+

SHOW COLUMNS et DESCRIBE peuvent afficher des informations à propos des colonnes des tables INFORMATION_SCHEMA.

Plusieurs commandes SHOW ont été étendues avec la clause WHERE :

SHOW CHARACTER SET
SHOW COLLATION
SHOW COLUMNS
SHOW DATABASES
SHOW FUNCTION STATUS
SHOW KEYS
SHOW OPEN TABLES
SHOW PROCEDURE STATUS
SHOW STATUS
SHOW TABLE STATUS
SHOW TABLES
SHOW VARIABLES

La clause WHERE, lorsqu'elle est disponible, utilise le nom des colonnes de l'affichage de la commande SHOW. Par exemple, la commande SHOW COLLATION produit ces colonnes :

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |      2 |
| dec8     | DEC West European           | dec8_swedish_ci     |      1 |
| cp850    | DOS West European           | cp850_general_ci    |      1 |
| hp8      | HP West European            | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |      1 |
| latin1   | ISO 8859-1 West European    | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |      1 |

...

Pour utiliser la clause WHERE avec la commande SHOW CHARACTER SET, il faut utiliser les noms de ces colonnes. Par exemple, la commande suivante affiche les informations sur les jeux de caractères dont la collation par défaut contient la chaîne "japanese" :

mysql> SHOW CHARACTER SET WHERE `Default collation` LIKE '%japanese%';
+---------+---------------------------+---------------------+--------+
| Charset | Description               | Default collation   | Maxlen |
+---------+---------------------------+---------------------+--------+
| ujis    | EUC-JP Japanese           | ujis_japanese_ci    |      3 |
| sjis    | Shift-JIS Japanese        | sjis_japanese_ci    |      2 |
| cp932   | SJIS for Windows Japanese | cp932_japanese_ci   |      2 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci |      3 |
+---------+---------------------------+---------------------+--------+

Cette commande affiche la liste des jeux de caractères multi-octets :

mysql> SHOW CHARACTER SET WHERE Maxlen > 1;
+---------+---------------------------+---------------------+--------+
| Charset | Description               | Default collation   | Maxlen |
+---------+---------------------------+---------------------+--------+
| big5    | Big5 Traditional Chinese  | big5_chinese_ci     |      2 |
| ujis    | EUC-JP Japanese           | ujis_japanese_ci    |      3 |
| sjis    | Shift-JIS Japanese        | sjis_japanese_ci    |      2 |
| euckr   | EUC-KR Korean             | euckr_korean_ci     |      2 |
| gb2312  | GB2312 Simplified Chinese | gb2312_chinese_ci   |      2 |
| gbk     | GBK Simplified Chinese    | gbk_chinese_ci      |      2 |
| utf8    | UTF-8 Unicode             | utf8_general_ci     |      3 |
| ucs2    | UCS-2 Unicode             | ucs2_general_ci     |      2 |
| cp932   | SJIS for Windows Japanese | cp932_japanese_ci   |      2 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci |      3 |
+---------+---------------------------+---------------------+--------+

23 - Mathématiques de précision

MySQL 5 introduit un module de mathématiques de précision, c'est-à-dire des opérations arithmétiques avec une précision accrue et un contrôle supérieur sur les erreurs, par rapport aux versions précédentes. Les nouvelles mathématiques sont basées sur deux changements dans l'implémentation :

- l'introduction de nouveau modes SQL en MySQL 5.0.2 qui contrôlent la sévérité du serveur lors de l'analyse des données ;

- l'introduction en MySQL 5.0.3 de la bibliothèque d'arithmétique.

Ces changements ont plusieurs implications au niveau des opérations numériques :

- plus grande précision dans les calculs.
Pour les nombres exacts, les calculs n'introduisent plus d'erreurs de décimale. La précision totale est alors utilisée. Par exemple, un nombre tel que 0,0001 est traité comme une valeur exacte, et non plus comme une valeur approchée. Si vous l'additionnez à lui-même 10 000 fois , vous obtiendrez la valeur de 1, et non pas une valeur proche de 1 ;

- arrondissement des valeurs maîtrisées.
Pour les nombres exacts, le résultat de ROUND() dépend de l'argument, et non plus d'éléments comme la bibliothèque C sous-jacente ;

- amélioration de la portabilité.
Les opérations sur les nombres exacts sont exactement les mêmes, quelque soit la plate-forme utilisée, Windows ou Unix ;

- contrôle sur la gestion des valeurs invalides.
Les dépassements de capacité et les divisions par zéro sont détectables, et peuvent être traités comme des erreurs. Par exemple, vous pouvez traiter une erreur trop grande pour une colonne comme une erreur au lieu de la tronquer à la valeur valide la plus proche. De même, vous pouvez traiter la division par zéro comme une erreur plutôt que de produire une valeur de type NULL. Le choix de l'approche revient alors à configurer la variable système sql_mode.

Une conséquence importante de ces changements est que MySQL est maintenant bien plus compatible avec les standards SQL.

Le chapitre suivant couvre différents aspects des mécanismes mathématiques, y compris les incompatibilités avec les anciennes applications. À la fin, des exemples illustrent le fonctionnement de MySQL 5.

23-A - Types de valeurs numériques

Les fonctionnalités mathématiques couvrent les types de données exacts (le type DECIMAL et les entiers), et les nombres décimaux exacts littéraux. Les types de données approximatifs sont gérés comme des nombres décimaux.

Les valeurs littérales exactes ont une partie entière ou une partie décimale, ou les deux. Elles peuvent être pourvues d'un signe. Par exemple : 1, .2, 3.4, -5, -6.78, +9.10.

Les valeurs littérales approximatives sont représentées en notation scientifique, avec une mantisse et un exposant. Les deux parties de cette représentation peuvent être pourvues d'un signe ou non. Par exemple : 1.2E3, 1.2E-3, -1.2E3, -1.2E-3.

Des nombres qui se ressemblent n'ont pas forcément le même type de données, exact ou approximatif. Par exemple, 2.34 est une valeur exacte (virgule fixe), alors que 2.34E0 est une valeur approximative (virgule flottante).

Le type de données DECIMAL est un type à virgule fixe, et les calculs qui s'y rattachent sont exacts. Pour MySQL, DECIMAL a plusieurs synonymes : NUMERIC, DEC et FIXED. Les types entiers sont aussi des valeurs exactes.

Les types de données FLOAT et DOUBLE sont des types à virgule flottante, et les calculs qui s'y rattachent sont des approximations. Pour MySQL, les types synonymes de FLOAT ou DOUBLE sont DOUBLE PRECISION et REAL.

23-B - Changements de type de données avec DECIMAL

En MySQL5.0.3, plusieurs modifications ont été apportées au type de données DECIMAL et à ses synonymes :

- le nombre maximal de chiffres ;

- le format de stockage ;

- la taille de stockage ;

- l'extension non standard de MySQL sur l'intervalle supérieure des colonnes DECIMAL.

Certaines de ces évolutions ont des incompatibilités potentielles avec les applications qui ont été écrites avec les vieilles versions de MySQL. Ces incompatibilités sont présentées dans cette section.

La syntaxe de déclaration des colonnes DECIMAL reste DECIMAL(M,D), même si l'intervalle de validité des arguments a un peu changé :

- M est le nombre maximal de chiffres : la précision. Il prend une valeur entière entre 1 et 64. Cela introduit des incompatibilités possibles avec les anciennes applications, car MySQL autorisait l'intervalle de 1 à 254 ;

- D est le nombre de chiffres décimaux : l'échelle. Il peut prendre des valeurs de 1 à 30, et ne doit pas dépasser M.

La valeur maximale de 64 pour M signifie que les calculs sur des valeurs DECIMAL ont une précision de 64 chiffres. Cette limite de 64 chiffres s'applique aussi aux valeurs numériques exactes littérales, ce qui fait que la taille maximale des littéraux est différente. Avant MySQL 5.0.3, les valeurs décimales pouvaient avoir jusqu'à 254 chiffres. Cependant, les calculs étaient faits avec des virgules flottantes, et restaient approximatifs. Ce changement dans la taille maximale des nombres est aussi une source de conflit avec les anciennes versions.

Les valeurs des colonnes DECIMAL ne sont plus représentées comme des chaînes, qui requièrent un octet par chiffre ou signe. À la place, un format binaire est utilisé, et il contient 9 chiffres dans 4 octets. Cela modifie la taille de stockage des valeurs DECIMAL. Chaque multiple de 9 chiffres requiert 4 octets, et le reste requiert une fraction de 9 chiffres. Par exemple, une colonne DECIMAL(18,9) a 9 chiffres de chaque côté de la virgule, ce qui fait que la partie entière et la partie décimale demandent 4 octets chacune. Une colonne DECIMAL(20,10) dispose de 10 chiffres de chaque côté de la virgule. Cela fait 4 octets pour chaque groupe de 9 chiffres, et 1 octet pour le reste.

Le stockage requis pour le « reste » est présenté dans le tableau suivant :

Reste

Nombre

Chiffres

d'octets

0

0

1

1

2

1

3

2

4

2

5

3

6

3

7

4

8

4

9

4

Une conséquence du changement de chaîne en format binaire de DECIMAL est que les colonnes DECIMAL ne peuvent plus stocker le caractère '+' initial ou les '0' initiaux. Avant MySQL 5.0.3, si vous insériez '+0003.1' dans une colonne DECIMAL(5,1), le nombre aurait été stocké sous forme de +0003.1. Depuis MySQL 5.0.3, il est stocké sous forme de 3.1. Les applications qui exploitent le vieux comportement doivent être modifiées pour prendre en compte ce changement.

Le changement de format de stockage signifie que les colonnes DECIMAL ne supportent plus les extensions non standards qui permettaient aux valeurs trop grandes d'être stockées. Pour les valeurs positives qui ne requièrent pas de signe, MySQL permettait l'ajout d'un chiffre de plus. Par exemple, dans une colonne DECIMAL(3,0), l'intervalle de validité était de -999 à 999, mais MySQL permettait le stockage de valeurs de 1000 à 9999, en utilisant l'octet de signe pour stocker les valeurs supplémentaires. Cette extension de la valeur maximale des colonnes DECIMAL n'est plus autorisée. Dans MySQL 5.0.3 et les plus récentes versions, une colonne DECIMAL(M,D) autorise le stockage d'au plus M-D chiffres à gauche de la virgule décimale. Cela peut engendrer des incompatibilités si une application exploitait cette tolérance de MySQL.

Le standard SQL requiert que la précision des valeurs NUMERIC(M,D) soit exactement de M. Pour DECIMAL(M,D), le standard requiert une précision d'au moins M, mais en autorise plus. Avec MySQL, DECIMAL(M,D) et NUMERIC(M,D) sont les mêmes, et les deux ont la même précision de M chiffres exactement.

Résumé des incompatibilités :

La liste suivante résume les incompatibilités qui résultent des modifications des comportements des colonnes DECIMAL. Vous pouvez l'utiliser pour vérifier vos anciennes applications et les migrer vers MySQL 5.0.3.

- Pour DECIMAL(M,D), la valeur maximale de M est 64, et non 254.

- Les calculs impliquant des valeurs décimales exactes ont 64 chiffres de précision. C'est inférieur au nombre maximal de chiffres précédemment autorisés avant MySQL 5.0.3 (254 chiffres), mais la précision est malgré tout améliorée. Les calculs étaient faits en double précision, ce qui représente 52 bits ou 15 chiffres.

- L'extension non standard MySQL de la limite supérieure de stockage des colonnes DECIMAL n'est plus supportée.

- Les caractères initiaux '+' et '0' ne sont plus stockés.

23-C - Gestion des expressions

Avec les mathématiques de précisions, les valeurs exactes sont utilisées aussi souvent que possible. Par exemple, les comparaisons entre noms sont faîtes exactement, sans perte de valeur. En mode SQL strict, lors d'une commande INSERT dans une colonne avec un type exact, tel que DECIMAL ou entier, un nombre est inséré avec sa valeur exacte s'il est contenu dans l'intervalle de validité de la colonne. Lorsqu'il est lu, sa valeur est la même que lors de l'insertion. Hors du mode strict, les arrondissements sur INSERT sont autorisés.

La gestion des expressions numériques dépend du type de valeurs qui sont manipulées :

- si une valeur approximative est impliquée, l'expression sera approximative, et sera évaluée avec l'arithmétique des nombres à virgule flottante ;

- si aucune valeur approximative n'est impliquée, l'expression ne contient que des valeurs exactes. Si aucune valeur ne contient de partie décimale, l'expression sera évaluée avec l'arithmétique exacte DECIMAL et la précision sera de 64 chiffres. « Exact » est soumis aux limitations des représentations binaires. 1.0/3.0 peut être représenté par .333... avec un nombre infini de chiffres, mais jamais « exactement » comme un tiers, et (1.0/3.0)*3.0 ne vaudra jamais exactement « 1.0. » ;

- sinon, l'expression ne contient que des entiers. L'expression est exacte, et est évaluée avec l'arithmétique entière, et la précision est celle d'un BIGINT (64 bits).

Si une expression numérique contient des chaînes de caractères, elles sont converties en valeur décimale de précision double, et l'expression sera une approximation.

Les insertions dans les colonnes numériques sont affectées par le mode SQL, qui est contrôlé par la variable système sql_mode. Voyez Section 1.5.2 : « Sélectionner les modes SQL ». La présentation suivante mentionne le mode strict, sélectionné par les valeurs STRICT_ALL_TABLES ou STRICT_TRANS_TABLES mode values et ERROR_FOR_DIVISION_BY_ZERO. Pour désactiver ces contraintes, vous pouvez utiliser simplement le mode TRADITIONAL, qui inclut le mode strict et ERROR_FOR_DIVISION_BY_ZERO :

mysql> SET sql_mode='TRADITIONAL';

Si un nombre est inséré dans une colonne de type exact (DECIMAL ou entier), il sera inséré comme valeur exacte s'il est dans l'intervalle de validité de la colonne.

Si la valeur a trop de chiffres décimaux, un arrondissement survient et une alerte est générée. L'arrondissement se fait tel que décrit par le « Comportement d'arrondissement ».

Si la valeur a trop de chiffres dans la partie entière, la valeur est alors trop grande, et elle est traitée comme suit :

- si le mode strict n'est pas activé, la valeur est coupée à la première valeur valide, et une alerte est générée ;

- si le mode strict est activé, une erreur de dépassement de capacité survient.

Les valeurs trop petites pour être stockées ne sont pas détectées, et aucune erreur ne survient dans ce cas : le comportement est indéfini.

Par défaut, la division par zéro produit le résultat NULL et aucune alerte n'est générée. Avec le mode SQL ERROR_FOR_DIVISION_BY_ZERO, MySQL gère les divisions par zéro différemment :

- si le mode strict n'est pas activé, une alerte survient ;

- si le mode strict est activé, les insertions et modifications qui manipulent des divisions par zéro sont interdites et une erreur survient.

En d'autres mots, les insertions et modifications qui impliquent des divisions par zéro peuvent être traitées comme des erreurs, mais cela requiert le mode SQL ERROR_FOR_DIVISION_BY_ZERO en plus du mode strict.

Supposez que nous ayons la commande suivante :

INSERT INTO t SET i = 1/0;

Voici ce qui arrive dans différentes combinaisons du mode strict et de ERROR_FOR_DIVISION_BY_ZERO :

sql_mode Value

Result

''

Aucune alerte, aucune erreur, i prend la valeur NULL

strict

Aucune alerte, aucune erreur, i vaut NULL

ERROR_FOR_DIVISION_BY_ZERO

Alerte, pas d'erreur, i vaut NULL

strict, ERROR_FOR_DIVISION_BY_ZERO

Erreur, pas d'insertion.

Pour les insertions de lignes dans une colonne numérique, la conversion de chaîne en valeur numérique est gérée comme suit :

- une chaîne qui ne commence pas par un nombre, ne peut pas être utilisée comme nombre et produit une erreur en mode strict, ou une alerte sinon. Cela vaut aussi pour les chaînes vides ;

- une chaîne qui commence avec un nombre peut être convertie, mais la partie non numérique sera tronquée. Cela produit une erreur en mode strict et une alerte sinon.

23-D - Arrondissement de valeurs

Cette section présente les méthodes d'arrondissement des valeurs par la fonction ROUND() et lors des insertions dans ces colonnes de type DECIMAL.

La fonction ROUND() arrondit différemment les valeurs, suivant qu'elles sont exactes ou approximatives :

- pour les valeurs exactes, ROUND() utilise la règle de l'arrondissement « à l'entier supérieur » : une valeur ayant une partie décimale de 0.5 ou plus est arrondie au prochain entier si elle est positive, et à l'entier inférieur si elle est négative (en d'autres termes, elle est arrondie en s'éloignant de 0). Une valeur avec une partie décimale inférieure à 0.5 est arrondie à l'entier inférieur si elle est positive, et à l'entier supérieur si elle est négative ;

- pour les nombres à valeur approchée, le résultat dépend de la bibliothèque C du système. Sur de nombreuses plates-formes, cela signifie que ROUND() utilise la règle de l'arrondissement « au prochain entier pair » : une valeur où la partie décimale est arrondie au prochain entier pair.

L'exemple suivant illustre la différence de comportement entre les deux valeurs :

mysql> SELECT ROUND(2.5), ROUND(25E-1);
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3          |            2 |
+------------+--------------+

Pour les insertions dans les colonnes de type DECIMAL, la cible est une valeur exacte, ce qui fait que l'arrondissement se fait à l'entier le plus proche, indépendamment de la nature de la valeur insérée, approchée ou exacte :

mysql> CREATE TABLE t (d DECIMAL(10,0));
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t VALUES(2.5),(2.5E0);
Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 2

mysql> SELECT d FROM t;
+------+
| d    |
+------+
| 3    |
| 3    |
+------+

23-E - Exemples de calculs mathématiques

Cette section fournit des exemples d'améliorations de la qualité des calculs mathématiques en MySQL 5, en comparaison avec les anciennes versions.

Exemple 1 : les nombres sont utilisés avec leur valeur exacte dès que possible.

Avant MySQL 5.0.3, les nombres étaient traités comme des nombres décimaux, avec des résultats inexacts :

mysql> SELECT .1 + .2 = .3;
+--------------+
| .1 + .2 = .3 |
+--------------+
|            0 |
+--------------+

Depuis MySQL 5.0.3, les nombres sont utilisés tels que spécifiés, tant que possible :

mysql> SELECT .1 + .2 = .3;
+--------------+
| .1 + .2 = .3 |
+--------------+
|            1 |
+--------------+

Cependant, pour les valeurs décimales, les erreurs de précision existent toujours :

mysql> SELECT .1E0 + .2E0 = .3E0;
+--------------------+
| .1E0 + .2E0 = .3E0 |
+--------------------+
|                  0 |
+--------------------+

Un autre moyen de voir la différence entre les valeurs exactes et les approximations est d'ajouter un grand nombre de fois des petites valeurs. Considérez la procédure stockée suivante qui ajoute .0001 mille fois à une variable.

CREATE PROCEDURE p ()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE d DECIMAL(10,4) DEFAULT 0;
DECLARE f FLOAT DEFAULT 0;
WHILE i < 10000 DO
SET d = d + .0001;
SET f = f + .0001E0;
SET i = i + 1;
END WHILE;
SELECT d, f;
END;

La somme de d et f vaut logiquement 1, mais cela n'est vrai que pour le calcul décimal. Les calculs décimaux introduisent une erreur :

+--------+------------------+
| d      | f                |
+--------+------------------+
| 1.0000 | 0.99999999999991 |
+--------+------------------+

Exemple 2 : la multiplication est faite avec l'échelle imposée par le standard SQL. C'est-à-dire que pour deux nombres X1 et X2 qui ont pour échelle respective S1 et S2, le résultat du produit est l'échelle S1 + S2.

Avant MySQL 5.0.3, ceci arrivait :

mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
|      0.00 |
+-----------+

La valeur affichée est incorrecte. La valeur a été calculée correctement dans cette situation, mais n'est pas affichée avec l'échelle nécessaire. Pour afficher la valeur correcte, il faut utiliser ceci :

mysql> SELECT .01 * .01 + .0000;
+-------------------+
| .01 * .01 + .0000 |
+-------------------+
|            0.0001 |
+-------------------+

Depuis MySQL 5.0.3, l'échelle finale est correcte :

mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
| 0.0001    |
+-----------+

Exemple 3 : l'arrondissement est bien maîtrisé.

Avant MySQL 5.0.3, l'arrondissement (par exemple, avec ROUND()) était lié à l'implémentation de la bibliothèque C sous-jacente. Cela conduisait à des incohérences entre les plates-formes. Par exemple, cela arrivait si vous essayiez de faire le même calcul sur Windows et sur Linux, ou sur différentes architectures telles que des x86 ou des PowerPC.

Depuis MySQL 5.0.3, l'arrondissement se fait comme ceci :

l'arrondit des colonnes DECIMAL des valeurs exactes utilisent la règle de l'« arrondi à la valeur supérieure ». Les valeurs ayant une partie décimale supérieure ou égale à .5 sont arrondies au prochain entier, comme ceci :

mysql> SELECT ROUND(2.5), ROUND(-2.5);
+------------+-------------+
| ROUND(2.5) | ROUND(-2.5) |
+------------+-------------+
| 3          | -3          |
+------------+-------------+

L'arrondi des valeurs décimales utilise toujours la bibliothèque C, qui applique la règle de l'arrondi à l'entier le plus proche :

mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0);
+--------------+---------------+
| ROUND(2.5E0) | ROUND(-2.5E0) |
+--------------+---------------+
|            2 |            -2 |
+--------------+---------------+

Exemple 4 : pour les insertions dans les tables, une valeur trop grande qui engendre un dépassement de capacité cause maintenant une erreur, et non plus la troncation de la valeur. Pour cela, il faut être en mode strict.

Avant MySQL 5.0.2, la troncation se faisait à la valeur valide la plus proche :

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 128;
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SELECT i FROM t;
+------+
| i    |
+------+
|  127 |
+------+
1 row in set (0.00 sec)

Depuis MySQL 5.0.2, le dépassement de capacité intervient dès que le mode strict est actif :

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.01 sec)

mysql> SET sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.10 sec)

mysql> INSERT INTO t SET i = 128;
ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1

mysql> SELECT i FROM t;
Empty set (0.00 sec)

Exemple 5 : lors des insertions dans les tables, les divisions par zéro causent des erreurs, et non des insertions de valeur NULL. Il faut utiliser le mot script et l'option ERROR_FOR_DIVISION_BY_ZERO.

Avant MySQL 5.0.2, la division par zéro conduisait à un NULL :

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET i = 1 / 0;
Query OK, 1 row affected (0.06 sec)

mysql> SELECT i FROM t;
+------+
| i    |
+------+
| NULL |
+------+
1 row in set (0.01 sec)

Depuis MySQL 5.0.2, la division par zéro est une erreur si le bon mode SQL est actif :

mysql> CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec)

mysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t SET i = 1 / 0;
ERROR 1365 (22012): Division by 0

mysql> SELECT i FROM t;
Empty set (0.01 sec)

Exemple 6 : dans MySQL 4, les valeurs littérales exactes et approximatives sont converties en nombres décimaux en double précision :

mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;

mysql> DESCRIBE t;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| a     | double(3,1) |      |     | 0.0     |       |
| b     | double      |      |     | 0       |       |
+-------+-------------+------+-----+---------+-------+

Dans MySQL 5, les nombres décimaux approximatives sont toujours convertis en nombres décimaux en précision double, mais les valeurs exactes sont gérées comme des nombres décimaux en précision simple DECIMAL :

mysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;

mysql> DESCRIBE t;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| a     | decimal(3,1) | NO   |     | 0.0     |       |
| b     | double       | NO   |     | 0       |       |
+-------+--------------+------+-----+---------+-------+

Exemple 7 : si un argument d'une fonction d'agrégation est une valeur exacte, le résultat sera aussi exact, avec une échelle au moins égale à cet argument. Le résultat ne sera pas un nombre décimal de précision double.

Considérez les commandes suivantes :

mysql> CREATE TABLE t (i INT, d DECIMAL, f FLOAT);
mysql> INSERT INTO t VALUES(1,1,1);
mysql> CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;

Le résultat avant MySQL 5.0.3 :

mysql> DESCRIBE y;
+--------+--------------+------+-----+---------+-------+
| Field  | Type         | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| AVG(i) | double(17,4) | YES  |     | NULL    |       |
| AVG(d) | double(17,4) | YES  |     | NULL    |       |
| AVG(f) | double       | YES  |     | NULL    |       |
+--------+--------------+------+-----+---------+-------+

Le résultat est un nombre décimal en précision double, quel que soit le type des arguments.

Le résultat depuis MySQL 5.0.3 :

mysql> DESCRIBE y;
+--------+---------------+------+-----+---------+-------+
| Field  | Type          | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(64,0) | YES  |     | NULL    |       |
| AVG(d) | decimal(64,0) | YES  |     | NULL    |       |
| AVG(f) | double        | YES  |     | NULL    |       |
+--------+---------------+------+-----+---------+-------+

Le résultat est un nombre décimal en précision double pour les arguments de type nombre décimal. Le résultat est une valeur exacte pour les arguments exacts.

24 - API MySQL

Ce chapitre décrit les interfaces disponibles pour MySQL, où les trouver, et comment les utiliser. L'API C est celle qui est couverte le plus en détail, puisqu'elle est développée par l'équipe MySQL, et sert de base à toutes les autres API.

24-A - Utilitaires de développement des programmes MySQL

Cette section décrit certains utilitaires que vous pouvez trouver utiles, lors du développement de programmes MySQL.

- msql2mysql
Un script Shell qui convertit un programme mSQL en MySQL. Il ne gère pas toutes les situations, mais c'est un bon début.

- mysql_config
Un script Shell qui produit les options nécessaires lors de la compilation de programmes MySQL.

24-A-1 - msql2mysql, convertit des programmes mSQL vers MySQL

Initialement, l'API C de MySQL a été développée pour être très similaire à celle du serveur mSQL. À cause de cela, les programmes mSQL peuvent souvent être convertis facilement pour utiliser MySQL, en changeant simplement les noms de l'API C.

L'utilitaire msql2mysql fait cette conversion, et transforme les appels C mSQL en leur équivalent MYSQL.

msql2mysql convertit le fichier sur place : il est recommandé de faire une copie avant de lancer la conversion. Par exemple, utilisez msql2mysql comme ceci :

shell> cp client-prog.c client-prog.c.orig
shell> msql2mysql client-prog.c
client-prog.c converted

Puis, examinez le fichier client-prog.c et faites toutes les modifications postconversions nécessaires.

msql2mysql utilise l'utilitaire replace pour faire les substitutions. Voir Section 8.13, « L'utilitaire de remplacement de chaînes replace ».

24-A-2 - mysql_config lit les options de compilations du client MySQL

mysql_config vous indique des informations pratiques pour compiler votre client MySQL et le connecter au serveur.

mysql_config supporte les options suivantes :

- --cflags
Options de compilation utilisées pour trouver les fichiers inclus.

- --include
Options du compilateur pour trouver les fichiers d'inclusion MySQL. (Normalement, il faut utiliser --cflags au lieu de cette commande.)

- --libs
Les bibliothèques et options requises pour compiler avec la bibliothèque client MySQL.

- --libs_r
Les bibliothèques et options requises pour la compilation avec la sécurité thread de la bibliothèque client MySQL.

- --socket
Le nom par défaut de la socket, défini lors de la configuration de MySQL.

- --port
Le numéro de port par défaut, défini lors de la configuration de MySQL.

- --version
Le numéro de version et la version de la distribution MySQL.

- --libmysqld-libs
Les bibliothèques et options requises pour compiler avec la bibliothèque intégrée MySQL.

Si vous exécutez mysql_config sans aucune option, il va afficher toutes les options qu'il supporte, ainsi que la valeur de toutes les options :

shell> mysql_config
Usage: /usr/local/mysql/bin/mysql_config [options]
Options:
--cflags         [-I/usr/local/mysql/include/mysql -mcpu=pentiumpro]
--include        [-I/usr/local/mysql/include/mysql]
--libs           [-L/usr/local/mysql/lib/mysql -lmysqlclient -lz
-lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto]
--libs_r         [-L/usr/local/mysql/lib/mysql -lmysqlclient_r
-lpthread -lz -lcrypt -lnsl -lm -lpthread]
--socket         [/tmp/mysql.sock]
--port           [3306]
--version        [4.0.16]
--libmysqld-libs [-L/usr/local/mysql/lib/mysql -lmysqld -lpthread -lz
-lcrypt -lnsl -lm -lpthread -lrt]

Vous pouvez utiliser mysql_config dans une ligne de commande pour inclure la valeur qui sera affichée par une option. Par exemple, pour compiler un client MySQL, utilisez mysql_config comme ceci :

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

Lorsque vous utilisez mysql_config de cette manière, assurez-vous de l'invoquer entre des guillemets obliques ('`'). Cela indique que le Shell doit exécuter cette expression, et remplacer le résultat dans la commande.

24-B - API MySQL C

L'interface C est distribuée avec MySQL. Elle est incluse dans la bibliothèque mysqlclient et permet aux programmes écrits en C d'accéder à la base de données.

De nombreux clients de la distribution source de MySQL sont écrits en C. Si vous recherchez des exemples d'illustration de l'utilisation de l'interface C, étudiez donc ces clients. Vous pouvez les trouver dans le dossier clients de la distribution source MySQL.

La plupart des autres interfaces clientes (sauf Connector/J) utilisent la bibliothèque mysqlclient pour communiquer avec le serveur MySQL. Cela signifie que, par exemple, vous pouvez exploiter adroitement de nombreuses autres variables qui sont utilisées par les autres programmes clients, car elles sont utilisées dans la bibliothèque. Voyez Chapitre 8, MySQL Scripts clients et utilitaires, pour une liste de ces variables.

Le client a une taille maximale de buffer de communication. La taille du buffer qui est allouée au lancement 16 ko bytes, est automatiquement augmentée jusqu'à la taille maximum de 16 Mo. Comme la taille du buffer croît à la demande, vous ne consommerez pas de ressources supplémentaires en augmentant la limite maximum par défaut. Cette limite sert surtout à s'assurer de bien identifier des problèmes de requêtes erronées ou des paquets de communication.

Le buffer de communication doit être assez grand pour contenir une commande SQL complète (dans le sens du trafic allant vers le serveur), et une ligne complète (dans le sens du trafic allant vers le client). Chaque buffer de threads est dynamiquement agrandi pour gérer les requêtes jusqu'à la taille limite. Par exemple, si vous avez des valeurs de type BLOB qui contient jusqu'à 16 Mo de données, vous devez avoir un buffer de communication dont la limite doit être au minimum de 16 Mo, aussi bien sur le serveur que sur le client. La limite par défaut sur le client est de 16 Mo, mais elle est de 1 Mo sur le serveur. Vous pouvez augmenter cette valeur en modifiant le paramètre max_allowed_packet lorsque le serveur est lancé. Voir Section 7.5.2, « Réglage des paramètres du serveur ».

Le serveur MySQL réduit la taille des buffers de communication à net_buffer_length octets après chaque requête. Pour les clients, le buffer est associé à une connexion, et les ressources ne seront libérées que lorsque cette dernière sera refermée.

Pour la programmation avec les threads, voyez la section Section 24.2.15, « Comment faire un client MySQL threadé ». Pour la création d'applications qui incluent le serveur et le client dans le même programme, et ne communiquent avec aucun serveur externe, voyez Section 24.2.16, « libmysqld, la bibliothèque du serveur embarqué MySQL ».

24-B-1 - Types de données de l'API C

- MYSQL
Cette structure représente un gestionnaire de connexions à la base de données. Elle est utilisée dans la plupart des fonctions MySQL.

- MYSQL_RES
Cette structure représente le résultat d'une requête qui retourne des lignes (SELECT, SHOW, DESCRIBE, EXPLAIN). L'information retournée par une requête est appelée jeu de résultats dans le reste de cette section.

- MYSQL_ROW
C'est une représentation sûre pour les types d'une ligne de données. Elle est actuellement implémentée en tant que tableau de chaînes à octets comptés. (Vous ne pouvez la traiter en tant que chaîne terminée par une valeur nulle, si les valeurs du champ peuvent contenir des données binaires, car de telles valeurs peuvent contenir elles-mêmes des octets nuls.) Les lignes sont obtenues en appelant mysql_fetch_row().

- MYSQL_FIELD
Cette structure contient des informations à propos du champ, telles que son nom, son type, et sa taille. Ses membres sont décrits en plus de détail ici. Vous pouvez obtenir une structure MYSQL_FIELD pour chaque champ en appelant plusieurs fois mysql_fetch_field(). Les valeurs des champs ne font pas partie de la structure, elles sont contenues dans une structure MYSQL_ROW.

- MYSQL_FIELD_OFFSET
C'est une représentation sûre des types pour les index dans une liste de champs MySQL. (Utilisés par mysql_field_seek().) Les index sont des numéros de champs, dans une ligne, commençant à zéro.

- my_ulonglong
Le type utilisé pour le nombre de lignes et pour mysql_affected_rows(), mysql_num_rows(), et mysql_insert_id(). Ce type fournit une échelle allant de 0 à 1.84e19.
Sur quelques systèmes, essayer d'écrire la valeur d'un type my_ulonglong ne fonctionnera pas. Pour écrire une telle valeur, convertissez-la en unsigned long et utilisez un format d'impression %lu. Exemple :

printf ("Nombre de lignes : %lu\n", (unsigned long) mysql_num_rows(result));

La structure MYSQL_FIELD contient les membres listés ici :

- char * name
Le nom du champ, une chaîne terminée par une valeur nulle.

- char * table
Le nom de la table contenant ce champ, s'il n'est pas calculé. Pour les champs calculés, la valeur de table est une chaîne vide.

- char * def
La valeur par défaut de ce champ, en tant que chaîne terminée par une valeur nulle. Ce n'est défini que si vous utilisez mysql_list_fields().

- enum enum_field_types type
Le type du champ. La valeur de type peut être l'une des suivantes :

Valeur de type

Description du type

FIELD_TYPE_TINY

Champ TINYINT

FIELD_TYPE_SHORT

Champ SMALLINT

FIELD_TYPE_LONG

Champ INTEGER

FIELD_TYPE_INT24

Champ MEDIUMINT

FIELD_TYPE_LONGLONG

Champ BIGINT

FIELD_TYPE_DECIMAL

Champ DECIMAL ou NUMERIC

FIELD_TYPE_FLOAT

Champ FLOAT

FIELD_TYPE_DOUBLE

Champ DOUBLE ou REAL

FIELD_TYPE_TIMESTAMP

Champ TIMESTAMP

FIELD_TYPE_DATE

Champ DATE

FIELD_TYPE_TIME

Champ TIME

FIELD_TYPE_DATETIME

Champ DATETIME

FIELD_TYPE_YEAR

Champ YEAR

FIELD_TYPE_STRING

Champ chaîne de caractères (CHAR ou VARCHAR)

FIELD_TYPE_VAR_STRING

Champ VARCHAR

FIELD_TYPE_BLOB

Champ BLOB ou TEXT (utilisez max_length pour déterminer la taille maximale)

FIELD_TYPE_SET

Champ SET

FIELD_TYPE_ENUM

Champ ENUM

FIELD_TYPE_NULL

Champ de type NULL

FIELD_TYPE_CHAR

Désapprouvé, utilisez FIELD_TYPE_TINY à la place

Vous pouvez utiliser la macro IS_NUM() pour tester si un champ est de type numérique ou non. Passez la valeur de type à IS_NUM() et elle sera évaluée à TRUE si le champ est numérique :

if (IS_NUM(field->type))
printf("Le champ est numérique\n");

- unsigned int length
La taille du champ, comme spécifié dans la définition de la table.

- unsigned int max_length
La longueur maximale du champ pour le jeu de résultats (la taille de la plus longue valeur de champ actuellement dans le jeu de résultat). Si vous utilisez mysql_store_result() ou mysql_list_fields(), cela contient la longueur maximale pour le champ. Si vous utilisez mysql_use_result(), la valeur de cette variable est zéro.

- unsigned int flags
Les différents attributs sous forme de bits pour le champ. La valeur de flags peut avoir zéro ou plusieurs de ces bits suivants activés :

Valeur d'attribut

Description d'attribut

NOT_NULL_FLAG

Le champ ne peut être NULL

PRI_KEY_FLAG

Le champ fait partie d'une clef primaire

UNIQUE_KEY_FLAG

Le champ fait partie d'une clef unique

MULTIPLE_KEY_FLAG

Le champ fait partie d'une clef non unique

UNSIGNED_FLAG

Le champ possède l'attribut UNSIGNED

ZEROFILL_FLAG

Le champ possède l'attribut ZEROFILL

BINARY_FLAG

Le champ possède l'attribut BINARY

AUTO_INCREMENT_FLAG

Le champ possède l'attribut AUTO_INCREMENT

ENUM_FLAG

Le champ est un ENUM (désapprouvé)

SET_FLAG

Le champ est un SET (désapprouvé)

BLOB_FLAG

Le champ est un BLOB ou TEXT (désapprouvé)

TIMESTAMP_FLAG

Le champ est un TIMESTAMP (désapprouvé)

L'utilisation des attributs BLOB_FLAG, ENUM_FLAG, SET_FLAG, et TIMESTAMP_FLAG est désapprouvé, car ils indiquent un type de champ plutôt qu'un attribut de type de champ. Il est préférable de tester field->type avec FIELD_TYPE_BLOB, FIELD_TYPE_ENUM, FIELD_TYPE_SET, ou FIELD_TYPE_TIMESTAMP à la place.

L'exemple suivant illustre une utilisation typique de la valeur de flags :

if (field->flags & NOT_NULL_FLAG)
printf("Le champ ne peut être nul\n");

Vous pouvez utiliser les différentes macros ci-dessous pour déterminer le statut booléen de la valeur de l'attribut :

Statut de l'attribut

Description

IS_NOT_NULL(flags)

Vrai si le champ est défini en tant que NOT NULL

IS_PRI_KEY(flags)

Vrai si le champ est une clef primaire

IS_BLOB(flags)

Vrai si le champ est un BLOB ou TEXT (désapprouvé, testez plutôt field->type)

- unsigned int decimals
Le nombre de décimales pour les champs numériques.

24-B-2 - Vue d'ensemble des fonctions de l'API C

Les fonctions disponibles dans l'API C sont listées ici et décrites en plus de détails dans la section suivante. Voir Section 24.2.3, « Description des fonctions de l'API C ».

Fonction

Description

mysql_affected_rows()

Retourne le nombre de lignes changées/effacées/insérées par le dernier UPDATE, DELETE, ou INSERT.

mysql_change_user()

Change l'utilisateur et la base de données pour une connexion ouverte.

mysql_character_set_name()

Retourne le nom du jeu de caractères de la connexion.

mysql_close()

Ferme une connexion au serveur.

mysql_connect()

Connecte à un serveur MySQL. Cette fonction est désapprouvée, utilisez mysql_real_connect() à la place.

mysql_create_db()

Crée une base de données. Cette fonction est désapprouvée, utilisez plutôt la commande SQL CREATE DATABASE.

mysql_data_seek()

Déplace le pointeur vers une ligne arbitraire dans le jeu de résultats de la requête.

mysql_debug()

Effectue un DBUG_PUSH avec la chaîne donnée.

mysql_drop_db()

Supprime une base de données. Cette fonction est désapprouvée, utilisez plutôt la commande SQL DROP DATABASE.

mysql_dump_debug_info()

Demande au serveur d'écrire les informations de débogage dans un fichier de log.

mysql_eof()

Détermine si la dernière ligne du jeu de résultats a été lue ou non. Cette fonction est désapprouvée, vous pouvez utiliser mysql_errno() ou mysql_error() à la place.

mysql_errno()

Retourne le numéro de l'erreur de la fonction appelée en dernier.

mysql_error()

Retourne le message d'erreur de la dernière fonction MySQL appelée.

mysql_escape_string()

Protège une chaîne en échappant les caractères spéciaux.

mysql_fetch_field()

Retourne le type du champ suivant dans la table.

mysql_fetch_field_direct()

Retourne le type d'une colonne, étant donné un numéro de champ.

mysql_fetch_fields()

Retourne un tableau avec toutes les structures de champs.

mysql_fetch_lengths()

Retourne la longueur de toutes les colonnes dans la ligne suivante.

mysql_fetch_row()

Récupère la ligne suivante dans le jeu de résultats.

mysql_field_seek()

Place le curseur de colonne sur une colonne précise.

mysql_field_count()

Retourne le nombre de colonnes dans le résultat pour la requête la plus récente.

mysql_field_tell()

Retourne la position du curseur de champs utilisé pour le dernier appel à mysql_fetch_field().

mysql_free_result()

Libère la mémoire utilisée par un jeu de résultats.

mysql_get_client_info()

Retourne la version du client sous forme de chaîne.

mysql_get_client_version()

Retourne la version du client sous forme d'entier.

mysql_get_host_info()

Retourne une chaîne décrivant la connexion.

mysql_get_server_version()

Retourne le numéro de version du serveur sous forme d'entier (nouveau en 4.1).

mysql_get_proto_info()

Retourne la version du protocole utilisé par la connexion.

mysql_get_server_info()

Retourne la version du serveur.

mysql_info()

Retourne des informations à propos de la requête la plus récente.

mysql_init()

Récupère ou initialise une structure MYSQL.

mysql_insert_id()

Retourne l'identifié généré pour une colonne AUTO_INCREMENT par la dernière requête.

mysql_kill()

Termine un processus donné.

mysql_list_dbs()

Retourne les noms des bases de données répondant à une expression régulière simple.

mysql_list_fields()

Retourne les noms des champs répondant à une expression régulière simple.

mysql_list_processes()

Retourne une liste des processus courants du serveur.

mysql_list_tables()

Retourne les noms des tables répondant à une expression régulière simple.

mysql_num_fields()

Retourne le nombre de colonnes dans un jeu de résultats.

mysql_num_rows()

Retourne le nombre de lignes dans le jeu de résultats.

mysql_options()

Configure les options de connexion pour mysql_connect().

mysql_ping()

Vérifie si la connexion au serveur a toujours lieu. Reconnecte si besoin.

mysql_query()

Exécute une requête SQL spécifiée en tant que chaîne terminée par un caractère nul.

mysql_real_connect()

Connecte à un serveur MySQL.

mysql_real_escape_string()

Protège les caractères spéciaux dans une chaîne utilisable dans une requête SQL, en prenant en compte le jeu de caractères courant de la connexion.

mysql_real_query()

Exécute une requête SQL spécifiée en tant que chaîne comptée.

mysql_reload()

Demande au serveur de recharger la table des droits.

mysql_row_seek()

Déplace le pointeur vers une ligne dans le jeu de résultats, en utilisant une valeur retournée par mysql_row_tell().

mysql_row_tell()

Retourne la position du curseur de lignes.

mysql_select_db()

Sélectionne une base de données.

mysql_set_server_option()

Spécifie la valeur d'une option pour la connexion (comme multi-statements).

mysql_sqlstate()

Retourne l'erreur SQLSTATE de la dernière erreur.

mysql_shutdown()

Termine le serveur de base de données.

mysql_stat()

Retourne le statut du serveur dans une chaîne.

mysql_store_result()

Récupère le jeu de résultats complet dans le client.

mysql_thread_id()

Retourne l'identifiant du thread courant.

mysql_thread_safe()

Retourne 1 si le client est compilé avec la sécurité thread.

mysql_use_result()

Initialise une récupération ligne par ligne des résultats.

mysql_warning_count()

Retourne le nombre d'alertes générées par la dernière commande SQL.

mysql_commit()

Valide une transaction (nouveau en 4.1).

mysql_rollback()

Annule une transaction (nouveau en 4.1).

mysql_autocommit()

Active et désactive le mode d'autovalidation (nouveau en 4.1).

mysql_more_results()

Vérifie s'il n'y a plus de résultats (nouveau en 4.1).

mysql_next_result()

Retourne/initie le prochain résultat dans une commande multirequête (nouveau en 4.1).

Pour vous connecter au serveur, appelez mysql_init() pour initialiser un gestionnaire de connexion, puis appelez mysql_real_connect() avec ce gestionnaire (avec d'autres informations telles que l'hôte, l'utilisateur et le mot de passe). Lors de la connexion, mysql_real_connect() définit l'option reconnect (quit fait partie de la structure MYSQL) à 1. Cette option indique, dans le cas où une requête ne peut être exécutée à cause d'une perte de connexion, d'essayer de se reconnecter au serveur avant d'abandonner. Lorsque vous n'avez plus besoin de la connexion, appelez mysql_close() pour la clore.

Tant qu'une connexion est active, le client envoie des requêtes SQL au serveur à l'aide de mysql_query() ou mysql_real_query(). La différence entre les deux est que mysql_query() s'attend à ce que la requête soit spécifiée en tant que chaîne terminée par la chaîne nulle, tandis que mysql_real_query() attend une chaîne de longueur connue. Si la chaîne contient des données binaires (incluant l'octet nul), vous devez utiliser mysql_real_query().

Pour chaque requête non sélective (par exemple, INSERT, UPDATE, DELETE), vous pouvez trouver combien de lignes ont été mises à jour (affectées) en appelant mysql_affected_rows().

Pour les requêtes SELECT, vous récupérez les lignes sélectionnées dans un jeu de résultat. (Notez que quelques commandes ont le même comportement que SELECT, dans le sens où elles renvoient des lignes. Cela inclut SHOW, DESCRIBE, et EXPLAIN. Elles doivent être traitées de la même façon que les requêtes SELECT.)

Il y a deux façons pour un client de gérer les jeux de résultats. Une méthode consiste à récupérer le jeu de résultats en entier et en une seule fois en appelant mysql_store_result(). Cette fonction obtient toutes les lignes retournées par la requête et les stocke dans le client. La seconde méthode consiste à initialiser une récupération ligne par ligne du jeu de résultats en appelant mysql_use_result(). Cette fonction initie la récupération, mais ne récupère actuellement aucune ligne à partir du serveur.

Dans les deux cas, vous accédez aux lignes en appelant mysql_fetch_row(). Avec mysql_store_result(), mysql_fetch_row() accède aux lignes qui ont déjà été récupérées à partir du serveur. Avec mysql_use_result(), mysql_fetch_row() récupère actuellement la ligne à partir du serveur. Les informations à propos de la taille des données dans chaque ligne sont disponibles en appelant mysql_fetch_lengths().

Après avoir fini de traiter le jeu de résultats, appelez mysql_free_result() pour libérer la mémoire utilisée.

Les deux mécanismes de récupération sont complémentaires. Les programmes clients doivent utiliser l'approche qui leur convient le mieux. En pratique, les clients tendent plus à utiliser mysql_store_result().

Un avantage de mysql_store_result() est que, puisque toutes les lignes ont été récupérées dans le client, vous ne pouvez pas que accéder aux lignes séquentiellement, vous pouvez revenir en arrière ou avancer dans le jeu de résultats en utilisant mysql_data_seek() ou mysql_row_seek() pour changer la position de la ligne courante dans le jeu de résultats. Vous pouvez aussi trouver le nombre total des lignes en appelant mysql_num_rows(). D'un autre côté, les besoins en mémoire de mysql_store_result() peuvent être très grands pour les grands jeux de résultats et vous aurez des chances d'obtenir un manque de mémoire.

Un avantage de mysql_use_result() est que le client a besoin de moins de mémoire pour le jeu de résultats, car il utilise une ligne à la fois (et puisqu'il y a moins de pertes de mémoire, mysql_use_result() peut être plus rapide). Les inconvénients sont que vous devez récupérer chaque ligne rapidement pour éviter de bloquer le serveur, vous n'avez pas d'accès aléatoires aux lignes dans le jeu de résultats (vous ne pouvez accéder aux lignes que séquentiellement), et vous ne savez pas combien de lignes comporte le jeu de résultats tant que vous ne les avez pas toutes récupérées. De plus, vous devez récupérer toutes les lignes même si vous trouvez entre-temps l'information que vous cherchiez.

L'API permet aux clients de gérer correctement les requêtes (récupérant les lignes seulement en cas de besoin) sans savoir si la requête était un SELECT ou non. Vous pouvez faire cela en appelant mysql_store_result() après chaque mysql_query() (ou mysql_real_query()). Si l'appel au jeu de résultats réussit, la requête était un SELECT et vous pouvez lire les lignes. Sinon, appelez mysql_field_count() pour vérifier si un résultat aurait dû être retourné. Si mysql_field_count() retourne zéro, la requête n'a pas retourné de données (cela indique que c'était un INSERT, UPDATE, DELETE, etc.), et ne devait pas retourner de lignes. Si mysql_field_count() est non nul, la requête aurait dû retourner des lignes, mais ne l'a pas fait. Cela indique que la requête était un SELECT qui a échoué. Reportez-vous à la description de mysql_field_count() pour un exemple d'utilisation.

mysql_store_result() et mysql_use_result() vous permettent d'obtenir des informations à propos des champs qui constituent le jeu de résultat (le nombre de champs, leur nom et type, etc.). Vous pouvez accéder aux informations du champ séquentiellement dans une ligne en appelant plusieurs fois mysql_fetch_field(), ou avec le numéro du champ dans la ligne en appelant mysql_fetch_field_direct(). La position courante du pointeur de champ peut être changée en appelant mysql_field_seek(). Changer le pointeur de champ affecte les appels suivants à mysql_fetch_field(). Vous pouvez aussi obtenir en une seule fois les informations sur les champs en appelant mysql_fetch_fields().

Pour détecter les erreurs, MySQL fournit un accès aux informations des erreurs via les fonctions mysql_errno() et mysql_error(). Elles retournent le code de l'erreur et le message pour la dernière fonction invoquée qui aurait pu réussir ou échouer, vous permettant ainsi de déterminer les erreurs et leurs causes.

24-B-3 - Description des fonctions de l'API C

Dans les descriptions suivantes, un paramètre ou retour de fonction NULL correspond au NULL dans le sens C du terme, et non dans le sens de la valeur NULL de MySQL.

Les fonctions qui retournent une valeur retournent la plupart du temps un pointeur ou un entier. Sauf en cas d'indications contraires, les fonctions retournant un pointeur retournent une valeur non NULL pour indiquer un succès ou une valeur NULL pour indiquer une erreur, les fonctions retournant un entier retournent zéro pour indiquer un succès et une valeur non nulle en cas d'erreur. Notez que « non nulle » ne signifie rien de plus que cela. Sauf si la description de la fonction le dit, ne testez pas avec une valeur différente de zéro :

if (result)                   /* correct */
... erreur ...

if (result < 0)               /* incorrect */
... erreur ...

if (result == -1)             /* incorrect */
... erreur ...

Lorsqu'une fonction retourne une erreur, la section Erreurs du descriptif de la fonction liste les types d'erreurs possibles. Vous pouvez trouver celle qui est arrivée en appelant mysql_errno(). Une chaîne de caractères représentant l'erreur peut être obtenue en appelant mysql_error().

24-B-3-a - mysql_affected_rows()

my_ulonglong mysql_affected_rows(MYSQL *mysql)

Description

Retourne le nombre de lignes modifiées par la dernière commande UPDATE, supprimées par la dernière commande DELETE ou insérées par la dernière commande INSERT. Peut être appelée immédiatement après mysql_query() pour les commandes UPDATE, DELETE, ou INSERT. Pour la commande SELECT, mysql_affected_rows() fonctionne comme mysql_num_rows().

Valeur de retour

Un entier supérieur à zéro indique le nombre de lignes affectées ou sélectionnées. Zéro indique qu'aucun enregistrement n'a été mis à jour pour une requête UPDATE, qu'aucune ligne n'a correspondu à la clause WHERE dans la requête ou que celle-ci n'a pas encore été exécutée. -1 indique que la requête a renvoyé une erreur ou que, pour une requête SELECT, mysql_affected_rows() a été appelée avant mysql_store_result(). Comme mysql_affected_rows() retourne une valeur non signée, vous pouvez comparer avec -1 en comparant la valeur retournée par (my_ulonglong)-1 (ou par (my_ulonglong)~0, ce qui est la même chose).

Erreurs

Aucune.

Exemple

mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
printf("%ld produits mis à jour",(long) mysql_affected_rows(&mysql));

Si on spécifie l'option CLIENT_FOUND_ROWS en se connectant à mysqld, mysql_affected_rows() retournera le nombre d'enregistrements correspondant à la clause WHERE pour une requête UPDATE.

Notez que quand on utilise une commande REPLACE, mysql_affected_rows() retournera 2 si le nouvel enregistrement en a remplacé un ancien. 2 en retour, car dans ce cas, l'ancienne ligne a été supprimée puis la nouvelle insérée.

24-B-3-b - mysql_change_user()

my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db)

Description

Change l'utilisateur et définit la base de données spécifiée par db en tant que base de données par défaut (courante) dans la connexion spécifiée par mysql. Pour les requêtes suivantes, cette base de données sera celle utilisée pour les références aux tables ne spécifiant pas explicitement une base de données.

Cette fonction a été introduite à la version 3.23.3 de MySQL.

mysql_change_user() échoue si l'utilisateur ne peut être authentifié ou s'il n'a pas le droit d'utiliser cette base de données. Dans ce cas, l'utilisateur et la base de données ne sont pas changés.

Le paramètre db peut être mis à NULL si vous ne voulez pas avoir de base de données par défaut.

Valeur de retour

Zéro en cas de succès. Différent de zéro si une erreur se produit.

Erreurs

Les mêmes que vous pouvez obtenir avec mysql_real_connect().

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

- ER_UNKNOWN_COM_ERROR
Le serveur MySQL n'implémente pas cette commande (probablement un ancien serveur)

- ER_ACCESS_DENIED_ERROR
L'utilisateur ou le mot de passe étaient erronés.

- ER_BAD_DB_ERROR
La base de données n'existe pas.

- ER_DBACCESS_DENIED_ERROR
L'utilisateur n'a pas le droit d'accéder à la base de données.

- ER_WRONG_DB_NAME
Le nom de la base de données était trop long.

Exemple

if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
fprintf(stderr, "Impossible de changer d'utilisateur.  Erreur : %s\n",
mysql_error(&mysql));
}

24-B-3-c - mysql_character_set_name()

const char *mysql_character_set_name(MYSQL *mysql)

Description

Retourne le jeu de caractères par défaut de la connexion courante.

Valeur de retour

Le jeu de caractères par défaut

Erreurs

Aucune.

24-B-3-d - mysql_close()

void mysql_close(MYSQL *mysql)

Description

Ferme la connexion ouverte précédemment. mysql_close() libère aussi le pointeur de connexion mysql, si celui-ci avait été alloué dynamiquement par mysql_init() ou mysql_connect().

Valeur de retour

Aucune.

Erreurs

Aucune.

24-B-3-e - mysql_connect()

MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)

Description

Cette fonction est désapprouvée. Il est préférable d'utiliser mysql_real_connect() à la place.

mysql_connect() essaye d'établir une connexion à un serveur MySQL lancé sur host. mysql_connect() doit s'achever avec succès avant que vous ne puissiez exécuter l'une des autres fonctions de l'API, à l'exception de mysql_get_client_info().

La signification des paramètres est la même que pour ceux de la fonction mysql_real_connect() à la différence que le paramètre de connexion peut être NULL. Dans ce cas, l'API C alloue automatiquement une mémoire pour la structure de connexion et la libère quand vous appelez mysql_close(). Le désavantage de cette approche est que vous ne pouvez pas récupérer les messages d'erreur si la connexion échoue. (Pour obtenir des informations sur les erreurs à partir de mysql_errno() ou mysql_error(), vous devez fournir un pointeur MYSQL valide.)

Valeur de retour

La même que pour mysql_real_connect().

Erreurs

Les mêmes que pour mysql_real_connect().

24-B-3-f - mysql_create_db()

int mysql_create_db(MYSQL *mysql, const char *db)

Description

Crée la base de données nommée avec le paramètre db.

Cette fonction est désapprouvée. Il est préférable d'utiliser mysql_query() pour générer une requête SQL CREATE DATABASE à la place.

Valeur de retour

Zéro si la base a été créée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

Exemple

if(mysql_create_db(&mysql, "ma_base"))
{
fprintf(stderr, "Impossible de créer une nouvelle base de données. Erreur : %s\n",
mysql_error(&mysql));
}

24-B-3-g - mysql_data_seek()

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)

Description

Se déplace vers une ligne arbitraire d'un jeu de résultats de requête. Cela nécessite que la structure du jeu de résultats contienne la totalité du résultat de la requête, de ce fait mysql_data_seek() peut être utilisée en conjonction avec mysql_store_result(), mais pas avec mysql_use_result().

L'index de la ligne doit être compris entre 0 et mysql_num_rows(result)-1.

Valeur de retour

Aucune.

Erreurs

Aucune.

24-B-3-h - mysql_debug()

void mysql_debug(const char *debug)

Description

Provoque un DBUG_PUSH avec la chaîne donnée. mysql_debug() utilise la bibliothèque de débogage Fred Fish. Pour utiliser cette fonction vous devez compiler la bibliothèque client avec le support débogage. Voir Section D.1, « Déboguer un serveur MySQL ». Voir Section D.2, « Débogage un client MySQL ».

Valeur de retour

Aucune.

Erreurs

Aucune.

Exemple

L'appel montré ici fait générer à la bibliothèque du client un fichier de trace dans /tmp/client.trace sur la machine du client :

mysql_debug("d:t:O,/tmp/client.trace");

24-B-3-i - mysql_drop_db()

int mysql_drop_db(MYSQL *mysql, const char *db)

Description

Supprime la base de données nommée avec le paramètre db.

Cette fonction est désapprouvée. Il est préférable d'utiliser mysql_query() pour générer une requête SQL DROP DATABASE à la place.

Valeur de retour

Zéro si la base a été effacée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

Exemple

if(mysql_drop_db(&mysql, "ma_base"))
fprintf(stderr, "Impossible de supprimer la base de données. Erreur : %s\n",
mysql_error(&mysql));

24-B-3-j - mysql_dump_debug_info()

int mysql_dump_debug_info(MYSQL *mysql)

Description

Demande au serveur d'écrire quelques informations de débogage dans le log. Pour que cela fonctionne, il faut que l'utilisateur ait le droit SUPER.

Valeur de retour

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-k - mysql_eof()

my_bool mysql_eof(MYSQL_RES *result)

Description

Cette fonction est désapprouvée. Vous pouvez utiliser mysql_errno() ou mysql_error() à la place.

mysql_eof() détermine si la dernière ligne d'un jeu de résultats a été lue.

Si vous obtenez un jeu de résultats suite à un appel à mysql_store_result(), le client reçoit le jeu entier en une seule opération. Dans ce cas, un retour NULL de la fonction mysql_fetch_row() signifie toujours que la fin du jeu de résultats a été atteinte et il n'est donc pas nécessaire d'appeler mysql_eof(). Lors d'une utilisation avec mysql_store_result(), mysql_eof() retournera toujours true.

D'un autre côté, si vous utilisez mysql_use_result() pour initialiser la récupération d'un jeu de résultats, les lignes sont obtenues du serveur une par une lors des appels successifs de mysql_fetch_row(). Puisqu'une erreur peut survenir à la connexion durant ce processus, une valeur de retour NULL de la part de mysql_fetch_row() ne signifie pas nécessairement que la fin du jeu de résultats a été atteinte normalement. Dans ce cas, vous pouvez utiliser mysql_eof() pour déterminer ce qui est arrivé. mysql_eof() retourne une valeur non nulle si la fin du jeu de résultats a été atteinte et zéro en cas d'erreur.

Historiquement, mysql_eof() a vu le jour avant les fonctions d'erreurs standards de MySQL mysql_errno() et mysql_error(). Puisque ces fonctions fournissent les mêmes informations, leur utilisation est préférée à mysql_eof(), qui est maintenant désapprouvée. (En fait, elles fournissent plus d'informations, car mysql_eof() ne retourne que des valeurs booléennes alors que les fonctions d'erreurs indiquent les raisons des erreurs lorsqu'elles surviennent.)

Valeur de retour

Zéro si aucune erreur n'est survenue. Autre chose dans le cas contraire.

Erreurs

Aucune.

Exemple

L'exemple suivant vous montre comment vous devez utiliser mysql_eof():

mysql_query(&mysql,"SELECT * FROM une_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// traite les données
}
if(!mysql_eof(result))  // mysql_fetch_row() failed due to an error
{
fprintf(stderr, "Erreur : %s\n", mysql_error(&mysql));
}

Vous pouvez reproduire la même chose avec les fonctions d'erreurs de MySQL :

mysql_query(&mysql,"SELECT * FROM une_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// traite les données
}
if(mysql_errno(&mysql))  // mysql_fetch_row() ne marche pas à cause d'une erreur
{
fprintf(stderr, "Erreur : %s\n", mysql_error(&mysql));
}

24-B-3-l - mysql_errno()

unsigned int mysql_errno(MYSQL *mysql)

Description

Pour la connexion spécifiée par mysql, mysql_errno() retourne le code de l'erreur pour l'appel le plus récent à une fonction de l'API qui peut réussir ou échouer. Un zéro en valeur de retour signifie qu'aucune erreur ne s'est produite. Les codes erreur du client sont listés dans le fichier d'entête MySQL (errmsg.h). Les codes erreur du serveur sont listés dans le fichier mysqld_error.h. Dans les sources de la distribution MySQL vous pouvez trouver la liste complète des messages d'erreur et le code qui leur est associé dans le fichier Docs/mysqld_error.txt. Les codes d'erreur serveur sont listés dans Chapitre 26, Gestion des erreurs avec MySQL.

Notez que certaines fonctions comme mysql_fetch_row() ne donnent pas de valeur à mysql_errno() si elles réussissent.

En général, les fonctions qui doivent interroger le serveur pour obtenir des informations vont remettre à zéro mysql_errno() si elles réussissent.

Valeur de retour

Un code d'erreur. Zéro si aucune erreur n'est survenue.

Erreurs

Aucune.

24-B-3-m - mysql_error()

char *mysql_error(MYSQL *mysql)

Description

Pour la connexion spécifiée par mysql, mysql_error() retourne le message d'erreur pour l'appel le plus récent à une fonction de l'API qui peut réussir ou échouer. Une chaîne vide ("") est retournée si aucune erreur n'est survenue. Cela signifie que les deux tests suivants sont équivalents :

if(mysql_errno(&mysql))
{
// une erreur est survenue
}

if(mysql_error(&mysql)[0] != '\0')
{
// une erreur est survenue
}

La langue des messages d'erreurs peut être changée en recompilant la bibliothèque du client MySQL. Actuellement, vous pouvez choisir les messages d'erreur parmi une liste de plusieurs langues. Voir Section 5.8.2, « Langue des messages d'erreurs ».

Valeur de retour

Une chaîne de caractères qui décrit l'erreur. Une chaîne vide si aucune erreur n'est survenue.

Erreurs

Aucune.

24-B-3-n - mysql_escape_string()

Vous devez utiliser la fonction mysql_real_escape_string() à la place de celle-ci !

Cette fonction est identique à mysql_real_escape_string() exception faite que mysql_real_escape_string() prend deux identifiants de connexion comme premiers arguments et échappe la chaîne en se basant sur le jeu de caractères courant. mysql_escape_string() ne prend pas d'identifiant de connexion et ne respecte pas le jeu de caractères courant.

24-B-3-o - mysql_fetch_field()

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

Description

Retourne la définition d'une colonne d'un jeu de résultats en tant que structure MYSQL_FIELD. Appelez cette fonction plusieurs fois pour obtenir des informations à propos de toutes les colonnes dans le jeu de résultats. mysql_fetch_field() retourne NULL quand il ne reste plus de champ.

mysql_fetch_field() est mis à zéro pour retourner des informations à propos du premier champ à chaque fois que vous exécutez une nouvelle requête SELECT. Le champ retourné par mysql_fetch_field() est aussi affecté par les appels à mysql_field_seek().

Si vous avez appelé mysql_query() pour exécuter un SELECT sur une table mais n'avez pas appelé mysql_store_result(), MySQL retourne la longueur par défaut du BLOB (8 ko octets) si vous avez appelé mysql_fetch_field() pour obtenir la longueur d'un champ BLOB. (La taille 8 K est choisie, car MySQL ne connaît pas la longueur maximale du BLOB. Cela devrait être un jour paramétrable.) Une fois que vous avez récupéré le jeu de résultats, field->max_length contient la longueur de la plus grande valeur de cette colonne dans la requête spécifiée.

Valeur de retour

La structure MYSQL_FIELD de la colonne courante. NULL s'il ne reste plus de colonne.

Erreurs

Aucune.

Exemple

MYSQL_FIELD *field;

while((field = mysql_fetch_field(result)))
{
printf("nom du champ : %s\n", field->name);
}

24-B-3-p - mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

Description

Retourne un tableau de toutes les structures MYSQL_FIELD dans un jeu de résultats. Chaque structure fournit la définition de champ d'une colonne dans le jeu de résultats.

Valeur de retour

Un tableau de structures MYSQL_FIELD pour toutes les colonnes dans le jeu de résultats.

Erreurs

Aucune.

Exemple

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;

num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
printf("Le champ %u est %s\n", i, fields[i].name);
}

24-B-3-q - mysql_fetch_field_direct()

MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)

Description

Étant donné un numéro de champ fieldnr pour une colonne dans un jeu de résultats, cette fonction retourne la définition de ce champ en tant que structure MYSQL_FIELD. Vous pouvez utiliser cette fonction pour obtenir la définition d'une colonne choisie arbitrairement. La valeur de fieldnr doit varier entre 0 et mysql_num_fields(result)-1.

Valeur de retour

La structure MYSQL_FIELD pour la colonne spécifiée.

Erreurs

Aucune.

Exemple

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *field;

num_fields = mysql_num_fields(result);
for(i = 0; i < num_fields; i++)
{
field = mysql_fetch_field_direct(result, i);
printf("La champ %u est %s\n", i, field->name);
}

24-B-3-r - mysql_fetch_lengths()

unsigned long *mysql_fetch_lengths(MYSQL_RES *result)

Description

Retourne les longueurs des colonnes de la ligne courante dans le jeu de résultats. Si vous voulez copier les valeurs des champs, cette information sur la longueur est très utile pour l'optimisation, car vous pouvez éviter les appels à strlen(). De plus, si le jeu de résultats contient des données binaires, vous devez utiliser cette fonction pour déterminer la longueur des données, car strlen() retourne des résultats incorrects pour les champs contenant des caractères nuls.

La longueur des colonnes vides et des colonnes contenant la valeur NULL est zéro. Pour savoir comment distinguer ces cas, voyez la description de mysql_fetch_row().

Valeur de retour

Un tableau d'entiers longs non signés représentant la taille de chaque colonne (n'incluant pas le caractère nul de terminaison). NULL si une erreur se produit.

Erreurs

mysql_fetch_lengths() n'est valide que pour la ligne courante du jeu de résultats. Cette fonction retourne NULL si vous l'appelez avant d'appeler mysql_fetch_row() ou après avoir récupéré toutes les lignes du résultat.

Exemple

MYSQL_ROW row;
unsigned long *lengths;
unsigned int num_fields;
unsigned int i;

row = mysql_fetch_row(result);
if (row)
{
num_fields = mysql_num_fields(result);
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("La colonne %u a %l octets de longueur.\n", i, lengths[i]);
}
}

24-B-3-s - mysql_fetch_row()

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

Description

Récupère la ligne suivante d'un jeu de résultats. Lorsqu'elle est utilisée après mysql_store_result(), mysql_fetch_row() retourne NULL quand il n'y a plus de ligne à récupérer. Lorsqu'elle est utilisée après mysql_use_result(), mysql_fetch_row() retourne NULL quand il n'y a plus de ligne à récupérer ou qu'une erreur est rencontrée.

Le nombre de valeurs dans la ligne est donné par mysql_num_fields(result). Si row contient la valeur de retour d'un appel à mysql_fetch_row(), les pointeurs sur les valeurs sont accédées de row[0] à row[mysql_num_fields(result)-1]. Les valeurs NULL de la ligne sont indiquées par des pointeurs NULL.

La longueur de la valeur du champ dans la ligne peut être obtenue en appelant mysql_fetch_lengths(). Les champs vides et les champs contenant NULL ont tous deux une longueur égale à zéro; vous pouvez les distinguer en vérifiant le pointeur sur la valeur du champ. Si le pointeur est NULL, le champ est NULL; sinon, le champ est vide.

Valeur de retour

Une structure MYSQL_ROW pour la prochaine ligne. NULL s'il n'y a plus de ligne à récupérer ou qu'une erreur survient.

Erreurs

- CR_SERVER_LOST
La connexion au serveur a été perdue durant la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;

num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
}
printf("\n");
}

24-B-3-t - mysql_field_count()

unsigned int mysql_field_count(MYSQL *mysql)

Si vous utilisez une version de MySQL plus ancienne que la 3.22.24, vous devez utiliser unsigned int mysql_num_fields(MYSQL *mysql).

Description

Retourne le nombre de colonnes pour la requête la plus récente de la connexion.

L'utilisation normale de cette fonction est lorsque mysql_store_result() a retourné NULL (et que vous n'avez donc pas de pointeur sur jeu de résultats). Dans ce cas, vous pouvez appeler mysql_field_count() pour déterminer si mysql_store_result() aurait dû produire un résultat non vide. Cela permet au programme client d'entreprendre les bonnes actions sans savoir si la requête était un SELECT (ou équivalent). L'exemple suivant illustre comment cela peut être fait.

Voir Section 24.2.13.1, « Pourquoi est-ce que mysql_store_result() retourne parfois NULL après que mysql_query() ait réussi ».

Valeur de retour

Un entier non signé représentant le nombre de champs dans un jeu de résultats.

Erreurs

Aucune.

Exemple

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
// erreur
}
else // requête bonne, traitons les données qu'elle renvoie
{
result = mysql_store_result(&mysql);
if (result)  // il y a des lignes
{
num_fields = mysql_num_fields(result);
// récupère les lignes, puis appelle mysql_free_result(result)
}
else  // mysql_store_result() n'a rien retourné; est-ce normal ?
{
if(mysql_field_count(&mysql) == 0)
{
// la requête ne retourne aucune donnée
// (ce n'était pas un SELECT)
num_rows = mysql_affected_rows(&mysql);
}
else // mysql_store_result() aurait dû retourner des données
{
fprintf(stderr, "Erreur : %s\n", mysql_error(&mysql));
}
}
}

Une autre voie est de remplacer l'appel à mysql_field_count(&mysql) par mysql_errno(&mysql). Dans ce cas, vous vérifiez directement les erreurs à partir de mysql_store_result() plutôt qu'à partir de mysql_field_count() si la requête était un SELECT.

24-B-3-u - mysql_field_seek()

MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)

Description

Place le pointeur de champs à la position donnée. Le prochain appel à mysql_fetch_field() récupérera la définition du champ de la colonne associée à cet index.

Pour vous placer au début d'une ligne, passez 0 comme valeur d'offset.

Valeur de retour

La dernière valeur de l'index de champ.

Erreurs

Aucune.

24-B-3-v - mysql_field_tell()

MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)

Description

Retourne la position du curseur de champs utilisé pour le dernier appel à mysql_fetch_field(). Cette valeur peut être utilisée en argument de mysql_field_seek().

Valeur de retour

L'indice courant du curseur de champs.

Erreurs

Aucune.

24-B-3-w - mysql_free_result()

void mysql_free_result(MYSQL_RES *result)

Description

Libère la mémoire allouée à un résultat avec mysql_store_result(), mysql_use_result(), mysql_list_dbs(), etc. Quand vous n'avez plus besoin d'un jeu de résultats, vous devez libérer la mémoire qu'il occupe en appelant mysql_free_result().

Valeur de retour

Aucune.

Erreurs

Aucune.

24-B-3-x - mysql_get_client_info()

char *mysql_get_client_info(void)

Description

Retourne une chaîne représentant la version de la bibliothèque du client.

Valeur de retour

Une chaîne de caractères représentant la version de la bibliothèque du client.

Erreurs

Aucune.

24-B-3-y - mysql_get_client_version()

unsigned long mysql_get_client_version(void)

Description

Retourne un entier qui représente la version de la bibliothèque cliente. Cette valeur est au format XYYZZ où X est la version majeure, YY est la version publiée, et ZZ est le numéro de version de la version publiée. Par exemple, la valeur 40102 représente la version 4.1.2.

Valeur retournée

Un entier qui représente la version de la bibliothèque cliente MySQL.

Erreurs

Aucune.

24-B-3-z - mysql_get_host_info()

char *mysql_get_host_info(MYSQL *mysql)

Description

Retourne une chaîne de caractères décrivant le type de connexion actuellement utilisé, incluant le nom du serveur.

Valeur de retour

Une chaîne de caractères représentant le nom du serveur et le type de connexion.

Erreurs

Aucune.

24-B-3-aa - mysql_get_proto_info()

unsigned int mysql_get_proto_info(MYSQL *mysql)

Description

Retourne la version du protocole utilisé par la connexion courante.

Valeur de retour

Un entier non signé représentant la version du protocole utilisé par la connexion courante.

Erreurs

Aucune.

24-B-3-ab - mysql_get_server_info()

char *mysql_get_server_info(MYSQL *mysql)

Description

Retourne une chaîne représentant le numéro de version du serveur.

Valeur de retour

Une chaîne de caractères représentant le numéro de version du serveur.

Erreurs

Aucune.

24-B-3-ac - mysql_get_server_version()

unsigned long mysql_get_server_version(MYSQL *mysql)

Description

Retourne le numéro de version du serveur, sous la forme d'un entier (nouveau en 4.1).

Valeurs retournées

Un nombre, qui représente le numéro de version du serveur MySQL, au format suivant :

major_version*10000 + minor_version *100 + sub_version

Par exemple, 4.1.0 est retournée comme ceci : 40100.

Ceci est pratique pour déterminer rapidement le numéro de version d'un serveur, dans un client, et connaître ainsi ses fonctionnalités.

Erreurs

Aucune.

24-B-3-ad - mysql_hex_string()

unsigned long mysql_hex_string(char *to, const char *from, unsigned long length)

Description

Cette fonction sert à créer une chaîne SQL valide que vous pouvez utiliser dans une requête SQL. Voir Section 9.1.1, « Chaînes ».

La chaîne de l'argument from est encodée au format hexadécimal, et chaque caractère prend alors deux chiffres hexadécimaux. Le résultat est placé dans le paramètre to et un caractère nul termine la chaîne.

La chaîne pointée par from doit faire length octets de long. Vous devez allouer le buffer to à au moins longueur * 2 + 1 de long. Lorsque mysql_hex_string() se termine, le contenu de to est une chaîne terminée par un caractère nul. La valeur de retour est la taille de la chaîne encodée, sans compter le caractère nul.

La valeur retournée peut être placée dans une commande SQL en utilisant le format 0xvalue ou X'value'. Cependant, la valeur de retour n'inclut pas les éléments de syntaxe 0x ou X'...'. Le code appelant doit fournir les éléments dont il a besoin.

mysql_hex_string() a été ajouté en MySQL 4.0.23 et 4.1.8.

Exemple

char query[1000],*end;

end = strmov(query,"INSERT INTO test_table values(");
end = strmov(end,"0x");
end += mysql_hex_string(end,"What's this",11);
end = strmov(end,",0x");
end += mysql_hex_string(end,"binary data: \0\r\n",16);
*end++ = ')';

if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
{
fprintf(stderr, "Failed to insert row, Error: %s\n",
mysql_error(&mysql));
}

La fonction strmov() utilisée dans l'exemple est incluse dans la bibliothèque cliente mysqlclient et fonctionne comme strcpy() mais retourne un pointeur sur le caractère nul final du premier paramètre.

Valeur retournée

La taille de la valeur placée dans to, hormis le caractère nul final.

Erreurs

Aucune.

24-B-3-ae - mysql_info()

char *mysql_info(MYSQL *mysql)

Description

Récupère une chaîne de caractères fournissant des informations à propos de la requête exécutée le plus récemment, mais seulement pour celles listées ici. Pour les autres requêtes, mysql_info() retournera NULL.

Le format de la chaîne varie selon le type de requête, comme décrit ici. Les nombres présentés sont des exemples, la chaîne retournée contiendra les informations correspondant à vos requêtes.

- INSERT INTO ... SELECT ...
Chaîne retournée : Records: 100 Duplicates: 0 Warnings: 0

- INSERT INTO ... VALUES (...),(...),(...)...
Chaîne retournée : Records: 3 Duplicates: 0 Warnings: 0

- LOAD DATA INFILE ...
Chaîne retournée : Records: 1 Deleted: 0 Skipped: 0 Warnings: 0

- ALTER TABLE
Chaîne retournée : Records: 3 Duplicates: 0 Warnings: 0

- UPDATE
Chaîne retournée : Rows matched: 40 Changed: 40 Warnings: 0

Notez que mysql_info() retourne une valeur non nulle (NULL) pour les requêtes INSERT ... VALUES seulement si une liste de valeurs multiples est fournie à la requête.

Valeur de retour

Une chaîne de caractères représentant des informations additionnelles à propos de la dernière requête exécutée. NULL si aucune information n'est disponible pour la requête.

Erreurs

Aucune.

24-B-3-af - mysql_init()

MYSQL *mysql_init(MYSQL *mysql)

Description

Alloue ou initialise un objet MYSQL convenable pour mysql_real_connect(). Si mysql est un pointeur NULL, la fonction alloue, initialise et retourne un nouvel objet. Sinon, l'objet est initialisé et son adresse est retournée. Si mysql_init() alloue un nouvel objet, il sera libéré quand mysql_close() sera appelée pour clore la connexion.

Valeur de retour

Un gestionnaire MYSQL* initialisé. NULL s'il n'y avait pas assez de mémoire pour allouer le nouvel objet.

Erreurs

Si la mémoire est insuffisante, NULL est retourné.

24-B-3-ag - mysql_insert_id()

my_ulonglong mysql_insert_id(MYSQL *mysql)

Description

Retourne l'identifiant généré pour une colonne AUTO_INCREMENT par la dernière requête. Utilisez cette commande après avoir exécuté une requête INSERT sur une table qui contient un champ AUTO_INCREMENT.

Plus précisément, mysql_insert_id() est mis à jour dans ces conditions :

- Les commandes INSERT qui stockent une valeur dans une colonne de type AUTO_INCREMENT. C'est vrai si la valeur est automatiquement générée suivant le stockage de NULL ou 0 dans la colonne, ou une valeur explicite non spéciale.

- Dans le cas des INSERT multiples, mysql_insert_id() retourne la première valeur AUTO_INCREMENT automatiquement générée : si aucune valeur n'est générée, elle retourne la dernière valeur explicitement insérée dans la colonne AUTO_INCREMENT.

- Les commandes INSERT qui génèrent une valeur AUTO_INCREMENT en insérant l'expression LAST_INSERT_ID(expr) dans une colonne.

- Les commandes INSERT qui génèrent une valeur AUTO_INCREMENT qui donne la valeur de LAST_INSERT_ID(expr) à une colonne.

- La valeur de mysql_insert_id() n'est pas affectée par les commandes telles que les commandes SELECT qui ne retournent pas de résultat.

- Si la commande précédente a retourné une erreur, la valeur de mysql_insert_id() est indéfinie.

Notez que mysql_insert_id() retourne 0 si la dernière requête n'a pas généré de valeur AUTO_INCREMENT. Si vous voulez garder cette valeur pour plus tard, assurez-vous d'appeler mysql_insert_id() immédiatement après la requête ayant généré cette valeur.

mysql_insert_id() est mis à jour après l'exécution de requêtes INSERT et UPDATE qui génèrent une valeur AUTO_INCREMENT ou qui définissent la valeur d'une colonne à LAST_INSERT_ID(expr). Voir Section 12.8.4, « Fonctions diverses ».

Notez aussi que la valeur de retour de la fonction SQL LAST_INSERT_ID() contient toujours la valeur d'AUTO_INCREMENT la plus à jour. Cette valeur n'est pas remise à zéro lors de l'exécution d'autres requêtes, car elle est maintenue pour le serveur.

Valeur de retour

La valeur de la colonne AUTO_INCREMENT qui a été mise à jour par la dernière requête. Retourne zéro si aucune requête n'avait eu lieu durant la connexion, ou si la dernière requête n'a pas mis à jour la valeur de la colonne AUTO_INCREMENT.

Erreurs

Aucune.

24-B-3-ah - mysql_kill()

int mysql_kill(MYSQL *mysql, unsigned long pid)

Description

Demande au serveur de terminer le thread spécifié par pid.

Valeur de retour

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-ai - mysql_library_end()

int mysql_library_init(int argc, char **argv, char **groups)

Description

Ceci est un synonyme de la fonction mysql_server_init(). Il a été ajouté en MySQL 4.1.10 et 5.0.3.

Voyez Section 24.2.2, « Vue d'ensemble des fonctions de l'API C » pour connaître son utilisation.

24-B-3-aj - mysql_library_end()

void mysql_library_end(void)

Description

Ceci est un synonyme de la fonction mysql_server_end(). Il a été ajouté en MySQL 4.1.10 et 5.0.3.

Voyez Section 24.2.2, « Vue d'ensemble des fonctions de l'API C » pour connaître son utilisation.

24-B-3-ak - mysql_list_dbs()

MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)

Description

Retourne un jeu de résultats se composant des noms des bases de données localisées sur le serveur qui correspondent à l'expression régulière spécifiée par le paramètre wild. wild peut contenir les caractères spéciaux '%' ou '_', ou peut être un pointeur NULL pour obtenir la liste de toutes les bases de données. Utiliser mysql_list_dbs() revient à exécuter la requête SHOW databases [LIKE wild].

Vous devez libérer le résultat avec mysql_free_result().

Valeur de retour

Un jeu de résultats MYSQL_RES en cas de succès. NULL si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-al - mysql_list_fields()

MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)

Description

Retourne un jeu de résultats comportant des noms de champs dans une table qui correspondent l'expression régulière simple spécifiée par la paramètre wild. wild peut contenir les caractères spéciaux '%' ou '_', ou peut être un pointeur NULL pour correspondre à tous les champs. Utiliser mysql_list_fields() revient à exécuter la requête SHOW COLUMNS FROM nom_de_table [LIKE wild].

Notez qu'il est recommandé d'utiliser SHOW COLUMNS FROM nom_de_table au lieu de /mysql_list_fields().

Vous devez libérer le résultat avec mysql_free_result().

Valeur de retour

Un jeu de résultats MYSQL_RES en cas de succès. NULL sinon.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-am - mysql_list_processes()

MYSQL_RES *mysql_list_processes(MYSQL *mysql)

Description

Retourne un jeu de résultats décrivant les threads courants du serveur. C'est le même genre d'informations renvoyé par mysqladmin processlist ou une requête SHOW PROCESSLIST.

Vous devez libérer le jeu de résultats avec mysql_free_result().

Valeur de retour

Un jeu de résultats MYSQL_RES en cas de succès. NULL si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-an - mysql_list_tables()

MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)

Description

Retourne un jeu de résultats comportant des noms de tables dans la base de données courante qui concordent avec l'expression régulière spécifiée par le paramètre wild. wild peut contenir les caractères spéciaux '%' ou '_', ou peut être un pointeur NULL pour obtenir toutes les tables. Faire appel à mysql_list_tables() revient à exécuter la requête SHOW tables [LIKE wild].

Vous devez libérer le jeu de résultats avec mysql_free_result().

Valeur de retour

Un jeu d'enregistrements MYSQL_RES en cas de succès. NULL en cas d'erreur.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-ao - mysql_num_fields()

unsigned int mysql_num_fields(MYSQL_RES *result)

ou

unsigned int mysql_num_fields(MYSQL *mysql)

La seconde forme ne fonctionne plus à partir de la version 3.22.24 de MySQL. Pour passer un argument MYSQL*, vous devez utiliser la fonction unsigned int mysql_field_count(MYSQL *mysql) à la place.

Description

Retourne le nombre de colonnes dans un jeu de résultats.

Notez que vous pouvez obtenir le nombre de colonnes soit à partir d'un pointeur sur résultat, soit d'un pointeur de connexion. Vous utiliserez le pointeur de connexion si mysql_store_result() ou mysql_use_result() ont retournés NULL (et que donc, vous n'avez pas de pointeur sur résultat). Dans ce cas, vous pouvez appeler mysql_field_count() pour déterminer si mysql_store_result() aurait dû retourner un résultat non vide. Cela permet au client d'effectuer les bonnes actions sans savoir si la requête était un SELECT (ou équivalent). L'exemple ci-dessous montre comment cela doit être utilisé.

Voir Section 24.2.13.1, « Pourquoi est-ce que mysql_store_result() retourne parfois NULL après que mysql_query() a réussi ».

Valeur de retour

Un entier non signé représentant le nombre de champs dans un jeu de résultats.

Erreurs

Aucune.

Exemple

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
// erreur
}
else // la requête fonctionne, on s'occupe des données
{
result = mysql_store_result(&mysql);
if (result)  // il y a des lignes
{
num_fields = mysql_num_fields(result);
// recupérer les lignes, puis appeler mysql_free_result(result)
}
else  // mysql_store_result() n'a rien retourné ! pourquoi ?
{
if (mysql_errno(&mysql))
{
fprintf(stderr, "Erreur : %s\n", mysql_error(&mysql));
}
else if (mysql_field_count(&mysql) == 0)
{
// la requête ne retourne pas de données
// (ce n'était pas un SELECT)
num_rows = mysql_affected_rows(&mysql);
}
}
}

Une autre voie (si vous savez que votre requête aurait dû retourner des résultats) est de remplacer l'appel à mysql_errno(&mysql) par un test sur la nullité de mysql_field_count(&mysql). Cela n'arrive que si un problème a été rencontré.

24-B-3-ap - mysql_num_rows()

my_ulonglong mysql_num_rows(MYSQL_RES *result)

Description

Retourne le nombre de lignes présentes dans le résultat.

L'utilisation de mysql_num_rows() dépend de si vous utilisez mysql_store_result() ou mysql_use_result() pour retourner le jeu de résultats. Si vous utilisez mysql_store_result(), mysql_num_rows() peut être appelé immédiatement. Si vous utilisez mysql_use_result(), mysql_num_rows() ne retournera pas la valeur correcte tant que toutes les lignes du résultat n'auront pas été récupérées.

Valeur de retour

Le nombre de lignes dans le résultat.

Erreurs

Aucune.

24-B-3-aq - mysql_options()

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)

Description

Cette fonction peut être utilisée pour spécifier des options de connexion et modifier le comportement de la session courante. Cette fonction peut être appelée plusieurs fois pour définir plusieurs options.

mysql_options() doit être appelée après mysql_init() et avant mysql_connect() ou mysql_real_connect().

L'argument option est l'option que vous voulez configurer, l'argument arg est la valeur pour cette option. Si l'option est un entier, arg doit pointer sur la valeur d'un entier.

Les valeurs possibles pour les options sont :

Option

Type de l'argument

Fonction

MYSQL_OPT_CONNECT_TIMEOUT

unsigned int *

Délai d'inactivité maximal permis.

MYSQL_OPT_READ_TIMEOUT

unsigned int *

Délai d'expiration pour les lectures depuis le serveur (fonctionne uniquement sur Windows sur les connexions TCP/IP)

MYSQL_OPT_WRITE_TIMEOUT

unsigned int *

Délai pour les écritures sur le serveur (fonctionne uniquement sur Windows sur les connexions TCP/IP)

MYSQL_OPT_COMPRESS

Non utilisé

Utiliser le protocole compressé client/serveur.

MYSQL_OPT_LOCAL_INFILE

pointeur optionnel sur uint

Si aucun pointeur n'est donné, ou que celui-ci pointe sur un unsigned int != 0 la commande LOAD LOCAL INFILE est activée.

MYSQL_OPT_NAMED_PIPE

Non utilisé

Utiliser les pipes nommés pour se connecter au serveur MySQL sur NT.

MYSQL_INIT_COMMAND

char *

Commande à exécuter lors de la connexion au serveur MySQL. Sera automatiquement réexécutée lors des reconnexions.

MYSQL_READ_DEFAULT_FILE

char *

Lit les options à partir du fichier d'options nommé plutôt que de my.cnf.

MYSQL_READ_DEFAULT_GROUP

char *

Lit les options à partir du groupe spécifié dans le fichier d'options my.cnfou le fichier spécifié par MYSQL_READ_DEFAULT_FILE.

MYSQL_OPT_PROTOCOL

unsigned int *

Type de protocole à utiliser. Doit être une des valeurs de mysql_protocol_type définies dans mysql.h.

MYSQL_SHARED_MEMORY_BASE_NAME

char*

Nom d'un objet de mémoire partagée pour communiquer avec le serveur. Doit être le même que l'option -shared-memory-base-name utilisé pour le serveur mysqld auquel vous voulez vous connecter.

Notez que le groupe client est toujours lu si vous utilisez MYSQL_READ_DEFAULT_FILE ou MYSQL_READ_DEFAULT_GROUP.

Le groupe spécifié dans le fichier des options peut contenir les options suivantes :

Option

Description

connect-timeout

Délai d'inactivité maximal permis en secondes. Sous Linux, ce délai est aussi utilisé lors de l'attente de la première réponse du serveur.

compress

Utiliser le protocole compressé client/serveur.

database

Se connecter à cette base de données si aucune base n'a été sélectionnée à la connexion.

debug

Options de débogage.

disable-local-infile

Interdit l'utilisation de LOAD DATA LOCAL.

host

Nom d'hôte par défaut.

init-command

Commande lors de la connexion au serveur MySQL. Sera automatiquement réexécutée lors des reconnexions.

interactive-timeout

Revient à spécifier CLIENT_INTERACTIVE à mysql_real_connect(). Voir Section 24.2.3.46, « mysql_real_connect() ».

local-infile[=(0|1)]

Si aucun argument, ou argument != 0, on permet alors l'utilisation de LOAD DATA LOCAL.

max_allowed_packet

Taille maximale de paquet que le client peut lire du serveur.

password

Mot de passe par défaut.

pipe

Utiliser les tunnels nommés pour se connecter à MySQL sur NT.

protocol=(TCP | SOCKET | PIPE | MEMORY)

Le protocole utilisé lors de la connexion au serveur (nouveau en version 4.1).

port

Port par défaut.

return-found-rows

Demande à mysql_info() de retourner les lignes trouvées au lieu des lignes mises à jour lors de l'utilisation de UPDATE.

shared-memory-base-name=name

Nom de l'objet en mémoire partagée à utiliser pour se connecter au serveur (par défaut, c'est "MySQL"). Nouveau en MySQL 4.1.

socket

Numéro de socket par défaut.

user

Utilisateur par défaut.

Notez que timeout a été remplacé par connect-timeout, mais que timeout fonctionne encore pour le moment.

Pour plus d'informations sur les fichiers d'options, reportez-vous à Section 4.3.2, « Fichier d'options my.cnf ».

Valeur de retour

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Exemple

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
fprintf(stderr, "Impossible de se connecter à la base de données. Erreur : %s\n",
mysql_error(&mysql));
}

Ce qui précède demande au client d'utiliser le protocole compressé client/serveur et lit les options optionnelles de la section odbc dans le fichier my.cnf.

24-B-3-ar - mysql_ping()

int mysql_ping(MYSQL *mysql)

Description

Vérifie si la connexion au serveur est encore assurée. Si ce n'est pas le cas, une reconnexion automatique est tentée.

Cette fonction peut être utilisée par les clients qui restent inactifs longtemps, pour vérifier que le serveur n'a pas fermé la connexion et se reconnecter si nécessaire.

Valeur de retour

Zéro si le serveur répond. Autre que zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-as - mysql_query()

int mysql_query(MYSQL *mysql, const char *query)

Description

Exécute la requête SQL pointée par la chaîne terminée par null query. La requête doit se composer d'une seule opération. Vous ne devez pas ajouter de caractère de terminaison (';') ou \g à la fin de la requête.

mysql_query() ne peut être utilisée pour les requêtes contenant des données binaires, vous devez utiliser mysql_real_query() à la place. (Les données binaires peuvent contenir le caractère '\0', qui est interprété comme la fin de la chaîne requête.)

Si vous voulez savoir si la requête doit retourner un jeu de résultats ou non, vous pouvez utiliser mysql_field_count() pour vérifier. Voir Section 24.2.3.20, « mysql_field_count() ».

Valeur de retour

Zéro si la requête a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-at - mysql_real_connect()

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)

Description

mysql_real_connect() essaye de se connecter à une base de données MySQL tournant sur l'hôte. mysql_real_connect() doit se terminer correctement avant que vous ne puissiez aucune autre fonction de l'API, à l'exception de mysql_get_client_info().

Les paramètres sont spécifiés comme suit.

- Le premier paramètre doit être l'adresse d'une structure MYSQL existante. Avant d'appeler mysql_real_connect() vous devez appeler mysql_init() pour initialiser la structure MYSQL. Vous pouvez changer un tas d'options de connexion en appelant mysql_options(). Voir Section 24.2.3.43, « mysql_options() ».

- La valeur de host peut être un nom de domaine ou une adresse IP. Si host est NULL ou égal à la chaîne "localhost", une connexion à la machine locale est essayée. Si le système supporte les sockets (Unix) ou les tunnels nommés (Windows), elles sont utilisées au lieu de TCP/IP pour se connecter au serveur.

- La paramètre user contient l'identifiant MySQL de l'utilisateur. Si user est NULL, l'utilisateur courant est sous-entendu. Avec Unix c'est l'utilisateur courant. Avec Windows ODBC, le nom de l'utilisateur courant doit être spécifié explicitement. Voir Section 25.1.9.2, « Configuration du DSN MyODBC sur Windows ».

- Le paramètre passwd contient le mot de passe de user. Si passwd est NULL, seules les entrées de la table user pour l'utilisateur ayant un champ vide seront testées. Cela permet à l'administrateur de mettre en place le système de privilèges MySQL de façon à ce que les utilisateurs aient divers privilèges selon qu'ils ont spécifié ou pas de mot de passe.
Note : N'essayez pas d'encrypter le mot de passe avant l'appel à mysql_real_connect(), l'encryptage du mot de passe est géré automatiquement par l'API du client.

- db est le nom de la base de données. Si db n'est pas NULL, la connexion changera la base par défaut en cette valeur.

- Si port est différent de 0, sa valeur sera utilisée comme port de connexion TCP/IP. Notez que le paramètre host détermine le type de la connexion.

- Si unix_socket n'est pas NULL, la chaîne spécifie la socket ou le tunnel nommé à utiliser. Notez que le paramètre host détermine le type de la connexion.

- La valeur de client_flag est habituellement 0, mais peut être la combinaison des options suivantes dans des circonstances très spéciales :

Nom de l'option

Description

CLIENT_COMPRESS

Utilise le protocole compressé.

CLIENT_FOUND_ROWS

Retourne le nombre de lignes trouvées, et non de lignes affectées.

CLIENT_IGNORE_SPACE

Autorise les espaces après les noms de fonctions. Rend tous les noms de fonctions des mots réservés.

CLIENT_INTERACTIVE

Autorise interactive_timeout secondes (au lieu de wait_timeout secondes) d'inactivité avant de fermer la connexion.

CLIENT_LOCAL_FILES

Active le support de LOAD DATA LOCAL.

CLIENT_MULTI_STATEMENTS

Indique au serveur que le client peut envoyer des requêtes multiples (séparées par des ';'). Si cette option n'est pas configurée, les commandes multiples sont désactivées. Nouveau en 4.1.

CLIENT_MULTI_RESULTS

Indique au serveur que le client peut gérer des jeux de résultats multiples, issus de commandes multiples, ou de procédures stockées. C'est automatique si l'option CLIENT_MULTI_STATEMENTS est active. Nouveau en 4.1.

CLIENT_NO_SCHEMA

N'autorise pas la syntaxe db_name.tbl_name.col_name. Cela est fait pour ODBC. Il fait générer une erreur à l'analyseur si vous utilisez cette syntaxe, ce qui peut se révéler fort utile pour la chasse aux bogues dans les programmes ODBC.

CLIENT_ODBC

Le client est un client ODBC. Cela rend mysqld plus accueillant vis-à-vis de ODBC.

CLIENT_SSL

Utilise SSL (protocole encrypté).

Valeur de retour

Un gestionnaire de connexions MYSQL* si la connexion a réussi, NULL si elle a échoué. Pour une connexion à succès, la valeur de retour est la même que la valeur du premier paramètre.

Erreurs

- CR_CONN_HOST_ERROR
Impossible de se connecter au serveur MySQL.

- CR_CONNECTION_ERROR
Impossible de se connecter au serveur MySQL local.

- CR_IPSOCK_ERROR
Impossible de créer une socket IP.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SOCKET_CREATE_ERROR
Impossible de créer une socket UNIX.

- CR_UNKNOWN_HOST
Impossible de trouver l'adresse IP de l'hôte.

- CR_VERSION_ERROR
Une disparité de protocole a résulté de la tentative de connexion à un serveur avec une bibliothèque de client qui utilise une version différente du protocole. Cela peut arriver si vous utilisez une très vieille bibliothèque cliente pour vous connecter à un serveur qui n'a pas été démarré avec l'option --old-protocol.

- CR_NAMEDPIPEOPEN_ERROR
Impossible de créer un tunnel nommé sur Windows.

- CR_NAMEDPIPEWAIT_ERROR
Impossible d'attendre un tunnel nommé sur Windows.

- CR_NAMEDPIPESETSTATE_ERROR
Impossible d'obtenir un gestionnaire de tunnels sur Windows.

- CR_SERVER_LOST
Si connect_timeout > 0 et qu'il a fallu plus de connect_timeout secondes pour se connecter au serveur, ou que celui-ci n'a plus répondu durant l'exécution de init-command.

Exemple

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
fprintf(stderr, "Impossible de se connecter à la base de données, erreur : %s\n",
mysql_error(&mysql));
}

En utilisant mysql_options() la bibliothèque MySQL lira les sections [client] et [your_prog_name] dans le fichier my.cnf ce qui assurera le bon fonctionnement de votre programme, même si quelqu'un a configuré MySQL d'une façon non standard.

Notez que pendant la connexion, mysql_real_connect() configure l'option reconnect (partie de la structure MYSQL) à 1. Cette option indique, dans le cas où une requête ne peut être exécutée à cause d'une déconnexion, d'essayer de se reconnecter au serveur avant d'abandonner.

24-B-3-au - mysql_real_escape_string()

unsigned long mysql_real_escape_string(MYSQL *mysql, char *en, const char *de, unsigned long longueur)

Description

Cette fonction est utilisée pour créer une requête SQL légale que vous pouvez utiliser dans une commande SQL. Voir Section 9.1.1, « Chaînes ».

La string dans de est encodée en chaîne échappé SQL, prenant en compte le jeu de caractères de la connexion. Le résultat est placé dans en et un octet nul de terminaison est ajouté à la fin de celui-ci. Les caractères encodés sont NUL (ASCII 0), '\n', '\r', '\', ''', '"', et Ctrl-Z ( Voir Section 9.1, « Littéraux : comment écrire les chaînes et les nombres »). (En fait, MySQL a seulement besoin que l'antislash et le guillemet utilisé pour entourer la chaîne soient échappés. Cette fonction échappe les autres caractères pour les rendre plus faciles à lire dans les fichiers de log.)

La chaîne pointée par de doit avoir une taille de longueur octets. Vous devez allouer à l'espace de en au moins longueur*2+1 octets. (Dans le pire des cas, chaque caractère devra être encodé en utilisant deux octets, et vous avez besoin de place pour l'octet nul de terminaison.) Lorsque mysql_escape_string() retourne un résultat, le contenu de en sera une chaîne terminée par un caractère nul. La valeur de retour est la longueur de la chaîne encodée, n'incluant pas le caractère nul de terminaison.

Exemple

char query[1000],*end;

end = strmov(query,"INSERT INTO test_table values(");
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"C'est quoi ça",11);
*end++ = '\'';
*end++ = ',';
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"donnée binaire : \0\r\n",16);
*end++ = '\'';
*end++ = ')';

if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
{
fprintf(stderr, "Impossible d'insérer la ligne, erreur : %s\n",
mysql_error(&mysql));
}

La fonction strmov() utilisée dans cet exemple est incluse dans la bibliothèque mysqlclient et fonctionne comme strcpy() mais retourne un pointeur sur le nul de fin du premier paramètre.

Valeur de retour

La longueur de la valeur passée dans to, n'incluant pas le caractère nul de fin de chaîne.

Erreurs

Aucune.

24-B-3-av - mysql_real_query()

int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)

Description

Exécute la requête SQL pointée par query, qui doit être une chaîne de caractères de length octets de longueur. La requête ne doit contenir qu'une seule commande. Vous ne devez pas ajouter de point-virgule (';') ou \g à la fin de la requête.

Vous devez utiliser mysql_real_query() au lieu de mysql_query() pour les requêtes qui contiennent des données binaires, car celles-ci peuvent contenir le caractère'\0'. De plus, mysql_real_query() est plus rapide que mysql_query() car elle n'invoque pas strlen() sur la chaîne contenant la requête.

Si vous voulez savoir si la requête est censée retourner un jeu de résultats ou non, vous pouvez utiliser mysql_field_count() pour vérifier cela. Voir Section 24.2.3.20, « mysql_field_count() ».

Valeur de retour

Zéro si la requête a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-aw - mysql_reload()

int mysql_reload(MYSQL *mysql)

Description

Demande au serveur MySQL de recharger les tables de droits. L'utilisateur doit avoir les droits RELOAD.

Cette fonction est déconseillée. Il est préférable d'utiliser mysql_query() pour exécuter une requête FLUSH PRIVILEGES à la place.

Valeur retournée

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-ax - mysql_row_seek()

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)

Description

Déplace le curseur de ligne vers une ligne arbitraire dans un jeu de résultats de requête. Cela nécessite que le jeu de résultats contienne la totalité des lignes retournées par la requête, et donc, mysql_row_seek() ne peut être utilisée qu'en conjonction avec mysql_store_result(), et non avec mysql_use_result().

La position doit être une valeur retournée par un appel à mysql_row_tell() ou à mysql_row_seek(). Cette valeur n'est pas un simple numéro de ligne, si vous voulez vous déplacer dans un jeu de résultats en utilisant le numéro d'une ligne, utilisez mysql_data_seek().

Valeur de retour

La position précédente du curseur de ligne. Cette valeur peut être passée à mysql_row_seek().

Erreurs

Aucune.

24-B-3-ay - mysql_row_tell()

MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)

Description

Retourne la position courante du pointeur de lignes pour le dernier appel à mysql_fetch_row(). Cette valeur peut être utilisée comme argument de mysql_row_seek().

Vous ne devez utiliser mysql_row_tell() qu'après mysql_store_result(), et non après mysql_use_result().

Valeur de retour

La position courante du pointeur de ligne.

Erreurs

Aucune.

24-B-3-az - mysql_select_db()

int mysql_select_db(MYSQL *mysql, const char *db)

Description

Rend la base de données spécifiée par db la base par défaut (courante) pour la connexion spécifiée par mysql. Pour les requêtes suivantes, cette base de données sera utilisée comme référence pour les tables dont la base de données n'a pas été spécifiée explicitement.

mysql_select_db() échoue si l'utilisateur ne peut être reconnu ayant droit d'accès à la base de données.

Valeur de retour

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-ba - mysql_set_server_option()

int mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)

Description

Active ou désactive une option de connexion. Le paramètre option peut prendre l'une des valeurs suivantes :

MYSQL_OPTION_MULTI_STATEMENTS_ON

Active le support des commandes multiples.

MYSQL_OPTION_MULTI_STATEMENTS_OFF

Désactive le support des commandes multiples.

Valeur retournée

Zéro en cas de succès. Non nul si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- ER_UNKNOWN_COM_ERROR
Le serveur ne supporte pas mysql_set_server_option() (ce qui peut être le cas d'un serveur antérieur à la version 4.1.1) ou le serveur ne supporte pas l'option qui a été utilisée.

24-B-3-bb - mysql_shutdown()

int mysql_shutdown(MYSQL *mysql)

Description

Demande au serveur de base de données de se terminer. L'utilisateur connecté doit avoir le droit SHUTDOWN.

Valeur de retour

Zéro si la commande a été effectuée avec succès. Différente de zéro si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-bc - mysql_sqlstate()

const char *mysql_sqlstate(MYSQL *mysql)

Description

Retourne une chaîne terminée par null, contenant le code d'erreur SQLSTATE de la dernière erreur. Le code d'erreur est constitué de 5 caractères. '00000' signifie « pas d'erreur ». Les valeurs sont spécifiées par les normes ANSI SQL et ODBC. Pour une liste des valeurs possibles, voyez Chapitre 26, Gestion des erreurs avec MySQL.

Notez que les erreurs MySQL ne sont pas toutes associées à une erreur SQLSTATE. La valeur 'HY000' (erreur générale) est utilisée pour ces erreurs.

Cette fonction a été ajoutée en MySQL 4.1.1.

Valeur retournée

Une chaîne terminée par null, qui contient le code d'erreur SQLSTATE.

Voir aussi

Voir Section 24.2.3.12, « mysql_errno() ». Voir Section 24.2.3.13, « mysql_error() ». Voir Section 24.2.7.26, « mysql_stmt_sqlstate() ».

24-B-3-bd - mysql_ssl_set()

int mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher)

Description

mysql_ssl_set() sert à établir des connexions sécurisées par SSL. Elle doit être appelée avec mysql_real_connect().

mysql_ssl_set() ne fait rien à moins que le support OpenSSL soit activé dans la bibliothèque cliente.

mysql est un gestionnaire de connexions, retourné par mysql_init(). Les autres paramètres sont les suivants.

- key est le chemin jusqu'au fichier de clé.

- cert est le chemin jusqu'au fichier de certificat.

- ca est le chemin jusqu'au fichier d'autorité de certification.

- capath est le chemin jusqu'au dossier qui contient les autorités de certification SSL reconnues, au format PEM.

- cipher est une liste de chiffrements autorisés avec SSL.

Tous les paramètres SSL inutilisés doivent être fournis avec la valeur NULL.

Valeur retournée

Cette fonction retourne toujours 0. Si la configuration SSL est incorrecte, mysql_real_connect() va retourner une erreur lors de la tentative de connexion.

24-B-3-be - mysql_stat()

char *mysql_stat(MYSQL *mysql)

Description

Retourne une chaîne de caractères contenant des informations similaires à celles fournies par la commande mysqladmin status. Cela inclut le temps de fonctionnement en secondes et le nombre de threads en cours d'exécution, questions, rechargement, et tables ouvertes.

Valeur de retour

Une chaîne de caractères décrivant l'état du serveur. NULL si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-bf - mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql)

Description

Vous devez appeler mysql_store_result() ou mysql_use_result() pour chaque requête qui récupère des données avec succès (SELECT, SHOW, DESCRIBE, EXPLAIN).

Vous n'avez pas à appeler mysql_store_result() ou mysql_use_result() pour d'autres requêtes, mais cela ne posera pas de problèmes ou ne ralentira pas vos scripts si vous appelez mysql_store_result() en tout cas. Vous pouvez savoir si la requête n'a pas renvoyé de résultat en vérifiant si mysql_store_result() retourne 0 (nous verrons cela plus tard).

Si vous voulez savoir si la requête devrait renvoyer un jeu de résultats ou non, vous pouvez utiliser mysql_field_count() pour vérifier. Voir Section 24.2.3.20, « mysql_field_count() ».

mysql_store_result() lit le résultat en entier et le stocke dans le client, alloue une structure MYSQL_RES, et place le résultat dans cette structure.

mysql_store_result() retourne un pointeur nul si la requête n'a pas retourné un jeu de résultats (si la requête était, par exemple, un INSERT).

mysql_store_result() retourne aussi un pointeur nul si la lecture à partir du jeu de résultats échoue. Vous pouvez vérifier la présence d'erreurs en regardant si mysql_error() ne retourne pas de pointeur nul, si mysql_errno() retourne <> 0, ou si mysql_field_count() retourne <> 0.

Un jeu de résultat vide est retourné si aucune ligne n'est retournée. (Un jeu de résultats vide diffère d'un pointeur nul en tant que valeur de retour.)

Une fois que vous avez appelé mysql_store_result() et obtenu un résultat qui n'est pas un pointeur nul, vous devez appeler mysql_num_rows() pour trouver combien de lignes contient le jeu de résultats.

Vous pouvez appeler mysql_fetch_row() pour récupérer des lignes à partir du jeu de résultats, ou mysql_row_seek() et mysql_row_tell() pour obtenir ou changer la ligne courante dans le jeu de résultats.

Vous devez appeler mysql_free_result() une fois que vous n'avez plus besoin du résultat.

Voir Section 24.2.13.1, « Pourquoi est-ce que mysql_store_result() retourne parfois NULL après que mysql_query() ait réussi ».

Valeur de retour

Une structure de résultat MYSQL_RES. NULL si une erreur survient.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-bg - mysql_thread_id()

unsigned long mysql_thread_id(MYSQL *mysql)

Description

Retourne l'identifiant du thread de la connexion courante. Cette valeur peut être utilisée comme argument de mysql_kill() pour terminer ce thread.

Si la connexion est perdue et que vous vous reconnectez via mysql_ping(), l'identifiant du thread changera. Cela signifie que cela ne sert à rien de récupérer l'identifiant du thread et de le sauvegarder pour l'utiliser plus tard. Vous devez le récupérer quand vous en avez besoin.

Valeur de retour

L'identifiant du thread de la connexion courante.

Erreurs

Aucune.

24-B-3-bh - mysql_use_result()

MYSQL_RES *mysql_use_result(MYSQL *mysql)

Description

Vous devez appeler mysql_store_result() ou mysql_use_result() pour chaque requête qui récupère des données avec succès (SELECT, SHOW, DESCRIBE, EXPLAIN).

mysql_use_result() initialise un jeu de résultats, mais ne l'enregistre pas dans le client comme le fait mysql_store_result(). À la place, chaque ligne doit être récupérée manuellement à l'aide de la commande mysql_fetch_row(). Cela lit le résultat directement à partir du serveur sans l'enregistrer dans une table temporaire ou un tampon local, ce qui est plus rapide et utilise moins de mémoire que mysql_store_result(). Le client n'allouera de la mémoire que pour la ligne courante et un tampon de communication qui peut aller jusqu'à max_allowed_packet octets.

D'une autre côté, vous ne devez pas utiliser mysql_use_result() si vous faites beaucoup de traitements pour chaque ligne côté client, ou que le résultat est envoyé à un écran où l'utilisateur peut entrer ^S (arrêt défilement). Cela bloquera le serveur et empêchera les autres threads de mettre à jour n'importe quelle table à partir de laquelle les données sont lues.

Lors de l'utilisation de mysql_use_result(), vous devez exécuter mysql_fetch_row() jusqu'à ce que NULL soit retourné, sinon, les lignes non retournées seront incluses dans le jeu de résultats de votre prochaine requête. L'API C donnera l'erreur Commands out of sync; you can't run this command now si vous oubliez de le faire !

Vous ne devez pas utiliser mysql_data_seek(), mysql_row_seek(), mysql_row_tell(), mysql_num_rows(), ou mysql_affected_rows() avec un résultat retourné par mysql_use_result(), de même, vous ne devez pas exécuter d'autres requêtes tant que la commande mysql_use_result() n'est pas terminée. (Toutefois, après avoir récupéré toutes les lignes, mysql_num_rows() retournera correctement le nombre de lignes récupérées.)

Vous devez appeler mysql_free_result() lorsque vous n'avez plus besoin du jeu de résultats.

Valeur de retour

Une structure de résultat MYSQL_RES. NULL si une erreur survient.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes n'ont pas été exécutées dans le bon ordre.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL ne répond pas.

- CR_SERVER_LOST
La connexion au serveur a été perdue au cours la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue s'est produite.

24-B-3-bi - mysql_warning_count()

unsigned int mysql_warning_count(MYSQL *mysql)

Description

Retourne le nombre d'alertes générées durant l'exécution de la dernière commande SQL. Disponible depuis MySQL 4.1.

Valeur retournée

Le nombre d'alertes.

Erreurs

Aucune.

24-B-3-bj - mysql_commit()

my_bool mysql_commit(MYSQL *mysql)

Description

Valide la transaction courante. Disponible depuis MySQL 4.1

Valeurs retournées

Zéro si la fonction réussit, non nul si une erreur survient.

Erreurs

Aucune

24-B-3-bk - mysql_rollback()

my_bool mysql_rollback(MYSQL *mysql)

Description

Annule la transaction courante. Disponible avec MySQL 4.1

Valeurs retournées

Zéro si l'annulation a réussi, et non nul si une erreur est survenue.

Erreurs

Aucune.

24-B-3-bl - mysql_autocommit()

my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)

Description

Active ou désactive le mode d'autovalidation (autocommit). Si le paramètre mode vaut 1, l'autovalidation est activée. Dans le cas où il vaut 0, l'autovalidation est désactivée. Disponible depuis MySQL 4.1

Valeurs retournées

Zéro si la fonction réussit. Non nul si une erreur survient.

Erreurs

Aucune.

24-B-3-bm - mysql_more_results()

my_bool mysql_more_results(MYSQL *mysql)

Description

Retourne TRUE s'il y a d'autres résultats disponibles pour la requête courante, et si l'application doit appeler mysql_next_result() pour lire ces résultats. Disponible en MySQL 4.1

Valeurs retournées

TRUE si d'autres résultats existent. FALSE s'il n'y a plus d'autres résultats disponibles.

Notez que dans la plupart des cas, vous pouvez appeler mysql_next_result() pour voir s'il existe plus d'un résultat, et initier le prochain jeu de résultats si c'est le cas.

Voir Section 24.2.9, « Gestion des commandes multiples avec l'interface C ». Voir Section 24.2.3.66, « mysql_next_result() ».

Erreurs

Aucune.

24-B-3-bn - mysql_next_result()

int mysql_next_result(MYSQL *mysql)

Description

S'il existe des résultats disponibles, mysql_next_result() va lire la prochaine ligne, et retourne son statut à l'application. Disponible depuis MySQL 4.1

Notez que vous devez appeler mysql_free_result() pour la précédente requête, si elle retournait un jeu de résultats.

Après avoir appelé mysql_next_result() l'état de la connexion est le même que si vous aviez appelé mysql_real_query() pour la requête suivante. Cela signifie que vous pouvez maintenant appeler mysql_store_result(), mysql_warning_count(), mysql_affected_rows(), etc. sur la connexion.

Si mysql_next_result() retourne une erreur, aucune autre commande ne pourra être exécutée, et il n'y a pas d'autres résultats à lire.

Voir Section 24.2.9, « Gestion des commandes multiples avec l'interface C ».

Valeurs retournées

Valeur retournée

Description

0

Requête réussie et il reste des résultats

-1

Requête réussie et il ne reste pas de résultat

>0

Une erreur est survenue

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide. Par exemple, si vous n'avez pas appelé mysql_use_result() avec un résultat précédent.

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_SERVER_LOST
La connexion au serveur a été perdue durant la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

24-B-4 - Fonctions C de commandes préparées

Depuis MySQL 4.1, vous pouvez aussi utiliser les commandes préparées en utilisant le gestionnaire « MYSQL_STMT », qui supporte l'exécution de commandes multiples, avec liaison en entrée et sortie.

L'exécution de requêtes préparées est un moyen efficace d'exécuter une requête plus d'une fois. La requête est préparée, ou analysée une première fois. Elle est ensuite exécutée une ou plusieurs fois plus tard, en utilisant un pointeur de commandes qui est retourné durant la préparation.

Un autre avantage des commandes préparées est qu'elles utilisent un protocole binaire qui rend les transferts entre le client et le serveur bien plus efficaces que l'ancien protocole MySQL.

Les commandes préparées sont plus rapides que les exécutions directes de requêtes qui sont exécutées plus d'une fois, notamment parce que la requête est analysée une seule fois. Dans le cas de l'exécution directe, la requête est analysée à chaque fois. Les commandes préparées permettent de réduire le trafic réseau durant l'exécution, car seules les données paramètres sont échangées.

24-B-5 - Types de données de l'API C

Note : les requêtes préparées sont susceptibles d'être revues. Les informations ci-dessous sont destinées aux nouveaux utilisateurs, mais soyez prévenus qu'elles peuvent changer. Des modifications incompatibles ont été faites en MySQL 4.1.2. Voyez Section 24.2.7, « Description des fonctions C pour les requêtes préparées » pour plus de détails.

Les requêtes préparées utilisent principalement les deux structures MYSQL_STMT et MYSQL_BIND :

- MYSQL_STMT
Cette structure représente un pointeur de commandes sur une commande préparée. Elle sert pour toutes les fonctions liées aux commandes.
La commande est initialisée lorsque la requête est préparée en utilisant mysql_prepare().
La structure est utilisée par toutes les fonctions ultérieures, liées aux commandes préparées.
La structure MYSQL_STMT n'a pas de membre utilisable par l'application.
Une connexion peut avoir de multiples pointeurs de commandes, et la limite ne dépend que des ressources système.

- MYSQL_BIND
Cette structure est utilisée pour lier les paramètres avec des buffers, avec mysql_bind_param(), pour utilisation avec mysql_execute(), ainsi que pour lier les résultats avec des buffers via mysql_bind_result()m, lors de la lecture de données avec mysql_fetch().
La structure MYSQL_BIND contient les membres suivants. Chacun est utilisé pour la lecture et l'écriture, mais leur objectif est parfois différent, en fonction du sens de communication.

- enum enum_field_types buffer_type
Le type de buffer. Les valeurs possibles pour buffer_type sont listées plus loin dans cette section. Pour l'envoi, buffer_type indique le type de valeur que vous allez fournir, lors de l'association de paramètres. Pour la réception, cela indique le type de valeur que vous pouvez lire dans le buffer de résultats.

- void *buffer
Pour l'envoi, c'est un pointeur sur le buffer où sont stockées les valeurs du paramètre de la requête. Pour la réception, c'est un pointeur sur la valeur retournée. Pour les types numériques, buffer pointe sur une variable avec le bon type C. Si vous associez la variable avec une colonne qui a un attribut UNSIGNED, la variable doit être de type C unsigned. Pour les colonnes de type date, buffer doit pointer sur une structure MYSQL_TIME. Pour les caractères et les chaînes binaires, buffer doit pointer sur un buffer de caractères.

- unsigned long buffer_length
La taille de *buffer en octets. Pour les caractères et les données binaires C, buffer_length spécifie la taille de *buffer à utiliser comme paramètre s'il est utilisé avec mysql_bind_param(), ou la taille lue dans le résultat s'il est utilisé avec mysql_bind_result().

- long *length
Un pointeur sur une variable unsigned long qui indique le nombre réel d'octets stockés dans *buffer. length est utilisé pour les données de type caractère ou binaire. Pour l'envoi de données, length pointe sur une variable unsigned long qui indique la taille des valeurs des paramètres stockés dans *buffer, cette valeur est utilisée par mysql_execute(). Si length est un pointeur null, le protocole suppose que les données caractères ou binaires sont terminées par null. Pour la lecture, mysql_fetch() place la taille de la valeur de la colonne retournée dans la variable length.
length est ignorée pour les valeurs numériques et temporelles, car la taille de ces valeurs est déterminée par la valeur de buffer_type.

- my_bool *is_null
Ce membre pointe sur une variable my_bool qui est true si la valeur est NULL, et false si elle n'est pas NULL. Pour l'envoi, donnez à *is_null la valeur de true pour indiquer que la valeur que vous émettez est NULL. Pour la réception, cette valeur sera true après avoir lu une ligne si le résultat est NULL.

- MYSQL_TIME
Cette structure est utilisée pour écrire et lire des données de type DATE, TIME et TIMESTAMP, directement avec le serveur. Cela se fait en donnant au membre buffer_type d'une structure MYSQL_BIND un des types temporels, et en donnant au membre buffer un pointeur sur une structure MYSQL_TIME.
La structure MYSQL_TIME contient les membres suivants :

- unsigned int year
L'année.

- unsigned int month
Le mois de l'année.

- unsigned int day
Le jour du mois.

- unsigned int hour
L'heure du jour.

- unsigned int minute
La minute de l'heure.

- unsigned int second
La seconde de la minute.

- my_bool neg
Un booléen pour indiquer que le temps est négatif.

- unsigned long second_part
La partie décimale de la seconde. Ce membre est actuellement inutilisé.

Seuls les membres d'une structure MYSQL_TIME qui s'appliquent à une valeur sont utilisés : les éléments year, month et day sont utilisés pour les types DATE, DATETIME et TIMESTAMP, les éléments hour, minute et second sont utilisés pour les types TIME, DATETIME et TIMESTAMP. Voir Section 24.2.10, « Gestion des dates et horaires avec l'interface C ».

La table suivante montre les valeurs permises, qui peuvent être spécifiées dans le membre buffer_type des structures MYSQL_BIND. La table montre aussi les types SQL qui correspondent à chaque type de buffer_type, et, pour les types numériques et temporels, le type C correspondant.

buffer_type Valeur

Type SQL

Type C

MYSQL_TYPE_TINY

TINYINT

char

MYSQL_TYPE_SHORT

SMALLINT

short int

MYSQL_TYPE_LONG

INT

long int

MYSQL_TYPE_LONGLONG

BIGINT

long long int

MYSQL_TYPE_FLOAT

FLOAT

float

MYSQL_TYPE_DOUBLE

DOUBLE

double

MYSQL_TYPE_TIME

TIME

MYSQL_TIME

MYSQL_TYPE_DATE

DATE

MYSQL_TIME

MYSQL_TYPE_DATETIME

DATETIME

MYSQL_TIME

MYSQL_TYPE_TIMESTAMP

TIMESTAMP

MYSQL_TIME

MYSQL_TYPE_STRING

CHAR

MYSQL_TYPE_VAR_STRING

VARCHAR

MYSQL_TYPE_TINY_BLOB

TINYBLOB/TINYTEXT

MYSQL_TYPE_BLOB

BLOB/TEXT

MYSQL_TYPE_MEDIUM_BLOB

MEDIUMBLOB/MEDIUMTEXT

MYSQL_TYPE_LONG_BLOB

LONGBLOB/LONGTEXT

Des conversions implicites de type peuvent survenir dans les deux directions de communication.

24-B-6 - Présentation des fonctions de l'interface C

Note : les fonctions pour les commandes préparées sont toujours en cours de développement. Les informations de cette section sont destinées aux premiers utilisateurs, mais il faut être conscient que l'API peut changer. Certains changements sont incompatibles avec MySQL 4.1.2. Voyez Section 24.2.7, « Description des fonctions C pour les requêtes préparées » pour plus de détails.

Voici les fonctions disponibles pour les commandes préparées. Elles sont listées ici et détailles plus loin. Voir Section 24.2.7, « Description des fonctions C pour les requêtes préparées ».

Fonction

Description

mysql_stmt_init()

Alloue la mémoire pour une structure MYSQL_STMT et l'initialise.

mysql_stmt_bind_param()

Associe un buffer avec une variable de requêtes, dans une commande préparée.

mysql_stmt_bind_result()

Lie les buffers de l'application avec les colonnes d'un résultat.

mysql_stmt_execute()

Exécute une commande préparée.

mysql_stmt_fetch()

Lit la prochaine ligne de données dans le résultat, et retourne toutes les données des colonnes liées.

mysql_stmt_fetch_column()

Lit les données d'une seule colonne, dans le résultat.

mysql_stmt_result_metadata()

Retourne les métadonnées de la commande préparée, sous forme d'un jeu de résultats.

mysql_stmt_param_count()

Retourne le nombre de paramètres d'une commande préparée.

mysql_stmt_param_metadata()

Retourne les métadonnées des paramètres, sous forme d'un jeu de résultats.

mysql_stmt_prepare()

Prépare une chaîne SQL pour l'exécution.

mysql_stmt_send_long_data()

Envoie de grandes données par parties.

mysql_stmt_affected_rows()

Retourne le nombre de lignes modifiées, effacées ou insérées dans la dernière requête UPDATE, DELETE ou INSERT.

mysql_stmt_insert_id()

Retourne l'identifiant généré par la colonne AUTO_INCREMENT de la dernière commande préparée.

mysql_stmt_close()

Libère une commande préparée de la mémoire.

mysql_stmt_data_seek()

Se place à un numéro de ligne arbitraire dans un jeu de résultats.

mysql_stmt_errno()

Retourne le numéro d'erreur de la dernière requête.

mysql_stmt_error()

Retourne le message d'erreur de la dernière requête.

mysql_stmt_free_result()

Libère les ressources allouées pour la commande.

mysql_stmt_num_rows()

Retourne le nombre total de lignes dans un jeu de résultats bufferisé.

mysql_stmt_reset()

Remet à zéro les buffers de la commande, sur le serveur.

mysql_stmt_row_seek()

Se place à un numéro de ligne, dans un résultat de commande, en utilisant la valeur retournée par mysql_stmt_row_tell().

mysql_stmt_row_tell()

Retourne la position du curseur de ligne de la commande.

mysql_stmt_sqlstate()

Retourne le code d'erreur SQLSTATE de la dernière opération.

mysql_stmt_store_result()

Lit tout le résultat dans le client.

mysql_stmt_attr_set()

Modifie un attribut d'une commande préparée.

mysql_stmt_attr_get()

Lit la valeur d'un attribut d'une commande préparée.

Appelez mysql_prepare() pour préparer et initialiser la commande, puis appelez mysql_bind_param() pour fournir les données des paramètres, enfin appelez mysql_execute() pour exécuter la requête. Vous pouvez répéter mysql_execute() en modifiant les valeurs des paramètres des buffers respectifs via mysql_bind_param().

Dans le cas où la requête est une commande SELECT, ou toute autre commande qui retourne un résultat, alors mysql_prepare() va aussi retourner les métadonnées de résultat sous la forme d'une structure MYSQL_RES avec mysql_prepare_result().

Vous pouvez fournir les buffers de résultats avec mysql_bind_result(), pour que mysql_fetch() lise automatiquement les résultats dans les buffers. Cela est fait ligne par ligne.

Vous pouvez aussi envoyer le texte ou les données binaires au serveur en utilisant la fonction mysql_stmt_send_long_data(). Voir Section 24.2.7.25, « mysql_stmt_send_long_data() ».

Une fois que l'exécution de la commande est terminée, elle doit être supprimée avec mysql_stmt_close pour que toutes les ressources allouées soient détruites.

Étapes d'exécution

Pour préparer et exécuter une commande, l'application :

1. Appelle mysql_prepare() et passe une chaîne contenant la commande SQL. Si la préparation réussit, mysql_prepare() retourne un pointeur de commande valide.

2. Si la requête a un résultat, alors mysql_prepare_result retourne les méta-informations de résultats.

3. Spécifie les valeurs de tous les paramètres de mysql_bind_param. Tous les paramètres doivent être fournis, sinon, cela générera une erreur, ou engendrera des résultats inattendus.

4. Appelle mysql_execute() pour exécuter la requête.

5. Répète les étapes 2 et 3 autant que nécessaire, en modifiant les valeurs des paramètres, et en exécutant à nouveau la commande.

6. Lie les buffers de données aux lignes de résultats, si la commande génère un résultat, en utilisant mysql_bind_result().

7. Lit les données dans les buffers, ligne par ligne, en appelant mysql_fetch() jusqu'à ce qu'il n'y ait plus de ligne.

Lorsque mysql_prepare() est appelé, dans le protocole client/serveur MySQL :

- Le serveur analyse la requête et envoie le statut OK au client en lui assignant un identifiant de commande. Il renvoie aussi le nombre total de paramètres, le nombre de colonnes et des méta-informations si un résultat est attendu. La syntaxe et la sémantique de la requête sont vérifiées durant cet appel.

- Le client utilise cet identifiant de commande pour les exécutions ultérieures, pour que le serveur identifie la commande dans le pool de commandes. Désormais, le client alloue un pointeur de commande avec cet identifiant, et le retourne à l'application.

Lorsque mysql_execute() est appelé, avec le protocole client/serveur MySQL :

- Le client utilise le pointeur de commande et envoie les paramètres au serveur.

- Le serveur identifie la commande en utilisant l'identifiant, et remplace les marqueurs de paramètres par leur valeur, puis il exécute la requête. Si cela conduit à un résultat, il est retourné au client, ou bien un statut OK, indiquant le nombre total de lignes affectées est retourné.

Lorsque mysql_fetch() est appelé, dans le protocole client/serveur MySQL :

- Le client lit les données dans le paquet, ligne par ligne, et les place dans les buffers de données, avec les conversions nécessaires. Si le type de buffers de l'application est le même que le type de champs, alors les conversions sont immédiates.

Vous pouvez lire les codes et messages d'erreur, ainsi que les codes d'erreur SQLSTATE avec les fonctions mysql_stmt_errno(), mysql_stmt_error() et mysql_stmt_sqlstate(), respectivement.

24-B-7 - Description des fonctions C pour les requêtes préparées

Vous devez utiliser ces fonctions lorsque vous voulez préparer et exécuter des commandes.

Note : l'API des commandes préparées est en cours de révision. Ces informations sont destinées aux nouveaux utilisateurs, mais soyez conscients que l'API peut changer sans préavis.

En MySQL 4.1.2, les noms de plusieurs fonctions de commandes préparées ont changé :

Ancien nom

Nouveau nom

mysql_bind_param()

mysql_stmt_bind_param()

mysql_bind_result()

mysql_stmt_bind_result()

mysql_prepare()

mysql_stmt_prepare()

mysql_execute()

mysql_stmt_execute()

mysql_fetch()

mysql_stmt_fetch()

mysql_fetch_column()

mysql_stmt_fetch_column()

mysql_param_count()

mysql_stmt_param_count()

mysql_param_result()

mysql_stmt_param_metadata()

mysql_get_metadata()

mysql_stmt_result_metadata()

mysql_send_long_data()

mysql_stmt_send_long_data()

Toutes les fonctions qui utilisent une structure MYSQL_STMT sont préfixées par mysql_stmt_.

De plus, en version 4.1.2, la signature de la fonction mysql_stmt_prepare() a changé en int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length). Pour créer un pointeur MYSQL_STMT, utilisez la fonction mysql_stmt_init().

24-B-7-a - mysql_stmt_affected_rows()

my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)

Description

Retourne le nombre total de lignes modifiées par la dernière commande. Cette fonction peut être appelée immédiatement après la fonction mysql_execute() pour les commandes UPDATE, DELETE ou INSERT. Pour les commandes SELECT, mysql_stmt_affected() fonctionne comme mysql_num_rows().

Valeurs retournées

Un entier supérieur à zéro indique le nombre de lignes affectées ou lues. Zéro indique qu'aucune ligne n'a été modifiée durant une commande UPDATE, ou qu'aucune ligne n'a vérifié la clause WHERE dans la requête, ou qu'aucune requête n'a été exécutée. -1 indique que la requête a retourné une erreur, ou que, pour une requête SELECT, mysql_stmt_affected_rows() a été appelée avant mysql_fetch(). Comme mysql_stmt_affected_rows() retourne une valeur non signée, vous pouvez surveiller la valeur -1 en analysant la valeur retournée par (my_ulonglong)-1 (ou (my_ulonglong)~0, qui est équivalent).

Erreurs

Aucune.

Exemple

Pour une illustration de mysql_stmt_affected_rows() voyez l'exemple de Section 24.2.7.10, « mysql_stmt_execute() ».

24-B-7-b - mysql_stmt_attr_get()

int mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, void *arg)

Description

Sert à lire la valeur courante pour un attribut de commande.

L'argument option est le nom de l'option que vous voulez lire, le pointeur arg doit pointer sur une variable qui contient la valeur de l'option. Si l'option est un entier, alors arg doit être un pointeur.

Voyez mysql_stmt_attr_set pour avoir la liste des options et leur type. Voir Section 24.2.7.3, « mysql_stmt_attr_set() ».

Valeur retournée

0 si tout va bien. 1 si attr_type est inconnu.

Erreurs

aucune

24-B-7-c - mysql_stmt_attr_set()

int mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, const void *arg)

Description

Sert à modifier le comportement d'une commande. Cette fonction peut être appelée plusieurs fois.

L'argument option est le nom de l'option que vous voulez modifier, le pointeur arg doit pointer sur une variable qui contient la valeur de l'option. Si l'option est un entier, alors arg doit être un pointeur.

Valeurs possibles pour les options :

Option

Type d'argument

Fonction

STMT_ATTR_UPDATE_MAX_LENGTH

my_bool *

Si la valeur est 1 : modifie les méta-données MYSQL_FIELD->max_length dans mysql_stmt_store_result().

Valeur retournée

0 si tout va bien. 1 si attr_type est inconnu.

Erreurs

aucune

24-B-7-d - mysql_stmt_bind_param()

my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)

Description

mysql_stmt_bind_param() sert à lire des données aux variables de requêtes dans une commande SQL, préparée avec mysql_stmt_prepare(). Elle utilise les structures MYSQL_BIND pour fournir les données. bind est l'adresse d'un tableau de structures MYSQL_BIND. La bibliothèque cliente attend un tableau contenant un élément pour chaque variable de requête '?' qui est présente dans la requête.

Supposez que vous ayez préparé la commande suivante :

INSERT INTO mytbl VALUES(?,?,?)

Lorsque vous liez les paramètres, le tableau de structures MYSQL_BIND doit contenir trois éléments, et peut être déclaré comme ceci :

MYSQL_BIND bind[3];

Les membres de chaque structure MYSQL_BIND doivent être configurés comme décrit dans la section Section 24.2.5, « Types de données de l'API C ».

Valeurs retournées

Zéro, si l'association a réussi. Non nul si une erreur est survenue.

Erreurs

- CR_INVALID_BUFFER_USE
Indique si les données seront fournies par bloc et si le type de buffer n'est pas chaîne, ou binaire.

- CR_UNSUPPORTED_PARAM_TYPE
La conversion n'est pas supportée. Éventuellement, la valeur de buffer_type est invalide, ou n'est pas d'un type supporté.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

Pour un exemple avec mysql_stmt_bind_param(), voyez la fonction Section 24.2.7.10, « mysql_stmt_execute() ».

24-B-7-e - mysql_stmt_bind_result()

my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)

Description

mysql_stmt_bind_result() est utilisé pour lier (bind) les colonnes du résultat aux données et taille des buffers. Lorsque mysql_stmt_fetch() est appelée pour lire les données de la ligne suivante, le protocole client/serveur MySQL place les données des colonnes liées dans le buffer désigné.

Toutes les colonnes doivent être liées avant l'appel à mysql_stmt_fetch(). Le paramètre bind désigne l'adresse d'un tableau de structures MYSQL_BIND. La bibliothèque du client s'attend à recevoir un tableau contenant un élément correspondant à chaque colonne du résultat. Dans le cas contraire, mysql_stmt_fetch() va ignorer la nouvelle ligne lue. Les buffers doivent également être assez grands pour stocker les valeurs, car le protocole ne retourne pas les valeurs par morceaux.

Une colonne peut être liée ou ré-associée à n'importe quel moment, y compris pendant la réception des données. La nouvelle liaison devient effective au prochain appel de mysql_stmt_fetch(). Supposons qu'une application lie les colonnes à un résultat et appelle mysql_stmt_fetch(). Le protocole client/serveur va stocker les données dans les buffers associés. Supposez maintenant que l'application lie les colonnes à un nouveau jeu de buffers. Le protocole ne mettra aucune donnée dans ces nouveaux buffers tant qu'il n'y aura pas de nouvel appel à mysql_stmt_fetch().

Pour lier une colonne, l'application appelle la fonction mysql_stmt_bind_result() en passant le type, l'adresse du buffer et l'adresse de sa taille. Les membres requis de chaque MYSQL_BIND sont décrits Section 24.2.5, « Types de données de l'API C ».

Valeurs retournées

Zéro si la liaison est effectuée avec succès. Une valeur non nulle si une erreur est survenue.

Erreurs

- CR_UNSUPPORTED_PARAM_TYPE
La conversion n'est pas supportée. Il est possible que la valeur de buffer_type soit erronée ou ne fasse pas partie de la liste des types supportés.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

Référez-vous à l'exemple de la Section 24.2.7.13, « mysql_stmt_fetch() » pour l'utilisation de la fonction mysql_stmt_bind_result().

24-B-7-f - mysql_stmt_close()

my_bool mysql_stmt_close(MYSQL_STMT *)

Description

Termine la commande préparée. mysql_stmt_close() va aussi désallouer le pointeur de commande alloué par stmt.

Si les résultats de la requête courante sont en attente, ou non lus, ils seront annulés. Le prochain appel pourra donc être exécuté.

Valeur retournée

Zéro si la commande a pu être terminée. Une valeur non nulle si une erreur est survenue.

Erreurs

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

Pour une illustration de la fonction mysql_stmt_close() voyez un exemple avec Section 24.2.7.10, « mysql_stmt_execute() ».

24-B-7-g - mysql_stmt_data_seek()

void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset)

Description

Place le pointeur de résultats à une ligne arbitraire. La valeur de offset est un numéro de ligne, et doit être dans l'intervalle 0 à mysql_stmt_num_rows(stmt)-1.

Cette fonction impose que la structure du jeu de résultats soit entièrement téléchargée : mysql_stmt_data_seek() ne peut être utilisée qu'avec mysql_stmt_store_result().

Valeurs retournées

Aucune.

Erreurs

Aucune.

24-B-7-h - mysql_stmt_errno()

unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)

Description

Pour la commande spécifiée par stmt, mysql_stmt_errno() retourne le code d'erreur de la plus récente fonction d'API appelée, qu'elle ait réussi ou échoué. Une valeur de zéro indique qu'il n'y a pas eu d'erreur. Les numéros d'erreurs client sont listés dans le fichier d'entêtes errmsg.h. Les messages d'erreurs serveur sont listés dans le fichier d'entêtes mysqld_error.h. Dans la distribution source de MySQLm vous pouvez trouver une liste complète des messages d'erreurs et de leur numéro, dans le fichier Docs/mysqld_error.txt. Les codes d'erreur du serveur sont aussi listés dans Chapitre 26, Gestion des erreurs avec MySQL.

Valeurs retournées

Une valeur représentant un code d'erreur. Zéro représente l'absence d'erreur.

Erreurs

Aucune

24-B-7-i - mysql_stmt_error()

char *mysql_stmt_error(MYSQL_STMT *stmt)

Description

Pour la commande spécifiée par stmt, mysql_stmt_error() retourne le message d'erreur de la fonction d'API la plus récemment appelée, qu'elle ait réussi ou pas. Une chaîne vide ("") est retournée si aucune erreur n'est survenue. Cela signifie que les instructions suivantes sont identiques :

if (mysql_stmt_errno(stmt))
{
// une erreur est survenue
}

if (mysql_stmt_error(stmt))
{
// une erreur est survenue
}

La langue utilisée pour les messages d'erreurs du client MySQL peut être modifiée à la compilation de la bibliothèque cliente MySQL. Actuellement, vous pouvez choisir les messages d'erreur dans plusieurs langues.

Valeurs retournées

Une chaîne de caractères qui décrit l'erreur. Une chaîne vide signifie qu'il n'y a pas eu d'erreur.

Erreurs

Aucune

24-B-7-j - mysql_stmt_execute()

int mysql_stmt_execute(MYSQL_STMT *stmt)

Description

mysql_stmt_execute() exécute la requête préparée, associée avec le pointeur 'stmt'. Les valeurs des marqueurs de paramètres seront envoyées au serveur durant cet appel, pour que le serveur remplace les marqueurs avec les nouvelles valeurs.

Si la commande est UPDATE, DELETE ou INSERT, le nombre total de lignes changées, modifiées ou insérées est accessible avec la fonction mysql_stmt_affected_rows. Si la requête retourne un résultat, alors vous devez appeler la fonction mysql_stmt_fetch() pour lire les données avant d'appeler toute autre fonction de traitement du résultat. Pour plus d'informations sur comment lire les données binaires, voyez aussi Section 24.2.7.13, « mysql_stmt_fetch() ».

Valeurs retournées

Zéro si l'exécution a réussi. Non zéro si une erreur est survenue. Le code d'erreur et le message peuvent être obtenus en appelant les fonctions mysql_stmt_errno() et mysql_stmt_error().

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_SERVER_LOST
La connexion a été perdue durant la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

L'exemple suivant explique l'utilisation de mysql_prepare, mysql_param_count, mysql_bind_param, mysql_stmt_execute et mysql_stmt_affected_rows().

MYSQL_BIND   bind[3];
MYSQL_STMT   *stmt;
ulonglong    affected_rows;
long         length;
unsigned int param_count;
int          int_data;
short        small_data;
char         str_data[50], query[255];
my_bool      is_null;

/* Passe en mode d'auto commit */
mysql_autocommit(mysql, 1);

if (mysql_query(mysql,"DROP TABLE IF EXISTS test_table"))
{
fprintf(stderr, "\n suppression de table a échoué");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
if (mysql_query(mysql,"CREATE TABLE test_table(col1 int, col2 varchar(50), \
col3 smallint,\
col4 timestamp(14))"))
{
fprintf(stderr, "\n la création de table a échoué");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}

/* Prépare une requête d'insertion de trois paramètres */
strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)");
if(!(stmt = mysql_prepare(mysql, query, strlen(query))))
{
fprintf(stderr, "\n la préparation de l\'insertion a échoué");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
fprintf(stdout, "\n la préparation de l\'insertion a réussi");

/* Lit le nombre de paramètres de la requête */
param_count= mysql_param_count(stmt);

fprintf(stdout, "\n total parameters in insert: %d", param_count);
if (param_count != 3) /* valide le nombre de paramètres */
{
fprintf(stderr, "\n le nombre de paramètres retourné par MySQL est invalide");
exit(0);
}

/* Lie les données aux paramètres */

/* INTEGER PART */
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&int_data;
bind[0].is_null= 0;
bind[0].length= 0;

/* STRING PART */
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= sizeof(str_data);
bind[1].is_null= 0;
bind[1].length= 0;

/* SMALLINT PART */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null;
bind[2].length= 0;
is_null= 0;

/* Lie les buffers */
if (mysql_bind_param(stmt, bind))
{
fprintf(stderr, "\n param bind failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Spécifie les données */
int_data= 10;             /* integer */
strcpy(str_data,"MySQL"); /* string  */

/* INSERT SMALLINT data as NULL */
is_null= 1;

/* Exécute la requête */
if (mysql_stmt_execute(stmt))
{
fprintf(stderr, "\n l\'exécution 1 a échoué");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Lit le nombre de lignes affectées */
affected_rows= mysql_stmt_affected_rows(stmt);

fprintf(stdout, "\n total affected rows: %lld", affected_rows);
if (affected_rows != 1) /* validation du nombre de lignes affectées */
{
fprintf(stderr, "\n nombre de lignes affectées par MySQL invalide");
exit(0);
}

/* Réexécute l'insertion, en modifiant les valeurs */
int_data= 1000;
strcpy(str_data,"La base de données Open Source la plus populaire");
small_data= 1000;         /* smallint */
is_null= 0;               /* remet à zéro NULL */

/* Exécute l'insertion : 2e */
if (mysql_stmt_execute(stmt))
{
fprintf(stderr, "\n la deuxième exécution a échoué");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Lit le nombre total de lignes affectées */
affected_rows= mysql_stmt_affected_rows(stmt);

fprintf(stdout, "\n Nombre de lignes affectées : %lld", affected_rows);
if (affected_rows != 1) /* valide le nombre de lignes affectées */
{
fprintf(stderr, "\n Nombre de lignes affectées invalides");
exit(0);
}

/* Ferme la requête */
if (mysql_stmt_close(stmt))
{
fprintf(stderr, "\n erreur lors de la fermeture de la commande");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Efface la table */
if (mysql_query(mysql,"DROP TABLE test_table"))
{
fprintf(stderr, "\n suppression de table a échoué");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
fprintf(stdout, "Bravo! les commandes préparées MySQL fonctionnent!!");

Note : pour des exemples complets sur l'utilisation des commandes préparées, voyez le fichier tests/mysql_client_test.c. Ce fichier est disponible dans la distribution source de MySQL,ou dans le serveur BitKeeper.

24-B-7-k - mysql_stmt_free_result()

my_bool mysql_stmt_free_result(MYSQL_STMT *stmt)

À définir.

Description

Valeur retournée

Erreurs

24-B-7-l - mysql_stmt_insert_id()

my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt)

Description

Retourne la valeur générée pour une colonne de type AUTO_INCREMENT par une requête préparée INSERT ou UPDATE. Utilisez cette fonction après avoir exécuté la commande INSERT sur la table qui contient la colonne AUTO_INCREMENT.

Voyez Section 24.2.3.33, « mysql_insert_id() » pour plus de détails.

Valeurs retournées

La valeur générée pour la colonne AUTO_INCREMENT qui était automatiquement générée ou explicitement donnée durant l'exécution de la requête, ou la valeur générée par la dernière fonction LAST_INSERT_ID(expr). La valeur retournée est indéfinie si la commande n'a pas manipulé de valeur AUTO_INCREMENT.

Erreurs

Aucune.

24-B-7-m - mysql_stmt_fetch()

int mysql_stmt_fetch(MYSQL_STMT *stmt)

Description

mysql_stmt_fetch() retourne la ligne suivante dans le résultat. La fonction peut être appelée uniquement si le résultat existe, c'est-à-dire après mysql_stmt_execute() qui crée le résultat, ou après mysql_stmt_store_result(), qui est appelé après mysql_stmt_execute() pour mettre en buffer tout le résultat.

Si les lignes sont liées à des buffers avec mysql_stmt_bind_result(), la fonction retourne les données dans ces buffers pour toutes les colonnes de la ligne en cours, et les tailles sont retournées dans le pointeur de taille.

Notez que toutes les colonnes doivent être liées par l'application avant d'appeler mysql_stmt_fetch().

Si les données lues contiennent la valeur NULL, alors la valeur is_null de MYSQL_BIND contiendra TRUE, 1, ou sinon, les données et leur longueur seront retournées dans les variables *buffer et *length, basées sur le type de buffers spécifié par l'application. Tous les nombres ont une taille fixe, listée en octet ci-dessous. La taille des types chaînes dépend des données, comme indiqué dans data_length.

Type

Longueur

MYSQL_TYPE_TINY

1

MYSQL_TYPE_SHORT

2

MYSQL_TYPE_LONG

4

MYSQL_TYPE_LONGLONG

8

MYSQL_TYPE_FLOAT

4

MYSQL_TYPE_DOUBLE

8

MYSQL_TYPE_TIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATE

sizeof(MYSQL_TIME)

MYSQL_TYPE_DATETIME

sizeof(MYSQL_TIME)

MYSQL_TYPE_TIMESTAMP

sizeof(MYSQL_TIME)

MYSQL_TYPE_STRING

data length

MYSQL_TYPE_VAR_STRING

data_length

MYSQL_TYPE_TINY_BLOB

data_length

MYSQL_TYPE_BLOB

data_length

MYSQL_TYPE_MEDIUM_BLOB

data_length

MYSQL_TYPE_LONG_BLOB

data_length

où *data_length ne vaut rien d'autre que 'la taille réelle des données'.

Valeurs retournées

Valeur retournée

Description

0

Réussi. Les données ont été lues, et placées dans les buffers.

1

Une erreur est survenue. Le code d'erreur et le message d'erreur sont disponibles grâce aux fonctions mysql_stmt_errno() et mysql_stmt_error().

100, MYSQL_NO_DATA

Il ne reste plus de donnée ou de ligne.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_SERVER_LOST
La connexion au serveur a été perdue durant la requête.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

- CR_UNSUPPORTED_PARAM_TYPE
Si le buffer est de type MYSQL_TYPE_DATE, DATETIME, TIME ou TIMESTAMP et le type de champ n'est pas DATE, TIME, DATETIME or TIMESTAMP.

- Toutes les autres erreurs de conversions non supportées sont disponibles avec mysql_bind_result().

Exemple

L'exemple ci-dessous explique l'utilisation de mysql_get_metadata(), mysql_bind_result() et mysql_stmt_fetch() Cet exemple s'attend à lire les deux lignes insérées dans l'exemple de Section 24.2.7.10, « mysql_stmt_execute() ».) La variable mysql est supposée être une connexion valide.

#define STRING_SIZE 50

#define SELECT_SAMPLE "SELECT col1, col2, col3, col4 FROM test_table"

MYSQL_STMT    *stmt;
MYSQL_BIND    bind[4];
MYSQL_RES     *prepare_meta_result;
MYSQL_TIME    ts;
unsigned long length[4];
int           param_count, column_count, row_count;
short         small_data;
int           int_data;
char          str_data[STRING_SIZE];
my_bool       is_null[4];

/* Prépare une commande SELECT pour lire les données dans la table test_table */
stmt = mysql_prepare(mysql, SELECT_SAMPLE, strlen(SELECT_SAMPLE));
if (!stmt)
{
fprintf(stderr, " mysql_prepare(), SELECT failed\n");
fprintf(stderr, " %s\n", mysql_error(mysql));
exit(0);
}
fprintf(stdout, " prepare, SELECT successful\n");

/* Lit le nombre de paramètres de la commande */
param_count= mysql_param_count(stmt);
fprintf(stdout, " total parameters in SELECT: %d\n", param_count);

if (param_count != 0) /* validate parameter count */
{
fprintf(stderr, " invalid parameter count returned by MySQL\n");
exit(0);
}

/* Lit les métadonnées */
prepare_meta_result = mysql_get_metadata(stmt);
if (!prepare_meta_result)
{
fprintf(stderr, " mysql_get_metadata(), returned no meta information\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

/* Lit le nombre de colonnes de la requête */
column_count= mysql_num_fields(prepare_meta_result);
fprintf(stdout, " total columns in SELECT statement: %d\n", column_count);

if (column_count != 4) /* validate column count */
{
fprintf(stderr, " invalid column count returned by MySQL\n");
exit(0);
}

/* Exécute la requête SELECT */
if (mysql_execute(stmt))
{
fprintf(stderr, " mysql_execute(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

/* Lie les buffers de résultats pour les 4 colonnes avant de les lire */

/* INTEGER COLUMN */
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&int_data;
bind[0].is_null= &is_null[0];
bind[0].length= &length[0];

/* STRING COLUMN */
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= STRING_SIZE;
bind[1].is_null= &is_null[1];
bind[1].length= &length[1];

/* SMALLINT COLUMN */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null[2];
bind[2].length= &length[2];

/* TIMESTAMP COLUMN */
bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP;
bind[3].buffer= (char *)&ts;
bind[3].is_null= &is_null[3];
bind[3].length= &length[3];

/* Lit les résultats */
if (mysql_bind_result(stmt, bind))
{
fprintf(stderr, " mysql_bind_result() failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

/* Maintenant, lit les résultats dans les buffers */
if (mysql_stmt_store_result(stmt))
{
fprintf(stderr, " mysql_stmt_store_result() failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

/* Lit toutes les lignes */
row_count= 0;
fprintf(stdout, "Fetching results ...\n");
while (!mysql_stmt_fetch(stmt))
{
row_count++;
fprintf(stdout, "  row %d\n", row_count);

/* colonne 1 */
fprintf(stdout, "   column1 (integer)  : ");
if (is_null[0])
fprintf(stdout, " NULL\n");
else
fprintf(stdout, " %d(%ld)\n", int_data, length[0]);

/* colonne 2 */
fprintf(stdout, "   column2 (string)   : ");
if (is_null[1])
fprintf(stdout, " NULL\n");
else
fprintf(stdout, " %s(%ld)\n", str_data, length[1]);

/* colonne 3 */
fprintf(stdout, "   column3 (smallint) : ");
if (is_null[2])
fprintf(stdout, " NULL\n");
else
fprintf(stdout, " %d(%ld)\n", small_data, length[2]);

/* colonne 4 */
fprintf(stdout, "   column4 (timestamp): ");
if (is_null[3])
fprintf(stdout, " NULL\n");
else
fprintf(stdout, " %04d-%02d-%02d %02d:%02d:%02d (%ld)\n",
ts.year, ts.month, ts.day,
ts.hour, ts.minute, ts.second,
length[3]);
fprintf(stdout, "\n");
}

/* Valide la ligne lue */
fprintf(stdout, " total rows fetched: %d\n", row_count);
if (row_count != 2)
{
fprintf(stderr, " MySQL failed to return all rows\n");
exit(0);
}

/* Libère les métadonnées de résultat */
mysql_free_result(prepare_meta_result);

/* Ferme la commande */
if (mysql_stmt_close(stmt))
{
fprintf(stderr, " failed while closing the statement\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
exit(0);
}

24-B-7-n - mysql_stmt_fetch_column()

int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset)

Description

Lit une colonne depuis la ligne de résultat actuelle. Le paramètre bind fournit le buffer à alimenter. Il doit être défini de la même façon que pour la fonction mysql_stmt_bind_result(). column indique la colonne à lire. La première colonne possède l'indice 0. offset représente l'offset à partir duquel la lecture est effectuée. Il peut être utilisé pour lire les données par morceaux. Les données de départ sont à l'offset 0.

Valeur retournée

Zéro si les données ont été lues, une valeur non nulle si une erreur est survenue.

Erreurs

- CR_INVALID_PARAMETER_NO

Un indice de colonne non valide.

- CR_NO_DATA

La fin de la ligne est déjà atteinte.

24-B-7-o - mysql_stmt_field_count()

unsigned int mysql_stmt_field_count(MYSQL_STMT *stmt)

Description

Retourne le nombre de colonnes de la commande exécutée la plus récente. Cette valeur vaudra zéro pour les commandes, telles que INSERT ou DELETE, qui n'ont pas produit de résultat.

mysql_stmt_field_count() peut être appelé après la préparation de la commande avec mysql_stmt_prepare().

Cette fonction a été ajoutée en MySQL 4.1.3.

Valeurs retournées

Un entier non signé, représentant le nombre de colonnes, si un jeu de résultats existe.

Erreurs

Aucune.

24-B-7-p - mysql_stmt_init()

MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)

Description

Crée une structure MYSQL_STMT.

Valeurs retournées

Un pointeur sur une structure MYSQL_STMT en cas de succès. NULL s'il n'y a plus de mémoire.

Erreurs

- CR_OUT_OF_MEMORY
Plus de mémoire.

24-B-7-q - mysql_stmt_num_rows()

my_ulonglong mysql_stmt_num_rows(MYSQL_STMT *stmt)

Description

Retourne le nombre de lignes dans le jeu de résultats.

L'utilisation de mysql_stmt_num_rows() dépend du fait que vous avez utilisé ou non mysql_stmt_store_result() pour rapatrier l'intégralité du résultat dans le client.

Si vous utilisez mysql_stmt_store_result(), mysql_stmt_num_rows() peut être appelé immédiatement.

Valeur retournée

Le nombre de lignes dans le jeu de résultats.

Erreurs

Aucun.

24-B-7-r - mysql_stmt_param_count()

unsigned long mysql_stmt_param_count(MYSQL_STMT *stmt)

Description

Retourne le nombre de marqueurs de paramètres présents dans la requête préparée.

Valeurs retournées

Un entier non signé, représentant le nombre de paramètres dans la requête.

Erreurs

Aucune.

Exemple

Pour une illustration de la fonction mysql_stmt_param_count(), voyez l'exemple de la fonction Section 24.2.7.10, « mysql_stmt_execute() ».

24-B-7-s - mysql_stmt_param_metadata()

MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt)

Cette fonction ne fait rien actuellement.

24-B-7-t - mysql_stmt_prepare()

int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)

Description

Prépare la requête représentée par la chaîne terminée par NUL query, et retourne un pointeur de commande à utiliser ultérieurement pour les autres opérations. La requête doit contenir une commande SQL unique. Vous ne devez pas ajouter le point-virgule (';') ni \g de fin de requête.

L'application peut inclure une ou plusieurs variables de requête SQL, grâce au caractère point d'interrogation ('?'), placé dans la commande SQL, aux bons endroits.

Les variables de requêtes ne sont valides qu'à certaines places dans les commandes SQL. Par exemple, elles sont autorisées dans les listes VALUES() d'une commande INSERT (pour spécifier les valeurs des lignes), ou dans les clauses de comparaisons WHERE, pour spécifier une valeur de comparaison. Sinon, elles ne sont pas autorisées pour les identifiants (comme les noms de tables ou de colonnes), dans les listes de colonnes sélectionnées par la commande SELECT, ou pour spécifier un opérateur tel que =. Cette dernière restriction est due au fait qu'il serait impossible de déterminer le type de paramètre. En général, les variables ne sont autorisées que dans les commandes de manipulations de données (Data Manipulation Language (DML)), et non pas dans les commandes de définition des données (Data Definition Language (DDL).

Les variables de requêtes doivent être liées par l'application à des variables, avec la fonction mysql_stmt_bind_param() avant exécution.

Valeurs retournées

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur s'est éteint durant l'exécution de la requête.

- CR_SERVER_LOST
La connexion au serveur a été perdue.

- CR_UNKNOWN_ERROR
Erreur inconnue.

Si la préparation échoue, c'est-à-dire si mysql_stmt_prepare() retourne NULL), un message d'erreur peut être obtenu en appelant mysql_error().

Exemple

Pour une utilisation de mysql_stmt_prepare(), voyez l'exemple dans Section 24.2.7.10, « mysql_stmt_execute() ».

24-B-7-u - mysql_stmt_reset()

my_bool mysql_stmt_reset(MYSQL_STMT *stmt)

Description

Remet la commande préparée sur le client et sur le serveur à son état juste après la préparation. Actuellement, on s'en sert surtout pour remettre à zéro les données envoyées par mysql_stmt_send_long_data().

Pour préparer à nouveau la commande pour une autre commande, utilisez mysql_stmt_prepare().

Valeurs retournées

Zéro si la commande a été remise à zéro. Non nulle, si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_SERVER_GONE_ERROR
Le serveur s'est éteint.

- CR_SERVER_LOST
La connexion au serveur a été perdue durant l'exécution.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

24-B-7-v - mysql_stmt_result_metadata()

MYSQL_RES *mysql_stmt_result_metadata(MYSQL_STMT *stmt)

Description

Si la fonction mysql_prepare() a généré un résultat, alors mysql_stmt_result_metadata() retourne les métadonnées de résultats sous la forme d'une structure MYSQL_RES, qui peut être utilisée ultérieurement pour traiter des méta-informations, telles que le nombre de champs et les informations individuelles de champs. Ce résultat peut être passé en argument à l'une des fonctions de champs suivantes, pour traiter les données :

- mysql_num_fields()

- mysql_fetch_field()

- mysql_fetch_field_direct()

- mysql_fetch_fields()

- mysql_field_count()

- mysql_field_seek()

- mysql_field_tell()

- mysql_free_result()

La structure de jeu de résultats doit être libérée une fois que vous en avez fini avec, grâce à la fonction mysql_free_result(). C'est similaire à la méthode pour libérer les ressources obtenues de mysql_store_result().

Le jeu de résultats retourné par mysql_stmt_result_metadata() contient uniquement des métadonnées. Il ne contient aucune ligne de résultat. Les lignes sont lues en utilisant la ressource de commande, avec la fonction mysql_stmt_fetch().

Valeurs retournées

Une structure de type MYSQL_RES. NULL si aucune métadonnée n'existe pour la requête préparée.

Erreurs

- CR_OUT_OF_MEMORY
Plus de mémoire

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

Exemple

Pour une illustration de la fonction mysql_stmt_result_metadata(), voyez l'exemple de la fonction Section 24.2.7.13, « mysql_stmt_fetch() ».

24-B-7-w - mysql_stmt_row_seek()

MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset)

Description

Place le pointeur de lignes à une position arbitraire dans le jeu de résultats. La valeur offset est un offset de ligne, qui doit être retourné par mysql_stmt_row_tell() ou par mysql_stmt_row_seek(). Cette valeur n'est pas un numéro de ligne : si vous voulez atteindre une ligne dans un résultat, à partir de son numéro, vous devez utiliser mysql_stmt_data_seek().

Cette fonction requiert que le jeu de résultats entier soit téléchargé, et donc, mysql_stmt_row_seek() ne peut être utilisé qu'avec mysql_stmt_store_result().

Valeur retournée

La position précédente du curseur de ligne. Cette valeur peut être passée à mysql_stmt_row_seek().

Erreurs

Aucune.

24-B-7-x - mysql_stmt_row_tell()

MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT *stmt)

Description

Retourne la position courante du pointeur de ligne. C'est la position à laquelle le dernier appel à mysql_fetch() l'a laissé. Cette valeur peut être utilisée comme argument avec mysql_stmt_row_seek().

Vous ne devez utiliser mysql_stmt_row_tell() qu'après mysql_stmt_store_result().

Valeur retournée

La position courante du pointeur de lignes.

Erreurs

Aucune.

24-B-7-y - mysql_stmt_send_long_data()

my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int parameter_number, const char *data, unsigned long length)

Description

Permet à une application d'envoyer des données par parties au serveur. Cette fonction doit être utilisée pour envoyer des caractères ou du contenu binaire par parties dans une colonne (qui sera de type TEXT ou BLOB), avec un type de caractères ou de données binaires.

Le paramètre data est un pointeur sur un buffer qui contient les données pour le paramètre, représenté par parameter_number. Le paramètre length indique la quantité de données qui doit être envoyée, en octets.

Note : le prochain appel à mysql_stmt_execute() va ignorer les buffers de variables de requêtes, pour tous les paramètres qui ont été utilisés avec mysql_stmt_send_long_data() depuis le dernier appel à mysql_stmt_execute() ou mysql_stmt_reset().

Si vous voulez remettre à zéro cette fonction, utilisez mysql_stmt_reset(). Voir Section 24.2.7.21, « mysql_stmt_reset() ».

Valeurs retournées

Zéro si les données ont pu être envoyées au serveur. Non nul si une erreur est survenue.

Erreurs

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été envoyées dans un ordre invalide.

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_UNKNOWN_ERROR
Yne erreur inconnue s'est produite.

Exemple

L'exemple ci-dessous explique comment envoyer des données par parties dans une colonne de type TEXT :

#define INSERT_QUERY "INSERT INTO test_long_data(text_column) VALUES(?)"

MYSQL_BIND bind[1];
long       length;

smtt = mysql_stmt_init(mysql);
if (!stmt)
{
fprintf(stderr, " mysql_stmt_init(), out of memory\n");
exit(0);
}
if (mysql_stmt_prepare(stmt, INSERT_QUERY, strlen(INSERT_QUERY)))
{
fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
memset(bind, 0, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].length= &length;
bind[0].is_null= 0;

/* Liaison des buffers */
if (mysql_stmt_bind_param(stmt, bind))
{
fprintf(stderr, "\n param bind failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Envoi des données au serveur, par parties */
if (!mysql_stmt_send_long_data(stmt,0,"MySQL",5))
{
fprintf(stderr, "\n send_long_data failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Envoi des données suivantes */
if (mysql_stmt_send_long_data(stmt,0," - The most popular open source database",40))
{
fprintf(stderr, "\n send_long_data failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

/* Exécution de la requête */
if (mysql_stmt_execute(stmt))
{
fprintf(stderr, "\n mysql_stmt_execute failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}

24-B-7-z - mysql_stmt_sqlstate()

const char *mysql_stmt_sqlstate(MYSQL_STMT *stmt)

Description

Pour la commande stmt, mysql_stmt_sqlstate() retourne une chaîne terminée par un null, contenant le code d'erreur SQLSTATE de la plus récente fonction de requête préparée qui a été utilisée. Le code d'erreur est constitué de 5 caractères. "00000" signifie « pas d'erreur ». Les valeurs sont spécifiées par les normes ANSI SQL et ODBC. Pour une liste des valeurs possibles, voyez Chapitre 26, Gestion des erreurs avec MySQL.

Notez que toutes les erreurs MySQL ne sont pas associées à une erreur SQLSTATE. La valeur "HY000" (erreur générale) sert pour les erreurs orphelines.

Cette fonction a été ajoutée en MySQL 4.1.1.

Valeur retournée

Une chaîne de caractères terminée par un null, contenant le code d'erreur SQLSTATE.

24-B-7-aa - mysql_stmt_store_result()

int mysql_stmt_store_result(MYSQL_STMT *stmt)

Description

Vous devez appeler la fonction mysql_stmt_store_result() pour chaque requête qui doit lire des données (SELECT, SHOW, DESCRIBE, EXPLAIN) et uniquement si vous voulez lire la totalité du résultat dans un buffer du client, pour que les appels suivants à mysql_fetch() retournent des données bufferisées.

Vous n'avez pas à appeler mysql_stmt_store_result() pour les requêtes suivantes, mais cela ne causera pas de ralentissement notable. Vous pouvez détecter si une requête n'a pas de résultat en vérifiant si mysql_prepare_result() retourne 0. Pour plus d'informations, voyez Section 24.2.7.22, « mysql_stmt_result_metadata() ».

Note : MySQL ne calcule pas par défaut MYSQL_FIELD->max_length pour toutes les colonnes de mysql_stmt_store_result() car ce calcul ralentirait considérablement mysql_stmt_store_result() et la plupart des applications n'ont pas besoin de max_length. Si vous voulez max_length, vous pouvez appeler mysql_stmt_attr_set(MYSQL_STMT, STMT_ATTR_UPDATE_MAX_LENGTH, &flag) pour l'obtenir. Voir Section 24.2.7.3, « mysql_stmt_attr_set() ».

Valeurs retournées

Zéro si les résultats sont mis en buffer correctement, et non nul si une erreur survient.

Errors

- CR_COMMANDS_OUT_OF_SYNC
Les commandes ont été exécutées dans un ordre invalide.

- CR_OUT_OF_MEMORY
Plus de mémoire.

- CR_SERVER_GONE_ERROR
Le serveur MySQL s'est éteint.

- CR_SERVER_LOST
La connexion au serveur MySQL s'est interrompue durant la commande.

- CR_UNKNOWN_ERROR
Une erreur inconnue est survenue.

24-B-8 - Problèmes avec l'interface C des commandes préparées

Voici la liste des problèmes connus avec les commandes préparées :

- TIME, TIMESTAMP et DATETIME ne supportent pas les fractions de seconde (par exemple, issues de DATE_FORMAT().

- Lors de la conversion d'un entier en chaîne, ZEROFILL est respecté avec les commandes préparées, même dans certains cas, où le serveur MySQL n'affiche pas les zéros initiaux (par exemple, avec MIN(number-with-zerofill)).

- Lors de la conversion d'un nombre décimal en chaîne par le client, la valeur peut être légèrement différente pour le dernier chiffre.

24-B-9 - Gestion des commandes multiples avec l'interface C

Depuis la version 4.1, MySQL supporte l'exécution de requêtes multiples dans une seule commande. Pour cela, vous devez activer l'option client CLIENT_MULTI_QUERIES lors de l'ouverture de la connexion.

Par défaut, mysql_query() ou mysql_real_query() ne retournent que le statut de la première requête, et les statuts suivants peuvent être obtenus avec mysql_more_results() et mysql_next_result().

/* Connexion au serveur, avec l'option CLIENT_MULTI_QUERIES */
mysql_real_query(..., CLIENT_MULTI_QUERIES);

/* Exécution de plusieurs requêtes */
mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\
CREATE TABLE test_table(id int);\
INSERT INTO test_table VALUES(10);\
UPDATE test_table SET id=20 WHERE id=10;\
SELECT * FROM test_table;\
DROP TABLE test_table";
while (mysql_more_results(mysql))
{
/* Traitement de tous les résultats */
mysql_next_result(mysql);
...
printf("total affected rows: %lld", mysql_affected_rows(mysql));
...
if ((result= mysql_store_result(mysql))
{
/* Retourne un résultat, le traite */
}
}

24-B-10 - Gestion des dates et horaires avec l'interface C

En utilisant le nouveau protocole binaire de MySQL 4.1 et plus récent, vous pouvez envoyer et recevoir les données de type (DATE, TIME, DATETIME et TIMESTAMP) avec la structure MYSQL_TIME. Les membres de cette structure sont décrits dans Section 24.2.5, « Types de données de l'API C ».

Afin d'envoyer les données, il faut utiliser une requête préparée avec la fonction mysql_prepare(). Avant d'appeler la fonction mysql_execute(), pour exécuter la commande, utilisez la procédure suivante pour préparer chaque donnée :

1. Dans la structure MYSQL_BIND, associée aux données, assignez au membre buffer_type le type de données que vous envoyez. Pour DATE, TIME, DATETIME, ou TIMESTAMP, utilisez buffer_type MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME, ou MYSQL_TYPE_TIMESTAMP, respectivement.

2. Donnez au membre buffer de la structure MYSQL_BIND, l'adresse de la structure MYSQL_TIME dans laquelle vous avez stocké votre valeur temporelle.

3. Remplissez les membres de la structure MYSQL_TIME qui sont adaptés au type de données que vous passez.

Utilisez mysql_bind_param() pour lier les données à la requête. Puis, appelez mysql_execute().

Pour lire des données temporelles, la procédure est similaire, hormis le fait que vous donnez au membre buffer_type le type de données que vous attendez, et que buffer doit pointer sur l'adresse de la structure MYSQL_TIME qui va recevoir les données retournées. Utilisez mysql_bind_results() pour lier les buffers à la commande après avoir appelé mysql_execute() et avant de lire les résultats.

Voici un exemple qui réalise l'insertion de données DATE, TIME et TIMESTAMP. La variable mysql est supposée représenter une connexion valide.

MYSQL_TIME  ts;
MYSQL_BIND  bind[3];
MYSQL_STMT  *stmt;

strmov(query, "INSERT INTO test_table(date_field, time_field,
timestamp_field) VALUES(?,?,?");

stmt= mysql_prepare(mysql, query, strlen(query)));

/* configure les trois buffers pour les trois paramètres */
bind[0].buffer_type= MYSQL_TYPE_DATE;
bind[0].buffer= (char *)&ts;
bind[0].is_null= 0;
bind[0].length= 0;
..
bind[1]= bind[2]= bind[0];
..

mysql_bind_param(stmt, bind);

/* Fournit les données à envoyer dans la structure ts */
ts.year= 2002;
ts.month= 02;
ts.day= 03;

ts.hour= 10;
ts.minute= 45;
ts.second= 20;

mysql_execute(stmt);
..

24-B-11 - Description des fonctions threadées de C

Vous devez utiliser les fonctions suivantes quand vous voulez créer un client threadé. Voir Section 24.2.15, « Comment faire un client MySQL threadé ».

24-B-11-a - my_init()

void my_init(void)

Description

Cette fonction doit être appelée une fois dans le programme avant tout appel à une fonction MySQL. Cela initialise quelques variables globales dont MySQL a besoin. Si vous utilisez une bibliothèque client sûre pour les threads, cela appellera aussi mysql_thread_init() pour ce thread.

Ceci est automatiquement appelé par mysql_init(), mysql_server_init() et mysql_connect().

Valeur de retour

Aucune.

24-B-11-b - mysql_thread_init()

my_bool mysql_thread_init(void)

Description

Cette fonction doit être appelée à chaque création de thread pour initialiser les variables spécifiques aux threads.

Elle est appelée automatiquement par my_init() et mysql_connect().

Valeur de retour

Aucune.

24-B-11-c - mysql_thread_end()

void mysql_thread_end(void)

Description

Cette fonction doit être appelée avant pthread_exit() pour libérer la mémoire allouée par mysql_thread_init().

Notez que cette fonction n'est pas invoquée automatiquement par la bibliothèque du client. Elle doit être invoquée explicitement pour éviter les pertes de mémoire.

Valeur de retour

Aucune.

24-B-11-d - mysql_thread_safe()

unsigned int mysql_thread_safe(void)

Description

Cette fonction indique si le client est compilé avec le support des threads (thread-safe).

Valeur de retour

1 indique que le client est thread-safe, 0 sinon.

24-B-12 - Description des fonctions C du serveur embarqué

Vous devez utiliser les fonctions suivantes si vous voulez permettre à votre application d'être liée avec la bibliothèque du serveur embarqué MySQL. Voir Section 24.2.16, « libmysqld, la bibliothèque du serveur embarqué MySQL ».

Si le programme est lié avec -lmysqlclient au lieu de -lmysqld, ces fonctions ne font rien. Cela permet de choisir d'utiliser un serveur embarqué MySQL, ou un serveur tournant à part sans avoir à changer votre code.

24-B-12-a - mysql_server_init()

int mysql_server_init(int argc, char **argv, char **groups)

Description

Cette fonction doit être appelée une fois dans le programme avant d'appeler toute autre fonction MySQL. Elle démarre le serveur et initialise tout sous-système (mysys, InnoDB, etc.) utilisé par le serveur. Si cette fonction n'est pas appelée, le programme plantera. Si vous utilisez le paquet DBUG fourni avec MySQL, vous devez exécuter cette fonction après avoir appelé MY_INIT().

Les arguments argc et argv sont analogues aux arguments de main(). Le premier élément argv est ignoré (il contient le plus souvent le nom du programme). Par convenance, argc peut être 0 (zéro) s'il n'y a aucun argument passé en ligne de commande pour le serveur.

La liste de mots terminée par NULL dans groups détermine les groupes dans les fichiers d'options qui seront actifs. Voir Section 4.3.2, « Fichier d'options my.cnf ». Par convenance, groups peut être NULL, dans ce cas, les groupes [server] et [emedded] sont activés.

Exemple

#include <mysql.h>
#include <stdlib.h>

static char *server_args[] = {
"ce_programme",       /* cette chaîne n'est pas utilisée */
"--datadir=.",
"--key_buffer_size=32M"
};
static char *server_groups[] = {
"embedded",
"server",
"this_program_SERVER",
(char *)NULL
};

int main(void) {
mysql_server_init(sizeof(server_args) / sizeof(char *),
server_args, server_groups);

/* Utilisez les fonctions de L'API MySQL ici */

mysql_server_end();

return EXIT_SUCCESS;
}

Valeur de retour

0 en cas de succès, 1 si une erreur survient.

24-B-12-b - mysql_server_end()

void mysql_server_end(void)

Description

Cette fonction doit être appelée une fois dans le programme après toutes les autres fonctions MySQL. Elle coupe le serveur incorporé.

Valeur de retour

Aucune.

24-B-13 - Questions courantes sur la bibliothèque C

24-B-13-a - Pourquoi est-ce que mysql_store_result() retourne parfois NULL après que mysql_query() ait réussi

Il est possible que mysql_store_result() retourne NULL après un appel à mysql_query(). Quand cela arrive, cela signifie que l'une des conditions suivantes a été remplie :

- Il y a eu un problème avec malloc() (par exemple, si la taille du résultat était trop importante).

- Les données n'ont pu être lues (erreur survenue à la connexion).

- La requête n'a retourné aucun résultat (par exemple, il s'agissait d'un INSERT, UPDATE, ou d'un DELETE).

Vous pouvez toujours vérifier si la requête devait bien fournir un résultat non vide en invoquant mysql_field_count(). Si mysql_field_count() retourne zéro, le résultat est vide et la dernière requête n'en retournait pas (par exemple, un INSERT ou un DELETE). Si mysql_field_count() retourne un résultat non nul, la requête aurait dû produire un résultat non nul. Voyez la documentation de la fonction mysql_field_count() pour plus d'exemples.

Vous pouvez tester les erreurs en faisant appel à mysql_error() ou mysql_errno().

24-B-13-b - Quels résultats puis-je obtenir d'une requête?

En plus des enregistrements retournés par une requête, vous pouvez obtenir les informations suivantes :

- mysql_affected_rows() retourne le nombre d'enregistrements affectés par la dernière requête INSERT, UPDATE, ou DELETE. Une exception est que si DELETE est utilisé sans clause WHERE, la table est recréée vide, ce qui est plus rapide. Dans ce cas, mysql_affected_rows() retournera zéro comme nombre d'enregistrements affectés.

- mysql_num_rows() retourne le nombre d'enregistrements dans le résultat. Avec mysql_store_result(), mysql_num_rows() peut être utilisée dès que mysql_store_result() retourne un résultat. Avec mysql_use_result(), mysql_num_rows() ne doit être appelé qu'après avoir récupéré tous les enregistrements avec mysql_fetch_row().

- mysql_insert_id() retourne l'ID généré par la dernière requête qui a inséré une ligne dans une table avec un index AUTO_INCREMENT. Voir Section 24.2.3.33, « mysql_insert_id() ».

- Quelques requêtes (LOAD DATA INFILE ..., INSERT INTO ... SELECT ..., UPDATE) retournent des informations additionnelles. Le résultat est renvoyé par mysql_info(). Regardez la documentation de mysql_info() pour plus d'informations sur le format de la chaîne retournée. mysql_info() retourne un pointeur NULL s'il n'y a pas d'information additionnelle.

24-B-13-c - Comment lire l'identifiant unique de la dernière ligne insérée

Si vous insérez une ligne dans une table qui contient une colonne ayant l'attribut AUTO_INCREMENT, vous pouvez obtenir le dernier identifiant généré en appelant la fonction mysql_insert_id().

Vous pouvez aussi récupérer cet identifiant en utilisant la fonction LAST_INSERT_ID() dans une requête que vous passez à mysql_query().

Vous pouvez vérifier qu'un index AUTO_INCREMENT est utilisé en exécutant le code suivant. Cela vérifiera aussi si la requête était un INSERT avec un index AUTO_INCREMENT :

if (mysql_error(&mysql)[0] == 0 &&
mysql_num_fields(result) == 0 &&
mysql_insert_id(&mysql) != 0)
{
used_id = mysql_insert_id(&mysql);
}

Pour plus d'informations, voyez la section Section 24.2.3.33, « mysql_insert_id() ».

Lorsqu'une nouvelle valeur AUTO_INCREMENT est générée, vous pouvez l'obtenir en utilisant la commande SELECT LAST_INSERT_ID() avec mysql_query() et en lisant la valeur dans le résultat obtenu.

Pour LAST_INSERT_ID(), l'identifiant généré par la dernière insertion est entretenu sur le serveur en se basant sur la connexion. Il ne sera pas changé par un autre client. Il ne changera pas non plus si vous mettez à jour une autre colonne AUTO_INCREMENT avec une valeur normale (ni NULL ni 0).

Si vous voulez utiliser l'identifiant généré pour une table et l'insérer dans une autre, vous pouvez utiliser les requêtes suivantes :

INSERT INTO foo (auto,text)
VALUES(NULL,'text');              # génère un identifiant en insérant NULL
INSERT INTO foo2 (id,text)
VALUES(LAST_INSERT_ID(),'text');  # on l'utilise dans la seconde page

Notez que mysql_insert_id() retourne la valeur stockée dans une colonne AUTO_INCREMENT, que cette valeur ait été générée automatiquement en enregistrant NULL ou 0 ou une valeur explicite. LAST_INSERT_ID() retourne les valeurs générées automatiquement par AUTO_INCREMENT. Si vous stockez une valeur explicite, autre que NULL ou 0, cela n'affecte pas le résultat de LAST_INSERT_ID().

24-B-13-d - Problèmes lors de la liaison avec l'API C

Lors de la liaison avec l'API C, l'erreur suivante peut survenir sur quelques systèmes :

gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl

Undefined        first referenced
symbol          in file
floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
ld: fatal: Symbol referencing errors. No output written to client

Si cela se produit sur votre système, vous devez inclure la bibliothèque mathématique en ajoutant -lm à la fin de la ligne de compilation/liaison.

24-B-14 - Compiler les clients

Si vous compilez des clients MySQL que vous avez écrits vous-même, ils doivent être liés en utilisant l'option -lmysqlclient -lz de la commande de liaison. Vous aurez peut-être besoin de spécifier l'option -L pour dire au programme ou trouver les bibliothèques. Par exemple, si la bibliothèque est installée dans /usr/local/mysql/lib, utilisez -L/usr/local/mysql/lib -lmysqlclient -lz dans votre commande.

Pour les clients qui utilisent les fichiers d'entêtes de MySQL, vous aurez besoin de spécifier une option -I lors de leur compilation (par exemple, -I/usr/local/mysql/include), pour que le programme puisse les trouver.

Pour rendre ce qui précède plus simple sur Unix, nous avons fourni le script mysql_config. Voir Section 24.1.2, « mysql_config lit les options de compilations du client MySQL ».

Vous pouvez l'utiliser pour compiler un client MySQL comme ceci :

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

sh -c est nécessaire pour s'assurer que le Shell ne traitera pas le résultat de mysql_config comme un seul mot.

24-B-15 - Comment faire un client MySQL threadé

La bibliothèque cliente est presque compatible avec les threads. Le problème le plus important est les routines de net.c qui lisent les sockets, et qui ne sont pas compatibles avec les interruptions. Cela a été fait en imaginant que vous souhaitiez vos propres alarmes, qui pourraient interrompre une lecture trop longue. Si vous installez des gestionnaires d'interruption pour l'alarme SIGPIPE, la gestion des sockets devrait être compatible avec les threads.

Dans les anciennes versions binaires que nous distribuions sur notre site web, (http://www.mysql.com/), les bibliothèques clientes étaient normalement compilées avec l'option de compatibilité avec les threads (les exécutables Windows sont par défaut compatibles avec les threads). Les nouvelles distributions binaires doivent disposer des deux bibliothèques, compatibles ou non avec les threads.

Pour obtenir un client threadé où vous pouvez interrompre le client avec d'autres threads, mettre des délais d'expiration lors des discussions avec le serveur MySQL, vous devriez utiliser les bibliothèques -lmysys, -lmystrings et -ldbug, ainsi que net_serv.o que le serveur utilise.

Si vous n'avez pas besoin des interruptions ou des expirations, vous pouvez compiler simplement une bibliothèque compatible avec les threads, (mysqlclient_r) et l'utiliser. Voir Section 24.2, « API MySQL C  ». Dans ce cas, vous n'avez pas à vous préoccuper du fichier net_serv.o ou des autres bibliothèques MySQL.

Lorsque vous utiliser un client threadé et que vous souhaitez utiliser des délais d'expiration et des interruptions, vous pouvez faire grand usage des routines du fichier thr_alarm.c. Si vous utilisez des routines issues de la bibliothèque mysys, la seule chose à penser est de commencer par utiliser my_init(). Voir Section 24.2.11, « Description des fonctions threadées de C ».

Toutes les fonctions, hormis mysql_real_connect() sont compatibles avec les threads par défaut. Les notes suivantes décrivent comment compiler une bibliothèque cliente compatible avec les threads. Les notes ci-dessous, écrites pour mysql_real_connect() s'appliquent aussi à mysql_connect(), mais comme mysql_connect() est obsolète, vous devriez utiliser mysql_real_connect()).

Pour rendre mysql_real_connect() compatible avec les threads, vous devez recompiler la bibliothèque cliente avec cette commande :

shell> ./configure --enable-thread-safe-client

Cela va créer une bibliothèque cliente compatible avec les threads libmysqlclient_r. Supposons que votre système d'exploitation dispose d'une fonction gethostbyname_r() compatible avec les threads. Cette bibliothèque est compatible avec les threads pour chaque connexion. Vous pouvez partager une connexion entre deux threads, avec les limitations suivantes :

- Deux threads ne peuvent pas envoyer de requêtes simultanées au serveur MySQL, sur la même connexion. En particulier, vous devez vous assurer qu'entre mysql_query() et mysql_store_result(), aucun autre thread n'utilise la même connexion.

- De nombreux threads peuvent accéder à différents résultats qui sont lus avec mysql_store_result().

- Si vous utilisez mysql_use_result, vous devez vous assurer qu'aucun autre thread n'utilise la même connexion jusqu'à ce qu'elle soit refermée. Cependant, il vaut bien mieux pour votre client threadé qu'il utilise mysql_store_result().

- Si vous voulez utiliser de multiples threads sur la même connexion, vous devez avoir un verrou mutex autour de vos fonctions mysql_query() et mysql_store_result(). Une fois que mysql_store_result() est prêt, le verrou peut être libéré et d'autres threads vont pouvoir utiliser la connexion.

- Si vous programmez avec les threads POSIX, vous pouvez utiliser les fonctions pthread_mutex_lock() et pthread_mutex_unlock() pour poser et enlever le verrou mutex.

Vous devez savoir ce qui suit si vous avez un thread qui appelle une fonction MySQL qui n'a pas créé de connexion à la base MySQL.

Lorsque vous appelez mysql_init() ou mysql_connect(), MySQL va créer une variable spécifique au thread qui est utilisée par la bibliothèque de débogage (entre autres).

Si vous appelez une fonction MYSQL, avant que le thread n'ait appelé mysql_init() ou mysql_connect(), le thread ne va pas avoir les variables spécifiques en place, et vous risquez d'obtenir un core dump tôt ou tard.

Pour faire fonctionner le tout proprement, vous devez suivre ces étapes :

1. Appeler my_init() au début du programme, s'il appelle une autre fonction MySQL, avant d'appeler mysql_real_connect().

2. Appeler mysql_thread_init() dans le gestionnaire de threads avant d'appeler une autre fonction MySQL.

3. Dans le thread, appelez mysql_thread_end() avant d'appeler pthread_exit(). Cela va libérer la mémoire utilisée par les variables spécifiques MySQL.

Vous pouvez rencontrer des erreurs à cause des symboles non définis lors du lien de votre client avec libmysqlclient_r. Dans la plupart des cas, c'est parce que vous n'avez pas inclus la bibliothèque de threads dans la ligne de compilation.

24-B-16 - libmysqld, la bibliothèque du serveur embarqué MySQL

24-B-16-a - Vue d'ensemble de la bibliothèque du serveur embarqué MySQL

La bibliothèque embarquée MySQL rend possible l'accès à un serveur MySQL complet, depuis une application. Le principal avantage est l'amélioration des performances, et une gestion bien plus simple des applications.

Les API sont identiques pour la version embarquée et la version client/serveur. Pour changer les anciennes applications threadées, et les faire utiliser la bibliothèque embarquée, vous devez simplement ajouter deux appels aux fonctions suivantes :

Fonction

Quand l'utiliser

mysql_server_init()

Doit être appelée avant toute autre fonction MySQL, et de préférence très tôt dans la fonction main().

mysql_server_end()

Doit être appelée avant que votre programme ne se termine.

mysql_thread_init()

Doit être appelée dans chaque thread que vous créez, qui aura accès à MySQL.

mysql_thread_end()

Doit être appelée avant d'appeler pthread_exit()

Puis, vous devez compiler votre code avec libmysqld.a au lieu de libmysqlclient.a.

Les fonctions ci-dessus mysql_server_xxx sont aussi incluses dans la bibliothèque libmysqlclient.a pour vous permettre de changer facilement entre les versions de la bibliothèque embarquée et celle de la bibliothèque client/serveur, en compilant simplement la bonne bibliothèque. Voir Section 24.2.12.1, « mysql_server_init() ».

24-B-16-b - Compiler des programmes avec libmysqld

Pour avoir la bibliothèque libmysqld vous devez configurer MySQL avec l'option --with-embedded-server.

Quand vous liez votre programme avec libmysqld, vous devez aussi inclure les bibliothèques pthread spécifiques au système et quelques bibliothèques que le serveur MySQL utilise. Vous pouvez obtenir la liste complète des bibliothèques en exécutant mysql_config --libmysqld-libs.

Les options correctes pour compiler et lier un programme threadé doivent être utilisées, même si vous n'appelez pas directement une fonction de threads dans votre code.

24-B-16-c - Restrictions lors de l'utilisation du serveur embarqué MySQL

Le serveur embarqué possède les limitations suivantes.

- Pas de support pour les tables ISAM. (Ceci est principalement fait pour rendre la bibliothèque plus petite)

- Pas de fonctions définies par l'utilisateur (UDF).

- Pas de traçage de piles lors des vidages de mémoire (core dump).

- Pas de support pour les RAID internes. (Cela n'est normalement pas requis vu que la plupart des systèmes d'exploitation supportent aujourd'hui les grands fichiers).

- Vous pouvez le configurer en tant que serveur ou maître (pas de réplication).

- vous ne pouvez vous connecter au serveur embarqué à partir d'un processus externe avec les sockets ou TCP/IP.

Quelques-unes de ces limitations peuvent être changées en éditant le fichier mysql_embed.h et recompilant MySQL.

24-B-16-d - Utilisation de fichiers d'options avec le serveur embarqué

Voici la manière recommandée d'utiliser les fichiers d'options pour que le passage des applications client/serveur vers une application où MySQL est embarqué soit plus facile. Voir Section 4.3.2, « Fichier d'options my.cnf ».

- Placez les options communes dans la section [server]. Elles seront lues par les deux versions de MySQL.

- Placez les options spécifiques au client/serveur dans la section [mysqld].

- Placez les options spécifiques à MySQL embarqué dans la section [embedded].

- Placez les options spécifiques aux applications dans une section [NomApplication_SERVER].

24-B-16-e - Choses à faire pour le serveur embarqué (TODO)

- Nous allons proposer des options pour se débarrasser de quelques parties de MySQL pour rendre la bibliothèque plus petite.

- Il y a encore beaucoup d'optimisations de vitesse à faire.

- Les erreurs sont écrites dans stderr. Nous ajouterons une option pour spécifier un fichier pour cela.

- Nous devons changer InnoDB pour qu'il n'y ait plus tant de sorties lors de l'utilisation du serveur embarqué.

24-B-16-f - Un exemple simple de serveur embarqué

Ce programme exemple et son makefile devraient fonctionner sans changements sur un système Linux ou FreeBSD. Pour les autres systèmes d'exploitation, quelques petits changements seront requis. Cet exemple est là pour vous donner assez de détails pour comprendre le problème, sans avoir en tête qu'il s'agit d'une partie nécessaire d'une application réelle.

Pour essayer cet exemple, créez un dossier test_libmysqld au même niveau que le dossier des sources mysql-4.0. Sauvegardez le fichier source test_libmysqld.c et GNUmakefile dans le dossier, puis exécutez GNU make à l'intérieur du répertoire test_libmysqld.

test_libmysqld.c

/*
* Un simple exemple de client, utilisant la bibliothèque du serveur embarqué MySQL
*/

#include <mysql.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

MYSQL *db_connect(const char *dbname);
void db_disconnect(MYSQL *db);
void db_do_query(MYSQL *db, const char *query);

const char *server_groups[] = {
"test_libmysqld_SERVER", "embedded", "server", NULL
};

int
main(int argc, char **argv)
{
MYSQL *one, *two;

/* mysql_server_init() doit être appelée avant toute autre fonction
* mysql.
*
* Vous pouvez utiliser mysql_server_init(0, NULL, NULL), et cela initialisera
* le serveur en utilisant groups = {
*   "server", "embedded", NULL
*  }.
*
* Dans votre fichier $HOME/.my.cnf, vous voudrez sûrement mettre :

[test_libmysqld_SERVER]
language = /chemin/vers/la/source/de/mysql/sql/share/english

* Vous pouvez, bien sûr, modifier argc et argv avant de les passer
* à cette fonction. Ou vous pouvez en créer de nouveaux de la manière
* que vous souhaitez. Mais tous les arguments dans argv (à part
* argv[0], qui est le nom du programme) doivent être des options valides
* pour le serveur MySQL.
*
* Si vous liez ce client avec la bibliothèque mysqlclient normale,
* cette fonction n'est qu'un bout de code qui ne fait rien.
*/
mysql_server_init(argc, argv, (char **)server_groups);

one = db_connect("test");
two = db_connect(NULL);

db_do_query(one, "SHOW TABLE STATUS");
db_do_query(two, "SHOW DATABASES");

mysql_close(two);
mysql_close(one);

/* Cela doit être appelé après toutes les autres fonctions mysql */
mysql_server_end();

exit(EXIT_SUCCESS);
}

static void
die(MYSQL *db, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
(void)putc('\n', stderr);
if (db)
db_disconnect(db);
exit(EXIT_FAILURE);
}

MYSQL *
db_connect(const char *dbname)
{
MYSQL *db = mysql_init(NULL);
if (!db)
die(db, "mysql_init a échoué : pas de mémoire");
/*
* Notez que le client et le serveur utilisent des noms de groupes séparés.
* Ceci est critique, car le serveur n'acceptera pas les options du client
* et vice versa.
*/
mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT");
if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
die(db, "mysql_real_connect a échoué : %s", mysql_error(db));

return db;
}

void
db_disconnect(MYSQL *db)
{
mysql_close(db);
}

void
db_do_query(MYSQL *db, const char *query)
{
if (mysql_query(db, query) != 0)
goto err;

if (mysql_field_count(db) > 0)
{
MYSQL_RES   *res;
MYSQL_ROW    row, end_row;
int num_fields;

if (!(res = mysql_store_result(db)))
goto err;
num_fields = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)))
{
(void)fputs(">> ", stdout);
for (end_row = row + num_fields; row < end_row; ++row)
(void)printf("%s\t", row ? (char*)*row : "NULL");
(void)fputc('\n', stdout);
}
(void)fputc('\n', stdout);
}
else
(void)printf("Lignes affectées : %lld\n", mysql_affected_rows(db));

return;

err:
die(db, "db_do_query a échoué : %s [%s]", mysql_error(db), query);
}

GNUmakefile

# On suppose que MySQL est installé dans /usr/local/mysql
inc      := /usr/local/mysql/include/mysql
lib      := /usr/local/mysql/lib

# Si vous n'avez pas encore installé MySQL, essayez plutôt ceci
#inc      := $(HOME)/mysql-4.0/include
#lib      := $(HOME)/mysql-4.0/libmysqld

CC       := gcc
CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
CFLAGS   := -g -W -Wall
LDFLAGS  := -static
# Vous pouvez changer -lmysqld en -lmysqlclient pour utiliser
# la bibliothèque client/serveur
LDLIBS    = -L$(lib) -lmysqld -lz -lm -lcrypt

ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))
# FreeBSD
LDFLAGS += -pthread
else
# Linux
LDLIBS += -lpthread
endif

# Cela fonctionne pour les programmes de tests sur un simple fichier
sources := $(wildcard *.c)
objects := $(patsubst %c,%o,$(sources))
targets := $(basename $(sources))

all: $(targets)

clean:
rm -f $(targets) $(objects) *.core

24-B-16-g - Licence du serveur embarqué

Nous encourageons tout le monde à promouvoir le logiciel libre en réalisant du code sous la licence GPL ou une autre licence compatible. Pour ceux qui ne peuvent le faire, une autre option est d'acheter la licence commerciale pour le code MySQL chez MySQL AB. Pour plus d'informations, voyez http://www.mysql.com/company/legal/licensing/.

24-C - API PHP pour MySQL

PHP est un langage côté serveur, qui peut être utilisé pour créer des pages web dynamiques. Il fournit un support d'accès à plusieurs systèmes de bases de données, dont MySQL fait partie. PHP peut être utilisé en tant que programme séparé, ou être compilé en tant que module pour le serveur web Apache.

La distribution et documentation sont disponibles sur le site web de PHP (http://www.php.net/).

24-C-1 - Problèmes fréquents avec MySQL et PHP

- Error: "Maximum Execution Time Exceeded". C'est une limitation de PHP. Éditez le fichier php.ini et changez le temps maximal d'exécution d'un script de 30 secondes à plus, selon vos besoins. C'est aussi une bonne idée de doubler la quantité de RAM allouée par script en la changeant à 16 MB.

- Error: "Fatal error: Call to unsupported or undefined function mysql_connect() in ...". Cela signifie que votre version de PHP n'est pas compilée avec le support de MySQL. Vous pouvez soit compiler un module dynamique MySQL et le charger dans PHP, ou bien recompiler PHP avec le support natif de MySQL. Ceci est décrit en détail dans le manuel PHP.

- Error: "undefined reference to `uncompress". Cela signifie que la bibliothèque cliente est compilée avec support d'un protocole client/serveur compressé. La solution est d'ajouter -lz à la fin lors de la liaison avec -lmysqlclient.

24-D - API Perl pour MySQL

DBI est une interface générique à plusieurs systèmes de bases de données. Cela signifie que vous pouvez écrire un script qui fonctionne parfaitement avec plusieurs systèmes différents sans y apporter aucun changement. Vous avez besoin de définir un pilote de bases de données (DataBase Driver : DBD) pour chaque système. Pour MySQL, ce pilote se nomme DBD::mysql.

Perl DBI est maintenant l'interface recommandée pour Perl. Elle remplace une ancienne interface appelée mysqlperl, qui doit être abandonnée.

Vous pouvez trouver les dernières informations relatives à DBI dans la section Section 2.9, « Commentaires sur l'installation de Perl ».

Plus de détails sur DBI sont disponibles en ligne de commande, sur Internet ou en version imprimée.

- Une fois que vous avez installé DBI et DBD::mysql, vous pouvez utiliser la commande perldoc pour obtenir plus d'informations à propos de DBI.

shell> perldoc DBI
shell> perldoc DBI::FAQ
shell> perldoc DBD::mysql

Vous pouvez aussi utiliser les outils pod2man, pod2html, etc. pour convertir la documentation en différents formats.

- Pour plus d'informations sur le module DBI de Perl5, visitez la page web de DBI : http://dbi.perl.org/

- Pour une documentation imprimée, voyez le guide officiel DBI : Programming the Perl DBI (Alligator Descartes et Tim Bunce, O'Reilly & Associates, 2000). Les informations sur le livre sont disponibles sur le site de DBI : http://dbi.perl.org/.
Pour des informations qui sont spécifiques à DBI et MySQL, voyez MySQL and Perl for the Web (Paul DuBois, New Riders, 2001). Le site web de ce livre est http://www.kitebird.com/mysql-perl/.

24-E - Interface MySQL C++

MySQL Connector/C++ (or MySQL++) est l'interface officielle de MySQL pour le C++. Plus d'informations sont disponibles sur http://www.mysql.com/products/mysql++/.

24-E-1 - Borland C++

Vous pouvez compiler la source Windows de MySQL avec Borland C++ 5.02. (La source Windows n'inclut que les fichiers issus de Microsoft VC++, pour Borland C++ vous devrez créer les fichiers de projet par vous-même.)

Un problème connu avec Borland C++ est qu'il utilise un alignement de structures différent de VC++. Cela signifie que vous aurez des problèmes si vous essayez d'utiliser la bibliothèque par défaut libmysql.dll (qui a été compilée avec VC++) avec Borland C++. Vous pouvez faire ce qui suit pour éviter ce problème.

- Vous pouvez utiliser les bibliothèques MySQL statiques pour Borland C++ que vous trouverez sur http://www.mysql.com/downloads/os-win32.html.

- Appelez mysql_init() avec NULL comme argument, et non une structure MYSQL préallouée.

24-F - MySQL Python API

MySQLdb fournit le support MySQL pour Python, compatible avec l'API de base de données Python version 2.0. Elle est disponible à l'URL http://sourceforge.net/projects/mysql-python/.

24-G - MySQL Tcl API

MySQLtcl est une API simple pour accéder au serveur MySQL depuis le langage de programmation Tcl. Il est disponible sur http://www.xdobry.de/mysqltcl/.

24-H - Couche MySQL pour Eiffel

Eiffel MySQL est une interface avec le langage de programmation Eiffel, écrit par Michael Ravits. Il est disponible sur http://efsa.sourceforge.net/archive/ravits/mysql.htm.

25 - Pilotes MySQL

Ce chapitre décrit les différents pilotes MySQL qui fournissent l'interface entre le serveur MySQL et les clients.

25-A - Support ODBC de MySQL

MySQL supporte ODBC grâce au MySQL Connector/ODBC, une famille de pilote MyODBC. C'est la référence pour les produits Connector/ODBC, qui fournissent un accès compatible ODBC 3.5x à MySQL. Cette section vous montre comment installer MyODBC et l'utiliser. Vous obtiendrez aussi des informations sur les programmes les plus courants qui sont reconnus pour fonctionner avec MyODBC et les réponses aux questions les plus courantes à propos de MyODBC.

Cette section s'applique à MyODBC 3.51. Vous pouvez trouver le manuel pour les anciennes versions de MyODBC dans la distribution source ou binaire de cette version.

C'est la section de référence pour les pilotes MySQL ODBC, et non pas un guide général pour ODBC. Pour plus d'informations sur ODBC, reportez-vous à http://www.microsoft.com/data/.

La partie sur le développement d'application de ce manuel de référence suppose une bonne connaissance du développement C, des concepts de bases de données relationnelles et MySQL. Pour plus d'informations sur MySQL et ses fonctionnalités, voyez http://dev.mysql.com/doc/.

Si vous avez des questions qui ne sont pas dans ce document, envoyez-les à <myodbc@lists.mysql.com>.

25-A-1 - Introduction à MyODBC

25-A-1-a - Qu'est-ce que ODBC ?

ODBC (Open Database Connectivity) fournit un moyen aux clients pour accéder à une vaste gamme d'applications et de sources de données. ODBC est une interface standardisée, qui permet la connexion aux serveurs de bases de données. Elle a été développée en fonction des spécifications du SQL Access Group et définit un ensemble de fonction, code d'erreurs et types de donnés qui peuvent être utilisés pour développer des applications indépendantes des bases de données. ODBC est généralement utilisé lorsque l'indépendance à la base de données ou les accès simultanés de différents clients est nécessaire.

Pour plus d'informations sur ODBC, regardez http://www.microsoft.com/data/.

25-A-1-b - Qu'est-ce que Connector/ODBC ?

Connector/ODBC est le nom désignant la famille des pilotes MySQL ODBC. Ils sont reconnus sous le nom de pilotes MyODBC.

25-A-1-c - Qu'est-ce que MyODBC 2.50 ?

MyODBC 2.50 est un pilote 32 bits ODBC de MySQL AB, basé sur les spécifications ODBC 2.50 de niveau 0 (avec les fonctionnalités de niveau 1 et 2). C'est l'un des pilotes ODBC les plus populaires du marché Open Source, utilisés par de nombreux programmeurs pour accéder aux fonctionnalités de MySQL.

25-A-1-d - Qu'est-ce que MyODBC 3.51 ?

MyODBC 3.51 est un pilote 32 bits ODBC, aussi connu sous le nom de MySQL ODBC 3.51. Cette version est une amélioration de la version MyODBC 2.50. Elle supporte les spécifications ODBC 3.5x de niveau 1 (API complète plus fonctionnalités de niveau 2), afin de fournir un accès à toutes les fonctionnalités ODBC lors de l'accès à MySQL.

25-A-1-e - Où obtenir MyODBC ?

MySQL AB distribue tous ses produits sous licence General Public License (GPL). Vous pouvez obtenir une copie de la dernière version des binaires MyODBC et des sources sur le site Web de MySQL AB : http://dev.mysql.com/downloads/.

Pour plus d'informations sur MyODBC, visitez http://www.mysql.com/products/myodbc/.

25-A-1-f - Plateformes supportées

MyODBC peut être utilisé sur la plupart des systèmes d'exploitation supportant MySQL comme :

- Windows 95, 98, Me, NT, 2000, et XP ;

- Tous les systèmes Unix :

- AIX,

- Amiga,

- BSDI,

- DEC,

- FreeBSD,

- HP-UX 10, 11,

- Linux,

- Mac OS X Server,

- Mac OS X,

- NetBSD,

- OpenBSD,

- OS/2,

- SGI Irix,

- Solaris,

- SunOS,

- SCO OpenServer,

- SCO UnixWare,

- Tru64 Unix.

Si une distribution binaire n'est pas disponible pour le téléchargement d'une plateforme particulière, vous pouvez construire le pilote vous-même en téléchargeant les sources du pilote. Vous pouvez contribuer aux binaires MySQL en envoyant un courriel à <myodbc@lists.mysql.com>, de sorte qu'il devienne disponible pour d'autres utilisateurs.

25-A-1-g - Listes de diffusion MyODBC

MySQL AB fournit une assistance à la communauté des utilisateurs par le biais de ses listes de diffusion. Pour les questions liées à MyODBC, vous pouvez obtenir de l'aide auprès des utilisateurs expérimentés en utilisant <myodbc@lists.mysql.com>.
Pour plus d'informations sur l'abonnement à la liste de diffusion MySQL ou pour parcourir la liste des archives, visitez http://lists.mysql.com/.

25-A-1-h - Forum MyODBC

Le support communautaire de la part d'utilisateurs expérimentés est disponible via les forums de MySQL, situé sur http://forums.mysql.com.

25-A-1-i - Rapporter des problèmes avec MYODBC

Si vous rencontrez des difficultés avec MyODBC, commencez par faire un fichier de log avec le gestionnaire ODBC (le fichier de log que vous obtenez en demande les logs de ODBCADMIN) et un log MyODBC.

Pour obtenir un fichier de log MyODBC, vous devez faire ceci :

1. Assurez-vous que vous utilisez myodbcd.dll et non pas myodbc.dll. Le moyen le plus facile pour le faire est d'obtenir myodbcd.dll dans la distribution MYODBC et de le copier à la place de myodbc.dll, qui est probablement dans le dossier C:\windows\system32 ou C:\winnt\system32.
Notez que vous voudrez probablement récupérer votre vieux fichier myodbc.dll lorsque vous aurez fini de tester, car il est bien plus rapide que myodbcd.dll ;

2. Activez l'option 'Trace MyODBC' dans l'écran de configuration de MyODBC. Le fichier de log sera écrit dans le fichier C:\myodbc.log.
Si l'option de trace n'est pas recommandée lorsque vous retournez dans l'écran précédent, cela signifie que vous n'utilisez pas myodbcd.dll (voir ci-dessus) ;

3. Démarrez votre application, et faîtes la planter.

Vérifiez le fichier de trace MyODBC, pour essayer de comprendre ce qui ne va pas. Vous devriez être capable de trouver les requêtes émises en recherchant la chaîne >mysql_real_query dans le fichier myodbc.log.

Vous devriez aussi essayer de dupliquer la requête dans le client mysql ou admndemo pour voir si le problème vient de MYODBC ou MySQL.

Si vous trouvez quelque chose d'incorrect, n'envoyez que les lignes pertinentes (maximum, 40 lignes) à <myodbc@lists.mysql.com>. N'envoyez jamais le fichier de log MYODBC ou ODBC complet !

Si vous êtes incapables de trouver une erreur, la dernière option est de faire une archive (tar ou zip) qui contienne le fichier de trace MYODBC, le fichier de log ODBC, et un fichier README qui contienne une description du problème. Vous pouvez envoyer le tout à ftp://support.mysql.com/pub/mysql/secret/ [ftp://support.mysql.com/pub/mysql/secret/]. Seuls nous, à MYSQL AB, pourront accéder à ces fichiers, et nous seront très respectueux de vos données.

Si vous pouvez créer un problème qui reproduit le problème, essayez de l'uploader aussi !

Si le programme fonctionne avec d'autres serveurs SQL, vous devriez faire un log ODBC où vous faites exactement la même chose sur les autres serveurs SQL.

N'oubliez jamais que plus vous nous fournissez d'explication, plus nous pourront vous aider !

25-A-1-j - Comment soumettre un correctif MyODBC

Vous pouvez envoyer un correctif ou suggérer une meilleure solution à un problème en envoyant un message à <myodbc@lists.mysql.com>.

25-A-2 - Informations générales sur ODBC et MyODBC

25-A-2-a - Introduction à ODBC

Open Database Connectivity (ODBC) est une interface d'application populaire pour accéder aux bases de données. Elle est basée sur l'interface CLI Call-Level Interface de X/Open et ISO/IEC pour les bases de données, et utilise le SQL (Structured Query Language) comme langage d'accès.

La liste des fonctions ODBC supportées par MyODBC est donnée dans la section Section 25.1.16, « Table de référence MyODBC ». Pour les informations générales sur ODBC, voyez http://www.microsoft.com/data/.

25-A-2-b - Architecture MyODBC

L'architecture MyODBC est basée sur cinq composants, comme le montre le diagramme suivant :

- Application :
Une application est un programme qui appelle l'API ODBC pour accéder aux données à partir du serveur MySQL. L'application communique avec le gestionnaire de pilotes en utilisant les appels ODBC standard. L'application ne se soucie pas du lieu de stockage des données, de comment elles sont stockées, ou même comment le système est configuré pour accéder à celles-ci. Il a seulement besoin de connaître le nom de la source de données (DSN).
Un certain nombre de tâches sont communes à toutes les applications, peu importe la façon dont ils utilisent ODBC. Ces tâches sont les suivantes :

- sélection du serveur MySQL et s'y connecter ;

- envoi des instructions SQL pour l'exécution ;

- récupération des résultats (le cas échéant) ;

- les erreurs de traitements ;

- protection ou annulation de la transaction entourant l'instruction SQL ;

- déconnexion du serveur MySQL ;

L'accès aux données se fait avec SQL, les tâches principales des applications utilisant ODBC soumettent des instructions SQL et la récupération des résultats générés se fait via ces déclarations.

- gestionnaire de pilotes :
Le gestionnaire de pilotes est une bibliothèque qui gère les communications entre l'application et le ou les pilotes. Il effectue les tâches suivantes :

- résout les DSN (DSN) ;

- charge le pilote et le décharge ;

- la fonction ODBC appelle et transmet les communications au pilote.

- Pilote MyODBC :
Le pilote MyODBC est une bibliothèque qui implémente les fonctions de l'API ODBC. Il traite les appels des fonctions ODBC, soumet des requêtes SQL vers le serveur MySQL, et renvoie les résultats à l'application. Si nécessaire, le pilote modifie la demande d'une application de telle sorte que la demande soit conforme à la syntaxe prise en charge MySQL.

- ODBC.INI :
ODBC.INI est le fichier de configuration ODBC qui stocke les informations du pilote et la base de données nécessaire pour se connecter au serveur. Il est utilisé par le gestionnaire de pilote pour déterminer quel pilote doit être chargé à l'aide des DSN. Pour plus d'informations, Section 25.1.9, « MyODBC Configuration ».

- serveur MySQL :
Le serveur MySQL est la source de données. MySQL est :

- un système de gestion de base de données (SGBD) ;

- un système de gestion de base de données relationnelle (SGBDR) ;

- un logiciel gratuit.

25-A-2-c - Gestionnaire de pilotes ODBC

Un gestionnaire de pilotes ODBC est une bibliothèque qui gère les communications entre une application compatible ODBC et les pilotes. Ses fonctionnalités principales sont :

- résolution des noms de sources (DSN) ;

- chargement et déchargement des pilotes ;

- traitement des appels de fonctions ODBC et relais vers le pilote.

Les gestionnaires suivants sont les plus utilisés :

- Microsoft Windows ODBC Driver Manager (odbc32.dll), http://www.microsoft.com/data/ ;

- unixODBC Driver Manager for Unix (libodbc.so), http://www.unixodbc.org ;

- iODBC ODBC Driver Manager for Unix (libiodbc.so), http://www.iodbc.org ;

MyODBC 3.51 est aussi livré avec UnixODBC depuis la version 2.1.2.

25-A-2-d - Types de pilotes MySQL ODBC

MySQL AB supporte deux pilotes ODBC Open Source pour accéder à MySQL via l'API ODBC : MyODBC (MyODBC 2.50) et MySQL ODBC 3.51 Driver (MyODBC 3.51).

Note : dans cette section, nous nous référerons aux deux pilotes sous le nom de MyODBC. Lorsque la différence sera nécessaire, nous utiliserons les noms originaux.

25-A-3 - Comment installer MyODBC

MyODBC 2.50 est un pilote 32-bit ODBC 2.50 avec un niveau de spécification 0 (avec le niveau 1 et 2 de proposés) pour connecter une application compatible ODBC à MySQL. MyODBC fonctionne sur Windows 9x/Me/NT/2000/XP et la plupart des plateformes Unix. MyODBC 3.51 est une version améliorée avec les spécifications de niveau 1 de ODBC 3.5x (API noyau complète + fonctionnalités du niveau 2).

MyODBC est Open Source, et vous pouvez trouver la version la plus récente sur http://www.mysql.com/downloads/api-myodbc.html. Notez que les versions 2.50.x sont licenciées LGPL tandis que les versions 3.51.x sont licenciées GPL.

Si vous avez des problèmes avec MyODBC et que votre programme fonctionne aussi avec OLEDB, essayez le pilote OLEDB.

Normalement, vous n'avez besoin d'installer MyODBC que sur les machines Windows. Vous avez besoin d'installer MyODBC sous Unix si vous avez un programme tel que ColdFusion qui fonctionne sur les machines Unix et utilise ODBC pour se connecter aux bases de données.

Si vous voulez installer MyODBC sur un ordinateur Unix, vous aurez aussi besoin d'un gestionnaire ODBC. MyODBC est connu pour fonctionner avec la plupart des gestionnaires ODBC d'Unix.

Pour installer MyODBC sur Windows, vous devez télécharger le fichier .zip de MyODBC approprié, le décompresser avec WinZIP ou un programme similaire et exécuter le fichier SETUP.EXE.

Sur Windows/NT/XP vous pouvez obtenir l'erreur suivante durant l'installation de MyODBC :

An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart
Windows and try installing again (before running any applications which
use ODBC)

Le problème dans ce cas est qu'un autre programme utilise ODBC et du fait de l'architecture Windows, vous ne pouvez pas installer de nouveau pilote ODBC avec le programme d'installation de Microsoft ODBC. Dans la plupart des cas, vous pouvez continuer en cliquant juste sur Ignore pour copier le reste des fichiers MyODBC et l'installation finale devrait fonctionner. Si ce n'est pas le cas, la solution est de redémarrer votre machine en mode safe mode (faites-le en appuyant sur F8 juste avant que votre machine ne démarre Windows), installez MyODBC, et redémarrez en mode normal.

- Pour créer une connexion à un ordinateur Unix depuis un ordinateur Windows, avec une application ODBC (une qui ne supporte pas MySQL nativement), vous devez installer MyODBC sur l'ordinateur Windows.

- L'utilisateur et la machine Windows doivent avoir les droits d'accès au serveur MySQL situé sur la machine Unix. Vous pouvez configurer cela avec la commande GRANT. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

- Vous devez créer une entrée DNS ODBC comme suit :

- ouvrez le panneau de configuration de Windows ;

- double-cliquez sur l'icône Sources de données ODBC (32 bits) ;

- cliquez sur le volet User DSN ;

- cliquez sur le bouton Add ;

- sélectionnez MySQL dans l'écran Create New Data Source et cliquez sur le bouton Terminer ;

- L'écran de configuration par défaut du pilote MySQL est affiché. Voir Section 25.1.9.2, « Configuration du DSN MyODBC sur Windows ».

- Démarrez maintenant votre application et sélectionnez le pilote ODBC avec les DSN que vous avez spécifiés dans l'administrateur ODBC.

Notez que d'autres options de configuration sont présentes dans l'écran de MySQL (traçage, se connecter automatiquement, etc.), vous pouvez les essayer en cas de problèmes.

25-A-4 - Installer MyODBC depuis une distribution binaire sur Windows

Pour installer MyODBC sur Windows, il est recommandé de télécharger la distribution appropriée sur http://dev.mysql.com/downloads/connector/odbc/, la décompresser, et exécuter la commande MyODBC-VERSION.exe.

Sous Windows, vous pourriez rencontrer l'erreur suivante lors de l'installation d'un ancien pilote MyODBC 2.50 :

An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart
Windows and try installing again (before running any applications
which use ODBC)

Le problème est qu'un autre programme utilise ODBC. À cause de l'architecture de Windows, vous pourriez ne pas pouvoir installer de nouveau pilote ODBC avec le programme d'installation de Microsoft. Dans la plupart des cas, vous pouvez continuer avec le bouton Ignore pour copier le restant des fichiers MyODBC et l'installation finale peut fonctionner malgré tout. Si ce n'est pas le cas, la solution est de relancer votre ordinateur en « mode sans échec ». Choisissez ce mode en pressant F8 durant le redémarrage de Windows : installez MyODBC et relancez en mode normal.

25-A-5 - Installer MyODBC depuis une distribution binaire Unix

25-A-5-a - Installer MyODBC depuis un RPM d'une distribution

Pour installer ou mettre à jour MyODBC depuis un RPM sous Linux, il faut le télécharger et lancer les commandes adéquates sous root.

Si c'est la toute première installation :

shell> su root
shell> rpm -ivh MyODBC-3.51.01.i386-1.rpm

Si le pilote existe déjà, la mise à jour se fait de la façon suivante :

shell> su root
shell> rpm -Uvh MyODBC-3.51.01.i386-1.rpm

S'il y a des erreurs de dépendances de bibliothèques clients MySQL, libmysqlclient, il faut l'ignorer via l'option --nodeps, et soyez sûr que le client MySQL partage la bibliothèque dans sa variable d'environnement ou l'assigne à travers LD_LIBRARY_PATH.

L'installation se fait dans /usr/local/lib et /usr/share/doc/MyODBC respectivement. Voir Section 25.1.9.3, « Configuration d'un DSN MyODBC sous Unix ».

Pour désinstaller le pilote, connectez-vous en root et exécutez la commande rpm suivante :

shell> su root
shell> rpm -e MyODBC

25-A-5-b - Installer MyODBC depuis une distribution binaire Tarball

Pour installer le pilote à partir d'un fichier tar.gz de distribution de tarball, téléchargez la dernière version du pilote pour votre système d'exploitation et suivez ces étapes :

shell> su root
shell> gunzip MyODBC-3.51.01-i686-pc-linux.tar.gz
shell> tar xvf MyODBC-3.51.01-i686-pc-linux.tar
shell> cd MyODBC-3.51.01-i686-pc-linux

Lire les instructions dans le fichier INSTALL-BINARY file et exécutez les commandes.

shell> cp libmyodbc* /usr/local/lib
shell> cp odbc.ini /usr/local/etc
shell> export ODBCINI=/usr/local/etc/odbc.ini

Ensuite, lisez le how to configure the DSN on unix pour configurer le DSN pour ODBC. Pour plus d'informations, se référer au fichier INSTALL-BINARY de votre distribution.

25-A-6 - Installer MyODBC depuis la version source sur Windows

25-A-6-a - Prérequis

- MDAC, Microsoft Data Access SDK téléchargé sur http://www.microsoft.com/data/.

- Bibliothèques client MySQL et fichiers d'inclusions de MySQL 4.0.0 ou plus récent. (De préférence, MySQL version 4.0.16 ou plus récent). Ceci est nécessaire, car MyODBC utilise les nouvelles interfaces et structures qui ne sont disponibles que depuis cette version. Pour télécharger les bibliothèques clientes et les fichiers d'inclusion, voyez http://dev.mysql.com/downloads/.

25-A-6-b - Compiler MyODBC 3.51

Les distributions source de MyODBC 3.51 incluent les fichiers Makefiles et utilisent nmake. Dans la distribution, vous pouvez trouver le Makefile pour différentes versions et le Makefile_debug pour compiler les versions de débogage du pilote et des DLL.

Pour compiler le pilote, suivez la procédure suivante :

1. Téléchargez et décompressez les sources dans un dossier, puis placez-vous dans ce dossier. Les commandes suivantes supposeront que ce dossier s'appelle myodbc3-src :

C:\> cd myodbc3-src

2. Éditez le fichier Makefile pour spécifier le chemin correct vers les bibliothèques client MySQL et les fichiers d'inclusions. Puis, utilisez les commandes suivantes pour compiler et installer votre version :

C:\> nmake -f Makefile
C:\> nmake -f Makefile install

nmake -f Makefile compile la version de production du pilote, et place les exécutables dans le dossier Release.

nmake -f Makefile install installe (copie) le pilote DLL et les bibliothèques (myodbc3.dll, myodbc3.lib) dans votre dossier système.

3. Pour compiler la version de débogage, utilisez Makefile_Debug plutôt que Makefile, comme ceci :

C:\> nmake -f Makefile_debug
C:\> nmake -f Makefile_debug install

4. Vous pouvez nettoyer et recompiler le pilote avec les commandes suivantes :

C:\> nmake -f Makefile clean
C:\> nmake -f Makefile install

Note :

- Assurez-vous de spécifier le chemin correct jusqu'aux bibliothèques client MySQL et aux fichiers d'entêtes dans le fichier Makefile (modifiez les variables MYSQL_LIB_PATH et MYSQL_INCLUDE_PATH). Le chemin d'entête par défaut est C:\mysql\include. Le chemin par défaut pour la bibliothèque est C:\mysql\lib\opt pour les versions de publication, et C:\mysql\lib\debug pour les versions de débogage.

- Pour une documentation complète de nmake, visitez http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcepb40/htm/_wcepb_nmake_tool.asp.

- Si vous utilisez les sources sous BitKeeper pour la compilation, tous les fichiers Makefiles spécifiques à Windows sont nommés Win_Makefile*.

25-A-6-c - Tests de MyODBC

Après la compilation et l'installation des bibliothèques du pilote dans le système, vous pouvez tester votre installation avec les commandes suivantes, fournies dans le sous-dossier samples :

C:\> cd samples
C:\> nmake -f Makefile all

25-A-6-d - Compiler MyODBC 2.50

La distribution source MyODBC 2.50 inclut un projet VC. Vous pouvez compiler le pilote à partir de ces fichiers .dsp et .dsw, en les chargeant directement dans Microsoft Visual Studio 6.0 ou plus récent.

25-A-7 - Installer MyODBC depuis une source sur Unix

25-A-7-a - Prérequis

- Bibliothèques client MySQL et fichiers d'inclusions de MySQL 4.0.0 ou plus récent. (De préférence, MySQL version 4.0.16 ou plus récente). Ceci est nécessaire, car MyODBC utilise les nouvelles interfaces et structures qui ne sont disponibles que depuis cette version. Pour télécharger les bibliothèques clientes et les fichiers d'inclusion, regardez http://dev.mysql.com/downloads/.

- La bibliothèque MySQL doit être configurée avec l'option --enable-thread-safe-client. libmysqlclient installée comme une bibliothèque partagée.

- Un des gestionnaires de pilotes ODBC Unix suivants doit être installé :

- iodbc 3.0 ou plus récent (http://www.iodbc.org) ;

- unixodbc Alpha 3 ou plus récent (http://www.unixodbc.org).

- Si vous utilisez un jeu de caractères qui n'est pas compilé dans la bibliothèque du client MySQL (les valeurs par défaut sont : latin1 big5 czech euc_kr gb2312 gbk sjis tis620 ujis), alors vous devez installer les définitions de caractères mysql du répertoire charsets dans SHAREDIR (par défaut, /usr/local/mysql/share/mysql/charsets). Ceux-ci devraient déjà exister si vous avez installé le serveur MySQL sur la même machine.

Une fois que vous avez tous les fichiers requis, décompressez les fichiers sources dans un répertoire distinct et suivez les instructions indiquées ci-dessous.

25-A-7-b - Options de configuration générales

Le script configure vous présente plusieurs manières de configurer votre MyODBC build. En règle générale, vous faites cela en utilisant les options de la ligne de commande configure. Vous pouvez également atteindre configure en utilisant certaines variables d'environnement. Pour une liste des options et des variables d'environnement supportées par configure, exécutez cette commande :

shell> ./configure --help

Certaines des options de configure les plus couramment utilisées sont décrites ici :

1. Pour compiler MyODBC, vous devez fournir le chemin la bibliothèque client MySQL et les fichiers d'inclusion en utilisant l'option --with-mysql-path=DIR, où DIR est le répertoire où MySQL est installé.
Les options de compilation de MySQL peuvent être déterminées en exécutant DIR/bin/mysql_config.

2. Remplacer le chemin de l'entête standard et des fichiers de la bibliothèque par votre gestionnaire de pilotes ODBC (iodbc or unixobc).

- Si vous utilisez i et qu'iodbc n'est pas installé dans cet emplacement par défaut (/usr/local), vous aurez à utiliser l'option --with-iodbc=DIR , où DIR est le répertoire où iodbc est installé.
Si les entêtes iodbc ne sont pas présents dans DIR/include, vous pouvez utiliser l'option --with-iodbc-includes=INCDIR pour spécifier leur emplacement.
La règle s'applique aux bibliothèques. Si elles ne sont pas dans le répertoire DIR/lib, vous pouvez utiliser l'option --with-iodbc-libs=LIBDIR.

- Si vous utilisez unixODBC, utilisez l'option --with-unixODBC=DIR (sensible à la casse) pour faire examiner configure pour unixODBC au lieu de iodbc par défaut, DIR est le répertoire où unixODBC est installé.
Si les entêtes et bibliothèques unixODBC ne sont pas présents dans DIR/include et DIR/lib, utilisez les options -with-unixODBC-includes=INCDIR et -with-unixODBC-libs=LIBDIR.

3. Vous pouvez spécifier un préfixe d'installation autre que /usr/local. Par exemple, pour installer les pilotes MyODBC dans /usr/local/odbc/lib, utilisez l'option --prefix=/usr/local/odbc.

La dernière commande de configuration ressemblera à quelque chose comme ceci :

shell> ./configure --prefix=/usr/local \
--with-iodbc=/usr/local \
--with-mysql-path=/usr/local/mysql

25-A-7-c - Thread-Safe Client

Afin de lier le pilote avec les bibliothèques MySQL client thread safe libmysqlclient_r.so ou libmysqlclient_r.a, vous devez spécifier l'option de configure suivante :

--enable-thread-safe

et peut-être désactiver (par défaut) à l'aide de :

--disable-thread-safe

Cette option permet la création du pilote de la bibliothèque thread-safe à partir de la liaison avec la bibliothèque mysql client libmysqlclient_r.so thread-safe (Les extensions dépendent du système d'exploitation).

Lors de la configuration avec l'option thread-safe, si vous obtenez une erreur de configuration, regardez la config.log et vérifiez si elle est due à l'absence de thread-libraries dans le système ; et fournissez en une avec des options LIBS à savoir :

LIBS="-lpthread" ./configure ..

25-A-7-d - Options partagées ou statiques

Vous pouvez activer ou désactiver les versions partagées et statiques à l'aide de ces options :

--enable-shared[=yes/no]
--disable-shared
--enable-static[=yes/no]
--disable-static

25-A-7-e - Activation des informations de débogage

Par défaut, toutes les distributions binaires sont créées comme des versions sans débogage (configurées avec -without-debug).

Pour activer les informations de débogage, créez le pilote à partir de la distribution source et utilisez --with-debug) lorsque vous exécutez configure.

25-A-7-f - Activation de la documentation

Cette option n'est disponible que pour les clones BK ; pas pour les distributions de sources normales.

Par défaut, le pilote est construit avec (--without-docs) ; et quand vous voulez que la documentation soit prise en charge dans la construction normale, alors configurez avec :

--with-docs

25-A-7-g - Génération et compilation

Pour créer les bibliothèques de pilotes, il suffit d'exécuter make, qui prend tout en charge.

shell> make

Si des erreurs se produisent, corrigez-les et poursuivez le processus de génération. Si vous n'êtes pas en mesure de créer, envoyez un e-mail détaillé à <myodbc@lists.mysql.com> pour obtenir de l'aide.

25-A-7-h - Création des bibliothèques partagées

Sur la plupart des plateformes, MySQL ne crée pas ou ne prend pas en charge les bibliothèques clientes .so (partagées) par défaut, car la génération avec des bibliothèques partagées nous a causé des problèmes dans le passé.

Dans les cas comme celui-ci, vous devez télécharger la distribution MySQL et la configurer avec les options suivantes :

--without-server --enable-shared

Pour créer des bibliothèques de pilotes partagés, vous devez spécifier l'option --enable-shared pour configure. Par défaut, configure n'active pas cette option.

Si vous avez configuré avec l'option --disable-shared vous pouvez créer un fichier .so à partir des bibliothèques statiques en utilisant les commandes suivantes :

shell> cd MyODBC-3.51.01
shell> make
shell> cd driver
shell> CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error \
-o .libs/libmyodbc3-3.51.01.so \
catalog.o connect.o cursor.o dll.o error.o execute.o \
handle.o info.o misc.o myodbc3.o options.o prepare.o \
results.o transact.o utility.o \
-L/usr/local/mysql/lib/mysql/ \
-L/usr/local/iodbc/lib/ \
-lz -lc -lmysqlclient -liodbcinst

Assurez-vous de remplacer -liodbcinst par -lodbcinst si vous avez utilisé unixODBC au lieu de iODBC et configurez les chemins de bibliothèques en conséquence.

Cela génère et place le fichier libmyodbc3-3.51.01.so dans le répertoire .libs. Copiez ce fichier dans le répertoire de la bibliothèque MyODBC (/usr/local/lib (ou le répertoire lib dans le répertoire d'installation que vous avez fourni avec --prefix).

shell> cd .libs
shell> cp libmyodbc3-3.51.01.so /usr/local/lib
shell> cd /usr/local/lib
shell> ln -s libmyodbc3-3.51.01.so libmyodbc3.so

Pour créer la bibliothèque de pilote thread-safe :

shell> CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3_r-3.51.01.so
catalog.o connect.o cursor.o dll.o error.o execute.o
handle.o info.o misc.o myodbc3.o options.o prepare.o
results.o transact.o utility.o
-L/usr/local/mysql/lib/mysql/
-L/usr/local/iodbc/lib/
-lz -lc -lmysqlclient_r -liodbcinst

25-A-7-i - Installation des bibliothèques de pilotes

Pour installer les bibliothèques de pilotes, exécutez les commandes suivantes :

shell> make install

Cette commande installe une des bibliothèques suivantes :

Pour MyODBC 3.51 :

- libmyodbc3.so ;

- libmyodbc3-3.51.01.so, où 3.51.01 est la version du pilote ;

- libmyodbc3.a.

Pour thread-safe MyODBC 3.51 :

- libmyodbc3_r.so ;

- libmyodbc3-3_r.51.01.so ;

- libmyodbc3_r.a.

Pour MyODBC 2.5.0 :

- libmyodbc.so ;

- libmyodbc-2.50.39.so, où 2.50.39 est la version du pilote ;

- libmyodbc.a.

Pour plus d'informations sur le processus de création, se référer au fichier INSTALL qui est fourni avec la distribution source. Notez que si vous avez essayé d'utiliser make de Sun, vous risquez d'avoir des erreurs. D'autre part, gmake GNU devrait fonctionner correctement sur toutes les plateformes.

25-A-7-j - Tester MyODBC sur Unix

Pour exécuter les exemples de base fournis dans la distribution avec les bibliothèques que vous avez créées, exécutez simplement :

shell> make test

Assurez-vous que DSN 'myodbc3' est configuré en premier dans odbc.ini et que la variable d'environnement ODBCINI pointe vers le bon fichier odbc.ini ; et que le serveur MySQL est en cours d'exécution. Vous pouvez trouver un exemple de odbc.ini avec la distribution du pilote.

Vous pouvez même modifier le script samples/run-samples pour transmettre les valeurs DSN, UID et PASSWORD souhaitées en tant qu'arguments de ligne de commande à chaque échantillon.

25-A-7-k - Notes Mac OS X

Pour exécuter le pilote sur Mac OS X (Darwin), utilisez l'exemple configure suivant :

shell> ./configure --prefix=/usr/local
--with-unixODBC=/usr/local
--with-mysql-path=/usr/local/mysql
--disable-shared
--enable-gui=no
--host=powerpc-apple

La commande suppose que UnixODBC et MySQL sont installés aux emplacements par défaut. Sinon, configurez en conséquence.

Sur Mac OS X, --enable-shared crée des fichiers .dylib par défaut. Vous pouvez créer des fichiers .so comme ceci :

shell> make
shell> cd driver
shell> CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3-3.51.01.so *.o
-L/usr/local/mysql/lib/
-L/usr/local/iodbc/lib
-liodbcinst -lmysqlclient -lz -lc

Pour créer la bibliothèque du pilote thread-safe :

shell> CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3-3.51.01.so *.o
-L/usr/local/mysql/lib/
-L/usr/local/iodbc/lib
-liodbcinst -lmysqlclienti_r -lz -lc -lpthread

Assurez-vous de remplacer -liodbcinst par -lodbcinst si vous unixODBC au lieu de iODBC at configurez les chemins des bibliothèques conséquemment.

Dans la version Apple de GCC, les deux cc et gcc sont en fait des liens symboliques à gcc3.

Maintenant, copiez cette bibliothèque dans le répertoire $prefix/lib et créer un lien symbolique vers libmyodbc3.so.

Vous pouvez vérifier les propriétés de la bibliothèque partagée à l'aide de cette commande :

shell> otool -LD .libs/libmyodbc3-3.51.01.so

25-A-7-l - Notes HP-UX

Pour créer le pilote sur HP-UX 10.x ou 11.x, utilisez la commande configure suivante :

Si vous utilisez cc :

shell> CC="cc" \
CFLAGS="+z" \
LDFLAGS="-Wl,+b:-Wl,+s" \
./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql/lib/mysql
--enable-shared
--enable-thread-safe

Si vous utilisez gcc :

shell> CC="gcc" \
LDFLAGS="-Wl,+b:-Wl,+s" \
./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql
--enable-shared
--enable-thread-safe

Une fois le pilote créé, vérifiez ses attributs en utilisant chatr .libs/libmyodbc3.sl pour voir si vous devez avoir le chemin des bibliothèques client MySQL à l'aide de la variable d'environnement SHLIB_PATH. Pour les versions statiques, ignorez toutes les options de bibliothèque partagée et exécutez configure avec l'option --disable-shared.

25-A-7-m - Notes pour AIX

Pour compiler le pilote sur AIX, utilisez la commande configure suivante :

shell> ./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql
--disable-shared
--enable-thread-safe

NOTE : pour plus d'informations sur la compilation et la configuration de bibliothèques statiques ou partagées sur différentes plateformes, voyez « Using static and shared libraries across platforms ».

25-A-8 - Installer MyODBC depuis le serveur de versions BitKeeper

Note : il est recommandé de lire cette section si vous souhaitez nous aider à tester les nouveaux codes.

Pour obtenir la version la plus récente depuis les serveurs de versions, utilisez ces instructions :

1. Téléchargez BitKeeper depuis http://www.bitmover.com/cgi-bin/download.cgi. Vous aurez besoin de BitKeeper 3.0 ou plus récent pour vous connecter au serveur de versions.

2. Suivez les instructions fournies pour l'installer.

3. Une fois que BitKeeper est installé, placez-vous dans le dossier où vous voulez travailler, puis utilisez la commande suivante pour cloner la branche MyODBC 3.51 :

shell> bk clone bk://mysql.bkbits.net/myodbc3 myodbc-3.51

Dans l'exemple précédent, les sources seront installés dans le dossier myodbc-3.51/ ou par défaut dans le sous-dossier myodbc3/ de votre dossier courant. Si vous êtes derrière un pare-feu, et que vous devez initier les connexions HTTP, vous devrez utiliser BitKeeper via HTTP. Si vous devez utiliser un serveur proxy, il suffit de configurer la variable d'environnement http_proxy pour qu'elle pointe sur votre proxy :

shell> export http_proxy="http://your.proxy.server:8080/"

Maintenant, remplacez simplement bk:// par http:// lors du clonage. Par exemple :

shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc-3.51

Le téléchargement initial de l'arbre peut prendre un certain temps, en fonction de votre connexion : soyez patients.

4. Vous aurez besoin de GNU autoconf 2.52 (ou plus récent), automake 1.4, libtool 1.4 et m4 pour lancer les commandes suivantes.

shell> cd myodbc-3.51
shell> bk -r edit
shell> aclocal; autoheader; autoconf;  automake;
shell> ./configure  # Add your favorite options here
shell> make

Pour plus d'informations sur la compilation, lisez le fichier INSTALL dans le même dossier. Sous Windows, utilisez les fichiers Windows Makefiles WIN-Makefile et WIN-Makefile_debug pour compiler le pilote. Pour plus d'informations, voyez Section 25.1.6, « Installer MyODBC depuis la version source sur Windows ».

5. Lorsque la compilation est faite, lancez make install pour installer le pilote MyODBC 3.51 sur votre système.

6. Si vous avez atteint l'instruction make et que la distribution ne compile pas, envoyez un message à <myodbc@lists.mysql.com>.

7. Après la commande bk clone initiale, vous devez utiliser la commande bk pull régulièrement, pour obtenir les dernières modifications.

8. Vous pouvez examiner l'historique de changements du fichier avec toutes les modifications grâce à la commande bk sccstool. Si vous rencontrez des patchs étranges sur lesquels vous avez des questions, envoyez un mail à <myodbc@lists.mysql.com>.
De même, si vous pensez avoir une meilleure idée pour un traitement, envoyez un courriel avec votre patch. bk diffs va générer un patch pour vous, à partir de vos modifications. Si vous n'avez pas le temps de programmer votre idée, envoyez simplement une description.

9. BitKeeper dispose d'une aide en ligne précieuse, que vous pouvez obtenir avec bk helptool.

Vous pouvez aussi lire les listes de modifications, les commentaires et les sources en ligne : http://mysql.bkbits.net:8080/myodbc3.

25-A-9 - Configuration MyODBC

Cette section décrit comment configurer MyODBC, incluant la création d'un DSN et les différents arguments que prend le pilote comme « input » pour la connexion. Il décrit également comment créer le fichier de traces d'un fichier ODBC.

25-A-9-a - Qu'est-ce qu'un Data Source Name, ou Nom de Source de Données ?

Une « source de données » est un système qui émet des données. Les sources de données doivent avoir un identifiant persistant, appelé Data Source Name, ou Nom de Source de Données. En utilisant un Nom de Source de Données, MySQL peut accéder aux informations d'initialisation. Avec les informations d'initialisation, MySQL sait où accéder à la base, et quelles options de configuration utiliser lors de la connexion.

En effet, la source de données est un chemin vers les données. Dans un contexte différent, cela signifie autre chose, mais typiquement, cela identifie un serveur MySQL : par exemple, une adresse réseau, ou un nom de service ; plus un nom de base de données par défaut et les informations obligatoires comme le port, par exemple. Les pilotes MySQL, le système Windows et le gestionnaire ODBC utiliseront la source de données pour se connecter. Un utilitaire d'administration, appelé Microsoft ODBC Data Source Administrator peut être utile dans cette situation.

Il y a deux endroits pour stocker les informations d'initialisation : dans la base de registres de Windows, ou via un DSN sur n'importe quel système.

Si les informations sont dans la base de registres de Windows, elles sont dites sources de données Machine ("Machine data source"). Cela peut être une source de données utilisateur ("User data source"), auquel cas, seul un utilisateur pourra la voir. Ou, cela peut être une source de données système ("System data source"), auquel cas, elle sera accessible à tous les utilisateurs du système, ou même, tous les utilisateurs connectés au serveur. Lorsque vous exécutez le programme d'administration ODBC, vous aurez le choix entre "User" et "System" : ce sont deux onglets séparés.

Si les informations sont dans un fichier DSN, elles portent le nom de source de données fichiers ("File data source"). C'est un fichier texte. Les avantages sont que (a) c'est une option pour n'importe quel ordinateur et non pas seulement sur Windows ; (b) son contenu peut être transmis ou copié facilement.

25-A-9-b - Configuration du DSN MyODBC sur Windows

Pour ajouter et configurer une nouvelle source de données MyODBC sur Windows, utilisez le ODBC Data Source Administrator. Le ODBC Administrator modifie les informations de connexion à la source de données. En ajoutant de nouvelles sources, le ODBC Administrator met à jour la base des registres pour vous.

Ouvrir le ODBC Administrateur via le panneau de configuration :

1. Cliquez sur Démarrer, pointez Paramètres et cliquez sur Panneau de configuration.

2. Sur les ordinateurs exécutant Microsoft Windows 2000 ou version ultérieure, double-cliquez sur Outils d'administration, puis double-cliquez sur Sources de données (ODBC). Sur les ordinateurs exécutant des versions antérieures de Windows, double-cliquez sur ODBC 32 bits ou ODBC.

La boîte de dialogue ODBC Data Source Administrator s'affiche, comme indiqué ici :

Cliquez Help pour des informations détaillées sur chaque onglet de la boîte de dialogue ODBC Data Source Administrator.

Pour ajouter une source de données sous Windows :

1. Ouvrir le ODBC Data Source Administrator.

2. Dans la boîte de dialogue ODBC Data Source Administrator, cliquez Add. La boîte de dialogue Créer une nouvelle source de données apparaît.

3. Sélectionnez le pilote MySQL ODBC 3.51 et cliquez sur Terminer. La boîte de dialogue de configuration du pilote MySQL ODBC 3.51 apparaît comme suit :

4. Dans la zone Data Source Name entrez le nom de la source de données à laquelle vous souhaitez accéder. Il peut s'agir de n'importe quel nom valide que vous choisissez.

5. Dans la zone Description, entrez la description requise pour le DSN.

6. Pour Host ou Server Name (ou IP), saisissez le nom de l'hôte du serveur MySQL auquel vous souhaitez accéder. Par défaut c'est localhost.

7. Dans la zone Database Name, entrez le nom de la base de données MySQL que vous voulez utiliser comme base de données par défaut.

8. Dans la zone User, entrez votre nom d'utilisateur MySQL (l'ID de votre base de données).

9. Dans la zone Password, entrez votre mot de passe.

10. Dans la zone Port, entrez le numéro du port si ce n'est pas celui par défaut (3306).

11. Dans la zone SQL Command, vous pouvez entrer une instruction SQL facultative que vous souhaitez lancer automatiquement une fois la connexion établie.
La boîte de dialogue finale ressemble à ceci :

Cliquez OK pour ajouter la source de données.

Note : lorsque vous cliquez sur OK, la boîte de dialogue Sources de données s'affiche et l'administrateur ODBC met à jour les informations du Registre. Le nom d'utilisateur et la chaîne de connexion que vous avez entrés deviennent les valeurs de connexion par défaut pour cette source de données lorsque vous vous connectez à elle.

Vous pouvez également vérifier si vos paramètres sont adaptés à la connexion au serveur à l'aide du bouton Test Data Source. Cette fonctionnalité est disponible uniquement pour le pilote MyODBC 3.51. Un résultat de test réussi dans la fenêtre suivante :

Un test échoué entraîne une erreur :

La boîte de dialogue de configuration DSN dispose également d'un bouton Options. Si vous le sélectionnez, la boîte de dialogue d'options suivante s'affiche affichant le comportement du pilote de contrôle. Voir la Section 25.1.9.4, « Paramètres de connexion » pour plus d'informations sur la signification de ces options.

Note : Les options répertoriées sous Driver Trace Options sont désactivées (grisé) sauf si vous utilisez la version de débogage du pilote DLL.

Pour modifier la source de données sous Windows :

1. Ouvrir le ODBC Data Source Administrator. Cliquez sur l'onglet DSN approprié.

2. Sélectionnez la source de données MySQL que vous voulez modifier et cliquez sur Configure. La boîte de dialogue MySQL ODBC 3.51 Driver - DSN apparaît.

3. Modifiez les champs de source de données applicables, puis cliquez sur OK.

Lorsque vous avez terminé de modifier les informations dans cette boîte de dialogue, l'administrateur ODBC met à jour les informations du Registre.

25-A-9-c - Configuration d'un DSN MyODBC sous Unix

Sous Unix, vous configurez les DSN directement dans le fichier odbc.ini. Voici un exemple typique de fichier odbc.ini qui configure myodbc et myodbc3 comme noms DSN pour MyODBC 2.50 et MyODBC 3.51, respectivement :

;
;  odbc.ini configuration for MyODBC and MyODBC 3.51 drivers
;

[ODBC Data Sources]
myodbc      = MyODBC 2.50 Driver DSN
myodbc3     = MyODBC 3.51 Driver DSN

[myodbc]
Driver       = /usr/local/lib/libmyodbc.so
Description  = MyODBC 2.50 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

[myodbc3]
Driver       = /usr/local/lib/libmyodbc3.so
Description  = MyODBC 3.51 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

[Default]
Driver       = /usr/local/lib/libmyodbc3.so
Description  = MyODBC 3.51 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

Reportez-vous aux Sections 25.1.9.4, « Paramètres de connexion », pour la liste de paramètres de connexion qui sont disponibles.

Note : si vous utilisez unixODBC, vous pouvez utiliser les outils suivants pour configurer les DSN :

- ODBCConfig GUI(HOWTO: ODBCConfig) ;

- odbcinst.

Dans certains cas lorsque vous utilisez unixODBC, vous pouvez obtenir cette erreur :

Data source name not found and no default driver specified

Lorsque cela survient, assurez-vous que les variables d'environnement ODBCINI et ODBCSYSINI pointent sur le bon fichier odbc.ini. Par exemple, si votre fichier odbc.ini est situé dans /usr/local/etc, donnez les valeurs suivantes aux variables d'environnement :

export ODBCINI=/usr/local/etc/odbc.ini
export ODBCSYSINI=/usr/local/etc

25-A-9-d - Paramètres de connexion

Vous pouvez spécifier les paramètres suivants de MyODBC dans la section [Data Source Name] du fichier ODBC.INI ou via l'argument InConnectionString dans l'appel à SQLDriverConnect().

Paramètre

Valeur par défaut

Commentaire

user

ODBC (sur Windows)

Le nom de l'utilisateur pour se connecter à MySQL.

server

localhost

Le nom de l'hôte MySQL.

database

La base de données par défaut.

option

0

Options qui spécifient comment MyODBC fonctionne. Voir ci-dessous.

port

3306

Le port TCP/IP à utiliser si le server n'est pas localhost.

stmt

Une commande à exécuter lors de la connexion à MySQL.

password

Le mot de passe pour le compte user sur le serveur server.

socket

Le fichier de socket Unix ou le pipe nommé Windows utilisé pour se connecter à server s'il est sur localhost.

L'argument option sert à indiquer à MyODBC que le client n'est pas compatible à 100 % ODBC. Sur Windows, vous pouvez sélectionner des options avec les boîtes à cocher dans l'écran de configuration, mais vous pouvez aussi les configurer avec l'argument option. Les options suivantes sont listées dans l'ordre d'apparition à l'écran de connexion MyODBC :

Valeur

Description

1

Le client ne peut pas gérer la taille réelle des colonnes retournées par MyODBC.

2

Le client ne peut pas gérer la vraie valeur des lignes modifiées. Si cette option est active, MySQL retourne « found rows » à la place. Vous devez avoir MySQL 3.21.14 ou plus récent pour faire fonctionner cette option.

4

Crée un log de débogage dans c:\myodbc.log. Cela revient à ajouter la ligne MYSQL_DEBUG=d:t:O,c::\myodbc.log dans le fichier AUTOEXEC.BAT. (Sous Unix, ce fichier est /tmp/myodbc.log.)

8

Ne pas envoyer de limites de paquets pour les résultats et paramètres.

16

Ne pose aucune question, même si le pilote souhaite poser des questions.

32

Active ou désactive le support des curseurs dynamiques. (Interdit en MyODBC 2.50.)

64

Ignore l'utilisation du nom de la base de données dans la syntaxe db_name.tbl_name.col_name.

128

Force l'utilisation du gestionnaire de curseur ODBC (expérimental).

256

Désactive l'utilisation de la lecture étendue (extended fetch, expérimental).

512

Complète les colonnes CHAR jusqu'à leur taille maximale.

1024

SQLDescribeCol() retourne des noms de colonnes complets.

2048

Utilise le protocole client-serveur compressé.

4096

Indique au serveur qu'il peut ignorer l'espace après les noms de fonctions, avant la parenthèse ouvrante « ( » (exigé par PowerBuilder). Cela transforme tous les noms de fonctions en mots clés.

8192

Connexion au serveur mysqld avec les pipes nommés sous NT.

16384

Change les colonnes LONGLONG en INT (certaines applications ne peuvent pas gérer les LONGLONG).

32768

Retourne 'user' comme Table_qualifier et Table_owner de SQLTables (expérimental).

65536

Lit les paramètres du client depuis les groupes [client] et [odbc] dans my.cnf.

131072

Ajoute certaines vérifications de sécurité (normalement inutiles, mais sait-on jamais...)

262144

Désactive les transactions.

524288

Active le log de requêtes dans le fichier c:\myodbc.sql(/tmp/myodbc.sql). (Activé uniquement en mode débogage).

1048576

Ne met pas les résultats en cache localement dans le pilote, mais lit toujours auprès du serveur (mysql_use_result()). Cela ne fonctionne que pour les curseurs directs. Cette option est très importante pour traiter les très grandes tables, lorsque vous ne voulez pas que le pilote mette en cache toute la table.

2097152

Impose l'utilisation du curseur Forward-only. Dans le cas d'applications qui configurent le type par défaut des curseurs, et que vous souhaitez malgré tout ne pas mettre en cache les résultats, cette option imposera un comportement de curseur direct.

Pour sélectionner plusieurs options en même temps, additionnez leurs valeurs. Par exemple, l'option 12 (4+8) vous donne le débogage sans limite de paquets.

myodbc3.dll par défaut est compilé pour les meilleures performances. Si vous voulez déboguer MyODBC 3.51 (par exemple, pour activer les traces), vous devriez utiliser myodbc3d.dll. Pour installer ce fichier, copiez le fichier myodbc3d.dll à la place de myodbc3.dll. Assurez-vous de bien remettre la bonne bibliothèque une fois que vous avez fini, car la version de débogage peut vous ralentir considérablement.

Pour MyODBC 2.50, myodbc.dll et myodbcd.dll doivent être utilisés.

La table suivante affiche différentes valeurs recommandées pour option :

Configuration

Valeur

Microsoft Access

3

Microsoft Visual Basic

3

Grandes tables avec trop de lignes

2049

Génération de trace de débogage

4

Génération de log de requêtes

524288

Génération de logs de requêtes et de traces

524292

De grandes tables sans cache

3145731

25-A-9-e - Se connecter sans définir de DSN

C'est possible. Vous pouvez vous connecter à un serveur MySQL en utilisant SQLDriverConnect, et en spécifiant le champ DRIVER. Voici les chaînes de connexion à utiliser avec MyODBC pour une connexion sans DSN :

Pour MyODBC 2.50 :

ConnectionString = "DRIVER={MySQL};\
SERVER=localhost;\
DATABASE=test;\
USER=venu;\
PASSWORD=venu;\
OPTION=3;"

Pour MyODBC 3.51 :

ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};\
SERVER=localhost;\
DATABASE=test;\
USER=venu;\
PASSWORD=venu;\
OPTION=3;"

Si votre langage de programmation convertit les antislash suivis d'espaces en espace, il est préférable de spécifier la chaîne de connexion sous la forme d'une longue chaîne, ou d'utiliser la concaténation de plusieurs chaînes, sans ajouter d'espace entre :

ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"
"SERVER=localhost;"
"DATABASE=test;"
"USER=venu;"
"PASSWORD=venu;"
"OPTION=3;"

Reportez-vous à la section Section 25.1.9.4, « Paramètres de connexion », pour la liste complète des paramètres de connexion à fournir.

25-A-9-f - Établir une connexion distante d'un système A à un système B

Si vous voulez connecter un système A à un système B, avec le nom d'utilisateur et le mot de passe myuser et mypassword, voici une procédure simple :

1. Sur le système A, suivez les étapes suivantes :

1. Lancez le serveur MySQL.

2. Utilisez la commande GRANT pour configurer un compte avec le nom d'utilisateur de myuser qui peut se connecter depuis le système B, avec le mot de passe de myuser :

GRANT ALL ON *.* to 'myuser'@'B' IDENTIFIED BY 'mypassword';

3. La commande GRANT donne tous les droits à l'utilisateur myuser pour se connecter depuis le système B, en utilisant le mot de passe mypassword. Pour exécuter cette commande, il faut les droits de root sur le système A, ou un utilisateur équivalent. Pour plus d'informations sur le système de droits de MySQL, voyez la section Section 5.6, « Gestion des comptes utilisateurs de MySQL ».

2. Sur le système B, suivez ces instructions :

1. Configurez un DSN MyODBC en utilisant les informations de connexion suivantes :

DSN            = remote_test
SERVER or HOST = A (ou l'adresse IP du système A)
DATABASE       = test (La base de données par défaut)
USER           = myuser
PASSWORD       = mypassword

Pour configurer une connexion sans DSN, voyez Section 25.1.9.5, « Se connecter sans définir de DSN ».

2. Vérifiez si vous êtes capables d'accéder au système A depuis le système B avec un ping ou un autre moyen. Si vous n'êtes pas capables d'atteindre B, vérifiez votre réseau, les connexions Internet ou alors contactez votre administrateur réseau.

3. Maintenant, essayez de vous connecter en utilisant DSN=remote_test. Si vous échouez, lisez le log MyODBC, et suivez les instructions indiquées dans le message d'erreur du log. Si vous avez besoin d'autre support, envoyez un mail à <myodbc@lists.mysql.com>.

Vous pouvez aussi lire un HOWTO sur http://www.phphelp.com/tutorial/using-myodbc-to-connect-to-a-remote-database.html.

25-A-9-g - Obtenir un fichier de trace ODBC

Si vous rencontrez des difficultés ou des problèmes avec MyODBC, vous devriez lancer le programme en créant un fichier de log à partir du ODBC Manager (le log que vous obteniez de ODBC ADMIN) et MyODBC.

Pour obtenir une trace ODBC via le gestionnaire de pilotes, faites ceci :

- ouvrez l'administrateur de sources ODBC :

1. cliquez sur Start, pointez sur Settings, et ensuite cliquez sur Control Panel,

2. sur les machines Microsoft Windows 2000 ou XP, double-cliquez sur Administrative Tools, puis sur Data Sources (ODBC), comme montré ci-dessous.

Sur les machines avec des versions de Microsoft plus anciennes, double-cliquez sur 32-bit ODBC ou ODBC dans le panneau de contrôle,

3. le dialogue ODBC Data Source Administrator apparaît :

4. cliquez sur Help pour des informations détaillées sur chaque onglet de la boîte de dialogue.

- Activez l'option de trace. Cette procédure est différente sur Windows et sur Unix.
Pour activer l'option de trace sur Windows :

1. l'onglet Tracing de la boîte de dialogue de ODBC Data Source Administrator vous permet de configurer la trace des fonctions ODBC,

2. lorsque vous activez la trace depuis l'onglet Tracing, le Driver Manager va enregistrer toutes les fonctions ODBC de toutes les futures applications,

3. les fonctions ODBC des applications en fonctionnement ne sont pas enregistrées. Les fonctions ODBC sont enregistrées dans le fichier de log que vous spécifiez,

4. la trace cesse après que vous ayez cliqué sur Stop Tracing Now. N'oubliez pas que tant que la trace est active, le fichier de log continue de croître en taille, et que la trace ralentit toutes vos applications ODBC.

Pour activer la trace sous Unix :

1. Sous Unix, vous devez explicitement configurer l'option Trace dans le fichier ODBC.INI.
Spécifiez la valeur de ON ou OFF aux options TraceFile et Trace dans le fichier odbc.ini :

TraceFile  = /tmp/odbc.trace
Trace      = 1

TraceFile spécifie le nom et le chemin complet des fichiers de trace, et Trace vaut ON ou OFF. Vous pouvez aussi utiliser 1 ou YES pour ON et 0 ou NO pour OFF. Si vous utilisez ODBCConfig avec unixODBC, alors suivez les instructions de trace d'unixODBC sur HOWTO-ODBCConfig.

Pour générer un log MyODBC, faites ceci :

1. Assurez-vous que vous utilisez la bibliothèque de débogage DLL, c'est-à-dire myodbc3d.dll et non pas myodbc3.dll de MyODBC 3.51, et myodbcd.dll pour MyODBC 2.50.
La méthode la plus facile est de prendre myodbc3d.dll ou myodbcd.dll dans la distribution de MyODBC 3.51 et de copier le fichier myodbc3.dll ou myodbc.dll, qui est probablement dans votre dossier C:\windows\system32 ou C:\winnt\system32. Notez que vous souhaiterez sûrement remettre l'ancien fichier myodbc.dll lorsque vous aurez fini, car il est bien plus rapide que myodbc3d.dll et myodbcd.dll : alors gardez une copie de vos fichiers originaux.

2. Activez l'option Trace MyODBC dans l'écran de connexion MyODBC. Le log sera écrit dans le fichier C:\myodbc.log. Si l'option de trace n'est pas conservée lorsque vous retournez dans l'écran ci-dessus, cela signifie que vous n'utilisez pas le pilote myodbcd.dll. Sur Linux ou si vous avec une connexion sans DSN, il faut fournir l'option OPTION=4 dans la chaîne de connexion.

3. Lancez votre application et essayez de reproduire votre problème. Puis, vérifiez le fichier de trace ODBC.
Si vous trouvez un problème, envoyez un message à <myodbc@lists.mysql.com> ou à <support@mysql.com> si vous avez un contrat de support, avec une brève description de votre problème, et les informations suivantes :

- version de MyODBC,

- type de pilote ODBC et sa version,

- serveur MySQL et sa version,

- la trace ODBC du gestionnaire de pilote,

- le fichier de log MyODBC du pilote MyODBC,

- un exemple reproductible aussi simple que possible.

Pensez que plus vous nous fournissez d'explication, plus nous pourrons résoudre votre problème rapidement.

De plus, après avoir envoyé le rapport de bogue, vérifiez les listes de discussion MyODBC sur http://lists.mysql.com/.

25-A-9-h - Applications testées avec MyODBC

MyODBC a été testé avec les applications suivantes :

- MS Access 95, 97, 2000, and 2002 ;

- C++-Builder, Borland Builder 4 ;

- Centura Team Developer (formerly Gupta SQL/Windows) ;

- ColdFusion (on Solaris and NT with service pack 5), How-to: MySQL and Coldfusion. Troubleshooting Data Sources and Database Connectivity for UnixPlatforms (http://www.macromedia.com/v1/handlers/index.cfm?ID=11328&Method=Full&PageCall=/support/index.cfm lien mort) ;

- Crystal Reports ;

- DataJunction ;

- Delphi ;

- Erwin ;

- MS Excel ;

- iHTML ;

- FileMaker Pro ;

- FoxPro ;

- Notes 4.5/4.6 ;

- MS Visio Enterprise 2000 ;

- Vision ;

- Visual Objects ;

- Visual Interdev ;

- SBSS ;

- Perl DBD-ODBC ;

- Paradox ;

- Powerbuilder ;

- Powerdesigner 32-bit ;

- MS Visual C++ ;

- Visual Basic ;

- ODBC.NET through CSharp(C#), VB and C++ ;

- Data Architect(http://thekompany.com/products/dataarchitect/) ;

- SQLExpress for Xbase++(http://www.SQLExpress.net) ;

- Open Office (http://www.openoffice.org) How-to: MySQL + OpenOffice (http://dba.openoffice.org/proposals/MySQL_OOo.html lien mort). How-to: OpenOffice + MyODBC + unixODBC ;

- Star Office (http://wwws.sun.com/software/star/staroffice/6.0/index.html) ;

- G2-ODBC bridge (http://www.gensym.com) ;

- Sambar Server (http://www.sambarserver.info) How-to: MyODBC + SambarServer + MySQL.

Si vous connaissez d'autres applications fonctionnant avec MyODBC, s'il vous plaît, envoyez un courriel à <myodbc@lists.mysql.com>.

25-A-9-i - Programmes fonctionnant avec MyODBC

La majorité des programmes doivent pouvoir fonctionner avec MyODBC, mais ceux qui sont listés ici ont été testés par nous-mêmes, ou bien par des utilisateurs de confiance. Les descriptions fournissent des palliatifs aux problèmes rencontrés.

- Programme
Commentaire

- Access
Pour faire fonctionner Access :

- si vous utilisez Access 2000, il est recommandé d'installer la dernière version 2.6 ou plus récente, de Microsoft MDAC (Microsoft Data Access Components) depuis http://www.microsoft.com/data/. Cela va corriger un problème dans Access lors de l'exportation de données vers MySQL, lorsque le nom de la table et de ses colonnes ne sont pas spécifiés. Une autre solution à ce problème est de passer en MyODBC 2.50.33 et MySQL 3.23.x, qui, ensemble, fournissent un palliatif à ce problème.
Nous vous recommandons aussi d'appliquer le Microsoft Jet 4.0 Service Pack 5 (SP5) qui est téléchargeable sur http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114. Cela corrigera des situations où les colonnes sont marquées comme #DELETED# dans Access.
Note : si vous utilisez MySQL 3.22, vous devez appliquer le patch MDAC et utiliser MyODBC 2.50.32 ou 2.50.34 et plus récent pour corriger le problème,

- pour toutes les versions d'Access, vous devez activer l'option MyODBC Return matching rows. Pour Access 2.0, il faut aussi activer l'option Simulate ODBC 1.0,

- il faut avoir une colonne timestamp dans toutes les tables qui seront modifiées. Pour une portabilité maximale, n'utilisez pas de spécification de taille dans la déclaration de la colonne. C'est-à-dire, utilisez TIMESTAMP, et non TIMESTAMP(n), n < 14,

- vous devez avoir une clé primaire dans la table. Sinon, les nouvelles lignes ou les lignes modifiées risquent d'apparaître comme #DELETED#,

- utilisez uniquement des champs décimaux DOUBLE. Access ne sait pas comparer des décimaux simples. Le symptôme est généralement que les nouvelles lignes ou les lignes modifiées apparaissent comme #DELETED# ou que vous ne pouvez pas trouver ou modifier ces lignes,

- si vous utilisez MyODBC pour relier une table qui a une colonne BIGINT, le résultat risque d'apparaître comme #DELETED. La solution est la suivante :

- ajoutez une ou plusieurs colonnes TIMESTAMP,

- sélectionnez l'option Change BIGINT columns to INT dans le dialogue de connexion ODBC DSN Administrator,

- effacez le lien de la table depuis Access et recréez-le.

Les anciennes lignes seront toujours affichées comme #DELETED#, mais les nouvelles lignes seront affichées correctement.

- Si vous avez toujours des erreurs de type Another user has changed your data après avoir ajouté une colonne de type TIMESTAMP, le truc suivant pourra vous aider :
N'utilisez pas les données de la table table en mode tableau. Au lieu de cela, créez un formulaire avec les champs que vous voulez, et utilisez le mode tableau de ce form. Activez l'option DefaultValue de la colonne TIMESTAMP, avec la valeur NOW(). C'est une bonne idée que de masquer la colonne TIMESTAMP pour que les utilisateurs ne soient pas perturbés.

- Dans certains cas, Access génère des commandes SQL incorrectes que MySQL ne peut pas comprendre. Vous pouvez corriger cela en sélectionnant l'option "Query|SQLSpecific|Pass-Through" dans le menu d'Access.

- Sous NT, Access indique que les colonnes BLOB sont des OLE OBJECTS. Si vous voulez avoir des colonnes MEMO à la place, changez les colonnes BLOB en TEXT avec ALTER TABLE.

- Access ne peut pas toujours gérer les colonnes DATE correctement. Si vous avez des problèmes avec elles, utilisez DATETIME.

- Si vous avez une colonne d'Access définie comme BYTE, Access va l'exporter comme TINYINT au lieu de TINYINT UNSIGNED. Cela vous posera des problèmes si vous avez des valeurs supérieures à 127.

- ADO
Lorsque vous codez avec l'API ADO et MyODBC, vous devez faire attention aux propriétés par défaut qui ne sont pas supportées par MySQL. Par exemple, en utilisant CursorLocation Property, adUseServer va retourner un résultat de -1 pour RecordCount Property. Pour avoir la bonne valeur, vous devez donner la valeur de adUseClient à cette propriété, tel que présenté ci-dessous :

Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long

myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount

myrs.Close
myconn.Close

Un autre palliatif est d'utiliser SELECT COUNT(*) pour connaître le nombre de lignes.

- Active server pages (ASP)
Il est recommandé de sélectionner l'option Return matching rows.

- applications BDE
Pour faire fonctionner ces applications, vous devez sélectionner les options Don't optimize column widths et Return matching rows.

- Borland Builder 4
Lorsque vous lancez une requête, vous pouvez utiliser la propriété Active ou la méthode Open. Notez que Active commencera par émettre automatiquement une requête SELECT * FROM .... Cela n'est pas forcément pratique si vos tables sont grandes.

- ColdFusion (On Unix)
Les informations suivantes sont tirées de la documentation ColdFusion :
Utilisez les informations suivantes pour configurer le serveur ColdFusion pour Linux avec le pilote unixODBC et MyODBC pour MySQL. Allaire a vérifié que MyODBC 2.50.26 fonctionne avec MySQL 3.22.27 et ColdFusion pour Linux. Toutes les versions plus récentes devraient aussi fonctionner. Vous pouvez télécharger MyODBC sur http://dev.mysql.com/downloads/connector/odbc/.
ColdFusion Version 4.5.1 vous permet d'utiliser l'administrateur ColdFusion pour ajouter des sources de données MySQL. Cependant, le pilote n'est pas inclus avec ColdFusion Version 4.5.1. Avant que le pilote MySQL n'apparaisse dans les listes de sources ODBC, vous devez compiler et copier le pilote MyODBC dans /opt/coldfusion/lib/libmyodbc.so.
Le dossier Contrib contient le programme mydsn-xxx.zip qui vous permet de compiler et supprimer le fichier DSN pour les applications Coldfusion qui utilisent le pilote MyODBC.

- DataJunction
Vous devez changer pour exporter des VARCHAR au lieu des types ENUM, car l'export de ce dernier pose des problèmes à MySQL.

- Excel
Fonctionne. Quelques conseils :

- Si vous avez des problèmes avec les dates, essayez de les transformer en chaîne, avec la fonction CONCAT() . Par exemple :

SELECT CONCAT(rise_time), CONCAT(set_time)
FROM sunrise_sunset;

Les valeurs lues comme des chaînes seront reconnues correctement par Excel97.

Le but de CONCAT() dans cet exemple est de faire croire à ODBC que la colonne est de type « chaîne ». Sans CONCAT(), ODBC sait que la colonne est de type TIME, et Excel ne le comprendra pas.

Notez que c'est un bogue dans Excel, car il convertit automatiquement une chaîne en heure. Cela serait bien si la source était un fichier de texte, mais malheureusement ici, la connexion ODBC indique le bon type pour chaque colonne.

- Word
Pour lire des données depuis MySQL vers des documents Word/Excel, vous devez utiliser le pilote MyODBC et le Add-in Microsoft Query.
Par exemple, pour créer une base de données avec une table avec 2 colonnes de texte :

- insérez deux lignes avec le client mysql ;

- créez un fichier DSN file en utilisant le gestionnaire ODBC, par exemple, my, pour la base de données créée ;

- lancez Word,

- créez un document vide,

- dans la barre d'outil Database, cliquez sur le bouton Insert Database,

- cliquez sur le bouton Get Data,

- dans la gauche de l'écran Get Data, cliquez sur Ms Query,

- dans Ms Query, créez une nouvelle source de données en utilisant le DSN my,

- sélectionnez la nouvelle requête,

- sélectionnez les colonnes que vous voulez,

- ajoutez le filtre que vous voulez,

- ajoutez le tri que vous souhaitez,

- sélectionnez Return Data to Microsoft Word,

- cliquez sur Finish,

- cliquez sur Insert Data et sélectionnez les lignes,

- Cliquez sur OK et voyez les lignes dans votre document Word.

- odbcadmin
Programme de test pour ODBC.

- Delphi
Vous devez utiliser BDE Version 3.2 ou plus récent. Sélectionnez l'option Don't optimize column width lors de la connexion à MySQL.
De plus, il y a des codes pratiques Delphi qui configurer une entrée ODBC et une source BDE pour MyODBC. La source BDE requiert BDE Alias Editor qui est gratuit sur Delphi Super Page. (Merci à Bryan Brunton <bryan@flesherfab.com> pour cela) :

fReg:= TRegistry.Create;
fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
fReg.WriteString('Database', 'Documents');
fReg.WriteString('Description', ' ');
fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
fReg.WriteString('Flag', '1');
fReg.WriteString('Password', '');
fReg.WriteString('Port', ' ');
fReg.WriteString('Server', 'xmark');
fReg.WriteString('User', 'winuser');
fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
fReg.WriteString('DocumentsFab', 'MySQL');
fReg.CloseKey;
fReg.Free;

Memo1.Lines.Add('DATABASE NAME=');
Memo1.Lines.Add('USER NAME=');
Memo1.Lines.Add('ODBC DSN=DocumentsFab');
Memo1.Lines.Add('OPEN MODE=READ/WRITE');
Memo1.Lines.Add('BATCH COUNT=200');
Memo1.Lines.Add('LANGDRIVER=');
Memo1.Lines.Add('MAX ROWS=-1');
Memo1.Lines.Add('SCHEMA CACHE DIR=');
Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
Memo1.Lines.Add('SQLQRYMODE=');
Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
Memo1.Lines.Add('ENABLE BCD=FALSE');
Memo1.Lines.Add('ROWSET SIZE=20');
Memo1.Lines.Add('BLOBS TO CACHE=64');
Memo1.Lines.Add('BLOB SIZE=32');

AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);

- C++ Builder
Testé avec BDE Version 3.0. Le seul problème est que lorsque le schéma de tables change, les champs de requêtes ne sont pas mis à jour. BDE, de son côté, ne semble pas reconnaître les clés primaires, et seulement l'index appelé PRIMARY, mais ce n'est jamais un problème.

- Vision
Vous devez sélectionner l'option Return matching rows.

- Visual Basic
Pour être capable de modifier une table, vous devez définir une clé primaire dans la table.
Visual Basic avec ADO ne peut pas gérer les grands entiers. Cela signifie que certaines requêtes comme SHOW PROCESSLIST ne fonctionneront pas comme attendu. Pour pallier ce problème, il faut utiliser l'option OPTION=16384 dans la chaîne de connexion ODBC ou sélectionnez l'option Change BIGINT columns to INT dans l'écran MyODBC. Vous pouvez aussi sélectionner l'option Return matching rows.

- VisualInterDev
Si vous avez un BIGINT dans votre résultat, vous pouvez aussi avoir l'erreur [Microsoft][ODBC Driver Manager] Driver does not support this parameter. Essayez de sélectionner Change BIGINT columns to INT dans la configuration MyODBC.

- Visual Objects
Vous devriez sélectionner l'option Don't optimize column widths.

- MS Visio Enterprise 2000
Nous avons créé un diagramme de base de données en connectant depuis MS Vision Enterprise 2000 vers MySQL via MyODBC (2.50.37 ou plus récent) et en utilisant les fonctions de rétro-ingénierie de Visio pour lire les informations sur la base (Visio montre toutes les définitions de colonnes, les clés primaires, les index, etc.). De plus, nous avons aussi testé la conception de nouvelles tables avec Visio, et avons réussi à les exporter de MySQL via MyODBC.

25-A-10 - Problèmes avec les connexions MyODBC

Cette section répond aux questions des connexions MyODBC.

25-A-10-a - Durant la configuration d'un DSN MyODBC, une erreur Could Not Load Translator or Setup Library survient

Pour plus d'informations, reportez-vous à MS KnowledgeBase Article(Q260558). De plus, assurez-vous que vous avez la dernière version ctl3d32.dll dans votre système.

25-A-10-b - Lors de la connexion, une erreur Access denied survient

Reportez-vous à Section 5.5.8, « Causes des erreurs Access denied ».

25-A-10-c - Informations  à propos des pools de connexions ODBC

Lisez ce document sur les pools de connexions : http://support.microsoft.com/default.aspx?scid=kb;EN-US;q169470.

25-A-11 - MyODBC et Microsoft Access

Cette section répond aux questions reliées à MyODBC et Microsoft Access.

25-A-11-a - Comment configurer Microsoft Access pour travailler avec MySQL via MyODBC ?

Les instructions suivantes doivent être faites sur votre PC, pour que Microsoft Access fonctionne avec MyODBC.

1. Si vous utilisez Access 2000, vous devez installer la dernière version (2.6 ou plus récent) de Microsoft MDAC (Microsoft Data Access Components) depuis http://www.microsoft.com/data/. Cela va corriger un bug d'Access qui survient lors de l'export vers MySQL, si les noms de table et de colonne ne sont pas spécifiés. Un autre moyen de contourner ce bug est de passer en MyODBC 2.50.33 et MySQL 3.23.x, qui pallie ce problème.
Il est aussi recommandé d'obtenir et appliquer le Microsoft Jet 4.0 Service Pack 5 (SP5), qui est disponible sur http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114. Cela va corriger certains cas où les colonnes sont marquées comme #DELETED# par Access.
Note : si vous utilisez MySQL 3.22, vous devez appliquer le patch MDAC et utiliser MyODBC 2.50.32 ou 2.50.34 et plus récent pour corriger ce problème.

2. Installez la dernière version de MySQL depuis http://dev.mysql.com/downloads/.

3. Installez la dernière version de MyODBC 3.51 ou 2.50 depuis http://dev.mysql.com/downloads/connector/odbc/.

4. Pour toutes les versions d'Access, il faut activer les options Return matching rows.

5. Utilisez Access comme Access interface pour MySQL via MyODBC.

25-A-11-b - Comment exporter une table ou une requête depuis Access vers MySQL ?

Vous ne pouvez pas exporter de table ou requête vers MySQL sans avoir installé MyODBC.

Pour exporter une table depuis Access vers MySQL, suivez ces instructions :

1. Lorsque vous ouvrez une base de données Access ou un projet Access, une fenêtre de base de données apparaît. Elle affiche les raccourcis pour créer une nouvelle base de données, ou ouvrir une base existante.

2. Cliquez sur le nom de la table ou de la requête query que vous souhaitez exporter, puis dans le menu File, sélectionnez Export.

3. Dans la boite de dialogue Export Object Type Object name To, dans le champ Save As Type, sélectionnez ODBC Databases () comme ci-dessous :

4. Dans la boîte de dialogue Export, entrez le nom d'un fichier ou bien utilisez le nom suggéré, et sélectionnez OK.

5. Le dialogue de sélection de source de données est alors affiché : il affiche les sources de données ODBC disponibles sur votre machine. Cliquez sur l'onglet File Data Source ou sur Machine Data Source, puis double-cliquez sur la source MyODBC ou MyODBC 3.51 que vous souhaitez exporter. Pour définir une nouvelle source MyODBC, voyez Section 25.1.9.2, « Configuration du DSN MyODBC sur Windows ».

Microsoft Access se connecte alors au serveur via ODBC et exporte les données.

25-A-11-c - Comment importer ou relier des bases de données MySQL avec Access ?

Vous ne pouvez pas exporter une table ou une requête vers un serveur MySQL sans avoir installé le pilote MyODBC.

Pour importer ou relier des tables depuis MySQL vers Access, suivez les instructions suivantes :

1. Ouvrez la base de données, ou passez à la fenêtre de bases de données de la base courante.

2. Pour importer des tables, dans le menu File, pointer sur Get External Data, et cliquer sur Import. Pour lier des tables, dans le menu File, pointez sur Get External Data, et cliquez sur Link Tables.

3. Dans le dialogue Import (ou Link), dans le champ Files Of Type, sélectionnez ODBC Databases (). Le dialogue Select Data Source liste les différentes sources de données : toutes les sources de tous les pilotes de votre machine sont listées ici. Cliquez sur l'onglet File Data Source ou Machine Data Source, puis double-cliquez sur une source MyODBC ou MyODBC 3.51, que vous voulez exporter. Pour définir une nouvelle source pour MyODBC ou MyODBC 3.51, voyez Section 25.1.9.2, « Configuration du DSN MyODBC sur Windows ».

4. Si la source ODBC que vous avez sélectionnée requiert une identification, saisissez votre nom d'utilisateur et votre mot de passe (ainsi que les informations complémentaires éventuelles), puis cliquez sur OK.

5. Microsoft Access se connecte au serveur MySQL via ODBC et affiche la liste des tables que vous pouvez importer ou lier.

6. Cliquez sur chaque table que voulez importer ou lier, puis cliquez sur OK. Si vous liez une table et qu'elle n'a pas d'index unique, alors Microsoft Access affiche une liste de champs de la table. Cliquez sur un champ ou une combinaison de champs qui identifieront sans ambiguïté une ligne, puis OK.

25-A-11-d - La structure ou la localisation d'une table liée a changé. Est-ce que je peux voir ces changements localement ?

Oui. Utilisez la procédure suivante pour voir ou rafraîchir les liens lorsque la structure ou la localisation d'une table liée a changé. Le Linked Table Manager liste les chemins de toutes les tables liées courantes.

Pour voir ou rafraîchir des liens :

1. Ouvrez la base de données qui contient les tables liées.

2. Dans le menu Tools, pointez sur Add-ins, et cliquez sur Linked Table Manager.

3. Sélectionnez la boîte à cocher des tables que vous voulez rafraîchir.

4. Cliquez sur le bouton OK.

Microsoft Access confirme les rafraîchissements réussis, ou, si une table n'a pu être trouvée, affiche le dialogue Select New Location of <table name>, dans lequel vous pouvez indiquer les nouvelles informations de la table. Si plusieurs tables ont été déplacées, le Linked Table Manager va rechercher dans ce dossier toutes les autres tables sélectionnées : il va mettre à jour plusieurs liens d'un coup.

Pour changer le chemin vers un jeu de tables liées :

1. Ouvrez la base de données qui contient les tables liées.

2. Dans le menu Tools, pointer sur Add-ins, et cliquez dans Linked Table Manager.

3. Sélectionnez la boîte Always Prompt For A New Location.

4. Sélectionnez la boîte des tables dont vous voulez modifier les liens, et cliquez dans OK.

5. Dans le dialogue Select New Location of <table name>, spécifiez la nouvelle localisation, cliquez dans Open, puis cliquez dans OK.

25-A-11-e - Lorsque j'insère ou modifie une ligne dans des tables liées, j'obtiens #DELETED#

Si la ligne insérée ou modifiée est présentée comme #DELETED#, alors :

- si vous utilisez Access 2000, il est recommandé d'installer la dernière version (version 2.6 ou plus récent) Microsoft MDAC (Microsoft Data Access Components) depuis http://www.microsoft.com/data/. Cela va corriger un bogue d'Access qui ne spécifie pas les noms des colonnes et des tables lors de leur exportation vers MySQL. Un autre palliatif est de passer en MyODBC 2.50.33 et MySQL 3.23.x, qui compense ce problème.
Il est aussi recommandé d'appliquer le paquet de service Microsoft Jet 4.0 Service Pack 5 (SP5) qui est disponible sur http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114. Cela corrigera certains cas où les colonnes sont marquées comme #DELETED# dans Access.
Note : si vous utilisez MySQL 3.22, vous devez appliquer le patch MDAC et utiliser MyODBC 2.50.32 ou 2.50.34 puis corriger ce problème ;

- pour toutes les versions d'Access, il est recommandé d'activer l'option MyODBC Return matching rows. Pour Access 2.0, il est recommandé d'ajouter l'option Simulate ODBC 1.0 ;

- il est recommandé d'avoir un timestamp dans toutes les tables que vous voulez pouvoir modifier. Pour une portabilité maximale, n'utilisez pas de taille de colonne dans la déclaration. C'est-à-dire, utilisez TIMESTAMP et non pas TIMESTAMP(n), n < 14 ;

- il est recommandé d'avoir toujours une clé primaire dans une table. Sinon, les nouvelles lignes ou les lignes modifiées peuvent être indiquées comme #DELETED# ;

- utilisez uniquement des champs décimaux DOUBLE. Access échoue à comparer des décimaux simples. Le symptôme est alors que les nouvelles lignes sont indiquées comme #DELETED# ou que vous ne pouvez pas les trouver ;

- si vous utilisez MyODBC pour relier une table qui a une colonne BIGINT, le résultat risque d'être affiché comme #DELETED. Le palliatif est :

- ajoutez une colonne avec le type TIMESTAMP,

- sélectionnez l'option Change BIGINT columns to INT dans le dialogue de connexion du gestionnaire ODBC,

- effacez le lien de table depuis Access, puis recréez-le.

Les anciennes lignes seront affichées comme #DELETED#, mais les nouvelles lignes seront affichées correctement.

25-A-11-f - Comment puis-je éviter les conflits d'écriture ou de localisation ?

Si vous rencontrez les erreurs suivantes, sélectionnez l'option Return Matching Rows dans la configuration du DSN, ou spécifiez OPTION=2, comme paramètre de connexion :

Write Conflict. Another user has changed your data.

Row cannot be located for updating. Some values may have been changed
since it was last read.

25-A-11-g - Lorsque j'exporte une table depuis Access 97, une erreur de syntaxe étrange survient

C'est une erreur étrange avec Access 97, qui n'apparaît plus avec Access 2000 ou 2002. Vous pouvez contourner ce problème en mettant à jour le pilote MyODBC en version MyODBC 3.51.02 ou plus récente.

25-A-11-h - Access retourne l'erreur Another user has modified the record that you have modified durant l'édition de lignes

Avec certains programmes, cette erreur survient : Another user has modified the record that you have modified. Dans la majorité des cas, ce problème peut être résolu avec l'une des techniques suivantes :

- ajouter une clé primaire dans la table, s'il n'y en a pas ;

- ajouter une colonne timestamp dans la table, s'il n'y en a pas ;

- utiliser uniquement des nombres décimaux doubles. Certains programmes échouent lors de la comparaison avec des décimaux simples.

Si ces stratégies ne vous dépannent pas, essayez de faire un log depuis le gestionnaire ODBC (c'est le log que vous obtenez lorsque vous demandez des logs depuis ODBCADMIN), et un log MyODBC vous aidera à comprendre ce qui se passe. Pour des instructions, voyez Section 25.1.9.7, « Obtenir un fichier de trace ODBC ».

25-A-11-i - Comment intercepter les messages d'erreur d'identification ODBC ?

Lisez, en anglais, « How to Trap ODBC Login Error Messages in Access » sur http://support.microsoft.com/support/kb/articles/Q124/9/01.asp?LN=EN-US&SD=gn&FR=0%3CP%3E.

25-A-11-j - Comment optimiser les performances d'accès avec MyODBC ?

- Optimizing for Client/Server Performance.

- Tips for Converting Applications to Using ODBCDirect.

- Tips for Optimizing Queries on Attached SQL Tables.

25-A-11-k - J'ai de très grandes tables. Quelle est la meilleure configuration pour que MyODBC accède à ces tables ?

Si vous avez de très grandes (longues) tables dans Access, elles peuvent prendre beaucoup de temps à s'ouvrir. Ou alors, vous allez consommer beaucoup de mémoire et finir avec une erreur bloquante de type ODBC Query Failed. Pour régler ce problème, sélectionnez une des options suivantes :

- Return Matching Rows (2) ;

- Allow BIG Results (8).

La somme de ces deux options fait alors 10 (OPTION=10).

25-A-11-l - Comment spécifier la valeur de QueryTimeout pour les connexions ODBC ?

Lisez, en anglais, « Set the QueryTimeout Value for ODBC Connections » sur http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B153756.

25-A-11-m - INFO : outils pour exporter/importer des données entre Access et MySQL

Voyez la section converters (http://www.mysql.com/portal/software/convertors/ lien mort) pour une liste d'outils disponibles.

25-A-12 - MyODBC et Microsoft VBA et ASP

Cette section répond aux questions reliées à MyODBC utilisé avec Microsoft Visual Basic (ADO, DAO & RDO) et ASP.

25-A-12-a - Pourquoi est-ce que SELECT COUNT(*) FROM tbl_name retourne une erreur ?

L'expression COUNT(*) retourne un entier de type BIGINT, et ADO ne comprend pas les nombres aussi gros. Sélectionnez l'option Change BIGINT columns to INT (Valeur 16384).

25-A-12-b - Quand j'utilise les méthodes ADO AppendChunk() ou GetChunk(), j'ai une erreur Multiple-step operation generated errors. Check each status value ?

Les méthodes GetChunk() et AppendChunk() d'ADO ne fonctionnent pas comment on l'attend lorsque la position du curseur est spécifiée avec adUseServer. D'un autre côté, vous pouvez pallier cette erreur avec adUseClient.

Un exemple simple est disponible sur http://www.dwam.net/iishelp/ado/docs/adomth02_4.htm.

25-A-12-c - Comment connaître le nombre total de lignes affectées par une requête SQL, avec ADO ?

Vous pouvez utiliser la propriété RecordsAffected de la méthode ADO execute. Pour plus d'informations sur l'utilisation de cette méthode, voyez http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcnnexecute.asp.

25-A-12-d - Comment puis-je gérer des données BLOB avec Visual Basic ?

Voici un excellent article de Mike Hillyer (<m.hillyer@telusplanet.net>) qui explique comment insérer et/ou lire des données dans des colonnes de type BOLD via MyODBC depuis ADO : MySQL BLOB columns and Visual Basic 6 (http://www.dynamergy.com/mike/articles/blobaccessvb.html lien mort).

25-A-12-e - Comment associer les types de données de Visual Basic avec ceux de MySQL ?

Voici un autre article brillant de Mike Hillyer (<m.hillyer@telusplanet.net>) : How to map Visual basic data type to MySQL types (http://www.dynamergy.com/mike/articles/vbmysqldatatypes.php lien mort).

25-A-12-f - Exemple VB avec ADO, DAO et RDO

Des exemples simples pour utiliser ADO, DAO et RDO avec VB sont disponibles sur ces sites :

- exemple avec ADO : Section 25.1.19, « MyODBC avec VB : ADO, DAO and RDO » ;

- exemple avec DAO : Section 25.1.19, « MyODBC avec VB : ADO, DAO and RDO » ;

- exemple avec RDO : Section 25.1.19, « MyODBC avec VB : ADO, DAO and RDO ».

Si vous trouvez d'autres bons exemples ou des tutoriels ADO/DAO/RDO, alors laissez-nous un message sur <myodbc@lists.mysql.com>.

25-A-12-g - ASP et MySQL avec MyODBC

Pour plus d'informations sur comment accéder à MySQL via ASP avec MyODBC, reportez-vous aux articles suivants :

- Using MyODBC To Access Your MySQL Database Via ASP ;

- ASP and MySQL at DWAM.NT (http://www.dwam.net/mysql/asp_myodbc.asp lien mort).

Une liste de questions fréquentes pour ASP est disponible sur http://support.microsoft.com/default.aspx?scid=/Support/ActiveServer/faq/data/adofaq.asp.

25-A-12-h - INFO : Question fréquemment posée sur les objets ActiveX Data Objects (ADO)

Pour plus d'informations, voyez ActiveX Data Objects(ADO) Freqently Asked Questions.

25-A-13 - MyODBC et les outils tierce partie

Cette section répond aux questions relatives à MyODBC en conjonction avec des outils ODBC, tels que Microsoft Word et Excel, ainsi que ColdFusion.

25-A-13-a - Comment lire les données MySQL dans un document Word ou Excel ?

Pour lire les données de MySQL vers Word/Excel, vous devez installer le pilote MyODBC et le compagnon Microsoft Query (Add-in Office).

Par exemple, créez une base de données avec une table, contenant les deux colonnes suivantes :

- insérez des lignes avec le client mysql ;

- créez un fichier DSN avec le gestionnaire ODBC, par exemple my, pour la base de données que vous avez créée ;

- lancez Word ;

- créez un nouveau document vide ;

- dans la barre d'outils Database, pressez le bouton Insert Database ;

- pressez le bouton Get Data ;

- sur la gauche de l'écran de Get Data, pressez le bouton Ms Query ;

- dans Ms Query, créez une nouvelle source de données, en utilisant le fichier my ;

- sélectionnez une requête ;

- sélectionnez les colonnes que vous désirez ;

- ajoutez un filtre si vous voulez ;

- ajoutez un tri si vous voulez ;

- sélectionnez Return Data to Microsoft Word ;

- cliquez sur le bouton Finish ;

- cliquez sur le bouton Insert Data et sélectionnez les lignes ;

- cliquez sur le bouton OK et vous pouvez voir les lignes dans votre document Word.

25-A-13-b - L'export des tables depuis MS DTS vers MySQL avec MyODBC conduit à une erreur de syntaxe

Ce problème est similaire à celui de Access 97 lorsque votre table est constituée de données de type TEXT ou VARCHAR. Vous pouvez corriger ce problème en mettant à jour votre pilote MyODBC en version 3.51.02 ou plus récent.

25-A-13-c - HOWTO : configuration de MySQL, MyODBC, unixODBC et ColdFusion sur Solaris

Reportez-vous à MySQL ColdFusion unixODBC MyODBC and Solaris - how to succeed.

25-A-14 - Fonctionnalités générales de MyODBC

Cette section répond aux questions reliées à MyODBC.

25-A-14-a - Comment obtenir la valeur d'une colonne AUTO_INCREMENT avec ODBC ?

Un problème récurrent est d'obtenir la dernière valeur générée automatiquement par une commande INSERT. Avec ODBC, vous pouvez procéder de cette façon (en supposons que auto est un champ AUTO_INCREMENT) :

INSERT INTO foo (auto,text) VALUES(NULL,'text');
SELECT LAST_INSERT_ID();

Ou, si vous voulez juste insérer cette valeur dans une autre table :

INSERT INTO foo (auto,text) VALUES(NULL,'text');
INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');

Voir Section 24.2.13.3, « Comment lire l'identifiant unique de la dernière ligne insérée ».

Pour quelques applications utilisant ODBC (du moins Delphi et Access), la requête suivante peut être utilisée pour trouver une ligne insérée dernièrement :

SELECT * FROM nom_de_table WHERE auto IS NULL;

25-A-14-b - Est-ce que MyODBC accepte les curseurs dynamiques ?

Oui. MyODBC 3.51 supporte les curseurs dynamiques avec les modes Forward-only et static.

À cause des problèmes de performances, le pilote ne supporte pas cette fonctionnalité par défaut. Vous pouvez l'activer en spécifiant l'option de connexion OPTION=32 ou en cliquant dans l'option Enable Dynamic Cursor dans le panneau de configuration DSN.

25-A-14-c - Quelle est la cause de l'erreur Transactions are not enabled ?

Le pilote retourne cette erreur lorsque l'application émet un appel transactionnel, mais que le serveur MySQL sous-jacent ne supporte pas les transactions.

Pour éviter ce problème, vous devez utiliser un serveur qui dispose des moteurs InnoDB ou BDB et utilise les tables de ce type. Les serveurs MySQL depuis la version 4.0 supportent InnoDB par défaut. Les serveurs MySQL-Max supportent aussi BDB sur les plateformes où BDB est disponible.

De plus, si votre serveur supporte les tables transactionnelles InnoDB ou BDB, assurez-vous que l'option disable transactions n'est pas active dans la configuration du DSN.

25-A-14-d - Quelle est la cause de l'erreur Cursor not found ?

C'est à cause d'applications qui utilisent d'anciennes versions MyODBC 2.50, et qui ne donnent pas de nom explicite aux curseurs, via SQLSetCursorName. La solution est de passer à version MyODBC 3.51.

25-A-14-e - Puis-je utiliser des applications MyODBC 2.50 avec MyODBC 3.51 ?

Oui. Si vous trouvez une erreur avec MyODBC 3.51 qui n'apparaît pas avec MyODBC 2.50, envoyez un message mail à <myodbc@lists.mysql.com>.

25-A-14-f - Puis-je accéder à MySQL depuis .NET avec MyODBC ?

Oui. Vous pouvez utiliser odbc.net pour vous connecter à MySQL via MyODBC. Voici quelques exemples simples pour vous connecter à MySQL depuis VC.NET et VB.NET.

- Voyez Section 25.1.20.1, « ODBC.NET : CSHARP(C#) ».

- Voyez Section 25.1.20.2, « ODBC.NET: VB ».

Voici un autre excellent article : « Exploring MySQL on .NET environment » by Venu (MyODBC developer) qui couvre toutes les interfaces MySQL .NET.

Attention : en utilisant ODBC.NET avec MyODBC, lorsque vous lisez des lignes vides (taille nulle), vous obtiendrez une exception SQL_NO_DATA. Vous pouvez obtenir un patch pour cela sur http://support.microsoft.com/default.aspx?scid=kb;EN-US;q319243.

25-A-14-g - Pourquoi est-ce que MyODBC s'exécute lentement et fait beaucoup d'accès disques pour de petites requêtes ?

MyODBC est bien plus rapide que n'importe quel autre pilote ODBC. Des lenteurs peuvent être causées par la mauvaise utilisation des options suivantes.

- L'option ODBC Tracing est active. Vous pouvez vérifier si cette option est active en suivant les instructions suivantes : here.

Comme vous pouvez le voir dans l'image ci-dessus, l'option « When to trace » du gestionnaire de sources de données ODBC, onglet 'Tracing', doit toujours pointer sur « Start Tracing Now », au lieu de « Stop Tracing Now ».

- La version Debug version du pilote est utilisée. Si vous utilisez la version de débogage de la bibliothèque DLL, vous serez ralenti par les traitements supplémentaires. Vous pouvez vérifier que vous utilisez la version de débogage ou non en lisant la section commentaire « Comments » des propriétés de la bibliothèque DLL (dans le dossier système, faites un clic droit sur le pilote DLL et choisissez les propriétés), tel que présenté ci-dessous :

- L'option Driver trace and query logs est activée. Même si vous envisagez d'utiliser la version de débogage du pilote (il est recommandé de toujours utiliser la version de production), assurez-vous que les traces du pilote et que les logs de requêtes (options OPTION=4,524288 respectivement) ne sont pas activés :

25-A-15 - Instructions de base pour utiliser MyODBC

Travailler avec un serveur MySQL depuis une application MyODBC se fait en plusieurs étapes :

- configuration du DSN MyODBC ;

- connexion au serveur MySQL ;

- initialisation des opérations ;

- exécution des requêtes SQL ;

- lecture des résultats ;

- calcul des transactions ;

- déconnexion.

La plupart des applications utilisent certaines variations de ces étapes. Les étapes de bases sont présentées dans ce diagramme :

25-A-16 - Table de référence MyODBC

Cette section rassemble toutes les routines ODBC, classées par catégories.

Pour la référence complète, voyez celle du programmeur ODBC sur http://msdn.microsoft.com/library/en-us/odbc/htm/odbcabout_this_manual.asp.

Une application peut appeler la fonction SQLGetInfo pour obtenir les informations de conformité MyODBC. Pour savoir si une fonction spécifique est supportée, vous pouvez appeler SQLGetFunctions.

Note : pour assurer la compatibilité ascendante, le pilote MyODBC 3.51 supporte toutes les fonctions obsolètes.

Les tables suivantes listent toutes les fonctions MyODBC, rassemblées par tâche :

Connexion à une source de données :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLAllocHandle

Non

Oui

ISO 92

Obtenir un pointeur d'environnement, de connexion, de commande ou de curseur.

SQLConnect

Oui

Oui

ISO 92

Se connecter à une source de données spécifique, avec un pilote donné, avec le nom de source, le mot de passe et le nom d'utilisateur.

SQLDriverConnect

Oui

Oui

ODBC

Se connecter à une source de données avec un pilote spécifique et une chaîne de connexion ou une requête du gestionnaire de pilote pour afficher un dialogue.

SQLAllocEnv

Oui

Oui

Obsolète

Obtenir un pointeur d'environnement pour un pilote.

SQLAllocConnect

Oui

Oui

Obsolète

Obtenir un pointeur de connexion.

Obtenir des informations sur les pilotes et les sources de données :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLDataSources

Non

Non

ISO 92

Retourne la liste des sources de données disponibles, gérées par le gestionnaire de pilotes.

SQLDrivers

Non

Non

ODBC

Retourne la liste des pilotes installés, leurs attributs et les pointeurs.

SQLGetInfo

Oui

Oui

ISO 92

Retourne les informations sur un pilote spécifique et ses sources de données.

SQLGetFunctions

Oui

Oui

ISO 92

Retourne les fonctions supportées par le pilote.

SQLGetTypeInfo

Oui

Oui

ISO 92

Retourne les informations sur les types de données supportés.

Configurer et lire des valeurs d'attributs :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLSetConnectAttr

Non

Oui

ISO 92

Configure un attribut de connexion.

SQLGetConnectAttr

Non

Oui

ISO 92

Retourne un attribut de connexion.

SQLSetConnectOption

Oui

Oui

Obsolète

Configure une option de connexion.

SQLGetConnectOption

Oui

Oui

Obsolète

Retourne une option de connexion.

SQLSetEnvAttr

Non

Oui

ISO 92

Configure un attribut d'environnement.

SQLGetEnvAttr

Non

Oui

ISO 92

Retourne un attribut d'environnement.

SQLSetStmtAttr

Non

Oui

ISO 92

Configure un attribut de commande.

SQLGetStmtAttr

Non

Oui

ISO 92

Retourne un attribut de commande.

SQLSetStmtOption

Oui

Oui

Obsolète

Configure une option de commande.

SQLGetStmtOption

Oui

Oui

Obsolète

Retourne une option de commande.

Préparation des commandes SQL :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLAllocStmt

Oui

Oui

Obsolète

Alloue un pointeur de connexion.

SQLPrepare

Oui

Oui

ISO 92

Prépare une commande SQL pour exécution ultérieure.

SQLBindParameter

Oui

Oui

ODBC

Assigne un paramètre de commande SQL.

SQLGetCursorName

Oui

Oui

ISO 92

Retourne le nom du curseur associé à une commande.

SQLSetCursorName

Oui

Oui

ISO 92

Spécifie un nom de curseur.

SQLSetScrollOptions

Oui

Oui

ODBC

Configure les options qui contrôlent un curseur.

Envoi de requête :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLExecute

Oui

Oui

ISO 92

Exécute une commande préparée.

SQLExecDirect

Oui

Oui

ISO 92

Exécute une commande.

SQLNativeSql

Oui

Oui

ODBC

Retourne le texte d'une commande, tel que traduit par le pilote.

SQLDescribeParam

Oui

Oui

ODBC

Retourne la description d'un paramètre spécifique d'une commande.

SQLNumParams

Oui

Oui

ISO 92

Retourne le nombre de paramètres dans une commande.

SQLParamData

Oui

Oui

ISO 92

Utilisé en conjonction avec SQLPutData pour fournir des données supplémentaires au moment de l'exécution : pratique pour les données de grande taille.

SQLPutData

Oui

Oui

ISO 92

Envoie une partie ou toute une valeur de paramètre : pratique pour les données de grande taille.

Lecture de résultats et d'informations sur les résultats :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLRowCount

Oui

Oui

ISO 92

Retourne le nombre de lignes affectées par une insertion, une modification ou un effacement.

SQLNumResultCols

Oui

Oui

ISO 92

Retourne le nombre de colonnes dans un résultat.

SQLDescribeCol

Oui

Oui

ISO 92

Décrit une colonne dans un résultat.

SQLColAttribute

Non

Oui

ISO 92

Décrit un attribut d'une colonne de résultat.

SQLColAttributes

Oui

Oui

Obsolète

Décrit les attributs d'une colonne dans un résultat.

SQLFetch

Oui

Oui

ISO 92

Retourne les lignes d'un résultat multiple.

SQLFetchScroll

Non

Oui

ISO 92

Retourne un résultat scrollable.

SQLExtendedFetch

Oui

Oui

Obsolète

Retourne un résultat scrollable

SQLSetPos

Oui

Oui

ODBC

Place un curseur dans un bloc lu, et laisse l'application rafraîchir les données dans le résultat, pour modifier ou effacer des lignes dans le résultat.

SQLBulkOperations

Non

Oui

ODBC

Effectue des insertions de masse et des opérations de masse, y compris les modifications, effacements et lectures par signet.

Lecture des erreurs et diagnostics :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLError

Oui

Oui

Obsolète

Retourne des informations supplémentaires sur une erreur ou un statut.

SQLGetDiagField

Oui

Oui

ISO 92

Retourne des informations supplémentaires sur un diagnostic (un seul champ de la structure de diagnostic).

SQLGetDiagRec

Oui

Oui

ISO 92

Retourne des informations supplémentaires sur un diagnostic (champ multiple de la structure de diagnostic).

Obtention des informations sur la source de données (catalogue de fonctions) :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLColumnPrivileges

Oui

Oui

ODBC

Retourne la liste des colonnes et les droits associés pour une ou plusieurs tables.

SQLColumns

Oui

Oui

X/Open

Retourne la liste des noms de colonnes pour les tables spécifiées.

SQLForeignKeys

Oui

Oui

ODBC

Retourne la liste des noms de colonnes dans une clé étrangère, s'il en existe pour les tables mentionnées.

SQLPrimaryKeys

Oui

Oui

ODBC

Retourne la liste des noms de colonnes de la clé primaire pour la table.

SQLSpecialColumns

Oui

Oui

X/Open

Retourne des informations sur le jeu de colonnes optimal qui identifie de manière unique une ligne, ou les colonnes qui sont automatiquement modifiées si une ligne est modifiée par une transaction.

SQLStatistics

Oui

Oui

ISO 92

Retourne des statistiques sur une table, et la liste des index associés.

SQLTablePrivileges

Oui

Oui

ODBC

Retourne la liste des tables et les droits associés de chaque table.

SQLTables

Oui

Oui

X/Open

Retourne la liste des noms de tables stockés dans une source de données spécifique.

Exécution des transactions :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLTransact

Oui

Oui

Obsolète

Archive ou annule une transaction.

SQLEndTran

Non

Oui

ISO 92

Archive ou annule une transaction.

Terminaison d'une commande :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLFreeStmt

Oui

Oui

ISO 92

Termine le traitement d'une commande, détruit les résultats et libère toutes les ressources.

SQLCloseCursor

Oui

Oui

ISO 92

Détruit un curseur ouvert par une commande.

SQLCancel

Oui

Oui

ISO 92

Annule une commande SQL.

Fin d'une connexion :

Nom de la fonction

MyODBC

MyODBC

Conformité

Utilisation

2.50

3.51

SQLDisconnect

Oui

Oui

ISO 92

Ferme la connexion.

SQLFreeHandle

Non

Oui

ISO 92

Libère les ressources occupées par un environnement, une connexion, une commande ou un descripteur.

SQLFreeConnect

Oui

Oui

Obsolète

Libère les ressources d'une commande.

SQLFreeEnv

Oui

Oui

Obsolète

Libère les ressources d'un environnement.

25-A-17 - Les types de données MyODBC

Le tableau suivant illustre comment le pilote mappe les types de données du serveur aux types de données SQL et C par défaut :

Native Value

SQL Type

C Type

bit

SQL_BIT

SQL_C_BIT

tinyint

SQL_TINYINT

SQL_C_STINYINT

tinyint unsigned

SQL_TINYINT

SQL_C_UTINYINT

bigint

SQL_BIGINT

SQL_C_SBIGINT

bigint unsigned

SQL_BIGINT

SQL_C_UBIGINT

long varbinary

SQL_LONGVARBINARY

SQL_C_BINARY

blob

SQL_VARBINARY

SQL_C_BINARY

longblob

SQL_VARBINARY

SQL_C_BINARY

tinyblob

SQL_BINARY

SQL_C_BINARY

mediumblob

SQL_LONGVARBINARY

SQL_C_BINARY

long varchar

SQL_LONGVARCHAR

SQL_C_CHAR

text

SQL_LONGVARCHAR

SQL_C_CHAR

mediumtext

SQL_LONGVARCHAR

SQL_C_CHAR

char

SQL_CHAR

SQL_C_CHAR

numeric

SQL_NUMERIC

SQL_C_CHAR

decimal

SQL_DECIMAL

SQL_C_CHAR

integer

SQL_INTEGER

SQL_C_SLONG

integer unsigned

SQL_INTEGER

SQL_C_ULONG

int

SQL_INTEGER

SQL_C_SLONG

int unsigned

SQL_INTEGER

SQL_C_ULONG

mediumint

SQL_INTEGER

SQL_C_SLONG

mediumint unsigned

SQL_INTEGER

SQL_C_ULONG

smallint

SQL_SMALLINT

SQL_C_SSHORT

smallint unsigned

SQL_SMALLINT

SQL_C_USHORT

real

SQL_FLOAT

SQL_C_DOUBLE

double

SQL_FLOAT

SQL_C_DOUBLE

float

SQL_REAL

SQL_C_FLOAT

double precision

SQL_DOUBLE

SQL_C_DOUBLE

date

SQL_DATE

SQL_C_DATE

time

SQL_TIME

SQL_C_TIME

year

SQL_SMALLINT

SQL_C_SHORT

datetime

SQL_TIMESTAMP

SQL_C_TIMESTAMP

timestamp

SQL_TIMESTAMP

SQL_C_TIMESTAMP

text

SQL_VARCHAR

SQL_C_CHAR

varchar

SQL_VARCHAR

SQL_C_CHAR

enum

SQL_VARCHAR

SQL_C_CHAR

set

SQL_VARCHAR

SQL_C_CHAR

bit

SQL_CHAR

SQL_C_CHAR

bool

SQL_CHAR

SQL_C_CHAR

25-A-18 - Codes d'erreurs MyODBC

La table suivante liste les codes d'erreurs retournés par le pilote, en plus des erreurs fournies par le serveur.

Code natif

SQLSTATE 2

SQLSTATE 3

Message d'erreur

500

01000

01000

General warning

501

01004

01004

String data, right truncated

502

01S02

01S02

Option value changed

503

01S03

01S03

No rows updated/deleted

504

01S04

01S04

More than one row updated/deleted

505

01S06

01S06

Attempt to fetch before the result set returned the first row set

506

07001

07002

SQLBindParameter not used for all parameters

507

07005

07005

Prepared statement not a cursor-specification

508

07009

07009

Invalid descriptor index

509

08002

08002

Connection name in use

510

08003

08003

Connection does not exist

511

24000

24000

Invalid cursor state

512

25000

25000

Invalid transaction state

513

25S01

25S01

Transaction state unknown

514

34000

34000

Invalid cursor name

515

S1000

HY000

General driver defined error

516

S1001

HY001

Memory allocation error

517

S1002

HY002

Invalid column number

518

S1003

HY003

Invalid application buffer type

519

S1004

HY004

Invalid SQL data type

520

S1009

HY009

Invalid use of null pointer

521

S1010

HY010

Function sequence error

522

S1011

HY011

Attribute can not be set now

523

S1012

HY012

Invalid transaction operation code

524

S1013

HY013

Memory management error

525

S1015

HY015

No cursor name available

526

S1024

HY024

Invalid attribute value

527

S1090

HY090

Invalid string or buffer length

528

S1091

HY091

Invalid descriptor field identifier

529

S1092

HY092

Invalid attribute/option identifier

530

S1093

HY093

Invalid parameter number

531

S1095

HY095

Function type out of range

532

S1106

HY106

Fetch type out of range

533

S1117

HY117

Row value out of range

534

S1109

HY109

Invalid cursor position

535

S1C00

HYC00

Optional feature not implemented

0

21S01

21S01

Column count does not match value count

0

23000

23000

Integrity constraint violation

0

42000

42000

Syntax error or access violation

0

42S02

42S02

Base table or view not found

0

42S12

42S12

Index not found

0

42S21

42S21

Column already exists

0

42S22

42S22

Column not found

0

08S01

08S01

Communication link failure

25-A-19 - MyODBC avec VB : ADO, DAO et RDO

Cette section contient des exemples simples qui illustrent l'utilisation de MySQL ODBC 3.51 avec ADO, DAO et RDO.

25-A-19-a - ADO: rs.addNew, rs.delete et rs.update

L'exemple ADO (ActiveX Data Objects) suivant crée une table my_ado et montre comment utiliser rs.addNew, rs.delete, et rs.update.

Private Sub myodbc_ado_Click()

Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim fld As ADODB.Field
Dim sql As String

'connect to MySQL server using MySQL ODBC 3.51 Driver
Set conn = New ADODB.Connection
conn.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"_
& "SERVER=localhost;"_
& " DATABASE=test;"_
& "UID=venu;PWD=venu; OPTION=3"

conn.Open

'create table
conn.Execute "DROP TABLE IF EXISTS my_ado"
conn.Execute "CREATE TABLE my_ado(id int not null primary key, name varchar(20)," _
& "txt text, dt date, tm time, ts timestamp)"

'direct insert
conn.Execute "INSERT INTO my_ado(id,name,txt) values(1,100,'venu')"
conn.Execute "INSERT INTO my_ado(id,name,txt) values(2,200,'MySQL')"
conn.Execute "INSERT INTO my_ado(id,name,txt) values(3,300,'Delete')"

Set rs = New ADODB.Recordset
rs.CursorLocation = adUseServer

'fetch the initial table ..
rs.Open "SELECT * FROM my_ado", conn
Debug.Print rs.RecordCount
rs.MoveFirst
Debug.Print String(50, "-") & "Initial my_ado Result Set " & String(50, "-")
For Each fld In rs.Fields
Debug.Print fld.Name,
Next
Debug.Print

Do Until rs.EOF
For Each fld In rs.Fields
Debug.Print fld.Value,
Next
rs.MoveNext
Debug.Print
Loop
rs.Close

'rs insert
rs.Open "select * from my_ado", conn, adOpenDynamic, adLockOptimistic
rs.AddNew
rs!Name = "Monty"
rs!txt = "Insert row"
rs.Update
rs.Close

'rs update
rs.Open "SELECT * FROM my_ado"
rs!Name = "update"
rs!txt = "updated-row"
rs.Update
rs.Close

'rs update second time..
rs.Open "SELECT * FROM my_ado"
rs!Name = "update"
rs!txt = "updated-second-time"
rs.Update
rs.Close

'rs delete
rs.Open "SELECT * FROM my_ado"
rs.MoveNext
rs.MoveNext
rs.Delete
rs.Close

'fetch the updated table ..
rs.Open "SELECT * FROM my_ado", conn
Debug.Print rs.RecordCount
rs.MoveFirst
Debug.Print String(50, "-") & "Updated my_ado Result Set " & String(50, "-")
For Each fld In rs.Fields
Debug.Print fld.Name,
Next
Debug.Print

Do Until rs.EOF
For Each fld In rs.Fields
Debug.Print fld.Value,
Next
rs.MoveNext
Debug.Print
Loop
rs.Close
conn.Close
End Sub

25-A-19-b - DAO : rs.addNew, rs.update et scrolls

L'exemple DAO (Data Access Objects) suivant crée la table my_dao et montre l'utilisation de rs.addNew, rs.update et le scroll dans les résultats.

Private Sub myodbc_dao_Click()

Dim ws As Workspace
Dim conn As Connection
Dim queryDef As queryDef
Dim str As String

'connect to MySQL using MySQL ODBC 3.51 Driver
Set ws = DBEngine.CreateWorkspace("", "venu", "venu", dbUseODBC)
str = "odbc;DRIVER={MySQL ODBC 3.51 Driver};"_
& "SERVER=localhost;"_
& " DATABASE=test;"_
& "UID=venu;PWD=venu; OPTION=3"
Set conn = ws.OpenConnection("test", dbDriverNoPrompt, False, str)

'Create table my_dao
Set queryDef = conn.CreateQueryDef("", "drop table if exists my_dao")
queryDef.Execute

Set queryDef = conn.CreateQueryDef("", "create table my_dao(Id INT AUTO_INCREMENT PRIMARY KEY, " _
& "Ts TIMESTAMP(14) NOT NULL, Name varchar(20), Id2 INT)")
queryDef.Execute

'Insert new records using rs.addNew
Set rs = conn.OpenRecordset("my_dao")
Dim i As Integer

For i = 10 To 15
rs.AddNew
rs!Name = "insert record" & i
rs!Id2 = i
rs.Update
Next i
rs.Close

'rs update..
Set rs = conn.OpenRecordset("my_dao")
rs.Edit
rs!Name = "updated-string"
rs.Update
rs.Close

'fetch the table back...
Set rs = conn.OpenRecordset("my_dao", dbOpenDynamic)
str = "Results:"
rs.MoveFirst
While Not rs.EOF
str = " " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print "DATA:" & str
rs.MoveNext
Wend

'rs Scrolling
rs.MoveFirst
str = " FIRST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str

rs.MoveLast
str = " LAST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str

rs.MovePrevious
str = " LAST-1 ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str

'free all resources
rs.Close
queryDef.Close
conn.Close
ws.Close

End Sub

25-A-19-c - RDO : rs.addNew et rs.update

L'exemple RDO (Remote Data Objects) crée une table my_rdo et illustre l'utilisation de rs.addNew et rs.update.

Dim rs As rdoResultset
Dim cn As New rdoConnection
Dim cl As rdoColumn
Dim SQL As String

'cn.Connect = "DSN=test;"
cn.Connect = "DRIVER={MySQL ODBC 3.51 Driver};"_
& "SERVER=localhost;"_
& " DATABASE=test;"_
& "UID=venu;PWD=venu; OPTION=3"

cn.CursorDriver = rdUseOdbc
cn.EstablishConnection rdDriverPrompt

'drop table my_rdo
SQL = "drop table if exists my_rdo"
cn.Execute SQL, rdExecDirect

'create table my_rdo
SQL = "create table my_rdo(id int, name varchar(20))"
cn.Execute SQL, rdExecDirect

'insert - direct
SQL = "insert into my_rdo values (100,'venu')"
cn.Execute SQL, rdExecDirect

SQL = "insert into my_rdo values (200,'MySQL')"
cn.Execute SQL, rdExecDirect

'rs insert
SQL = "select * from my_rdo"
Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
rs.AddNew
rs!id = 300
rs!Name = "Insert1"
rs.Update
rs.Close

'rs insert
SQL = "select * from my_rdo"
Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
rs.AddNew
rs!id = 400
rs!Name = "Insert 2"
rs.Update
rs.Close

'rs update
SQL = "select * from my_rdo"
Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
rs.Edit
rs!id = 999
rs!Name = "updated"
rs.Update
rs.Close

'fetch back...
SQL = "select * from my_rdo"
Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
Do Until rs.EOF
For Each cl In rs.rdoColumns
Debug.Print cl.Value,
Next
rs.MoveNext
Debug.Print
Loop
Debug.Print "Row count="; rs.RowCount

'close
rs.Close
cn.Close

End Sub

25-A-20 - MyODBC avec Microsoft .NET

Cette section contient des exemples simples qui illustrent l'utilisation de MyODBC avec ODBC.NET.

25-A-20-a - ODBC.NET : CSHARP(C#)

L'exemple suivant crée une table my_odbc_net et illustre l'utilisation de C#.

/**
* @sample    : mycon.cs
* @purpose   : Demo sample for ODBC.NET using MyODBC
* @author    : Venu, <venu@mysql.com>
*
* (C) Copyright MySQL AB, 1995-2004
*
**/

/* build command
*
*  csc /t:exe
*      /out:mycon.exe mycon.cs
*      /r:Microsoft.Data.Odbc.dll
*/

using Console = System.Console;
using Microsoft.Data.Odbc;

namespace myodbc3
{
class mycon
{
static void Main(string[] args)
{
try
{
//Connection string for MyODBC 2.50
/*string MyConString = "DRIVER={MySQL};" +
"SERVER=localhost;" +
"DATABASE=test;" +
"UID=venu;" +
"PASSWORD=venu;" +
"OPTION=3";
*/
//Connection string for MyODBC 3.51
string MyConString = "DRIVER={MySQL ODBC 3.51 Driver};" +
"SERVER=localhost;" +
"DATABASE=test;" +
"UID=venu;" +
"PASSWORD=venu;" +
"OPTION=3";

//Connect to MySQL using MyODBC
OdbcConnection MyConnection = new OdbcConnection(MyConString);
MyConnection.Open();

Console.WriteLine("\n !!! success, connected successfully !!!\n");

//Display connection information
Console.WriteLine("Connection Information:");
Console.WriteLine("\tConnection String:" + MyConnection.ConnectionString);
Console.WriteLine("\tConnection Timeout:" + MyConnection.ConnectionTimeout);
Console.WriteLine("\tDatabase:" + MyConnection.Database);
Console.WriteLine("\tDataSource:" + MyConnection.DataSource);
Console.WriteLine("\tDriver:" + MyConnection.Driver);
Console.WriteLine("\tServerVersion:" + MyConnection.ServerVersion);

//Create a sample table
OdbcCommand MyCommand = new OdbcCommand("DROP TABLE IF EXISTS my_odbc_net",MyConnection);
MyCommand.ExecuteNonQuery();
MyCommand.CommandText = "CREATE TABLE my_odbc_net(id int, name varchar(20), idb bigint)";
MyCommand.ExecuteNonQuery();

//Insert
MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(10,'venu', 300)";
Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());;

//Insert
MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',400)";
Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());

//Insert
MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',500)";
Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());

//Update
MyCommand.CommandText = "UPDATE my_odbc_net SET id=999 WHERE id=20";
Console.WriteLine("Update, Total rows affected:" + MyCommand.ExecuteNonQuery());

//COUNT(*)
MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_odbc_net";
Console.WriteLine("Total Rows:" + MyCommand.ExecuteScalar());

//Fetch
MyCommand.CommandText = "SELECT * FROM my_odbc_net";
OdbcDataReader MyDataReader;
MyDataReader =  MyCommand.ExecuteReader();
while (MyDataReader.Read())
{
if(string.Compare(MyConnection.Driver,"myodbc3.dll") == 0) {
Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
MyDataReader.GetString(1) + " " +
MyDataReader.GetInt64(2)); //Supported only by MyODBC 3.51
}
else {
Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
MyDataReader.GetString(1) + " " +
MyDataReader.GetInt32(2)); //BIGINTs not supported by MyODBC
}
}

//Close all resources
MyDataReader.Close();
MyConnection.Close();
}
catch (OdbcException MyOdbcException)//Catch any ODBC exception ..
{
for (int i=0; i < MyOdbcException.Errors.Count; i++)
{
Console.Write("ERROR #" + i + "\n" +
"Message: " + MyOdbcException.Errors[i].Message + "\n" +
"Native: " + MyOdbcException.Errors[i].NativeError.ToString() + "\n" +
"Source: " + MyOdbcException.Errors[i].Source + "\n" +
"SQL: " + MyOdbcException.Errors[i].SQLState + "\n");
}
}
}
}
}

25-A-20-b - ODBC.NET: VB

L'exemple suivant crée une table my_vb_net et illustre l'utilisation de VB.

' @sample    : myvb.vb
' @purpose   : Demo sample for ODBC.NET using MyODBC
' @author    : Venu, <venu@mysql.com>
'
' (C) Copyright MySQL AB, 1995-2004
'
'

'
' build command
'
' vbc /target:exe
'     /out:myvb.exe
'     /r:Microsoft.Data.Odbc.dll
'     /r:System.dll
'     /r:System.Data.dll
'

Imports Microsoft.Data.Odbc
Imports System

Module myvb
Sub Main()
Try

'MyODBC 3.51 connection string
Dim MyConString As String = "DRIVER={MySQL ODBC 3.51 Driver};" & _
"SERVER=localhost;" & _
"DATABASE=test;" & _
"UID=venu;" & _
"PASSWORD=venu;" & _
"OPTION=3;"

'Connection
Dim MyConnection As New OdbcConnection(MyConString)
MyConnection.Open()

Console.WriteLine ("Connection State::" & MyConnection.State.ToString)

'Drop
Console.WriteLine ("Dropping table")
Dim MyCommand As New OdbcCommand()
MyCommand.Connection = MyConnection
MyCommand.CommandText = "DROP TABLE IF EXISTS my_vb_net"
MyCommand.ExecuteNonQuery()

'Create
Console.WriteLine ("Creating....")
MyCommand.CommandText = "CREATE TABLE my_vb_net(id int, name varchar(30))"
MyCommand.ExecuteNonQuery()

'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(10,'venu')"
Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net(id) VALUES(30)"
Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

'Update
MyCommand.CommandText = "UPDATE my_vb_net SET id=999 WHERE id=20"
Console.WriteLine("Update, Total rows affected:" & MyCommand.ExecuteNonQuery())

'COUNT(*)
MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_vb_net"
Console.WriteLine("Total Rows:" & MyCommand.ExecuteScalar())

'Select
Console.WriteLine ("Select * FROM my_vb_net")
MyCommand.CommandText = "SELECT * FROM my_vb_net"
Dim MyDataReader As OdbcDataReader
MyDataReader = MyCommand.ExecuteReader
While MyDataReader.Read
If MyDataReader("name") Is DBNull.Value Then
Console.WriteLine ("id = " & CStr(MyDataReader("id")) & "  name = " & _
"NULL")
Else
Console.WriteLine ("id = " & CStr(MyDataReader("id")) & "  name = " & _
CStr(MyDataReader("name")))
End If
End While

'Catch ODBC Exception
Catch MyOdbcException As OdbcException
Dim i As Integer
Console.WriteLine (MyOdbcException.ToString)

'Catch program exception
Catch MyException As Exception
Console.WriteLine (MyException.ToString)
End Try
End Sub
End Module

25-A-21 - Crédits

Voici la liste des développeurs qui ont travaillé sur les pilotes MyODBC et MyODBC 3.51 de MySQL AB.

- Micheal (Monty) Widenius.

- Venu Anuganti.

- Peter Harvey.

25-B - MySQL et Java (JDBC)

Il y a deux pilotes JDBC supportés pour MySQL :

- MySQL Connector/J de MySQL AB, implémenté 100 % Java natif. Ce produit était connu sous le nom de pilote mm.mysql. Vous pouvez télécharger MySQL Connector/J depuis l'URL http://www.mysql.com/products/connector-j/ ;

- le pilote Resin JDBC, qui est disponible sur l'URL http://www.caucho.com/projects/jdbc-mysql/index.xtp.

Pour de la documentation, consultez celle de JDBC et des pilotes pour les fonctionnalités relatives à MySQL.

La documentation de MySQL Connector/J est disponible en ligne, sur le site de MySQL AB à http://dev.mysql.com/doc/.

26 - Gestion des erreurs avec MySQL

Ce chapitre décrit comment MySQL gère les erreurs.

Voici la liste des erreurs que vous pouvez rencontrer lorsque vous utilisez MySQL sur un serveur ayant le support de la langue locale.

Les colonnes Name et Error Code correspondent aux définitions placées dans le code source MySQL : include/mysqld_error.h

La colonne SQLSTATE correspond aux définitions du code source MySQL : include/sql_state.h

Le code d'erreur SQLSTATE n'apparaîtra que si vous utilisez MySQL version 4.1. Les codes d'erreurs SQLSTATE ont été ajoutés pour assurer la compatibilité avec X/Open / ANSI / ODBC.

Un message d'erreur est disponible dans le fichier de messages d'erreurs : share/english/errmsg.sys

Comme les mises à jour sont fréquentes, il est possible que les sources ci-dessus contiennent d'autres codes d'erreur.

- Error: 1000 SQLSTATE: HY000 (ER_HASHCHK)
Message : hashchk.

- Error: 1001 SQLSTATE: HY000 (ER_NISAMCHK)
Message : isamchk.

- Error: 1002 SQLSTATE: HY000 (ER_NO)
Message : NON.

- Error: 1003 SQLSTATE: HY000 (ER_YES)
Message : OUI.

- Error: 1004 SQLSTATE: HY000 (ER_CANT_CREATE_FILE)
Message : Ne peut créer le fichier '%s' (Errcode: %d).

- Error: 1005 SQLSTATE: HY000 (ER_CANT_CREATE_TABLE)
Message : Ne peut créer la table '%s' (Errcode: %d).

- Error: 1006 SQLSTATE: HY000 (ER_CANT_CREATE_DB)
Message : Ne peut créer la base '%s' (Erreur %d)..

- Error: 1007 SQLSTATE: HY000 (ER_DB_CREATE_EXISTS)
Message : Ne peut créer la base '%s'; elle existe déjà.

- Error: 1008 SQLSTATE: HY000 (ER_DB_DROP_EXISTS)
Message : Ne peut effacer la base '%s'; elle n'existe pas.

- Error: 1009 SQLSTATE: HY000 (ER_DB_DROP_DELETE)
Message : Ne peut effacer la base '%s' (erreur %d).

- Error: 1010 SQLSTATE: HY000 (ER_DB_DROP_RMDIR)
Message : Erreur en effaçant la base (rmdir '%s', erreur %d).

- Error: 1011 SQLSTATE: HY000 (ER_CANT_DELETE_FILE)
Message : Erreur en effaçant '%s' (Errcode: %d).

- Error: 1012 SQLSTATE: HY000 (ER_CANT_FIND_SYSTEM_REC)
Message : Ne peut lire un enregistrement de la table 'system'.

- Error: 1013 SQLSTATE: HY000 (ER_CANT_GET_STAT)
Message : Ne peut obtenir le status de '%s' (Errcode: %d).

- Error: 1014 SQLSTATE: HY000 (ER_CANT_GET_WD)
Message : Ne peut obtenir le répertoire de travail (Errcode: %d).

- Error: 1015 SQLSTATE: HY000 (ER_CANT_LOCK)
Message : Ne peut verrouiller le fichier (Errcode: %d).

- Error: 1016 SQLSTATE: HY000 (ER_CANT_OPEN_FILE)
Message : Ne peut ouvrir le fichier: '%s' (Errcode: %d).

- Error: 1017 SQLSTATE: HY000 (ER_FILE_NOT_FOUND)
Message : Ne peut trouver le fichier: '%s' (Errcode: %d).

- Error: 1018 SQLSTATE: HY000 (ER_CANT_READ_DIR)
Message : Ne peut lire le répertoire de '%s' (Errcode: %d).

- Error: 1019 SQLSTATE: HY000 (ER_CANT_SET_WD)
Message : Ne peut changer le répertoire pour '%s' (Errcode: %d).

- Error: 1020 SQLSTATE: HY000 (ER_CHECKREAD)
Message : Enregistrement modifié depuis sa dernière lecture dans la table '%s'.

- Error: 1021 SQLSTATE: HY000 (ER_DISK_FULL)
Message : Disque plein (%s). J'attends que quelqu'un libère de l'espace...

- Error: 1022 SQLSTATE: 23000 (ER_DUP_KEY)
Message : Écriture impossible, doublon dans une clé de la table '%s'.

- Error: 1023 SQLSTATE: HY000 (ER_ERROR_ON_CLOSE)
Message : Erreur à la fermeture de '%s' (Errcode: %d).

- Error: 1024 SQLSTATE: HY000 (ER_ERROR_ON_READ)
Message : Erreur en lecture du fichier '%s' (Errcode: %d).

- Error: 1025 SQLSTATE: HY000 (ER_ERROR_ON_RENAME)
Message : Erreur en renommant '%s' en '%s' (Errcode: %d).

- Error: 1026 SQLSTATE: HY000 (ER_ERROR_ON_WRITE)
Message : Erreur d'écriture du fichier '%s' (Errcode: %d).

- Error: 1027 SQLSTATE: HY000 (ER_FILE_USED)
Message : '%s' est verrouillé contre les modifications.

- Error: 1028 SQLSTATE: HY000 (ER_FILSORT_ABORT)
Message : Tri alphabétique abandonné.

- Error: 1029 SQLSTATE: HY000 (ER_FORM_NOT_FOUND)
Message : La vue (View) '%s' n'existe pas pour '%s'.

- Error: 1030 SQLSTATE: HY000 (ER_GET_ERRNO)
Message : Reçu l'erreur %d du handler de la table.

- Error: 1031 SQLSTATE: HY000 (ER_ILLEGAL_HA)
Message : Le handler de la table '%s' n'a pas cette option.

- Error: 1032 SQLSTATE: HY000 (ER_KEY_NOT_FOUND)
Message : Ne peut trouver l'enregistrement dans '%s'.

- Error: 1033 SQLSTATE: HY000 (ER_NOT_FORM_FILE)
Message : Information erronée dans le fichier: '%s'.

- Error: 1034 SQLSTATE: HY000 (ER_NOT_KEYFILE)
Message : Index corrompu dans la table: '%s'; essayez de le réparer.

- Error: 1035 SQLSTATE: HY000 (ER_OLD_KEYFILE)
Message : Vieux fichier d'index pour la table '%s'; réparez-le !

- Error: 1036 SQLSTATE: HY000 (ER_OPEN_AS_READONLY)
Message : '%s' est en lecture seulement.

- Error: 1037 SQLSTATE: HY001 (ER_OUTOFMEMORY)
Message : Manque de mémoire. Redémarrez le démon et réessayez (%d octets nécessaires).

- Error: 1038 SQLSTATE: HY001 (ER_OUT_OF_SORTMEMORY)
Message : Manque de mémoire pour le tri. Augmentez-la.

- Error: 1039 SQLSTATE: HY000 (ER_UNEXPECTED_EOF)
Message : Fin de fichier inattendue en lisant '%s' (Errcode: %d).

- Error: 1040 SQLSTATE: 08004 (ER_CON_COUNT_ERROR)
Message : Trop de connexions.

- Error: 1041 SQLSTATE: HY000 (ER_OUT_OF_RESOURCES)
Message : Manque de 'threads'/mémoire.

- Error: 1042 SQLSTATE: 08S01 (ER_BAD_HOST_ERROR)
Message : Ne peut obtenir de hostname pour votre adresse.

- Error: 1043 SQLSTATE: 08S01 (ER_HANDSHAKE_ERROR)
Message : Mauvais 'handshake'.

- Error: 1044 SQLSTATE: 42000 (ER_DBACCESS_DENIED_ERROR)
Message : Accès refusé pour l'utilisateur: '%s'@'@%s'. Base '%s'.

- Error: 1045 SQLSTATE: 28000 (ER_ACCESS_DENIED_ERROR)
Message : Accès refusé pour l'utilisateur: '%s'@'@%s' (mot de passe: %s).

- Error: 1046 SQLSTATE: 3D000 (ER_NO_DB_ERROR)
Message : Aucune base n'a été sélectionnée.

- Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
Message : Commande inconnue.

- Error: 1048 SQLSTATE: 23000 (ER_BAD_NULL_ERROR)
Message : Le champ '%s' ne peut être vide (null).

- Error: 1049 SQLSTATE: 42000 (ER_BAD_DB_ERROR)
Message : Base '%s' inconnue.

- Error: 1050 SQLSTATE: 42S01 (ER_TABLE_EXISTS_ERROR)
Message : La table '%s' existe déjà.

- Error: 1051 SQLSTATE: 42S02 (ER_BAD_TABLE_ERROR)
Message : Table '%s' inconnue.

- Error: 1052 SQLSTATE: 23000 (ER_NON_UNIQ_ERROR)
Message : Champ: '%s' dans %s est ambigu.

- Error: 1053 SQLSTATE: 08S01 (ER_SERVER_SHUTDOWN)
Message : Arrêt du serveur en cours.

- Error: 1054 SQLSTATE: 42S22 (ER_BAD_FIELD_ERROR)
Message : Champ '%s' inconnu dans %s.

- Error: 1055 SQLSTATE: 42000 (ER_WRONG_FIELD_WITH_GROUP)
Message : '%s' n'est pas dans 'group by'.

- Error: 1056 SQLSTATE: 42000 (ER_WRONG_GROUP_FIELD)
Message : Ne peut regrouper '%s'.

- Error: 1057 SQLSTATE: 42000 (ER_WRONG_SUM_SELECT)
Message : Vous demandez la fonction sum() et des champs dans la même commande.

- Error: 1058 SQLSTATE: 21S01 (ER_WRONG_VALUE_COUNT)
Message : Column count doesn't match value count.

- Error: 1059 SQLSTATE: 42000 (ER_TOO_LONG_IDENT)
Message : Le nom de l'identificateur '%s' est trop long.

- Error: 1060 SQLSTATE: 42S21 (ER_DUP_FIELDNAME)
Message : Nom du champ '%s' déjà utilisé.

- Error: 1061 SQLSTATE: 42000 (ER_DUP_KEYNAME)
Message : Nom de clef '%s' déjà utilisé.

- Error: 1062 SQLSTATE: 23000 (ER_DUP_ENTRY)
Message : Duplicata du champ '%s' pour la clef %d.

- Error: 1063 SQLSTATE: 42000 (ER_WRONG_FIELD_SPEC)
Message : Mauvais paramètre de champ pour le champ '%s'.

- Error: 1064 SQLSTATE: 42000 (ER_PARSE_ERROR)
Message : %s près de '%s' à la ligne %d.

- Error: 1065 SQLSTATE: 42000 (ER_EMPTY_QUERY)
Message : Query est vide.

- Error: 1066 SQLSTATE: 42000 (ER_NONUNIQ_TABLE)
Message : Table/alias: '%s' non unique.

- Error: 1067 SQLSTATE: 42000 (ER_INVALID_DEFAULT)
Message : Valeur par défaut invalide pour '%s'.

- Error: 1068 SQLSTATE: 42000 (ER_MULTIPLE_PRI_KEY)
Message : Plusieurs clefs primaires définies.

- Error: 1069 SQLSTATE: 42000 (ER_TOO_MANY_KEYS)
Message : Trop de clefs sont définies. Maximum de %d clefs allouées.

- Error: 1070 SQLSTATE: 42000 (ER_TOO_MANY_KEY_PARTS)
Message : Trop de parties spécifiées dans la clef. Maximum de %d parties.

- Error: 1071 SQLSTATE: 42000 (ER_TOO_LONG_KEY)
Message : La clé est trop longue. Longueur maximale: %d.

- Error: 1072 SQLSTATE: 42000 (ER_KEY_COLUMN_DOES_NOT_EXITS)
Message : La clé '%s' n'existe pas dans la table.

- Error: 1073 SQLSTATE: 42000 (ER_BLOB_USED_AS_KEY)
Message : Champ BLOB '%s' ne peut être utilisé dans une clé.

- Error: 1074 SQLSTATE: 42000 (ER_TOO_BIG_FIELDLENGTH)
Message : Champ '%s' trop long (max = %d). Utilisez un BLOB.

- Error: 1075 SQLSTATE: 42000 (ER_WRONG_AUTO_KEY)
Message : Un seul champ automatique est permis et il doit être indexé.

- Error: 1076 SQLSTATE: HY000 (ER_READY)
Message : %s: Prêt pour des connexions.

- Error: 1077 SQLSTATE: HY000 (ER_NORMAL_SHUTDOWN)
Message : %s: Arrêt normal du serveur.

- Error: 1078 SQLSTATE: HY000 (ER_GOT_SIGNAL)
Message : %s: Reçu le signal %d. Abandonne !

- Error: 1079 SQLSTATE: HY000 (ER_SHUTDOWN_COMPLETE)
Message : %s: Arrêt du serveur terminé.

- Error: 1080 SQLSTATE: 08S01 (ER_FORCING_CLOSE)
Message : %s: Arrêt forcé de la tâche (thread) %ld utilisateur: '%s'.

- Error: 1081 SQLSTATE: 08S01 (ER_IPSOCK_ERROR)
Message : Ne peut créer la connexion IP (socket).

- Error: 1082 SQLSTATE: 42S12 (ER_NO_SUCH_INDEX)
Message : La table '%s' n'a pas d'index comme celle utilisée dans CREATE INDEX. Recréez la table.

- Error: 1083 SQLSTATE: 42000 (ER_WRONG_FIELD_TERMINATORS)
Message : Séparateur de champs inconnu. Vérifiez dans le manuel.

- Error: 1084 SQLSTATE: 42000 (ER_BLOBS_AND_NO_TERMINATED)
Message : Vous ne pouvez utiliser des lignes de longueur fixe avec des BLOBs. Utiliser 'fields terminated by'.

- Error: 1085 SQLSTATE: HY000 (ER_TEXTFILE_NOT_READABLE)
Message : Le fichier '%s' doit être dans le répertoire de la base et lisible par tous.

- Error: 1086 SQLSTATE: HY000 (ER_FILE_EXISTS_ERROR)
Message : Le fichier '%s' existe déjà.

- Error: 1087 SQLSTATE: HY000 (ER_LOAD_INFO)
Message : Enregistrements: %ld Effacés: %ld Non traités: %ld Avertissements: %ld.

- Error: 1088 SQLSTATE: HY000 (ER_ALTER_INFO)
Message : Enregistrements: %ld Doublons: %ld.

- Error: 1089 SQLSTATE: HY000 (ER_WRONG_SUB_KEY)
Message : Mauvaise sous-clef. Ce n'est pas un 'string' ou la longueur dépasse celle définie dans la clef.

- Error: 1090 SQLSTATE: 42000 (ER_CANT_REMOVE_ALL_FIELDS)
Message : Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE.

- Error: 1091 SQLSTATE: 42000 (ER_CANT_DROP_FIELD_OR_KEY)
Message : Ne peut effacer (DROP) '%s'. Vérifiez s'il existe.

- Error: 1092 SQLSTATE: HY000 (ER_INSERT_INFO)
Message : Enregistrements: %ld Doublons: %ld Avertissements: %ld.

- Error: 1093 SQLSTATE: HY000 (ER_UPDATE_TABLE_USED)
Message : You can't specify target table '%s' for update in FROM clause.

- Error: 1094 SQLSTATE: HY000 (ER_NO_SUCH_THREAD)
Message : Numéro de tâche inconnu: %lu.

- Error: 1095 SQLSTATE: HY000 (ER_KILL_DENIED_ERROR)
Message : Vous n'êtes pas propriétaire de la tâche no: %lu.

- Error: 1096 SQLSTATE: HY000 (ER_NO_TABLES_USED)
Message : Aucune table utilisée.

- Error: 1097 SQLSTATE: HY000 (ER_TOO_BIG_SET)
Message : Trop de chaînes dans la colonne %s avec SET.

- Error: 1098 SQLSTATE: HY000 (ER_NO_UNIQUE_LOGFILE)
Message : Ne peut générer un unique nom de journal %s.(1-999).

- Error: 1099 SQLSTATE: HY000 (ER_TABLE_NOT_LOCKED_FOR_WRITE)
Message : Table '%s' verrouillée lecture (READ): modification impossible.

- Error: 1100 SQLSTATE: HY000 (ER_TABLE_NOT_LOCKED)
Message : Table '%s' non verrouillée: utilisez LOCK TABLES.

- Error: 1101 SQLSTATE: 42000 (ER_BLOB_CANT_HAVE_DEFAULT)
Message : BLOB '%s' ne peut avoir de valeur par défaut.

- Error: 1102 SQLSTATE: 42000 (ER_WRONG_DB_NAME)
Message : Nom de base de données illégal: '%s'.

- Error: 1103 SQLSTATE: 42000 (ER_WRONG_TABLE_NAME)
Message : Nom de table illégal: '%s'.

- Error: 1104 SQLSTATE: 42000 (ER_TOO_BIG_SELECT)
Message : SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien.

- Error: 1105 SQLSTATE: HY000 (ER_UNKNOWN_ERROR)
Message : Erreur inconnue.

- Error: 1106 SQLSTATE: 42000 (ER_UNKNOWN_PROCEDURE)
Message : Procédure %s inconnue.

- Error: 1107 SQLSTATE: 42000 (ER_WRONG_PARAMCOUNT_TO_PROCEDURE)
Message : Mauvais nombre de paramètres pour la procédure %s.

- Error: 1108 SQLSTATE: HY000 (ER_WRONG_PARAMETERS_TO_PROCEDURE)
Message : Paramètre erroné pour la procédure %s.

- Error: 1109 SQLSTATE: 42S02 (ER_UNKNOWN_TABLE)
Message : Table inconnue '%s' dans %s.

- Error: 1110 SQLSTATE: 42000 (ER_FIELD_SPECIFIED_TWICE)
Message : Champ '%s' spécifié deux fois.

- Error: 1111 SQLSTATE: HY000 (ER_INVALID_GROUP_FUNC_USE)
Message : Utilisation invalide de la clause GROUP.

- Error: 1112 SQLSTATE: 42000 (ER_UNSUPPORTED_EXTENSION)
Message : Table '%s' : utilise une extension invalide pour cette version de MySQL.

- Error: 1113 SQLSTATE: 42000 (ER_TABLE_MUST_HAVE_COLUMNS)
Message : Une table doit comporter au moins une colonne.

- Error: 1114 SQLSTATE: HY000 (ER_RECORD_FILE_FULL)
Message : La table '%s' est pleine.

- Error: 1115 SQLSTATE: 42000 (ER_UNKNOWN_CHARACTER_SET)
Message : Jeu de caractères inconnu: '%s'.

- Error: 1116 SQLSTATE: HY000 (ER_TOO_MANY_TABLES)
Message : Trop de tables. MySQL ne peut utiliser que %d tables dans un JOIN.

- Error: 1117 SQLSTATE: HY000 (ER_TOO_MANY_FIELDS)
Message : Trop de champs.

- Error: 1118 SQLSTATE: 42000 (ER_TOO_BIG_ROWSIZE)
Message : Ligne trop grande. Le taille maximale d'une ligne, sauf les BLOBs, est %d. Changez le type de quelques colonnes en BLOB.

- Error: 1119 SQLSTATE: HY000 (ER_STACK_OVERRUN)
Message : Débordement de la pile des tâches (Thread stack). Utilisées: %ld pour une pile de %ld. Essayez 'mysqld -O thread_stack=#' pour indiquer une plus grande valeur.

- Error: 1120 SQLSTATE: 42000 (ER_WRONG_OUTER_JOIN)
Message : Dépendance croisée dans une clause OUTER JOIN. Vérifiez la condition ON.

- Error: 1121 SQLSTATE: 42000 (ER_NULL_COLUMN_IN_INDEX)
Message : La colonne '%s' fait partie d'un index UNIQUE ou INDEX mais n'est pas définie comme NOT NULL.

- Error: 1122 SQLSTATE: HY000 (ER_CANT_FIND_UDF)
Message : Impossible de charger la fonction '%s'.

- Error: 1123 SQLSTATE: HY000 (ER_CANT_INITIALIZE_UDF)
Message : Impossible d'initialiser la fonction '%s'; %s.

- Error: 1124 SQLSTATE: HY000 (ER_UDF_NO_PATHS)
Message : Chemin interdit pour les bibliothèques partagées.

- Error: 1125 SQLSTATE: HY000 (ER_UDF_EXISTS)
Message : La fonction '%s' existe déjà.

- Error: 1126 SQLSTATE: HY000 (ER_CANT_OPEN_LIBRARY)
Message : Impossible d'ouvrir la bibliothèque partagée '%s' (errno: %d %s).

- Error: 1127 SQLSTATE: HY000 (ER_CANT_FIND_DL_ENTRY)
Message : Impossible de trouver la fonction '%s' dans la bibliothèque.

- Error: 1128 SQLSTATE: HY000 (ER_FUNCTION_NOT_DEFINED)
Message : La fonction '%s' n'est pas définie.

- Error: 1129 SQLSTATE: HY000 (ER_HOST_IS_BLOCKED)
Message : L'hôte '%s' est bloqué à cause d'un trop grand nombre d'erreurs de connexion. Débloquez-le par 'mysqladmin flush-hosts'.

- Error: 1130 SQLSTATE: HY000 (ER_HOST_NOT_PRIVILEGED)
Message : L'hôte '%s' n'est pas autorisé à se connecter à ce serveur MySQL.

- Error: 1131 SQLSTATE: 42000 (ER_PASSWORD_ANONYMOUS_USER)
Message : Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe.

- Error: 1132 SQLSTATE: 42000 (ER_PASSWORD_NOT_ALLOWED)
Message : Vous devez avoir le privilège update sur les tables de la base de données mysql pour pouvoir changer les mots de passe des autres.

- Error: 1133 SQLSTATE: 42000 (ER_PASSWORD_NO_MATCH)
Message : Impossible de trouver un enregistrement correspondant dans la table user.

- Error: 1134 SQLSTATE: HY000 (ER_UPDATE_INFO)
Message : Enregistrements correspondants: %ld Modifiés: %ld Warnings: %ld.

- Error: 1135 SQLSTATE: HY000 (ER_CANT_CREATE_THREAD)
Message : Impossible de créer une nouvelle tâche (errno %d). S'il reste de la mémoire libre, consultez le manuel pour trouver un éventuel bug dépendant de l'OS.

- Error: 1136 SQLSTATE: 21S01 (ER_WRONG_VALUE_COUNT_ON_ROW)
Message : Column count doesn't match value count at row %ld.

- Error: 1137 SQLSTATE: HY000 (ER_CANT_REOPEN_TABLE)
Message : Impossible de rouvrir la table: '%s.

- Error: 1138 SQLSTATE: 22004 (ER_INVALID_USE_OF_NULL)
Message : Utilisation incorrecte de la valeur NULL.

- Error: 1139 SQLSTATE: 42000 (ER_REGEXP_ERROR)
Message : Erreur '%s' provenant de regexp.

- Error: 1140 SQLSTATE: 42000 (ER_MIX_OF_GROUP_FUNC_AND_FIELDS)
Message : Mélanger les colonnes GROUP (MIN(),MAX(),COUNT()...) avec des colonnes normales est interdit s'il n'y a pas de clause GROUP BY.

- Error: 1141 SQLSTATE: 42000 (ER_NONEXISTING_GRANT)
Message : Un tel droit n'est pas défini pour l'utilisateur '%s' sur l'hôte '%s'.

- Error: 1142 SQLSTATE: 42000 (ER_TABLEACCESS_DENIED_ERROR)
Message : La commande '%s' est interdite à l'utilisateur: '%s'@'@%s' sur la table '%s'.

- Error: 1143 SQLSTATE: 42000 (ER_COLUMNACCESS_DENIED_ERROR)
Message : La commande '%s' est interdite à l'utilisateur: '%s'@'@%s' sur la colonne '%s' de la table '%s'.

- Error: 1144 SQLSTATE: 42000 (ER_ILLEGAL_GRANT_FOR_TABLE)
Message : Commande GRANT/REVOKE incorrecte. Consultez le manuel.

- Error: 1145 SQLSTATE: 42000 (ER_GRANT_WRONG_HOST_OR_USER)
Message : L'hôte ou l'utilisateur donné en argument à GRANT est trop long.

- Error: 1146 SQLSTATE: 42S02 (ER_NO_SUCH_TABLE)
Message : La table '%s.%s' n'existe pas.

- Error: 1147 SQLSTATE: 42000 (ER_NONEXISTING_TABLE_GRANT)
Message : Un tel droit n'est pas défini pour l'utilisateur '%s' sur l'hôte '%s' sur la table '%s'.

- Error: 1148 SQLSTATE: 42000 (ER_NOT_ALLOWED_COMMAND)
Message : Cette commande n'existe pas dans cette version de MySQL.

- Error: 1149 SQLSTATE: 42000 (ER_SYNTAX_ERROR)
Message : Erreur de syntaxe.

- Error: 1150 SQLSTATE: HY000 (ER_DELAYED_CANT_CHANGE_LOCK)
Message : La tâche 'delayed insert' n'a pas pu obtenir le verrou demandé sur la table %s.

- Error: 1151 SQLSTATE: HY000 (ER_TOO_MANY_DELAYED_THREADS)
Message : Trop de tâches 'delayed' en cours.

- Error: 1152 SQLSTATE: 08S01 (ER_ABORTING_CONNECTION)
Message : Connexion %ld avortée vers la bd: '%s' utilisateur: '%s' (%s).

- Error: 1153 SQLSTATE: 08S01 (ER_NET_PACKET_TOO_LARGE)
Message : Paquet plus grand que 'max_allowed_packet' reçu.

- Error: 1154 SQLSTATE: 08S01 (ER_NET_READ_ERROR_FROM_PIPE)
Message : Erreur de lecture reçue du pipe de connexion.

- Error: 1155 SQLSTATE: 08S01 (ER_NET_FCNTL_ERROR)
Message : Erreur reçue de fcntl().

- Error: 1156 SQLSTATE: 08S01 (ER_NET_PACKETS_OUT_OF_ORDER)
Message : Paquets reçus dans le désordre.

- Error: 1157 SQLSTATE: 08S01 (ER_NET_UNCOMPRESS_ERROR)
Message : Impossible de décompresser le paquet reçu.

- Error: 1158 SQLSTATE: 08S01 (ER_NET_READ_ERROR)
Message : Erreur de lecture des paquets reçus.

- Error: 1159 SQLSTATE: 08S01 (ER_NET_READ_INTERRUPTED)
Message : Timeout en lecture des paquets reçus.

- Error: 1160 SQLSTATE: 08S01 (ER_NET_ERROR_ON_WRITE)
Message : Erreur d'écriture des paquets envoyés.

- Error: 1161 SQLSTATE: 08S01 (ER_NET_WRITE_INTERRUPTED)
Message : Timeout d'écriture des paquets envoyés.

- Error: 1162 SQLSTATE: 42000 (ER_TOO_LONG_STRING)
Message : La chaîne résultat est plus grande que 'max_allowed_packet'.

- Error: 1163 SQLSTATE: 42000 (ER_TABLE_CANT_HANDLE_BLOB)
Message : Ce type de table ne supporte pas les colonnes BLOB/TEXT.

- Error: 1164 SQLSTATE: 42000 (ER_TABLE_CANT_HANDLE_AUTO_INCREMENT)
Message : Ce type de table ne supporte pas les colonnes AUTO_INCREMENT.

- Error: 1165 SQLSTATE: HY000 (ER_DELAYED_INSERT_TABLE_LOCKED)
Message : INSERT DELAYED ne peut être utilisé avec la table '%s', car elle est verrouillée avec LOCK TABLES.

- Error: 1166 SQLSTATE: 42000 (ER_WRONG_COLUMN_NAME)
Message : Nom de colonne '%s' incorrect.

- Error: 1167 SQLSTATE: 42000 (ER_WRONG_KEY_COLUMN)
Message : Le handler de la table ne peut indexé la colonne '%s'.

- Error: 1168 SQLSTATE: HY000 (ER_WRONG_MRG_TABLE)
Message : Toutes les tables de la table de type MERGE n'ont pas la même définition.

- Error: 1169 SQLSTATE: 23000 (ER_DUP_UNIQUE)
Message : Écriture impossible à cause d'un index UNIQUE sur la table '%s'.

- Error: 1170 SQLSTATE: 42000 (ER_BLOB_KEY_WITHOUT_LENGTH)
Message : La colonne '%s' de type BLOB est utilisée dans une définition d'index sans longueur d'index.

- Error: 1171 SQLSTATE: 42000 (ER_PRIMARY_CANT_HAVE_NULL)
Message : Toutes les parties d'un index PRIMARY KEY doivent être NOT NULL; Si vous avez besoin d'un NULL dans l'index, utilisez un index UNIQUE.

- Error: 1172 SQLSTATE: 42000 (ER_TOO_MANY_ROWS)
Message : Le résultat contient plus d'un enregistrement.

- Error: 1173 SQLSTATE: 42000 (ER_REQUIRES_PRIMARY_KEY)
Message : Ce type de table nécessite une clé primaire (PRIMARY KEY).

- Error: 1174 SQLSTATE: HY000 (ER_NO_RAID_COMPILED)
Message : Cette version de MySQL n'est pas compilée avec le support RAID.

- Error: 1175 SQLSTATE: HY000 (ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE)
Message : Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index.

- Error: 1176 SQLSTATE: HY000 (ER_KEY_DOES_NOT_EXITS)
Message : L'index '%s' n'existe pas sur la table '%s'.

- Error: 1177 SQLSTATE: 42000 (ER_CHECK_NO_SUCH_TABLE)
Message : Impossible d'ouvrir la table.

- Error: 1178 SQLSTATE: 42000 (ER_CHECK_NOT_IMPLEMENTED)
Message : Ce type de table ne supporte pas les %s.

- Error: 1179 SQLSTATE: 25000 (ER_CANT_DO_THIS_DURING_AN_TRANSACTION)
Message : Vous n'êtes pas autorisé à exécute cette commande dans une transaction.

- Error: 1180 SQLSTATE: HY000 (ER_ERROR_DURING_COMMIT)
Message : Erreur %d lors du COMMIT.

- Error: 1181 SQLSTATE: HY000 (ER_ERROR_DURING_ROLLBACK)
Message : Erreur %d lors du ROLLBACK.

- Error: 1182 SQLSTATE: HY000 (ER_ERROR_DURING_FLUSH_LOGS)
Message : Erreur %d lors du FLUSH_LOGS.

- Error: 1183 SQLSTATE: HY000 (ER_ERROR_DURING_CHECKPOINT)
Message : Erreur %d lors du CHECKPOINT.

- Error: 1184 SQLSTATE: 08S01 (ER_NEW_ABORTING_CONNECTION)
Message : Connexion %ld avortée vers la bd: '%s' utilisateur: '%s' hôte: '%s' (%s).

- Error: 1185 SQLSTATE: HY000 (ER_DUMP_NOT_IMPLEMENTED)
Message : Ce type de table ne supporte pas les copies binaires.

- Error: 1186 SQLSTATE: HY000 (ER_FLUSH_MASTER_BINLOG_CLOSED)
Message : Binlog closed, cannot RESET MASTER.

- Error: 1187 SQLSTATE: HY000 (ER_INDEX_REBUILD)
Message : La reconstruction de l'index de la table copiée '%s' a échoué.

- Error: 1188 SQLSTATE: HY000 (ER_MASTER)
Message : Erreur reçue du maître: '%s'.

- Error: 1189 SQLSTATE: 08S01 (ER_MASTER_NET_READ)
Message : Erreur de lecture réseau reçue du maître.

- Error: 1190 SQLSTATE: 08S01 (ER_MASTER_NET_WRITE)
Message : Erreur d'écriture réseau reçue du maître.

- Error: 1191 SQLSTATE: HY000 (ER_FT_MATCHING_KEY_NOT_FOUND)
Message : Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes.

- Error: 1192 SQLSTATE: HY000 (ER_LOCK_OR_ACTIVE_TRANSACTION)
Message : Impossible d'exécuter la commande, car vous avez des tables verrouillées ou une transaction active.

- Error: 1193 SQLSTATE: HY000 (ER_UNKNOWN_SYSTEM_VARIABLE)
Message : Variable système '%s' inconnue.

- Error: 1194 SQLSTATE: HY000 (ER_CRASHED_ON_USAGE)
Message : La table '%s' est marquée 'crashed' et devrait être réparée.

- Error: 1195 SQLSTATE: HY000 (ER_CRASHED_ON_REPAIR)
Message : La table '%s' est marquée 'crashed' et le dernier 'repair' a échoué.

- Error: 1196 SQLSTATE: HY000 (ER_WARNING_NOT_COMPLETE_ROLLBACK)
Message : Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées.

- Error: 1197 SQLSTATE: HY000 (ER_TRANS_CACHE_FULL)
Message : Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez.

- Error: 1198 SQLSTATE: HY000 (ER_SLAVE_MUST_STOP)
Message : Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord.

- Error: 1199 SQLSTATE: HY000 (ER_SLAVE_NOT_RUNNING)
Message : Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE.

- Error: 1200 SQLSTATE: HY000 (ER_BAD_SLAVE)
Message : Le serveur n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO.

- Error: 1201 SQLSTATE: HY000 (ER_MASTER_INFO)
Message : Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL.

- Error: 1202 SQLSTATE: HY000 (ER_SLAVE_THREAD)
Message : Impossible de créer une tâche esclave, vérifiez les ressources système.

- Error: 1203 SQLSTATE: 42000 (ER_TOO_MANY_USER_CONNECTIONS)
Message : L'utilisateur %s possède déjà plus de 'max_user_connections' connections actives.

- Error: 1204 SQLSTATE: HY000 (ER_SET_CONSTANTS_ONLY)
Message : Seules les expressions constantes sont autorisées avec SET.

- Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
Message : Timeout sur l'obtention du verrou.

- Error: 1206 SQLSTATE: HY000 (ER_LOCK_TABLE_FULL)
Message : Le nombre total de verrous dépasse la taille de la table des verrous.

- Error: 1207 SQLSTATE: 25000 (ER_READ_ONLY_TRANSACTION)
Message : Un verrou en update ne peut être acquis pendant une transaction READ UNCOMMITTED.

- Error: 1208 SQLSTATE: HY000 (ER_DROP_DB_WITH_READ_LOCK)
Message : DROP DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture.

- Error: 1209 SQLSTATE: HY000 (ER_CREATE_DB_WITH_READ_LOCK)
Message : CREATE DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture.

- Error: 1210 SQLSTATE: HY000 (ER_WRONG_ARGUMENTS)
Message : Mauvais arguments à %s.

- Error: 1211 SQLSTATE: 42000 (ER_NO_PERMISSION_TO_CREATE_USER)
Message : '%s'@'%s' n'est pas autorisé à créer de nouveaux utilisateurs.

- Error: 1212 SQLSTATE: HY000 (ER_UNION_TABLES_IN_DIFFERENT_DIR)
Message : Définition de table incorrecte; toutes les tables MERGE doivent être dans la même base de données.

- Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK)
Message : Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction.

- Error: 1214 SQLSTATE: HY000 (ER_TABLE_CANT_HANDLE_FT)
Message : Le type de table utilisé ne supporte pas les index FULLTEXT.

- Error: 1215 SQLSTATE: HY000 (ER_CANNOT_ADD_FOREIGN)
Message : Impossible d'ajouter des contraintes d'index externe.

- Error: 1216 SQLSTATE: 23000 (ER_NO_REFERENCED_ROW)
Message : Impossible d'ajouter un enregistrement fils : une contrainte externe l'empêche.

- Error: 1217 SQLSTATE: 23000 (ER_ROW_IS_REFERENCED)
Message : Impossible de supprimer un enregistrement père : une contrainte externe l'empêche.

- Error: 1218 SQLSTATE: 08S01 (ER_CONNECT_TO_MASTER)
Message : Error connecting to master: %s.

- Error: 1219 SQLSTATE: HY000 (ER_QUERY_ON_MASTER)
Message : Error running query on master: %s.

- Error: 1220 SQLSTATE: HY000 (ER_ERROR_WHEN_EXECUTING_COMMAND)
Message : Error when executing command %s: %s.

- Error: 1221 SQLSTATE: HY000 (ER_WRONG_USAGE)
Message : Incorrect usage of %s and %s.

- Error: 1222 SQLSTATE: 21000 (ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT)
Message : The used SELECT statements have a different number of columns.

- Error: 1223 SQLSTATE: HY000 (ER_CANT_UPDATE_WITH_READLOCK)
Message : Can't execute the query because you have a conflicting read lock.

- Error: 1224 SQLSTATE: HY000 (ER_MIXING_NOT_ALLOWED)
Message : Mixing of transactional and non-transactional tables is disabled.

- Error: 1225 SQLSTATE: HY000 (ER_DUP_ARGUMENT)
Message : Option '%s' used twice in statement.

- Error: 1226 SQLSTATE: 42000 (ER_USER_LIMIT_REACHED)
Message : User '%s' has exceeded the '%s' resource (current value: %ld).

- Error: 1227 SQLSTATE: 42000 (ER_SPECIFIC_ACCESS_DENIED_ERROR)
Message : Access denied; you need the %s privilege for this operation.

- Error: 1228 SQLSTATE: HY000 (ER_LOCAL_VARIABLE)
Message : Variable '%s' is a SESSION variable and can't be used with SET GLOBAL.

- Error: 1229 SQLSTATE: HY000 (ER_GLOBAL_VARIABLE)
Message : Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL.

- Error: 1230 SQLSTATE: 42000 (ER_NO_DEFAULT)
Message : Variable '%s' doesn't have a default value.

- Error: 1231 SQLSTATE: 42000 (ER_WRONG_VALUE_FOR_VAR)
Message : Variable '%s' can't be set to the value of '%s'.

- Error: 1232 SQLSTATE: 42000 (ER_WRONG_TYPE_FOR_VAR)
Message : Incorrect argument type to variable '%s'.

- Error: 1233 SQLSTATE: HY000 (ER_VAR_CANT_BE_READ)
Message : Variable '%s' can only be set, not read.

- Error: 1234 SQLSTATE: 42000 (ER_CANT_USE_OPTION_HERE)
Message : Incorrect usage/placement of '%s'.

- Error: 1235 SQLSTATE: 42000 (ER_NOT_SUPPORTED_YET)
Message : This version of MySQL doesn't yet support '%s'.

- Error: 1236 SQLSTATE: HY000 (ER_MASTER_FATAL_ERROR_READING_BINLOG)
Message : Got fatal error %d: '%s' from master when reading data from binary log.

- Error: 1237 SQLSTATE: HY000 (ER_SLAVE_IGNORED_TABLE)
Message : Slave SQL thread ignored the query because of replicate-*-table rules.

- Error: 1238 SQLSTATE: HY000 (ER_INCORRECT_GLOBAL_LOCAL_VAR)
Message : Variable '%s' is a %s variable.

- Error: 1239 SQLSTATE: 42000 (ER_WRONG_FK_DEF)
Message : Incorrect foreign key definition for '%s': %s.

- Error: 1240 SQLSTATE: HY000 (ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)
Message : Key reference and table reference don't match.

- Error: 1241 SQLSTATE: 21000 (ER_OPERAND_COLUMNS)
Message : Operand should contain %d column(s).

- Error: 1242 SQLSTATE: 21000 (ER_SUBQUERY_NO_1_ROW)
Message : Subquery returns more than 1 row.

- Error: 1243 SQLSTATE: HY000 (ER_UNKNOWN_STMT_HANDLER)
Message : Unknown prepared statement handler (%.*s) given to %s.

- Error: 1244 SQLSTATE: HY000 (ER_CORRUPT_HELP_DB)
Message : Help database is corrupt or does not exist.

- Error: 1245 SQLSTATE: HY000 (ER_CYCLIC_REFERENCE)
Message : Cyclic reference on subqueries.

- Error: 1246 SQLSTATE: HY000 (ER_AUTO_CONVERT)
Message : Converting column '%s' from %s to %s.

- Error: 1247 SQLSTATE: 42S22 (ER_ILLEGAL_REFERENCE)
Message : Reference '%s' not supported (%s).

- Error: 1248 SQLSTATE: 42000 (ER_DERIVED_MUST_HAVE_ALIAS)
Message : Every derived table must have its own alias.

- Error: 1249 SQLSTATE: 01000 (ER_SELECT_REDUCED)
Message : Select %u was reduced during optimization.

- Error: 1250 SQLSTATE: 42000 (ER_TABLENAME_NOT_ALLOWED_HERE)
Message : Table '%s' from one of the SELECTs cannot be used in %s.

- Error: 1251 SQLSTATE: 08004 (ER_NOT_SUPPORTED_AUTH_MODE)
Message : Client does not support authentication protocol requested by server; consider upgrading MySQL client.

- Error: 1252 SQLSTATE: 42000 (ER_SPATIAL_CANT_HAVE_NULL)
Message : All parts of a SPATIAL index must be NOT NULL.

- Error: 1253 SQLSTATE: 42000 (ER_COLLATION_CHARSET_MISMATCH)
Message : COLLATION '%s' is not valid for CHARACTER SET '%s'.

- Error: 1254 SQLSTATE: HY000 (ER_SLAVE_WAS_RUNNING)
Message : Slave is already running.

- Error: 1255 SQLSTATE: HY000 (ER_SLAVE_WAS_NOT_RUNNING)
Message : Slave already has been stopped.

- Error: 1256 SQLSTATE: HY000 (ER_TOO_BIG_FOR_UNCOMPRESS)
Message : Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted).

- Error: 1257 SQLSTATE: HY000 (ER_ZLIB_Z_MEM_ERROR)
Message : ZLIB: Not enough memory.

- Error: 1258 SQLSTATE: HY000 (ER_ZLIB_Z_BUF_ERROR)
Message : ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted).

- Error: 1259 SQLSTATE: HY000 (ER_ZLIB_Z_DATA_ERROR)
Message : ZLIB: Input data corrupted.

- Error: 1260 SQLSTATE: HY000 (ER_CUT_VALUE_GROUP_CONCAT)
Message : %d line(s) were cut by GROUP_CONCAT().

- Error: 1261 SQLSTATE: 01000 (ER_WARN_TOO_FEW_RECORDS)
Message : Row %ld doesn't contain data for all columns.

- Error: 1262 SQLSTATE: 01000 (ER_WARN_TOO_MANY_RECORDS)
Message : Row %ld was truncated; it contained more data than there were input columns.

- Error: 1263 SQLSTATE: 22004 (ER_WARN_NULL_TO_NOTNULL)
Message : Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld.

- Error: 1264 SQLSTATE: 22003 (ER_WARN_DATA_OUT_OF_RANGE)
Message : Out of range value adjusted for column '%s' at row %ld.

- Error: 1265 SQLSTATE: 01000 (WARN_DATA_TRUNCATED)
Message : Data truncated for column '%s' at row %ld.

- Error: 1266 SQLSTATE: HY000 (ER_WARN_USING_OTHER_HANDLER)
Message : Using storage engine %s for table '%s'.

- Error: 1267 SQLSTATE: HY000 (ER_CANT_AGGREGATE_2COLLATIONS)
Message : Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'.

- Error: 1268 SQLSTATE: HY000 (ER_DROP_USER)
Message : Cannot drop one or more of the requested users.

- Error: 1269 SQLSTATE: HY000 (ER_REVOKE_GRANTS)
Message : Can't revoke all privileges for one or more of the requested users.

- Error: 1270 SQLSTATE: HY000 (ER_CANT_AGGREGATE_3COLLATIONS)
Message : Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'.

- Error: 1271 SQLSTATE: HY000 (ER_CANT_AGGREGATE_NCOLLATIONS)
Message : Illegal mix of collations for operation '%s'.

- Error: 1272 SQLSTATE: HY000 (ER_VARIABLE_IS_NOT_STRUCT)
Message : Variable '%s' is not a variable component (can't be used as XXXX.variable_name).

- Error: 1273 SQLSTATE: HY000 (ER_UNKNOWN_COLLATION)
Message : Unknown collation: '%s'.

- Error: 1274 SQLSTATE: HY000 (ER_SLAVE_IGNORED_SSL_PARAMS)
Message : SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started.

- Error: 1275 SQLSTATE: HY000 (ER_SERVER_IS_IN_SECURE_AUTH_MODE)
Message : Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format.

- Error: 1276 SQLSTATE: HY000 (ER_WARN_FIELD_RESOLVED)
Message : Field or reference '%s%s%s%s%s' of SELECT #%d was resolved in SELECT #%d.

- Error: 1277 SQLSTATE: HY000 (ER_BAD_SLAVE_UNTIL_COND)
Message : Incorrect parameter or combination of parameters for START SLAVE UNTIL.

- Error: 1278 SQLSTATE: HY000 (ER_MISSING_SKIP_SLAVE)
Message : It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart.

- Error: 1279 SQLSTATE: HY000 (ER_UNTIL_COND_IGNORED)
Message : SQL thread is not to be started so UNTIL options are ignored.

- Error: 1280 SQLSTATE: 42000 (ER_WRONG_NAME_FOR_INDEX)
Message : Incorrect index name '%s'.

- Error: 1281 SQLSTATE: 42000 (ER_WRONG_NAME_FOR_CATALOG)
Message : Incorrect catalog name '%s'.

- Error: 1282 SQLSTATE: HY000 (ER_WARN_QC_RESIZE)
Message : Query cache failed to set size %lu; new query cache size is %lu.

- Error: 1283 SQLSTATE: HY000 (ER_BAD_FT_COLUMN)
Message : Column '%s' cannot be part of FULLTEXT index.

- Error: 1284 SQLSTATE: HY000 (ER_UNKNOWN_KEY_CACHE)
Message : Unknown key cache '%s'.

- Error: 1285 SQLSTATE: HY000 (ER_WARN_HOSTNAME_WONT_WORK)
Message : MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work.

- Error: 1286 SQLSTATE: 42000 (ER_UNKNOWN_STORAGE_ENGINE)
Message : Unknown table engine '%s'.

- Error: 1287 SQLSTATE: HY000 (ER_WARN_DEPRECATED_SYNTAX)
Message : '%s' is deprecated; use '%s' instead.

- Error: 1288 SQLSTATE: HY000 (ER_NON_UPDATABLE_TABLE)
Message : The target table %s of the %s is not updatable.

- Error: 1289 SQLSTATE: HY000 (ER_FEATURE_DISABLED)
Message : The '%s' feature is disabled; you need MySQL built with '%s' to have it working.

- Error: 1290 SQLSTATE: HY000 (ER_OPTION_PREVENTS_STATEMENT)
Message : The MySQL server is running with the %s option so it cannot execute this statement.

- Error: 1291 SQLSTATE: HY000 (ER_DUPLICATED_VALUE_IN_TYPE)
Message : Column '%s' has duplicated value '%s' in %s.

- Error: 1292 SQLSTATE: 22007 (ER_TRUNCATED_WRONG_VALUE)
Message : Truncated incorrect %s value: '%s'.

- Error: 1293 SQLSTATE: HY000 (ER_TOO_MUCH_AUTO_TIMESTAMP_COLS)
Message : Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause.

- Error: 1294 SQLSTATE: HY000 (ER_INVALID_ON_UPDATE)
Message : Invalid ON UPDATE clause for '%s' column.

- Error: 1295 SQLSTATE: HY000 (ER_UNSUPPORTED_PS)
Message : This command is not supported in the prepared statement protocol yet.

- Error: 1296 SQLSTATE: HY000 (ER_GET_ERRMSG)
Message : Got error %d '%s' from %s.

- Error: 1297 SQLSTATE: HY000 (ER_GET_TEMPORARY_ERRMSG)
Message : Got temporary error %d '%s' from %s.

- Error: 1298 SQLSTATE: HY000 (ER_UNKNOWN_TIME_ZONE)
Message : Unknown or incorrect time zone: '%s'.

- Error: 1299 SQLSTATE: HY000 (ER_WARN_INVALID_TIMESTAMP)
Message : Invalid TIMESTAMP value in column '%s' at row %ld.

- Error: 1300 SQLSTATE: HY000 (ER_INVALID_CHARACTER_STRING)
Message : Invalid %s character string: '%s'.

- Error: 1301 SQLSTATE: HY000 (ER_WARN_ALLOWED_PACKET_OVERFLOWED)
Message : Result of %s() was larger than max_allowed_packet (%ld) - truncated.

- Error: 1302 SQLSTATE: HY000 (ER_CONFLICTING_DECLARATIONS)
Message : Conflicting declarations: '%s%s' and '%s%s'.

- Error: 1303 SQLSTATE: 2F003 (ER_SP_NO_RECURSIVE_CREATE)
Message : Can't create a %s from within another stored routine.

- Error: 1304 SQLSTATE: 42000 (ER_SP_ALREADY_EXISTS)
Message : %s %s already exists.

- Error: 1305 SQLSTATE: 42000 (ER_SP_DOES_NOT_EXIST)
Message : %s %s does not exist.

- Error: 1306 SQLSTATE: HY000 (ER_SP_DROP_FAILED)
Message : Failed to DROP %s %s.

- Error: 1307 SQLSTATE: HY000 (ER_SP_STORE_FAILED)
Message : Failed to CREATE %s %s.

- Error: 1308 SQLSTATE: 42000 (ER_SP_LILABEL_MISMATCH)
Message : %s with no matching label: %s.

- Error: 1309 SQLSTATE: 42000 (ER_SP_LABEL_REDEFINE)
Message : Redefining label %s.

- Error: 1310 SQLSTATE: 42000 (ER_SP_LABEL_MISMATCH)
Message : End-label %s without match.

- Error: 1311 SQLSTATE: 01000 (ER_SP_UNINIT_VAR)
Message : Referring to uninitialized variable %s.

- Error: 1312 SQLSTATE: 0A000 (ER_SP_BADSELECT)
Message : PROCEDURE %s can't return a result set in the given context.

- Error: 1313 SQLSTATE: 42000 (ER_SP_BADRETURN)
Message : RETURN is only allowed in a FUNCTION.

- Error: 1314 SQLSTATE: 0A000 (ER_SP_BADSTATEMENT)
Message : %s is not allowed in stored procedures.

- Error: 1315 SQLSTATE: 42000 (ER_UPDATE_LOG_DEPRECATED_IGNORED)
Message : The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored.

- Error: 1316 SQLSTATE: 42000 (ER_UPDATE_LOG_DEPRECATED_TRANSLATED)
Message : The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN.

- Error: 1317 SQLSTATE: 70100 (ER_QUERY_INTERRUPTED)
Message : Query execution was interrupted.

- Error: 1318 SQLSTATE: 42000 (ER_SP_WRONG_NO_OF_ARGS)
Message : Incorrect number of arguments for %s %s; expected %u, got %u.

- Error: 1319 SQLSTATE: 42000 (ER_SP_COND_MISMATCH)
Message : Undefined CONDITION: %s.

- Error: 1320 SQLSTATE: 42000 (ER_SP_NORETURN)
Message : No RETURN found in FUNCTION %s.

- Error: 1321 SQLSTATE: 2F005 (ER_SP_NORETURNEND)
Message : FUNCTION %s ended without RETURN.

- Error: 1322 SQLSTATE: 42000 (ER_SP_BAD_CURSOR_QUERY)
Message : Cursor statement must be a SELECT.

- Error: 1323 SQLSTATE: 42000 (ER_SP_BAD_CURSOR_SELECT)
Message : Cursor SELECT must not have INTO.

- Error: 1324 SQLSTATE: 42000 (ER_SP_CURSOR_MISMATCH)
Message : Undefined CURSOR: %s.

- Error: 1325 SQLSTATE: 24000 (ER_SP_CURSOR_ALREADY_OPEN)
Message : Cursor is already open.

- Error: 1326 SQLSTATE: 24000 (ER_SP_CURSOR_NOT_OPEN)
Message : Cursor is not open.

- Error: 1327 SQLSTATE: 42000 (ER_SP_UNDECLARED_VAR)
Message : Undeclared variable: %s.

- Error: 1328 SQLSTATE: HY000 (ER_SP_WRONG_NO_OF_FETCH_ARGS)
Message : Incorrect number of FETCH variables.

- Error: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)
Message : No data - zero rows fetched, selected, or processed.

- Error: 1330 SQLSTATE: 42000 (ER_SP_DUP_PARAM)
Message : Duplicate parameter: %s.

- Error: 1331 SQLSTATE: 42000 (ER_SP_DUP_VAR)
Message : Duplicate variable: %s.

- Error: 1332 SQLSTATE: 42000 (ER_SP_DUP_COND)
Message : Duplicate condition: %s.

- Error: 1333 SQLSTATE: 42000 (ER_SP_DUP_CURS)
Message : Duplicate cursor: %s.

- Error: 1334 SQLSTATE: HY000 (ER_SP_CANT_ALTER)
Message : Failed to ALTER %s %s.

- Error: 1335 SQLSTATE: 0A000 (ER_SP_SUBSELECT_NYI)
Message : Subselect value not supported.

- Error: 1336 SQLSTATE: 0A000 (ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG)
Message : %s is not allowed in stored function or trigger.

- Error: 1337 SQLSTATE: 42000 (ER_SP_VARCOND_AFTER_CURSHNDLR)
Message : Variable or condition declaration after cursor or handler declaration.

- Error: 1338 SQLSTATE: 42000 (ER_SP_CURSOR_AFTER_HANDLER)
Message : Cursor declaration after handler declaration.

- Error: 1339 SQLSTATE: 20000 (ER_SP_CASE_NOT_FOUND)
Message : Case not found for CASE statement.

- Error: 1340 SQLSTATE: HY000 (ER_FPARSER_TOO_BIG_FILE)
Message : Configuration file '%s' is too big.

- Error: 1341 SQLSTATE: HY000 (ER_FPARSER_BAD_HEADER)
Message : Malformed file type header in file '%s'.

- Error: 1342 SQLSTATE: HY000 (ER_FPARSER_EOF_IN_COMMENT)
Message : Unexpected end of file while parsing comment '%s'.

- Error: 1343 SQLSTATE: HY000 (ER_FPARSER_ERROR_IN_PARAMETER)
Message : Error while parsing parameter '%s' (line: '%s').

- Error: 1344 SQLSTATE: HY000 (ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER)
Message : Unexpected end of file while skipping unknown parameter '%s'.

- Error: 1345 SQLSTATE: HY000 (ER_VIEW_NO_EXPLAIN)
Message : EXPLAIN/SHOW can not be issued; lacking privileges for underlying table.

- Error: 1346 SQLSTATE: HY000 (ER_FRM_UNKNOWN_TYPE)
Message : File '%s' has unknown type '%s' in its header.

- Error: 1347 SQLSTATE: HY000 (ER_WRONG_OBJECT)
Message : '%s.%s' is not %s.

- Error: 1348 SQLSTATE: HY000 (ER_NONUPDATEABLE_COLUMN)
Message : Column '%s' is not updatable.

- Error: 1349 SQLSTATE: HY000 (ER_VIEW_SELECT_DERIVED)
Message : View's SELECT contains a subquery in the FROM clause.

- Error: 1350 SQLSTATE: HY000 (ER_VIEW_SELECT_CLAUSE)
Message : View's SELECT contains a '%s' clause.

- Error: 1351 SQLSTATE: HY000 (ER_VIEW_SELECT_VARIABLE)
Message : View's SELECT contains a variable or parameter.

- Error: 1352 SQLSTATE: HY000 (ER_VIEW_SELECT_TMPTABLE)
Message : View's SELECT refers to a temporary table '%s'.

- Error: 1353 SQLSTATE: HY000 (ER_VIEW_WRONG_LIST)
Message : View's SELECT and view's field list have different column counts.

- Error: 1354 SQLSTATE: HY000 (ER_WARN_VIEW_MERGE)
Message : View merge algorithm can't be used here for now (assumed undefined algorithm).

- Error: 1355 SQLSTATE: HY000 (ER_WARN_VIEW_WITHOUT_KEY)
Message : View being updated does not have complete key of underlying table in it.

- Error: 1356 SQLSTATE: HY000 (ER_VIEW_INVALID)
Message : View '%s.%s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them.

- Error: 1357 SQLSTATE: HY000 (ER_SP_NO_DROP_SP)
Message : Can't drop or alter a %s from within another stored routine.

- Error: 1358 SQLSTATE: HY000 (ER_SP_GOTO_IN_HNDLR)
Message : GOTO is not allowed in a stored procedure handler.

- Error: 1359 SQLSTATE: HY000 (ER_TRG_ALREADY_EXISTS)
Message : Trigger already exists.

- Error: 1360 SQLSTATE: HY000 (ER_TRG_DOES_NOT_EXIST)
Message : Trigger does not exist.

- Error: 1361 SQLSTATE: HY000 (ER_TRG_ON_VIEW_OR_TEMP_TABLE)
Message : Trigger's '%s' is view or temporary table.

- Error: 1362 SQLSTATE: HY000 (ER_TRG_CANT_CHANGE_ROW)
Message : Updating of %s row is not allowed in %strigger.

- Error: 1363 SQLSTATE: HY000 (ER_TRG_NO_SUCH_ROW_IN_TRG)
Message : There is no %s row in %s trigger.

- Error: 1364 SQLSTATE: HY000 (ER_NO_DEFAULT_FOR_FIELD)
Message : Field '%s' doesn't have a default value.

- Error: 1365 SQLSTATE: 22012 (ER_DIVISION_BY_ZERO)
Message : Division by 0.

- Error: 1366 SQLSTATE: HY000 (ER_TRUNCATED_WRONG_VALUE_FOR_FIELD)
Message : Incorrect %s value: '%s' for column '%s' at row %ld.

- Error: 1367 SQLSTATE: 22007 (ER_ILLEGAL_VALUE_FOR_TYPE)
Message : Illegal %s '%s' value found during parsing.

- Error: 1368 SQLSTATE: HY000 (ER_VIEW_NONUPD_CHECK)
Message : CHECK OPTION on non-updatable view '%s.%s'.

- Error: 1369 SQLSTATE: HY000 (ER_VIEW_CHECK_FAILED)
Message : CHECK OPTION failed '%s.%s'.

- Error: 1370 SQLSTATE: 42000 (ER_PROCACCESS_DENIED_ERROR)
Message : %s command denied to user '%s'@'%s' for routine '%s'.

- Error: 1371 SQLSTATE: HY000 (ER_RELAY_LOG_FAIL)
Message : Failed purging old relay logs: %s.

- Error: 1372 SQLSTATE: HY000 (ER_PASSWD_LENGTH)
Message : Password hash should be a %d-digit hexadecimal number.

- Error: 1373 SQLSTATE: HY000 (ER_UNKNOWN_TARGET_BINLOG)
Message : Target log not found in binlog index.

- Error: 1374 SQLSTATE: HY000 (ER_IO_ERR_LOG_INDEX_READ)
Message : I/O error reading log index file.

- Error: 1375 SQLSTATE: HY000 (ER_BINLOG_PURGE_PROHIBITED)
Message : Server configuration does not permit binlog purge.

- Error: 1376 SQLSTATE: HY000 (ER_FSEEK_FAIL)
Message : Failed on fseek().

- Error: 1377 SQLSTATE: HY000 (ER_BINLOG_PURGE_FATAL_ERR)
Message : Fatal error during log purge.

- Error: 1378 SQLSTATE: HY000 (ER_LOG_IN_USE)
Message : A purgeable log is in use, will not purge.

- Error: 1379 SQLSTATE: HY000 (ER_LOG_PURGE_UNKNOWN_ERR)
Message : Unknown error during log purge.

- Error: 1380 SQLSTATE: HY000 (ER_RELAY_LOG_INIT)
Message : Failed initializing relay log position: %s.

- Error: 1381 SQLSTATE: HY000 (ER_NO_BINARY_LOGGING)
Message : You are not using binary logging.

- Error: 1382 SQLSTATE: HY000 (ER_RESERVED_SYNTAX)
Message : The '%s' syntax is reserved for purposes internal to the MySQL server.

- Error: 1383 SQLSTATE: HY000 (ER_WSAS_FAILED)
Message : WSAStartup Failed.

- Error: 1384 SQLSTATE: HY000 (ER_DIFF_GROUPS_PROC)
Message : Can't handle procedures with different groups yet.

- Error: 1385 SQLSTATE: HY000 (ER_NO_GROUP_FOR_PROC)
Message : Select must have a group with this procedure.

- Error: 1386 SQLSTATE: HY000 (ER_ORDER_WITH_PROC)
Message : Can't use ORDER clause with this procedure.

- Error: 1387 SQLSTATE: HY000 (ER_LOGGING_PROHIBIT_CHANGING_OF)
Message : Binary logging and replication forbid changing the global server %s.

- Error: 1388 SQLSTATE: HY000 (ER_NO_FILE_MAPPING)
Message : Can't map file: %s, errno: %d.

- Error: 1389 SQLSTATE: HY000 (ER_WRONG_MAGIC)
Message : Wrong magic in %s.

- Error: 1390 SQLSTATE: HY000 (ER_PS_MANY_PARAM)
Message : Prepared statement contains too many placeholders.

- Error: 1391 SQLSTATE: HY000 (ER_KEY_PART_0)
Message : Key part '%s' length cannot be 0.

- Error: 1392 SQLSTATE: HY000 (ER_VIEW_CHECKSUM)
Message : View text checksum failed.

- Error: 1393 SQLSTATE: HY000 (ER_VIEW_MULTIUPDATE)
Message : Can not modify more than one base table through a join view '%s.%s'.

- Error: 1394 SQLSTATE: HY000 (ER_VIEW_NO_INSERT_FIELD_LIST)
Message : Can not insert into join view '%s.%s' without fields list.

- Error: 1395 SQLSTATE: HY000 (ER_VIEW_DELETE_MERGE_VIEW)
Message : Can not delete from join view '%s.%s'.

- Error: 1396 SQLSTATE: HY000 (ER_CANNOT_USER)
Message : Operation %s failed for %s.

- Error: 1397 SQLSTATE: XAE04 (ER_XAER_NOTA)
Message : XAER_NOTA: Unknown XID.

- Error: 1398 SQLSTATE: XAE05 (ER_XAER_INVAL)
Message : XAER_INVAL: Invalid arguments (or unsupported command).

- Error: 1399 SQLSTATE: XAE07 (ER_XAER_RMFAIL)
Message : XAER_RMFAIL: The command cannot be executed when global transaction is in the %s state.

- Error: 1400 SQLSTATE: XAE09 (ER_XAER_OUTSIDE)
Message : XAER_OUTSIDE: Some work is done outside global transaction.

- Error: 1401 SQLSTATE: XAE03 (ER_XAER_RMERR)
Message : XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency.

- Error: 1402 SQLSTATE: XA100 (ER_XA_RBROLLBACK)
Message : XA_RBROLLBACK: Transaction branch was rolled back.

- Error: 1403 SQLSTATE: 42000 (ER_NONEXISTING_PROC_GRANT)
Message : There is no such grant defined for user '%s' on host '%s' on routine '%s'.

- Error: 1404 SQLSTATE: HY000 (ER_PROC_AUTO_GRANT_FAIL)
Message : Failed to grant EXECUTE and ALTER ROUTINE privileges.

- Error: 1405 SQLSTATE: HY000 (ER_PROC_AUTO_REVOKE_FAIL)
Message : Failed to revoke all privileges to dropped routine.

- Error: 1406 SQLSTATE: 22001 (ER_DATA_TOO_LONG)
Message : Data too long for column '%s' at row %ld.

- Error: 1407 SQLSTATE: 42000 (ER_SP_BAD_SQLSTATE)
Message : Bad SQLSTATE: '%s'.

- Error: 1408 SQLSTATE: HY000 (ER_STARTUP)
Message : %s: ready for connections. Version: '%s' socket: '%s' port: %d %s.

- Error: 1409 SQLSTATE: HY000 (ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR)
Message : Can't load value from file with fixed size rows to variable.

- Error: 1410 SQLSTATE: 42000 (ER_CANT_CREATE_USER_WITH_GRANT)
Message : You are not allowed to create a user with GRANT.

- Error: 1411 SQLSTATE: HY000 (ER_WRONG_VALUE_FOR_TYPE)
Message : Incorrect %s value: '%s' for function %s.

- Error: 1412 SQLSTATE: HY000 (ER_TABLE_DEF_CHANGED)
Message : Table definition has changed, please retry transaction.

- Error: 1413 SQLSTATE: 42000 (ER_SP_DUP_HANDLER)
Message : Duplicate handler declared in the same block.

- Error: 1414 SQLSTATE: 42000 (ER_SP_NOT_VAR_ARG)
Message : OUT or INOUT argument %d for routine %s is not a variable.

- Error: 1415 SQLSTATE: 0A000 (ER_SP_NO_RETSET)
Message : Not allowed to return a result set from a %s.

- Error: 1416 SQLSTATE: 22003 (ER_CANT_CREATE_GEOMETRY_OBJECT)
Message : Cannot get geometry object from data you send to the GEOMETRY field.

- Error: 1417 SQLSTATE: HY000 (ER_FAILED_ROUTINE_BREAK_BINLOG)
Message : A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes.

- Error: 1418 SQLSTATE: HY000 (ER_BINLOG_UNSAFE_ROUTINE)
Message : This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable).

- Error: 1419 SQLSTATE: HY000 (ER_BINLOG_CREATE_ROUTINE_NEED_SUPER)
Message : You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable).

- Error: 1420 SQLSTATE: HY000 (ER_EXEC_STMT_WITH_OPEN_CURSOR)
Message : You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it..

- Error: 1421 SQLSTATE: HY000 (ER_STMT_HAS_NO_OPEN_CURSOR)
Message : The statement (%lu) has no open cursor..

- Error: 1422 SQLSTATE: HY000 (ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG)
Message : Explicit or implicit commit is not allowed in stored function or trigger..

- Error: 1423 SQLSTATE: HY000 (ER_NO_DEFAULT_FOR_VIEW_FIELD)
Message : Field of view '%s.%s' underlying table doesn't have a default value.

- Error: 1424 SQLSTATE: HY000 (ER_SP_NO_RECURSION)
Message : Recursive stored functions and triggers are not allowed..

- Error: 1425 SQLSTATE: 42000 (ER_TOO_BIG_SCALE)
Message : Too big scale %d specified for column '%s'. Maximum is %d..

- Error: 1426 SQLSTATE: 42000 (ER_TOO_BIG_PRECISION)
Message : Too big precision %d specified for column '%s'. Maximum is %d..

- Error: 1427 SQLSTATE: 42000 (ER_M_BIGGER_THAN_D)
Message : For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%s')..

- Error: 1428 SQLSTATE: HY000 (ER_WRONG_LOCK_OF_SYSTEM_TABLE)
Message : You can't combine write-locking of system '%s.%s' table with other tables.

- Error: 1429 SQLSTATE: HY000 (ER_CONNECT_TO_FOREIGN_DATA_SOURCE)
Message : Unable to connect to foreign data source: %s.

- Error: 1430 SQLSTATE: HY000 (ER_QUERY_ON_FOREIGN_DATA_SOURCE)
Message : There was a problem processing the query on the foreign data source. Data source error: %-.64.

- Error: 1431 SQLSTATE: HY000 (ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST)
Message : The foreign data source you are trying to reference does not exist. Data source error: %s.

- Error: 1432 SQLSTATE: HY000 (ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE)
Message : Can't create federated table. The data source connection string '%s' is not in the correct format.

- Error: 1433 SQLSTATE: HY000 (ER_FOREIGN_DATA_STRING_INVALID)
Message : The data source connection string '%s' is not in the correct format.

- Error: 1434 SQLSTATE: HY000 (ER_CANT_CREATE_FEDERATED_TABLE)
Message : Can't create federated table. Foreign data src error: %s.

- Error: 1435 SQLSTATE: HY000 (ER_TRG_IN_WRONG_SCHEMA)
Message : Trigger in wrong schema.

- Error: 1436 SQLSTATE: HY000 (ER_STACK_OVERRUN_NEED_MORE)
Message : Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack..

- Error: 1437 SQLSTATE: 42000 (ER_TOO_LONG_BODY)
Message : Routine body for '%s' is too long.

- Error: 1438 SQLSTATE: HY000 (ER_WARN_CANT_DROP_DEFAULT_KEYCACHE)
Message : Cannot drop default keycache.

- Error: 1439 SQLSTATE: 42000 (ER_TOO_BIG_DISPLAYWIDTH)
Message : Display width out of range for column '%s' (max = %d).

- Error: 1440 SQLSTATE: XAE08 (ER_XAER_DUPID)
Message : XAER_DUPID: The XID already exists.

- Error: 1441 SQLSTATE: 22008 (ER_DATETIME_FUNCTION_OVERFLOW)
Message : Datetime function: %s field overflow.

- Error: 1442 SQLSTATE: HY000 (ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG)
Message : Can't update table '%s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger..

- Error: 1443 SQLSTATE: HY000 (ER_VIEW_PREVENT_UPDATE)
Message : The definition of table '%s' prevents operation %s on table '%s'..

- Error: 1444 SQLSTATE: HY000 (ER_PS_NO_RECURSION)
Message : The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner.

- Error: 1445 SQLSTATE: HY000 (ER_SP_CANT_SET_AUTOCOMMIT)
Message : Not allowed to set autocommit from a stored function or trigger.

- Error: 1446 SQLSTATE: HY000 (ER_MALFORMED_DEFINER)
Message : Definer is not fully qualified.

- Error: 1447 SQLSTATE: HY000 (ER_VIEW_FRM_NO_USER)
Message : View '%s'.'%s' has no definer information (old table format). Current user is used as definer. Please recreate the view!.

- Error: 1448 SQLSTATE: HY000 (ER_VIEW_OTHER_USER)
Message : You need the SUPER privilege for creation view with '%s'@'%s' definer.

- Error: 1449 SQLSTATE: HY000 (ER_NO_SUCH_USER)
Message : There is no '%s'@'%s' registered.

- Error: 1450 SQLSTATE: HY000 (ER_FORBID_SCHEMA_CHANGE)
Message : Changing schema from '%s' to '%s' is not allowed..

- Error: 1451 SQLSTATE: 23000 (ER_ROW_IS_REFERENCED_2)
Message : Cannot delete or update a parent row: a foreign key constraint fails (%s).

- Error: 1452 SQLSTATE: 23000 (ER_NO_REFERENCED_ROW_2)
Message : Cannot add or update a child row: a foreign key constraint fails (%s).

- Error: 1453 SQLSTATE: 42000 (ER_SP_BAD_VAR_SHADOW)
Message : Variable '%s' must be quoted with `...`, or renamed.

- Error: 1454 SQLSTATE: HY000 (ER_TRG_NO_DEFINER)
Message : No definer attribute for trigger '%s'.'%s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger..

- Error: 1455 SQLSTATE: HY000 (ER_OLD_FILE_FORMAT)
Message : '%s' has an old format, you should re-create the '%s' object(s).

- Error: 1456 SQLSTATE: HY000 (ER_SP_RECURSION_LIMIT)
Message : Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %s.

- Error: 1457 SQLSTATE: HY000 (ER_SP_PROC_TABLE_CORRUPT)
Message : Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d).

- Error: 1458 SQLSTATE: 42000 (ER_SP_WRONG_NAME)
Message : Incorrect routine name '%s'.

Les informations d'erreur client sont issues des fichiers suivants :

- Les valeurs d'erreur et les symboles entre parenthèses correspondent aux définitions dans le fichier include/errmsg.h MySQL.

- La valeur du correspond au message d'erreur listé dans le fichier libmysql/errmsg.c. %d et %s représentent des nombres ou des chaînes qui seront remplacées dans les messages lorsqu'elles seront affichées.

Comme les mises à jour sont fréquentes, il est possible que ces fichiers contiennent des erreurs qui ne sont pas listées ici.

- Error: 2000 (CR_UNKNOWN_ERROR)
Message : Unknown MySQL error.

- Error: 2001 (CR_SOCKET_CREATE_ERROR)
Message : Can't create UNIX socket (%d).

- Error: 2002 (CR_CONNECTION_ERROR)
Message : Can't connect to local MySQL server through socket '%s' (%d).

- Error: 2003 (CR_CONN_HOST_ERROR)
Message : Can't connect to MySQL server on '%s' (%d).

- Error: 2004 (CR_IPSOCK_ERROR)
Message : Can't create TCP/IP socket (%d).

- Error: 2005 (CR_UNKNOWN_HOST)
Message : Unknown MySQL server host '%s' (%d).

- Error: 2006 (CR_SERVER_GONE_ERROR)
Message : MySQL server has gone away.

- Error: 2007 (CR_VERSION_ERROR)
Message : Protocol mismatch; server version = %d, client version = %d.

- Error: 2008 (CR_OUT_OF_MEMORY)
Message : MySQL client ran out of memory.

- Error: 2009 (CR_WRONG_HOST_INFO)
Message : Wrong host info.

- Error: 2010 (CR_LOCALHOST_CONNECTION)
Message : Localhost via UNIX socket.

- Error: 2011 (CR_TCP_CONNECTION)
Message : %s via TCP/IP.

- Error: 2012 (CR_SERVER_HANDSHAKE_ERR)
Message : Error in server handshake.

- Error: 2013 (CR_SERVER_LOST)
Message : Lost connection to MySQL server during query.

- Error: 2014 (CR_COMMANDS_OUT_OF_SYNC)
Message : Commands out of sync; you can't run this command now.

- Error: 2015 (CR_NAMEDPIPE_CONNECTION)
Message : Named pipe: %s.

- Error: 2016 (CR_NAMEDPIPEWAIT_ERROR)
Message : Can't wait for named pipe to host: %s pipe: %s (%lu).

- Error: 2017 (CR_NAMEDPIPEOPEN_ERROR)
Message : Can't open named pipe to host: %s pipe: %s (%lu).

- Error: 2018 (CR_NAMEDPIPESETSTATE_ERROR)
Message : Can't set state of named pipe to host: %s pipe: %s (%lu).

- Error: 2019 (CR_CANT_READ_CHARSET)
Message : Can't initialize character set %s (path: %s).

- Error: 2020 (CR_NET_PACKET_TOO_LARGE)
Message : Got packet bigger than 'max_allowed_packet' bytes.

- Error: 2021 (CR_EMBEDDED_CONNECTION)
Message : Embedded server.

- Error: 2022 (CR_PROBE_SLAVE_STATUS)
Message : Error on SHOW SLAVE STATUS:.

- Error: 2023 (CR_PROBE_SLAVE_HOSTS)
Message : Error on SHOW SLAVE HOSTS:.

- Error: 2024 (CR_PROBE_SLAVE_CONNECT)
Message : Error connecting to slave:.

- Error: 2025 (CR_PROBE_MASTER_CONNECT)
Message : Error connecting to master:.

- Error: 2026 (CR_SSL_CONNECTION_ERROR)
Message : SSL connection error.

- Error: 2027 (CR_MALFORMED_PACKET)
Message : Malformed packet.

- Error: 2028 (CR_WRONG_LICENSE)
Message : This client library is licensed only for use with MySQL servers having '%s' license.

- Error: 2029 (CR_NULL_POINTER)
Message : Invalid use of null pointer.

- Error: 2030 (CR_NO_PREPARE_STMT)
Message : Statement not prepared.

- Error: 2031 (CR_PARAMS_NOT_BOUND)
Message : No data supplied for parameters in prepared statement.

- Error: 2032 (CR_DATA_TRUNCATED)
Message : Data truncated.

- Error: 2033 (CR_NO_PARAMETERS_EXISTS)
Message : No parameters exist in the statement.

- Error: 2034 (CR_INVALID_PARAMETER_NO)
Message : Invalid parameter number.

- Error: 2035 (CR_INVALID_BUFFER_USE)
Message : Can't send long data for non-string/non-binary data types (parameter: %d).

- Error: 2036 (CR_UNSUPPORTED_PARAM_TYPE)
Message : Using unsupported buffer type: %d (parameter: %d).

- Error: 2037 (CR_SHARED_MEMORY_CONNECTION)
Message : Shared memory: %s.

- Error: 2038 (CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR)
Message : Can't open shared memory; client could not create request event (%lu).

- Error: 2039 (CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR)
Message : Can't open shared memory; no answer event received from server (%lu).

- Error: 2040 (CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR)
Message : Can't open shared memory; server could not allocate file mapping (%lu).

- Error: 2041 (CR_SHARED_MEMORY_CONNECT_MAP_ERROR)
Message : Can't open shared memory; server could not get pointer to file mapping (%lu).

- Error: 2042 (CR_SHARED_MEMORY_FILE_MAP_ERROR)
Message : Can't open shared memory; client could not allocate file mapping (%lu).

- Error: 2043 (CR_SHARED_MEMORY_MAP_ERROR)
Message : Can't open shared memory; client could not get pointer to file mapping (%lu).

- Error: 2044 (CR_SHARED_MEMORY_EVENT_ERROR)
Message : Can't open shared memory; client could not create %s event (%lu).

- Error: 2045 (CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR)
Message : Can't open shared memory; no answer from server (%lu).

- Error: 2046 (CR_SHARED_MEMORY_CONNECT_SET_ERROR)
Message : Can't open shared memory; cannot send request event to server (%lu).

- Error: 2047 (CR_CONN_UNKNOW_PROTOCOL)
Message : Wrong or unknown protocol.

- Error: 2048 (CR_INVALID_CONN_HANDLE)
Message : Invalid connection handle.

- Error: 2049 (CR_SECURE_AUTH)
Message : Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled).

- Error: 2050 (CR_FETCH_CANCELED)
Message : Row retrieval was canceled by mysql_stmt_close() call.

- Error: 2051 (CR_NO_DATA)
Message : Attempt to read column without prior row fetch.

- Error: 2052 (CR_NO_STMT_METADATA)
Message : Prepared statement contains no metadata.

- Error: 2053 (CR_NO_RESULT_SET)
Message : Attempt to read a row while there is no result set associated with the statement.

- Error: 2054 (CR_NOT_IMPLEMENTED)
Message : This feature is not implemented yet.

27 - Étendre MySQL

27-A - Rouages de MySQL

Ce chapitre décrit un grand nombre de notions que vous devez connaître lorsque vous travaillez sur le code MySQL. Si vous envisagez de contribuer au développement de MySQL, que vous voulez accéder à du code ultra récent ou que vous souhaitez simplement vous tenir au courant du développement, suivez les instructions de la section Section 2.4.3, « Installer à partir de l'arbre source de développement ». Si vous êtes intéressé par les rouages internes de MySQL, il est recommandé de vous inscrire à notre liste de diffusion interne internals. Cette liste est relativement calme. Pour les détails d'inscription, voyez Section 1.4.1.1, « Les listes de diffusion de MySQL ». Tous les développeurs de MySQL AB sont sur la liste internals et nous aidons ceux qui travaillent sur le code de MySQL. Utilisez cette liste pour poser des questions sur le code, et partagez les correctifs que vous voulez voir intégrer au projet MySQL.

27-A-1 - Threads MySQL

Le serveur MySQL crée les threads suivants :

- le thread de connexion TCP/IP qui gère toutes les demandes de connexion et crée un nouveau thread dédié pour gérer l'identification et le traitement des requêtes SQL, pour chaque connexion ;

- sur Windows NT, il y a un thread appelé gestionnaire de pipe, qui effectue le même travail que le thread de gestion des demandes de connexion, sur les demandes de connexion par pipe ;

- le thread de signal qui gère tous les signaux. Ce thread gère aussi normalement les alertes et les appels à process_alarm() pour forcer les délais d'expiration des connexions qui sont inactives ;

- si mysqld est compilé avec l'option -DUSE_ALARM_THREAD, un thread dédié aux alarmes est créé. Il est uniquement utilisé sur certains systèmes où il y a des problèmes avec la fonction sigwait() ou si vous voulez utiliser la fonction thr_alarm() dans des applications qui n'ont pas de threads dédiés aux signaux ;

- lors de l'utilisation de l'option --flush_time=#, un thread dédié est créé pour vider les tables de la mémoire à intervalle régulier ;

- chaque connexion a son propre thread dédié ;

- chaque table différente sur laquelle des INSERT DELAYED sont pratiquées reçoit un thread ;

- si vous utilisez l'option --master-host, un thread de réplication sera démarré pour lire et appliquer les modifications du maître.

mysqladmin processlist affiche uniquement les threads de connexion, ceux de INSERT DELAYED et ceux de réplication.

27-A-2 - Suite de tests de MySQL

Jusqu'à récemment, notre suite de tests principaux était basée sur des données propriétaires de clients, et pour cette raison, il n'a jamais été publié. Le seul système de test public actuel est notre script crash-me, qui est un script Perl DBI/DBD qui se trouve dans le dossier sql-bench, et divers tests qui font partie du dossier tests. Le manque d'une suite de tests publique et standardisée rend difficiles à nos utilisateurs et nos développeurs les possibilités de tests de régression. Pour corriger ce problème, nous avons créé un nouveau système de tests qui est inclus dans les distributions source et binaire, à partir de la version 3.23.29.

Le jeu de tests actuel ne couvre pas toutes les situations en MySQL, mais il permet d'identifier les bogues les plus courants lors de requêtes SQL, les problèmes de bibliothèques et aussi les problèmes de réplication. Notre but est de lui faire couvrir 100 % du code. Nous apprécions les contributions à notre suite de tests. Vous pouvez notamment fournir des tests qui examinent certaines fonctions critiques de votre système et qui assureront que les futures versions de MySQL les prennent en compte.

27-A-2-a - Exécuter la suite des tests MySQL

Le système de tests est constitué d'un interpréteur de langage de tests (mysqltest), un script Shell qui exécute tous les scripts (mysql-test-run), les cas de tests réels, écrits dans un langage spécial de tests, et leurs résultats attendus. Pour exécuter ces tests sur votre système après une compilation, tapez make test ou mysql-test/mysql-test-run depuis la racine de la distribution. Si vous avez installé une distribution binaire, cd jusqu'au dossier d'installation (par exemple, /usr/local/mysql), et exécutez scripts/mysql-test-run. Tous les tests doivent réussir. Si ce n'est pas le cas, vous devriez essayer de trouver pourquoi et faire un rapport de bogues à MySQL. Voir Section 27.1.2.3, « Rapporter des bogues dans la suite de tests MySQL ».

Si vous avez une copie de mysqld qui fonctionne sur la machine où vous voulez faire des tests, vous n'avez pas à l'arrêter, tant qu'elle n'utilise pas les ports 9306 et 9307. Si l'un de ces ports est pris, vous devriez éditer le script mysql-test-run et changer les valeurs des ports des maîtres et esclaves en les remplaçant par des ports libres.

Vous pouvez exécuter des tests individuels avec mysql-test/mysql-test-run test_name.

Si l'un des tests échoue, vous devriez tester mysql-test-run avec l'option --force pour vérifier si aucun autre test n'échoue.

27-A-2-b - Améliorer la suite de tests MySQL

Vous pouvez utiliser le langage de mysqltest pour écrire vos propres cas de tests. Malheureusement, nous n'avons pas encore écrit une documentation complète pour ce logiciel, et nous prévoyons de le faire rapidement. Vous pouvez, toutefois, utiliser les cas de tests actuels comme exemples. Les points suivants devraient vous mettre le pied à l'étrier.

- Les tests sont situés dans mysql-test/t/*.test.

- Un cas de test est constitué de commandes terminées par un ;, et est similaire aux données d'entrées du client mysql. Une commande est par défaut une commande envoyée au serveur MySQL, à moins qu'il ne soit reconnu comme une commande interne (par exemple, sleep).

- Toutes les requêtes qui produisent des résultats, comme SELECT, SHOW, EXPLAIN, etc., doivent être précédées par @/path/to/result/file. Le fichier contient alors les résultats attendus. Un moyen simple pour générer le résultat du fichier est d'exécuter mysqltest -r < t/test-case-name.test depuis le dossier de tests mysql-test, puis d'éditer le fichier résultant, si nécessaire, pour ajuster le contenu. Dans ce cas, soyez très prudent lors de l'ajout ou la suppression de caractères invisibles : assurez-vous de ne changer que du texte, ou d'effacer des lignes. Vous pouvez utiliser od -c pour vous assurer que votre éditeur n'a pas perturbé le fichier durant l'édition. Bien sûr, nous espérons que vous n'aurez jamais à éditer le résultat du fichier mysqltest -r, car vous n'avez à faire cela que lorsque vous découvrez un bogue.

- Pour être cohérent avec votre configuration, vous devriez placer les fichiers de résultats dans le dossier mysql-test/r et les nommer test_name.result. Si le test produit plus qu'un résultat, vous devez utiliser test_name.a.result, test_name.b.result, etc.

- Si une commande retourne une erreur, vous devez, sur la ligne de la commande, le spécifier avec --error error-number. Le numéro d'erreur peut être une liste d'erreurs possibles, séparées par des virgules ','.

- Si vous écrivez un test de réplication, vous devez, sur la première ligne du fichier de test, ajouter le code source include/master-slave.inc;. Pour passer entre le maître et l'esclave, utilisez connection master; et connection slave;. Si vous avez besoin d'utiliser une connexion alternative, vous pouvez utiliser connection master1; pour le maître, et connection slave1; pour l'esclave.

- Si vous avez besoin d'une boucle, vous pouvez utiliser ceci :

let $1=1000;
while ($1)
{
# votre requête ici
dec $1;
}

- Pour faire une pause entre les requêtes, utilisez la commande sleep. Elle supporte les fractions de seconde, ce qui vous permet d'utiliser sleep 1.3;, pour attendre 1,3 seconde.

- Pour exécuter l'esclave avec des options additionnelles pour votre cas de test, ajoutez-les au format ligne de commande dans mysql-test/t/test_name-slave.opt. Pour le maître, ajoutez-les dans mysql-test/t/test_name-master.opt.

- Si vous avez une question sur la suite de tests, ou que vous avez un test à proposer, envoyez-le par courriel à la liste interne. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ». Comme la liste n'accepte pas les pièces jointes, vous devriez les placer sur le serveur FTP : ftp://support.mysql.com/pub/mysql/Incoming/ [ftp://support.mysql.com/pub/mysql/Incoming/].

27-A-2-c - Rapporter des bogues dans la suite de tests MySQL

Si votre version de MySQL ne passe pas un test, vous devez faire ceci :

- n'envoyez pas de rapport de bogue avant d'avoir étudié au maximum les raisons possibles de l'échec ! Lorsque vous le faites, utilisez le programme mysqlbug, pour que nous puissions obtenir un maximum d'informations sur votre système et la version de MySQL. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème » ;

- assurez-vous d'inclure le résultat de mysql-test-run, ainsi que le contenu de tous les fichiers .reject du dossier mysql-test/r ;

- si un test de la suite échoue, vérifiez si le test échoue aussi en l'exécutant seul :

cd mysql-test
mysql-test-run --local test-name

Si cela échoue, alors vous devriez configurer MySQL avec --with-debug et exécuter mysql-test-run avec l'option --debug. Si cela échoue aussi, envoyez le fichier de trace var/tmp/master.trace à ftp://support.mysql.com/pub/mysql/secret pour que nous puissions l'examiner. N'oubliez pas d'inclure une description complète de votre système, ainsi que de la version de l'exécutable mysqld, et de sa compilation ;

- essayez d'exécuter mysql-test-run avec l'option --force pour voir s'il n'y a pas d'autres tests qui échouent ;

- si vous avez compilé MySQL vous-même, vérifiez notre manuel, ainsi que les notes de compilation pour votre plate-forme, ou bien, utilisez à la place un des exécutables que nous avons compilés pour vous, disponibles à http://www.mysql.com/downloads/. Toutes nos versions exécutables doivent passer la suite de tests ;

- si vous obtenez une erreur, comme Result length mismatch ou Result content mismatch, cela signifie que le résultat de la suite de tests n'a pas la taille attendue. Cela peut être un bogue de MySQL, ou que votre version de MySQL fournit un résultat d'une autre taille, dans certaines circonstances.
Les résultats de test qui ont échoué sont placés dans un fichier avec le même nom de base que le fichier de test, et avec l'extension .reject. Si votre test échoue, faites un diff sur les deux fichiers. Si vous ne pouvez pas voir où ils diffèrent, examinez ces deux fichiers avec od -c, et vérifiez leur taille respective ;

- si un test échoue totalement, vous devriez vérifier les fichiers de log dans le dossier mysql-test/var/log, pour avoir des indices sur ce qui a échoué ;

- si vous avez compilé MySQL avec le débogage, vous pouvez essayer de le déboguer en exécutant mysql-test-run avec --gdb et/ou --debug. Voir Section D.1.2, « Créer un fichier de traçage ».
Si vous n'avez pas compilé MySQL pour le débogage, vous devriez essayer de le faire. Spécifiez simplement l'option --with-debug dans le script de configure ! Voir Section 2.4, « Installation de MySQL avec une distribution source ».

27-B - Ajouter des fonctions à MySQL

Il y a deux méthodes pour ajouter des fonctions à MySQL :

- vous pouvez ajouter la fonction grâce à l'interface de fonctions utilisateur (UDF). Les fonctions utilisateur sont ajoutées et supprimées dynamiquement avec les commandes CREATE FUNCTION et DROP FUNCTION. Voir Section 27.2.2, « Syntaxe de CREATE FUNCTION/DROP FUNCTION » ;

- vous pouvez ajouter une fonction sous la forme native (intégrée) d'une fonction MySQL. Les fonctions natives sont compilées dans mysqld et sont disponibles en permanence.

Chaque méthode a ses avantages et inconvénients :

- si vous écrivez une fonction utilisateur, vous devez installer le fichier objet en plus du serveur lui-même. Si vous compilez votre fonction dans le serveur, vous n'avez pas ce problème ;

- vous pouvez ajouter des UDF à une distribution binaire de MySQL. Les fonctions natives requièrent une modification de la distribution source ;

- si vous mettez à jour votre distribution MySQL, vous pouvez continuer à utiliser vos fonctions précédemment installées. Pour les fonctions natives, vous devez refaire les modifications du code à chaque mise à jour.

Quelle que soit la méthode que vous utilisez pour ajouter de nouvelles fonctions, ces fonctions pourront être utilisées comme des fonctions natives telles que ABS() ou SOUNDEX().

27-B-1 - Fonctionnalités des fonctions utilisateur

L'interface MySQL pour créer des fonctions utilisateur fournit les fonctionnalités et capacités suivantes :

- les fonctions peuvent retourner des chaînes, des entiers ou des nombres décimaux ;

- vous pouvez définir des fonctions simples qui travaillent sur une ligne à la fois, ou bien des fonctions d'agrégation, qui travaillent sur plusieurs lignes à la fois ;

- des informations fournies aux fonctions pour qu'elles puissent vérifier le nombre et le type des arguments qui leur sont passés ;

- vous pouvez demander à MySQL de forcer certains arguments à certains types avant de les transmettre à votre fonction ;

- vous pouvez indiquer qu'une fonction retourne NULL ou qu'une erreur est survenue.

27-B-2 - Syntaxe de CREATE FUNCTION/DROP FUNCTION

CREATE [AGGREGATE] FUNCTION nom_fonction RETURNS {STRING|REAL|INTEGER}
SONAME nom_librairie_partagée

DROP FUNCTION nom_fonction

Une fonction définie par un utilisateur (UDF) est une méthode pour intégrer une fonction qui fonctionne de la même façon qu'une fonction native de MySQL, comme ABS() et CONCAT().

AGGREGATE est une nouvelle option pour MySQL version 3.23. Une fonction AGGREGATE fonctionne exactement comme une fonction native comme SUM ou COUNT().

CREATE FUNCTION enregistre le nom de la fonction, le type, et le nom des bibliothèques partagées dans la table mysql.func. Vous devez avoir les droits INSERT et DELETE dans la base mysql pour créer et supprimer les fonctions.

Toutes les fonctions actives sont rechargées chaque fois que le serveur démarre, sauf si vous démarrez mysqld avec l'option --skip-grant-tables. Dans ce cas, l'utilisation des UDF n'est pas prise en compte et les UDF ne sont pas disponibles. (Une fonction active est une fonction qui peut être chargée avec CREATE FUNCTION et supprimée par REMOVE FUNCTION.)

Concernant l'écriture des UDF, Section 27.2, « Ajouter des fonctions à MySQL ». Pour que le mécanisme des fonctions UDF fonctionne, les fonctions doivent être écrites en C ou C++, votre système doit supporter le chargement dynamique et vous devez avoir compilé mysqld dynamiquement (pas statiquement).

Notez que pour faire fonctionner AGGREGATE, vous devez avoir une table mysql.func qui contient la colonne type. Si ce n'est pas le cas, vous devez exécuter le script mysql_fix_privilege_table pour résoudre ce problème.

27-B-3 - Ajouter une nouvelle fonction définie par l'utilisateur (UDF)

Pour que le mécanisme UDF fonctionne, les fonctions doivent être écrites en C ou C++ et votre système doit supporter le chargement dynamique. Les sources de MySQL incluent un fichier sql/udf_example.cc qui définit 5 nouvelles fonctions. Consultez ce fichier pour voir comment marchent les conventions d'appels des UDF.

Pour que mysqld puisse utiliser les fonctions UDF, vous devez configurer MySQL avec l'option --with-mysqld-ldflags=-rdynamic. La raison est que sur diverses plates-formes, (Linux inclus) vous pouvez charger une bibliothèque dynamique (avec dlopen()) depuis un programme statique lié, que vous pouvez obtenir si vous utilisez l'option --with-mysql-ldflags=-all-static. Si vous voulez utiliser une UDF qui nécessite un accès aux symboles de mysqld (comme l'exemple methaphone dans sql/udf_example.cc qui utilise default_charset_info), vous devez lier le programme avec -rdynamic (voir man dlopen).

Pour chaque fonction que vous voulez utiliser dans SQL, vous devez définir les fonctions correspondantes en C (ou C++). Dans la discussion ci-dessous, le nom « xxx » est utilisé comme un exemple de nom de fonction. Pour faire la différence entre l'usage de SQL et de C/C++, XXX() (majuscules) indique l'appel d'une fonction SQL et xxx() (minuscules) indique l'appel d'une fonction C/C++.

Les fonctions C/C++ que vous écrivez pour l'implémentation de l'interface de XXX() sont :

- xxx() (requis)
La fonction principale. C'est là où le résultat de la fonction est calculé. La correspondance entre le type de SQL et le type retourné par votre fonction C/C++ est affichée ci-dessous :

SQL type

C/C++ type

STRING

char *

INTEGER

long long

REAL

double

- xxx_init() (optionnel)
La fonction d'initialisation de xxx(). Elle peut-être utilisée pour :

- vérifier le nombre d'arguments de XXX() ;

- vérifier que les arguments correspondent aux types requis ou indiquer à MySQL de contraindre des arguments aux types que vous voulez quand la fonction principale est appelée ;

- allouer la mémoire requise pour la fonction principale ;

- spécifier la longueur maximale de la sortie ;

- spécifier (pour les fonctions REAL) le nombre maximal de décimales ;

- spécifier si le résultat peut-être NULL.

- xxx_deinit() (optionnel)
La terminaison de la fonction xxx(). Elle doit libérer toute la mémoire allouée par l'initialisation de la fonction.

Quand une requête SQL fait appel à XXX(), MySQL appelle l'initialisation de la fonction xxx_init(), pour laisser exécuter n'importe quelle action exigée, telle que la vérification d'arguments ou l'allocation de mémoire.

Si xxx_init() retourne une erreur, la requête SQL est annulée avec un message d'erreur et la fonction principale et la fonction de terminaison ne sont pas appelées. Autrement, la fonction principale xxx() est appelée une fois pour chaque ligne. Après que toutes les lignes aient été traitées, la fonction de terminaison xxx_deinit() est appelée pour procéder aux nettoyages requis.

Pour les fonctions d'agrégat (comme SUM()), vous pouvez également ajouter les fonctions suivantes.

- xxx_reset() (requise)
Remet la somme à zéro et insère l'argument en tant que valeur initiale pour un nouveau groupe.

- xxx_add() (requise)
Ajoute l'argument à l'ancienne somme.

Quand vous utilisez les UDF d'agrégat, MySQL opère comme suit.

Toutes les fonctions doivent être compatibles avec les threads (et non pas simplement la fonction principale, mais aussi les fonctions d'initialisation et de terminaison). Cela signifie que vous ne pouvez pas allouer de variables globales ou statiques. Si vous avez besoin de mémoire, allouez-la avec la fonction xxx_init() et libérez-la avec xxx_deinit().

1. Appeler xxx_init() pour laisser la fonction d'agrégat allouer la mémoire dont elle aura besoin pour stocker les résultats.

2. Trier la table en accord avec la clause GROUP BY.

3. Pour la première ligne dans un nouveau groupe, appeler la fonction xxx_reset().

4. Pour chaque ligne appartenant à un même groupe, appeler la fonction xxx_add().

5. Quand le groupe change ou lorsque la dernière ligne a été traitée, appeler xxx() pour obtenir le résultat de l'agrégat.

6. Répéter les étapes de 3 à 5 tant que toutes les lignes n'ont pas été traitées.

7. Appeler xxx_deinit() pour libérer la mémoire allouée.

Toutes les fonctions doivent être sûres pour les threads (pas seulement la fonction principale, mais les fonctions d'initialisation et de terminaison également). Cela signifie que vous n'êtes pas autorisé à allouer une variable globale ou statique qui change ! Si vous avez besoin de mémoire, vous devez l'allouer avec la fonction xxx_init() et la libérer avec xxx_deinit().

27-B-3-a - Fonctions utilisateur : appeler des fonctions simples

La fonction principale doit être déclarée comme illustrée ici. Notez que le type de retour et les paramètres diffèrent, suivant que vous voulez déclarer une fonction SQL XXX() qui retournera une STRING, un INTEGER ou un REAL dans la commande CREATE FUNCTION :

Pour les fonctions de chaînes STRING :

char *xxx(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error);

Pour les fonctions d'entiers INTEGER :

long long xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Pour les fonctions de nombres à virgule flottante REAL :

double xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Les fonctions d'initialisation et de terminaison sont déclarées comme ceci :

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

void xxx_deinit(UDF_INIT *initid);

Le paramètre initid est passé aux trois fonctions. Il pointe sur une structure UDF_INIT qui est utilisée pour communiquer des informations entre les fonctions. Les membres de la structure UDF_INIT sont ceux qui sont listés ci-dessous. La fonction d'initialisation doit préparer les membres qu'elle veut, et notamment leur donner une valeur initiale (pour utiliser les valeurs par défaut, laissez le membre intact) :

- my_bool maybe_null
xxx_init() doit remplacer maybe_null par 1 si xxx() peut retourner NULL. La valeur par défaut est 1 si l'un des arguments n'est déclaré comme maybe_null.

- unsigned int decimals
Le nombre de décimales. La valeur par défaut est le nombre maximum de décimales dans l'argument passé à la fonction. Par exemple, vis la fonction reçoit 1.34, 1.345 et 1.3, ce nombre sera 3, car 1.345 a 3 décimales.

- unsigned int max_length
La taille maximale de la chaîne résultat. La valeur par défaut dépend du type de résultat de la fonction. Pour les fonctions de chaînes, la valeur par défaut est la taille du plus grand argument. Pour les fonctions entières, la valeur est de vingt et un chiffres. Pour les fonctions à nombre à virgule flottante, la valeur est de 13, plus le nombre de décimales indiqué par initid->decimals. Pour les fonctions numériques, la taille inclut le signe et le séparateur décimal.
Si vous voulez retourner un BLOB, vous devez donner à ce membre la valeur de 65 ko ou 16 Mo; cet espace mémoire ne sera pas alloué, mais utilisé pour décider quel type de colonne utiliser, s'il y a un besoin de stockage temporaire.

- char *ptr
Un pointeur que la fonction peut utiliser pour ses besoins propres. Par exemple, la fonction peut utiliser initid->ptr pour transférer de la mémoire allouée entre les trois fonctions. En xxx_init(), allouez de la mémoire, et assignez-la à ce pointeur :

initid->ptr = allocated_memory;

En xxx() et xxx_deinit(), utilisez initid->ptr pour exploiter ou supprimer la mémoire.

27-B-3-b - Appeler des fonctions utilisateur pour les groupements

Voici une description des différentes fonctions que vous devez définir pour réaliser des calculs sur des regroupements, avec une fonction utilisateur.

Notez que ce qui suit n'est pas demandé ou utilisé par MySQL 4.1.1. Vous pouvez conserver cette définition pour assurer la compatibilité entre MySQL 4.0 et MySQL 4.1.1.

char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Cette fonction est appelée lorsque MySQL trouve la première ligne dans un nouveau groupe. Dans cette fonction, vous devez remettre à zéro des variables internes de sommaire, puis indiquer le nouvel argument comme premier membre du nouveau groupe.

Dans de nombreuses situations, cela se fait en interne en remettant à zéro toutes les variables, et en appelant xxx_add().

Cette fonction n'est demandée que par MySQL 4.1.1 et plus récents :

char *xxx_clear(UDF_INIT *initid, char *is_null, char *error);

Cette fonction est appelée à chaque fois qu'une ligne qui appartient à un groupe est trouvée, hormis la première ligne. Durant cette fonction, vous devez ajouter les données dans votre variable interne de sommaire.

Vous pouvez utiliser le pointeur error pour stocker un octet si quelque chose n'a pas fonctionné.

char *xxx_add(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);

Cette fonction est appelée pour toutes les lignes du même groupe, hormis pour la première ligne. Dans cette dernière, vous devez ajouter la valeur dans UDF_ARGS pour vos variables internes.

La fonction xxx() doit être déclarée de manière identique à celle d'une fonction utilisateur simple. Voir Section 27.2.3.1, « Fonctions utilisateur : appeler des fonctions simples ».

Cette fonction est appelée lorsque toutes les lignes d'un groupe ont été traitées. Vous ne devez normalement pas accéder à la variable args ici, mais retourner votre valeur, à partir des valeurs du sommaire interne.

Tous les traitements des arguments de xxx_reset() et xxx_add() doivent être faits d'une manière similaire à celle des fonctions UDF normales. Voir Section 27.2.3.3, « Traitement des arguments ».

La gestion de la valeur retournée par xxx() doit être identique à celle d'une fonction utilisateur classique. Voir Section 27.2.3.4, « Valeurs de retour et gestion d'erreurs. ».

Le pointeur argument de is_null et error sont les mêmes pour tous les appels de xxx_reset(), xxx_add() et xxx(). Vous pouvez utiliser ces valeurs pour vous rappeler si vous avez rencontré une erreur, ou si la fonction xxx() doit retourner NULL. Notez que vous ne devez pas stocker de chaîne dans *error! C'est un conteneur d'un seul octet !

is_null est remis à zéro pour chaque (avant d'appeler xxx_reset(). error n'est jamais remis à zéro.

Si isnull ou error sont modifiés après xxx(), alors MySQL va retourner NULL comme résultat de la fonction de groupement.

27-B-3-c - Traitement des arguments

Le paramètre args pointe sur une structure UDF_ARGS qui dispose des membres suivants.

- unsigned int arg_count
Le nombre d'arguments. Vérifiez cette valeur dans la fonction d'initialisation, si vous voulez que votre fonction soit appelée avec un nombre particulier d'arguments. Par exemple :

if (args->arg_count != 2)
{
strcpy(message,"XXX() requires two arguments");
return 1;
}

- enum Item_result *arg_type
Le type de chaque argument. Les valeurs possibles pour chaque type sont STRING_RESULT, INT_RESULT et REAL_RESULT.
Pour s'assurer que les arguments sont d'un type donné, et retourner une erreur dans le cas contraire, vérifiez le tableau arg_type durant la fonction d'initialisation. Par exemple :

if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != INT_RESULT)
{
strcpy(message,"XXX() requires a string and an integer");
return 1;
}

Comme alternative à l'imposition d'un type particulier pour les arguments des fonctions, vous pouvez utiliser la fonction pour qu'elle modifie le type des arguments et donne aux valeurs de arg_type le type que vous souhaitez. Cela fait que MYSQL va forcer les arguments à un type donné, pour chaque appel de la fonction xxx(). Par exemple, pour forcer le type des deux premiers arguments en chaîne et entier, vous pouvez utiliser la fonction d'initialisation xxx_init() :

args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;

- char **args
args->args communique les informations à la fonction d'initialisation, ainsi que la nature des arguments avec lesquels elle a été appelée. Pour un argument constant i, args->args[i] pointe sur la valeur de l'argument. Voir plus bas pour les instructions d'accès à cette valeur. Pour les valeurs non constantes, args->args[i] vaut 0. Un argument constant est une expression qui utilise des constantes, comme 3 ou 4*7-2 ou SIN(3.14). Un argument non constant est une expression qui fait référence aux valeurs qui peuvent changer de ligne en ligne, par exemple des noms de colonnes ou des fonctions qui sont appelées avec des arguments non constants.
Pour chaque invocation de la fonction principale, args->args contient les arguments réels qui sont passés à la ligne qui sera traitée.
Les fonctions peuvent faire référence à un argument i comme ceci :

- un argument de type STRING_RESULT est donné sous la forme d'un pointeur de chaîne, plus une longueur, pour permettre la gestion des données binaires ou des données de taille arbitraire. Le contenu des chaînes est disponible avec l'expression args->args[i] et la taille de la chaîne est args->lengths[i]. Ne supposez pas que les chaînes sont terminées par le caractère nul ;

- pour un argument de type INT_RESULT, vous devez transtyper la valeur args->args[i] en valeur long long :

long long int_val;
int_val = *((long long*) args->args[i]);

- pour un argument de type REAL_RESULT, vous devez transtyper la valeur args->args[i] en valeur double :

double    real_val;
real_val = *((double*) args->args[i]);

- unsigned long *lengths
Pour une fonction d'initialisation, le tableau lengths indique la taille maximale des chaînes pour chaque argument. Vous ne devez pas les modifier. Pour chaque appel de la fonction principale, lengths contient la taille réelle de toutes les chaînes arguments qui sont passées pour la ligne traitée. Pour les arguments de type INT_RESULT ou REAL_RESULT, lengths contient toujours la taille maximale de l'argument (comme pour la fonction d'initialisation).

27-B-3-d - Valeurs de retour et gestion d'erreurs

La fonction d'initialisation doit retourner 0 si aucune erreur ne s'est produite et 1 sinon. Si une erreur s'est produite, xxx_init() doit stocker un message se terminant par un NULL dans le paramètre message. Le message sera retourné au client. La taille du tampon du message est de MYSQL_ERRMSG_SIZE caractères, mais vous devez essayer de garder une taille de message inférieure à 80 caractères, sinon, il remplit la largeur d'un écran de terminal standard.

La valeur de retour de la fonction principale xxx() est la valeur de la fonction, pour les fonctions long long et double. Une fonction de chaîne de caractères doit retourner un pointeur vers le résultat et stocker la taille de la chaîne de caractères dans l'argument length.

Affectez cette valeur au contenu et à la longueur de la valeur retournée. Par exemple :

memcpy(result, "chaîne retournée", 16);
*length = 16;

Le tampon result qui est passé à la fonction a une taille de 255 bits. Si votre résultat dépasse ceci, ne vous inquiétez pas de l'allocation de mémoire pour ce résultat.

Si votre fonction de chaînes de caractères a besoin de retourner une chaîne de caractères plus grande que 255 bits, vous devez allouer de l'espace pour cela avec malloc() dans votre fonction xxx_init(). Vous pouvez stocker la mémoire allouée dans le tampon ptr de la structure UDF_INIT pour être réutilisée par les appels futurs de xxx(). Voir Section 27.2.3.1, « Fonctions utilisateur : appeler des fonctions simples ».

Pour indiquer une valeur de retour NULL dans la fonction principale, mettez is_null à 1 :

*is_null = 1;

Pour indiquer une erreur retournée dans la fonction principale, mettez le paramètre error à 1:

*error = 1;

Si xxx() met *error à 1 pour chaque ligne, la valeur de la fonction est NULL pour la ligne en question et pour chaque ligne suivante traitée par le processus dans lequel XXX() est invoqué. (xxx() ne sera même pas appelé pour les lignes suivantes).

Remarque : dans les versions antérieures à 3.22.10, vous devez définir *error et *is_null :

*error = 1;
*is_null = 1;

27-B-3-e - Compiler et installer des fonctions utilisateur

Les fichiers qui implémentent des fonctions utilisateur doivent être compilés et installés sur le même hôte que celui du serveur. Ce processus est décrit plus bas, avec le fichier udf_example.cc qui est inclus dans les sources MySQL. Ce fichier contient les fonctions suivantes :

- metaphon() retourne la version métaphon de la chaîne en argument. C'est une technique proche du soundex, mais elle est bien plus optimisée pour l'anglais ;

- myfunc_double() retourne la moyenne des codes ASCII des caractères de la chaîne passée en argument ;

- myfunc_int() retourne la somme de tailles des arguments ;

- sequence([const int]) retourne une séquence, commençant à partir du nombre choisi ou 1, si aucun nombre n'a été fourni ;

- lookup() retourne l'adresse IP numérique d'un hôte ;

- reverse_lookup() retourne le nom d'hôte pour une adresse IP. Cette fonction peut être appelée avec une chaîne au format "xxx.xxx.xxx.xxx" ou quatre nombres.

Un fichier dynamiquement chargé doit être compilé sous la forme d'un objet partagé, grâce à une commande comme celle-ci :

shell> gcc -shared -o udf_example.so myfunc.cc

Vous pouvez facilement trouver les options correctes pour la compilation en exécutant cette commande dans le dossier sql de votre installation source :

shell> make udf_example.o

Vous devez exécuter une commande de compilation similaire à celle que le make affiche, sauf que vous devrez supprimer l'option -c près de la fin de la ligne, et ajouter -o udf_example.so à la fin de la ligne. Sur certains systèmes, vous devrez aussi supprimer -c de la commande).

Une fois que vous compilez un objet partagé contenant des fonctions utilisateur, vous devez les installer, et prévenir le serveur MYSQL. Compiler un objet partagé avec udf_example.cc produit un fichier qui s'appelle udf_example.so (le nom exact peut varier suivant la plate-forme). Copiez ce fichier dans l'un des dossiers utilisé par ld, tel que /usr/lib. Par exemple, /etc/ld.so.conf.

Sur de nombreux systèmes, vous pouvez faire pointer la variable d'environnement LD_LIBRARY ou LD_LIBRARY_PATH vers le dossier où vous avez vos fichiers de fonctions. Le manuel de dlopen vous indiquera quelle variable utiliser sur votre système. Vous devriez indiquer cette valeur dans les options de démarrage de mysql.server et safe_mysqld, et redémarrer mysqld.

Après que la bibliothèque a été installée, indiquez à mysqld ces nouvelles fonctions avec ces commandes :

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup
->        RETURNS STRING SONAME "udf_example.so";
mysql> CREATE AGGREGATE FUNCTION avgcost
->        RETURNS REAL SONAME "udf_example.so";

Les fonctions peuvent être effacées plus tard avec DROP FUNCTION:

mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
mysql> DROP FUNCTION avgcost;

Les commandes CREATE FUNCTION et DROP FUNCTION modifient la table système func dans la base mysql. Le nom de la fonction, son type et le nom de la bibliothèque partagée sont alors sauvés dans la table. Vous devez avoir les droits de INSERT et DELETE dans la base mysql pour ajouter et effacer des fonctions.

Vous ne devez pas utiliser la commande CREATE FUNCTION pour ajouter une fonction qui a déjà été créée. Si vous devez réinstaller une fonction, vous devez la supprimer avec la commande DROP FUNCTION puis la réinstaller avec CREATE FUNCTION. Vous devrez faire cela, par exemple, si vous recompilez une nouvelle version de votre fonction, pour que mysqld utilise cette nouvelle version. Sinon, le serveur va continuer à utiliser l'ancienne version.

Les fonctions actives sont rechargées à chaque fois que le serveur démarre, à moins que vous ne démarriez le serveur mysqld avec l'option --skip-grant-tables. Dans ce cas, l'initialisation des fonctions utilisateur est ignorée, et ces fonctions sont inutilisables. Une fonction active doit avoir été créée avec CREATE FUNCTION et pas supprimée avec DROP FUNCTION.

27-B-3-f - Précautions à prendre avec les fonctions utilisateur

MySQL prend les mesures suivantes pour éviter une utilisation abusive des fonctions utilisateur.

Vous devez avoir les droits de INSERT pour être capable d'utiliser la commande CREATE FUNCTION et le droit de DELETE pour être capable d'effacer une fonction (DROP FUNCTION. Ceci est nécessaire, car ces commandes ajoutent et suppriment des lignes dans la table mysql.func.

UDF doit avoir au moins un symbole défini, en plus du symbole xxx qui correspond à la fonction principale xxx(). Ces symboles auxiliaires correspondent aux fonctions xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear() et xxx_add(). Depuis MySQL 4.0.24, 4.1.10a et 5.0.3, mysqld supporte l'option --allow-suspicious-udfs qui spécifie si les UDF qui n'ont qu'une fonction xxx peuvent être chargées. Par défaut, cette fonction est désactivée, ce qui empêche les fonctions de charger des fonctions depuis des objets partagés autres que les UDF légales. Si vous avez de vieilles fonctions UDF qui contiennent uniquement le symbole xxx qui ne peuvent pas être recompilées pour utiliser un symbole auxiliaire, il sera nécessaire d'utiliser l'option --allow-suspicious-udfs. Sinon, vous devrez vous passer de cette fonctionnalité.

Les fichiers d'objet UDF ne peuvent pas être placés dans n'importe quel dossier. Ils doivent être placés dans un dossier système que le compilateur dynamique peut analyser. Pour assurer le fonctionnement de cette restriction, et éviter les attaques par spécification de chemins arbitraires en dehors de ceux que le compilateur dynamique peut atteindre, MySQL vérifie dans le nom de l'objet partagé spécifié dans la commande CREATE FUNCTION la présence de délimiteurs de dossiers. Depuis MySQL 4.0.24, 4.1.10a et 5.0.3, MySQL vérifie aussi les délimiteurs de fichiers stockés dans la table mysql.func lorsque vous chargez les fonctions. Cela évite les tentatives de spécifications de chemins interdits, en manipulant directement les tables mysql.func. Pour plus de détails sur les UDF et le compilateur dynamique, voyez Section 27.2.3.5, « Compiler et installer des fonctions utilisateur ».

27-B-4 - Ajouter de nouvelles fonctions natives

La procédure pour ajouter une nouvelle fonction native est décrite ici. Notez que vous ne pouvez ajouter de fonctions natives à une distribution binaire, car la procédure implique la modification du code source de MySQL. Vous devez compiler MySQL vous-même à partir d'une distribution des sources. Notez aussi que si vous migrez vers une autre version de MySQL (par exemple, quand une nouvelle version est réalisée), vous devrez répéter la procédure avec la nouvelle version.

Pour ajouter une nouvelle fonction native à MySQL, suivez les étapes suivantes :

1. Ajoutez une ligne dans lex.h qui définit le nom de la fonction dans le tableau sql_functions[] ;

2. Si le prototype de la fonction est simple (elle prend zéro, un, deux ou trois arguments), vous devez spécifier dans lex.h SYM(FUNC_ARG#) (où # est le nombre d'arguments) en tant que second argument dans le tableau sql_functions[] et ajouter une fonction qui crée un objet fonction dans item_create.cc. Regardez "ABS" et create_funcs_abs() pour un exemple.
Si le prototype de la fonction est compliqué (par exemple, elle prend un nombre variable d'arguments), vous devez ajouter deux lignes à sql_yacc.yy. Une qui indique le symbole préprocesseur que yacc doit définir (cela doit être ajouté au début du fichier). Puis définir les paramètres de la fonction et un « item » avec ces paramètres à la règle simple_expr. Pour un exemple, vérifiez toutes les occurrences de ATAN dans sql_yacc.yy pour voir comment cela se fait ;

3. Dans item_func.h, déclarez une classe héritant de Item_num_func ou de Item_str_func, selon que votre fonction retourne un nombre ou une chaîne ;

4. Dans le fichier item_func.cc, ajoutez l'une des déclarations suivantes, selon que vous définissez une fonction numérique ou de chaîne de caractères :

double   Item_func_newname::val()
longlong Item_func_newname::val_int()
String  *Item_func_newname::Str(String *str)

Si vous héritez votre objet de l'un des éléments standard (comme Item_num_func) vous n'aurez probablement qu'à définir l'une des fonctions décrites ci-dessus et laisser l'objet parent prendre soin des autres fonctions. Par exemple, la classe Item_str_func définit une fonction val() qui exécute atof() sur la valeur retournée par ::str() ;

5. Vous devez aussi probablement définir la fonction objet suivante :

void Item_func_newname::fix_length_and_dec()

Cette fonction doit au moins calculer max_length en se basant sur les arguments donnés. max_length est le nombre maximal de caractères que la fonction peut retourner. Cette fonction doit aussi définir maybe_null = 0 si la fonction principale ne peut pas retourner une valeur NULL. La fonction peut vérifier si l'un de ses arguments peut retourner NULL en vérifiant la variable maybe_null des arguments. Vous pouvez regarder Item_func_mod::fix_length_and_dec pour avoir un exemple concret.

Toutes les fonctions doivent être sûres pour les threads (en d'autres termes, n'utilisez aucune variable statique ou globale dans la fonction sans les protéger avec mutex).

Si vous voulez retourner NULL, à partir de ::val(), ::val_int() ou ::str() vous devez mettre null_value à 1 et retourner 0.

Pour les fonctions de l'objet ::str(), il y a d'autres considérations à prendre en compte :

- l'argument String *str fournit un tampon de chaîne qui peut être utilisé pour contenir le résultat. (Pour plus d'informations à propos du type String, regardez le fichier sql_string.h) ;

- la fonction ::str() doit retourner la chaîne contenant le résultat ou (char*) 0 si celui-ci est NULL ;

- aucune des fonctions de chaînes n'essaye d'allouer de mémoire tant que ce n'est pas nécessaire !

27-C - Ajouter une nouvelle procédure à MySQL

Avec MySQL, vous pouvez définir une procédure en C++ qui accède et modifie les données dans la requête avant que celle-ci ne soit envoyée au client. La modification peut être faite ligne par ligne ou au niveau de GROUP BY.

Nous avons créé une procédure d'exemple avec la version 3.23 de MySQL pour vous montrer comment cela fonctionne.

De plus, nous vous recommandons de jeter un œil à mylua. Avec cela, vous pouvez utiliser le langage LUA pour charger dynamiquement une procédure dans mysqld.

27-C-1 - La procédure Analyse

analyse([max elements,[max memory]])

Cette procédure est définie dans le fichier sql/sql_analyse.cc. Elle examine les résultats de vos requêtes et en retourne une analyse :

- max elements (256 par défaut) est le nombre maximal de valeurs distinctes que analyse retiendra par colonne. C'est utilisé par analyse pour vérifier si le type optimal de la colonne ne serait pas le type ENUM ;

- max memory (8192 par défaut) est le maximum de mémoire que analyse doit allouer par colonne quand elle essaye de trouver toutes les valeurs distinctes.

SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])

27-C-2 - Écrire une procédure

Pour le moment, la seule documentation à ce sujet est constituée par les sources.

Vous pourrez trouver toutes les informations sur les procédures en examinant les fichiers suivants :

- sql/sql_analyse.cc ;

- sql/procedure.h ;

- sql/procedure.cc ;

- sql/sql_select.cc.

28 - Problèmes et erreurs communs

Ce chapitre liste quelques problèmes et erreurs communs que les utilisateurs rencontreront. Vous apprendrez à déterminer d'où vient le problème et comment le résoudre. Vous trouverez aussi les solutions appropriées à quelques problèmes communs.

28-A - Comment déterminer ce qui pose problème

Lorsque vous faite face à un problème, la première chose à faire est de trouver quel programme / pièce de l'équipement pose ce problème :

- si vous avez l'un des symptômes suivants : (mémoire, carte mère, processeur, ou disque dur) ou un problème de noyau (kernel) :

- le clavier ne fonctionne pas. Cela peut être vérifié en pressant la touche de verrouillage des majuscules. Si la lumière des majuscules ne s'allume pas, vous devez remplacer votre clavier. (Avant de le faire, redémarrez votre ordinateur après avoir vérifié les câbles du clavier.),

- le curseur de la souris ne bouge pas,

- la machine ne répond pas à un ping externe,

- d'autres programmes ne fonctionnent pas correctement,

- votre système a redémarré sans que vous vous y attendiez (un programme corrompu appartenant à un utilisateur ne devrait jamais être capable de couper votre système) ;

Dans ce cas, vous devez commencer par vérifier tous vos câbles et démarrer quelques outils de diagnostic pour vérifier votre matériel ! Vous devez aussi regarder s'il existe des patches, mises à jour, ou packs de services pour votre système d'exploitation qui pourraient résoudre votre problème. Vérifiez aussi que vos bibliothèques (comme glibc) sont à jour.

Il est toujours bon d'utiliser une machine avec de la mémoire ECC pour découvrir les problèmes de mémoire assez tôt !

- Si votre clavier est bloqué, vous pouvez réparer cela en vous identifiant sur votre machine à partir d'une autre machine et en exécutant kbd_mode -a.

- Examinez votre fichier de log système (/var/log/messages ou similaire) pour connaître les raisons de vos problèmes. Si vous pensez que le problème vient de MySQL, vous devez aussi examiner les fichiers de log de MySQL. Voir Section 5.9.3, « Le log de modification ».

- Si vous ne pensez pas avoir de problèmes au niveau du matériel, vous devez trouver quel programme pose problème : essayez en utilisant top, ps, taskmanager, ou des programmes similaires, pour voir quel programme utilise trop de ressources ou bloque la machine.Vérifiez avec top, df, ou un programme similaire si vous n'avez plus de mémoire, d'espace disque, trop de fichiers ouverts ou un problème avec une autre ressource critique.

- Si le problème vient d'un processus, vous pouvez toujours essayer de le terminer. S'il ne veut pas se terminer, c'est probablement un bogue du système d'exploitation.

Si après tout cela, vous pensez encore que le problème vient du serveur MySQL ou du client MySQL, il est temps de préparer un rapport de bogue pour notre liste de diffusion ou notre équipe de support. Dans ce rapport, essayez de donner la description la plus détaillée possible du comportement du système et de ce que vous pensez qu'il se passe. Vous devez aussi mentionner pourquoi pensez-vous que le problème vient de MySQL. Prenez en considération toutes les situations décrites dans ce chapitre. Décrivez les problèmes exactement comme ils surviennent sur votre système. Utilisez la méthode « copier/coller » pour les affichages et les messages d'erreurs provenant des programmes ou des fichiers de log.

Essayez de décrire en détail quel est le programme qui ne fonctionne pas et tous les symptômes que vous voyez ! Nous avons déjà reçu beaucoup de rapports de bogue qui disaient juste « le système ne marche pas ». Cela ne nous fournit aucune information à propos du problème.

Si un programme échoue, il est toujours utile de savoir :

- est-ce que le programme en question a causé une erreur de segmentation (core dump) ?

- est-ce que le programme consomme toutes les ressources processeur ? Vérifiez avec top. Laissez le programme fonctionner un bout de temps, il se peut qu'il soit entrain de traiter une tâche lourde ;

- si c'est le serveur mysqld qui pose problème, pouvez-vous essayer un mysqladmin -u root ping ou mysqladmin -u root processlist ?

- que dit un programme client (essayez avec mysql, par exemple) quand vous essayez de vous connecter au serveur MySQL ? Le programme se bloque-t-il ? Obtenez-vous un retour quelconque ?

Lors de l'envoi d'un rapport de bogue, vous devez respecter les règles définies dans ce manuel. Voir Section 1.4.1.2, « Poser des questions ou rapporter un bogue ».

28-B - Erreurs communes rencontrées avec MySQL

Cette section couvre les erreurs les plus fréquemment rencontrées par les utilisateurs. Vous trouverez ici une description de ces erreurs et un moyen de les corriger.

28-B-1 - Erreur Access denied

Une erreur Access denied peut avoir de nombreuses causes. Souvent, le problème est relié aux comptes MySQL sur le serveur, qui autorisent la connexion des clients. Voir Section 5.5.8, « Causes des erreurs Access denied ». Voir Section 5.5.2, « Comment fonctionne le système de droits ».

28-B-2 - Erreur Can't connect to [local] MySQL server

Un client MySQL sous Unix peut se connecter au serveur mysqld de deux façons différentes : sockets Unix, qui se connectent via un fichier du système de fichiers (/tmp/mysqld.sock par défaut) ou TCP/IP, qui se connecte via un port. Les sockets Unix sont plus rapides que TCP/IP mais ne peuvent être utilisées que pour des connexions locales. Les sockets sont utilisées si vous ne spécifiez pas de nom d'hôte ou si vous spécifiez le nom d'hôte spécial localhost.

Sur Windows, si le serveur mysqld tourne sur 9x/Me, vous ne pouvez vous connecter qu'avec TCP/IP. Si le serveur tourne sur NT/2000/XP et que mysqld a été démarré avec l'option --enable-named-pipe, vous pouvez aussi vous connecter avec un tunnel nommé. Son nom est MySQL. Si vous ne spécifiez pas un nom d'hôte lors de la connexion à mysqld, un client MySQL essayera d'abord de se connecter au tunnel nommé et, si cela ne marche pas, il se connectera au port TCP/IP. Vous pouvez forcer l'utilisation des tunnels nommés sous Windows en utilisant . en tant que nom d'hôte.

L'erreur (2002) Can't connect to... signifie généralement qu'il n'y a aucun serveur MySQL qui tourne sur la machine ou que vous utilisez un mauvais fichier de socket, ou un port erroné quand vous essayez de vous connecter au serveur mysqld.

Commencez par vérifier (en utilisant ps ou le gestionnaire de tâches sous Windows) qu'il y a un processus nommé mysqld sur votre serveur ! S'il n'y en a aucun, vous devrez en démarrer un. Voir Section 2.5.2.3, « Problèmes de démarrage du serveur MySQL ».

Si un processus mysqld est actif, vous pouvez tester le serveur avec l'une des connexions suivantes (le port et le chemin vers la socket peuvent être différents chez vous, bien sûr) :

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip de votre hôte' version
shell> mysqladmin --socket=/tmp/mysql.sock version

Notez l'utilisation des guillemets obliques plutôt que les simples avec la commande hostname ; cela provoque la substitution de hostname par la valeur courante du nom d'hôte de la machine dans la commande mysqladmin.

Voilà quelques raisons pouvant entraîner l'erreur Can't connect to local MySQL server :

- mysqld ne fonctionne pas ;

- vous utilisez un système qui emploie les pthreads MIT. Si vous utilisez un système qui n'a pas le support natif des threads, mysqld utilise le paquet MIT-pthreads. Voir Section 2.1.1, « Systèmes d'exploitation supportés par MySQL ». Toutefois, toutes les versions de MIT-pthreads ne supportent pas les sockets Unix. Sur un système qui ne supporte pas les sockets, vous devez toujours spécifier le nom d'hôte explicitement lors de la connexion au serveur. Utilisez cette commande :

shell> mysqladmin -h `hostname` version

pour vérifier la connexion au serveur ;

- quelqu'un a effacé le fichier de socket Unix que mysqld utilise (/tmp/mysqld.sock par défaut). Vous avez peut-être une tâche cron qui efface la socket MySQL (par exemple, une tâche qui supprime les anciens fichiers du dossier /tmp). Vous pouvez toujours exécuter mysqladmin version et vérifier que la socket que mysqladmin tente d'utiliser existe vraiment. La solution dans ce cas est de modifier la tâche cron pour qu'elle n'efface plus mysqld.sock ou de placer la socket ailleurs. Voir Section A.4.5, « Comment protéger ou changer le fichier socket /tmp/mysql.sock » ;

- vous avez démarré mysqld avec l'option --socket=/chemin/vers/socket. Si vous changez le chemin vers la socket, vous devez aussi en notifier les clients. Vous pouvez le faire en fournissant le chemin vers la socket en argument au client. Voir Section A.4.5, « Comment protéger ou changer le fichier socket /tmp/mysql.sock » ;

- vous utilisez Linux et un thread s'est terminé (core dumped). Dans ce cas, vous devez aussi terminer les autres threads mysqld (par exemple, avec le script mysql_zap avant de pouvoir démarrer un nouveau serveur MySQL. Voir Section A.4.2, « Que faire si MySQL plante constamment ? » ;

- vous n'avez peut-être pas les privilèges de lecture et écriture sur le dossier contenant la socket ou sur la socket elle-même. Dans ce cas, vous devez changer les droits sur ce dossier / fichier ou redémarrer mysqld pour qu'il prenne en compte un dossier auquel vous avec accès.

Si vous obtenez l'erreur Can't connect to MySQL server on un_hôte, vous pouvez essayer ce qui suit pour trouver le problème :

- vérifiez que le serveur fonctionne en faisant telnet votre-nom-d-hôte port-tcp-ip et pressez la touche Enter plusieurs fois. Si il y a un serveur MySQL qui tourne sur ce port, vous devriez obtenir une réponse contenant le numéro de version du serveur. Si vous obtenez une erreur proche de telnet: Unable to connect to remote host: Connection refused, c'est qu'il n'y a pas de serveur tournant sur le port donné ;

- essayez de vous connecter au démon mysqld sur la machine locale et vérifiez le port TCP/IP de la configuration de mysqld (variable port) avec mysqladmin variables ;

- vérifiez que votre serveur mysqld n'est pas configuré avec l'option --skip-networking.

28-B-3 - Erreur Client does not support authentication protocol

MySQL 4.1 utilise un protocole d'identification basé sur un algorithme de hachage, qui est incompatible avec celui des anciens clients. Si vous passez d'une ancienne version en version 4.1, et que vous essayez de vous connecter au serveur avec un vieux client, vous allez rencontrer ce message d'erreur :

shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

Pour résoudre ce problème, vous devez :

- passer tous les programmes clients en version 4.1.1, ou plus récent ;

- utiliser un compte qui a un ancien mot de passe, lorsque vous vous connectez avec un client pre-4.1 ;

- remettre un mot de passe ancien format pour les clients pre-4.1 :
ceci est fait avec la commande SET PASSWORD et la fonction OLD_PASSWORD() :

mysql> SET PASSWORD FOR
-> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

- alternativement, utilisez UPDATE et FLUSH PRIVILEGES :

mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd')
-> WHERE Host = 'some_host' AND User = 'some_user';
mysql> FLUSH PRIVILEGES;

- dire au serveur qu'il doit utiliser l'ancien algorithme de hachage :

1. Démarrez mysqld avec -old-passwords,

2. Donnez un mot de passe à tous les utilisateurs qui ont un hash long de mot de passe. Vous pouvez les trouver comme ceci :

SELECT * FROM mysql.user WHERE LENGTH(password) > 16;

Pour plus d'information sur l'identification et le hachage, voyez Section 5.5.9, «hachagede mots de passe en MySQL 4.1 ».

28-B-4 - Échec de saisie du mot de passe avec le client interactif

Les clients MySQL demandent le mot de passe en ligne de commande lorsque l'option --password ou -p n'a pas de valeur :

shell> mysql -u user_name -p
Enter password:

Sur certains systèmes, vous vous apercevrez que votre mot de passe fonctionne lorsqu'il est spécifié dans un fichier de configuration, ou bien en ligne de commande, mais pas interactivement, lorsque l'invite Enter password: est proposée. Cela survient lorsque la bibliothèque système limite la taille des mots de passe à huit caractères (généralement). C'est un problème lié à la bibliothèque système, et non à MySQL. Pour pallier ce problème, changez votre mot de passe MySQL pour qu'il fasse huit caractères ou moins, ou bien placez votre mot de passe dans votre fichier d'options.

28-B-5 - Erreur Host '...' is blocked

Si vous obtenez cette erreur :

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

cela veut dire que mysqld a reçu trop de tentatives de connexions (max_connect_errors) à l'hôte 'hostname' qui ont été interrompues en plein milieu. Après max_connect_errors requêtes échouées, mysqld pense qu'il se passe quelque chose de mauvais (comme une attaque de la part d'un pirate), et bloque le serveur pour les prochaines connexions jusqu'à ce que quelqu'un exécute la commande mysqladmin flush-hosts. Voir Section 5.2.3, « Variables serveur système ».

Par défaut, mysqld bloque le serveur après dix connexions erronées. Vous pouvez facilement changer ce comportement en démarrant le serveur avec ces arguments :

shell> safe_mysqld -O max_connect_errors=10000 &

Notez que si vous recevez ce message pour un hôte en particulier, vous devriez vous assurer qu'il n'y a pas de problèmes de connexions TCP/IP depuis cet hôte. Si vos connexions TCP/IP ne marchent pas, il ne servira à rien d'augmenter la valeur de la variable max_connect_errors !!

28-B-6 - Erreur Too many connections

Si vous obtenez l'erreur Too many connections en essayant de vous connecter à MySQL, cela signifie qu'il y a déjà max_connections clients connectés au serveur mysqld.

Si vous avez besoin de plus de connexions que par défaut (100), vous devez redémarrer mysqld avec une plus grande valeur pour la variable max_connections.

Notez que mysqld permet actuellement à (max_connections+1) clients de se connecter. La dernière connexion est réservée à l'utilisateur ayant le privilège SUPER. En ne donnant pas ce privilège aux utilisateurs normaux (ils ne devraient pas en avoir besoin), un administrateur avec ce privilège peut se connecter et utiliser SHOW PROCESSLIST pour trouver ce qui pose problème. Voir Section 13.5.3, « Syntaxe de SHOW ».

Le nombre maximal de connexions MySQL dépend de la qualité de la bibliothèque des threads sur une plate-forme donnée. Linux et Solaris devraient être capables de supporter jusqu'à 500-1000 connexions simultanées, cela dépend évidemment de la quantité de RAM que vous avez et de ce que font les clients.

28-B-7 - Erreur Out of memory

Si vous lancez une requête et que vous obtenez l'erreur suivante :

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory

notez que cette erreur parle du client MySQL client mysql. La raison de cette erreur est simplement que le client n'a pas la mémoire suffisante pour stocker le résultat en entier.

Pour remédier à ce problème, vérifiez d'abord que votre requête est correcte. Est-ce normal qu'elle retourne autant de lignes ? Si oui, vous pouvez utiliser mysql --quick, qui utilise mysql_use_result() pour récupérer les résultats. Cela sollicitera moins le client (mais plus le serveur).

28-B-8 - Erreur MySQL server has gone away

Cette section couvre aussi l'erreur Lost connection to server during query.

Le plus souvent, l'erreur MySQL server has gone away se produit lorsque le serveur a dépassé le délai d'attente d'actions et a clos la connexion. Par défaut, le serveur clos la connexion après huit heures si rien n'est arrivé. Vous pouvez changer cette limite en configurant le paramètre wait_timeout lorsque vous démarrez mysqld.

Une autre raison de recevoir l'erreur MySQL server has gone away, est d'avoir émis un « close » sur votre connexion, puis d'avoir essayé d'actionner une autre commande alors que la connexion était close.

Si vous avez un script, vous n'avez qu'à lancer la requête à nouveau pour que le client se reconnecte automatiquement.

Vous obtiendrez normalement les codes erreurs suivants dans ce cas (qui est indépendant du système d'exploitation) :

Code erreur

Description

CR_SERVER_GONE_ERROR

Le client ne peut envoyer de commandes au serveur.

CR_SERVER_LOST

Le client n'a pas obtenu d'erreur en contactant le serveur, mais n'a pas obtenu de réponse complète à la question posée.

Par défaut, le serveur ferme la connexion après huit heures si rien ne se passe durant ce temps. Vous pouvez modifier la limite de temps en changeant la variable wait_timeout lorsque vous lancez mysqld. Voir Section 5.2.3, « Variables serveur système ».

Si vous avez un script, il suffit d'émettre une nouvelle requête pour que le client se reconnecte automatiquement.

Vous obtiendrez aussi cette erreur si quelqu'un à terminé le processus avec kill#idprocessus#.

Vous pouvez vérifier si le serveur MySQL est encore en marche en exécutant mysqladmin version et en examinant la date de mise en route. Si le problème est que mysqld a planté, vous devriez vous concentrer sur la résolution du problème. Vous devez dans ce cas commencer par vérifier si émettre la même requête fera à nouveau planter MySQL. Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

Vous pouvez aussi obtenir ces erreurs si vous envoyez une requête incorrecte ou trop grande au serveur. Si mysqld reçoit un paquet trop large ou mal ordonné, il suppose que quelque chose s'est mal passé au niveau du client et ferme la connexion. Si vous avez besoin de grande requêtes (par exemple, si vous travaillez avec de grandes colonnes BLOB) vous pouvez augmenter la taille limite des requêtes en démarrant mysqld avec l'option -O max_allowed_packet=# (1 Mo par défaut). Le surplus de mémoire est alloué à la demande, ce qui fait que mysqld n'utilisera de la mémoire que lorsque vous émettrez une grande requête ou qu'il aura à retourner de grandes réponses ! Plus d'informations sur la configuration de la taille des paquets sont disponibles dans la section Section A.2.9, « Erreur Packet too large ».

Si vous voulez rapporter un bogue concernant ce problème, merci d'inclure les informations suivantes :

- MySQL a-t-il planté ? Vous pouvez le savoir en regardant le fichier hostname.err. Voir Section A.4.2, « Que faire si MySQL plante constamment ? » ;

- si une requête spécifique fait planter mysqld et que les tables concernées ont bien été vérifiées avec CHECK TABLE avant l'exécution, pouvez-vous faire une batterie de tests ? Voir Section D.1.6, « Faire une batterie de tests lorsque vous faites face à un problème de table corrompue » ;

- quelle est la valeur de la variable wait_timeout dans le serveur MySQL ? mysqladmin variables vous donnera une réponse ;

- avez-vous essayé de démarrer mysqld avec --log et vérifié si la requête apparaît bien dans le log ?

Voir Section 1.4.1.2, « Poser des questions ou rapporter un bogue ».

28-B-9 - Erreur Packet too large

Lorsqu'un client MySQL ou le serveur mysqld reçoit un paquet plus grand que max_allowed_packet octets, il provoque une erreur Packet too large et ferme la connexion.

En MySQL 3.23, le plus gros paquet possible est 16 Mo (à cause des limites du protocole client/serveur). En MySQL 4.0.1 et plus, cela n'est plus limité que par la quantité de mémoire que vous avez sur votre serveur (cela va théoriquement à un maximum de 2 Go).

Un paquet de communication est une simple commande SQL envoyée au serveur, ou une simple ligne renvoyée au client.

Lorsqu'un client MySQL ou que le serveur mysqld reçoit un paquet plus grand que max_allowed_packet octets, il provoque une erreur Packet too large et ferme la connexion. Avec quelques clients, vous pouvez aussi obtenir l'erreur Lost connection to MySQL server during query, si le paquet est trop grand.

Notez que le client et le serveur ont chacun leur propre variable max_allowed_packet. Si vous voulez gérer les gros paquets, vous devrez changer cette variable côté client et côté serveur.

Si utilisez le client mysql, la variable max_allowed_packet vaut par défaut 16 Mo. C'est aussi la valeur maximale avant MySQL 4.0. Pour lui donner une valeur maximale plus grande, depuis 4.0, lancez mysql comme ceci :

mysql> mysql --max_allowed_packet=32M

Cela fixe une taille de paquet à 32 Mo.

La valeur par défaut de max_allowed_packet est 1 Mo. Vous pouvez augmenter cette valeur si le serveur doit gérer de grosses requêtes (par exemple, si vous travaillez avec de grandes colonnes BLOB). Par exemple, pour modifier la variable en lui donnant une valeur de 16 Mo, lancez le serveur comme ceci :

mysql> mysqld --max_allowed_packet=16M

Avant MySQL 4.0

mysql> mysqld --set-variable=max_allowed_packet=16M

Vous pouvez aussi utiliser le fichier d'options pour spécifier la valeur de max_allowed_packet. Par exemple, pour spécifier une valeur de 16 Mo, ajoutez la ligne suivante dans le fichier d'options :

[mysqld]
max_allowed_packet=16M

Avant MySQL 4.0

[mysqld]
set-variable = max_allowed_packet=16M

Il n'est pas dangereux d'augmenter cette valeur étant donné que la mémoire n'est allouée que lorsque besoin en est. Cette variable est plus une précaution pour capturer les paquets erronés qui circulent entre le client et le serveur. Elle sert aussi a vous assurer que vous n'utilisez pas accidentellement de gros paquets qui consommeront toute la mémoire.

Si vous utilisez le client mysql, vous pouvez spécifier un plus grand tampon en démarrant le client avec mysql --set-variable=max_allowed_packet=8M. Les autres clients ont différentes méthodes pour configurer cette variable. Notez que --set-variable est désapprouvée depuis MySQL 4.0, utilisez --max-allowed-packet=8M à la place.

Vous pouvez utiliser le fichier d'options pour augmenter la taille de max_allowed_packet dans mysqld. Par exemple, si vous vous attendez à stocker la totalité d'un MEDIUMBLOB dans une table, vous aurez besoin de démarrer le serveur avec l'option set-variable=max_allowed_packet=16M.

Vous pouvez aussi rencontrer d'étranges problèmes avec les gros paquets si vous utilisez les grands blob, mais que vous n'avez pas donné à mysqld l'accès à assez de mémoire pour gérer ces requêtes. Si vous pensez être dans ce cas, essayez d'ajouter ulimit -d 256000 au début du script safe_mysqld et redémarrez mysqld.

28-B-10 - Erreurs de communication / Connexion annulée

À partir de MySQL 3.23.40 vous n'obtenez l'erreur Aborted connection que si vous démarrez mysqld avec --warnings.

Si vous trouvez des erreurs comme celle qui suit dans vos logs d'erreurs :

010301 14:38:23  Aborted connection 854 to db: 'users' user: 'josh'

Voir Section 5.9.1, « Le log d'erreurs ».

Cela signifie qu'un problème est survenu :

- le programme client n'a pas appelé mysql_close() avant de quitter ;

- le client a été inactif plus de wait_timeout ou interactive_timeout secondes sans aucune requête. Voir Section 5.2.3, « Variables serveur système » ;

- l'exécution du programme client s'est terminée soudainement au milieu d'un transfert.

Lorsque ce qui précède arrive, la variable Aborted_clients est incrémentée.

La variable serveur Aborted_connects est incrémentée lorsque :

- un paquet de connexion ne contient pas la bonne information ;

- l'utilisateur n'avait pas les droits d'accès à la base de données ;

- l'utilisateur a utilisé un mot de passe erroné ;

- il a fallu plus de connect_timeout secondes pour obtenir un paquet de communication. Voir Section 5.2.3, « Variables serveur système ».

Notez que ce qui précède peut indiquer que quelqu'un essaye de s'introduire dans votre base de données !

Autres raisons pour les problèmes de clients échoués / connexions interrompues :

- l'utilisation du protocole Ethernet sous Linux, que le Duplex soit intégral (Full-Duplex) ou partiel (Half Duplex). La plupart des pilotes Ethernet de Linux ont ce bogue que vous pouvez tester en transférant un énorme fichier via FTP d'une machine à l'autre. Si le transfert est saccadé (succession de transfert-pause/transfert-pause) alors vous vivez le syndrome du duplex de Linux. La seule solution est de changer le mode de Duplex sur les deux cartes réseau et Hub/Switch en duplex partiel ou duplex intégral et de faire des tests pour connaître la meilleure configuration ;

- quelques problèmes avec la bibliothèque de threads qui causent des interruptions de lectures ;

- mauvaise configuration TCP/IP ;

- les câbles, concentrateurs ou commutateurs Ethernet défectueux. On peut le diagnostiquer aisément en remplaçant le matériel ;

- max_allowed_packet est trop petit ou les requêtes ont besoin de plus de mémoire que celle que vous avez alloué à mysqld. Voir Section A.2.9, « Erreur Packet too large ».

28-B-11 - Erreur The table is full

Il y a différents cas où vous pouvez obtenir cette erreur :

- vous utilisez une ancienne version de MySQL (avant 3.23.0) quand une table temporaire en mémoire devient plus grande que tmp_table_size octets. Pour éviter ce problème, vous pouvez utiliser l'option -O tmp_table_size=# pour faire augmenter la taille des tables temporaires à mysqld ou utiliser l'option SQL BIG_TABLES avant d'exécuter la requête qui pose problème. Voir Section 13.5.2.8, « Syntaxe de SET » ;
vous pouvez aussi démarrer mysqld avec l'option --big-tables. Cela revient à utiliser BIG_TABLES pour toutes les requêtes.
Dans la version 3.23 de MySQL, les tables temporaires en mémoire seront automatiquement changées en tables physiques MyISAM après qu'elles ont dépassé tmp_table_size ;

- vous utilisez des tables InnoDB et avez dépassé leur taille. Dans ce cas, la solution est d'augmenter les tailles des tables. Voir Section 15.8, « Ajouter et retirer des données et des logs InnoDB » ;

- vous utilisez des tables ISAM ou MyISAM sur un système d'exploitation qui ne supporte pas les fichiers de plus de 2 Go et vous avez atteint cette limite dans le fichier de données ou d'index. Voir Section 5.2.3, « Variables serveur système » ;

- vous utilisez des tables MyISAM et la taille des données ou de l'index est plus grande que celle que MySQL a alloué aux pointeurs. (Si vous ne spécifiez pas MAX_ROWS à CREATE TABLE MySQL n'allouera que des pointeurs supportant 4 Go de données.)
Vous pouvez obtenir la taille maximale des données / index en faisant :

SHOW TABLE STATUS FROM database LIKE 'nom_de_table';

ou utiliser myisamchk -dv database/nom_de_table.

Si le problème vient de là, vous pouvez le corriger en faisant quelque chose se rapprochant de :

ALTER TABLE nom_de_table MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;

Vous n'avez besoin de spécifier AVG_ROW_LENGTH que pour les tables avec des champs BLOB/TEXT, car dans ce cas, MySQL ne peut optimiser l'espace requis en se basant uniquement sur le nombre de lignes.

28-B-12 - Erreur Can't create/write to file

Si vous obtenez une erreur de ce type pour quelques requêtes :

Can't create/write to file '\\sqla3fe_0.ism'.

cela signifie que MySQL ne peut créer un fichier temporaire pour le jeu de résultats dans le dossier temporaire défini. (L'erreur précédente est typique de Windows, et le message d'erreur Unix est similaire.) La solution est de démarrer mysqld avec l'option --tmpdir=chemin ou d'ajouter à votre fichier d'options., par exemple, pour spécifier le dossier C:\temp :

[mysqld]
tmpdir=C:/temp

Le dossier C:\temp doit exister au préalable. Voir Section 4.3.2, « Fichier d'options my.cnf ».

Vérifiez aussi le code erreur que vous obtenez avec perror. Une autre raison peut être une erreur de disque saturé.

shell> perror 28
Error code  28:  No space left on device

28-B-13 - Erreur du client Commands out of sync

Si vous obtenez l'erreur Commands out of sync; you can't run this command now, le problème vient du fait que vous appelez les fonctions dans le mauvais ordre dans votre code !

Cela peut se produire, par exemple, si vous utilisez mysql_use_result() et essayez d'exécuter une nouvelle requête avant d'avoir appelé mysql_free_result(). Cela peut aussi se produire si vous essayez d'exécuter deux requêtes qui retournent des données dans appeler mysql_use_result() ou mysql_store_result() entre les deux.

28-B-14 - Erreur Ignoring user

Si vous obtenez l'erreur suivante :

Found wrong password for user: 'some_user@some_host'; ignoring user,

cela signifie que mysqld, lors du démarrage ou lorsqu'il a rechargé les tables de permissions, a trouvé une entrée dans la table user avec un mot de passe invalide. De ce fait, l'entrée est tout simplement ignorée par le système de droits.

Causes possibles et solutions pour ce problème :

- vous faites peut-être tourner une nouvelle version de mysqld avec une vielle table user. Vous pouvez vérifier cela en exécutant mysqlshow mysql user pour voir si le champ du mot de passe est plus petit que seize caractères. Si c'est le cas, vous pouvez le corriger en exécutant le script scripts/add_long_password ;

- l'utilisateur a un ancien mot de passe (huit caractères) et vous n'avez pas démarré mysqld avec l'option --old-protocol. Mettez à jour le mot de passe dans la table user ou redémarrez mysqld avec -old-protocol ;

- vous avez spécifié un mot de passe dans la table user sans passer par la fonction PASSWORD(). Utilisez mysql pour mettre à jour l'utilisateur dans la table user avec un nouveau mot de passe. Assurez-vous d'utiliser la fonction PASSWORD() :

mysql> UPDATE user SET password=PASSWORD('votre mot de passe')
->             WHERE user='XXX';

28-B-15 - Erreur Table 'xxx' doesn't exist

Si vous obtenez l'erreur suivante, cela signifie qu'aucune table portant le nom xxx n'existe dans la base de données courante :

Table 'tbl_name' doesn't exist
Can't find file: 'tbl_name' (errno: 2)

Dans certains cas, les tables pourraient exister, mais vous n'utilisez pas les références correctes :

- comme MySQL utilise des dossiers et des fichiers pour stocker les bases de données et les tables, les noms sont sensibles à la casse si le serveur fonctionne sur un système d'exploitation qui est sensible à la casse ;

- même pour les systèmes de fichiers qui ne sont pas sensibles à la casse, comme sur Windows, toutes les références dans une requêtes doivent être faites dans la même casse.

Vous pouvez vérifier les tables disponibles avec la commande SHOW TABLES. Voir Section 13.5.3, « Syntaxe de SHOW ».

28-B-16 - Erreur Can't initialize character set xxx

Si vous obtenez l'erreur suivante :

MySQL Connection Failed: Can't initialize character set xxx

Cela signifie l'une des choses suivantes :

- le jeu de caractères est un jeu multioctets et votre client ne le supporte pas.
Dans ce cas, vous devez recompiler le client avec --with-charset=xxx ou avec --with-extra-charsets=xxx. Voir Section 2.4.2, « Options habituelles de configure ».
Tous les binaires standards de MySQL sont compilés avec --with-extra-character-sets=complex qui active le support de tous les jeux de caractères multioctets. Voir Section 5.8.1, « Le jeu de caractères utilisé pour les données et le stockage » ;

- le jeu de caractères n'est pas compilé dans mysqld et les fichiers de définition du jeu ne sont pas à l'endroit où le client s'y attend.
Dans ce cas, vous avez besoin de :

- recompiler le client avec le support du jeu de caractères. Voir Section 2.4.2, « Options habituelles de configure »,

- spécifier au client où les fichiers de définition du jeu de caractères se situent. Pour beaucoup de clients, vous pouvez le faire avec l'option -character-sets-dir=chemin-vers-dossier-jeu-caractères,

- copier les fichiers de définition du jeu de caractères dans le dossier où le client s'attend à les trouver.

28-B-17 - Fichier non trouvé

Si vous obtenez ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24), ou toute autre erreur avec errno 23 ou errno 24 de la part de MySQL, cela signifie que vous n'avez pas alloué assez de descripteurs de fichiers à MySQL. Vous pouvez utiliser l'utilitaire perror pour obtenir une description de ce que veut dire l'identifiant de l'erreur :

shell> perror 23
File table overflow
shell> perror 24
Too many open files
shell> perror 11
Resource temporarily unavailable

Le problème ici est que mysqld essaye de garder trop de fichiers ouverts en même temps. Vous pouvez soit demander à mysqld de ne pas ouvrir autant de fichiers simultanément ou augmenter le nombre de descripteurs de fichiers alloués à mysqld.

Pour dire à mysqld de garder moins de fichiers ouverts en même temps, vous pouvez rendre le cache de tables plus petit en utilisant l'option -O table_cache=32 de safe_mysqld (la valeur par défaut est 64). Réduire la valeur de max_connections réduira aussi le nombre de fichiers ouverts (90 comme valeur par défaut).

Pour changer le nombre de descripteurs de fichiers alloués à mysqld, vous pouvez utiliser l'option --open-files-limit=# de safe_mysqld ou -O open-files-limit=# de mysqld. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ». La façon la plus facile de faire cela est d'ajouter cette option dans votre fichier d'options. Voir Section 4.3.2, « Fichier d'options my.cnf ». Si vous avec une ancienne version de mysqld qui ne le supporte pas, vous pouvez éditer le script safe_mysqld. Il y a une ligne commentée ulimit -n 256 dans le script. Vous pouvez enlever le caractère '#' pour décommenter cette ligne, et changer le nombre 256 pour affecter le nombre de descripteurs de fichiers alloués à mysqld.

ulimit (et open-files-limit) peuvent augmenter le nombre de descripteurs de fichiers, mais seulement jusqu'à la limite imposée par le système d'exploitation. Il y a aussi une limite 'matérielle' qui ne peut être dépassée que si vous démarrez safe_mysqld ou mysqld en tant que root (souvenez-vous juste que vous devez aussi utiliser l'option --user=... dans ce cas). Si vous avez besoin de repousser les limites du système d'exploitation pour les descripteurs de fichiers disponibles pour chaque processus, consultez la documentation de votre système.

Note : notez que si vous démarrez le Shell tcsh, ulimit ne fonctionnera pas ! tcsh retournera aussi des valeurs incorrectes si vous atteignez la limite courante ! Dans ce cas, vous devez démarrer safe_mysqld avec sh !

28-C - Notes relatives à l'installation

28-C-1 - Problèmes lors de la liaison avec la bibliothèque du client MySQL

Si vous liez votre programme et que vous obtenez des erreurs pour des symboles non référencés qui commencent par mysql_, comme ce qui suit :

/tmp/ccFKsdPa.o: In function 'main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to 'mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to 'mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to 'mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to 'mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to 'mysql_close'

Vous pouvez réparer cela en ajoutant -Ldir_path-lmysqlclient dans votre ligne de liaison. Pour déterminer le dossier correct, utilisez cette commande :

shell> mysql_config --libs

Si vous obtenez une erreur undefined reference pour la fonction uncompress ou compress, ajoutez -lz à la fin de votre ligne de liaison et essayez à nouveau !

Si vous obtenez des erreurs undefined reference pour des fonctions qui devraient exister sur votre système, comme connect, vérifiez la page du manuel pour la fonction en question, pour les bibliothèques que vous devez ajouter à la ligne de liaison !

Si vous obtenez une erreur undefined reference pour des fonctions inexistantes sur votre système, ressemblant à ce qui suit :

mf_format.o(.text+0x201): undefined reference to '__lxstat'

Cela signifie que votre bibliothèque est compilée sur un système qui n'est pas à 100 % compatible avec le vôtre. Dans ce cas, vous devez obtenir la dernière distribution des sources de MySQL et compiler vous-même. Voir Section 2.4, « Installation de MySQL avec une distribution source ».

Si vous essayez de faire fonctionner un programme et que vous obtenez des erreurs pour des symboles non référencés qui commencent par mysql_ ou une erreur disant que la bibliothèque mysqlclient ne peut être trouvée, cela signifie que votre système n'arrive pas à trouver la bibliothèque partagée libmysqlclient.so.

La solution est de dire à votre système de chercher les bibliothèques partagées là où la bibliothèque est située avec l'une des méthodes suivantes :

- ajouter le chemin vers le dossier où se situe libmysqlclient.so dans la variable d'environnement LD_LIBRARY_PATH ;

- ajouter le chemin vers le dossier où se situe libmysqlclient.so dans la variable d'environnement LD_LIBRARY ;

- copiez le fichier libmysqlclient.so à un endroit où votre système le cherche, comme dans le dossier /lib, et mettez à jour les informations de la bibliothèque partagée en exécutant ldconfig.

Un autre moyen de résoudre ce problème est de lier votre programme statiquement, avec -static, ou en effaçant les bibliothèques dynamiques de MySQL avant de lier votre code. Dans le second cas vous devez vous assurer qu'aucun autre programme n'utilise les bibliothèques dynamiques !

28-C-2 - Comment exécuter MySQL comme un utilisateur normal

Le serveur MySQL mysqld peut être démarré par n'importe quel utilisateur. Afin de changer l'utilisateur qui fait tourner mysqld en l'utilisateur Unix nom_utilisateur, vous devez faire ceci :

1. Stoppez le serveur si il fonctionne (utilisez mysqladmin shutdown) ;

2. Changez le propriétaire du dossier et des fichiers de bases pour qu'il soit nom_utilisateur. Il faut que cet utilisateur ait les droits d'écriture et de lecture (vous pourriez avoir à faire cette manipulation en tant que root Unix) :

shell> chown -R nom_utilisateur /path/to/mysql/datadir

Si les dossier ou les fichiers de données de MySQL sont des liens symboliques, vous devez vous assurer de pouvoir suivre ces lignes, et de changer les propriétaires des fichiers et dossiers sur lesquels ils pointent. L'option chown -R de chown peut ne pas suivre les liens symboliques ;

3. Démarrez le serveur avec l'utilisateur nom_utilisateur, ou bien, si vous utilisez MySQL version 3.22 ou plus récent, démarrez mysqld en tant que root Unix, et utilisez l'option --user=nom_utilisateur. mysqld va alors changer automatiquement d'utilisateur pour utiliser nom_utilisateur avant d'accepter les connexions ;

4. Pour démarrer le serveur sous le nom d'utilisateur automatiquement au moment du démarrage du système, ajoutez une ligne user qui spécifie le nom de l'utilisateur et que le groupe de [mysqld] est du même groupe que le fichier d'options /etc/my.cnf ou le fichier d'options my.cnf dans le dossier de données du serveur. Par exemple :

[mysqld]
user=nom_utilisateur

À ce moment, votre processus mysqld doit fonctionner normalement sous le nom de l'utilisateur Unix nom_utilisateur. Une chose n'a pas changé : les droits dans les tables de droits de MySQL. Par défaut, juste après avoir exécuté le script d'installation des tables de droits mysql_install_db, l'utilisateur MySQL root est le seul utilisateur du système avec les droits de créer et de détruire les bases. À moins que vous n'ayez changé ces droits, ils ont toujours cours. Cela ne va pas vous empêcher d'accéder à MySQL en tant que root MySQL, même si vous n'êtes pas connecté en tant que root Unix. Spécifiez simplement l'option -u root au programme client.

Notez qu'accéder à MySQL en tant que root, en fournissant l'option -u root en ligne de commande, n'a rien a voir avec MySQL qui fonctionne avec les droits de root Unix, ou d'un autre utilisateur Unix. Les droits d'accès et les noms d'utilisateurs MySQL sont complètement séparés des noms d'utilisateurs et des mots de passe Unix. Le seul rapport avec les utilisateurs Unix est que, si vous ne fournissez pas l'option -u lorsque vous démarrez votre client, le client va essayer de se connecter à MySQL avec votre nom d'utilisateur Unix.

Si votre serveur Unix n'est pas sécurisé, il est recommandé de donner un mot de passe à l'utilisateur MySQL root dans les tables de droits. Sinon, n'importe quel utilisateur ayant un compte sur cette machine va pouvoir accéder au compte root avec l'option mysql -u root nom_base et faire ce qu'il veut. Voir Section 2.5, « Procédure de postinstallation ».

28-C-3 - Problèmes avec les permissions sur fichiers

Si vous avez des problèmes avec les droits sur fichiers, par exemple, si mysql génère l'erreur suivante lorsque vous créez une table :

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

alors la variable d'environnement UMASK est peut-être mal configurée lorsque mysqld est démarré. La valeur par défaut de umask est 0660. Vous pouvez corriger ce comportement en démarrant safe_mysqld de la façon suivante :

shell> UMASK=384  # = 600 en octal
shell> export UMASK
shell> /chemin/vers/safe_mysqld &

Par défaut, MySQL créera les dossiers des bases de données et de RAID avec 0700 comme type de permissions. Vous pouvez modifier ce comportement en définissant la variable UMASK_DIR. Si vous le faites, les nouveaux dossiers seront créés en combinant UMASK et UMASK_DIR. Par exemple, si vous voulez donner un accès de groupe à tous les nouveaux dossiers, vous pouvez faire :

shell> UMASK_DIR=504  # = 770 en octal
shell> export UMASK_DIR
shell> /chemin/vers/safe_mysqld &

À partir de la version 3.23.25, MySQL suppose que les valeurs de UMASK et UMASK_DIR sont en octal si elles commencent par un zéro.

Voir Annexe E, Variables d'environnement.

28-D - Notes relatives à l'administration

28-D-1 - Comment réinitialiser un mot de passe Root oublié

Si vous n'avez jamais configuré un mot de passe root pour MySQL, le serveur n'en demandera jamais un pour toutes les connexions de cet utilisateur. Il est recommandé de toujours assigner un mot de passe à chaque utilisateur. Voir Section 5.4, « Sécurité générale du serveur ».

Si vous avez configuré un mot de passe pour l'utilisateur root, mais que vous l'avez oublié, vous pouvez en choisir un nouveau en suivant la procédure suivante :

La procédure sous Windows :

1. Identifiez-vous sur le système en tant qu'administrateur ;

2. Stoppez le serveur MySQL s'il fonctionnait. Pour un serveur en fonctionnement en tant que service Windows, il faut aller dans le gestionnaire de services :

Start Menu -> Control Panel -> Administrative Tools -> Services

Puis, trouvez le service MySQL dans la liste et arrêtez-le.

Si votre serveur ne fonctionne pas comme un service, essayer d'utiliser le gestionnaire de tâches pour l'arrêter.

3. Ouvrez une fenêtre de console DOS :

Start Menu -> Run -> cmd

4. Nous supposerons ici que vous avez installé MySQL dans le dossier C:\mysql. Si vous l'avez installé ailleurs, ajustez les commandes ;
À l'invite de commandes, exécutez cette commande :

C:\> C:\mysql\bin\mysqld-nt --skip-grant-tables

Cela va relancer le serveur dans un mode spécial, qui ne vérifie pas les droits dans les tables ;

5. Gardez la première console ouverte, ouvrez-en une seconde et exécutez la commande suivante (une commande par ligne) :

C:\> C:\mysql\bin\mysqladmin -u root
flush-privileges password "newpwd"
C:\> C:\mysql\bin\mysqladmin -u root -p shutdown

Remplacez « newpwd » par le mot de passe root que vous voulez utiliser. La seconde commande va vous demander d'entrer le mot de passe pour identification d'accès. Entrez le mot de passe que vous avez assigné dans la première commande ;

6. Stoppez le serveur MySQL et relancez-le comme d'habitude. Si vous lancez MySQL comme un service, démarrez-le depuis le gestionnaire de services. Si vous le lancez manuellement, utilisez votre commande habituelle ;

7. Vous devriez pouvoir vous connecter en utilisant le nouveau mot de passe.

Dans un environnement Unix, la procédure pour redéfinir le mot de passe root est la suivante :

1. Connectez-vous sur votre système en tant que root Unix, ou avec le compte qui fait tourner le démon mysqldá ;

2. Repérez le fichier .pid qui contient l'identifiant du processus du serveur. Le chemin et le nom exact de ce fichier dépendent de votre distribution, nom de serveur et configuration. Les chemins classiques sont : /var/lib/mysql/, /var/run/mysqld/ et /usr/local/mysql/data/. Généralement, le nom du fichier est suivi de l'extension .pid et commence avec mysqld ou le nom de votre serveur ;
Terminez le serveur mysqld en lui envoyant une commande kill (pas un kill -9), en utilisant le numéro d'identifiant de processus que vous venez de lire dans le fichier .pid.

shell> kill `cat /dossier-donnees-mysql/hote.pid`

Vous devez être l'utilisateur Unix root ou l'utilisateur qui fait tourner mysqld pour pouvoir le faire ;

3. Redémarrez mysqld avec l'option -skip-grant-tables :

shell> mysqld_safe --skip-grant-tables &

4. Choisissez un nouveau mot de passe avec la commande mysqladmin password :

shell> mysqladmin -u root password 'nouveaumotdepasse'

Remplacez « nouveaumotdepasse » avec le mot de passe root que vous souhaitez ;

5. Après cela, vous devriez pouvoir vous connecter avec le nouveau mot de passe.

Alternativement, sur toutes les plates-formes, vous pouvez aussi choisir le nouveau mot de passe en utilisant le client mysql :

1. Stoppez et redémarrez mysqld avec l'option --skip-grant-tables comme décrit plus haut ;

2. Connectez-vous au serveur mysqld avec :

shell> mysql -u root mysql

3. Exécutez la commande suivante dans le client mysql :

mysql> UPDATE user SET Password=PASSWORD('nouveaumotdepasse')
->             WHERE User='root';
mysql> FLUSH PRIVILEGES;

4. Après cela, vous devriez pouvoir vous connecter avec le nouveau mot de passe.

28-D-2 - Que faire si MySQL plante constamment ?

Toutes les versions de MySQL sont testées sur plusieurs plates-formes avant leur publication. Cela ne signifie pas qu'elles sont exemptées de bogues, cela signifie juste que s'il y a des bogues, il y en a très peu et ils sont durs à trouver. Si vous avez un problème, cela nous aidera toujours si vous essayez de trouver d'où vient exactement le plantage système, et vous aurez plus de chances de le voir résolu rapidement.

D'abord, vous devez essayer de trouver si le problème vient du démon mysqld qui se termine, ou s'il est lié à votre client. Vous pouvez savoir depuis combien de temps le serveur mysqld tourne en exécutant mysqladmin version. Si mysqld s'est terminé, vous trouverez sûrement la raison dans le fichier de log d'erreurs. Voir Section 5.9.1, « Le log d'erreurs ».

Sur certains systèmes, vous pouvez trouver dans ce fichier une trace de la pile, au moment où mysqld s'est arrêté, que vous pouvez étudier avec resolve_back_stack. Voir Section D.1.4, « Utilisation d'un traçage de pile mémoire ». Notez que les valeurs des variables écrites dans .err peuvent ne pas être toujours correctes.

Plusieurs plantages de MySQL sont causés par des fichiers de données ou d'index corrompus. MySQL écrira les données sur le disque avec un appel système à write(), après chaque requête et avant d'en notifier le client. (Cela n'est pas vrai si vous utilisez delay_key_write, auquel cas seules les données sont écrites.) Cela signifie que les données sont intègres même si mysqld plante, puisque le système d'exploitation s'assurera que les données non sorties du tampon ne sont pas enregistrées sur le disque. Vous pouvez forcer MySQL à se synchroniser avec le disque après chaque requête en démarrant mysqld avec --flush.

Ce qui précède signifie que normalement, vous ne devriez obtenir de tables corrompues que si :

- quelqu'un ou quelque chose a coupé mysqld, ou la machine au milieu d'une mise à jour ;

- vous avez trouvé un bogue dans mysqld qui le termine au milieu d'une mise à jour ;quelqu'un manipule les fichiers de données ou d'index en dehors de mysqld sans verrouiller proprement les tables ;

- si vous faites tourner plusieurs serveurs mysqld avec les mêmes données sur un système qui ne gère pas bien les verrous de fichiers (normalement gérés par le démon lockd) ou que vous le faites avec --skip-external-locking ;;

- vous avez un fichier de données ou d'index corrompu qui contient des données faussées ce qui amène mysqld à confusion ;

- vous avez trouvé un bogue dans le système de stockage des données. Cela paraît impossible, mais sait-on jamais ? Dans ce cas, essayez de changer le type de fichier pour qu'il soit pris en charge par un autre gestionnaire de bases de données en utilisant ALTER TABLE sur une copie réparée de la table !

Parce qu'il est très difficile de savoir pourquoi quelque chose plante, essayez d'abord de voir si les choses qui marchent pour les autres ne fonctionnent pas chez vous. Merci d'essayer les différentes choses suivantes :

- coupez le démon mysqld avec mysqladmin shutdown, exécutez myisamchk --silent --force */*.MYI sur toutes les tables, et redémarrez le démon mysqld. Cela vous assurera que vous partez d'un bon point de départ. Voir Chapitre 5, Administration du serveur ;

- utilisez mysqld --log et essayez de déterminer à partir des informations du log si une requête spécifique fait planter le serveur. Plus de 95 % de tous les bogues sont liés à une requête spécifique ! Normalement, c'est la dernière requête dans le fichier de log avant que MySQL n'ait redémarré. Voir Section 5.9.2, « Le log général de requêtes ». Si vous pouvez faire planter MySQL à plusieurs reprise avec une requête, même après avoir vérifié toutes les tables avant de l'exécuter, alors vous avez trouvé le bogue et vous devez faire un rapport de bogue pour nous en avertir ! Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème » ;

- essayez d'effectuer une batterie de tests que nous pourrons utiliser pour reproduire le problème. Voir Section D.1.6, « Faire une batterie de tests lorsque vous faites face à un problème de table corrompue » ;

- essayez d'exécuter le test inclus du dossier mysql-test et les benchmarks MySQL. Voir Section 27.1.2, « Suite de test de MySQL ». Ils devraient tester plutôt bien MySQL. Vous pouvez aussi ajouter ce code au benchmarks pour simuler votre application ! Les benchmarks peuvent être trouvés dans le répertoire sql-bench, dans la distribution des sources ou, pour une distribution binaire, dans le répertoire sql-bench de votre dossier d'installation MySQL ;

- essayez fork_test.pl. Il est situé dans le dossier tests de la distribution source ;

- si vous configurez MySQL pour le débogage, il sera plus facile d'obtenir des informations à propos des erreurs possibles si quelque chose se passe mal. Reconfigurez MySQL avec l'option --with-debug ou --with-debug=full de configure puis recompilez. Voir Section D.1, « Déboguer un serveur MySQL » ;

- configurez MySQL pour le débogage incluant peut-être un outil d'allocation de mémoire qui peut trouver quelques erreurs. Il fournit aussi beaucoup d'informations sur ce qui se passe ;

- avez-vous appliqué les derniers patches de votre système d'exploitation ?

- utilisez l'option --skip-external-locking de mysqld. Sur quelques systèmes, le gestionnaire des verrous lockd ne fonctionne pas convenablement ; l'option --skip-external-locking dit à mysqld de ne pas utiliser de verrous externes. (Cela signifie que vous ne pouvez pas faire tourner deux serveurs mysqld sur les mêmes données et que vous devez faire attention si vous utilisez myisamchk, mais il peut être instructif d'essayer cette option comme test.) ;

- avez-vous essayé mysqladmin -u root processlist lorsque mysqld semble fonctionner mais ne répond plus ? Quelquefois, mysqld n'est pas comateux, même si vous le croyez. Le problème peut-être que toutes les connexions sont utilisées, ou qu'il y a quelques problèmes avec les verrous internes. mysqladmin processlist devra normalement être en mesure d'effectuer une connexion même dans ce cas, et peut fournir des informations utiles à propos du nombre de connexions courantes et de leur statut ;

- exécutez la commande mysqladmin -i 5 status ou mysqladmin -i 5 -r status, ou dans une fenêtre séparée pour produire des statistiques pendant que vous exécutez vos autres requêtes ;

- essayez ce qui suit :

1. Démarrez mysqld à partir de gdb (ou d'un autre débogueur). Voir Section D.1.3, « Déboguer mysqld sous gdb »,

2. Exécutez vos scripts de tests,

3. Affichez le traçage et les variables locales aux trois niveaux les plus bas. Avec gdb vous pouvez le faire avec les commandes suivantes lorsque mysqld s'est planté à l'intérieur de gdb :

backtrace
info local
up
info local
up
info local

Avec gdb vous pouvez aussi savoir quels threads existent avec info threads et en prendre un avec thread #, où # est l'identifiant du thread ;

- essayez de simuler votre application avec un script Perl pour forcer MySQL à planter ou à avoir un comportement défectueux ;

- envoyez un rapport de bogue normal. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ». Soyez le plus précis possible et donnez plus de détails que d'habitude. Puisque MySQL fonctionne pour beaucoup de personnes, il se peut que le plantage résulte de quelque chose de spécifique à votre système (par exemple, une erreur liée à la particularité de vos bibliothèques système) ;

- si vous avez des problèmes avec des tables à lignes de longueurs dynamiques et que vous n'utilisez pas de colonnes BLOB/TEXT (mais seulement des colonnes VARCHAR), vous pouvez essayer de changer tous les VARCHAR en CHAR avec ALTER TABLE. Cela forcera MySQL à utiliser des lignes de tailles fixes. Les lignes à tailles fixées prennent un peu plus d'espace, mais sont plus tolérantes aux corruptions !
Le code courant des lignes dynamiques est utilisé chez MySQL AB depuis au moins trois ans sans aucun problème, mais par nature, les lignes à longueur dynamique sont plus exposées aux erreurs, il est donc bon d'essayer ce qui précède pour voir si cela vous aide !

28-D-3 - Comment MySQL gère un disque plein

Lorsqu'il n'y a plus d'espace disque, MySQL fait ce qui suit :

- il vérifie chaque minute pour voir s'il y a assez d'espace pour écrire la ligne courante. Si oui, il continue comme si rien ne s'était passé ;

- chaque six minutes, il ajoute un avertissement dans le fichier de log à propos de la condition du disque.

Pour contourner ce problème, vous pouvez effectuer les actions suivantes :

- pour continuer, il suffit juste d'avoir assez d'espace disque pour insérer tous les enregistrements ;

- pour annuler le thread, vous devez lui envoyer un mysqladmin kill. Le thread sera annulé la prochaine fois qu'il vérifiera le disque (dans une minute) ;

- notez que d'autres threads peuvent être en train d'attendre pour accéder à la table qui a causé le problème de disque plein. Si vous avez beaucoup de threads « locked », terminer le thread qui a causé la défaillance permettra aux autres threads de continuer.

Les exceptions pour le comportement suivant sont, lorsque vous utilisez REPAIR ou OPTIMIZE , ou lorsque les index sont créés dans un batch après l'exécution de LOAD DATA INFILE ou d'un ALTER TABLE.

Toutes les commandes précédentes risquent d'utiliser de gros fichiers temporaires, qui pourraient perturber le reste du système s'ils n'étaient pas supprimés. Si MySQL obtient une erreur de disque plein lors de l'exécution d'une des commandes précédentes, il effacera les gros fichiers temporaires et marquera la table comme corrompue (à part pour ALTER TABLE, où l'ancienne table sera restaurée).

28-D-4 - Où MySQL stocke les fichiers temporaires ?

MySQL utilise la valeur de la variable d'environnement TMPDIR comme chemin du dossier où stocker les fichiers temporaires. Si vous n'avez pas de variable TMPDIR, MySQL utilise alors le dossier système par défaut, qui est normalement /tmp, /var/tmp ou /usr/tmp. Si le support qui contient votre dossier temporaire est trop petit, modifiez le script safe_mysqld pour configurer TMPDIR, et lui faire désigner un dossier où vous aurez la place. Vous pouvez aussi configurer ce dossier avec l'option --tmpdir de mysqld.

Depuis MySQL 4.1, l'option --tmpdir peut prendre une liste de plusieurs chemins, qui seront utilisés alternativement. Les chemins doivent être séparés par des deux-points (':') sous Unix et par des points-virgules (';') sous Windows, NetWare et OS/2. Note : pour répartir la charge entre plusieurs disques physiques, les chemins doivent être dirigés vers des disques physiques distincts, et non pas des partitions différentes du même disque.

Si le serveur MySQL est configuré comme un esclave de réplication, vous ne devez pas faire pointer le chemin de --tmpdir vers un dossier en mémoire vive, ou vers un dossier qui sera vidé au démarrage du serveur. Un esclave de réplication doit être capable de retrouver ses fichiers temporaires lors du redémarrage du serveur, de manière à pouvoir reprendre la réplication des tables temporaires ou des opérations de LOAD DATA INFILE. Si les fichiers du dossier temporaire sont perdus après redémarrage, la réplication échouera.

MySQL crée tous les fichiers temporaires sous forme de fichier cachés. Cela garantit que les fichiers temporaires seront supprimés lorsque mysqld est terminé. L'inconvénient d'utiliser les fichiers cachés est que vous ne verrez pas que le dossier temporaire est gros et qu'ils risquent de remplir votre dossier temporaire.

Lors des tris avec les clauses ORDER BY ou GROUP BY, MySQL utilise normalement deux dossiers temporaires. L'espace disque maximal nécessaire est :

(taille de ce qui est trié + taille du pointeur de base)
* nombre de lignes trouvées
* 2

taille du pointeur de base vaut généralement 4, mais peut croître dans le futur pour les tables réellement grandes.

Pour certaines requêtes SELECT, MySQL crée aussi des tables temporaires SQL. Elles ne sont pas cachées, et portent un nom du type SQL_*.

ALTER TABLE crée une table temporaire dans le même dossier que la table originale.

28-D-5 - Comment protéger ou changer le fichier socket /tmp/mysql.sock

Le dossier par défaut pour le fichier de socket Unix que le serveur utilise pour les communications locales est /tmp/mysql.sock. Cela peut poser des problèmes, car sur certaines versions d'Unix, tout le monde peut effacer les fichiers dans le dossier /tmp.

Sur la plupart des versions d'Unix, vous pouvez protéger votre dossier /tmp pour que les fichiers ne puissent être effacés que par leur propriétaire ou le super-utilisateur (root). Pour cela, utilisez le sticky sur le dossier /tmp en vous connectant en tant que root et en exécutant la commande suivante :

shell> chmod +t /tmp

Vous pouvez vérifier que le bit sticky est actif en exécutant ls -ld /tmp. Si le dernier bit de permission est t, il l'est.

Vous pouvez changer l'endroit où MySQL utilise / place le fichier de socket de la façon suivante :

- spécifiez le chemin dans un fichier d'options globales ou locales. Par exemple, placez dans /etc/my.cnf :

[client]
socket=chemin-vers-fichier-socket

[mysqld]
socket=chemin-vers-fichier-socket

Voir Section 4.3.2, « Fichier d'options my.cnf »  ;

- spécifiez cela en ligne de commande à safe_mysqld et à la plupart des clients avec l'option --socket=chemin-vers-fichier-socket ;

- spécifiez le chemin vers la socket dans la variable d'environnement MYSQL_UNIX_PORT ;

- définissez le chemin avec l'option de configure --with-unix-socket-path=chemin-vers-fichier-socket. Voir Section 2.4.2, « Options habituelles de configure ».

Vous pouvez vérifier que la socket fonctionne avec cette commande :

shell> mysqladmin --socket=/chemin/vers/socket version

28-D-6 - Problèmes de fuseaux horaires

Si vous avez un problème avec SELECT NOW() qui retournerait des valeurs en GMT et non votre temps local, vous devez configurer la variable d'environnement TZ et la mettre sur votre fuseau horaire courant. Cela peut être fait pour l'environnement dans lequel le serveur fonctionne, par exemple, dans safe_mysqld ou mysql.server. Voir Annexe E, Variables d'environnement.

28-E - Problèmes relatifs aux requêtes

28-E-1 - Sensibilité à la casse dans les recherches

Par défaut, les recherches de MySQL ne sont pas sensibles à la casse (cependant, il existe des jeux de caractères qui ne sont jamais insensibles à la casse, comme czech).

Cela signifie que si vous recherchez avec nom_colonne LIKE 'a%', vous aurez toutes les valeurs de la colonne qui commencent par un A ou un a. Si vous voulez que cette recherche soit sensible à la casse, utilisez, par exemple, INSTR(nom_colonne, "A")=1 pour vérifier un préfixe. Utilisez STRCMP(nom_colonne, "A") = 0 si la valeur de la colonne doit être exactement "A".

Les opérations de comparaisons simples (>=, >, = , < , <=, tri et groupement) sont basées sur la « valeur de tri » de chaque caractère. Les caractères avec la même valeur de tri (comme (comme 'E', 'e' et 'é')) sont considérés comme le même caractère !

Dans les anciennes versions de MySQL les comparaisons avec LIKE étaient effectuées sur la majuscule de chaque caractère (E == e mais E <> é). Dans les nouvelles versions LIKE fonctionne comme les autres opérateurs de comparaison.

Si vous voulez qu'une colonne soit toujours traitée de façon sensible à la casse, déclarez-la en tant que BINARY. Voir Section 13.2.5, « Syntaxe de CREATE TABLE ».

Si vous utilisez des données chinoises avec l'encodage big5, vous devez rendre toutes les colonnes de chaînes BINARY. Cela fonctionne, car l'ordre de tri de l'encodage big5 est basé sur l'ordre des codes ASCII. Depuis MySQL 4.1, vous pouvez explicitement déclarer une colonne avec le jeu de caractères big5 :

CREATE TABLE t (name CHAR(40) CHARACTER SET big5);

28-E-2 - Problèmes avec l'utilisation des colonnes DATE

Le format d'une valeur de DATE est 'YYYY-MM-DD'. En accord avec ANSI SQL, aucun autre format n'est autorisé. Vous devez utiliser ce format dans les UPDATE et les clauses WHERE des requêtes SELECT. Par exemple :

mysql> SELECT * FROM nom_de_table WHERE date >= '1997-05-05';

MySQL convertit automatiquement une date en nombre si la date est utilisée dans un contexte numérique (et vice versa). Il est aussi assez intelligent pour permettre une forme « relaxée » lors des mises à jour et dans les clauses WHERE qui comparent une date et une colonne TIMESTAMP, DATE, ou DATETIME. (Forme relaxée signifie que n'importe quel caractère de ponctuation peut être utilisé en tant que séparateurs des parties. Par exemple, '1998-08-15' et '1998#08#15' sont équivalents.) MySQL peut convertir une chaîne ne contenant aucun séparateur (comme '19980815'), en supposant qu'elle a un sens pour une date.

La date spéciale '0000-00-00' peut être stockée et récupérée en tant que '0000-00-00'. Lors de l'utilisation d'une date '0000-00-00' avec MyODBC, elle sera automatiquement convertie en NULL à partir de la version 2.50.12 de MyODBC, car ODBC ne peut gérer ce type de dates.

Puisque MySQL effectue les conversions décrites plus haut, ce qui suit fonctionnera :

mysql> INSERT INTO nom_de_table (idate) VALUES (19970505);
mysql> INSERT INTO nom_de_table (idate) VALUES ('19970505');
mysql> INSERT INTO nom_de_table (idate) VALUES ('97-05-05');
mysql> INSERT INTO nom_de_table (idate) VALUES ('1997.05.05');
mysql> INSERT INTO nom_de_table (idate) VALUES ('1997 05 05');
mysql> INSERT INTO nom_de_table (idate) VALUES ('0000-00-00');

mysql> SELECT idate FROM nom_de_table WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM nom_de_table WHERE idate >= 19970505;
mysql> SELECT MOD(idate,100) FROM nom_de_table WHERE idate >= 19970505;
mysql> SELECT idate FROM nom_de_table WHERE idate >= '19970505';

Toutefois, ce qui suit ne fonctionnera pas :

mysql> SELECT idate FROM nom_de_table WHERE STRCMP(idate,'19970505')=0;

STRCMP() est une fonction de chaînes de caractères, elle convertit donc idate en une chaîne et effectue une comparaison de chaînes. Elle ne convertit pas '19970505' en date et n'effectue donc pas de comparaison de dates.

Notez que MySQL vérifie très peu l'intégrité des dates. Si vous stockez une date erronée, comme '1998-2-31', la date erronée sera enregistrée.

Vu que MySQL compresse les dates pour les stocker, il ne peut stocker tout format donné, car il risquerait de ne pas correspondre au tampon de résultat. Les règles d'acceptations de dates sont :

- si MySQL peut enregistrer et récupérer une date donnée, la date erronée est acceptée pour les colonnes DATE et DATETIME ;

- toutes les valeurs de jours comprises entre 0 et 31 sont acceptées. Cela est fort convenable pour les applications web où vous demandez l'année, mois et jour dans trois champs textes (ou liste déroulantes) différents ;

- le champ jour ou mois peut être un zéro. Cela est convenable si vous voulez enregistrer un anniversaire dans une colonne DATE et que vous ne connaissez qu'une partie de la date.

Si la date ne peut être convertie en une valeur raisonnable, un 0 est inséré dans le champ DATE, il sera récupéré en tant que 0000-00-00. Cela est une solution rapide et convenue vu que nous considérons que la responsabilité de la base de données est de récupérer la même date que vous aviez stocké (même si la date n'est pas correcte). Nous pensons que c'est à l'application de vérifier les dates, et non au serveur de le faire.

28-E-3 - Problèmes avec les valeurs NULL

Le concept de la valeur NULL est une source de confusions pour les débutants en SQL, qui pensent souvent que NULL est la même chose qu'une chaîne de caractères vide "". Ce n'est pas le cas ! Par exemple, les deux requêtes suivantes sont complètement différentes :

mysql> INSERT INTO ma_table (telephone) VALUES (NULL);
mysql> INSERT INTO ma_table (telephone) VALUES ("");

Les deux requêtes insèrent des valeurs dans la colonne telephone, mais la première insère une valeur NULL et la seconde insère une chaîne vide. La signification de la première peut être « le numéro de téléphone est inconnu » et la seconde peut être considérée comme « elle n'a pas de téléphone ».

En SQL, la valeur NULL est toujours FALSE en comparaison à n'importe quelle autre valeur, même NULL. Une expression contenant NULL produit toujours un résultat NULL sauf si une indication contraire est présente dans la documentation des opérateurs et des fonctions impliquées dans l'expression. Toutes les colonnes de l'exemple suivant retournent NULL :

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

Si vous voulez trouver les colonnes dont la valeur est NULL, vous ne pouvez pas utiliser le test =NULL. La requête suivante ne retourne aucune ligne, car expr = NULL est FALSE, pour n'importe quelle expression :

mysql> SELECT * FROM ma_table WHERE telephone = NULL;

Pour trouver les valeurs NULL, vous devez utiliser le test IS NULL. Ce qui suit montre comment trouver les numéros de téléphone NULL et les numéros vides :

mysql> SELECT * FROM ma_table WHERE telephone IS NULL;
mysql> SELECT * FROM ma_table WHERE telephone = "";

Notez que vous ne pouvez ajouter d'index qu'aux colonnes pouvant avoir la valeur NULL si vous utilisez la version 3.23.2 de MySQL ou plus récente avec des tables de type MyISAM ou InnoDB. Dans les versions précédentes et avec les autres types, vous devez déclarer de telles colonnes NOT NULL. Cela signifie aussi que vous ne pouvez pas insérer NULL dans les colonnes indexées.

Lors de la lecture de données avec LOAD DATA INFILE, les colonnes vides sont interprétées en tant que ''. Si vous voulez une valeur NULL dans une colonne, vous devez utiliser \N dans le fichier. Le mot littéral 'NULL' peut aussi être utilisé dans certaines circonstances. Voir Section 13.1.5, « Syntaxe de LOAD DATA INFILE ».

Lors de l'utilisation de ORDER BY, les valeurs NULL sont présentées en premier. Si vous triez dans l'ordre décroissant en utilisant DESC, les valeurs NULL sont présentées en dernier. Lors de l'utilisation de GROUP BY, toutes les valeurs NULL sont considérées comme égales.

Pour mieux gérer les valeurs NULL, vous pouvez utiliser les opérateurs IS NULL et IS NOT NULL et la fonction IFNULL().

Lors de l'utilisation de GROUP BY, toutes les valeurs NULL sont considérées comme égales.

Les fonctions agrégeantes comme COUNT(), MIN() et SUM() ignorent les valeurs NULL. Exception faite de COUNT(*), qui compte les lignes et non pas les valeurs de colonnes. Par exemple, la commande suivante va donner deux comptes différents. Le premier est le nombre de lignes de la table, et le second est le nombre de lignes nonNULL de la colonne age :

mysql> SELECT COUNT(*), COUNT(age) FROM person;

Pour certains types de colonnes, les valeurs NULL sont traitées spécialement. Si vous insérez NULL dans la première colonne TIMESTAMP d'une table, la date et le temps courants sont insérés. Si vous insérez NULL dans une colonne AUTO_INCREMENT, le nombre suivant de la séquence sera inséré.

28-E-4 - Problèmes avec les alias

Vous pouvez utiliser un alias pour vous référer à une colonne dans une clause GROUP BY, ORDER BY, ou HAVING. Les alias peuvent aussi être utilisés pour donner de meilleurs noms aux colonnes :

SELECT SQRT(a*b) as rt FROM nom_de_table GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM nom_de_table GROUP BY id HAVING cnt > 0;
SELECT id AS "Identité du client" FROM nom_de_table;

Notez que ANSI SQL ne vous permet pas de vous référer à un alias dans une clause WHERE. Il en est ainsi, car lorsque le code de WHERE est exécuté, la valeur de la colonne ne peut pas encore être déterminée. Par exemple, la requête suivante est illégale :

SELECT id,COUNT(*) AS cnt FROM nom_de_table WHERE cnt > 0 GROUP BY id;

La clause WHERE est exécutée pour savoir quelles lignes devraient être incluses dans la partie GROUP BY tandis que HAVING est utilisé pour décider quelles lignes du jeu de résultats doivent être utilisées.

28-E-5 - Erreur Some non-transactional changed tables couldn't be rolled back

Si vous obtenez le message d'erreur :

Warning: Some non-transactional changed tables couldn't be rolled back

en essayant de faire un ROLLBACK, cela signifie que certaines tables que vous avez utilisées dans la transaction ne supportent pas les transactions.

Ces tables non transactionnelles ne seront pas affectées par la commande ROLLBACK.

Si vous ne mélangez pas délibérément des tables transactionnelles et non transactionnelles dans une transaction, la source la plus probable de cette erreur est qu'une table que vous croyiez transactionnelle ne l'est pas. Cela peut arriver lorsque vous créez une table en utilisant un moteur de tables qui n'est pas supporté par le serveur mysqld (ou qui a été désactivé avec une option de démarrage). Si mysqld ne supporte pas le moteur de table, il va changer le type et utiliser MyISAM, qui n'est pas non transactionnelle.

Vous pouvez vérifier le type de table en utilisant une de ces commandes :

SHOW TABLE STATUS LIKE 'tbl_name';
SHOW CREATE TABLE tbl_name;

Voyez Section 13.5.3.16, « SHOW TABLE STATUS » et Section 13.5.3.5, « Syntaxe de SHOW CREATE TABLE ».

Vous pouvez vérifier les moteurs de tables disponibles avec le serveur mysqld, avec ces commandes :

SHOW ENGINES;

Avant MySQL 4.1.2, SHOW ENGINES est inaccessible. Utilisez la commande suivante et vérifiez la valeur de la variable qui est associée au moteur de tables que vous voulez :

SHOW VARIABLES LIKE 'have_%';

Par exemple, pour déterminer si le moteur InnoDB est disponible, vérifiez la valeur de la variable have_innodb.

Voyez Section 13.5.3.7, « Syntaxe SHOW ENGINES » et Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ».

28-E-6 - Effacer des lignes de tables reliées

Comme MySQL ne supporte encore ni les sous-requêtes ni l'utilisation de plusieurs tables dans une requête DELETE (avant la version 4.0), vous devez utiliser l'approche suivante pour effacer des lignes de deux tables reliées :

1. Sélectionnez (SELECT) les lignes de la table principale en vous basant sur une condition WHERE ;

2. Effacez (DELETE) les lignes de la table principale en vous basant sur la même condition ;

3. DELETE FROM table_liée WHERE colonne_liée IN (lignes_sélectionnées).

Si le nombre total des caractères dans la requête avec la colonne_liée est supérieur à 1,048,576 (la valeur par défaut est max_allowed_packet, vous devez la découper en parties plus petites et exécuter plusieurs DELETE. Vous obtiendrez probablement les suppressions les plus rapides en n'effaçant que 100-1000 colonne_liée par requête si colonne_liée est un index. Si ce n'est pas un index, la vitesse est indépendante du nombre d'arguments dans la clause IN.

28-E-7 - Résoudre les problèmes des lignes non retournées

Si vous avez une requête complexe avec beaucoup de tables et qu'elle ne retourne aucun résultat, vous devez suivre la procédure suivante pour trouver ce qui cloche dans votre requête :

1. Testez la requête avec EXPLAIN et vérifiez si vous trouvez quelque chose qui vous paraît faux. Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) » ;

2. Ne sélectionnez que les champs que vous utilisez dans la clause WHERE ;

3. Enlevez une table à la fois de la requête jusqu'à ce qu'elle retourne quelques lignes. Si les tables sont grandes, il est bon d'utiliser LIMIT 10 dans la requête ;

4. Exécutez un SELECT pour les colonnes qui auraient dû trouver des lignes dans la dernière table supprimée de la requête ;

5. Si vous comparez des colonnes FLOAT ou DOUBLE avec des nombres à virgule, vous ne pouvez pas utiliser '='. C'est un problème commun à la plupart des langages de programmation, car les valeurs à virgules flottantes ne sont pas des valeurs exactes. Dans le plupart des cas, changer la colonnes FLOAT en DOUBLE corrigera cela. Voir Section A.5.8, « Problèmes de comparaisons avec nombres à virgule flottante » ;

6. Si vous ne pouvez toujours pas trouver ce qui ne va pas, créez un test minimal pouvant être exécuté avec mysql test < query.sql montrant votre problème. Vous pouvez créer un fichier de test avec mysqldump --quick base tables > query.sql. Éditez le fichier et supprimez quelques lignes d'insertions (s'il y en a trop), et ajoutez votre requête de sélection à la fin du fichier.
Vérifiez que vous avez encore le problème en faisant :

shell> mysqladmin create test2
shell> mysql test2 < query.sql

Envoyez le fichier de test, en utilisant mysqlbug, à sur les listes diffusion. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

28-E-8 - Problèmes de comparaisons avec nombres à virgule flottante

Les nombres à virgule flottante portent souvent à confusion, car ils ne sont pas enregistrés en tant que valeurs exactes dans l'architecture de l'ordinateur. Ce qu'on voit à l'écran n'est souvent pas la valeur exacte du nombre.

Ce discours s'applique aux champs de types FLOAT, DOUBLE et DECIMAL.

CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
(6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
-> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

Le résultat est correct. Même si les cinq premiers enregistrements ne devraient pas passer le test a priori, ils le font sûrement, car la différence entre les nombres se situe plus loin que les décimales, ou que cela dépend de l'architecture de l'ordinateur.

Le problème ne peut être résolu en utilisant ROUND() (ou une fonction similaire), car le résultat est encore un nombre à virgule flottante. Exemple :

mysql> SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b
-> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

Voilà ce à quoi les nombres dans le champ 'a' ressemblent :

mysql> SELECT i, ROUND(SUM(d1), 2)*1.0000000000000000 AS a,
-> ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
+------+----------------------+-------+
| i    | a                    | b     |
+------+----------------------+-------+
|    1 |  21.3999999999999986 | 21.40 |
|    2 |  76.7999999999999972 | 76.80 |
|    3 |   7.4000000000000004 |  7.40 |
|    4 |  15.4000000000000004 | 15.40 |
|    5 |   7.2000000000000002 |  7.20 |
|    6 | -51.3999999999999986 |  0.00 |
+------+----------------------+-------+

Selon l'architecture de votre ordinateur, vous pouvez obtenir ou non les mêmes résultats. Chaque CPU peut évaluer les nombres à virgule flottante d'une manière différente. Par exemple, sur des machines vous pouvez obtenir les résultats 'corrects' en multipliant les deux arguments par 1, l'exemple suivant illustre cela.

ATTENTION : NE FAITES JAMAIS CONFIANCE À CETTE METHODE DANS VOS APPLICATIONS, C'EST UN EXEMPLE DE MAUVAISE METHODES !

mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b
-> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+

La raison pour laquelle l'exemple précédent semble fonctionner est que, en particulier sur la machine sur laquelle le test a été effectué, l'arithmétique des nombres à virgule flottante du CPU arrondi les nombres à la même valeur, mais il n'y a aucune règle stipulant qu'un CPU doit faire cela, on ne peut donc pas s'y fier.

La façon correcte d'effectuer des comparaisons de nombres à virgule flottante est, en premier lieu de décider du degré de tolérance voulu entre les nombres, puis d'effectuer la comparaison selon le nombre de tolérances. Par exemple, si nous décidons que les nombres à virgule flottante sont considérés comme égaux s'ils ont la même précision au dix-millième près (0.0001), la comparaison ressemblera à cela :

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+
1 row in set (0.00 sec)

Et vice versa, si vous voulez obtenir les lignes où les nombres sont les mêmes, le test sera :

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) < 0.0001;
+------+-------+-------+
| i    | a     | b     |
+------+-------+-------+
|    1 | 21.40 | 21.40 |
|    2 | 76.80 | 76.80 |
|    3 |  7.40 |  7.40 |
|    4 | 15.40 | 15.40 |
|    5 |  7.20 |  7.20 |
+------+-------+-------+

28-F - Problèmes liés à l'optimiseur

MySQL utilise un optimiseur de coûts pour trouver le meilleur moyen de résoudre une requête. Dans de nombreux cas, MySQL peut calculer la meilleure solution pour une requête, mais parfois, MySQL n'a pas les informations nécessaires, et il fait des évaluations.

Pour les cas où MySQL ne fait pas le « bon » choix, des outils sont disponibles, pour que vous aidiez MySQL :

- utilisez la commande EXPLAIN pour savoir comment MySQL va traiter la requête. Pour l'utiliser, ajoutez simplement le mot clé EXPLAIN avant votre requête SELECT :

mysql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.i = t2.i;

EXPLAIN est présenté en détails dans la section Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) » ;

- utilisez la commande ANALYZE TABLE tbl_name pour mettre à jour les distributions de clés dans la table traitée. Voir Section 13.5.2.1, « Syntaxe de ANALYZE TABLE » ;

- utilisez l'option FORCE INDEX pour la table scannée, pour dire à MySQL que les scans de tables sont très coûteux, comparés aux scans d'index. Voir Section 13.1.7, « Syntaxe de SELECT » :

SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
WHERE t1.col_name=t2.col_name;

USE INDEX et IGNORE INDEX peuvent aussi être utiles ;

- STRAIGHT_JOIN de niveau global ou table. Voir Section 13.1.7, « Syntaxe de SELECT » ;

- vous pouvez paramétrer les variables globales ou spécifiques au thread. Par exemple, lancez mysqld avec l'option --max-Voirks-for-key=1000 ou utilisez SET max_Voirks_for_key=1000 pour dire à l'optimiseur qu'il doit supposer que les scans de clés ne représenteront pas plus de 1000 recherches. Voyez Section 5.2.3, « Variables serveur système ».

28-G - Questions relatives aux définitions de tables

28-G-1 - Problèmes avec ALTER TABLE.

ALTER TABLE change une table avec le jeu de caractères courant. Si durant l'exécution d'ALTER TABLE vous obtenez une erreur de clé dupliquée, alors la cause est soit que le nouveau jeu de caractères interprète deux clés à la même valeur ou que la table est corrompue, auquel cas vous devez exécuter REPAIR TABLE sur la table.

Si ALTER TABLE se termine avec une erreur de ce genre :

Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)

le problème est peut-être que MySQL a planté lors d'un précédent appel à ALTER TABLE et qu'il y a une ancienne table nommée A-quelquechose ou B-quelquechose qui subsiste. Dans ce cas, placez-vous dans le dossier de données MySQL et effacez tous les fichiers dont les noms commencent par A- ou B-. (Vous voudrez peut-être les déplacer autre part plutôt que de les effacer.)

ALTER TABLE fonctionne de la façon suivante :

- crée une nouvelle table nommée A-xxx avec les changements voulus ;

- toutes les lignes de l'ancienne table sont copiées dans A-xxx ;

- l'ancienne table est renommée B-xxx ;

- A-xxx est renommée avec le nom de votre ancienne table ;

- B-xxx est supprimée.

Si quelque chose se passe mal durant l'opération de changement de nom, MySQL essaye d'annuler les changements. Si quelque chose de grave se passe (cela ne devrait jamais arriver, bien sûr), MySQL peut laisser l'ancienne table en tant que B-xxx, mais un simple changement de nom au niveau système devrait restaurer vos données.

28-G-2 - Comment changer l'ordre des colonnes dans une table

Tout d'abord, réfléchissez bien à la raison qui vous pousse à changer l'ordre des colonnes. Le but de SQL est de séparer l'application du stockage des données. Vous devez toujours spécifier l'ordre dans lequel vous devez lire les données. La première commande retourne les valeurs dans l'ordre col_name1, col_name2, col_name3, alors que la seconde utilise l'ordre col_name1, col_name3, col_name2 :

mysql> SELECT col_name1, col_name2, col_name3 FROM tbl_name;
mysql> SELECT col_name1, col_name3, col_name2 FROM tbl_name;

Si vous décidez de changer l'ordre des colonnes dans une table, vous pouvez le faire comme ceci :

1. Créez une nouvelle table avec les colonnes dans le nouvel ordre ;

2. Exécutez cette commande :

mysql> INSERT INTO new_table
-> SELECT columns-in-new-order FROM old_table;

3. Effacez ou renommez la table old_table ;

4. Renommez la nouvelle table avec l'ancien nom.

mysql> ALTER TABLE new_table RENAME old_table;

SELECT * est parfait pour tester les requêtes. Mais, dans une application, vous me devriez jamais utiliser SELECT * et lire les colonnes en vous basant sur l'ordre retourné par la table. L'ordre et la position des colonnes peut changer. Un simple modification de la structure de la table vous conduira à une erreur.

28-G-3 - Problèmes avec les tables temporaires

Voici une liste des limitations avec TEMPORARY TABLES.

- Une table temporaire ne peut être que du type HEAP, ISAM, MyISAM ou InnoDB.

- Vous ne pouvez utiliser une table plus d'une fois dans une requête. Par exemple, ce qui suit ne marche pas :

mysql> SELECT * FROM temp_table, temp_table AS t2;
ERROR 1137: Can't reopen table: 'temp_table'

- La commande SHOW TABLES ne liste pas les tables TEMPORARY.

- Vous ne pouvez pas utiliser la commande RENAME pour renommer une table TEMPORARY. Cependant, vous pouvez utiliser la commande ALTER TABLE pour cela :

mysql> ALTER TABLE orig_name RENAME new_name;

29 - Crédits

Cet annexe liste les développeurs, contributeurs, et supporters qui ont fait que MySQL est ce qu'il est aujourd'hui.

29-A - Développeurs chez MySQL AB

Voici les développeurs qui sont employés par MySQL AB pour travailler sur la base de données MySQL, grosso modo dans leur ordre d'embauche. Pour chaque développeur, vous trouverez une petite liste de leurs tâches et de leurs responsabilités, ainsi que leurs réalisations. Tous les développeurs sont impliqués dans le support.

- Michael (Monty) Widenius

- Chef d'équipe et auteur principal du serveur MySQL (mysqld).

- Nouvelles fonctions dans la bibliothèque de chaînes de caractères.

- La majorité de la bibliothèque mysys.

- Les bibliothèques ISAM et MyISAM (les fichiers d'index B-tree avec compression d'index et différents formats d'enregistrement).

- La bibliothèque HEAP. Un système de gestion des tables en mémoire avec un hashage dynamique efficace. Utilisé depuis 1980 et publié en 1984.

- Le programme replace (jetez-y un œil c'est carrément COOL !).

- MyODBC, le pilote ODBC de Windows95.

- La correction de bogues avec les MIT-pthreads pour qu'ils fonctionnent avec MySQL. Et aussi l'Unireg, une application à base de curses avec de nombreuses utilisations.

- Le port d'outils mSQL comme msqlperl, DBD/DBI et DB2mysql.

- La majorité de crash-me et les fondations des tests de performance de MySQL.

- David Axmark

- Auteur original du manuel de référence, incluses les améliorations de texi2html.

- La mise à jour automatique du site web depuis le manuel.

- Le support initial de Autoconf, Automake et Libtool.

- Les licences.

- Des parties de tous les fichiers texte (de nos jours, uniquement le README est encore présent. Le reste est dans le manuel).

- Nombreux tests des nouvelles fonctionnalités.

- Notre expert légal des logiciels libres.

- Le responsable des listes de diffusion (qui n'a jamais le temps de le faire correctement...)

- Notre code initial pour le port (bientôt plus de 10 ans). De nos jours, seules des parties de mysys restent.

- La personne que Monty appelle au milieu de la nuit lorsqu'il a réussi à faire fonctionner la nouvelle fonctionnalité !

- Le chef « Open Source » (Relations avec la communauté MySQL).

- Jani Tolonen

- mysqlimport

- Un grand nombre d'extensions pour le client en ligne de commande.

- PROCEDURE ANALYSE()

- Sinisa Milivojevic

- Compression du protocole client/serveur avec zlib.

- Hashing parfait pour la phase d'analyse lexicale.

- Insertions multilignes

- Option mysqldump -e

- LOAD DATA LOCAL INFILE

- Option SQL_CALC_FOUND_ROWS SELECT

- Option --max-user-connections=...

- net_read et net_write_timeout

- GRANT/REVOKE et SHOW GRANTS FOR

- Nouveau protocole client/serveur pour la version 4.0

- UNION en version 4.0

- Traitements multitables de DELETE/UPDATE

- Tables dérivées en version 4.1.

- Gestion des ressources utilisateur.

- Développeur initial de l'API MySQL++ C++ API et du client MySQLGUI.

- Tonu Samuel (ancien développeur)

- Interface VIO (la base pour le protocole client/serveur chiffré).

- Système de fichiers MySQL (une méthode pour utiliser la base MySQL comme un système de fichiers).

- L'expression CASE.

- Les fonctions MD5() et COALESCE().

- Le support RAID des tables MyISAM.

- Sasha Pachev

- Implémentation initiale de la réplication (jusqu'en version 4.0).

- SHOW CREATE TABLE.

- mysql-bench

- Matt Wagner

- Suite de tests MySQL.

- Webmestre (jusqu'en 2002).

- Coordinateur du développement.

- Miguel Solorzano

- Développement Win32 et publications.

- Code du serveur sur Windows NT.

- WinMySQLAdmin

- Timothy Smith (ancien développeur)

- Support des jeux de caractères dynamiques.

- le script configure, les RPM et d'autres parties du système de compilation.

- Développeur initial de libmysqld, le serveur intégré.

- Sergei Golubchik

- Recherche en texte plein.

- Bibliothèque de clés pour MERGE.

- Jeremy Cole

- Relecture et édition de ce manuel.

- ALTER TABLE ... ORDER BY ....

- UPDATE ... ORDER BY ....

- DELETE ... ORDER BY ....

- Indrek Siitan

- Design et programmation de notre interface web.

- Auteur de notre lettre d'actualité.

- Jorge del Conde

- MySQLCC (MySQL Control Center)

- Développement Win32

- Implémentation initiale des portails du site web.

- Venu Anuganti

- MyODBC 3.51

- Nouveau protocole client/serveur pour la version 4.1 (pour les requêtes préparées).

- Arjen Lentz

- Responsable du manuel de référence MySQL.

- Préparation de la version imprimée chez O'Reilly.

- Alexander (Bar) Barkov, Alexey (Holyfoot) Botchkov et Ramil Kalimullin

- Données spatiales (GIS) et R-Trees en version 4.1.

- Unicode et jeux de caractères pour la version 4.1.

- Oleksandr (Sanja) Byelkin

- Cache de requêtes en version 4.0.

- Implémentation des sous-requêtes en version 4.1.

- Aleksey (Walrus) Kishkin et Alexey (Ranger) Stroganov

- Design des tests de performance et analyse.

- Maintenance de la suite de tests MySQL.

- Zak Greant

- Porte-parole Open Source, relation avec la communauté.

- Carsten Pedersen

- Le programme de certification MySQL.

- Lenz Grimmer

- Ingénierie de mise en production (compilation et publication).

- Peter Zaitsev

- Fonction SHA1(), AES_ENCRYPT() et AES_DECRYPT().

- Débogage et nettoyage de diverses fonctionnalités.

- Alexander (Salle) Keremidarski

- Support.

- Débogage.

- Per-Erik Martin

- Chef de projet pour les procédures stockées et les triggers.

- Jim Winstead

- Chef développeur web.

- Mark Matthews

- Connecteur/Pilote J (Java).

- Peter Gulutzan

- Compatibilité avec les standards SQL-99, SQL-2003.

- Documentation des codes/algorithmes MySQL existants.

- Guilhem Bichot

- Réplication, depuis MySQL version 4.0.

- Correction de la gestion des exposants pour les DECIMAL.

- Auteur de mysql_tableinfo.

- Antony T. Curtis

- Port de MySQL sur OS/2.

29-B - Contributeurs à MySQL

Bien que MySQL AB possède tous les droits du serveur MySQL et du manuel MySQL, nous voulons montrer notre reconnaissance à ceux qui ont apporté leur contribution d'une manière ou d'une autre à la distribution MySQL. Les contributeurs sont listés ici, dans un ordre aléatoire :

- Gianmassimo Vigazzola <qwerg@mbox.vol.it> ou <qwerg@tin.it>
Le portage initial sur Win32/NT.

- Per Eric Olsson
Pour des critiques plus ou moins constructives, et des tests sur les formats de lignes dynamiques.

- Irena Pancirov <irena@mail.yacc.it>
Portage sur Win32 avec le compilateur Borland. mysqlshutdown.exe et mysqlwatch.exe.

- David J. Hughes
Pour ses efforts de constitution d'une base de données SQL partagée. Chez TcX, le prédécesseur de MySQL AB, nous avons commencé avec mSQL, mais nous nous sommes aperçus que cela ne satisfaisait pas nos besoins, et nous avons écrit une interface SQL avec notre application Unireg. Les clients mysqladmin et mysql ont été largement influencés par leur équivalent mSQL. Nous avons mis une grande partie de nos efforts à faire que la syntaxe de MySQL soit un surensemble de celle de mSQL. De nombreuses idées d'API ont été empruntées à mSQL pour rendre plus facile le portage des programmes depuis mSQL vers MySQL. Le logiciel MySQL ne contient aucun code extrait de mSQL. Les deux fichiers (client/insert_test.c et client/select_test.c) qui font partie de la distribution sont basés sur les fichiers correspondants, et sans droits de la distribution mSQL, mais sont modifiés, pour servir d'exemple aux modifications nécessaires à la conversion de code de mSQL vers MySQL. (mSQL est la propriété de David J. Hughes).

- Patrick Lynch
Pour nous avoir aidés à acquérir http://www.mysql.com/.

- Fred Lindberg
Pour avoir configuré qmail pour qu'il gère les listes de diffusions MySQLm et pour l'aide incroyable que nous avons reçue pour gérer les listes de diffusions de MySQL.

- Igor Romanenko <igor@frog.kiev.ua>
mysqldump (précédemment appelé msqldump, mais porté et amélioré par Monty).

- Yuri Dario
Pour avoir suivi et amélioré la version MySQL pour OS/2.

- Tim Bunce
Auteur de mysqlhotcopy.

- Zarko Mocnik <zarko.mocnik@dem.si>
Tri pour le slovène.

- « TAMITO » <tommy@valley.ne.jp>
Les macros de jeux de caractères _MBm et les jeux de caractères ujis et sjis.

- Joshua Chamas <joshua@chamas.com>
La base des insertions concurrentes, la syntaxe de date améliorée, le débogage sous NT et les réponses sur la liste de diffusion.

- Yves Carlier <Yves.Carlier@rug.ac.be>
mysqlaccess, un programme qui affiche les droits des utilisateurs.

- Rhys Jones <rhys@wales.com> (et GWE Technologies Limited)
Pour JDBC, un module pour extraire des données de bases MySQL avec un client Java.

- Dr Xiaokun Kelvin ZHU <X.Zhu@brad.ac.uk>
Développement du pilote JDBC et d'autres outils MySQL liés à Java.

- James Cooper <pixel@organic.com>
Pour la configuration d'une archive indexée des listes de diffusion sur son site.

- Rick Mehalick <Rick_Mehalick@i-o.com>
Pour xmysql, un client graphique X pour MySQL.

- Doug Sisk <sisk@wix.com>
Pour les paquets RPM de MySQL pour RedHat Linux.

- Diemand Alexander V. <axeld@vial.ethz.ch>
Pour les paquets RPM de MySQL pour RedHat Linux-Alpha.

- Antoni Pamies Olive <toni@readysoft.es>
Pour les paquets RPM de MySQL pour Intel et SPARC.

- Jay Bloodworth <jay@pathways.sde.state.sc.us>
Pour les paquets RPM de MySQL pour MySQL Version 3.21.

- David Sacerdote <davids@secnet.com>
Idées pour la vérification sécuritaire des noms d'hôtes.

- Wei-Jou Chen <jou@nematic.ieo.nctu.edu.tw>
Le support des caractères chinois (BIG5).

- Wei He <hewei@mail.ied.ac.cn>
Un grand nombre de fonctionnalités pour le jeu de caractères Chinese (GBK).

- Jan Pazdziora <adelton@fi.muni.cz>
Ordre de tri tchèque.

- Zeev Suraski <bourbon@netvision.net.il>
Format d'heure FROM_UNIXTIME(), fonctions ENCRYPT() et conseiller bison. Membre actif des listes de diffusion.

- Luuk de Boer <luuk@wxs.nl>
Portage et amélioration de la suite de tests avec DBI/DBD. A été d'une grande aide avec le test crash-me et l'exécution des tests. Certaines améliorations de la fonction de date. Le script mysql_setpermissions.

- Alexis Mikhailov <root@medinf.chuvashia.su>
Fonctions utilisateur (UDF); CREATE FUNCTION et DROP FUNCTION.

- Andreas F. Bobak <bobak@relog.ch>
L'extension AGGREGATE des fonctions UDF.

- Ross Wakelin <R.Wakelin@march.co.uk>
Aide avec InstallShield pour MySQL-Win32.

- Jethro Wright III <jetman@li.net>
La bibliothèque libmysql.dll.

- James Pereria <jpereira@iafrica.com>
Mysqlmanager, un outil d'administration Win32 graphique pour MySQL.

- Curt Sampson <cjs@portal.ca>
Portage des MIT-pthreads vers NetBSD/Alpha et NetBSD 1.3/i386.

- Martin Ramsch <m.ramsch@computer.org>
Exemples dans les tutoriels du manuel MySQL.

- Steve Harvey
Pour la sécurisation de mysqlaccess.

- Konark IA-64 Centre of Persistent Systems Private Limited
http://www.pspl.co.in/konark/. Aide avec le port Win64 du serveur MySQL.

- Albert Chin-A-Young.
Modifications de la configuration pour Tru64, support des grands fichiers, et amélioration des gestionnaires TCP.

- John Birrell
Émulation de pthread_mutex() pour OS/2.

- Benjamin Pflugmann
Tables MERGE améliorées pour la gestion des INSERTS. Membre actif des listes de diffusion.

- Jocelyn Fournier
Travail excellent et report d'un grand nombre de bogues (surtout dans le code des requêtes imbriquées de MySQL 4.1).

- Marc Liyanage
Maintenance des paquets Mac OS X et informations de grande valeur en ce qui concerne la création des paquets pour Mac OS X.

D'autres contributeurs, chasseurs de bogues et testeurs : James H. Thompson, Maurizio Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis, Elmar Haneke, <jehamby@lightside>, <psmith@BayNetworks.com>, <duane@connect.com.au>, Ted Deppner <ted@psyber.com>, Mike Simons, Jaakko Hyvatti.

Et de nombreux autres patches et rapports issus des mailing listes.

Un grand merci à ceux qui aident à répondre aux questions sur la liste de diffusion de MYSQL :

- Daniel Koch <dkoch@amcity.com>
Configuration Irix.

- Luuk de Boer <luuk@wxs.nl>
Questions performances.

- Tim Sailer <tps@users.buoy.com>
Questions sur DBD::mysql.

- Boyd Lynn Gerber <gerberb@zenez.com>
Questions sur SCO.

- Richard Mehalick <RM186061@shellus.com>
Questions sur xmysql et les questions d'installation de bases.

- Zeev Suraski <bourbon@netvision.net.il>
Configuration du module Apache (log & identification), MySQL et PHP, syntaxe SQL et autres questions.

- Francesc Guasch <frankie@citel.upc.es>
Questions générales.

- Jonathan J Smith <jsmith@wtp.net>
Questions spécifiques aux OS comme Linux, syntaxe SQL et autres sujets intéressants.

- David Sklar <sklar@student.net>
Utilisation de MySQL avec PHP et Perl.

- Alistair MacDonald <A.MacDonald@uel.ac.uk>
Pas encore spécifié, mais généraliste : Linux et un peu HP-UX. Pousse les utilisateurs à utiliser mysqlbug.

- John Lyon <jlyon@imag.net>
Questions sur l'installation de MySQL sur le système Linux, avec soit les fichiers .rpm ou en compilant depuis la source.

- Lorvid Ltd. <lorvid@WOLFENET.com>
Questions sur la facturation, les licences, le support et le copyright de MySQL.

- Patrick Sherrill <patrick@coconet.com>
Questions sur les interfaces ODBC et VisualC++.

- Randy Harmon <rjharmon@uptimecomputers.com>
DBD, Linux, et quelques questions SQL.

29-C - Documenteurs et traducteurs

La liste des personnes suivantes nous ont aidé à écrire la documentation MySQL et à la traduire. Certains ont aussi travaillé sur les messages d'erreurs MySQL.

- Paul DuBois
Contribution continuelle pour rendre ce manuel présentable et compréhensible. Cela inclut la réécriture des courageux essais de Monty et David, dans un anglais que tout le monde comprend.

- Kim Aldale
Aide à la réécriture des premières versions de Monty et David.

- Michael J. Miller Jr. <mke@terrapin.turbolift.com>
Pour le premier manuel MySQL. Et beaucoup de corrections orthographiques et typographiques dans la FAQ, qui a été finalement transformée en une documentation complète.

- Yan Cailin
Premier traducteur du manuel de référence MySQL en chinois simplifié, au début de l'année 2000, en Big5 et HK. (http://mysql.hitstar.com/) Page personnelle linuxdb.yeah.net.

- Jay Flaherty <fty@mediapulse.com>
Grosses contributions dans la section Perl DBI/DBD du manuel.

- Paul Southworth <pauls@etext.org>, Ray Loyzaga <yar@cs.su.oz.au>
Relecture du manuel de référence.

- Therrien Gilbert <gilbert@ican.net>, Jean-Marc Pouyot <jmp@scalaire.fr>
Messages d'erreurs en français.

- Petr Snajdr, <snajdr@pvt.net>
Messages d'erreurs en tchèque.

- Jaroslaw Lewandowski <jotel@itnet.com.pl>
Messages d'erreurs en polonais.

- Miguel Angel Fernandez Roiz
Messages d'erreurs en espagnol.

- Roy-Magne Mo <rmo@www.hivolda.no>
Messages d'erreurs en norvégien et test de la version 3.21.#.

- Timur I. Bakeyev <root@timur.tatarstan.ru>
Messages d'erreurs en russe.

- <brenno@dewinter.com> & Filippo Grassilli <phil@hyppo.com>
Messages d'erreurs en italien.

- Dirk Munzinger <dirk@trinity.saar.de>
Messages d'erreurs en allemand.

- Billik Stefan <billik@sun.uniag.sk>
Messages d'erreurs en slovaque.

- Stefan Saroiu <tzoompy@cs.washington.edu>
Messages d'erreurs en roumain.

- Peter Feher
Messages d'erreurs en hongrois.

- Roberto M. Serqueira
Messages d'erreurs en portugais.

- Carsten H. Pedersen
Messages d'erreurs en danois.

- Arjen G. Lentz
Messages d'erreurs en néerlandais, et fin de la traduction partielle.

29-D - Bibliothèques utilisées et incluses dans MySQL

Voici une liste des auteurs de bibliothèques que nous avons incluses dans le source du serveur MySQL, pour le rendre plus facile à compiler et à installer. Nous sommes reconnaissants envers ceux qui les ont créées : ils nous ont facilité la vie.

- Fred Fish
Pour son excellente bibliothèque de débogage et de trace. Monty a ajouté de nombreuses petites améliorations à la bibliothèque (en termes de vitesse et fonctionnalités).

- Richard A. O'Keefe
Pour la bibliothèque de gestion des chaînes de caractères, disponible dans le domaine public.

- Henry Spencer
Pour sa bibliothèque d'expressions régulières, utilisée dans WHERE column REGEXP regexp.

- Chris Provenzano
Pthreads utilisateurs. Dans le copyright : This product includes software developed by Chris Provenzano, the University of California, Berkeley, and contributors. Nous utilisons la version 1_60_beta6, modifiée par Monty (voir mit-pthreads/Changes-mysql).

- Jean-Loup Gailly et Mark Adler
Pour la bibliothèque zlib (utilisée avec MySQL sous Windows).

- Bjorn Benson
Pour son paquet safe_malloc (contrôle de mémoire), qui est utilisé lorsque vous configurez MySQL avec --debug.

- Free Software Foundation
La bibliothèque readline (utilisée par le client mysql).

- La fondation NetBSD
Le paquet libedit (utilisé optionnellement par le client mysql).

29-E - Applications qui supportent MySQL

Voici une liste de responsables et auteurs d'interfaces, applications et paquets, que de nombreuses personnes utilisent avec MySQL.

Nous ne pouvons pas lister tous les paquets possibles, car la liste serait trop difficile à entretenir. Pour les autres paquets, voyez le portail d'applications à http://www.mysql.com/portal/software.

- Tim Bunce, Alligator Descartes
Pour l'interface DBD (Perl).

- Andreas Koenig <a.koenig@mind.de>
Pour l'interface Perl avec MySQL.

- Jochen Wiedmann <wiedmann@neckar-alb.de>
Pour le module Perl DBD::mysql.

- Eugene Chan <eugene@acenet.com.sg>
Pour le port de PHP sur MySQL Server.

- Georg Richter
Tests de MySQL 4.1 et chasse aux bogues. Nouvelles extensions PHP 5.0 mysqli (API) pour MySQL 4.1 et plus récents.

- Giovanni Maruzzelli <maruzz@matrice.it>
Pour le port de iODBC (Unix ODBC).

- Xavier Leroy <Xavier.Leroy@inria.fr>
L'auteur de LinuxThreads (utilisé par MySQL Server sur Linux).

29-F - Outils utilisés pour créer MySQL

Voici une liste des outils que nous avons utilisés pour créer MySQL. Nous utilisons cette page pour remercier les auteurs qui les ont créés, et sans lesquels nous n'aurions pas pu faire de MySQL ce qu'il est aujourd'hui.

- Free Software Foundation
De qui nous avons reçu un excellent compilateur (gcc), un excellent débogueur (gdb et la bibliothèque libc (à laquelle nous avons emprunté le fichier strto.c pour faire fonctionner du code sur Linux).

- Free Software Foundation & l'équipe de développement XEmacs
Pour un éditeur texte et un environnement de programmation fantastique, utilisé par presque tout le monde chez MySQL AB.

- Julian Seward
L'auteur de valgrind, un excellent outil de vérification de mémoire, qui nous a aidés à trouver des bogues très difficiles à traquer.

- Dorothea Lütkehaus et Andreas Zeller
Pour DDD (Le Data Display Debugger) qui est une excellente interface graphique pour gdb).

29-G - Supporters de MySQL

Tandis que MySQL AB possède tous les droits du serveur MySQL et du manuel MySQL, nous voulons montrer notre reconnaissance aux compagnies suivantes, qui nous ont aidés à financer le développement du serveur MySQL, soit en nous payant pour développer de nouvelles fonctionnalités, soit en nous fournissant en matériel pour le développement du serveur MySQL.

- VA Linux / Andover.net
Financement de la réplication.

- NuSphere
Édition du manuel MySQL.

- Stork Design studio
Le site web MySQL utilisé entre 1998 et 2000.

- Intel
Contribution au développement sur les plates-formes Windows et Linux.

- Compaq
Contribution au développement sur Linux/Alpha.

- SWSoft
Développement de la version embarquée mysqld.

- FutureQuest
--skip-show-database

29-H - Les évolutions de MySQL (la liste des tâches)

Cette section liste les fonctionnalités que nous prévoyons d'ajouter à MySQL. Les listes sont réparties par version, et les actions sont réparties approximativement par ordre de priorité.

Note : si vous êtes un utilisateur professionnel, avec un besoin urgent pour une fonctionnalité, contactez <sales@mysql.com> pour discuter de possibilités de sponsor. En allouant des finances à certaines fonctionnalités, nous pouvons nous concentrer sur certains objectifs à court terme. Un des exemples de fonctionnalité sponsorisée est la réplication.

29-H-1 - Nouvelles fonctionnalités prévues pour la version 5.0

Les fonctionnalités suivantes sont prévues pour la version 5.0. Notez que comme nous avons de nombreux développeurs qui travaillent sur différents projets, il peut aussi y avoir des ajouts de fonctionnalités. Il y a aussi des chances que ces fonctionnalités soient ajoutées en MySQL 4.1. Pour une liste des fonctionnalités déjà disponibles en MySQL 4.1, voyez Section 1.3.2.1, « Fonctionnalités disponibles en MySQL 4.1 ».

Pour ceux qui souhaitent étudier en détail les tout derniers développements de MySQL, vous pouvez accéder au serveur BitKeeper public de MySQL 5.0. Voir Section 2.4.3, « Installer à partir de l'arbre source de développement ». Depuis décembre 2003, des versions binaires pour les versions 5.0 sont aussi disponibles.

- Procédures stockées

- Les procédures stockées sont actuellement développées avec notre version 5.0. Voir Chapitre 19, Procédures stockées et fonctions.
Nous allons aussi ajouter un environnement pour permettre l'utilisation de langages externes et assurer (lorsque c'est possible) une compatibilité avec PL/SQL et T-SQL.

- Nouvelles fonctionnalités

- Support élémentaire des curseurs. Voir Section 19.2.11, « Curseurs ».

- La capacité de spécifier explicitement pour les tables MyISAM qu'un index est de type RTREE. En version 4.1, les index RTREE sont généralement utilisés pour les données géométriques (types GIS), mais ne peuvent pas être créés à la demande.

- Les tables HEAP à taille de ligne dynamique.

- Compatibilité avec les standards, portabilité et migration.

- Ajout d'un véritable type VARCHAR (ce support est déjà disponible avec le format de table MyISAM).

- Amélioration de la vitesse

- SHOW COLUMNS FROM table_name (utilisé par le client mysql pour permettre la recherche de nom de colonnes) ne devrait pas ouvrir la table, mais seulement le fichier de définition. Cela prendra moins de mémoire, et sera bien plus rapide.

- Permettre à la commande DELETE sur les tables MyISAM l'utilisation des caches de lignes. Pour cela, nous devons modifier le thread de cache de ligne lorsque nous modifions le fichier .MYD.

- Amélioration des tables en mémoire HEAP :

- Lignes de taille dynamique.

- Gestion plus rapide des lignes (moins de copies).

- Amélioration de l'ergonomie

- Résolution du problème avec RENAME TABLE, utilisé sur une table active dans un MERGE, qui conduit à la corruption de la table.

Le manuel inclut le changelog de la version, avec plus de détails sur les nouvelles fonctionnalités. Voir Section C.1, « Changements de la version 5.0.0 (Développement) ».

29-H-2 - Nouvelles fonctionnalités prévues pour 5.1

- Nouvelle fonctionnalité

- FOREIGN KEY supporte tous les types de tables.

- Contraintes de niveau colonne.

- Réplication protégée contre les crash.

- Sauvegarde à chaud, avec peu d'impact sur les performances. La sauvegarde à chaud permettra de simplifier l'ajout d'esclaves de réplication sans avoir à éteindre le maître.

- Amélioration de la vitesse

- Nouveau format de définition des tables en format texte (fichiers .frm) et un cache de table pour les définitions de tables. Cela permettra d'accélérer les requêtes de structure de tables, et de consolider le support des clés étrangères.

- Optimisation du type BIT pour qu'il prenne 1 bit (actuellement, BIT prend 1 caractère).

- Amélioration de l'ergonomie

- Ajout d'options au protocole client/serveur pour obtenir des indications de progression pour les requêtes longues.

- Implémentation de RENAME DATABASE. Pour que cela soit sécuritaire pour tous les pilotes de stockage, cela doit fonctionner comme ceci :

- crée une nouvelle base de données ;

- pour chaque table, faire un renommage d'une base à l'autre, comme nous le faisons avec RENAME ;

- effacer l'ancienne base.

- Nouvelle interface interne pour les fichiers. Cela rendra la gestion des fichiers bien plus générale et simplifiera l'ajout d'extensions comme RAID (l'implémentation actuelle est un bidouillage).

29-H-3 - Ce qui doit être fait dans un futur proche

- Nouvelle fonctionnalité

- Commande CONNECT BY PRIOR ..., inspirée d'Oracle, pour traiter les structures de type arbre (hiérarchisée).

- Tous les types manquants de ANSI92 et ODBC 3.0.

- Ajout de SUM(DISTINCT).

- INSERT SQL_CONCURRENT et mysqld --concurrent-insert pour faire des insertions concurrentes à la fin du fichier, même s'il est verrouillé en lecture.

- Permettre la modification de variables dans une commande UPDATE. Par exemple : UPDATE TABLE foo SET @a=a+b,a=@a, b=@a+c.

- Changer le moment de modifications des variables, pour que l'on puisse les utiliser avec les commandes de groupement GROUP BY, comme ceci : SELECT id, @a:=COUNT(*), SUM(sum_col)/@a FROM table_name GROUP BY id.

- Ajout de l'option IMAGE à la commande LOAD DATA INFILE pour ne pas modifier les champs TIMESTAMP et AUTO_INCREMENT.

- Ajout de la syntaxe LOAD DATE INFILE ... UPDATE, qui fonctionne comme ceci :

- pour les tables ayant des clés primaires, si les données contiennent une clé primaire, les données qui existent et correspondent à cette clé sont modifiées. Cependant, les colonnes omises sont ignorées ;

- pour les tables ayant une clé primaire dont il manque une partie dans les données entrantes, ou qui n'ont pas de clé primaire, le flux est traité comme LOAD DATA INFILE ... REPLACE INTO.

- Rendre la syntaxe LOAD DATA INFILE utilisable comme ceci :

LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
TEXT_FIELDS (text_field1, text_field2, text_field3)
SET table_field1=CONCAT(text_field1, text_field2),
table_field3=23
IGNORE text_field3

Cela peut être utilisé pour ignorer des colonnes supplémentaires dans le fichier texte, ou pour modifier des colonnes en fonction de données dans les valeurs entrantes.

- De nouvelles fonctions pour travailler avec le type de colonne SET :

- ADD_TO_SET(value,set)

- REMOVE_FROM_SET(value,set)

- Si vous interrompez mysql au beau milieu d'une requête, vous pouvez ouvrir une autre connexion pour tuer la requête en cours. Ou bien, une tentative doit être faite pour détecter cela sur le serveur.

- Ajout d'une interface au moteur de sauvegarde pour que vous puissiez l'utiliser comme table système. Cela sera un peu lent si vous demandez toutes les informations de toutes les tables, mais très souple. SHOW INFO FROM tbl_name doit être implémenté pour connaître les informations de base des tables.

- Permettre SELECT a FROM crash_me LEFT JOIN crash_me2 USING (a); dans ce cas, a est supposé provenir de la table crash_me.

- Les options DELETE et REPLACE dans les commandes UPDATE (cela va effacer les lignes lors d'un doublon dans la requête).

- Modification du format de DATETIME pour stocker les fractions de seconde.

- Rendre possible l'utilisation de la bibliothèque GNU regexp au lieu de la bibliothèque actuelle (la bibliothèque GNU devrait être plus rapide que l'ancienne).

- Compatibilité avec les standards, migration et portabilité.

- Ne pas utiliser de valeur par défaut (DEFAULT) pour les colonnes. Indiquer une erreur lors des commandes INSERT, si elle contient une colonne qui n'a pas de valeur par défaut.

- Ajout des fonctions de groupement ANY(), EVERY() et SOME(). En ANSI SQL, elles ne fonctionnent que sur les colonnes de type booléen, mais nous pouvons étendre leur champ d'action aux colonnes et expression, en appliquant la règle suivante : value == 0 -> FALSE et value <> 0 -> TRUE.

- Correction du type pour que MAX(column) ait le même type de colonne :

mysql> CREATE TABLE t1 (a DATE);
mysql> INSERT INTO t1 VALUES (NOW());
mysql> CREATE TABLE t2 SELECT MAX(a) FROM t1;
mysql> SHOW COLUMNS FROM t2;

- Amélioration des performances

- Ne permettre qu'à un nombre défini de threads d'exécuter des réparations MyISAM simultanément.

- Changer INSERT ... SELECT pour utiliser optionnellement des insertions simultanées.

- Ajouter une option pour écrire sur le disque les pages de clés pour les tables à clés retardées, qui n'ont pas été sauvées dernièrement.

- Permettre les jointures sur des parties de clés (problème d'optimisation).

- Un analyseur de logs, qui permettrait d'extraire des informations sur les tables le plus souvent utilisées, les jointures, etc. Cela permettra aux utilisateurs d'identifier les tables qui peuvent être optimisées.

- Internationalisation

- Ergonomie

- Retourner le type de champ original lors des requêtes SELECT MIN(column) ... GROUP BY.

- Rendre possible la spécification de long_query_time avec une granularité de l'ordre de la microseconde.

- Intégrer le code de myisampack dans le serveur, activer les commandes PACK or COMPRESS depuis le serveur.

- Ajouter un cache de buffer de clés temporaires durant les commandes INSERT/DELETE/UPDATE pour que nous puissions nous rétablir si jamais le fichier d'index est plein.

- Si vous effectuez la commande ALTER TABLE sur une table qui est un lien symbolique sur un autre disque, les tables temporaires seront aussi faites sur ce disque.

- Implémenter un type DATE/DATETIME qui gère les fuseaux horaires correctement, pour résoudre le problème du décalage horaire.

- Corriger la configuration pour que l'on puisse compiler toutes les bibliothèques (comme MyISAM) sans les threads.

- Permettre toutes les variables SQL dans la clause LIMIT, comme LIMIT @a,@b.

- Affichage automatique de mysql vers un navigateur web.

- LOCK DATABASES (avec différentes options).

- De nombreuses nouvelles variables dans SHOW STATUS. Les lignes lues et modifiées. Les sélections sur tables uniques et les jointures. Le nombre moyen de tables dans une sélection. Le nombre de requêtes ORDER BY et GROUP BY.

- mysqladmin copy database new-database; a besoin de la commande COPY dans mysqld.

- La liste des processus doit afficher le nombre de requêtes et de threads.

- SHOW HOSTS affichera les informations concernant le cache de noms d'hôtes.

- Changer le nom des tables de chaîne vide à NULL pour les colonnes calculées.

- Ne pas utiliser la fonction Item_copy_string sur les valeurs numériques, pour éviter les conversions nombre -> chaine -> chaine en cas de : SELECT COUNT(*)*(id+0) FROM table_name GROUP BY id

- Changer ALTER TABLE pour qu'il n'interrompe pas le client qui exécute des INSERT DELAYED.

- Lorsque les colonnes sont spécifiées dans UPDATE, elles contiennent les anciennes valeurs d'avant la modification.

- Nouveaux systèmes d'exploitation.

- Port des clients MySQL vers LynxOS.

29-H-4 - Ce qui est prévu à moyen terme

- Implémenter la fonction : get_changed_tables(timeout,table1,table2,...).

- Remplacer la lecture dans les tables par une zone mémoire aussi souvent que possible. Actuellement, seules les tables compressées utilisent des memmap.

- Rendre le code des timestamp automatiques bien plus pratique. Ajouter les timestamps dans le log avec SET TIMESTAMP=#;.

- Utiliser un mutex de lecture/écriture pour gagner de la vitesse.

- Vues simples (implémentation progressive jusqu'à support total). Voir Section 1.5.5.6, « Les vues ».

- Fermer automatiquement des tables si une table, une table temporaire ou un fichier temporaire reçoit une erreur 23 (plus assez de fichiers ouverts).

- Meilleure propagation des constantes. Lorsqu'une occurrence de col_name=n est trouvée dans une expression, pour une n, remplacer les autres occurrences de col_name de l'expression avec n. Actuellement, cela n'arrive que pour les cas les plus simples.

- Changer toutes les expressions constantes par des expressions calculées, si possible.

- Optimiser les comparaisons key = expression. Actuellement, seules les relations key = column or key = constant sont optimisées.

- Fusionner les fonctions de copie pour améliorer le code.

- Changez sql_yacc.yy pour le remplacer par un analyseur de ligne de commande plus petit, et qui gère mieux les messages.

- Changer l'analyseur pour utiliser uniquement une règle pour tous les nombres d'arguments possibles dans une fonction.

- Utiliser les calculs de noms complets dans la clause ORDER (pour ACCESS97).

- MINUS, INTERSECT et FULL OUTER JOIN. (actuellement, UNION [en 4.0] et LEFT OUTER JOIN fonctionnent).

- SQL_OPTION MAX_SELECT_TIME=# pour donner une limite de temps à une requête.

- Diriger le log de modification vers une base.

- Améliorer LIMIT pour permettre la lecture de données à la fin du résultat.

- Alertes lors des connexions/écritures/lectures du client.

- Notez ces modifications de safe_mysqld : selon la FSSTND (que Debian essaie de suivre) les fichiers PID devraient être placés dans /var/run/<progname>.pid et les fichiers de logs dans /var/log. Il serait bien si vous pouviez mettre le « DATADIR » dans la première déclaration de « pidfile » et « log », de façon à ce que l'emplacement de ces fichiers puisse être modifié en une seule ligne.

- Permettre au client de commander le log des actions.

- Ajouter l'utilisation de zlib() pour les fichiers gzip, avec la commande LOAD DATA INFILE.

- Corriger le tri et le groupage avec les colonnes BLOB (en partie résolu).

- Utiliser des sémaphores pour compter les threads. Il faut commencer par implémenter des sémaphores pour MIT-pthreads.

- Ajouter le support complet pour les JOIN avec parenthèses.

- Comme alternative à la relation un thread, une connexion, gérer un groupe de threads pour répondre aux requêtes.

- Permettre la pose de plusieurs verrous avec GET_LOCK. Lors de ces verrous multiples, gérer le cas des blocages par verrous qui pourrait être introduit.

Le temps est indiqué en temps de travail et non pas en temps normal.

29-H-5 - Ce qui n'est pas prévu

Rien. Nous nous dirigeons vers la compatibilité complète avec ANSI 92/ANSI 99.

30 - Historique des changements MySQL

Cet appendice liste les changements de version à version dans le code source de MySQL.

Nous travaillons maintenant activement sur MySQL 4.1 et 5.0 et ne fournirons que les correctifs pour les bogues critiques de MySQL 3.23 et 4.0. Nous mettons à jour cette section lorsque nous ajoutons de nouvelles fonctionnalités pour que tout le monde puisse suivre le cours du développement.

Notre section TODO contient ce que nous planifions pour les versions 4.x. Voir Section B.8, « Les évolutions de MySQL (la liste des tâches) ».

Notez que nous essayons de mettre à jour le manuel en même temps que nous apportons des changements à MySQL. Si vous trouvez une version mentionnée ici que vous ne pouvez retrouver dans la page des téléchargements MySQL (http://www.mysql.com/downloads/), cela signifie que la version n'a pas encore été publiée !

La date mentionnée avec la version est la date de dernière modification dans le serveur BitKeeper, sur laquelle la version a été bâtie. Les exécutables sont généralement disponibles après quelques jours, car il faut du temps pour compiler et tester tous les paquets.

30-A - Changements de la version 5.0.0 (Développement)

The following changelog shows what has already been done in the 5.0 tree:

- Basic support for stored procedures (SQL:2003 style). Voir Chapitre 19, Procédures stockées et fonctions.

- Added SELECT INTO list_of_vars, which can be of mixed, that is, global and local type. Voir Section 19.2.9.3, « Syntaxe de SELECT ... INTO ».

- Removed the update log. It is fully replaced by the binary log. If the MySQL server is started with --log-update, it will be translated to --log-bin (or ignored if the server is explicitly started with --log-bin), and a warning message will be written to the error log. Setting SQL_LOG_UPDATE will silently set SQL_LOG_BIN instead (or do nothing if the server is explicitly started with --log-bin).

- User variable names are now case insensitive: if you do SET @a=10; then SELECT @A; will now return 10. Case sensitivity of a variable's value depends on the collation of the value.

For a full list of changes, please refer to the changelog sections for each individual 5.0.x release.

30-A-1 - Changements de la version 5.0.6 (pas encore publiée)

Fonctionnalités ajoutées ou modifiées :

- Updated version of libedit to 2.9. (Bug #2596)

Bogues corrigés :

- MAX() for an INT UNSIGNED (unsigned 4-byte integer) column could return negative values if the column contained values larger than 2^31. (Bug #9298)

- SHOW CREATE VIEW got confused and could not find the view if there was a temporary table with the same name as the view. (Bug #8921)

- Fixed a deadlock resulting from use of FLUSH TABLES WITH READ LOCK while an INSERT DELAYED statement is in progress. (Bug #7823)

- The optimizer was choosing suboptimal execution plans for certain outer joins where the right table of a left join (or left table of a right join) had both ON and WHERE conditions. (Bug #10162)

- RENAME TABLE for an ARCHIVE table failed if the .arn file was not present. (Bug #9911)

- Invoking a stored function that executed a SHOW statement resulted in a server crash. (Bug #8408)

- Fixed problems with static variables and do not link with libsupc++ to allow building on FreeBSD 5.3. (Bug #9714)

- Fixed some awk script portability problems in cmd-line-utils/libedit/makelist.sh. (Bug #9954)

- Fixed a problem with mishandling of NULL key parts in hash indexes on VARCHAR columns, resulting in incorrect query results. (Bug #9489, Bug #10176)

30-A-2 - Changements de la version 5.0.5 (Bientôt publiée)

Fonctionnalités ajoutées ou modifiées :

- Added support for the BIT data type to the MEMORY, InnoDB, and BDB storage engines.

- SHOW VARIABLES no longer displays the deprecated log_update system variable. (Bug #9738)

- --innodb-fast-shutdown is now also settable on the fly (global variable innodb_fast_shutdown). It now accepts values 0, 1 and 2 (except on Netware where 2 is disabled); if set to 2, then when the MySQL server shuts down, InnoDB will just flush its logs and then shut down brutally (and quickly) as if it was a MySQL crash; no committed transaction will be lost, but a crash recovery will be done at next startup.

Bogues corrigés :

- Security fix : If mysqld was started with --user=non_existent_user, it would run using the privileges of the account it was invoked from, even if that was root. (Bug #9833)

- Multiple-table updates could produce spurious data-truncation warnings if they used a join across columns that are indexed using a column prefix. (Bug #9103)

- Fixed a string-length comparison problem that caused mysql to fail loading dump files containing certain '\'-sequences. (Bug #9756)

- Fixed a failure to resolve a column reference properly when an outer join involving a view contained a subquery and the column was used in the subquery and the outer query. (Bug #6106, Bug #6107)

- Use of a subquery that used WITH ROLLUP in the FROM clause of the main query sometimes resulted in a Column cannot be null error. (Bug #9681)

- Fixed a memory leak that occurred when selecting from a view that contained a subquery. (Bug #10107)

- Fixed an optimizer bug in computing the union of two ranges for the OR operator. (Bug #9348)

- Fixed a segmentation fault in mysqlcheck that occurred when the last table checked in --auto-repair mode returned an error (such as the table being a MERGE table). (Bug #9492)

- Incorrect results were returned for queries of the form SELECT ... LEFT JOIN ... WHERE EXISTS (subquery), where the subquery selected rows based on an IS NULL condition. (Bug #9516)

- Executing LOCK TABLES and then calling a stored procedure caused an error and resulting in the server thinking that no stored procedures exist. (Bug #9566)

- Selecting from a view containing a subquery caused the server to hang. (Bug #8490)

- Attempting to execute a multiple-table UPDATE within a stored procedure failed with a Table 'tbl_name' was locked with a READ lock and can't be updated error. (Bug #9486)

- Starting mysqld with the --skip-innodb and --default-storage-engine=innodb (or --default-table-type=innodb caused a server crash. (Bug #9815)

- Queries containing CURRENT_USER() incorrectly were registered in the query cache. (Bug #9796)

- Setting the storage_engine system variable to MEMORY succeeded, but retrieving the variable resulted in a value of HEAP (the old name for the MEMORY storage engine) rather than MEMORY. (Bug #10039)

- mysqlshow displayed an incorrect row count for tables. (Bug #9391)

- The server died with signal 11 if a non-existent location was specified for the location of the binary log. Now the server exits after printing an appropriate error messsage. (Bug #9542)

- Fixed a problem in the client/server protocol where the server closed the connection before sending the final error message. The problem could show up as a Lost connection to MySQL server during query when attempting to connect to access a non-existent database. (Bug #6387, Bug #9455)

- Fixed a readline-related crash in mysql when the user pressed Control-R. (Bug #9568)

- For stored functions that should return a YEAR value, corrected a failure of the value to be in YEAR format. (Bug #8861)

- Fixed a server crash resulting from invocation of a stored function that returned a value having an ENUM or SET data type. (Bug #9775)

- Fixed a server crash resulting from invocation of a stored function that returned a value having a BLOB data type. (Bug #9102)

- Fixed a server crash resulting from invocation of a stored function that returned a value having a BIT data type. (Bug #7648)

- TIMEDIFF() with a negative time first argument and postive time second argument produced incorrect results. (Bug #8068)

- Fixed a problem with OPTIMIZE TABLE for InnoDB tables being written twice to the binary log. (Bug #9149)

- InnoDB : Prevent ALTER TABLE from changing the storage engine if there are foreign key constraints on the table. (Bug #5574, Bug #5670)

- InnoDB : Fixed a bug where next-key locking doesn't allow the insert which does not produce a phantom. (Bug #9354) If the range is of type 'a' <= uniquecolumn, InnoDB lock only the RECORD, if the record with the column value 'a' exists in a CLUSTERED index. This allows inserts before a range.

- InnoDB : When FOREIGN_KEY_CHECKS=0, ALTER TABLE and RENAME TABLE will ignore any type incompatibilities between referencing and referenced columns. Thus, it will be possible to convert the character sets of columns that participate in a foreign key. Be sure to convert all tables before modifying any data! (Bug #9802)

- Provide more informative error messages in clustered setting when a query is issued against a table that has been modified by another mysqld server. (Bug #6762)

30-A-3 - Changements de la version 5.0.4 (16 avril 2005)

Fonctionnalités ajoutées ou modifiées :

- Added ENGINE=MyISAM table option when creating mysql.proc table in mysql_create_system_tables script to make sure the table is created as a MyISAM table even if the default storage engine has been changed. (Bug #9496)

- SHOW CREATE TABLE for an INFORMATION_SCHEMA table no longer prints a MAX_ROWS value because the value has no meaning. (Bug #8941)

- Invalid DEFAULT values for CREATE TABLE now generate errors. (Bug #5902)

- Added --show-table-type option to mysqlshow, to display a column indicating the table type, as in SHOW FULL TABLES. (Bug #5036)

- The way the time zone information is stored into the binary log was changed, so that it's now possible to have a replication master and slave running with different global time zones. A drawback is that replication from 5.0.4 masters to pre-5.0.4 slaves is impossible.

- Added --with-big-tables compilation option to configure. (Previously it was necessary to pass -DBIG_TABLES to the compiler manually in order to enable large table support.) Voir Section 2.4.2, « Options habituelles de configure » for details.

- New configuration directives !include and !includedir implemented for including option files and searching directories for option files. Voir Section 4.3.2, « Fichier d'options my.cnf » for usage.

Bogues corrigés :

- The use of XOR together with NOT ISNULL() erroneously resulted in some outer joins being converted to inner joins by the optimizer. (Bug #9017)

- Fixed an optimizer problem where extraneous comparisons between NULL values in indexed columns were being done for operators such as = that are never true for NULL. (Bug #8877)

- Fixed the client/server protocol for prepared statements so that reconnection works properly when the connection is killed while reconnect is enabled. (Bug #8866)

- A server installed as a Windows service and started with --shared-memory could not be stopped. (Bug #9665)

- Fixed a server crash resulting from multiple executions of a prepared statement involving a join of an INFORMATION_SCHEMA table with another table. (Bug #9383)

- Fixed utf8_spanish2_ci and ucs2_spanish2_ci collations to not consider 'r' equal to 'rr'. If you upgrade to this version from an earlier version, you should rebuild the indexes of affected tables. (Bug #9269)

- mysqldump dumped core when invoked with --tmp and --single-transaction options and a non-existent table name. (Bug #9175)

- Allow extra HKSCS and cp950 characters (big5 extension characters) to be accepted in big5 columns. (Bug #9357)

- mysql.server no longer uses non-portable alias command or LSB functions. (Bug #9852)

- Fixed a server crash resulting from GROUP BY on a decimal expression. (Bug #9210)

- In prepared statements, subqueries containing parameters were erroneously treated as const tables during preparation, resulting in a server crash. (Bug #8807)

- InnoDB : ENUM and SET columns were treated incorrectly as character strings. This bug did not manifest itself with latin1 collations if there were less than about 100 elements in an ENUM, but it caused malfunction with UTF-8. Old tables will continue to work. In new tables, ENUM and SET will be internally stored as unsigned integers. (Bug #9526)

- InnoDB : Avoid test suite failures caused by a locking conflict between two server instances at server shutdown/startup. This conflict on advisory locks appears to be the result of a bug in the operating system; these locks should be released when the files are closed, but somehow that does not always happen immediately in Linux. (Bug #9381)

- InnoDB : True VARCHAR : InnoDB stored the 'position' of a row wrong in a column prefix primary key index; this could cause MySQL to complain ERROR 1032: Can't find record ... in an update of the primary key, and also some ORDER BY or DISTINCT queries. (Bug #9314)

- InnoDB : Fix bug in MySQL/InnoDB 5.0.3 : SQL statements were not rolled back on error. (Bug #8650)

- Fixed a Commands out of sync error when two prepared statements for single-row result sets were open simultaneously. (Bug #8880)

- Fixed a server crash after a call to mysql_stmt_close() for single-row result set. (Bug #9159)

- Fixed server crashes for CREATE TABLE ... SELECT or INSERT INTO ... SELECT when selecting from multiple-table view. (Bug #8703, Bug #9398)

- TRADITIONAL SQL mode should prevent inserts where a column with no default value is omitted or set to a value of DEFAULT. Fixed cases where this restriction was not enforced. (Bug #5986)

- Fixed a server crash when creating a PRIMARY KEY for a table, if the table contained a BIT column. (Bug #9571)

- Warning message from GROUP_CONCAT() did not always indicate correct number of lines. (Bug #8681)

- The commit count cache for NDB was not properly invalidated when deleting a record using a cursor. (Bug #8585)

- Fixed option-parsing code for the embedded server to understand K, M, and G suffixes for the net_buffer_length and max_allowed_packet options. (Bug #9472)

- Selecting a BIT column failed if the binary client/server protocol was used. (Bug #9608)

- Fixed a permissions problem whereby information in INFORMATION_SCHEMA could be exposed to a user with insufficient privileges. (Bug #7214)

- An error now occurs if you try to insert an invalid value via a stored procedure in STRICT mode. (Bug #5907)

- Link with libsupc++ on Fedora Core 3 to get language support functions. (Bug #6554)

- The value of the CHARACTER_MAXIMUM_LENGTH and CHARACTER_OCTET_LENGTH columns of the INFORMATION_SCHEMA.COLUMNS table must be NULL for numeric columns, but were not. (Bug #9344)

- DROP TABLE did not drop triggers that were defined for the table. DROP DATABASE did not drop triggers in the database. (Bug #5859, Bug #6559)

- CREATE OR REPLACE VIEW and ALTER VIEW now require the CREATE VIEW and DROP privileges, not CREATE VIEW and DELETE. (DELETE is a row-level privilege, not a table-level privilege.) (Bug #9260)

- Some user variables were not being handled with « implicit » coercibility. (Bug #9425)

- Setting the max_error_count system variable to 0 resulted in a setting of 1. (Bug #9072)

- Fixed a collation coercibility problem that caused a union between binary and non-binary columns to fail. (Bug #6519)

- Fixed a bug in division of floating point numbers. It could cause nine zeroes (000000000) to be inserted in the middle of the quotient. (Bug #9501)

- INFORMATION_SCHEMA tables had an implicit upper limit for the number of rows. As a result, not all data could be returned for some queries. (Bug #9317)

- Fixed a problem with the tee command in mysql that resulted in mysql crashing. (Bug #8499)

- CAST() now produces warnings when casting a wrong INTEGER and CHAR values. This also applies to implicite string to number casts. (Bug #5912)

- ALTER TABLE now fails in STRICT mode if generates warnings.

- Using CONVERT('0000-00-00',date) or CAST('0000-00-00' as date) in TRADITIONAL mode now produces a warning. (Bug #6145)

- Inserting a zero date in a DATE, DATETIME or TIMESTAMP column during TRADITIONAL mode now produces an error. (Bug #5933)

- Inserting a zero date into a DATETIME column in TRADITIONAL mode now produces an error.

- STR_TO_DATE() now produces errors in strict mode (and warnings otherwise) when given an illegal argument. (Bug #5902)

- Fixed a problem with ORDER BY that sometimes caused incorrect sorting of utf8 data. (Bug #9309)

- Fixed server crash resulting from queries that combined SELECT DISTINCT, SUM(), and ROLLUP. (Bug #8615)

- Incorrect results were returned from queries that combined SELECT DISTINCT, GROUP BY, and ROLLUP. (Bug #8616)

- Too many rows were returned from queries that combined ROLLUP and LIMIT if SQL_CALC_FOUND_ROWS was given. (Bug #8617)

- If on replication master a LOAD DATA INFILE is interrupted in the middle (integrity constraint violation, killed connection...), the slave used to skip this LOAD DATA INFILE entirely, thus missing some changes if this command permanently inserted/updated some table records before being interrupted. This is now fixed. (Bug #3247)

30-A-4 - Changements de la version 5.0.3 (23 mars 2005 : Beta)

Note : This Beta release, as any other pre-production release, should not be installed on « production » level systems or systems with critical data. It is good practice to back up your data before installing any new version of software. Although MySQL has done its best to ensure a high level of quality, protect your data by making a backup as you would for any software beta release.

Fonctionnalités ajoutées ou modifiées :

- New privilege CREATE USER was added.

- Security improvement : The server creates .frm, .MYD, .MYI, .MRG, .ISD, and .ISM table files only if a file with the same name does not already exist. Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0711)

- Security improvement : User-defined functions should have at least one symbol defined in addition to the xxx symbol that corresponds to the main xxx() function. These auxiliary symbols correspond to the xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear(), and xxx_add() functions. mysqld by default no longer loads UDFs unless they have at least one auxiliary symbol defined in addition to the main symbol. The --allow-suspicious-udfs option controls whether UDFs that have only an xxx symbol can be loaded. By default, the option is off. mysqld also checks UDF filenames when it reads them from the mysql.func table and rejects those that contain directory pathname separator characters. (It already checked names as given in CREATE FUNCTION statements.) Voir Section 27.2.3.1, « Fonctions utilisateur : appeler des fonctions simples », Section 27.2.3.2, « Appeler des fonctions utilisateurs pour les groupements », and Section 27.2.3.6, « Précautions à prendre avec les fonctions utilisateur ». Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0709, CAN-2005-0710)

- Support for the ISAM storage engine has been removed. If you have ISAM tables, you should convert them before upgrading. Voir Section 2.6.1, « Passer en de version 4.1 en version 5.0 ».

- Support for RAID options in MyISAM tables has been removed. If you have tables that use these options, you should convert them before upgrading. Voir Section 2.6.1, « Passer en de version 4.1 en version 5.0 ».

- Added support for AVG(DISTINCT).

- ONLY_FULL_GROUP_BY no longer is included in the ANSI composite SQL mode. (Bug #8510)

- mysqld_safe will create the directory where the UNIX socket file is to be located if the directory does not exist. This applies only to the last component of the directory pathname. (Bug #8513)

- The coercibility for the return value of functions such as USER() or VERSION() now is « system constant » rather than « implicit. » This makes these functions more coercible than column values so that comparisons of the two do not result in Illegal mix of collations errors. COERCIBILITY() was modified to accommodate this new coercibility value. Voir Section 12.8.3, « Fonctions d'informations ».

- User variable coercibility has been changed from « coercible » to « implicit. » That is, user variables have the same coercibility as column values.

- Boolean full-text phrase searching now requires only that matches contain exactly the same words as the phrase and in the same order. Non-word characters no longer need match exactly.

- CHECKSUM TABLE returns a warning for non-existing tables. The checksum value remains NULL as before. (Bug #8256)

- The server now includes a timestamp in the Ready for connections message that is written to the error log at startup. (Bug #8444)

- Added SQL_NOTES session variable to cause Note-level warnings not to be recorded. (Bug #6662)

- Allowed the service-installation command for Windows servers to specify a single option other than --defaults-file following the service name. This is for compatibility with MySQL 4.1. (Bug #7856)

- InnoDB : Upgrading from 4.1 : The sorting order for end-space in TEXT columns for InnoDB tables has changed. Starting from 5.0.3, InnoDB compares TEXT columns as space-padded at the end. If you have a non-unique index on a TEXT column, you should run CHECK TABLE on it, and run OPTIMIZE TABLE if the check reports errors. If you have a UNIQUE INDEX on a TEXT column, you should rebuild the table with OPTIMIZE TABLE.

- InnoDB : Commit after every 10,000 copied rows when executing ALTER TABLE, CREATE INDEX, DROP INDEX or OPTIMIZE TABLE. This makes it much faster to recover from an aborted operation.

- Added VAR_POP() and STDDEV_POP() as standard SQL aliases for the VARIANCE() and STDDEV() functions that compute population variance and standard deviation. Added new VAR_SAMP() and STDDEV_SAMP() functions to compute sample variance and standard deviation. (Bug #3190)

- Fixed a problem with out-of-order packets being sent (ERROR after OK or EOF) following a KILL QUERY statement. (Bug #6804)

- Retrieving from a view defined as a SELECT that mixed UNION ALL and UNION DISTINCT resulted in a different result than retrieving from the original SELECT. (Bug #6565)

- Fixed a problem with non-optimal index_merge query execution plans being chosen on IRIX. (Bug #8578)

- BIT in column definitions now is a distinct data type; it no longer is treated as a synonym for TINYINT(1).

- Bit-field values can be written using b'value' notation. value is a binary value written using 0s and 1s.

- From the Windows distribution, predefined accounts without passwords for remote users ("root@%", "@%") were removed (other distributions never had them).

- Added mysql_library_init() and mysql_library_end() as synonyms for the mysql_server_init() and mysql_server_end() C API functions. mysql_library_init() and mysql_library_end() are #define symbols, but the names more clearly indicate that they should be called when beginning and ending use of a MySQL C API library no matter whether the application uses libmysqlclient or libmysqld. (Bug #6149)

- SHOW COLUMNS now displays NO rather than blank in the Null output column if the corresponding table column cannot be NULL.

- Changed XML format for mysql from <col_name>col_value</col_name> to <field name="col_name">col_value</field> to allow for proper encoding of column names that are not legal as element names. (Bug #7811)

- Added --innodb-checksums and --innodb-doublewrite options for mysqld.

- Added --large-pages option for mysqld.

- Added multi_read_range system variable.

- SHOW DATABASES, SHOW TABLES, SHOW COLUMNS, and so forth display information about the INFORMATION_SCHEMA database. Also, several SHOW statements now accept a WHERE clause specifying which output rows to display. Voir Chapitre 22, La base de données d'informations INFORMATION_SCHEMA.

- Added the CREATE ROUTINE and ALTER ROUTINE privileges, and made the EXECUTE privilege operational.

- InnoDB : Corrected a bug in the crash recovery of ROW_FORMAT=COMPACT tables that caused corruption. (Bug #7973) There may still be bugs in the crash recovery, especially in COMPACT tables.

- When the MyISAM storage engine detects corruption of a MyISAM table, a message describing the problem now is written to the error log.

- InnoDB : When MySQL/InnoDB is compiled on Mac OS X 10.2 or earlier, detect the operating system version at run time and use the fcntl() file flush method on Mac OS X versions 10.3 and later. Apple had disabled fsync() in Mac OS X for internal disk drives, which caused corruption at power outages.

- InnoDB : Implemented fast TRUNCATE TABLE. The old approach (deleting rows one by one) may be used if the table is being referenced by foreign keys. (Bug #7150)

- Added cp932 (SJIS for Windows Japanese) and eucjpms (UJIS for Windows Japanese) character sets.

- Added several InnoDB status variables. Voir Section 5.2.4, « Variables de statut du serveur  ».

- Added the FEDERATED storage engine. Voir Section 14.6, « Le moteur de table FEDERATED ».

- SHOW CREATE TABLE now uses USING index_type rather than TYPE index_type to specify an index type. (Bug #7233)

- InnoDB now supports a fast TRUNCATE TABLE. One visible change from this is that auto-increment values for this table are reset on TRUNCATE.

- Added an error member to the MYSQL_BIND data structure that is used in the C API for prepared statements. This member is used for reporting data truncation errors. Truncation reporting is enabled via the new MYSQL_REPORT_DATA_TRUNCATION option for the mysql_options() C API function.

- API change : the reconnect flag in the MYSQL structure is now set to 0 by mysql_real_connect(). Only those client programs which didn't explicitly set this flag to 0 or 1 after mysql_real_connect() experience a change. Having automatic reconnection enabled by default was considered too dangerous (after reconnection, table locks, temporary tables, user and session variables are lost).

- FLUSH TABLES WITH READ LOCK is now killable while it's waiting for running COMMIT statements to finish.

- MEMORY (HEAP) can have VARCHAR() fields.

- VARCHAR columns now remember end space. A VARCHAR() column can now contain up to 65535 bytes. For more details, Voir Section C.1, « Changements de la version 5.0.0 (Développement) ». If the table handler doesn't support the new VARCHAR type, then it's converted to a CHAR column. Currently this happens for NDB tables.

- InnoDB : Introduced a compact record format that does not store the number of columns or the lengths of fixed-size columns. The old format can be requested by specifying ROW_FORMAT=REDUNDANT. The new format (ROW_FORMAT=COMPACT) is the default. The new format typically saves 20 % of disk space and memory.

- InnoDB : Setting the initial AUTO_INCREMENT value for an InnoDB table using CREATE TABLE ... AUTO_INCREMENT = n now works, and ALTER TABLE ... AUTO_INCREMENT = n resets the current value.

- Seconds_Behind_Master is NULL (which means « unknown ») if the slave SQL thread is not running, or if the slave I/O thread is not running or not connected to master. It is zero if the SQL thread has caught up to the I/O thread. It no longer grows indefinitely if the master is idle.

- The MySQL server aborts immediately instead of simply issuing a warning if it is started with the --log-bin option but cannot initialize the binary log at startup (that is, an error occurs when writing to the binary log file or binary log index file).

- The binary log file and binary log index file now are handled the same way as MyISAM tables when there is a « disk full » or « quota exceeded » error. Voir Section A.4.3, « Comment MySQL gère un disque plein ».

- The MySQL server now aborts when started with option --log-bin-index and without --log-bin, and when started with --log-slave-updates and without --log-bin.

- If the MySQL server is started without an argument to --log-bin and without --log-bin-index, thus not providing a name for the binary log index file, a warning is issued because MySQL falls back to using the hostname for that name, and this is prone to replication issues if the server's hostname's gets changed later. Voir Section 1.5.7.4, « Bugs connus / limitations de MySQL ».

- Added account-specific MAX_USER_CONNECTIONS limit, which allows you to specify the maximum number of concurrent connections for the account. Also, all limited resources now are counted per account (instead of being counted per user + host pair as it was before). Use the --old-style-user-limits option to get the old behavior.

- InnoDB : A shared record lock (LOCK_REC_NOT_GAP) is now taken for a matching record in the foreign key check because inserts can be allowed into gaps.

- InnoDB : Relaxed locking in INSERT...SELECT, single table UPDATE...SELECT and single table DELETE...SELECT clauses when innobase_locks_unsafe_for_binlog is used and isolation level of the transaction is not serializable. InnoDB uses consistent read in these cases for a selected table.

- Added a new global system variable slave_transaction_retries : if the replication slave SQL thread fails to execute a transaction because of an InnoDB deadlock or exceeded InnoDB's innodb_lock_wait_timeout or NDBCluster's TransactionDeadlockDetectionTimeout or TransactionInactiveTimeout, it automatically retries slave_transaction_retries times before stopping with an error. The default is 10. (Bug #8325)

- When a client releases a user-level lock, DO RELEASE_LOCK() will not be written to the binary log anymore (this makes the binary log smaller); as a counterpart, the slave does not actually take the lock when it executes GET_LOCK(). This is mainly an optimization and should not affect existing setups. (Bug #7998)

- The way the character set information is stored into the binary log was changed, so that it's now possible to have a replication master and slave running with different global character sets. A drawback is that replication from 5.0.3 masters to pre-5.0.3 slaves is impossible.

- The LOAD DATA statement was extended to support user variables in the target column list, and an optional SET clause. Now one can perform some transformations on data after they have been read and before they are inserted into the table. For example :

LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, @var1)
SET column2 = @var1/100;

Also, replication of LOAD DATA was changed, so you can't replicate such statements from a 5.0.3 master to pre-5.0.3 slaves.

Bogues corrigés :

- If a MyISAM table on Windows had INDEX DIRECTORY or DATA DIRECTORY table options, mysqldump dumped the directory pathnames with single-backslash pathname separators. This would cause syntax errors when importing the dump file. mysqldump now changes '\' to '/' in the pathnames on Windows. (Bug #6660)

- mysql_fix_privilege_tables now fixes that the mysql privilege tables can be used in MySQL 4.1. This allows one to easily downgrade to 4.1 or run MySQL 5.0 and 4.1 with the same privilege files for testing purposes.

- Fixed bug creating user with GRANT fails with password but works without, (Bug #7905)

- mysqldump misinterpreted '_' and '%' characters in the names of tables to be dumped as wildcard characters. (Bug #9123)

- The definition of the enumeration-valued sql_mode column of the mysql.proc table was missing some of the current allowable SQL modes, so stored routines would not necessarily execute with the SQL mode in effect at the time of routine definition. (Bug #8902)

- REPAIR TABLE did not invalidate query results in the query cache that were generated from the table. (Bug #8480)

- In strict or traditional SQL mode, too-long string values assigned to string columns (CHAR, VARCHAR, BINARY, VARBINARY, TEXT, or BLOB) were correctly truncated, but the server returned an SQLSTATE value of 01000 (should be 22001). (Bug #6999, Bug #9029)

- Stored functions that used cursors could return incorrect results. (Bug #8386)

- AES_DECRYPT(col_name,key) could fail to return NULL for invalid values in col_name, if col_name was declared as NOT NULL. (Bug #8669)

- Ordering by unsigned expression (more complex than a column reference) was treating the value as signed, producing incorrectly sorted results. (Bug #7425)

- HAVING was treating unsigned columns as signed. (Bug #7425)

- Fixed a problem with boolean full-text searches on utf8 columns where a double quote in the search string caused a server crash. (Bug #8351)

- For a query with both GROUP BY and COUNT(DISTINCT) clauses and a FROM clause with a subquery, NULL was returned for any VARCHAR column selected by the subquery. (Bug #8218)

- Fixed a bug in TRUNCATE, which did not work within stored procedures. A workaround has been made so that within stored procedures, TRUNCATE is executed like DELETE. This was necessary because TRUNCATE is implicitly locking tables. (Bug #8850)

- Fixed an optimizer bug that caused incorrectly ordered result from a query that used a FULLTEXT index to retrieve rows and there was another index that was usable for ORDER BY. For such a query, EXPLAIN showed fulltext join type, but regular (not FULLTEXT) index in the Key column. (Bug #6635)

- If SELECT DISTINCT named an index column multiple times in the select list, the server tried to access different key fields for each instance of the column, which could result in a crash. (Bug #8532)

- For a stored function that refers to a given table, invoking the function while selecting from the same table resulted in a server crash. (Bug #8405)

- Comparison of a DECIMAL column containing NULL to a subquery that produced DECIMAL values resulted in a server crash. (Bug #8397)

- The --set-character-set option for myisamchk was changed to --set-collation. The value needed for specifying how to sort indexes is a collation name, not a character set name. (Bug #8349)

- Hostname matching didn't work if a netmask was specified for table-specific privileges. (Bug #3309)

- Corruption of MyISAM table indexes could occur with TRUNCATE TABLE if the table had already been opened. For example, this was possible if the table had been opened implicitly by selecting from a MERGE table that mapped to the MyISAM table. The server now issues an error message for TRUNCATE TABLE under these conditions. (Bug #8306)

- Setting the connection collation to a value different from the server collation followed by a CREATE TABLE statement that included a quoted default value resulted in a server crash. (Bug #8235)

- Fixed handling of table-name matching in mysqlhotcopy to accommodate DBD::mysql 2.9003 and up (which implement identifier quoting). (Bug #8136)

- Selecting from a view defined as a join caused a server crash if the query cache was enabled. (Bug #8054)

- Results in the query cache generated from a view were not properly invalidated after ALTER VIEW or DROP VIEW on that view. (Bug #8050)

- FOUND_ROWS() returned an incorrect value after a SELECT SQL_CALC_FOUND_ROWS DISTINCT statement that selected constants and included GROUP BY and LIMIT clauses. (Bug #7945)

- Selecting from an INFORMATION_SCHEMA table combined with a subselect on an INFORMATION_SCHEMA table caused an error with the message Table tbl_name is corrupted. (Bug #8164)

- Fixed a problem with equality propagation optimization for prepared statements and stored procedures that caused a server crash upon re-execution of the prepared statement or stored procedure. (Bug #8115, Bug #8849)

- LEFT OUTER JOIN between an empty base table and a view on an empty base table caused a server crash. (Bug #7433)

- Use of GROUP_CONCAT() in the select list when selecting from a view caused a server crash. (Bug #7116)

- Use of a view in a correlated subquery that contains HAVING but no GROUP BY caused a server crash. (Bug #6894)

- Handling by mysql_list_fields() of references to stored functions within views was incorrect and could result in a server crash. (Bug #6814)

- mysqldump now avoids writing SET NAMES to the dump output if the server is older than version 4.1 and would not understand that statement. (Bug #7997)

- Fixed problems when selecting from a view that had an EXISTS or NOT EXISTS subquery. Selecting columns by name caused a server crash. With SELECT *, a crash did not occur, but columns in outer query were not resolved properly. (Bug #6394)

- DDL statements for views were not being written to the binary log (and thus not subject to replication). (Bug #4838)

- The CHAR() function was not ignoring NULL arguments, contrary to the documentation. (Bug #6317)

- Creating a table using a name containing a character that is illegal in character_set_client resulted in the character being stripped from the name and no error. The character now is considered an error. (Bug #8041)

- Fixed a problem with the Cyrillic letters I and SHORT I being treated the same by the utf8_general_ci collation. (Bug #8385)

- Some INFORMATION_SCHEMA columns that contained catalog identifiers were of type LONGTEXT. These were changed to VARCHAR(N, where N is the appropriate maximum identifier length. (Bug #7215)

- Some INFORMATION_SCHEMA columns that contained timestamp values were of type VARBINARY. These were changed to TIMESTAMP. (Bug #7217)

- An expression that tested a case-insensitive character column against string constants that differed in lettercase could fail because the constants were treated as having a binary collation. (For example, WHERE city='London' AND city='london' could fail.) (Bug #7098, Bug #8690)

- The output of the STATUS (\s) command in mysql had the values for the server and client character sets reversed. (Bug #7571)

- If the slave was running with --replicate-*-table options which excluded one temporary table and included another, and the two tables were used in a single DROP TEMPORARY TABLE IF EXISTS statement, as the ones the master automatically writes to its binary log upon client's disconnection when client has not explicitly dropped these, the slave could forget to delete the included replicated temporary table. Only the slave needs to be upgraded. (Bug #8055)

- When setting integer system variables to a negative value with SET VARIABLES, the value was treated as a positive value modulo 2^32. (Bug #6958)

- Corrected a problem with references to DUAL where statements such as SELECT 1 AS a FROM DUAL would succeed but statements such as SELECT 1 AS a FROM DUAL LIMIT 1 would fail. (Bug #8023)

- Fixed a server crash caused by DELETE FROM tbl_name ... WHERE ... ORDER BY tbl_name.col_name when the ORDER BY column was qualified with the table name. (Bug #8392)

- Fixed a bug in MATCH ... AGAINST in natural language mode that could cause a server crash if the FULLTEXT index was not used in a join (EXPLAIN did not show fulltext join mode) and the search query matched no rows in the table (Bug #8522).

- InnoDB : Honor the --tmpdir startup option when creating temporary files. Previously, InnoDB temporary files were always created in the temporary directory of the operating system. On Netware, InnoDB will continue to ignore --tmpdir. (Bug #5822)

- Platform and architecture information in version information produced for --version option on Windows was always Win95/Win98 (i32). More accurately determine platform as Win32 or Win64 for 32-bit or 64-bit Windows, and architecture as ia32 for x86, ia64 for Itanium, and axp for Alpha. (Bug #4445)

- If multiple semicolon-separated statements were received in a single packet, they were written to the binary log as a single event rather than as separate per-statement events. For a server serving as a replication master, this caused replication to fail when the event was sent to slave servers. (Bug #8436)

- Fixed LOAD INDEX statement to actually load index in memory. (Bug #8452)

- Fixed a failure of multiple-table updates to replicate properly on slave servers when --replicate-*-table options had been specified. (Bug #7011)

- Fixed failure of CREATE TABLE ... LIKE Windows when the source or destination table was located in a symlinked database directory. (Bug #6607)

- With lower_case_table_names set to 1, mysqldump on Windows could write the same table name in different lettercase for different SQL statements. Fixed so that consistent lettercase is used. (Bug #5185)

- mysqld_safe now understands the --help option. Previously, it ignored the option and attempted to start the server anyway. (Bug #7931)

- Fixed problem in NO_BACKSLASH_ESCAPES SQL mode for strings that contained both the string quoting character and backslash. (Bug #6368)

- Fixed some portability issues with overflow in floating point values.

- Prepared statements now gives warnings on prepare.

- Fixed bug in prepared statements with SUM(DISTINCT...).

- Fixed bug in prepared statements with OUTER JOIN.

- Fixed a bug in CONV() function returning unsigned BIGINT number (third argument is positive, and return value does not fit in 32 bits). (Bug #7751)

- Fixed a failure of the IN() operator to return correct result if all values in the list were constants and some of them were using substring functions, for example, LEFT(), RIGHT(), or MID(). (Bug #7716)

- Fixed a crash in CONVERT_TZ() function when its second or third argument was from a const table (Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) »). (Bug #7705)

- Fixed a problem with calculation of number of columns in row comparison against subquery. (Bug #8020)

- Fixed erroneous output resulting from SELECT DISTINCT combined with a subquery and GROUP BY. (Bug #7946)

- Fixed server crash in comparing a nested row expression (for example row(1,(2,3))) with a subquery. (Bug #8022)

- Fixed server crash resulting from certain correlated subqueries with forward references (references to an alias defined later in the outer query). (Bug #8025)

- Fixed server crash resulting from re-execution of prepared statements containing subqueries. (Bug #8125)

- Fixed a bug where ALTER TABLE improperly would accept an index on a TIMESTAMP column that CREATE TABLE would reject. (Bug #7884)

- SHOW CREATE TABLE now reports ENGINE=MEMORY rather than ENGINE=HEAP for a MEMORY table (unless the MYSQL323 SQL mode is enabled). (Bug #6659)

- Fixed a bug where the use of GROUP_CONCAT() with HAVING caused a server crash. (Bug #7769)

- Fixed a bug where comparing the result of a subquery to a non-existent column caused a server crash on Windows. (Bug #7885)

- Fixed a bug in a combination of -not and trunc* operators of full-text search. Using more than one truncated negative search term, was causing empty result set.

- InnoDB : Corrected the handling of trailing spaces in the ucs2 character set. (Bug #7350, Bug #8771)

- InnoDB : Use native tmpfile() function on Netware. All InnoDB temporary files are created under sys:\tmp. Previously, InnoDB temporary files were never deleted on Netware.

- Fixed a bug in max_heap_table_size handling, that resulted in Table is full error when the table was still smaller than the limit. (Bug #7791).

- Fixed a symlink vulnerability in the mysqlaccess script. Reported by Javier Fernandez-Sanguino Pena and Debian Security Audit Team. (CAN-2005-0004)

- Fixed a bug that caused server crash if some error occured during filling of temporary table created for derived table or view handling. (Bug #7413)

- Fixed a bug which caused server crash if query containing CONVERT_TZ() function with constant arguments was prepared. (Bug #6849)

- Prevent adding CREATE TABLE .. SELECT query to the binary log when the insertion of new records partially failed. (Bug #6682)

- Fixed a bug which caused a crash when only the slave I/O thread was stopped and started. (Bug #6148)

- Giving mysqld a SIGHUP caused it to crash.

- Changed semantics of CREATE/ALTER/DROP DATABASE statements so that replication of CREATE DATABASE is possible when using --binlog-do-db and --binlog-ignore-db. (Bug #6391)

- A sequence of BEGIN (or SET AUTOCOMMIT=0), FLUSH TABLES WITH READ LOCK, transactional update, COMMIT, FLUSH TABLES WITH READ LOCK could hang the connection forever and possibly the MySQL server itself. This happened for example when running the innobackup script several times. (Bug #6732)

- mysqlbinlog did not print SET PSEUDO_THREAD_ID statements in front of LOAD DATA INFILE statements inserting into temporary tables, thus causing potential problems when rolling forward these statements after restoring a backup. (Bug #6671)

- InnoDB : Fixed a bug no error message for ALTER with InnoDB and AUTO_INCREMENT (Bug #7061). InnoDB now supports ALTER TABLE...AUTO_INCREMENT = x query to set auto increment value for a table.

- Made the MySQL server accept executing SHOW CREATE DATABASE even if the connection has an open transaction or locked tables; refusing it made mysqldump --single-transaction sometimes fail to print a complete CREATE DATABASE statement for some dumped databases. (Bug #7358)

- Fixed that, when encountering a « disk full » or « quota exceeded » write error, MyISAM sometimes didn't sleep and retry the write, thus resulting in a corrupted table. (Bug #7714)

- Fixed that --expire-log-days was not honored if using only transactions. (Bug #7236)

- Fixed that a slave could crash after replicating many ANALYZE TABLE, OPTIMIZE TABLE, or REPAIR TABLE statements from the master. (Bug #6461, Bug #7658)

- mysqlbinlog forgot to add backquotes around the collation of user variables (causing later parsing problems as BINARY is a reserved word). (Bug #7793)

- Ensured that mysqldump --single-transaction sets its transaction isolation level to REPEATABLE READ before proceeding (otherwise if the MySQL server was configured to run with a default isolation level lower than REPEATABLE READ it could give an inconsistent dump). (Bug #7850)

- Fixed that when using the RPAD() function (or any function adding spaces to the right) in a query that had to be resolved by using a temporary table, all resulting strings had rightmost spaces removed (i.e. RPAD() did not work) (Bug #4048)

- Fixed that a 5.0.3 slave can connect to a master < 3.23.50 without hanging (the reason for the hang is a bug in these quite old masters -- SELECT @@unknown_var hangs them -- which was fixed in MySQL 3.23.50). (Bug #7965)

- InnoDB : Fixed a deadlock without any locking, simple select and update (Bug #7975). InnoDB now takes an exclusive lock when INSERT ON DUPLICATE KEY UPDATE is checking duplicate keys.

- Fixed a bug where MySQL was allowing concurrent updates (inserts, deletes) to a table if binary logging is enabled. Changed to ensure that all updates are executed in a serialized fashion, because they are executed serialized when binlog is replayed. (Bug #7879)

- Fixed a rare race condition which could lead to FLUSH TABLES WITH READ LOCK hanging. (Bug #8682)

- Fixed a bug that caused the slave to stop on statements that produced an error on the master. (Bug #8412)

30-A-5 - Changements de la version 5.0.2 (1er Décembre 2004)

Fonctionnalités ajoutées ou modifiées :

- The SCHEMA and SCHEMAS keywords now are accepted as synonyms for DATABASE and DATABASES.

- Added initial support for rudimentary triggers.

- Added basic support for read-only server side cursors.

- Added --start-datetime, --stop-datetime, --start-position, --stop-position options to mysqlbinlog (makes point-in-time recovery easier).

- Made the MySQL server not react to signals SIGHUP and SIGQUIT on Mac OS X 10.3. This is needed because under this OS, the MySQL server receives lots of these signals (reported as Bug #2030).

- New --auto-increment-increment and --auto-increment-offset startup options. These allow you to set up a server to generate auto-increment values that don't conflict with another server.

- MySQL now by default will check dates and only allow fully correct dates. If you want to MySQL to behave as default, you should enable the new ALLOW_INVALID_DATES SQL mode.

- Added STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, and TRADITIONAL SQL modes. The TRADITIONAL mode is shorthand for all the preceding modes. When using mode TRADITIONAL, MySQL generates an error if you try to insert a wrong value in a column. It does not adjust the value to the closest possible legal value.

- MySQL now remembers which columns were declared to have default values. In STRICT_TRANS_TABLES/STRICT_ALL_TABLES mode, you now get an error if you do an INSERT without specifying all columns that don't have a default value. A side effect of this is that when you do SHOW CREATE for a new table, you will no longer Voir a DEFAULT value for a column for which you didn't specify a default value.

- The compilation flag DONT_USE_DEFAULT_FIELDS was removed because you can get the same behavior by setting the sql_mode system variable to STRICT_TRANS_TABLES.

- We now detect too-large floating point numbers during statement parsing and generate an error messages for them.

- Renamed the sql_updatable_view_key system variable to updatable_views_with_limit. This variable now can have only two values:

- 1 or YES: Don't issue an error message (warning only) if a VIEW without presence of a key in the underlying table is used in queries with a LIMIT clause for updating. (This is the default value.)

- 0 or NO: Prohibit update of a VIEW, which does not contain a key in the underlying table and the query uses a LIMIT clause (usually get from GUI tools).

- Reverted output format of SHOW TABLES to old pre-5.0.1 format that did not include a table type column. To get the additional column that lists the table type, use SHOW FULL TABLES now.

- The mysql_fix_privilege_tables script now initializes the global CREATE VIEW and SHOW VIEW privileges in the user table to the value of the CREATE privilege in that table.

- If the server finds that the user table has not been upgraded to include the view-related privilege columns, it treats each account as having view privileges that are the same as its CREATE privilege.

Bogues corrigés :

- Fixed that mysqlbinlog --read-from-remote-server sometimes couldn't accept two binary logfiles on the command line. (Bug #4507)

- Fixed that mysqlbinlog --position --read-from-remote-server had incorrect # at lines. (Bug #4506)

- Fixed that CREATE TABLE ... TYPE=HEAP ... AS SELECT... caused replication slave to stop. (Bug #4971)

- Fixed that mysql_options(...,MYSQL_OPT_LOCAL_INFILE,...) failed to disable LOAD DATA LOCAL INFILE. (Bug #5038)

- Fixed that disable-local-infile option had no effect if client read it from a configuration file using mysql_options(...,MYSQL_READ_DEFAULT,...). (Bug #5073)

- Fixed that SET GLOBAL SYNC_BINLOG did not work on some platforms (Mac OS X). (Bug #5064)

- Fixed that mysql-test-run failed on the rpl_trunc_binlog test if running test from the installed (the target of 'make install') directory. (Bug #5050)

- Fixed that mysql-test-run failed on the grant_cache test when run as Unix user 'root'. (Bug #4678)

- Fixed an unlikely deadlock which could happen when using KILL. (Bug #4810)

- Fixed a crash when one connection got KILLed while it was doing START SLAVE. (Bug #4827)

- Made FLUSH TABLES WITH READ LOCK block COMMIT if server is running with binary logging; this ensures that the binary log position can be trusted when doing a full backup of tables and the binary log. (Bug #4953)

- Fixed that the counter of an auto_increment column was not reset by TRUNCATE TABLE is the table was a temporary one. (Bug #5033)

- Fixed slave SQL thread so that the SET COLLATION_SERVER... statements it replicates don't advance its position (so that if it gets interrupted before the actual update query, it will later redo the SET). (Bug #5705)

- Fixed that if the slave SQL thread found a syntax error in a query (which should be rare, as the master parsed it successfully), it stops. (Bug #5711)

- Fixed that if a write to a MyISAM table fails because of a full disk or an exceeded disk quota, it prints a message to the error log every 10 minutes, and waits until disk becomes free. (Bug #3248)

- Fixed problem introduced in 4.0.21 where a connection starting a transaction, doing updates, then FLUSH TABLES WITH READ LOCK, then COMMIT, would cause replication slaves to stop complaing about error 1223. Bug surfaced when using the InnoDB innobackup script. (Bug #5949)

30-A-6 - Changements de la version 5.0.1 (pas encore publiée)

Fonctionnalité ajoutée ou modifiée :

- For replication of MEMORY (HEAP) tables: Made the master automatically write a DELETE FROM statement to its binary log when a MEMORY table is opened for the first time since master's startup. This is for the case where the slave has replicated a non-empty MEMORY table, then the master is shut down and restarted: the table is now empty on master; the DELETE FROM empties it on slave too. Note that even with this fix, between the master's restart and the first use of the table on master, the slave still has out-of-date data in the table. But if you use the --init-file option to populate the MEMORY table on the master at startup, it ensures that the failing time interval is zero. (Bug #2477)

- When a session having open temporary tables terminates, the statement automatically written to the binary log is now DROP TEMPORARY TABLE IF EXISTS instead of DROP TEMPORARY TABLE, for more robustness.

- The MySQL server now returns an error if SET SQL_LOG_BIN is issued by a user without the SUPER privilege (in previous versions it just silently ignored the statement in this case).

- Changed that when the MySQL server has binary logging disabled (that is, no log-bin option was used) then no transaction binlog cache is allocated for connections (this should save binlog_cache_size bytes of memory (32 kilobytes by default) for every connection).

- Added option --replicate-same-server-id.

Bogues corrigés :

- Strange results with index (x, y) ... WHERE x=val_1 AND y>=val_2 ORDER BY pk; (Bug #3155)

- Subquery and order by (Bug #3118)

- ALTER DATABASE caused the client to hang if the database did not exist. (Bug #2333)

- SLAVE START (which is a deprecated syntax, START SLAVE should be used instead) could crash the slave. (Bug #2516)

- Multiple-table DELETE statements were never replicated by the slave if there were any replicate-*-table options. (Bug #2527)

- The MySQL server did not report any error if the query (submitted through mysql_real_query() or mysql_prepare()) was terminated by garbage characters (which can happen if you pass a wrong length parameter to mysql_real_query() or mysql_prepare()); the result was that the garbage characters were written into the binary log. (Bug #2703)

- Replication: If a client connects to a slave server and issues an administrative statement for a table (for example, OPTIMIZE TABLE or REPAIR TABLE), this could sometimes stop the slave SQL thread. This does not lead to any corruption, but you must use START SLAVE to get replication going again. (Bug #1858)

- Made clearer the error message which one gets when an update is refused because of the read-only option. (Bug #2757)

- Fixed that replicate-wild-*-table rules apply to ALTER DATABASE when the table pattern is '%', like it is already the case for CREATE DATABASE and DROP DATABASE. (Bug #3000)

- Fixed that when a Rotate event is found by the slave SQL thread in the middle of a transaction, the value of Relay_Log_Pos in SHOW SLAVE STATUS remains correct. (Bug #3017)

- Corrected the master's binary log position that InnoDB reports when it is doing a crash recovery on a slave server. (Bug #3015)

- Changed the column Seconds_Behind_Master in SHOW SLAVE STATUS to never show a value of -1. (Bug #2826)

- Changed that when a DROP TEMPORARY TABLE statement is automatically written to the binlog when a session ends, the statement is recorded with an error code of value zero (this ensures that killing a SELECT on the master does not result in a superfluous error on the slave). (Bug #3063)

- Changed that when a thread handling INSERT DELAYED (also known as a delayed_insert thread) is killed, its statements are recorded with an error code of value zero (killing such a thread does not endanger replication, so we thus avoid a superfluous error on the slave). (Bug #3081)

- Fixed deadlock when two START SLAVE commands were run at the same time. (Bug #2921)

- Fixed that a statement never triggers a superfluous error on the slave, if it must be excluded given the replicate-* options. The bug was that if the statement had been killed on the master, the slave would stop. (Bug #2983)

- The --local-load option of mysqlbinlog now requires an argument.

- Fixed a segmentation fault when running LOAD DATA FROM MASTER after RESET SLAVE. (Bug #2922)

- mysqlbinlog --read-from-remote-server read all binary logs following the one that was requested. It now stops at the end of the requested file, the same was it does when reading a local binary log. (Bug #3204)

- Fixed mysqlbinlog --read-from-remote-server to print the exact positions of events in the "at #" lines. (Bug #3214)

- Fixed a rare error condition that caused the slave SQL thread spuriously to print the message Binlog has bad magic number and stop when it was not necessary to do so. (Bug #3401)

- Fixed mysqlbinlog not to forget to print a USE statement under rare circumstances where the binary log contained a LOAD DATA INFILE statement. (Bug #3415)

- Fixed a memory corruption when replicating a LOAD DATA INFILE when the master had version 3.23. (Bug #3422)

- Multiple-table DELETE statements were always replicated by the slave if there were some replicate-*-ignore-table options and no replicate-*-do-table options. (Bug #3461)

- Fixed a crash of the MySQL slave server when it was built with --with-debug and replicating itself. (BUG #3568)

- Fixed that in some replication error messages, a very long query caused the rest of the message to be invisible (truncated), by putting the query last in the message. (Bug #3357)

30-A-7 - Changements de la version 5.0.0 (22 décembre 2003 : Alpha)

Fonctionnalité ajoutée ou modifiée :

- The KILL statement now takes CONNECTION and QUERY modifiers. The first is the same as KILL with no modifier (it kills a given connection thread). The second kills only the statement currently being executed by the connection.

- Added TIMESTAMPADD() and TIMESTAMPDIFF() functions.

- Added WEEK and QUARTER values as INTERVAL arguments for the DATE_ADD() and DATE_SUB() functions.

- New binary log format that enables replication of these session variables: sql_mode, SQL_AUTO_IS_NULL, FOREIGN_KEY_CHECKS (which was already replicated since 4.0.14, but here it's done more efficiently and takes less space in the binary logs), UNIQUE_CHECKS. Other variables (like character sets, SQL_SELECT_LIMIT, ...) will be replicated in upcoming 5.0.x releases.

- Implemented Index Merge optimization for OR clauses. Voir Section 7.2.6, « Optimisation de combinaison d'index ».

- Basic support for stored procedures (SQL:2003 style). Voir Chapitre 19, Procédures stockées et fonctions.

- Added SELECT INTO list_of_vars, which can be of mixed (that is, global and local) types. Voir Section 19.2.9.3, « Syntaxe de SELECT ... INTO ».

- Easier replication upgrade (5.0.0 masters can read older binary logs and 5.0.0 slaves can read older relay logs). Voir Section 6.5, « Compatibilité de la réplication entre les versions de MySQL » for more details). The format of the binary log and relay log is changed compared to that of MySQL 4.1 and older.

- Important note: If you upgrade to MySQL 4.1.1 or higher, it is difficult to downgrade back to 4.0 or 4.1.0! That is because, for earlier versions, InnoDB is not aware of multiple tablespaces.

Bogues corrigés :

30-B - Changements de la version 4.1.x (Alpha)

Version 4.1 of the MySQL server includes many enhancements and new features. Binaries for this version are available for download at http://www.mysql.com/downloads/mysql-4.1.html.

- Subqueries and derived tables (unnamed views). Voir Section 13.1.8, « Sous-sélections (SubSELECT) ».

- INSERT ... ON DUPLICATE KEY UPDATE ... syntax. This allows you to UPDATE an existing row if the insert would cause a duplicate value in a PRIMARY or UNIQUE key. (REPLACE allows you to overwrite an existing row, which is something entirely different.) Voir Section 13.1.4, « Syntaxe de INSERT ».

- A newly designed GROUP_CONCAT() aggregate function. Voir Section 12.9, « Fonctions et options à utiliser dans les clauses GROUP BY ».

- Extensive Unicode (UTF8) support.

- Character sets can be defined per column, table, and database.

- New key cache for MyISAM tables with many tunable parameters. You can have multiple key caches, preload index into caches for batches...

- BTREE index on HEAP tables.

- Support for OpenGIS spatial types (geographical data). Voir Chapitre 18, Données spatiales avec MySQL.

- SHOW WARNINGS shows warnings for the last command. Voir Section 13.5.3.19, « SHOW WARNINGS | ERRORS ».

- Faster binary protocol with prepared statements and parameter binding. Voir Section 24.2.4, « Fonctions C de commandes préparées ».

- You can now issue multiple statements with a single C API call and then read the results in one go. Voir Section 24.2.9, « Gestion des commandes multiples avec l'interface C ».

- Create Table: CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table2 LIKE table1.

- Server based HELP command that can be used in the mysql command line client (and other clients) to get help for SQL statements.

For a full list of changes, please refer to the changelog sections for each individual 4.1.x release.

30-B-1 - Changements de la version 4.1.12 (Pas encore publiée)

Fonctionnalités ajoutées ou modifiées :

- Updated version of libedit to 2.9. (Bug #2596)

- InnoDB: When FOREIGN_KEY_CHECKS=0, ALTER TABLE and RENAME TABLE will ignore any type incompatibilities between referencing and referenced columns. Thus, it will be possible to convert the character sets of columns that participate in a foreign key. Be sure to convert all tables before modifying any data! (Bug #9802)

- Previously in MySQL 4.1, an Illegal mix of collations error occurred when mixing strings from same character set when one had a non-binary collation and the other a binary collation. Now the binary collation takes precedence, so that both strings are treated as having the binary collation. This restores compatibility with MySQL 4.0 behavior.

Bogues corrigés :

- Security fix: If mysqld was started with --user=non_existent_user, it would run using the privileges of the account it was invoked from, even if that was root. (Bug #9833)

- MAX() for an INT UNSIGNED (unsigned 4-byte integer) column could return negative values if the column contained values larger than 2^31. (Bug #9298)

- Fixed a deadlock resulting from use of FLUSH TABLES WITH READ LOCK while an INSERT DELAYED statement is in progress. (Bug #7823)

- Multiple-table updates could produce spurious data-truncation warnings if they used a join across columns that are indexed using a column prefix. (Bug #9103)

- Use of a subquery that used WITH ROLLUP in the FROM clause of the main query sometimes resulted in a Column cannot be null error. (Bug #9681)

- RENAME TABLE for an ARCHIVE table failed if the .arn file was not present. (Bug #9911)

- Fixed an optimizer problem where extraneous comparisons between NULL values in indexed columns were being done for operators such as = that are never true for NULL. (Bug #8877)

- SELECT ROUND(expr) produced a different result than CREATE TABLE ... SELECT ROUND(expr). (Bug #9837)

- Fixed some awk script portability problems in cmd-line-utils/libedit/makelist.sh. (Bug #9954)

- Changed metadata for result of SHOW KEYS: Data type for Sub_part column now is SMALLINT rather than TINYINT because key part length can be longer than 255. (Bug #9439)

- Fixed some problems with myisampack on 64-bit systems that resulted in segmentation violations. (Bug #9487)

- Fixed an optimizer bug in computing the union of two ranges for the OR operator. (Bug #9348)

- Fixed an index corruption problem for MyISAM tables that resulted from the 4.1 behavior of padding values with blanks for comparison: Dumping a table with mysqldump, reloading it, and then re-running the binary log against it crashed the index and necessitated a repair. (Bug #9188)

- Fixed a segmentation fault in mysqlcheck that occurred when the last table checked in --auto-repair mode returned an error (such as the table being a MERGE table). (Bug #9492)

- Fixed the client/server protocol for prepared statements so that reconnection works properly when the connection is killed while reconnect is enabled. (Bug #8866)

- INSERT ... ON DUPLICATE KEY UPDATE incorrectly updated a TIMESTAMP column to the current timestamp, even if the update list included col_name = col_name for that column to prevent the update. (Bug #7806)

- Starting mysqld with the --skip-innodb and --default-storage-engine=innodb (or --default-table-type=innodb caused a server crash. (Bug #9815)

- Queries containing CURRENT_USER() incorrectly were registered in the query cache. (Bug #9796)

- A server installed as a Windows service and started with --shared-memory could not be stopped. (Bug #9665)

- mysqldump dumped core when invoked with --tmp and --single-transaction options and a non-existent table name. (Bug #9175)

- Additional fix for mysql_server_init() and mysql_server_end() C API functions so that stopping and restarting the embedded server will not cause a crash. (Bug #7344)

- mysql.server no longer uses non-portable alias command or LSB functions. (Bug #9852)

- Fixed a readline-related crash in mysql when the user pressed Control-R. (Bug #9568)

- TIMEDIFF() with a negative time first argument and postive time second argument produced incorrect results. (Bug #8068)

- Fixed a bug that caused concurrent inserts to be allowed into the tables in the SELECT ... UNION ... part of INSERT ... SELECT ... UNION .... This could result in the incorrect order of queries in the binary log. (Bug #9922)

- Warning message from GROUP_CONCAT() did not always indicate correct number of lines. (Bug #8681)

- InnoDB: ENUM and SET columns were treated incorrectly as character strings. This bug did not manifest itself with latin1 collations, but it caused malfunction with utf8. Old tables will continue to work. In new tables, ENUM and SET will be internally stored as unsigned integers. (Bug #9526)

- InnoDB: Avoid test suite failures caused by a locking conflict between two server instances at server shutdown/startup. This conflict on advisory locks appears to be the result of a bug in the operating system; these locks should be released when the files are closed, but somehow that does not always happen immediately in Linux. (Bug #9381)

- InnoDB: Prevent ALTER TABLE from changing the storage engine if there are foreign key constraints on the table. (Bug #5574, Bug #5670)

- InnoDB: Fixed a deadlock without any locking, simple select and update. (Bug #7975) InnoDB now takes an exclusive lock when INSERT ON DUPLICATE KEY UPDATE is checking duplicate keys.

30-B-2 - Changements de la version 4.1.11 (1 avril 2005)

Fonctionnalités ajoutées ou modifiées :

- ONLY_FULL_GROUP_BY no longer is included in the ANSI composite SQL mode. (Bug #8510)

- mysqld_safe will create the directory where the UNIX socket file is to be located if the directory does not exist. This applies only to the last component of the directory pathname. (Bug #8513)

- The coercibility for the return value of functions such as USER() or VERSION() now is « system constant » rather than « implicit. » This makes these functions more coercible than column values so that comparisons of the two do not result in Illegal mix of collations errors. COERCIBILITY() was modified to accommodate this new coercibility value. Voir Section 12.8.3, « Fonctions d'informations ».

- User variable coercibility has been changed from « coercible » to « implicit. » That is, user variables have the same coercibility as column values.

- NULL now is considered more coercible than string constants. This resolves some Illegal mix of collations conflicts.

- Modified the parser to allow SELECT statements following the UNION keyword to be subqueries in parentheses. (Bug #2435)

- For slave replication servers started with --replicate-* options, statements that should not be replicated according those options no longer are written to the slave's general query log. (Bug #8297)

- Added SQL_NOTES session variable to cause Note-level warnings not to be recorded. (Bug #6662)

- InnoDB: Commit after every 10,000 copied rows when executing CREATE INDEX, DROP INDEX or OPTIMIZE TABLE, which are internally implemented as ALTER TABLE. This makes it much faster to recover from an aborted operation.

- Added a new global system variable slave_transaction_retries: If the replication slave SQL thread fails to execute a transaction because of an InnoDB deadlock or exceeded InnoDB's innodb_lock_wait_timeout or NDBCluster's TransactionDeadlockDetectionTimeout or TransactionInactiveTimeout, it automatically retries slave_transaction_retries times before stopping with an error. The default in MySQL 4.1 is 0. You must explicitly set the value greater than 0 to enable the « retry » behavior. (In MySQL 5.0.3 or newer, the default is 10.) (Bug #8325)

- Added --with-big-tables compilation option to configure. (Previously it was necessary to pass -DBIG_TABLES to the compiler manually in order to enable large table support.) Voir Section 2.4.2, « Options habituelles de configure » for details.

- Added configuration directives !include and !includedir for including option files and searching directories for option files. Voir Section 4.3.2, « Fichier d'options my.cnf » for usage.

Bogues corrigés :

- The use of XOR together with NOT ISNULL() erroneously resulted in some outer joins being converted to inner joins by the optimizer. (Bug #9017)

- Fixed utf8_spanish2_ci and ucs2_spanish2_ci collations to not consider 'r' equal to 'rr'. If you upgrade to this version from an earlier version, you should rebuild the indexes of affected tables. (Bug #9269)

- Allow extra HKSCS and cp950 characters (big5 extension characters) to be accepted in big5 columns. (Bug #9357)

- BLOB(M) and TEXT(M) columns, with M less than 256, were being created as BLOB and TEXT columns rather than TINYBLOB or TINYTEXT columns. (Bug #9303)

- Fixed a problem with INSERT ... SELECT ... ON DUPLICATE KEY UPDATE where a column named in the insert list and in the ON DUPLICATE KEY UPDATE clause was erroneously declared to be ambiguous. (Bug #8147)

- In prepared statements, subqueries containing parameters were erroneously treated as const tables during preparation, resulting in a server crash. (Bug #8807)

- Fixed a problem with OPTIMIZE TABLE for InnoDB tables being written twice to the binary log. (Bug #9149)

- Provide more informative error messages in clustered setting when a query is issued against a table that has been modified by another mysqld server. (Bug #6762)

- For MyISAM tables, REPAIR TABLE no longer discard rows that have incorrect checksum. (Bug #9824)

- Depending on index statistics, GROUP BY col1, col2, ... could return incorrect results if the first table processed for a join had several indexes that cover the grouped columns. (Bug #9213)

- Fixed incorrect evaluation of ALL/ANY subqueries that contain a HAVING clause. (Bug #9350)

- Fixed server crash when left expression of IN/ALL/ANY comparision was a subquery. (Bug #8888)

- Fixed option-parsing code for the embedded server to understand K, M, and G suffixes for the net_buffer_length and max_allowed_packet options. (Bug #9472)

- Fixed a crash when using TIMESTAMP columns with no minute or second parts in GROUP BY with the new system variable set to 1. (Bug #9401)

- If a MyISAM table on Windows had INDEX DIRECTORY or DATA DIRECTORY table options, mysqldump dumped the directory pathnames with single-backslash pathname separators. This would cause syntax errors when importing the dump file. mysqldump now changes '\' to '/' in the pathnames on Windows. (Bug #6660)

- Fixed a server crash caused by use of NOW() is a subquery. (Bug #8824)

- Fixed problems with static variables to allow building on Fedora Core 3. (Bug #6554)

- Some user variables were not being handled with « implicit » coercibility. (Bug #9425)

- Setting the max_error_count system variable to 0 resulted in a setting of 1. (Bug #9072)

- Fixed a collation coercibility problem that caused a union between binary and non-binary columns to fail. (Bug #6519)

- Fixed a problem with the tee command in mysql that resulted in mysql crashing. (Bug #8499)

- On Windows, create shared memory objects with the proper access rights to make them usable when the client and server are running under different accounts. (Bug #8226)

- Bundled zlib in the source distribution was upgraded to 1.2.2. (Bug #9118)

- Fixed server crash resulting from queries that combined SELECT DISTINCT, SUM(), and ROLLUP. (Bug #8615)

- Incorrect results were returned from queries that combined SELECT DISTINCT, GROUP BY, and ROLLUP. (Bug #8616)

- Fixed a bug that under certain circumstances could allow a privilege escalation via database wildcards in GRANT. (CAN-2004-0957)

- Too many rows were returned from queries that combined ROLLUP and LIMIT if SQL_CALC_FOUND_ROWS was given. (Bug #8617)

- mysqldump misinterpreted '_' and '%' characters in the names of tables to be dumped as wildcard characters. (Bug #9123)

- Made the relay_log_space_limit system variable show up in the output of SHOW VARIABLES. (Bug #7100)

- Use of GROUP_CONCAT(x) in a subquery, where x was an alias to a column in the outer query, resulted in a server crash. (Bug #8656)

- The CHARSET(), COLLATION(), and COERCIBILITY() functions sometimes returned NULL. CHARSET() and COLLATION() returned NULL when given any of these arguments that evaluated to NULL: A system function such as DATABASE(); a column value; and a user variable. Now CHARSET() and COLLATION() return the system character set and collation; the column character set and collation; and binary. COERCIBILITY(NULL) now returns « ignorable » coercibility rather than NULL. (Bug #9129)

- Expressions involving nested CONCAT() calls and character set conversion of string constants could return an incorrect result. (Bug #8785)

- The MEMORY storage engine did not properly increment an AUTO_INCREMENT column if there was a second composite index that included the column. (Bug #8489)

- Fixed a bug in the filesort routine such that killing a filesort could cause an assertion failure. (Bug #8799)

- REPAIR TABLE did not invalidate query results in the query cache that were generated from the table. (Bug #8480)

- If max_join_size was set, a query containing a subquery that exceeded the examined-rows limit could hang. (Bug #8726)

- Mixed-case database and table names in the grant tables were ignored for authentication if the lower_case_table_names system variable was set. GRANT will not create such privileges when lower_case_table_names is set, but it is possible to create them by direct manipulation of the grant tables, or that old grant records were present before setting the variable. (Bug #7989)

- AES_DECRYPT(col_name,key) could fail to return NULL for invalid values in col_name, if col_name was declared as NOT NULL. (Bug #8669)

- Ordering by unsigned expression (more complex than a column reference) was treating the value as signed, producing incorrectly sorted results. (Bug #7425)

- HAVING was treating unsigned columns as signed. (Bug #7425)

- Fixed a problem with boolean full-text searches on utf8 columns where a double quote in the search string caused a server crash. (Bug #8351)

- MIN(col_name) and MAX(col_name) could fail to produce the correct result if col_name was contained in multiple indexes and the optimizer did not choose the first index that contained the column. (Bug #8893)

- Table creation for a MyISAM table failed if DATA DIRECTORY or INDEX DIRECTORY options were given that specified the pathname to the database directory where the table files would be created by default. (Bug #8707)

- Fixed a problem with LIKE pattern-matching for strings with the cp1251_bin binary collation. (Bug #8560)

- A join on two tables failed when each contained a BIGINT UNSIGNED column that were compared when their values exceeded 2^63 - 1. The match failed and the join returned no rows. (Bug #8562)

- For a query with both GROUP BY and COUNT(DISTINCT) clauses and a FROM clause with a subquery, NULL was returned for any VARCHAR column selected by the subquery. (Bug #8218)

- Fixed an optimizer bug that caused incorrectly ordered result from a query that used a FULLTEXT index to retrieve rows and there was another index that was usable for ORDER BY. For such a query, EXPLAIN showed fulltext join type, but regular (not FULLTEXT) index in the Key column. (Bug #6635)

- For a statement string that contained multiple slow queries, only the last one would be written to the slow query log. (Bug #8475)

- When the server was started with --skip-name-resolve, specifying hostname values that included netmasks in GRANT statements did not work. (Bug #8471)

- The --set-character-set option for myisamchk was changed to --set-collation. The value needed for specifying how to sort indexes is a collation name, not a character set name. (Bug #8349)

- Hostname matching didn't work if a netmask was specified for table-specific privileges. (Bug #3309)

- Binary data stored in BLOB or BINARY columns would be erroneously dumped if mysqldump was invoked with --hex-blob and --skip-extended-insert arguments. This happened if data contained characters larger then 0x7F (Bug #8830).

- Corruption of MyISAM table indexes could occur with TRUNCATE TABLE if the table had already been opened. For example, this was possible if the table had been opened implicitly by selecting from a MERGE table that mapped to the MyISAM table. The server now issues an error message for TRUNCATE TABLE under these conditions. (Bug #8306)

- Fixed handling of table-name matching in mysqlhotcopy to accommodate DBD::mysql 2.9003 and up (which implement identifier quoting). (Bug #8136)

- In the mysql_real_escape_string() C API function, when a multi-byte character is encountered that is illegal in the current character set, escape only the first byte, not each byte. This avoids creating a valid character from an invalid one. (Bug #8378)

- Fixed a problem with the cp1250_czech_cs collation that caused empty literal strings not to compare equal to empty character columns. (Bug #8840)

- Fixed a problem in index cost calculation that caused a USE INDEX or FORCE INDEX hint not to be used properly for a LEFT JOIN across indexed BLOB columns. (Bug #7520)

- The column type for MAX(datetime_col) was returned as VARCHAR rather than DATETIME if the query included a GROUP BY clause. (Bug #5615)

- FOUND_ROWS() returned an incorrect value for preceding SELECT statements that used no table or view. (Bug #6089)

- In string literals with an escape character ('\') followed by a multi-byte character that has a second byte of '\', the literal was not interpreted correctly. The next character now is escaped, not just the next byte. (Bug #8303)

- InnoDB: Work around a problem in AIX 5.1 patched with ML7 security patch: InnoDB would refuse to open its ibdata files, complaining about an operating system error 0.

- InnoDB: Fixed a memory corruption bug if one created a table with a primary key that contained at least two column prefixes. An example: CREATE TABLE t(a char(100), b tinyblob, PRIMARY KEY(a(5), b(10))).

- InnoDB: Do not try to space-pad BLOB columns containing ucs2 characters. This avoids an assertion failure that was introduced when fixing Bug #7350. (Bug #8771)

- InnoDB: Fixed a bug : MySQL-4.1.8 - 4.1.10 could complain that an InnoDB table created with MySQL-3.23.49 or earlier was in the new compact InnoDB table format of 5.0.3 or later, and InnoDB would refuse to use that table. There is nothing wrong with the table, it is mysqld that is in error. Workaround: wait that 4.1.11 is released before doing an upgrade, or dump the table and recreate it with any MySQL version >= 3.23.50 before upgrading.

- InnoDB: Honor the --tmpdir startup option when creating temporary files. Previously, InnoDB temporary files were always created in the temporary directory of the operating system. On Netware, InnoDB will continue to ignore --tmpdir. (Bug #5822)

- InnoDB: If MySQL wrote to its binlog, but for some reason trx->update_undo and trx->insert_undo were NULL in InnoDB, then trx->commit_lsn was garbage, and InnoDB could assert in the log flush of trx_commit_complete_for_mysql(). (Bug #9277)

- InnoDB: If InnoDB cannot allocate memory, keep retrying for 60 seconds before we intentionally crash mysqld; maybe the memory shortage is just temporary.

- InnoDB: If one used LOCK TABLES, created an InnoDB temp table, and did a multi-table update where a MyISAM table was the update table and the temp table was a read table, then InnoDB asserted in row0sel.c because n_mysql_tables_in_use was 0. Also, we remove the assertion altogether and just print an error to the .err log if this important consistency check fails. (Bug #8677)

- mysqldump now avoids writing SET NAMES to the dump output if the server is older than version 4.1 and would not understand that statement. (Bug #7997)

- Fixed a bug in my_print_defaults that made it ignore the --defaults-extra-file and --defaults-file options.

- Retrieving from a view defined as a SELECT that mixed UNION ALL and UNION DISTINCT resulted in a different result than retrieving from the original SELECT. (Bug #6565)

- Worked around a bug in support for NSS support in glibc when static linking is used and LDAP is one of the NSS sources. The workaround is to detect when the bug causes a segfault and issue a diagnostic message with information about the problem. (Bug #3037, Bug #4872)

- If the mysql prompt was configured to display the default database name, and that database was dropped, mysql did not update the prompt. (Bug #4802)

- perror was printing a spurious extra line of output ("Error code ###: Unknown error ###" printed directly before the correct line with the error message). (Bug #8517)

- The CHAR() function was not ignoring NULL arguments, contrary to the documentation. (Bug #6317)

- Neither SHOW ERRORS nor SHOW WARNINGS were displaying Error-level messages. (Bug #6572)

- Creating a table using a name containing a character that is illegal in character_set_client resulted in the character being stripped from the name and no error. The character now is considered an error. (Bug #8041)

- Fixed a problem with the Cyrillic letters I and SHORT I being treated the same by the utf8_general_ci collation. (Bug #8385)

- The MAX_CONNECTIONS_PER_HOUR resource limit was not being reset hourly and thus imposed an absolute limit on number of connections per account until the server is restarted or the limits flushed. (Bug #8350)

- With a database was dropped with lower_case_table_names=2, tables in the database also were dropped but not being flushed properly from the table cache. If the database was recreated, the tables also would appear to have been recreated. (Bug #8355)

- Changed mysql_server_end() C API function to restore more variables to their initial state so that a subsequent call to mysql_server_init() would not cause a client program crash. (Bug #7344)

- Fixed a problem with accented letters improperly being treated as distinct with the utf_general_ci collation. (Bug #7878)

- ENUM and SET columns in privilege tables incorrectly had a case-sensitive collation, resulting in failure of assignments of values that did not have the same lettercase as given in the column definitions. The collation was changed to be case insensitive. (Bug #7617)

- An expression that tested a case-insensitive character column against string constants that differed in lettercase could fail because the constants were treated as having a binary collation. (For example, WHERE city='London' AND city='london' could fail.) (Bug #7098, Bug #8690)

- The output of the STATUS (\s) command in mysql had the values for the server and client character sets reversed. (Bug #7571)

- If the slave was running with --replicate-*-table options which excluded one temporary table and included another, and the two tables were used in a single DROP TEMPORARY TABLE IF EXISTS statement, as the ones the master automatically writes to its binary log upon client's disconnection when client has not explicitly dropped these, the slave could forget to delete the included replicated temporary table. Only the slave needs to be upgraded. (Bug #8055)

- Treat user variables as having IMPLICIT derivation (coercibility) to avoid « Illegal mix of collations » errors when replicating user variables. (Bug #6676)

- When setting integer system variables to a negative value with SET VARIABLES, the value was treated as a positive value modulo 2^32. (Bug #6958)

- Fixed a bug in bundled readline library that caused segmentation fault in mysql when user entered Shift+Enter. (Bug #5672)

- Fix conversion of strings -> double to get higher accuracy for floating point values that are integers, like: 123.45E+02 (Bug #7840).

- Fixed a bug in MATCH ... AGAINST in natural language mode that could cause a server crash if the FULLTEXT index was not used in a join (EXPLAIN did not show fulltext join mode) and the search query matched no rows in the table (Bug #8522).

- Platform and architecture information in version information produced for --version option on Windows was always Win95/Win98 (i32). More accurately determine platform as Win32 or Win64 for 32-bit or 64-bit Windows, and architecture as ia32 for x86, ia64 for Itanium, and axp for Alpha. (Bug #4445)

- Fixed a rare race condition which could lead to FLUSH TABLES WITH READ LOCK hanging. (Bug #8682)

- Fixed a bug that caused the slave to stop on statements that produced an error on the master. (Bug #8412)

- If multiple semicolon-separated statements were received in a single packet, they were written to the binary log as a single event rather than as separate per-statement events. For a server serving as a replication master, this caused replication to fail when the event was sent to slave servers. (Bug #8436)

30-B-3 - Changements de la version 4.1.10 (12 février 2005)

Note: The security improvements related to creation of table files and to user-defined functions were made after MySQL 4.1.10 was released and are present in MySQL 4.1.10a. We would like to thank Stefano Di Paola <stefano.dipaola@wisec.it> for making us aware of these.

Fonctionnalités ajoutées ou modifiées :

- Added back faster subquery execution from 4.1.8. This adds also back a bug from 4.1.8 in comparing NULL to the value of a subquery. Voir Section 1.5.7.4, « Bugs connus / limitations de MySQL ».

- Security improvement: The server creates .frm, .MYD, .MYI, .MRG, .ISD, and .ISM table files only if a file with the same name does not already exist. Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0711)

- Security improvement: User-defined functions should have at least one symbol defined in addition to the xxx symbol that corresponds to the main xxx() function. These auxiliary symbols correspond to the xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear(), and xxx_add() functions. mysqld by default no longer loads UDFs unless they have at least one auxiliary symbol defined in addition to the main symbol. The --allow-suspicious-udfs option controls whether UDFs that have only an xxx symbol can be loaded. By default, the option is off. mysqld also checks UDF filenames when it reads them from the mysql.func table and rejects those that contain directory pathname separator characters. (It already checked names as given in CREATE FUNCTION statements.) Voir Section 27.2.3.1, « Fonctions utilisateur : appeler des fonctions simples », Section 27.2.3.2, « Appeler des fonctions utilisateurs pour les groupements », and Section 27.2.3.6, « Précautions à prendre avec les fonctions utilisateur ». Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0709, CAN-2005-0710)

- Setting the connection collation to a value different from the server collation followed by a CREATE TABLE statement that included a quoted default value resulted in a server crash. (Bug #8235)

- Thread stack size was increased from 192KB to 256KB on Linux/IA-64 (too small stack size was causing server crashes on some queries). (Bug #8391)

- From the Windows distribution, predefined accounts without passwords for remote users ("root@%", "@%") were removed (other distributions never had them).

- Added mysql_library_init() and mysql_library_end() as synonyms for the mysql_server_init() and mysql_server_end() C API functions. mysql_library_init() and mysql_library_end() are #define symbols, but the names more clearly indicate that they should be called when beginning and ending use of a MySQL C API library no matter whether the application uses libmysqlclient or libmysqld. (Bug #6149)

- The server now issues a warning when lower_case_table_names=2 and the data directory is on a case-sensitive filesystem, just as when lower_case_table_names=0 on a case-insensitive filesystem. (Bug #7887)

- The server now issues a warning to the error log when it encounters older tables that contain character columns that might be interpreted by newer servers to have a different column length. (Bug #6913) Voir Section 2.6.2, « Passer de la version 4.0 à la version 4.1 » for a discussion of this problem and what to do about it.

- InnoDB: When MySQL/InnoDB is compiled on Mac OS X 10.2 or earlier, detect the operating system version at run time and use the fcntl() file flush method on Mac OS X versions 10.3 and later. Apple had disabled fsync() in Mac OS X for internal disk drives, which caused corruption at power outages.

- InnoDB: A shared record lock (LOCK_REC_NOT_GAP) is now taken for a matching record in the foreign key check because inserts can be allowed into gaps.

- InnoDB: Relaxed locking in INSERT...SELECT, single table UPDATE...SELECT and single table DELETE...SELECT clauses when innobase_locks_unsafe_for_binlog is used and isolation level of the transaction is not serializable. InnoDB uses consistent read in these cases for a selected table.

Bogues corrigés :

- FOUND_ROWS() returned an incorrect value after a SELECT SQL_CALC_FOUND_ROWS DISTINCT statement that selected constants and included GROUP BY and LIMIT clauses. (Bug #7945)

- Fixed a bug in cardinality estimations for HASH indexes of TEMPORARY tables created using MEMORY storage engine. As a result queries that were using this index (as shown by EXPLAIN) could have returned incorrect results. (Bug #8371)

- Corrected a problem with references to DUAL where statements such as SELECT 1 AS a FROM DUAL would succeed but statements such as SELECT 1 AS a FROM DUAL LIMIT 1 would fail. (Bug #8023)

- Fixed a server crash caused by DELETE FROM tbl_name ... WHERE ... ORDER BY tbl_name.col_name when the ORDER BY column was qualified with the table name. (Bug #8392)

- mysqld had problems finding its language files if the basedir value was specified as a very long pathname. (Bug #8015)

- Updates were being written to the binary log when there were binlog-do-db or binlog-ignore-db options even when there was no current database, contrary to Section 5.9.4, « Le log binaire ». (Bug #6749)

- Fixed conversion of floating-point values to character fields when the absolute value of the float was less than 1, and also fixed calculation of length for negative values. (Bug #7774)

- Column headers in query results retrieved from the query cache could be corrupted when a non-4.1 client was served a result originally generated for a 4.1 client. The query cache was not keeping track of which client/server protocol was being used. (Bug #6511)

- Fixed LOAD INDEX statement to actually load index in memory. (Bug #8452)

- If multiple prepared statements were executed without retrieving their results, executing one of them again would cause the client program to crash. (Bug #8330)

- Non-numeric values inserted into a YEAR column were being stored as 2000 rather than as 0000. (Bug #6067)

- Fixed a failure of multiple-table updates to replicate properly on slave servers when --replicate-*-table options had been specified. (Bug #7011)

- mysql_stmt_close() C API function was not clearing an error indicator when a previous prepare call failed, causing subsequent invocations of error-retrieving calls to indicate spurious error values. (Bug #7990)

- Fixed failure of CREATE TABLE ... LIKE Windows when the source or destination table was located in a symlinked database directory. (Bug #6607)

- With lower_case_table_names set to 1, mysqldump on Windows could write the same table name in different lettercase for different SQL statements. Fixed so that consistent lettercase is used. (Bug #5185) HAVING that referred to RAND() or a user-defined function in the SELECT part through an alias could cause a crash or wrong value. (Bug #8216)

- If one used CONVERT_TZ() function in SELECT, which in its turn was used in CREATE TABLE statements, then system time zone tables were added to list of tables joined in SELECT and thus erroneous result was produced. (Bug #7899)

- Fixed a bug in CONV() function returning unsigned BIGINT number (third argument is positive, and return value does not fit in 32 bits). (Bug #7751)

- Fixed a failure of the IN() operator to return correct result if all values in the list were constants and some of them were using substring functions, for example, LEFT(), RIGHT(), or MID().

- Fixed problem with SHOW INDEX reporting Sub_part values in bytes rather than characters for columns with a multi-byte character set. (Bug #7943)

- Fixed a crash in CONVERT_TZ() function when its second or third argument was from a const table (Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) »). (Bug #7705)

- Correct a problem with mysql_config, which was failing to produce proper zlib option for linking under some circumstances. (Bug #6273)

- Fixed a problem with calculation of number of columns in row comparison against a subquery. (Bug #8020)

- Fixed erroneous output resulting from SELECT DISTINCT combined with a subquery and GROUP BY. (Bug #7946)

- Fixed server crash in comparing a nested row expression (for example row(1,(2,3))) with a subquery. (Bug #8022)

- Fixed server crash resulting from certain correlated subqueries with forward references (referring to an alias defined later in the outer query). (Bug #8025)

- Fixed server crash resulting from re-execution of prepared statements containing subqueries. (Bug #8125)

- Removed a dependence of boolean full-text search on --default-character-set option. (Bug #8159)

- Fixed a crash in a boolean full-text search in certain joins. (Bug #8234)

- Fixed erroneous comparison where strings that began with CHAR(31) were considered equal to the empty string. (Bug #8134)

- Add description of debug command to mysqladmin help output. (Bug #8207)

- perror.exe was always returning « Unknown error » on Windows. Voir Section 8.12, « perror, expliquer les codes d'erreurs ». (Bug #7390)

- Modify SET statements produced by mysqldump to write quoted strings using single quotes rather than double quotes. This avoids problems if the dump file is reloaded while the ANSI_QUOTES SQL mode is in effect. (Bug #8148)

- Fixed a bug where ALTER TABLE improperly would accept an index on a TIMESTAMP column that CREATE TABLE would reject. (Bug #7884)

- Fixed a bug in multiple-table UPDATE statements that could cause spurious Table '#sql_....' is full errors if the number of rows to update is big enough. (Bug #7788)

- Fixed a problem where SHOW INDEX on a MERGE table could crash a debugging version of the server. (Bug #7377)

- Fixed a problem where adding an ORDER BY clause for an indexed column would cause a SELECT to return an empty result. (Bug #7331)

- Fixed a problem where ALTER TABLE on a TEMPORARY table with a mixed-lettercase name could cause the table to disappear when lower_case_table_names was set to 2. (Bug #7261)

- Fixed a problem with key cache statistics being reported incorrectly by the server after receipt of a SIGHUP signal. (Bug #4285)

- Fixed a problem that caused mysql_stmt_prepare() to be very slow when used in client programs on Windows. (Bug #5787)

- For indexes, SHOW CREATE TABLE now displays the index type even if it is the default, for storage engines that support multiple index types. (Bug #7235)

- Fixed a bug where the use of GROUP_CONCAT() with HAVING caused a server crash. (Bug #7769)

- Fixed a bug where comparing the result of a subquery to a non-existent column caused a server crash on Windows. (Bug #7885)

- Fixed a bug which caused TIMEDIFF() function to return wrong results if one of its arguments had non-zero microsecond part (Bug #7586).

- Fixed a bug which caused TIMESTAMP columns with display width specified to be not identical to DATETIME columns when server was run in MAXDB mode (Bug #7418).

- Fixed a bug in UNION statements that resulted in the wrong number of the examined rows reported in the slow query log.

- Fixed a bug in a combination of -not and trunc* operators of full-text search. Using more than one truncated negative search term, was causing empty result set.

- InnoDB: Fixed a bug introduced in 4.1.9 to the Windows version if you used innodb_file_per_table. mysqld would stop and complain about Windows error number 87 in a file operation. (Voir the Bugs database or the 4.1.9 change notes about a workaround for that bug in 4.1.9). (Bug #8021)

- InnoDB: Corrected the handling of trailing spaces in the ucs2 character set. (Bug #7350)

- InnoDB: Use native tmpfile() function on Netware. All InnoDB temporary files are created under sys:\tmp. Previously, InnoDB temporary files were never deleted on Netware.

- InnoDB: Fix a race condition that could cause the assertion space->n_pending_flushes == 0 to fail in fil0fil.c, in fil_space_free(), in DROP TABLE or in ALTER TABLE.

- InnoDB: ALTER TABLE ... ADD CONSTRAINT PRIMARY KEY ... complained about bad foreign key definition. (Bug #7831)

- InnoDB: Fix a theoretical hang over the adaptive hash latch in InnoDB if one runs INSERT ... SELECT ... (binlog not enabled), or a multi-table UPDATE or DELETE, and only the read tables are InnoDB type, the rest are MyISAM. (Bug #7879)

- Fixed a bug in max_heap_table_size handling, that resulted in Table is full error when the table was still smaller than the limit. (Bug #7791).

- Fixed a symlink vulnerability in the mysqlaccess script. Reported by Javier Fernandez-Sanguino Pena and Debian Security Audit Team. (CAN-2005-0004)

- mysqlbinlog forgot to add backquotes around the collation of user variables (causing later parsing problems as BINARY is a reserved word). (Bug #7793)

- Ensured that mysqldump --single-transaction sets its transaction isolation level to REPEATABLE READ before proceeding (otherwise if the MySQL server was configured to run with a default isolation level lower than REPEATABLE READ it could give an inconsistent dump). (Bug #7850)

- Changed mysql client so that including \p as part of a prompt command uses the name of the shared memory connection when the connection is using shared memory. (Bug #7922)

- Fixed a problem in the server where executing a multi-statement query more than once with the query cache active could yield incorrect result sets. (Bug #7966)

- Fixed that a 4.1.10 slave can connect to a master < 3.23.50 without hanging (the reason for the hang is a bug in these quite old masters -- SELECT @@unknown_var hangs them -- which was fixed in MySQL 3.23.50). (Bug #7965)

- Fixed a bug where MySQL was allowing concurrent updates (inserts, deletes) to a table if binary logging is enabled. Changed to ensure that all updates are executed in a serialized fashion, because they are executed serialized when binlog is replayed. (Bug #7879)

30-B-4 - Changements de la version 4.1.9 (11 Janvier 2005)

Fonctionnalités ajoutées ou modifiées :

- mysqld_safe no longer tests for the presence of the data directory when using a relatively located server binary. It just assumes the directory is there, and fails to start up if it is not. This allows the data directory location to be specified on the command line, and avoids running a server binary that was not intended. (Bug #7249)

- The naming scheme of the Windows installation packages has changed slightly:
Examples: mysql-essential-4.1.9-win32.msi, mysql-noinstall-4.1.9-win32.zip Voir Section 2.2.1, « Installer MySQL sous Windows ».

- The platform suffix was changed from -win to -win32

- The product descriptions -noinstall and -essential have been moved in front of the version number

- The Mac OS X 10.3 installation disk images now include a MySQL Preference Pane for the Mac OS X Control Panel that enables the user to start and stop the MySQL server via the GUI and activate and deactivate the automatic MySQL server startup on bootup.

- The MySQL-shared-compat Linux RPM now includes the 3.23 as well as the 4.0 libysqlclient.so shared libraries. (Bug #6342)

- Seconds_Behind_Master is NULL (which means « unknown ») if the slave SQL thread is not running, or if the slave I/O thread is not running or not connected to master. It is zero if the SQL thread has caught up with the I/O thread. It no longer grows indefinitely if the master is idle.

- InnoDB: Do not acquire an internal InnoDB table lock in LOCK TABLES if AUTOCOMMIT=1. This helps in porting old MyISAM applications to InnoDB. InnoDB table locks in that case caused deadlocks very easily.

- InnoDB: Print a more descriptive error and refuse to start InnoDB if the size of ibdata files is smaller than what is stored in the tablespace header; innodb_force_recovery overrides this.

- The MySQL server aborts immediately instead of simply issuing a warning if it is started with the --log-bin option but cannot initialize the binary log at startup (that is, an error occurs when writing to the binary log file or binary log index file).

- The binary log file and binary log index file now behave like MyISAM when there is a "disk full" or "quota exceeded" error. Voir Section A.4.3, « Comment MySQL gère un disque plein ».

Bogues corrigés :

- Fixed problem where running mysql_fix_privilege_tables could result in grant table columns with too-short lengths if the server character set had been set to a multi-byte character set first. (Bug #7539)

- InnoDB: Fixed the critical bug if you enabled innodb_file_per_table in my.cnf. If you shut down mysqld, records could disappear from the secondary indexes of a table. Unfortunately, on Windows a new Bug #8021 was introduced. Windows users of innodb_file_per_table should put a line innodb_flush_method=unbuffered to their my.cnf or my.ini to work around 8021. (Bug #7496)

- InnoDB: Fixed a bug : 32-bit mysqld binaries built on HP-UX-11 did not work with InnoDB files greater than 2 GB in size. (Bug #6189)

- InnoDB: Return a sensible error code from DISCARD TABLESPACE if it fails because the table is referenced by a FOREIGN KEY.

- InnoDB: Fixed a bug : InnoDB failed to drop a table in the background drop queue if the table was referenced by a FOREIGN KEY constraint.

- InnoDB: Fixed a bug : if we dropped a table where an INSERT was waiting for a lock to check a FOREIGN KEY constraint, then an assertion would fail in lock_reset_all_on_table().

- InnoDB: Fix a little bug: we looked at the physical size of a stored SQL NULL value from a wrong field in the index; this has probably caused no bugs visible to the user. It caused only some extra space to be used in some rare cases.

- InnoDB: Use the fcntl() file flush method on Mac OS X versions 10.3 and up. Apple had disabled fsync() in Mac OS X for internal disk drives, which caused corruption at power outages.

- mysqladmin password now checks whether the server has --old-passwords turned on or predates 4.1 and uses the old-format password if so. (Bug #7451)

- Added a --default-character-set option to mysqladmin to avoid problems when the default character set is not latin1. (Bug #7524)

- Fix a problem with truncation of FLOAT values. (Bug #7361)

- Fixed a bug in PROCEDURE ANALYSE(), which did not quote some ENUM values properly. (Bug #2813)

- Fixed a bug that caused incorrect results for complex datetime expressions containing casts of datetime values to TIME or DATE values. (Bug #6914)

- Include compression library flags in the output from mysql_config --lib_r. (Bug #7021)

- Corrected a problem with mysql_config not producing all relevant flags from CFLAGS. (Bug #6964)

- Corrected a problem with mysqld_safe not properly capturing output from ps. (Bug #5878)

- Fixed a bug that caused a linking failure when linking both the MySQL client library and IMAP library. (Bug #7428)

- Fixed table corruption bug when using INSERT DELAYED with prepared statements.

- Fixed a bug that caused microseconds to be gobbled from the string result of the STR_TO_DATE function, if there is some other specifier in the format string following %f. (Bug #7458)

- Made the MySQL server accept executing SHOW CREATE DATABASE even if the connection has an open transaction or locked tables. Refusing it made mysqldump --single-transaction sometimes fail to print a complete CREATE DATABASE statement for some dumped databases. (Bug #7358)

- Fixed that, when encountering a « disk full » or « quota exceeded » write error, MyISAM sometimes didn't sleep and retry the write, thus resulting in a corrupted table. (Bug #7714)

- Fixed that --expire-log-days was not honored if using only transactions. (Bug #7236)

- Fixed that a slave could crash after replicating many ANALYZE TABLE, OPTIMIZE TABLE, or REPAIR TABLE statements from the master. (Bug #6461, Bug #7658)

30-B-5 - Changements de la version 4.1.8 (14 Décembre 2004)

Fonctionnalités ajoutées ou modifiées :

Bogues corrigés :

30-B-6 - Changements de la version 4.1.7 (bientôt publiée)

Fonctionnalité ajoutée ou modifiée :

- InnoDB: Made LOCK TABLES behave by default like it did before MySQL 4.0.20 or 4.1.2: no InnoDB lock will be taken. Added a startup option and settable system variable innodb_table_locks for making LOCK TABLE acquire also InnoDB locks. Voir Section 15.17, « Restrictions sur les tables InnoDB ». (Bug #3299, Bug #5998)

Bogues corrigés :

- Fixed a bug with FOUND_ROWS() used together with LIMIT clause in prepared statements. (Bug#6088)

- Fixed a bug with NATURAL JOIN in prepared statements. (Bug#6046).

- Fixed a bug in join of tables from different databases having columns with identical names (prepared statements). (Bug#6050)

- Now implicit access to system time zone description tables (which happens when you set time_zone variable or use CONVERT_TZ() function) does not require any privileges. (Bug #6116)

- Fixed a bug which caused server crash when deprecated libmysqlclient functilon mysql_create_db() was called. (Bug #6081)

- Fixed REVOKE ALL PRIVILEGES, GRANT OPTION FROM user so that all privileges are revoked correctly. (Bug #5831). This corrects a case that the fix in 4.1.6 could miss.

- Fixed a bug that could cause MyISAM index corruption when key values start with character codes below BLANK. This was caused by the new key sort order in 4.1. (Bug #6151)

- Fixed a bug in the prepared statements protocol when wrong metadata was sent for SELECT statements not returning a result set (such as SELECT ... INTO OUTFILE). (Bug #6059)

- Fixed bug which allowed to circumvent missing UPDATE privilege if one had INSERT and SELECT privileges for table with primary key. (Bug #6173)

- Fixed a bug in libmysqlclient with wrong conversion of negative time values to strings. (Bug #6049).

- Fixed a bug in libmysqlclient with wrong conversion of zero date values (0000-00-00) to strings. (Bug #6058)

- Fixed a bug that caused the server to crash on attempt to prepare a statement with RAND(?). (Bug #5985)

- Fixed a bug with handling of DATE, TIME, and DATETIME columns in the binary protocol. The problem is compiler-specific and could have been observed on HP-UX, AIX, Solaris9, when compiling with native compiler. (Bug #6025)

- Fixed a bug with handling of TINYINT columns in the binary protocol. The problem is specific to platforms where the C compiler has the char data type unsigned by default. (Bug #6024)

- Fixed problem introduced in MySQL 4.0.21 where a connection starting a transaction, doing updates, then FLUSH TABLES WITH READ LOCK, then COMMIT, would cause replication slaves to stop complaing about error 1223. Bug surfaced when using the InnoDB innobackup script. (Bug #5949)

30-B-7 - Changements de la version 4.1.6 (10 Octobre 2004)

Fonctionnalité ajoutée ou modifiée :

- Added option --sigint-ignore to the mysql command line client to make it ignore SIGINT signals (typically the result of the user pressing Control-C).

- InnoDB: Added the startup option and settable global variable innodb_max_purge_lag for delaying INSERT, UPDATE and DELETE operations when the purge operations are lagging. The default value of this parameter is zero, meaning that there are no delays. Voir Section 15.13, « Implémentation du multi-versionnage ».

- InnoDB: The innodb_autoextend_increment startup option that was introduced in release 4.1.5 was made a settable global variable. (Bug #5736)

- InnoDB: If DROP TABLE is invoked on an InnoDB table for which the .ibd file is missing, print to error log that the table was removed from the InnoDB data dictionary, and allow MySQL to delete the .frm file. Maybe DROP TABLE should issue a warning in this case.

- TIMESTAMP columns now can store NULL values. To create such a column, you must explicitly specify the NULL attribute in the column specification. (Unlike all other column types, TIMESTAMP columns are NOT NULL by default.)

- Now if ALTER TABLE converts one AUTO_INCREMENT column to another AUTO_INCREMENT column it preserves zero values (this includes the case that we don't change such column at all).

- Now if ALTER TABLE converts some column to TIMESTAMP NOT NULL column it converts NULL values to current timestamp value (One can still get old behavior by setting system TIMESTAMP variable to zero).

- On Windows, the MySQL configuration files included in the package now use .ini instead of .cnf as the file name suffix.

Bogues corrigés :

- Fixed a bug that caused the server to crash on attempt to execute a prepared statement with a subselect inside a boolean expression. (Bug #5987)

- Fixed a bug that caused the server to sometimes choose non-optimal execution plan for a prepared statement executed with changed placeholder values. (Bug #6042)

- InnoDB: Make the check for excessive semaphore waits tolerate glitches in the system clock (do not crash the server if the system time is adjusted while InnoDB is under load.). (Bug #5898)

- InnoDB: Fixed a bug in the InnoDB FOREIGN KEY parser that prevented ALTER TABLE of tables containing '#' in their names. (Bug #5856)

- InnoDB: Fixed a bug that prevented ALTER TABLE t DISCARD TABLESPACE from working. (Bug #5851)

- InnoDB: SHOW CREATE TABLE now obeys the SET SQL_MODE=ANSI and SET SQL_QUOTE_SHOW_CREATE=0 settings. (Bug #5292)

- InnoDB: Fixed a bug that caused CREATE TEMPORARY TABLE ... ENGINE=InnoDB to terminate mysqld when running in innodb_file_per_table mode. Per-table tablespaces for temporary tables from now on are created in the temporary directory of mysqld. (Bug #5137)

- InnoDB: Fixed some (not all) UTF-8 bugs in column prefix indexes. (Bug #5975)

- InnoDB: If one updated a column so that its size changed, or updated it to an externally stored (TEXT or BLOB) value, then ANOTHER externally stored column would show up as 512 bytes of good data + 20 bytes of garbage in a consistent read that fetched the old version of the row. (Bug #5960)

- InnoDB: Change error code to HA_ERR_ROW_IS_REFERENCED if we cannot DROP a parent table referenced by a FOREIGN KEY constraint; this error number is less misleading than the previous number HA_ERR_CANNOT_ADD_FOREIGN, but misleading still. (Bug #6202)

- Fixed REVOKE ALL PRIVILEGES, GRANT OPTION FROM user so that all privileges are revoked correctly. (Bug #5831)

- Fixed a bug that caused the server to crash when character set conversion was implicitly used in prepared mode; for example, as in 'abc' LIKE CONVERT('abc' as utf8). (Bug #5688)

- The mysql_change_user() C API function now frees all prepared statements associated with the connection. (Bug #5315)

- Fixed a bug when inserting NULL into an AUTO_INCREMENT column failed, when using prepared statements. (Bug #5510)

- Fixed slave SQL thread so that the SET COLLATION_SERVER... statements it replicates don't advance its position (so that if it gets interrupted before the actual update query, it later redoes the SET). (Bug #5705)

- Fixed that if the slave SQL thread found a syntax error in a query (which should be rare, as the master parsed it successfully), it stops. (Bug #5711)

- Fixed that if a write to a MyISAM table fails because of a full disk or an exceeded disk quota, it prints a message to the error log every 10 minutes, and waits until disk space becomes available. (Bug #3248)

- Now MySQL does not prefer columns, which are mentioned in select list but are renamed, over columns from other tables participating in FROM clause when it resolves GROUP BY clause (e.g. SELECT t1.a AS c FROM t1, t2 ORDER BY a produces an error if both t1 and t2 tables contain a column). (Bug #4302)

- Behavior of ALTER TABLE converting column containing NULL values to AUTO_INCREMENT column is no longer affected by NO_AUTO_VALUE_ON_ZERO mode. (Bug #5915).

30-B-8 - Changements de la version 4.1.4 (16 Septembre 2004)

Fonctionnalité ajoutée ou modifiée :

- InnoDB: Added configuration option innodb_autoextend_increment for setting the size in megabytes by which InnoDB tablespaces are extended when they become full. The default value is 8, corresponding to the fixed increment of 8MB in previous versions of MySQL.

Bogues corrigés :

- Fixed a bug which caused the server to crash on attempt to execute a prepared statement with BETWEEN ? AND ? and a datetime column. (Bug #5748)

- Fixed name resolving of external fields of subqueries if subquery placed in select list of query with grouping. (Bug #5326)

- Fixed detection of using same table for updating and selecting in multi-update queries. (Bug #5455)

- The values of the max_sort_length, sql_mode, and group_concat_max_len system variables now are stored in the query cache with other query information to avoid returning an incorrect result from the query cache. (Bug #5394) (Bug #5515)

- Fixed syntax analyzer with sql_mode=IGNORE_SPACE. It happened to take phrases like default .07 as identifier.identifier. (Bug #5318)

- Fixed illegal internal field length of user variables of integer type. This showed up when creating a table as SELECT @var_name. (Bug #4788)

- Fixed a buffer overflow in prepared statements API (libmysqlclient) when a statement containing thousands of placeholders was executed. (Bug #5194)

- Fixed a bug in the server when after reaching a certain limit of prepared statements per connection (97), statement ids began to overlap, so occasionally wrong statements were chosen for execution. (Bug #5399)

- Fixed a bug in prepared statements when LIKE used with arguments in different character sets crashed server on first execute. (Bug #4368)

- Fixed a bug in prepared statements when providing '0000-00-00' date to a parameter lead to server crash. (Bug #4231, Bug #4562)

- Fixed a bug in OPTIMIZE TABLE that could cause table corruption on FULLTEXT indexes. (Bug #5327)

- InnoDB: Fixed a bug that InnoDB only allowed a maximum of 1000 connections inside InnoDB at the same time. A higher number could cause an assertion failure in sync0arr.c, line 384. Now we allow 1000, 10000, or 50000, depending on the buffer pool size. (Bug #5414)

30-B-9 - Changements de la version 4.1.4 (26 Août 2004)

Note: To fix a compile problem on systems that do not have automake 1.7 installed, an updated 4.1.4a source tarball has been published. In addition to resolving this automake dependency (Bug #5319), it also fixes some reported libedit compile errors when using a non-gcc compiler (Bug #5353).

Fonctionnalité ajoutée ou modifiée :

- Made internal representation of TIMESTAMP values in InnoDB in 4.1 to be the same as in 4.0. This difference resulted in incorrect datetime values in TIMESTAMP columns in InnoDB tables after an upgrade from 4.0 to 4.1. (Bug #4492) Warning: extra steps during upgrade required! Unfortunately this means that if you are upgrading from 4.1.x, where x <= 3, to 4.1.4 you should use mysqldump for saving and then restoring your InnoDB tables with TIMESTAMP columns.

- The mysqld-opt Windows server was renamed to mysqld. This completes the Windows server renaming begun in MySQL 4.1.2. Voir Section 2.2.8.1, « Choisir un serveur MySQL sur Windows ».

- Added Latin language collations for the ucs2 and utf8 Unicode character sets. These are called ucs2_roman_ci and utf8_roman_ci.

- Corrected the name of the Mac OS X StartupItem script (it must match the name of the subdirectory, which was renamed to MySQLCOM in MySQL 4.1.2). Thanks to Bryan McCormack for reporting this.

- Added --start-datetime, --stop-datetime, --start-position, and --stop-position options to mysqlbinlog. These make point-in-time recovery easier.

- Killing a CHECK TABLE statement does not result in the table being marked as « corrupted » any more; the table remains as if CHECK TABLE had not even started. Voir Section 13.5.4.3, « Syntaxe de KILL ».

- Made the MySQL server ignore SIGHUP and SIGQUIT on Mac OS X 10.3. This is needed because under this OS, the MySQL server receives lots of these signals (reported as Bug #2030).

Bogues corrigés :

- Fixed a bug that caused libmysql to crash when attempting to fetch a value of MEDIUMINT column. (Bug #5126)

- Fixed a bug that caused the MySQL server to crash when attempting to execute a prepared statement with SELECT ... INTO @var for a second time. (Bug #5034)

- Fixed execution of optimized IN subqueries that use compound indexes. (Bug #4435)

- Prohibited resolving of table fields in inner queries if fields do not take part in grouping for queries with grouping (inside aggregate function arguments, all table fields are still allowed). (Bug #4814)

- Fixed a crash after SLAVE STOP if the IO thread was in a special state. (Bug #4629)

- Fixed an old bug in concurrent accesses to MERGE tables (even one MERGE table and MyISAM tables), that could have resulted in a crash or hang of the server. (Bug #2408)

- Fixed a bug that caused server crash on attempt to execute for a second time a prepared statement with NOT in WHERE or ON clauses. (Bug #4912)

- MATCH ... AGAINST now works in a subquery. (Bug #4769)

- Fixed a bug that omitted the .err extension of the error log file (--log-error) when the hostname contained a domain name. The domain name is now replaced by the extension. (Bug #4997)

- Fixed a crash in myisamchk. (Bug #4901)

- Fixed a bug which caused server crash if one used the CONVERT_TZ() function with time zone described in database as parameter and this time zone was not used before. (Bug #4508)

- Support for %T, %r, %V, %v and %X, %x format specifiers was added to STR_TO_DATE() function. (Bug #4756)

- Fixed a bug (hang) in NATURAL JOIN where joined table had no common column. (Bug #4807)

- Fixed a crash caused by UNHEX(NULL). (Bug #4441)

- mysql_fix_privilege_tables didn't correctly handle the argument of its --password=# option. (Bug #4240, Bug #4543)

- Fixed that mysqlbinlog --read-from-remote-server sometimes couldn't accept 2 binary logs on command line. (Bug #4507)

- Fixed that mysqlbinlog --position --read-from-remote-server had wrong # at lines. (Bug #4506)

- If CREATE TEMPORARY TABLE t SELECT failed while loading the data, the temporary table was not dropped. (Bug #4551)

- Fixed that when a multiple-table DROP TABLE failed to drop a table on the master server, the error code was not written to the binary log. (Bug #4553)

- When the slave SQL thread was replicating a LOAD DATA INFILE statement, it didn't show the statement in the output of SHOW PROCESSLIST. (Bug #4326)

- Fixed an assertion failure when reading the grant tables (Bug #4407)

- Fixed that CREATE TABLE ... TYPE=HEAP ... AS SELECT... caused replication slave to stop. (Bug #4971)

- Fixed that mysql_options(...,MYSQL_OPT_LOCAL_INFILE,...) failed to disable LOAD DATA LOCAL INFILE. (Bug #5038)

- Fixed that disable-local-infile option had no effect if client read it from a configuration file using mysql_options(...,MYSQL_READ_DEFAULT,...). (Bug #5073)

- Fixed that SET GLOBAL SYNC_BINLOG did not work on some platforms (Mac OS X). (Bug #5064)

- Fixed that mysql-test-run failed on the rpl_trunc_binlog test if running test from the installed (the target of 'make install') directory. (Bug #5050)

- Fixed that mysql-test-run failed on the grant_cache test when run as Unix user 'root'. (Bug #4678)

- Fixed an unlikely deadlock which could happen when using KILL. (Bug #4810)

- Fixed a crash when one connection got KILLed while it was doing START SLAVE. (Bug #4827)

- Made FLUSH TABLES WITH READ LOCK block COMMIT if server is running with binary logging; this ensures that the binary log position is trustable when doing a full backup of tables and the binary log. (Bug #4953)

- Fixed that the counter of an auto_increment column was not reset by TRUNCATE TABLE if the table was a temporary table. (Bug #5033)

- Fixed bug which caused error to be reported when column from ORDER BY clause was present in two tables participating in SELECT even if the second instance of column in select list was renamed. (Bug #4302)

30-B-10 - Changements de la version 4.1.3 (pas encore publiée)

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- Fixed a crash of mysqld that was started with binary logging disabled, but with non-zero expire_logs_days variable. (Bug #3807)

30-B-11 - Changements de la version 4.1.2

Fonctionnalité ajoutée ou modifiée :

- Added explanation of hidden SELECT of UNION in output of EXPLAIN SELECT statement.

- mysql command-line client now supports multiple -e options. (Bug #591)

- New myisam_data_pointer_size system variable. Voir Section 5.2.3, « Variables serveur système ».

- The --log-warnings server option now is enabled by default. Disable with --skip-log-warnings.

- The --defaults-file=file_name option now requires that the filename must exist (safety fix). (Bug #3413)

- mysqld_multi now creates the log in datadir (from [mysqld] section in my.cnf or compiled in), not in /tmp - vulnerability id CAN-2004-0388. Thanks to Christian Hammers from Debian Security Team for reporting this!

- Warning: Incompatible change! String comparison now works according to the SQL standard. Because we have that 'a' = 'a ' then from it must follow that 'a' > 'a\t'. (The latter was not the case before 4.1.2.) To implement it, we had to change how storage engines compare strings internally. As a side effect, if you have a table where a CHAR or VARCHAR column in some row has a value with the last character less than ASCII(32), you will have to repair this table. CHECK TABLES will tell you if this problem exists. (Bug #3152)

- Added support for DEFAULT CURRENT_TIMESTAMP and for ON UPDATE CURRENT_TIMESTAMP specifications for TIMESTAMP columns. Now you can explicitly say that a TIMESTAMP column should be set automatically to the current timestamp for INSERT and/or UPDATE statements, or even prevent the column from updating automatically. Only one column with such an auto-set feature per table is supported. TIMESTAMP columns created with earlier versions of MySQL behave as before. Behavior of TIMESTAMP columns that were created without explicit specification of default/on as earlier depends on its position in table: If it is the first TIMESTAMP column, it will be treated as having been specified as TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. In other cases, it would be treated as a TIMESTAMP DEFAULT 0 column. NOW is supported as an alias for CURRENT_TIMESTAMP. Warning: Incompatible change! Unlike in previous versions, explicit specification of default values for TIMESTAMP column is never ignored and turns off the auto-set feature (unless you have CURRENT_TIMESTAMP as the default).

- Warning: Incompatible change! Renamed prepared statements C API functions:

Old Name

New Name

mysql_bind_param()

mysql_stmt_bind_param()

mysql_bind_result()

mysql_stmt_bind_result()

mysql_prepare()

mysql_stmt_prepare()

mysql_execute()

mysql_stmt_execute()

mysql_fetch()

mysql_stmt_fetch()

mysql_fetch_column()

mysql_stmt_fetch_column()

mysql_param_count()

mysql_stmt_param_count()

mysql_param_result()

mysql_stmt_param_metadata()

mysql_get_metadata()

mysql_stmt_result_metadata()

mysql_send_long_data()

mysql_stmt_send_long_data()

Now all functions that operate with a MYSQL_STMT structure begin with the prefix mysql_stmt_.

- Warning: Incompatible change! The signature of the mysql_stmt_prepare() function was changed to int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length). To create a MYSQL_STMT handle, you should use the mysql_stmt_init() function.

- SHOW GRANTS with no FOR clause or with FOR CURRENT_USER() shows the privileges for the current session.

- The improved character set support introduced in MySQL 4.1.0 for the MyISAM and HEAP storage engines is now available for InnoDB as well.

- A name of « Primary » no longer can be specified as an index name. (That name is reserved for the PRIMARY KEY if the table has one.) (Bug #856)

- MySQL now issues a warning when a SET or ENUM column with duplicate values in the list is created. (Bug #1427)

- Now SQL_SELECT_LIMIT variable has no influence on subqueries. (Bug #2600)

- UNHEX() function implemented. Voir Section 12.3, « Fonctions de chaînes de caractères ».

- History in command line client does not store multiple copies of identical queries that are run consecutively.

- Multi-line queries in the command line client now are stored as a single line.

- UUID() function implemented. Note that it does not work with replication yet. Voir Section 12.8.4, « Fonctions diverses ».

- Prepared statements with all types of subqueries fixed.

- MySQL now supports up to 64 keys per table.

- MyISAM tables now support keys up to 1000 bytes long.

- MyISAM and InnoDB tables now support index prefix lengths up to 1000 bytes long.

- If you try to create a key with a key part that is too long, and it is safe to auto-truncate it to a smaller length, MySQL now does so. A warning is generated, rather than an error.

- The ft_boolean_syntax variable now can be changed while the server is running. Voir Section 5.2.3, « Variables serveur système ».

- REVOKE ALL PRIVILEGES, GRANT FROM user_list is changed to a more consistent REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_list. (Bug #2642)

- Internal string-to-number conversion now supports only SQL:2003 compatible syntax for numbers. In particular, '0x10'+0 will not work anymore. (Actually, it worked only on some systems before, such as Linux. It did not work on others, such as FreeBSD or Solaris. Making these queries OS-independent was the goal of this change). Use CONV() to convert hexadecimal numbers to decimal. E.g. CONV(MID('0x10',3),16,10)+0.

- mysqlhotcopy now works on NetWare.

- ALTER TABLE DROP PRIMARY KEY no longer drops the first UNIQUE index if there is no primary index. (Bug #2361)

- Added latin1_spanish_ci (Modern Spanish) collation for the latin1 character set.

- Added the ENGINE table option as a synonym for the TYPE option for CREATE TABLE and ALTER TABLE.

- Added the --default-storage-engine server option as a synonym for --default-table-type.

- Added the storage_engine system variable as a synonym for table_type.

- Added init_connect and init_slave server variables. The values should be SQL statements to be executed when each client connects or each time a slave's SQL thread starts, respectively.

- C API enhancement: SERVER_QUERY_NO_INDEX_USED and SERVER_QUERY_NO_GOOD_INDEX_USED flags are now set in the server_status field of the MYSQL structure. It is these flags that make the query to be logged as slow if mysqld was started with --log-slow-queries --log-queries-not-using-indexes.

- For replication of MEMORY (HEAP) tables: Made the master automatically write a DELETE FROM statement to its binary log when a MEMORY table is opened for the first time since master's startup. This is for the case where the slave has replicated a non-empty MEMORY table, then the master is shut down and restarted: the table is now empty on master; the DELETE FROM empties it on slave too. Note that even with this fix, between the master's restart and the first use of the table on master, the slave still has out-of-date data in the table. But if you use the init-file option to populate the MEMORY table on the master at startup, it ensures that the failing time interval is zero. (Bug #2477)

- When a session having open temporary tables terminates, the statement automatically written to the binary log is now DROP TEMPORARY TABLE IF EXISTS instead of DROP TEMPORARY TABLE, for more robustness.

- The MySQL server now returns an error if SET SQL_LOG_BIN or SET SQL_LOG_UPDATE is issued by a user without the SUPER privilege (in previous versions it just silently ignored the statement in this case).

- Changed that when the MySQL server has binary logging disabled (that is, no log-bin option was used) then no transaction binlog cache is allocated for connections (this should save binlog_cache_size bytes of memory (32 kilobytes by default) for every connection).

- Added Binlog_cache_use and Binlog_cache_disk_use status variables that count the number of transactions that used transaction binary log and that had to flush this temporary binary log to disk instead of using only buffer in memory. They can be used for tuning the binlog_cache_size system variable.

- Added option --replicate-same-server-id.

- The Mac OS X Startup Item has been moved from the directory /Library/StartupItems/MySQL to /Library/StartupItems/MySQLCOM to avoid a file name collision with the MySQL Startup Item installed with Mac OS X Server. Voir Section 2.8.2, « Notes relatives à Mac OS X ».

Bogues corrigés :

- Fixed check of EXPLAIN of UNION. (Bug #3639)

- Fixed a bug in a query that used DISTINCT and ORDER BY by column's real name, while the column had an alias, specified in SELECT clause. (Bug #3681)

- Fixed crash of group_concat on expression with ORDER BY and external ORDER BY in a query. (Bug #3752)

- Fixed a bug in ALL/SOME subqueries in case of optimisation (key field present in subquery). (Bug #3646)

- Fixed a bug in SHOW GRANTS and EXPLAIN SELECT character set conversion. (Bug #3403)

- Prepare statements parameter do not cause error message as fields used in select list but not included in ORDER BY list.

- UNION statements did not consult SQL_SELECT_LIMIT value when set. This is now fixed properly, which means that this limit is applied to the top level query, unless LIMIT for entire UNION is used.

- Fixed a bug in multiple-table UPDATE statements that resulted in an error when one of the tables was not updated but was used in the nested query, contained therein.

- Fixed mysql_stmt_send_long_data() behavior on second execution of prepared statement and in case when long data had zero length. (Bug #1664)

- Fixed crash on second execution of prepared statement with UNION. (Bug #3577)

- Fixed incorrect results of aggregate functions in subquery with empty result set. (Bug #3505)

- You can now call mysql_stmt_attr_set(..., STMT_ATTR_UPDATE_MAX_LENGTH) to tell the client library to update MYSQL_FIELD->max_length when doing mysql_stmt_store_result(). (Bug #1647).

- Added support for unsigned integer types to prepared statement API (Bug #3035).

- Fixed crash in prepared statements when subquery in the FROM clause with parameter used. (Bug #3020)

- Fixed unknown error when negative value bind to unsigned. (Bug #3223)

- Fixed aggregate function in prepared statements. (Bug #3360)

- Incorrect error message when wrong table used in multiple-table DELETE statement in prepared statements. (Bug #3411)

- Requiring UPDATE privilege for tables which will not be updated in multiple-table UPDATE statement in prepared statements.

- Fixed prepared statement support for INSERT, REPLACE, CREATE, DELETE, SELECT, DO, SET and SHOW. All other commands are prohibited via prepared statement interface. (Bug #3398, Bug #3406, Bug #2811)

- Fixed a lot of bugs in GROUP_CONCAT(). (Bug #2695, Bug #3381, Bug #3319)

- Added optimization that allows for prepared statements using a large number of tables or tables with a large number of columns to be re-executed significantly faster. (Bug #2050)

- Fixed bug that caused execution of prepared statements to fail then table that this statement were using left table cache. This bug showed up as if this prepared statement used random garbage as column names or as server crashes. (Bug #3307)

- Fixed a problem resulting from setting the character_set_results variable to NULL. (Bug #3296)

- Fixed query cache statistics.

- Fixed bug in ANALYZE TABLE on a BDB table inside a transaction that hangs server thread. (Bug #2342)

- Fixed a symlink vulnerability in mysqlbug script. (Bug #3284)

- Fixed a bug in parallel repair (myisamchk -p, myisam_repair_threads); sometimes the repair process failed to repair a table. (Bug #1334)

- A query that uses both UNION [DISTINCT] and UNION ALL now works correctly. (Bug #1428)

- Table default character set affects LONGBLOB columns. (Bug #2821)

- CONCAT_WS() makes the server die in case of illegal mix of collations. (Bug #3087)

- UTF8 charset breaks joins with mixed column/string constant. (Bug #2959)

- Fixed DROP DATABASE to report number of tables deleted.

- Fixed memory leak in the client library when statement handle was freed on closed connection (call to mysql_stmt_close after mysql_close). (Bug #3073)

- Fixed server segfaults when processing malformed prepared statements commands. (Bug #2795, Bug #2274)

- Fixed using subqueries with OR and AND functions. (Bug #2838)

- Fixed comparison of tables/database names with --lower_case_table_names option. (Bug #2880)

- Removed try to check NULL if index built on column where NULL is impossible in IN subquery optimization. (Bug #2393)

- Fixed incorrect parsing of subqueries in the FROM clause. (Bug #2421)

- Fixed processing of RAND() in subqueries with static tables. (bug #2645)

- Fixed bug with quoting of table names in mysqldump for various values of sql_mode of server. (Bug #2591)

- Fixed bug with storing values that are out of range for DOUBLE and FLOAT columns. (Bug #2082)

- Fixed bug with compiling --with-pstack with binutils 2.13.90. (Bug #1661)

- Fixed a bug in the GRANT system. When a password was assigned to an account at the global level and then privileges were granted at the database level (without specifying any password), the existing password was replaced temporarily in memory until the next FLUSH PRIVILEGES operation or the server was restarted. (Bug #2953)

- Fixed a bug in full-text search on multi-byte character set (such as UTF8) that appeared when a search word was shorter than a matching word from the index (for example, searching for « Uppsala » when table data contain « Uppsa*la »). (Bug #3011)

- Fixed a bug that made Max_used_connections to be less than the actual maximum number of connections in use simultaneously.

- Fixed calculation of Index_length in HEAP table status for BTREE indexes. (Bug #2719)

- Fixed mysql_stmt_affected_rows() call to always return number of rows affected by given statement. (Bug #2247)

- Fixed crash in MATCH ... AGAINST() on a phrase search operator with a missing closing double quote. (Bug #2708)

- Fixed output of mysqldump --tab. (Bug #2705)

- Fix for a bug in UNION operations that prevented proper handling of NULL columns. This happened only if a column in the first SELECT node was NOT NULL. (Bug #2508)

- Fix for a bug in UNION operations with InnoDB storage engine, when some columns from one table where used in one SELECT statement and some were used in another SELECT statement. (Bug #2552)

- Fixed a few years old bug in the range optimizer that caused a segmentation fault on some very rare queries. (Bug #2698)

- Fixed bug with SHOW CREATE TABLE ... which didn't properly double quotes. (Bug #2593)

- Queries with subqueries in FROM clause locks all tables at once for now. This also fixed bugs in EXPLAIN of subqueries in FROM output. (Bug #2120)

- Fixed bug with mysqldump not quoting « tricky » names correctly. (Bug #2592)

- Fix for a bug that prevented table / column privileges from being loaded on startup. (Bug #2546)

- Fixed bug in replication with CREATE TABLE ... LIKE ... that resulted in a statement not being written to the binary log. (Bug #2557)

- Fixed memory leak in INSERT ... ON DUPLICATE KEY UPDATE .... (Bug #2438)

- Fixed bug in the parser, making the syntax CONVERT(expr,type) legal again.

- Fixed parsing of short-form IP addresses in INET_ATON(). (Bug #2310)

- Fixed a bug in CREATE ... SELECT that sometimes caused a string column with a multi-byte character set (such as utf8) to have insufficient length to hold the data.

- Fixed a rare table corruption on adding data (INSERT, REPLACE, UPDATE, etc. but not DELETE) to a FULLTEXT index. (Bug #2417)

- Compile the MySQL-client RPM package against libreadline instead of libedit. (Bug #2289)

- Fix for a crashing bug that was caused by not setting vio_timeout() virtual function for all protocols. This bug occurred on Windows. (Bug #2025)

- Fix for a bug that caused mysql client program to erroneously cache the value of the current database. (Bug #2025)

- Fix for a bug that caused client/server communication to be broken when mysql_set_server_option() or mysql_get_server_option() were invoked. (Bug #2207)

- Fix for a bug that caused wong results when CAST() was applied on NULL to signed or unsigned integer column. (Bug #2219)

- Fix for a crashing bug that occurred in the mysql client program when database name was longer then expected. (Bug #2221)

- Fixed a bug in CHECK TABLE that sometimes resulted in a spurious error Found key at page ... that points to record outside datafile for a table with a FULLTEXT index. (Bug #2190)

- Fixed bug in GRANT with table-level privilege handling. (Bug #2178)

- Fixed bug in ORDER BY on a small column. (Bug #2147)

- Fixed a bug with the INTERVAL() function when 8 or more comparison arguments are provided. (Bug #1561)

- Packaging: Fixed a bug in the Mac OS PKG postinstall script (mysql_install_db was called with an obsolete argument).

- Packaging: Added missing file mysql_create_system_tables to the server RPM package. This bug was fixed for the 4.1.1 RPMs by updating the MySQL-server RPM from MySQL-server-4.1.1-0 to MySQL-server-4.1.1-1. The other RPMs were not affected by this change.

- Fixed a bug in myisamchk and CHECK TABLE that sometimes resulted in a spurious error Found key at page ... that points to record outside datafile for a table with a FULLTEXT index. (Bug #1977)

- Fixed a hang in full-text indexing of strings in multi-byte (all besides utf8) charsets. (Bug #2065)

- Fixed a crash in full-text indexing of UTF8 data. (Bug #2033)

- Replication: a rare race condition in the slave SQL thread that could lead to an incorrect complaint that the relay log is corrupted. (Bug #2011)

- Replication: If a client connects to a slave server and issues an administrative statement for a table (for example, OPTIMIZE TABLE or REPAIR TABLE), this could sometimes stop the slave SQL thread. This does not lead to any corruption, but you must use START SLAVE to get replication going again. (Bug #1858)

- Replication: in the slave SQL thread, a multiple-table UPDATE could produce an incorrect complaint that some record was not found in one table, if the UPDATE was preceded by a INSERT ... SELECT. (Bug #1701)

- Replication: sometimes the master gets a non-fatal error during the execution of a statement but finally the statements succeeds (for example, a write to a MyISAM table first receives "no space left on device" but is able to finally complete, Voir Section A.4.3, « Comment MySQL gère un disque plein »); the bug was that the master forgot to reset the error code to 0 after success, so the error code got into its binary log, thus making the slave giving false alarms like "did not get the same error as on master". (Bug #2083)

- Removed a misleading "check permissions on master.info" from a replication error message, because the cause of the problem could be different from permissions. (Bug #2121)

- Fixed a crash when the replication slave was unable to create the first relay log. (Bug #2145)

- ALTER DATABASE caused the client to hang if the database did not exist. (Bug #2333)

- Multiple-table DELETE statements were never replicated by the slave if there were any replicate-*-table options. (Bug #2527)

- Fixed bug in ALTER TABLE RENAME, when rename to the table with the same name in another database silently dropped destination table if it existed. (Bug #2628)

- The MySQL server did not report any error if the query (submitted through mysql_real_query() or mysql_prepare()) was terminated by garbage characters (which can happen if you pass a wrong length parameter to mysql_real_query() or mysql_prepare()); the result was that the garbage characters were written into the binary log. (Bug #2703)

- Fixed bug in client library which caused mysql_fetch and mysql_stmt_store_result() to hang if they were called without prior call of mysql_execute(). Now they give an error instead. (Bug #2248)

- Made clearer the error message which one gets when an update is refused because of the read-only option. (Bug #2757)

- Fixed that replicate-wild-*-table rules apply to ALTER DATABASE when the table pattern is '%', like it is already the case for CREATE DATABASE and DROP DATABASE. (Bug #3000)

- Fixed that when a Rotate event is found by the slave SQL thread in the middle of a transaction, the value of Relay_Log_Pos in SHOW SLAVE STATUS remains correct. (Bug #3017)

- Corrected the master's binary log position that InnoDB reports when it is doing a crash recovery on a slave server. (Bug #3015)

- Changed the column Seconds_Behind_Master in SHOW SLAVE STATUS to never show a value of -1. (Bug #2826)

- Changed that when a DROP TEMPORARY TABLE statement is automatically written to the binary log when a session ends, the statement is recorded with an error code of value zero (this ensures that killing a SELECT on the master does not result in a superfluous error on the slave). (Bug #3063)

- Changed that when a thread handling INSERT DELAYED (also known as a delayed_insert thread) is killed, its statements are recorded with an error code of value zero (killing such a thread does not endanger replication, so we thus avoid a superfluous error on the slave). (Bug #3081)

- Fixed deadlock when two START SLAVE commands were run at the same time. (Bug #2921)

- Fixed that a statement never triggers a superfluous error on the slave, if it must be excluded given the replicate-* options. The bug was that if the statement had been killed on the master, the slave would stop. (Bug #2983)

- The --local-load option of mysqlbinlog now requires an argument.

- Fixed a segmentation fault when running LOAD DATA FROM MASTER after RESET SLAVE. (Bug #2922)

- mysqlbinlog --read-from-remote-server read all binary logs following the one that was requested. It now stops at the end of the requested file, the same was it does when reading a local binary log. (Bug #3204)

- Fixed mysqlbinlog --read-from-remote-server to print the exact positions of events in the "at #" lines. (Bug #3214)

- Fixed a rare error condition that caused the slave SQL thread spuriously to print the message Binlog has bad magic number and stop when it was not necessary to do so. (Bug #3401)

- Fixed the Exec_master_log_pos column and its disk image in the relay-log.info file to be correct if the master had version 3.23. (The value was too big by six bytes.) This bug does not exist in MySQL 5.0. (Bug #3400)

- Fixed mysqlbinlog not to forget to print a USE statement under rare circumstances where the binary log contained a LOAD DATA INFILE statement. (Bug #3415)

- Fixed a memory corruption when replicating a LOAD DATA INFILE when the master had version 3.23. Some smaller problems remain in this setup, Voir Section 6.7, « Fonctionnalités de la réplication et problèmes connus ». (Bug #3422)

- Multiple-table DELETE statements were always replicated by the slave if there were some replicate-*-ignore-table options and no replicate-*-do-table options. (Bug #3461)

- Fixed a crash of the MySQL slave server when it was built with --with-debug and replicating itself. (BUG #3568)

- Fixed that in some replication error messages, a very long query caused the rest of the message to be invisible (truncated), by putting the query last in the message. (Bug #3357)

30-B-12 - Changements de la version 4.1.1 (01 décembre 2003)

This release includes all fixes in MySQL 4.0.16 and most of the fixes in MySQL 4.0.17.

Fonctionnalité ajoutée ou modifiée :

- New CHECKSUM TABLE statement for reporting table checksum values.

- Added character_set_client, character_set_connection, character_set_database, character_set_results, character_set_server, character_set_system, collation_connection, collation_database, and collation_server system variables to provide information about character sets and collations.

- It is now possible to create multiple key caches, assign table indexes to particular caches, and to preload indexes into caches. Voir Section 13.5.4.1, « Syntaxe de CACHE INDEX ». Voir Section 13.5.4.4, « Syntaxe de LOAD INDEX INTO CACHE ». Structured system variables are introduced as a means of grouping related key cache parameters. Voir Section 9.4.1, « Variables système structurées ».

- New COERCIBILITY() function to return the collation coercibility of a string.

- The --quote-names option for mysqldump now is enabled by default.

- mysqldump now includes a statement in the dump output to set FOREIGN_KEY_CHECKS to 0 to avoid problems with tables having to be reloaded in a particular order when the dump is reloaded. The existing FOREIGN_KEY_CHECKS value is saved and restored.

- Important note: If you upgrade to InnoDB-4.1.1 or higher, you cannot downgrade to a version lower than 4.1.1 any more! That is because earlier versions of InnoDB are not aware of multiple tablespaces.

- One can revoke all privileges from a user with REVOKE ALL PRIVILEGES, GRANT FROM user_list.

- Added IGNORE option for DELETE statement.

- The MySQL source distribution now also includes the MySQL Internals Manual internals.texi.

- Added mysql_set_server_option() C API client function to allow multiple statement handling in the server to be enabled or disabled.

- The mysql_next_result() C API function now returns -1 if there are no more result sets.

- Renamed CLIENT_MULTI_QUERIES connect option flag to CLIENT_MULTI_STATEMENTS. To allow for a transition period, the old option will continue to be recognized for a while.

- Require DEFAULT before table and database default character set. This enables us to use ALTER TABLE tbl_name ... CHARACTER SET=... to change the character set for all CHAR, VARCHAR, and TEXT columns in a table.

- Added MATCH ... AGAINST( ... WITH QUERY EXPANSION) and the ft_query_expansion_limit server variable.

- Removed unused ft_max_word_len_for_sort system variable.

- Removed unused ft_max_word_len_for_sort variable from myisamchk.

- Full-text search now supports multi-byte character sets and the Unicode utf8 character set. (The Unicode ucs2 character set is not yet supported.)

- Phrase search in MATCH ... AGAINST ( ... IN BOOLEAN MODE) no longer matches partial words.

- Added aggregate function BIT_XOR() for bitwise XOR operations.

- Replication over SSL now works.

- The START SLAVE statement now supports an UNTIL clause for specifying that the slave SQL thread should be started but run only until it reaches a given position in the master's binary logs or in the slave's relay logs.

- Produce warnings even for single-row INSERT statements, not just for multiple-row INSERT statements. Previously, it was necessary to set SQL_WARNINGS=1 to generate warnings for single-row statements.

- Added delimiter (\d) command to the mysql command-line client for changing the statement delimiter (terminator). The default delimiter is semicolon.

- CHAR, VARCHAR, and TEXT columns now have lengths measured in characters rather than in bytes. The character size depends on the column's character set. This means, for example, that a CHAR(n) column for a multi-byte character set will take more storage than before. Similarly, index values on such columns are measured in characters, not bytes.

- LIMIT no longer accepts negative arguments (they used to be treated as very big positive numbers before).

- The DATABASE() function now returns NULL rather than the empty string if there is no database selected.

- Added --sql-mode=NO_AUTO_VALUE_ON_ZERO option to suppress the usual behavior of generating the next sequence number when zero is stored in an AUTO_INCREMENT column. With this mode enabled, zero is stored as zero; only storing NULL generates a sequence number.

- Warning: Incompatible change! Client authentication now is based on 41-byte passwords in the user table, not 45-byte passwords as in 4.1.0. Any 45-byte passwords created for 4.1.0 must be reset after running the mysql_fix_privilege_tables script.

- Added secure_auth global server system variable and --secure-auth server option that disallow authentication for accounts that have old (pre-4.1.1) passwords.

- Added --secure-auth option to mysql command-line client. If this option is set, the client refuses to send passwords in old (pre-4.1.1) format.

- Warning: Incompatible change! Renamed the C API mysql_prepare_result() function to mysql_get_metadata() as the old name was confusing.

- Added DROP USER 'user_name'@'host_name' statement to drop an account that has no privileges.

- The interface to aggregated UDF functions has changed a bit. You must now declare a xxx_clear() function for each aggregate function XXX().

- Added new ADDTIME(), DATE(), DATEDIFF(), LAST_DAY(), MAKEDATE(), MAKETIME(), MICROSECOND(), SUBTIME(), TIME(), TIMEDIFF(), TIMESTAMP(), UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP(), and WEEKOFYEAR() functions.

- Added new syntax for ADDDATE() and SUBDATE(). The second argument now may be a number representing the number of days to be added to or subtracted from the first date argument.

- Added new type values DAY_MICROSECOND, HOUR_MICROSECOND, MINUTE_MICROSECOND, SECOND_MICROSECOND, and MICROSECOND for DATE_ADD(), DATE_SUB(), and EXTRACT().

- Added new %f microseconds format specifier for DATE_FORMAT() and TIME_FORMAT().

- All queries in which at least one SELECT does not use indexes properly now are written to the slow query log when long log format is used.

- It is now possible to create a MERGE table from MyISAM tables in different databases. Formerly, all the MyISAM tables had to be in the same database, and the MERGE table had to be created in that database as well.

- Added new COMPRESS(), UNCOMPRESS(), and UNCOMPRESSED_LENGTH() functions.

- When using SET sql_mode='mode' for a complex mode (like ANSI), we now update the sql_mode variable to include all the individual options implied by the complex mode.

- Added the OLAP (On-Line Analytical Processing) function ROLLUP, which provides summary rows for each GROUP BY level.

- Added SQLSTATE codes for all server errors.

- Added mysql_sqlstate() and mysql_stmt_sqlstate() C API client functions that return the SQLSTATE error code for the last error.

- TIME columns with hour values greater than 24 were returned incorrectly to the client.

- ANALYZE TABLE, OPTIMIZE TABLE, REPAIR TABLE, and FLUSH statements are now stored in the binary log and thus replicated to slaves. This logging does not occur if the optional NO_WRITE_TO_BINLOG keyword (or its alias LOCAL) is given. Exceptions are that FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE, and FLUSH TABLES WITH READ LOCK are not logged in any case. For a syntax example, Voir Section 13.5.4.2, « Syntaxe de FLUSH ».

- New global system variable relay_log_purge to enable or disable automatic relay log purging.

- LOAD DATA now produces warnings that can be fetched with SHOW WARNINGS.

- Added support for syntax CREATE TABLE table2 (LIKE table1) that creates an empty table table2 with a definition that is exactly the same as table1, including any indexes.

- CREATE TABLE tbl_name (...) TYPE=storage_engine now generates a warning if the named storage engine is not available. The table is still created as a MyISAM table, as before.

- Most subqueries are now much faster than before.

- Added PURGE BINARY LOGS as an alias for PURGE MASTER LOGS.

- Disabled the PURGE LOGS statement that was added in version 4.1.0. The statement now should be issued as PURGE MASTER LOGS or PURGE BINARY LOGS.

- Added SHOW BDB LOGS as an alias for SHOW LOGS.

- Added SHOW MASTER LOGS (which had been deleted in version 4.1.0) as an alias for SHOW BINARY LOGS.

- Added Slave_IO_State and Seconds_Behind_Master columns to the output of SHOW SLAVE STATUS. Slave_IO_State indicates the state of the slave I/O thread, and Seconds_Behind_Master indicates the number of seconds by which the slave is late compared to the master.

- The --lower-case-table-names=1 server option now also makes aliases case insensitive. (Bug #534)

- Changed that the relay log is flushed to disk by the slave I/O thread every time it reads a relay log event. This reduces the risk of losing some part of the relay log in case of brutal crash.

Bogues corrigés :

- Fixed mysql parser not to erroneously interpret ';' character within /* ... */ comment as statement terminator.

- Fixed merging types and length of result set columns for UNION operations. The types and lengths now are determined taking into account values for all SELECT statements in the UNION, not just the first SELECT.

- Fixed a bug in privilege handling that caused connections from certain IP addresses to be assigned incorrect database-level privileges. A connection could be assigned the database privileges of the previous successful authentication from one of those IP addresses, even if the IP address username and database name were different. (Bug #1636)

- Error-handling functions were not called properly when an error resulted from [CREATE | REPLACE| INSERT] ... SELECT statements.

- HASH, BTREE, RTREE, ERRORS, and WARNINGS no longer are reserved words. (Bug #724)

- Fix for bug in ROLLUP when all tables were const tables. (Bug #714)

- Fixed a bug in UNION that prohibited NULL values from being inserted into result set columns where the first SELECT of the UNION retrieved NOT NULL columns. The type and max_length of the result column is now defined based on all UNION parts.

- Fixed name resolution of columns of reduced subqueries in unions. (Bug #745)

- Fixed memory overrun in subqueries in select list with WHERE clause bigger than outer query WHERE clause. (Bug #726)

- Fixed a bug that caused MyISAM tables with FULLTEXT indexes created in 4.0.x to be unreadable in 4.1.x.

- Fixed a data loss bug in REPAIR TABLE ... USE_FRM when used with tables that contained TIMESTAMP columns and were created in 4.0.x.

- Fixed reduced subquery processing in ORDER BY/GROUP BY clauses. (Bug #442)

- Fixed name resolution of outer columns of subquery in INSERT/REPLACE statements. (Bug #446)

- Fixed bug in marking columns of reduced subqueries. (Bug #679)

- Fixed a bug that made CREATE FULLTEXT INDEX syntax illegal.

- Fixed a crash when a SELECT that required a temporary table (marked by Using temporary in EXPLAIN output) was used as a derived table in EXPLAIN command. (Bug #251)

- Fixed a rare table corruption bug in DELETE from a big table with a new (created by MySQL-4.1) full-text index.

- LAST_INSERT_ID() now returns 0 if the last INSERT statement didn't insert any rows.

- Fixed missing last character in function output. (Bug #447)

- Fixed a rare replication bug when a transaction spanned two or more relay logs, and the slave was stopped while executing the part of the transaction that was in the second or later relay log. Then replication would resume at the beginning of the second or later relay log, which was incorrect. (It should resume at BEGIN, in the first relay log.) (Bug #53)

- CONNECTION_ID() now is properly replicated. (Bug #177)

- The new PASSWORD() function in 4.1 is now properly replicated. (Bug #344)

- Fixed a bug with double freed memory.

- Fixed a crashing bug in UNION operations that involved temporary tables.

- Fixed a crashing bug in DERIVED TABLES when EXPLAIN is used on a DERIVED TABLES with a join.

- Fixed a crashing bug in DELETE with ORDER BY and LIMIT caused by an uninitialized array of reference pointers.

- Fixed a bug in the USER() function caused by an error in the size of the allocated string.

- Fixed a crashing bug when attempting to create a table containing a spatial (GIS) column with a storage engine that does not support spatial types.

- Fixed a crashing bug in UNION caused by the empty select list and a non-existent column being used in some of the individual SELECT statements.

- Fixed a replication bug with a 3.23 master and a 4.0 slave: The slave lost the replicated temporary tables if FLUSH LOGS was issued on the master. (Bug #254)

- Fixed a security bug: A server compiled without SSL support still allowed connections by users who had the REQUIRE SSL option specified for their accounts.

- When an undefined user variable was used in a updating query on the master (such as INSERT INTO t VALUES(@a), where @a had never been set by this connection before), the slave could replicate the query incorrectly if a previous transaction on the master used a user variable of the same name. (Bug #1331)

- Fixed bug with prepared statements: Using the ? prepared statement parameter as the argument to certain functions or statement clauses caused a server crash when mysql_prepare() was invoked. (Bug #1500)

- Fixed bug with prepared statements: after call to mysql_prepare placeholders became allowed in all consequent statements, even if they are not prepared (Bug #1946)

- SLAVE START (which is a deprecated syntax, START SLAVE should be used instead) could crash the slave. (Bug #2516)

- Fixed bug in ALTER TABLE RENAME, when rename to the table with the same name in another database silently dropped destination table if it existed. (Bug #2628)

30-B-13 - Changements de la version 4.1.0 (03 Avril 2003 : alpha)

Fonctionnalité ajoutée ou modifiée :

- Added --compatible option to mysqldump for producing output that is compatible with other database systems or with older MySQL servers.

- The --opt option for mysqldump now is enabled by default, as are all the options implied by --opt.

- New CHARSET() and COLLATION() functions to return the character set and collation of a string.

- Allow index type to be specified explicitly for some storage engines via USING type_name syntax in index definition.

- New function IS_USED_LOCK() for determining the connection identifier of the client that holds a given advisory lock.

- New more secure client authentication based on 45-byte passwords in the user table.

- New CRC32() function to compute cyclic redundancy check value.

- On Windows, we are now using shared memory to communicate between server and client when they are running on the same machine and you are connecting to localhost.

- REPAIR TABLE of MyISAM tables now uses less temporary disk space when sorting char columns.

- DATE/DATETIME checking is now a bit stricter to support the ability to automatically distinguish between date, datetime, and time with microseconds. For example, dates of type YYYYMMDD HHMMDD are no longer supported; you must either have separators between each DATE/TIME part or not at all.

- Server side help for all MySQL functions. One can now type help week in the mysql client and get help for the week() function.

- Added new mysql_get_server_version() C API client function.

- Fixed bug in libmysqlclient that fetched column defaults.

- Fixed bug in mysql command-line client in interpreting quotes within comments. (Bug #539)

- Added record_in_range() method to MERGE tables to be able to choose the right index when there are many to choose from.

- Replication now works with RAND() and user variables @var.

- Allow one to change mode for ANSI_QUOTES on the fly.

- EXPLAIN SELECT now can be killed. Voir Section 13.5.4.3, « Syntaxe de KILL ».

- REPAIR TABLE now can be killed. Voir Section 13.5.4.3, « Syntaxe de KILL ».

- Allow empty index lists to be specified for USE INDEX, IGNORE INDEX, and FORCE INDEX.

- DROP TEMPORARY TABLE now drops only temporary tables and doesn't end transactions.

- Added support for UNION in derived tables.

- Warning: Incompatible change! TIMESTAMP is now returned as a string of type 'YYYY-MM-DD HH:MM:SS' and different timestamp lengths are not supported.
This change was necessary for SQL standards compliance. In a future version, a further change will be made (backward compatible with this change), allowing the timestamp length to indicate the desired number of digits of fractions of a second.

- New faster client/server protocol that supports prepared statements, bound parameters, and bound result columns, binary transfer of data, warnings.

- Added database and real table name (in case of alias) to the MYSQL_FIELD structure.

- Multi-line queries: You can now issue several queries at once and then read the results in one go.

- In CREATE TABLE foo (a INT not null primary key) the PRIMARY word is now optional.

- In CREATE TABLE the attribute SERIAL is now an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.

- SELECT ... FROM DUAL is an alias for SELECT .... (To be compatible with some other databases).

- If one creates a too long CHAR/VARCHAR it's now automatically changed to TEXT or BLOB; One will get a warning in this case.

- One can specify the different BLOB/TEXT types with the syntax BLOB(length) and TEXT(length). MySQL will automatically change it to one of the internal BLOB/TEXT types.

- CHAR BYTE is an alias for CHAR BINARY.

- VARCHARACTER is an alias for VARCHAR.

- New operators integer MOD integer and integer DIV integer.

- SERIAL DEFAULT VALUE added as an alias for AUTO_INCREMENT.

- TRUE and FALSE added as alias for 1 and 0, respectively.

- Aliases are now forced in derived tables, as per standard SQL.

- Fixed SELECT .. LIMIT 0 to return proper row count for SQL_CALC_FOUND_ROWS.

- One can specify many temporary directories to be used in a round-robin fashion with: --tmpdir=dirname1:dirname2:dirname3.

- Subqueries: SELECT * from t1 where t1.a=(SELECT t2.b FROM t2).

- Derived tables:

SELECT a.col1, b.col2
FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
other_table b
WHERE a.col1=b.col1;

- Character sets to be defined per column, table and database.

- Unicode (UTF8) support.

- New CONVERT(... USING ...) syntax for converting string values between character sets.

- BTREE index on MEMORY (HEAP) tables.

- Faster embedded server (new internal communication protocol).

- One can add a comment per column in CREATE TABLE.

- SHOW FULL COLUMNS FROM tbl_name shows column comments.

- ALTER DATABASE.

- Support for GIS (Geometrical data). Voir Chapitre 18, Données spatiales avec MySQL.

- SHOW [COUNT(*)] WARNINGS shows warnings from the last command.

- One can specify a column type for a column in CREATE TABLE ... SELECT by defining the column in the CREATE part.

CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

- expr SOUNDS LIKE expr same as SOUNDEX(expr)=SOUNDEX(expr).

- Added new VARIANCE(expr) function returns the variance of expr

- One can create a table from the existing table using CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table (LIKE table). The table can be either normal or temporary.

- New options --reconnect and --skip-reconnect for the mysql client, to reconnect automatically or not if the connection is lost.

- START SLAVE (STOP SLAVE) no longer returns an error if the slave is already started (stopped); it returns a warning instead.

- SLAVE START and SLAVE STOP are no longer accepted by the query parser; use START SLAVE and STOP SLAVE instead.

30-C - Changements de la version 4.0.x (Production)

Version 4.0 of the MySQL server includes many enhancements and new features:

- The InnoDB storage engine is now included in the standard binaries, adding transactions, row-level locking, and foreign keys. Voir Chapitre 15, Le moteur de tables InnoDB.

- A query cache, offering vastly increased performance for many applications. By caching complete result sets, later identical queries can return instantly. Voir Section 5.11, « Cache de requêtes MySQL ».

- Improved full-text indexing with boolean mode, truncation, and phrase searching. Voir Section 12.6, « Recherche en texte intégral (Full-text) dans MySQL ».

- Enhanced MERGE tables, now supporting INSERT statements and AUTO_INCREMENT. Voir Section 14.2, « Tables assemblées MERGE ».

- UNION syntax in SELECT. Voir Section 13.1.7.2, « Syntaxe de UNION ».

- Multiple-table DELETE statements. Voir Section 13.1.1, « Syntaxe de DELETE ».

- libmysqld, the embedded server library. Voir Section 24.2.16, « libmysqld, la bibliothèque du serveur embarqué MySQL ».

- Additional GRANT privilege options for even tighter control and security. Voir Section 13.5.1.3, « Syntaxe de GRANT et REVOKE ».

- Management of user resources in the GRANT system, particularly useful for ISPs and other hosting providers. Voir Section 5.6.4, « Limiter les ressources utilisateurs ».

- Dynamic server variables, allowing configuration changes to be made without having to stop and restart the server. Voir Section 13.5.2.8, « Syntaxe de SET ».

- Improved replication code and features. Voir Chapitre 6, Réplication de MySQL.

- Numerous new functions and options.

- Changes to existing code for enhanced performance and reliability.

For a full list of changes, please refer to the changelog sections for each individual 4.0.x release.

30-C-1 - Changements de la version 4.0.25 (pas encore publié)

Fonctionnalité ajoutée ou modifiée :

- Added --with-big-tables compilation option to configure. (Previously it was necessary to pass -DBIG_TABLES to the compiler manually in order to enable large table support.) Section 2.4.2, « Options habituelles de configure » for details.

Bogues corrigés :

- Fixed a deadlock resulting from use of FLUSH TABLES WITH READ LOCK while an INSERT DELAYED statement is in progress. (Bug #7823)

- Fixed a segmentation fault in mysqlcheck that occurred when the last table checked in --auto-repair mode returned an error (such as the table being a MERGE table). (Bug #9492)

- Fixed faulty display of TIMESTAMP columns retrieved as col_name+0 while the new system variable is set to 1. (Bug #8894)

- Queries containing CURRENT_USER() incorrectly were registered in the query cache. (Bug #9796)

- Fixed problems with static variables to allow building on Fedora Core 3. (Bug #6554)

- An UPDATE that updated only some of the columns in a multiple-column index could result in a loop. (Bug #8942)

- REPAIR TABLE did not invalidate query results in the query cache that were generated from the table. (Bug #8480)

- Fixed a bug that caused concurrent inserts to be allowed into the tables in the SELECT ... UNION ... part of INSERT ... SELECT ... UNION .... This could result in the incorrect order of queries in the binary log. (Bug #9922)

- Fixed a bug that under certain circumstances could allow a privilege escalation via database wildcards in GRANT. (Bug #3924, CAN-2004-0957)

- <=> was not properly comparing NULL values in the WHERE clause of outer joins. (Bug #8711)

- InnoDB: Fixed a bug : MySQL-4.0.23 and 4.0.24 could complain that an InnoDB table created with MySQL-3.23.49 or earlier was in the new compact InnoDB table format of 5.0.3 or later, and InnoDB would refuse to use that table. (The same bug exists in 4.1.8 - 4.1.10.) There is nothing wrong with the table, it is mysqld that is in error. Workaround: wait that 4.0.25 or 4.1.11 is released before doing an upgrade, or dump the table and recreate it with any MySQL version >= 3.23.50 before upgrading to 4.0.23 or 4.0.24.

30-C-2 - Changements de la version 4.0.24 (04 Mars 2005)

Fonctionnalité ajoutée ou modifiée :

- Security improvement: The server creates .frm, .MYD, .MYI, .MRG, .ISD, and .ISM table files only if a file with the same name does not already exist. Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0711)

- Security improvement: User-defined functions should have at least one symbol defined in addition to the xxx symbol that corresponds to the main xxx() function. These auxiliary symbols correspond to the xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear(), and xxx_add() functions. mysqld by default no longer loads UDFs unless they have at least one auxiliary symbol defined in addition to the main symbol. The --allow-suspicious-udfs option controls whether UDFs that have only an xxx symbol can be loaded. By default, the option is off. mysqld also checks UDF filenames when it reads them from the mysql.func table and rejects those that contain directory pathname separator characters. (It already checked names as given in CREATE FUNCTION statements.) Voir Section 27.2.3.1, « Fonctions utilisateur : appeler des fonctions simples », Section 27.2.3.2, « Appeler des fonctions utilisateurs pour les groupements », and Section 27.2.3.6, « Précautions à prendre avec les fonctions utilisateur ». Thanks to Stefano Di Paola <stefano.dipaola@wisec.it> for finding and informing us about this issue. (CAN-2005-0709, CAN-2005-0710)

- InnoDB: Added configuration option and settable global variable innodb_autoextend_increment for setting the size in megabytes by which InnoDB tablespaces are extended when they become full. The default value is 8, corresponding to the fixed increment of 8MB in previous versions of MySQL.

- InnoDB: Do not acquire an internal InnoDB table lock in LOCK TABLES if AUTOCOMMIT=1. This helps in porting old MyISAM applications to InnoDB. InnoDB table locks in that case caused deadlocks very easily.

Bogues corrigés :

- AES_DECRYPT(col_name,key) could fail to return NULL for invalid values in col_name, if col_name was declared as NOT NULL. (Bug #8669)

- FOUND_ROWS() returned an incorrect value after a SELECT SQL_CALC_FOUND_ROWS DISTINCT statement that selected constants and included GROUP BY and LIMIT clauses. (Bug #7945)

- Queries of the form (SELECT ...) ORDER BY ... were being treated as a UNION. This improperly resulted in only distinct values being returned (because UNION by default eliminates.) (Bug #7672)

- Index cardinality was not being updated properly for TEMPORARY tables under some circumstances, such as CREATE TABLE ... SELECT followed by ANALYZE TABLE. (Bug #7519)

- Fixed a server crash caused by DELETE FROM tbl_name ... WHERE ... ORDER BY tbl_name.col_name when the ORDER BY column was qualified with the table name. (Bug #8392)

- Fixed a bug in MATCH ... AGAINST in natural language mode that could cause a server crash if the FULLTEXT index was not used in a join (EXPLAIN did not show fulltext join mode) and the search query matched no rows in the table (Bug #8522).

- Platform and architecture information in version information produced for --version option on Windows was always Win95/Win98 (i32). More accurately determine platform as Win32 or Win64 for 32-bit or 64-bit Windows, and architecture as ia32 for x86, ia64 for Itanium, and axp for Alpha. (Bug #4445)

- Fixed an optimization problem that allowed a negative number to be stored in a DOUBLE UNSIGNED column when it was assigned a value from a signed DOUBLE column. (Bug #7700)

- Fixed a failure of multiple-table updates to replicate properly on slave servers when --replicate-*-table options had been specified. (Bug #7011)

- Renamed set_bit() and clear_bit() functions in source code to avoid a conflict with functions of the same names in Linux kernel header files. (Bug #7971)

- Part of the information being used to cache access-permission lookups was not always reinitialized properly, particularly for connections from localhost on Windows. The result was connection failures that appeared to occur randomly. (Bug #5569)

- Corrected a problem with the QUOTE() function returning bad results. (Bug #8248)

- Fixed a problem where INSERT INTO ...SELECT failed when the source and target table were the same. (Bug #6034)

- Fixed a problem where RPM installation on Linux as a non-privileged user would result in incomplete installation. (Bug #7347)

- Change thread stack size used for building Linux RPM distributions to avoid warnings about stack size during server startup. (Bug #6226)

- Fixed a symlink vulnerability in the mysqlaccess script. Reported by Javier Fernandez-Sanguino Pena and Debian Security Audit Team. (CAN-2005-0004)

- Fixed support for C API function mysql_list_fields(), which was accidentally broken in 4.0.22 (Bug#6761)

- Make query_cache_wlock_invalidate system variable visible in SHOW VARIABLES output. (Bug #7594)

- Fixed a bug which caused FROM_UNIXTIME() function to return NULL for zero argument instead of the Epoch. (Bug #7515)

- Now in datetime values two digit year is interpreted as year in 20th or 21st century even with zero month and day. (Bug #7297)

- Fixed a bug in QUOTE function when used in conjunction with some other string functions. This lead to severe buffer overflow and server crashing. (Bug #7495)

- InnoDB: Work around a problem in AIX 5.1 patched with ML7 security patch: InnoDB would refuse to open its ibdata files, complaining about an operating system error 0.

- InnoDB: Fixed a memory corruption bug if one created a table with a primary key that contained at least two column prefixes. An example: CREATE TABLE t(a char(100), b tinyblob, PRIMARY KEY(a(5), b(10))).

- InnoDB: Use native tmpfile() function on Netware. All InnoDB temporary files are created under sys:\tmp. Previously, InnoDB temporary files were never deleted on Netware.

- InnoDB: Honor the --tmpdir startup option when creating temporary files. Previously, InnoDB temporary files were always created in the temporary directory of the operating system. On Netware, InnoDB will continue to ignore --tmpdir. (Bug #5822)

- InnoDB: Fix a theoretical hang over the adaptive hash latch in InnoDB if one runs INSERT ... SELECT ... (binlog not enabled), or a multi-table UPDATE or DELETE, and only the read tables are InnoDB type, the rest are MyISAM; this also fixes bug #7879Bug #7879 for InnoDB type tables. ()

- InnoDB: Fixed a bug : 32-bit mysqld binaries built on HP-UX-11 did not work with InnoDB files greater than 2 GB in size. (Bug #6189)

- InnoDB: Fixed a bug : InnoDB failed to drop a table in the background drop queue if the table was referenced by a foreign key constraint.

- InnoDB: Fixed a bug : if we dropped a table where an INSERT was waiting for a lock to check a FOREIGN KEY constraint, then an assertion would fail in lock_reset_all_on_table(), since that operation assumes no waiting locks on the table or its records.

- Fixed that, when encountering a « disk full » or « quota exceeded » write error, MyISAM sometimes didn't sleep and retry the write, thus resulting in a corrupted table. (Bug #7714)

- Fixed that a slave could crash after replicating many ANALYZE TABLE, OPTIMIZE TABLE, or REPAIR TABLE statements from the master. (Bug #6461, Bug #7658)

- Fixed a bug where MySQL was allowing concurrent updates (inserts, deletes) to a table if binary logging is enabled. Changed to ensure that all updates are executed in a serialized fashion, because they are executed serialized when binlog is replayed. (Bug #7879)

- Fixed a bug that caused the slave to stop on statements that produced an error on the master. (Bug #8412)

- Documented problem with using mysqldump in 4.0.x to dump TIMESTAMP(2) and TIMESTAMP(4) column types. (Bug #6530)

30-C-3 - Changements de la version 4.0.23 (18 Décembre 2004)

Note: Due to a libtool-related bug in the source distribution, the creation of shared libmysqlclient libraries was not possible (the resulting files were missing the .so file name extension). The file ltmain.sh was updated to fix this problem and the resulting source distribution was released as mysql-4.0.23a.tar.gz. This modification did not affect the binary packages. (Bug #7401)

Fonctionnalité ajoutée ou modifiée :

- Added --hex-blob option to mysqldump for dumping binary string columns using hexadecimal notation.

- Added mysql_hex_string() C API function that hex-encodes a string.

- InnoDB: Do not periodically write SHOW INNODB STATUS information to a temporary file unless the configuration option innodb_status_file=1 is set.

- InnoDB: Made the foreign key parser better aware of quotes. (Bug #6340)

- mysqlbinlog now prints an informative commented line (thread id, timestamp, server id, etc) before each LOAD DATA INFILE, like it does for other queries; unless --short-form is used.

Bogues corrigés :

- Corrected accounts in the mysql.user table in Windows distributions that had been created with a Host value of build rather than %. (Bug #6000)

- Prevent adding CREATE TABLE .. SELECT query to the binary log when the insertion of new records partially failed. (Bug #6682)

- Fixed bug which caused FROM_UNIXTIME() function to return wrong result if the argument was too big. (Bug #6439)

- Fixed bug which caused MySQL server to store wrong values in TIMESTAMP columns and give wrong results for UNIX_TIMESTAMP() function if it was run in time zone with leap seconds. (Bug #6387)

- InnoDB: Fixed a bug in LOAD DATA INFILE...REPLACE printing duplicate key error when executing the same load query several times. (Bug #5835)

- InnoDB: Refuse to open new-style tables created with MySQL 5.0.3 or later. (Bug #7089)

- InnoDB: Do not call rewind() when displaying SHOW INNODB STATUS information on stderr.

- InnoDB: If one used INSERT IGNORE to insert several rows at a time, and the first inserts were ignored because of a duplicate key collision, then InnoDB in a replication slave assigned AUTO_INCREMENT values 1 bigger than in the master. This broke the MySQL replication. (Bug #6287)

- InnoDB: Fix two hangs: FOREIGN KEY constraints treated table and database names as case-insensitive. RENAME TABLE t TO T would hang in an endless loop if t had a foreign key constraint defined on it. Fix also a hang over the dictionary mutex that would occur if one tried in ALTER TABLE or RENAME TABLE to create a foreign key constraint name that collided with another existing name. (Bug #3478)

- InnoDB: Treat character 0xA0 as space in InnoDB's FOREIGN KEY parser if MySQL treats it as space in the default charset. EMS MySQL Manager inserts character 0xA0 after the table name in an ALTER, which confused InnoDB's parser.

- Fixed a bug which caused a crash when only the slave I/O thread was stopped and restarted. (Bug #6148)

- If a connection had an open transaction but had done no updates to transactional tables (for example if had just done a SELECT FOR UPDATE then executed a non-transactional update, that update automatically committed the transaction (thus releasing InnoDB's row-level locks etc). (Bug #5714)

- If a connection was interrupted by a network error and did a rollback, the network error code got stored into the BEGIN and ROLLBACK binary log events; that caused superfluous slave stops. (Bug #6522)

- A sequence of BEGIN (or SET AUTOCOMMIT=0), FLUSH TABLES WITH READ LOCK, transactional update, COMMIT, FLUSH TABLES WITH READ LOCK could hang the connection forever and possibly the MySQL server itself. This happened for example when running the innobackup script several times. (Bug #6732)

30-C-4 - Changements de la version 4.0.22 (27 Octobre 2004)

Fonctionnalités ajoutées ou modifiées :

- InnoDB: Made LOCK TABLES behave by default like it did before MySQL 4.0.20 or 4.1.2: no InnoDB lock will be taken. Added a startup option and settable system variable innodb_table_locks for making LOCK TABLE acquire also InnoDB locks. Voir Section 15.17, « Restrictions sur les tables InnoDB ». (Bug #3299, Bug #5998)

- The --with-openssl option for configure now accepts a path prefix as an argument. --with-openssl-includes and --with-openssl-libs still are supported, but are needed only to override the default values. (Bug #5494)

- Added new --without-man option to configure to suppress building/installing the manual pages. (Bug #5379)

Bogues corrigés :

- Fixed bug in server which caused connection stall when one of deprecated libmysqlclient functions mysql_create_db(), mysql_rm_db() were called and were going to return error. (Bug #6081)

- Fixed returning wrong query result from query cache if temporary table haded real tables after putting results to query cache. (Bug #6084)

- Fixed ENABLE KEYS, which failed if tmpdir ran out of space. Now, a full repair is done in this case. (Bug #5625)

- Fixed an improper error message when trying to drop a table which is referenced by a FOREIGN KEY constraint. (Bug #5784)

- Fixed a bug that allowed FLUSH TABLE(S) to close HANDLER tables. HANDLER tables now are re-opened after a FLUSH TABLE(S) when they are next used. However, they lose their file position if this happens. (Bug #4286)

- Fixed a bug that allowed HANDLER tables with the same alias to be multiple opened. HANDLER aliases must now be unique, even though it is syntactically correct in versions below 4.1, to qualify them with their base table's database name (e.g. test_db.handler_tbl, but this will now conflict with e.g. another_db.handler_tbl). (Bug #4335)

- Fixed crash when using MySQL 4.0 with privilege tables from MySQL 5.0.

- InnoDB: Make the check for excessive semaphore waits tolerate glitches in the system clock (do not crash the server if the system time is adjusted while InnoDB is under load.). (Bug #5898)

- mysqlimport now reads input files locally from the client host only if the --local option is given. Previously, it assumed incorrectly in some cases that files were local even without --local. (Bug #5829)

- InnoDB: Fixed a bug in the InnoDB FOREIGN KEY parser that prevented ALTER TABLE of tables containing '#' in their names. (Bug #5856)

- Fixed a bug which resulted in erronously calculated number of examined rows in UNION's. This value is printed in the slow query log. (Bug #5879)

- Fixed bug with crash of server on some values of read_rnd_buffer_size (Bug #5492)

- Fixed bug which caused truncation of values read from or into TIMESTAMP fields if --new mode was enabled. (Bug #4131)

- mysqladmin now returns a status of 0 even when the server denies access; such an error means theserver is running. (Bug #3120)

- InnoDB: Fixed a bug introduced in 4.0.21. An assertion failed if one used mysqldump with the option -l or --opt, or if one used LOCK TABLES ... LOCAL. (Workaround in 4.0.21: use --quick and --single-transaction. (Bug #5538)

- Fixed that if the slave SQL thread found a syntax error in a query (which should be rare, as the master parsed it successfully), it stops. (Bug #5711)

- Fixed that if a write to a MyISAM table fails because of a full disk or an exceeded disk quota, it prints a message to the error log every 10 minutes, and waits until disk becomes free. (Bug #3248)

- Fixed problem with symlinked databases on Windows being shown with SHOW DATABASES even if the database name doesn't match the given wildcard (Bug #5539)

- Fixed problem introduced in 4.0.21 where a connection starting a transaction, doing updates, then FLUSH TABLES WITH READ LOCK, then COMMIT, would cause replication slaves to stop complaing about error 1223. Bug surfaced when using the InnoDB innobackup script. (Bug #5949)

30-C-5 - Changements de la version 4.0.21

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- Fixed a bug with truncation of big values (> 4294967295) of 64-bit system variables. (Bug #3754)

30-C-6 - Changements de la version 4.0.20

Fonctionnalité ajoutée ou modifiée :

- Phrase search in MATCH ... AGAINST ( ... IN BOOLEAN MODE) no longer matches partial words.

Bogues corrigés :

- Fixed a bug in division / reporting incorrect metadata (number of digits after the decimal point). It can be Voirn, e.g. in CREATE TABLE t1 SELECT "0.01"/"3". (Bug #3612)

- Fixed a problem with non-working DROP DATABASE on some configurations (in particular, Linux 2.6.5 with ext3 are known to expose this bug). (Bug #3594)

- Fixed that in some replication error messages, a very long query caused the rest of the message to be invisible (truncated), by putting the query last in the message. (Bug #3357)

30-C-7 - Changements de la version 4.0.19 (04 mai 2004)

Note: The MySQL 4.0.19 binaries were uploaded to the download mirrors on May, 10th. However, a potential crashing bug was found just before the 4.0.19 release was publicly announced and published from the 4.0 download pages at http://dev.mysql.com/.

Voir (Bug #3596) for details (it was reported against MySQL-4.1, but was confirmed to affect 4.0.19 as well).

A fix for this bug was pushed into the MySQL source tree shortly after it could be reproduced and will be included in the upcoming MySQL 4.0.20, to be released shortly. We recommend users to stick to MySQL 4.0.18 for the time being, until MySQL 4.0.20 has been released (this specific bug was introduced after MySQL 4.0.18 was released, so older versions were not affected by it). We apologize for the inconvenience!

Fonctionnalité ajoutée ou modifiée :

- If length of a timestamp field is defined as 19, the timestamp will be displayed as "YYYY-MM-DD HH:MM:SS". This is done to make it easier to use tables created in MySQL 4.1 to be used in MySQL 4.0.

- If you use RAID_CHUNKS with a value > 255 it will be set to 255. This was made to ensure that all raid directories are always 2 hex bytes. (Bug #3182)

- Changed that the optimizer will now consider the index specified in FORCE INDEX clause as a candidate to resolve ORDER BY as well.

- Non-standard behavior of UNION statements has changed to the standard ones. So far, a table name in the ORDER BY clause was tolerated. From now on a proper error message is issued (Bug #3064).

- Added max_insert_delayed_threads system variable as a synonym for max_delayed_threads.

- Added query_cache_wlock_invalidate system variable. It allow emulation of MyISAM table write-locking behavior, even for queries in the query cache. (Bug #2693)

- The keyword MASTER_SERVER_ID is not reserved anymore.

- The following is mainly relevant for Mac OS X users who use a case-insensitive filesystem. This is not relevant for Windows users as InnoDB in this case always stores file names in lower case:
One can now force lower_case_table_names to 0 from the command line or a configuration file. This is useful with case-insensitive filesystems when you have previously not used lower_case_table_names=1 or lower_case_table_names=2 and your have already created InnoDB tables. With lower_case_table_names=0, InnoDB tables were stored in mixed case while setting lower_case_table_names <> 0 will now force it to lower case (to make the table names case insensitive).
Because it's possible to crash MyISAM tables by referring to them with different case on a case-insensitive filesystem, we recommend that you use lower_case_table_names or lower_case_table_names=2 on such filesystems.
The easiest way to convert to use lower_case_table_names=2 is to dump all your InnoDB tables with mysqldump, drop them and then restore them.

- Non-standard behavior of UNION statements has changed to the standard ones. So far, a table name in the ORDER BY clause was tolerated. From now on a proper error message is issued (Bug #3064).

- Added max_insert_delayed_threads system variable as a synonym for max_delayed_threads.

- Added query_cache_wlock_invalidate system variable. It allow emulation of MyISAM table write-locking behavior, even for queries in the query cache. (Bug #2693)

- Changed that the relay log is flushed to disk by the slave I/O thread every time it reads a relay log event. This reduces the risk of losing some part of the relay log in case of brutal crash.

- When a session having open temporary tables terminates, the statement automatically written to the binary log is now DROP TEMPORARY TABLE IF EXISTS instead of DROP TEMPORARY TABLE, for more robustness.

- Added option --replicate-same-server-id.

Bogues corrigés :

- Added missing full-text variable ft_stopword_file to myisamchk.

- Don't allow stray ',' at the end of field specifications. (Bug #3481)

- INTERVAL now can handle big values for seconds, minutes and hours. (Bug #3498)

- Blank hostname did not work as documented for table and column privileges. Now it's works the same way as '%'. (Bug #3473)

- Fixed a harmless buffer overflow in replace utility. (Bug# 3541)

- Fixed SOUNDEX() to ignore non-alphabetic characters also in the beginning of the string. (Bug #3556)

- Fixed a bug in MATCH ... AGAINST() searches when another thread was doing concurrent inserts into the MyISAM table in question. The first --- full-text search --- query could return incorrect results in this case (e.g. « phantom » rows or not all matching rows, even an empty result set). The easiest way to check whether you are affected is to start mysqld with --skip-concurrent-insert switch and Voir if it helps.

- Fixed bug when doing DROP DATABASE on a directory containing non- MySQL files. Now a proper error message is returned.

- Fixed bug in ANALYZE TABLE on a BDB table inside a transaction that hangs server thread. (Bug #2342)

- Fixed a symlink vulnerability in mysqlbug script. (Bug #3284)

- Fixed core dump bug in SELECT DISTINCT where all selected parts where constants and there were hidden columns in the created temporary table. (Bug #3203)

- Fixed core dump bug in COUNT(DISTINCT) when there was a lot of values and one had a big value for max_heap_table_size.

- Fixed problem with multi-table-update and BDB tables. (Bug: #3098)

- Fixed memory leak when dropping database with RAID tables. (Bug #2882)

- Fixed core dump crash in replication during relay-log switch when the relay log went over max_relay_log_size and the slave thread did a flush_io_cache() at the same time.

- Fixed hangup bug when issuing multiple SLAVE START from different threads at the same time. (Bug #2921)

- Fixed bug when using DROP DATABASE with lower_case_table_names=2.

- Fixed wrong result in UNION when using lower_case_table_names=2. (Bug #2858)

- One can now kill threads that is 'stuck' in the join optimizer (can happen when there is MANY tables in the join in which case the optimizer can take really long time). (Bug #2825)

- Rollback DELETE and UPDATE statements if thread is killed. (Bug #2422)

- Ensure that all rows in an INSERT DELAYED statement is written at once if binary logging is enabled. (Bug #2491).

- Fixed bug in query cache statistic, more accurate formula linked statistic variables mentioned in the manual.

- Fixed a bug in parallel repair (myisamchk -p, myisam_repair_threads) - sometimes repair process failed to repair a table. (Bug #1334)

- Fixed bugs with names of tables, databases and columns that end to space (Bug #2985)

- Fixed a bug in multiple-table UPDATE statements involving at least one constant table. Bug was exhibited in allowing non matching row to be updated. (Bug #2996).

- Fixed all bugs in scripts for creating/upgrading system database (Bug #2874) Added tests which guarantee against such bugs in the future.

- Fixed bug in mysql command-line client in interpreting quotes within comments. (Bug #539)

- --set-character-set and --character-sets-dir options in myisamchk now work.

- Fixed a bug in mysqlbinlog that caused one pointer to be free'd twice in some cases.

- Fixed a bug in boolean full-text search, that sometimes could lead to false matches in queries with several levels of subexpressions using + operator (for example, MATCH ... AGAINST('+(+(word1 word2)) +word3*' IN BOOLEAN MODE).

- Fixed Windows-specific portability bugs in myisam_ftdump.

- Fixed a bug in multiple-table DELETE that was caused by foreign key constraints. If the order of the tables established by MySQL optimizer did not match parent-child order, no rows were deleted and no error message was provided. (Bug #2799)

- Fixed a few years old bug in the range optimizer that caused a segmentation fault on some very rare queries. (Bug #2698)

- Replication: If a client connects to a slave server and issues an administrative statement for a table (for example, OPTIMIZE TABLE or REPAIR TABLE), this could sometimes stop the slave SQL thread. This does not lead to any corruption, but you must use START SLAVE to get replication going again. (Bug #1858) The bug was accidentally not fixed in 4.0.17 as it was unfortunately earlier said.

- Fixed that when a Rotate event is found by the slave SQL thread in the middle of a transaction, the value of Relay_Log_Pos in SHOW SLAVE STATUS remains correct. (Bug #3017)

- Corrected the master's binary log position that InnoDB reports when it is doing a crash recovery on a slave server. (Bug #3015)

- Changed that when a DROP TEMPORARY TABLE statement is automatically written to the binary log when a session ends, the statement is recorded with an error code of value zero (this ensures that killing a SELECT on the master does not result in a superfluous error on the slave). (Bug #3063)

- Changed that when a thread handling INSERT DELAYED (also known as a delayed_insert thread) is killed, its statements are recorded with an error code of value zero (killing such a thread does not endanger replication, so we thus avoid a superfluous error on the slave). (Bug #3081)

- Fixed deadlock when two START SLAVE commands were run at the same time. (Bug #2921)

- Fixed that a statement never triggers a superfluous error on the slave, if it must be excluded given the replicate-* options. The bug was that if the statement had been killed on the master, the slave would stop. (Bug #2983)

- The --local-load option of mysqlbinlog now requires an argument.

- Fixed a segmentation fault when running LOAD DATA FROM MASTER after RESET SLAVE. (Bug #2922)

- Fixed a rare error condition that caused the slave SQL thread spuriously to print the message Binlog has bad magic number and stop when it was not necessary to do so. (Bug #3401)

- Fixed the column Exec_master_log_pos (and its disk image in the relay-log.info file) to be correct if the master had version 3.23 (it was too big by 6 bytes). This bug does not exist in the 5.0 version. (Bug #3400)

- Fixed that mysqlbinlog does not forget to print a USE command under rare circumstances where the binary log contained a LOAD DATA INFILE command. (Bug #3415)

- Fixed a memory corruption when replicating a LOAD DATA INFILE when the master had version 3.23. Some smaller problems remain in this setup, Voir Section 6.7, « Fonctionnalités de la réplication et problèmes connus ». (Bug #3422)

- Multiple-table DELETE statements were always replicated by the slave if there were some replicate-*-ignore-table options and no replicate-*-do-table options. (Bug #3461)

- Fixed a crash of the MySQL slave server when it was built with --with-debug and replicating itself. (BUG #3568)

30-C-8 - Changements de la version 4.0.18 (pas encore publiée)

Fonctionnalité ajoutée ou modifiée :

- Fixed processing of LOAD DATA by mysqlbinlog in remote mode. (Bug #1378)

- New utility program myisam_ftdump was added to binary distributions.

- ENGINE is now a synonym for the TYPE option for CREATE TABLE and ALTER TABLE.

- lower_case_table_names system variable now can take a value of 2, to store table names in mixed case on case-insensitive filesystems. It's forced to 2 if the database directory is located on a case-insensitive filesystem.

- For replication of MEMORY (HEAP) tables: Made the master automatically write a DELETE FROM statement to its binary log when a MEMORY table is opened for the first time since master's startup. This is for the case where the slave has replicated a non-empty MEMORY table, then the master is shut down and restarted: the table is now empty on master; the DELETE FROM empties it on slave too. Note that even with this fix, between the master's restart and the first use of the table on master, the slave still has out-of-date data in the table. But if you use the init-file option to populate the MEMORY table on the master at startup, it ensures that the failing time interval is zero. (Bug #2477)

- Optimizer is now better tuned for the case where the first used key part (of many) is a constant. (Bug #1679)

- Removed old non-working --old-rpl-compat server option, which was a holdover from the very first 4.0.x versions. (Bug #2428)

Bogues corrigés :

- mysqlhotcopy now works on NetWare.

- DROP DATABASE could not drop databases with RAID tables that had more than nine RAID_CHUNKS. (Bug #2627)

- Fixed bug in range optimizer when using overlapping ranges. (Bug #2448)

- Limit wait_timeout to 2147483 on Windows (OS limit). (Bug #2400)

- Fixed bug when --init-file crashes MySQL if it contains a large SELECT. (Bug #2526)

- SHOW KEYS now shows NULL in the Sub_part column for FULLTEXT indexes.

- The signal thread's stack size was increased to enable mysqld to run on Debian/IA-64 with a TLS-enabled glibc. (Bug #2599)

- Now only the SELECT privilege is needed for tables that are only read in multiple-table UPDATE statements. (Bug #2377)

- Give proper error message if one uses LOCK TABLES ... ; INSERT ... SELECT and one used the same table in the INSERT and SELECT part. (Bug #2296)

- SELECT INTO ... DUMPFILE now deletes the generated file on error.

- Fixed foreign key reference handling to allow references to column names that contain spaces. (Bug #1725)

- Fixed problem with index reads on character columns with BDB tables. The symptom was that data could be returned in the wrong lettercase. (Bug #2509)

- Fixed a spurious table corruption problem that could sometimes appear on tables with indexed TEXT columns if these columns happened to contain values having trailing spaces. This bug was introduced in 4.0.17.

- Fixed a problem where some queries could hang if a condition like indexed_TEXT_column =expr was present and the column contained values having trailing spaces. This bug was introduced in 4.0.17.

- Fixed a bug that could cause incorrect results from a query that involved range conditions on indexed TEXT columns that happened to contain values having trailing spaces. This bug was introduced in 4.0.17. (Bug #2295)

- Fixed incorrect path names in some of the manual pages. (Bug #2270)

- Fixed spurious « table corrupted » errors in parallel repair operations. Voir Section 5.2.3, « Variables serveur système ».

- Fixed a crashing bug in parallel repair operations. Voir Section 5.2.3, « Variables serveur système ».

- Fixed bug in updating MyISAM tables for BLOB values longer than 16MB. (Bug #2159)

- Fixed bug in mysqld_safe when running multiple instances of MySQL. (Bug #2114)

- Fixed a bug in using HANDLER statement with tables not from a current database. (Bug #2304)

- Fixed a crashing bug that occurred due to the fact that multiple-table UPDATE statements did not check that there was only one table to be updated. (Bug #2103)

- Fixed a crashing bug that occurred due to BLOB column type index size being calculated incorrectly in MIN() and MAX() optimizations. (Bug #2189)

- Fixed a bug with incorrect syntax for LOCK TABLES in mysqldump. (Bug #2242)

- Fixed a bug in mysqld_safe that caused mysqld to generate a warning about duplicate user=xxx options if this option was specified in the [mysqld] or [server] sections of my.cnf. (Bug #2163)

- INSERT DELAYED ... SELECT ... could cause table corruption because tables were not locked properly. This is now fixed by ignoring DELAYED in this context. (Bug #1983)

- Replication: Sometimes the master gets a non-fatal error during the execution of a statement that does not immediately succeed. (For example, a write to a MyISAM table may first receive « no space left on device, » but later complete when disk space becomes available. Voir Section A.4.3, « Comment MySQL gère un disque plein ».) The bug was that the master forgot to reset the error code to 0 after success, so the error code got into its binary log, thus causing the slave to issue false alarms such as « did not get the same error as on master. » (Bug #2083)

- Removed a misleading « check permissions on master.info » from a replication error message, because the cause of the problem could be something other than permissions. (Bug #2121)

- Fixed a crash when the replication slave was unable to create the first relay log. (Bug #2145)

- Replication of LOAD DATA INFILE for an empty file from a 3.23 master to a 4.0 slave caused the slave to print an error. (Bug #2452)

- When automatically forcing lower_case_table_names to 1 if the file system was case insensitive, mysqld could crash. This bug existed only in MySQL 4.0.17. (Bug #2481)

- Restored ability to specify default values for TIMESTAMP columns that was erroneously disabled in previous release. (Bug #2539) Fixed SHOW CREATE TABLE to reflect these values. (Bug #1885) Note that because of the auto-update feature for the first TIMESTAMP column in a table, it makes no sense to specify a default value for the column. Any such default will be silently ignored (unless another TIMESTAMP column is added before this one). Also fixed the meaning of the DEFAULT keyword when it is used to specify the value to be inserted into a TIMESTAMP column other than the first. (Bug #2464)

- Fixed bug for out-of-range arguments on QNX platform that caused UNIX_TIMESTAMP() to produce incorrect results or that caused non-zero values to be inserted into TIMESTAMP columns. (Bug #2523) Also, current time zone now is taken into account when checking if datetime values satisfy both range boundaries for TIMESTAMP columns. The range allowed for a TIMESTAMP column is time zone-dependent and equivalent to a range of 1970-01-01 00:00:01 UTC to 2037-12-31 23:59:59 UTC.

- Multiple-table DELETE statements were never replicated by the slave if there were any replicate-*-table options. (Bug #2527)

- Changes to session counterparts of variables query_prealloc_size, query_alloc_block_size, trans_prealloc_size, trans_alloc_block_size now have an effect. (Bug #1948)

- Fixed bug in ALTER TABLE RENAME, when rename to the table with the same name in another database silently dropped destination table if it existed. (Bug #2628)

30-C-9 - Changements de la version 4.0.17 (14 décembre 2003)

Fonctionnalité ajoutée ou modifiée :

- mysqldump no longer dumps data for MERGE tables. (Bug #1846)

- lower_case_table_names is now forced to 1 if the database directory is located on a case-insensitive file system. (Bug #1812)

- Symlink creation is now disabled on systems where realpath() doesn't work. (Before one could use CREATE TABLE .. DATA DIRECTORY=.. even if HAVE_BROKEN_REALPATH was defined. This is now disabled to avoid problems when running ALTER TABLE).

- Inserting a negative AUTO_INCREMENT value in a MyISAM table no longer updates the AUTO_INCREMENT counter to a big unsigned value. (Bug #1366)

- Added four new modes to WEEK(..., mode) function. Voir WEEK(date: (mode)). (Bug #1178)

- Allow UNION DISTINCT syntax.

- mysql_server_init() now returns 1 if it can't initialize the environment. (Previously mysql_server_init() called exit(1) if it could not create a key with pthread_key_create(). (Bug #2062)

- Allow spaces in Windows service names.

- Changed the default Windows service name for mysqld from MySql to MySQL. This should not affect usage, because service names are not case sensitive.

- When you install mysqld as a service on Windows systems, mysqld will read startup options in option files from the option group with the same name as the service name. (Except when the service name is MySQL).

Bogues corrigés :

- One can now configure MySQL as a Windows service as a normal user. (Bug #1802). Thanks to Richard Hansen for fixing this.

- Database names are now compared in lowercase in ON clauses when lower_case_table_names is set. (Bug #1736)

- IGNORE ... LINES option to LOAD DATA INFILE didn't work when used with fixed length rows. (Bug #1704)

- Fixed problem with UNIX_TIMESTAMP() for timestamps close to 0. (Bug #1998)

- Fixed problem with character values greater than 128 in the QUOTE() function. (Bug #1868)

- Fixed searching of TEXT with end space. (Bug #1651)

- Fixed caching bug in multiple-table updates where same table was used twice. (Bug #1711)

- Fixed directory permissions for the MySQL-server RPM documentation directory. (Bug #1672)

- Fixed server crash when updating an ENUM column that is set to the empty string (for example, with REPLACE()). (Bug #2023)

- mysql client program now correctly prints connection identifier returned by mysql_thread_id() as unsigned integer rather than as signed integer. (Bug #1951)

- FOUND_ROWS() could return incorrect number of rows after a query with an impossible WHERE condition. (Bug #1468)

- SHOW DATABASES no longer shows .sym files (on Windows) that do not point to a valid directory. (Bug #1385)

- Fixed a possible memory leak on Mac OS X when using the shared libmysql.so library. (from pthread_key_create()). (Bug #2061)

- Fixed bug in UNION statement with alias *. (Bug #1249)

- Fixed a bug in DELETE ... ORDER BY ... LIMIT where the rows where not deleted in the proper order. (Bug #1024, Bug #1697).

- Fixed serious problem with multi-threaded programs on Windows that used the embedded MySQL libraries. (Locks of tables were not handled correctly between different threads).

- Code cleanup: Fixed a few code defects (potential memory leaks, null pointer dereferences, uninitialized variables). Thanks to Reasoning Inc. for informing us about these findings.

- Fixed a buffer overflow error that occurred with prepended '0' characters in some columns of type DECIMAL. (Bug #2128)

- Filesort was never shown in EXPLAIN if query contained an ORDER BY NULL clause. (Bug #1335)

- Fixed invalidation of whole query cache on DROP DATABASE. (Bug #1898)

- Fixed bug in range optimizer that caused wrong results for some unlikely AND/OR queries. (Bug #1828)

- Fixed a crash in ORDER BY when ordering by expression and identifier. (Bug #1945)

- Fixed a crash in an open HANDLER when an ALTER TABLE was executed in a different connection. (Bug #1826)

- Fixed a bug in trunc* operator of full-text search which sometimes caused MySQL not to find all matched rows.

- Fixed bug in prepending '0' characters to DECIMAL column values.

- Fixed optimizer bug, introduced in 4.0.16, when REF access plan was preferred to more efficient RANGE on another column.

- Fixed problem when installing a MySQL server as a Windows service using a command of the form mysqld --install mysql --defaults-file=path-to-file. (Bug #1643)

- Fixed an incorrect result from a query that uses only const tables (such as one-row tables) and non-constant expression (such as RAND()). (Bug #1271)

- Fixed bug when the optimizer did not take SQL_CALC_FOUND_ROWS into account if LIMIT clause was present. (Bug #1274)

- mysqlbinlog now asks for a password at the console when the -p or --password option is used with no argument. This is consistent with the way that other clients such mysqladmin and mysqldump already behave. Note: A consequence of this change is that it is no longer possible to invoke mysqlbinlog as mysqlbinlog -p pass_val (with a space between the -p option and the following password value). (Bug #1595)

- Fixed bug accidentally introduced in 4.0.16 where the slave SQL thread deleted its replicated temporary tables when STOP SLAVE was issued.

- In a « chain » replication setup A->B->C, if 2 sessions on A updated temporary tables of the same name at the same time, the binary log of B became incorrect, resulting in C becoming confused. (Bug #1686)

- In a « chain » replication setup A->B->C, if STOP SLAVE was issued on B while it was replicating a temporary table from A, then when START SLAVE was issued on B, the binary log of B became incorrect, resulting in C becoming confused. (Bug #1240)

- When MASTER_LOG_FILE and MASTER_LOG_POS were not specified, CHANGE MASTER used the coordinates of the slave I/O thread to set up replication, which broke replication if the slave SQL thread lagged behind the slave I/O thread. This caused the slave SQL thread to lose some events. The new behavior is to use the coordinates of the slave SQL thread instead. Voir Section 13.6.2.1, « CHANGE MASTER TO ». (Bug #1870)

- Now if integer is stored or converted to TIMESTAMP or DATETIME value checks of year, month, day, hour, minute and second ranges are performed and numbers representing illegal timestamps are converted to 0 value. This behavior is consistent with manual and with behavior of string to TIMESTAMP/DATETIME conversion. (Bug #1448)

- Fixed bug when BIT_AND() and BIT_OR() group functions returned incorrect value if SELECT used a temporary table and no rows were found. (Bug #1790).

- BIT_AND() is now unsigned in all contexts. This means that it will now return 18446744073709551615 (= 0xffffffffffffffff) instead of -1 if there were no rows in the result.

- Fixed bug with BIT_AND() still returning signed value for an empty set in some cases. (Bug #1972)

- Fixed bug with ^ (XOR) and >> (bit shift) still returning signed value in some cases. (Bug #1993)

- Replication: a rare race condition in the slave SQL thread, which could lead to a wrong complain that the relay log is corrupted. (Bug #2011)

- Replication: if an administrative command on a table (OPTIMIZE TABLE, REPAIR TABLE etc) was run on the slave, this could sometimes stop the slave SQL thread (this did not led to any corruption; one just had to type START SLAVE to get replication going again). (Bug #1858)

- Replication: in the slave SQL thread, a multi-table UPDATE could produce a wrong complain that some record was not found in one table, if the UPDATE was preceded by a INSERT ... SELECT. (Bug #1701)

- Fixed deficiency in MySQL code which is responsible for scanning directories. This deficiency caused SHOW TABLE STATUS to be very slow for big number of tables in database even if single particular table were specified. (Bug #1952)

30-C-10 - Changements de la version 4.0.16 (17 octobre 2003)

Fonctionnalité ajoutée ou modifiée :

- Option values in option files now may be quoted. This is useful for values that contain whitespace or comment characters.

- Write memory allocation information to error log when doing mysqladmin debug. This works only on systems that support the mallinfo() call (like newer Linux systems).

- Added the following new server variables to allow more precise memory allocation: range_alloc_block_size, query_alloc_block_size, query_prealloc_size, transaction_alloc_block_size, and transaction_prealloc_size.

- mysqlbinlog now reads option files. To make this work, you must now specify --read-from-remote-server when reading binary logs from a MySQL server. (Note that using a remote server is deprecated and may disappear in future mysqlbinlog versions).

- Block SIGPIPE signals also for non-threaded programs. The blocking is moved from mysql_init() to mysql_server_init(), which is automatically called on the first call to mysql_init().

- Added --libs_r and --include options to mysql_config.

- New `> prompt for mysql. This prompt is similar to the '> and "> prompts, but indicates that an identifier quoted with backticks was begun on an earlier line and the closing backtick has not yet been Voirn.

- Updated mysql_install_db to be able to use the local machine's IP address instead of the hostname when building the initial grant tables if skip-name-resolve has been specified. This option can be helpful on FreeBSD to avoid thread-safety problems with the FreeBSD resolver libraries. (Thanks to Jeremy Zawodny for the patch.)

- A documentation change: Added a note that when backing up a slave, it is necessary also to back up the master.info and relay-log.info files, as well as any SQL_LOAD-* files located in the directory specified by the --slave-load-tmpdir option. All these files are needed when the slave resumes replication after you restore the slave's data.

Bogues corrigés :

- Fixed a spurious error ERROR 14: Can't change size of file (Errcode: 2) on Windows in DELETE FROM tbl_name without a WHERE clause or TRUNCATE TABLE tbl_name, when tbl_name is a MyISAM table. (Bug #1397)

- Fixed a bug that resulted in thr_alarm queue is full warnings after increasing the max_connections variable with SET GLOBAL. (Bug #1435)

- Made LOCK TABLES to work when Lock_tables_priv is granted on the database level and Select_priv is granted on the table level.

- Fixed crash of FLUSH QUERY CACHE on queries that use same table several times (Bug #988).

- Fixed core dump bug when setting an enum system variable (such as SQL_WARNINGS) to NULL.

- Extended the default timeout value for Windows clients from 30 seconds to 1 year. (The timeout that was added in MySQL 4.0.15 was way too short). This fixes a bug that caused ERROR 2013: Lost connection to MySQL server during query for queries that lasted longer than 30 seconds, if the client didn't specify a limit with mysql_options(). Users of 4.0.15 on Windows should upgrade to avoid this problem.

- More « out of memory » checking in range optimizer.

- Fixed and documented a problem when setting and using a user variable within the same SELECT statement. (Bug #1194).

- Fixed bug in overrun check for BLOB values with compressed tables. This was a bug introduced in 4.0.14. It caused MySQL to regard some correct tables containing BLOB values as corrupted. (Bug #770, Bug #1304, and maybe Bug #1295)

- SHOW GRANTS showed USAGE instead of the real column-level privileges when no table-level privileges were given.

- When copying a database from the master, LOAD DATA FROM MASTER dropped the corresponding database on the slave, thus erroneously dropping tables that had no counterpart on the master and tables that may have been excluded from replication using replicate-*-table rules. Now LOAD DATA FROM MASTER no longer drops the database. Instead, it drops only the tables that have a counterpart on the master and that match the replicate-*-table rules. replicate-*-db rules can still be used to include or exclude a database as a whole from LOAD DATA FROM MASTER. A database will also be included or excluded as a whole if there are some rules like replicate-wild-do-table=db1.% or replicate-wild-ignore-table=db1.%, as is already the case for CREATE DATABASE and DROP DATABASE in replication. (Bug #1248)

- Fixed a bug where mysqlbinlog crashed with a segmentation fault when used with the -h or --host option. (Bug #1258)

- Fixed a bug where mysqlbinlog crashed with a segmentation fault when used on a binary log containing only final events for LOAD DATA. (Bug #1340)

- mysqlbinlog will not reuse temporary file names from previous runs. Previously mysqlbinlog failed if was used several times on the same binary log file that contained a LOAD DATA command.

- Fixed compilation problem when compiling with OpenSSL 0.9.7 with disabled old DES support (If OPENSSL_DISABLE_OLD_DES_SUPPORT option was enabled).

- Fixed a bug when two (or more) MySQL servers were running on the same machine, and they were both slaves, and at least one of them was replicating some LOAD DATA INFILE command from its master. The bug was that one slave MySQL server sometimes deleted the SQL_LOAD-* files (used for replication of LOAD DATA INFILE and located in the slave-load-tmpdir directory, which defaults to tmpdir) belonging to the other slave MySQL server of this machine, if these slaves had the same slave-load-tmpdir directory. When that happened, the other slave could not replicate LOAD DATA INFILE and complained about not being able to open some SQL_LOAD-* file. (Bug #1357)

- If LOAD DATA INFILE failed for a small file, the master forgot to write a marker (a Delete_file event) in its binary log, so the slave could not delete 2 files (SQL_LOAD-*.info and SQL_LOAD-*.data from its tmpdir. (Bug #1391)

- On Windows, the slave forgot to delete a SQL_LOAD-*.info file from tmpdir after successfully replicating a LOAD DATA INFILE command. (Bug #1392)

- When a connection terminates, MySQL writes DROP TEMPORARY TABLE statements to the binary log for all temporary tables which the connection had not explicitly dropped. MySQL forgot to use backticks to quote the database and table names in the statement. (Bug #1345)

- On some 64-bit machines (some HP-UX and Solaris machines), a slave installed with the 64-bit MySQL binary could not connect to its master (it connected to itself instead). (Bug #1256, Bug #1381)

- Code was introduced in MySQL 4.0.15 for the slave to detect that the master had died while writing a transaction to its binary log. This code reported an error in a legal situation: When the slave I/O thread was stopped while copying a transaction to the relay log, the slave SQL thread would later pretend that it found an unfinished transaction. (Bug #1475)

30-C-11 - Changements de la version 4.0.15 (03 septembre 2003)

IMPORTANT:

If you are using this release on Windows, you should upgrade at least your clients (any program that uses libmysql.lib) to 4.0.16 or above. This is because the 4.0.15 release had a bug in the Windows client library that causes Windows clients using the library to die with a Lost connection to MySQL server during query error for queries that take more than 30 seconds. This problem is specific to Windows; clients on other platforms are unaffected.

Fonctionnalité ajoutée ou modifiée :

- mysqldump now correctly quotes all identifiers when communicating with the server. This assures that during the dump process, mysqldump will never send queries to the server that result in a syntax error. This problem is not related to the mysqldump program's output, which was not changed. (Bug #1148)

- Change result set metadata information so that MIN() and MAX() report that they can return NULL (this is true because an empty set will return NULL). (Bug #324)

- Produce an error message on Windows if a second mysqld server is started on the same TCP/IP port as an already running mysqld server.

- The mysqld server variables wait_timeout, net_read_timeout, and net_write_timeout now work on Windows. One can now also set timeouts for read and writes in Windows clients with mysql_options().

- Added option --sql-mode=NO_DIR_IN_CREATE to make it possible for slaves to ignore INDEX DIRECTORY and DATA DIRECTORY options given to CREATE TABLE. When this is mode is on, SHOW CREATE TABLE will not show the given directories.

- SHOW CREATE TABLE now shows the INDEX DIRECTORY and DATA DIRECTORY options, if they were specified when the table was created.

- The open_files_limit server variable now shows the real open files limit.

- MATCH ... AGAINST() in natural language mode now treats words that are present in more than 2,000,000 rows as stopwords.

- The Mac OS X installation disk images now include an additional MySQLStartupItem.pkg package that enables the automatic startup of MySQL on system bootup. Voir Section 2.2.13, « Installer MySQL sur Mac OS X ».

- Most of the documentation included in the binary tarball distributions (.tar.gz) has been moved into a subdirectory docs. Voir Section 2.1.5, « Dispositions d'installation ».

- The manual is now included as an additional info file in the binary distributions. (Bug #1019)

- The binary distributions now include the embedded server library (libmysqld.a) by default. Due to a linking problem with non-gcc compilers, it was not included in all packages of the initial 4.0.15 release. The affected packages were rebuilt and released as 4.0.15a. Voir Section 1.3.1.2, « MySQL Server intégré (embedded) ».

- MySQL can now use range optimization for BETWEEN with non-constant limits. (Bug #991)

- Replication error messages now include the default database, so that users can check which database the failing query was run for.

- A documentation change: Added a paragraph about how the binlog-do-db and binlog-ignore-db options are tested against the database on the master (Voir Section 5.9.4, « Le log binaire »), and a paragraph about how replicate-do-db, replicate-do-table and analogous options are tested against the database and tables on the slave (Voir Section 6.8, « Options de démarrage de la réplication »).

- Now the slave does not replicate SET PASSWORD if it is configured to exclude the mysql database from replication (using for example replicate-wild-ignore-table=mysql.%). This was already the case for GRANT and REVOKE since version 4.0.13 (though there was Bug #980 in 4.0.13 & 4.0.14, which has been fixed in 4.0.15).

- Rewrote the information shown in the State column of SHOW PROCESSLIST for replication threads and for MASTER_POS_WAIT() and added the most common states for these threads to the documentation, Voir Section 6.3, « Détails d'implémentation de la réplication ».

- Added a test in replication to detect the case where the master died in the middle of writing a transaction to the binlog; such unfinished transactions now trigger an error message on the slave.

- A GRANT command that creates an anonymous user (that is, an account with an empty username) no longer requires FLUSH PRIVILEGES for the account to be recognized by the server. (Bug #473)

- CHANGE MASTER now flushes relay-log.info. Previously this was deferred to the next run of START SLAVE, so if mysqld was shutdown on the slave after CHANGE MASTER without having run START SLAVE, the relay log's name and position were lost. At restart they were reloaded from relay-log.info, thus reverting to their old (incorrect) values from before CHANGE MASTER and leading to error messages (as the old relay log did not exist any more) and the slave threads refusing to start. (Bug #858)

Bogues corrigés :

- Fixed buffer overflow in password handling which could potentially be exploited by MySQL users with ALTER privilege on the mysql.user table to execute random code or to gain shell access with the UID of the mysqld process (thanks to Jedi/Sector One for spotting and reporting this bug).

- Fixed server crash on FORCE INDEX in a query that contained "Range checked for each record" in the EXPLAIN output. (Bug #1172)

- Fixed table/column grant handling - proper sort order (from most specific to less specific, Voir Section 5.5.6, « Contrôle d'accès, étape 2 : Vérification de la requête ») was not honored. (Bug #928)

- Fixed rare bug in MYISAM introduced in 4.0.3 where the index file header was not updated directly after an UPDATE of split dynamic rows. The symptom was that the table had a corrupted delete-link if mysqld was shut down or the table was checked directly after the update.

- Fixed Can't unlock file error when running myisamchk --sort-index on Windows. (Bug #1119)

- Fixed possible deadlock when changing key_buffer_size while the key cache was actively used. (Bug #1088)

- Fixed overflow bug in MyISAM and ISAM when a row is updated in a table with a large number of columns and at least one BLOB/TEXT column.

- Fixed incorrect result when doing UNION and LIMIT #,# when one didn't use braces around the SELECT parts.

- Fixed incorrect result when doing UNION and ORDER BY .. LIMIT # when one didn't use braces around the SELECT parts.

- Fixed problem with SELECT SQL_CALC_FOUND_ROWS ... UNION ALL ... LIMIT # where FOUND_ROWS() returned incorrect number of rows.

- Fixed unlikely stack bug when having a BIG expression of type 1+1-1+1-1... in certain combinations. (Bug #871)

- Fixed the bug that sometimes prevented a table with a FULLTEXT index from being marked as "analyzed".

- Fixed MySQL so that the column length (in C API) for the second column in SHOW CREATE TABLE is always larger than the data length. The only known application that was affected by the old behavior was Borland dbExpress, which truncated the output from the command. (Bug #1064)

- Fixed crash in comparisons of strings using the tis620 character set. (Bug #1116)

- Fixed ISAM bug in MAX() optimization.

- myisamchk --sort-records=N no longer marks table as crashed if sorting failed because of an inappropriate key. (Bug #892)

- Fixed a minor bug in MyISAM compressed table handling that sometimes made it impossible to repair compressed table in "Repair by sort" mode. "Repair with keycache" (myisamchk --safe-recover) worked, though. (Bug #1015)

- Fixed bug in propagating the version number to the manual included in the distribution files. (Bug #1020)

- Fixed key sorting problem (a PRIMARY key declared for a column that is not explicitly marked NOT NULL was sorted after a UNIQUE key for a NOT NULL column).

- Fixed the result of INTERVAL when applied to a DATE value. (Bug #792)

- Fixed compiling of the embedded server library in the RPM spec file. (Bug #959)

- Added some missing files to the RPM spec file and fixed some RPM building errors that occurred on Red Hat Linux 9. (Bug #998)

- Fixed incorrect XOR evaluation in WHERE clause. (Bug #992)

- Fixed bug with processing in query cache merged tables constructed from more then 255 tables. (Bug #930)

- Fixed incorrect results from outer join query (e.g. LEFT JOIN) when ON condition is always false, and range search in used. (Bug #926)

- Fixed a bug causing incorrect results from MATCH ... AGAINST() in some joins. (Bug #942)

- MERGE tables do not ignore "Using index" (from EXPLAIN output) anymore.

- Fixed a bug that prevented an empty table from being marked as "analyzed". (Bug #937)

- Fixed myisamchk --sort-records crash when used on compressed table.

- Fixed slow (as compared to 3.23) ALTER TABLE and related commands such as CREATE INDEX. (Bug #712)

- Fixed segmentation fault resulting from LOAD DATA FROM MASTER when the master was running without the --log-bin option. (Bug #934)

- Fixed a security bug: A server compiled without SSL support still allowed connections by users that had the REQUIRE SSL option specified for their accounts.

- Fixed a random bug: Sometimes the slave would replicate GRANT or REVOKE queries even if it was configured to exclude the mysql database from replication (for example, using replicate-wild-ignore-table=mysql.%). (Bug #980)

- The Last_Errno and Last_Error fields in the output of SHOW SLAVE STATUS are now cleared by CHANGE MASTER and when the slave SQL thread starts. (Bug #986)

- A documentation mistake: It said that RESET SLAVE does not change connection information (master host, port, user, and password), whereas it does. The statement resets these to the startup options (master-host etc) if there were some. (Bug #985)

- SHOW SLAVE STATUS now shows correct information (master host, port, user, and password) after RESET SLAVE (that is, it shows the new values, which are copied from the startup options if there were some). (Bug #985)

- Disabled propagation of the original master's log position for events because this caused unexpected values for Exec_Master_Log_Pos and problems with MASTER_POS_WAIT() in A->B->C replication setup. (Bug #1086)

- Fixed a segfault in mysqlbinlog when --position=x was used with x being between a Create_file event and its fellow Append_block, Exec_load or Delete_file events. (Bug #1091)

- mysqlbinlog printed superfluous warnings when using --database, which caused syntax errors when piped to mysql. (Bug #1092)

- Made mysqlbinlog --database filter LOAD DATA INFILE too (previously, it filtered all queries except LOAD DATA INFILE). (Bug #1093)

- mysqlbinlog in some cases forgot to put a leading '#' in front of the original LOAD DATA INFILE (this command is displayed only for information, not to be run; it is later reworked to LOAD DATA LOCAL with a different filename, for execution by mysql). (Bug #1096)

- binlog-do-db and binlog-ignore-db incorrectly filtered LOAD DATA INFILE (it was half-written to the binary log). This resulted in a corrupted binary log, which could cause the slave to stop with an error. (Bug #1100)

- When, in a transaction, a transactional table (such as an InnoDB table) was updated, and later in the same transaction a non-transactional table (such as a MyISAM table) was updated using the updated content of the transactional table (with INSERT ... SELECT for example), the queries were written to the binary log in an incorrect order. (Bug #873)

- When, in a transaction, INSERT ... SELECT updated a non-transactional table, and ROLLBACK was issued, no error was returned to the client. Now the client is warned that some changes could not be rolled back, as this was already the case for normal INSERT. (Bug #1113)

- Fixed a potential bug: When STOP SLAVE was run while the slave SQL thread was in the middle of a transaction, and then CHANGE MASTER was used to point the slave to some non-transactional statement, the slave SQL thread could get confused (because it would still think, from the past, that it was in a transaction).

30-C-12 - Changements de la version 4.0.14 (18 juillet 2003)

Fonctionnalité ajoutée ou modifiée :

- Added default_week_format system variable. The value is used as the default mode for the WEEK() function.

- mysqld now reads an additional option file group having a name corresponding to the server's release series: [mysqld-4.0] for 4.0.x servers, [mysqld-4.1] for 4.1.x servers, and so forth. This allows options to be specified on a series-specific basis.

- The CONCAT_WS() function no longer skips empty strings. (Bug #586).

- InnoDB now supports indexing a prefix of a column. This means, in particular, that BLOB and TEXT columns can be indexed in InnoDB tables, which was not possible before.

- A documentation change: Function INTERVAL(NULL, ...) returns -1.

- Enabled INSERT from SELECT when the table into which the records are inserted is also a table listed in the SELECT.

- Allow CREATE TABLE and INSERT from any UNION.

- The SQL_CALC_FOUND_ROWS option now always returns the total number of rows for any UNION.

- Removed --table option from mysqlbinlog to avoid repeating mysqldump functionality.

- Comment lines in option files can now start from the middle of a line, too (like basedir=c:\mysql # installation directory).

- Changed optimizer slightly to prefer index lookups over full table scans in some boundary cases.

- Added thread-specific max_Voirks_for_key variable that can be used to force the optimizer to use keys instead of table scans even if the cardinality of the index is low.

- Added optimization that converts LEFT JOIN to normal join in some cases.

- A documentation change: added a paragraph about failover in replication (how to use a surviving slave as the new master, how to resume to the original setup). Voir Section 6.9, « FAQ de la réplication ».

- A documentation change: added warning notes about safe use of the CHANGE MASTER command. Voir Section 13.6.2.1, « CHANGE MASTER TO ».

- MySQL now issues a warning (not an error, as in 4.0.13) when it opens a table that was created with MySQL 4.1.

- Added --nice option to mysqld_safe to allow setting the niceness of the mysqld process. (Thanks to Christian Hammers for providing the initial patch.) (Bug #627)

- Added --read-only option to cause mysqld to allow no updates except from slave threads or from users with the SUPER privilege. (Original patch from Markus Benning).

- SHOW BINLOG EVENTS FROM x where x is less than 4 now silently converts x to 4 instead of printing an error. The same change was done for CHANGE MASTER TO MASTER_LOG_POS=x and CHANGE MASTER TO RELAY_LOG_POS=x.

- mysqld now only adds an interrupt handler for the SIGINT signal if you start it with the new --gdb option. This is because some MySQL users encountered strange problems when they accidentally sent SIGINT to mysqld threads.

- RESET SLAVE now clears the Last_Errno and Last_Error fields in the output of SHOW SLAVE STATUS.

- Added max_relay_log_size variable; the relay log will be rotated automatically when its size exceeds max_relay_log_size. But if max_relay_log_size is 0 (the default), max_binlog_size will be used (as in older versions). max_binlog_size still applies to binary logs in any case.

- FLUSH LOGS now rotates relay logs in addition to the other types of logs it already rotated.

Bogues corrigés :

- Comparison/sorting for latin1_de character set was rewritten. The old algorithm could not handle cases like "sä" > "ßa". Voir Section 5.8.1.1, « Jeu de caractères allemand ». In rare cases it resulted in table corruption.

- Fixed a problem with the password prompt on Windows. (Bug #683)

- ALTER TABLE ... UNION=(...) for MERGE table is now allowed even if some underlying MyISAM tables are read-only. (Bug #702)

- Fixed a problem with CREATE TABLE t1 SELECT x'41'. (Bug #801)

- Removed some incorrect lock warnings from the error log.

- Fixed memory overrun when doing REPAIR TABLE on a table with a multiple-part auto_increment key where one part was a packed CHAR.

- Fixed a probable race condition in the replication code that could potentially lead to INSERT statements not being replicated in the event of a FLUSH LOGS command or when the binary log exceeds max_binlog_size. (Bug #791)

- Fixed a crashing bug in INTERVAL and GROUP BY or DISTINCT. (Bug #807)

- Fixed bug in mysqlhotcopy so it actually aborts for unsuccessful table copying operations. Fixed another bug so that it succeeds when there are thousands of tables to copy. (Bug #812)

- Fixed problem with mysqlhotcopy failing to read options from option files. (Bug #808)

- Fixed bugs in optimizer that sometimes prevented MySQL from using FULLTEXT indexes even though it was possible (for example, in SELECT * FROM t1 WHERE MATCH a,b AGAINST("index") > 0).

- Fixed a bug with « table is full » in UNION operations.

- Fixed a security problem that enabled users with no privileges to obtain information on the list of existing databases by using SHOW TABLES and similar commands.

- Fixed a stack problem on UnixWare/OpenUnix.

- Fixed a configuration problem on UnixWare/OpenUNIX and OpenServer.

- Fixed a stack overflow problem in password verification.

- Fixed a problem with max_user_connections.

- HANDLER without an index now works properly when a table has deleted rows. (Bug #787)

- Fixed a bug with LOAD DATA in mysqlbinlog. (Bug #670)

- Fixed that SET CHARACTER SET DEFAULT works. (Bug #462)

- Fixed MERGE table behavior in ORDER BY ... DESC queries. (Bug #515)

- Fixed server crash on PURGE MASTER LOGS or SHOW MASTER LOGS when the binary log is off. (Bug #733)

- Fixed password-checking problem on Windows. (Bug #464)

- Fixed the bug in comparison of a DATETIME column and an integer constant. (Bug #504)

- Fixed remote mode of mysqlbinlog. (Bug #672)

- Fixed ERROR 1105: Unknown error that occurred for some SELECT queries, where a column that was declared as NOT NULL was compared with an expression that took NULL value.

- Changed timeout in mysql_real_connect() to use poll() instead of select() to work around problem with many open files in the client.

- Fixed incorrect results from MATCH ... AGAINST used with a LEFT JOIN query.

- Fixed a bug that limited the maximum value for mysqld variables to 4294967295 when they are specified on the command line.

- Fixed a bug that sometimes caused spurious « Access denied » errors in HANDLER ... READ statements, when a table is referenced via an alias.

- Fixed portability problem with safe_malloc, which caused MySQL to give "Freeing wrong aligned pointer" errors on SCO 3.2.

- ALTER TABLE ... ENABLE/DISABLE KEYS could cause a core dump when done after an INSERT DELAYED statement on the same table.

- Fixed problem with conversion of localtime to GMT where some times resulted in different (but correct) timestamps. Now MySQL should use the smallest possible timestamp value in this case. (Bug #316)

- Very small query cache sizes could crash mysqld. (Bug #549)

- Fixed a bug (accidentally introduced by us but present only in version 4.0.13) that made INSERT ... SELECT into an AUTO_INCREMENT column not replicate well. This bug is in the master, not in the slave. (Bug #490)

- Fixed a bug : When an INSERT ... SELECT statement inserted rows into a non-transactional table, but failed at some point (for example, due to a « Duplicate key » error), the query was not written to the binary log. Now it is written to the binary log, with its error code, as all other queries are. About the slave-skip-errors option for how to handle partially completed queries in the slave, Voir Section 6.8, « Options de démarrage de la réplication ». (Bug #491)

- SET FOREIGN_KEY_CHECKS=0 was not replicated properly. The fix probably will not be backported to 3.23.

- On a slave, LOAD DATA INFILE which had no IGNORE or REPLACE clause on the master, was replicated with IGNORE. While this is not a problem if the master and slave data are identical (a LOAD that produces no duplicate conflicts on the master will produce none on the slave anyway), which is true in normal operation, it is better for debugging not to silently add the IGNORE. That way, you can get an error message on the slave and discover that for some reason, the data on master and slave are different and investigate why. (Bug #571)

- On a slave, LOAD DATA INFILE printed an incomplete « Duplicate entry '%-.64s' for key %d »' message (the key name and value were not mentioned) in case of duplicate conflict (which does not happen in normal operation). (Bug #573)

- When using a slave compiled with --debug, CHANGE MASTER TO RELAY_LOG_POS could cause a debug assertion failure. (Bug #576)

- When doing a LOCK TABLES WRITE on an InnoDB table, commit could not happen, if the query was not written to the binary log (for example, if --log-bin was not used, or binlog-ignore-db was used). (Bug #578)

- If a 3.23 master had open temporary tables that had been replicated to a 4.0 slave, and the binary log got rotated, these temporary tables were immediately dropped by the slave (which caused problems if the master used them subsequently). This bug had been fixed in 4.0.13, but in a manner which caused an unlikely inconvenience: If the 3.23 master died brutally (power failure), without having enough time to automatically write DROP TABLE statements to its binary log, then the 4.0.13 slave would not notice the temporary tables have to be dropped, until the slave mysqld server is restarted. This minor inconvenience is fixed in 3.23.57 and 4.0.14 (meaning the master must be upgraded to 3.23.57 and the slave to 4.0.14 to remove the inconvenience). (Bug #254)

- If MASTER_POS_WAIT() was waiting, and the slave was idle, and the slave SQL thread terminated, MASTER_POS_WAIT() would wait forever. Now when the slave SQL thread terminates, MASTER_POS_WAIT() immediately returns NULL (« slave stopped »). (Bug #651)

- After RESET SLAVE; START SLAVE;, the Relay_Log_Space value displayed by SHOW SLAVE STATUS was too big by four bytes. (Bug #763)

- If a query was ignored on the slave (because of replicate-ignore-table and other similar rules), the slave still checked if the query got the same error code (0, no error) as on the master. So if the master had an error on the query (for example, « Duplicate entry » in a multiple-row insert), then the slave stopped and warned that the error codes didn't match. (Bug #797)

30-C-13 - Changements de la version 4.0.13 (16 Mai 2003)

Fonctionnalité ajoutée ou modifiée :

- PRIMARY KEY now implies NOT NULL. (Bug #390)

- The Windows binary packages are now compiled with --enable-local-infile to match the Unix build configuration.

- Removed timing of tests from mysql-test-run. time does not accept all required parameters on many platforms (for example, QNX) and timing the tests is not really required (it's not a benchmark anyway).

- SHOW MASTER STATUS and SHOW SLAVE STATUS required the SUPER privilege; now they accept REPLICATION CLIENT as well. (Bug #343)

- Added multi-threaded MyISAM repair optimization and myisam_repair_threads variable to enable it. Voir Section 5.2.3, « Variables serveur système ».

- Added innodb_max_dirty_pages_pct variable which controls amount of dirty pages allowed in InnoDB buffer pool.

- CURRENT_USER() and Access denied error messages now report the hostname exactly as it was specified in the GRANT command.

- Removed benchmark results from the source and binary distributions. They are still available in the BK source tree, though.

- InnoDB tables now support ANALYZE TABLE.

- MySQL now issues an error when it opens a table that was created with MySQL 4.1.

- Option --new now changes binary items (0xFFDF) to be treated as binary strings instead of numbers by default. This fixes some problems with character sets where it's convenient to input the string as a binary item. After this change you have to convert the binary string to INTEGER with a CAST if you want to compare two binary items with each other and know which one is bigger than the other. SELECT CAST(0xfeff AS UNSIGNED) < CAST(0xff AS UNSIGNED). This will be the default behavior in MySQL 4.1. (Bug #152)

- Enabled delayed_insert_timeout on Linux (most modern glibc libraries have a fixed pthread_cond_timedwait()). (Bug #211)

- Don't create more insert delayed threads than given by max_delayed_threads. (Bug #211)

- Changed UPDATE ... LIMIT to apply the limit to rows that were matched, whether or not they actually were changed. Previously the limit was applied as a restriction on the number of rows changed.

- Tuned optimizer to favor clustered index over table scan.

- BIT_AND() and BIT_OR() now return an unsigned 64-bit value.

- Added warnings to error log of why a secure connection failed (when running with --log-warnings).

- Deprecated options --skip-symlink and --use-symbolic-links and replaced these with --symbolic-links.

- The default option for innodb_flush_log_at_trx_commit was changed from 0 to 1 to make InnoDB tables ACID by default. Voir Section 15.5, « Options de démarrage InnoDB ».

- Added a feature to SHOW KEYS to display keys that are disabled by ALTER TABLE DISABLE KEYS command.

- When using a non-existing table type with CREATE TABLE, first try if the default table type exists before falling back to MyISAM.

- Added MEMORY as an alias for HEAP.

- Renamed function rnd to my_rnd as the name was too generic and is an exported symbol in libmysqlclient (thanks to Dennis Haney for the initial patch).

- Portability fix: renamed include/dbug.h to include/my_dbug.h.

- mysqldump no longer silently deletes the binary logs when invoked with the --master-data or --first-slave option; while this behavior was convenient for some users, others may suffer from it. Now you must explicitly ask for binary logs to be deleted by using the new --delete-master-logs option.

- If the slave is configured (using for example replicate-wild-ignore-table=mysql.%) to exclude mysql.user, mysql.host, mysql.db, mysql.tables_priv and mysql.columns_priv from replication, then GRANT and REVOKE will not be replicated.

Bogues corrigés :

- Logged Access denied error message had incorrect Using password value. (Bug #398)

- Fixed bug with NATURAL LEFT JOIN, NATURAL RIGHT JOIN and RIGHT JOIN when using many joined tables. The problem was that the JOIN method was not always associated with the tables surrounding the JOIN method. If you have a query that uses many RIGHT JOIN or NATURAL ... JOINS you should verify that they work as you expected after upgrading MySQL to this version. (Bug #291)

- Fixed mysql parser not to erroneously interpret ''' or '"' characters within /* ... */ comment as beginning a quoted string.

- mysql command line client no longer looks for \* commands inside backtick-quoted strings.

- Fixed Unknown error when using UPDATE ... LIMIT. (Bug #373)

- Fixed problem with ANSI mode and GROUP BY with constants. (Bug #387)

- Fixed bug with UNION and OUTER JOIN. (Bug #386)

- Fixed bug if one used a multiple-table UPDATE and the query required a temporary table bigger than tmp_table_size. (Bug #286)

- Run mysql_install_db with the -IN-RPM option for the Mac OS X installation to not fail on systems with improperly configured hostname configurations.

- LOAD DATA INFILE will now read 000000 as a zero date instead as "2000-00-00".

- Fixed bug that caused DELETE FROM table WHERE const_expression always to delete the whole table (even if expression result was false). (Bug #355)

- Fixed core dump bug when using FORMAT('nan',#). (Bug #284)

- Fixed name resolution bug with HAVING ... COUNT(DISTINCT ...).

- Fixed incorrect result from truncation operator (*) in MATCH ... AGAINST() in some complex joins.

- Fixed a crash in REPAIR ... USE_FRM command, when used on read-only, nonexisting table or a table with a crashed index file.

- Fixed a crashing bug in mysql monitor program. It occurred if program was started with --no-defaults, with a prompt that contained the hostname and a connection to a non-existent database was requested.

- Fixed problem when comparing a key for a multi-byte character set. (Bug #152)

- Fixed bug in LEFT, RIGHT and MID when used with multi-byte character sets and some GROUP BY queries. (Bug #314)

- Fix problem with ORDER BY being discarded for some DISTINCT queries. (Bug #275)

- Fixed that SET SQL_BIG_SELECTS=1 works as documented (This corrects a new bug introduced in 4.0)

- Fixed some serious bugs in UPDATE ... ORDER BY. (Bug #241)

- Fixed unlikely problem in optimizing WHERE clause with constant expression like in WHERE 1 AND (a=1 AND b=1).

- Fixed that SET SQL_BIG_SELECTS=1 works again.

- Introduced proper backtick quoting for db.table in SHOW GRANTS.

- FULLTEXT index stopped working after ALTER TABLE that converts TEXT column to CHAR. (Bug #283)

- Fixed a security problem with SELECT and wildcarded select list, when user only had partial column SELECT privileges on the table.

- Mark a MyISAM table as "analyzed" only when all the keys are indeed analyzed.

- Only ignore world-writable my.cnf files that are regular files (and not, for example, named pipes or character devices).

- Fixed few smaller issues with SET PASSWORD.

- Fixed error message which contained deprecated text.

- Fixed a bug with two NATURAL JOINs in the query.

- SUM() didn't return NULL when there was no rows in result or when all values was NULL.

- On Unix symbolic links handling was not enabled by default and there was no way to turn this on.

- Added missing dashes to parameter --open-files-limit in mysqld_safe. (Bug #264)

- Fixed incorrect hostname for TCP/IP connections displayed in SHOW PROCESSLIST.

- Fixed a bug with NAN in FORMAT(...) function ...

- Fixed a bug with improperly cached database privileges.

- Fixed a bug in ALTER TABLE ENABLE / DISABLE KEYS which failed to force a refresh of table data in the cache.

- Fixed bugs in replication of LOAD DATA INFILE for custom parameters (ENCLOSED, TERMINATED and so on) and temporary tables. (Bug #183, Bug #222)

- Fixed a replication bug when the master is 3.23 and the slave 4.0: the slave lost the replicated temporary tables if FLUSH LOGS was issued on the master. (Bug #254)

- Fixed a bug when doing LOAD DATA INFILE IGNORE: When reading the binary log, mysqlbinlog and the replication code read REPLACE instead of IGNORE. This could make the slave's table become different from the master's table. (Bug #218)

- Fixed a deadlock when relay_log_space_limit was set to a too small value. (Bug #79)

- Fixed a bug in HAVING clause when an alias is used from the select list.

- Fixed overflow bug in MyISAM when a row is inserted into a table with a large number of columns and at least one BLOB/TEXT column. Bug was caused by incorrect calculation of the needed buffer to pack data.

- Fixed a bug when SELECT @nonexistent_variable caused the error in client - server protocol due to net_printf() being sent to the client twice.

- Fixed a bug in setting SQL_BIG_SELECTS option.

- Fixed a bug in SHOW PROCESSLIST which only displayed a localhost in the "Host" column. This was caused by a glitch that used only current thread information instead of information from the linked list of threads.

- Removed unnecessary Mac OS X helper files from server RPM. (Bug #144)

- Allow optimization of multiple-table update for InnoDB tables as well.

- Fixed a bug in multiple-table updates that caused some rows to be updated several times.

- Fixed a bug in mysqldump when it was called with --master-data: the CHANGE MASTER TO commands appended to the SQL dump had incorrect coordinates. (Bug #159)

- Fixed a bug when an updating query using USER() was replicated on the slave; this caused segfault on the slave. (Bug #178). USER() is still badly replicated on the slave (it is replicated to "").

30-C-14 - Changements de la version 4.0.12 (15 Mars 2003 : Production)

Fonctionnalité ajoutée ou modifiée :

- mysqld no longer reads options from world-writeable config files.

- Integer values between 9223372036854775807 and 9999999999999999999 are now regarded as unsigned longlongs, not as floats. This makes these values work similar to values between 10000000000000000000 and 18446744073709551615.

- SHOW PROCESSLIST will now include the client TCP port after the hostname to make it easier to know from which client the request originated.

Bogues corrigés :

- Fixed mysqld crash on extremely small values of sort_buffer variable.

- INSERT INTO u SELECT ... FROM t was written too late to the binary log if t was very frequently updated during the execution of this query. This could cause a problem with mysqlbinlog or replication. The master must be upgraded, not the slave. (Bug #136)

- Fixed checking of random part of WHERE clause. (Bug #142)

- Fixed a bug with multiple-table updates with InnoDB tables. This bug occurred as, in many cases, InnoDB tables cannot be updated « on the fly, » but offsets to the records have to be stored in a temporary table.

- Added missing file mysql_secure_installation to the server RPM subpackage. (Bug #141)

- Fixed MySQL (and myisamchk) crash on artificially corrupted .MYI files.

- Don't allow BACKUP TABLE to overwrite existing files.

- Fixed a bug with multiple-table UPDATE statements when user had all privileges on the database where tables are located and there were any entries in tables_priv table, that is, grant_option was true.

- Fixed a bug that allowed a user with table or column grants on some table, TRUNCATE any table in the same database.

- Fixed deadlock when doing LOCK TABLE followed by DROP TABLE in the same thread. In this case one could still kill the thread with KILL.

- LOAD DATA LOCAL INFILE was not properly written to the binary log (hence not properly replicated). (Bug #82)

- RAND() entries were not read correctly by mysqlbinlog from the binary log which caused problems when restoring a table that was inserted with RAND(). INSERT INTO t1 VALUES(RAND()). In replication this worked ok.

- SET SQL_LOG_BIN=0 was ignored for INSERT DELAYED queries. (Bug #104)

- SHOW SLAVE STATUS reported too old positions (columns Relay_Master_Log_File and Exec_Master_Log_Pos) for the last executed statement from the master, if this statement was the COMMIT of a transaction. The master must be upgraded for that, not the slave. (Bug #52)

- LOAD DATA INFILE was not replicated by the slave if replicate_*_table was set on the slave. (Bug #86)

- After RESET SLAVE, the coordinates displayed by SHOW SLAVE STATUS looked un-reset (though they were, but only internally). (Bug #70)

- Fixed query cache invalidation on LOAD DATA.

- Fixed memory leak on ANALYZE procedure with error.

- Fixed a bug in handling CHAR(0) columns that could cause incorrect results from the query.

- Fixed rare bug with incorrect initialization of AUTO_INCREMENT column, as a secondary column in a multi-column key (Voir Section 3.6.9, « Utiliser AUTO_INCREMENT »), when data was inserted with INSERT ... SELECT or LOAD DATA into an empty table.

- On Windows, STOP SLAVE didn't stop the slave until the slave got one new command from the master (this bug has been fixed for MySQL 4.0.11 by releasing updated 4.0.11a Windows packages, which include this individual fix on top of the 4.0.11 sources). (Bug #69)

- Fixed a crash when no database was selected and LOAD DATA command was issued with full table name specified, including database prefix.

- Fixed a crash when shutting down replication on some platforms (for example, Mac OS X).

- Fixed a portability bug with pthread_attr_getstacksize on HP-UX 10.20 (Patch was also included in 4.0.11a sources).

- Fixed the bigint test to not fail on some platforms (for example, HP-UX and Tru64) due to different return values of the atof() function.

- Fixed the rpl_rotate_logs test to not fail on certain platforms (e.g. Mac OS X) due to a too long file name (changed slave-master-info.opt to .slave-mi).

30-C-15 - Changements de la version 4.0.11 (20 Février 2003)

Fonctionnalité ajoutée ou modifiée :

- NULL is now sorted LAST if you use ORDER BY ... DESC (as it was before MySQL 4.0.2). This change was required to comply with the SQL-99 standard. (The original change was made because we thought that SQL-99 required NULL to be always sorted at the same position, but this was incorrect).

- Added START TRANSACTION (SQL-99 syntax) as alias for BEGIN. This is recommended to use instead of BEGIN to start a transaction.

- Added OLD_PASSWORD() as a synonym for PASSWORD().

- Allow keyword ALL in group functions.

- Added support for some new INNER JOIN and JOIN syntaxes. For example, SELECT * FROM t1 INNER JOIN t2 didn't work before.

- Novell NetWare 6.0 porting effort completed, Novell patches merged into the main source tree.

Bogues corrigés :

- Fixed problem with multiple-table delete and InnoDB tables.

- Fixed a problem with BLOB NOT NULL columns used with IS NULL.

- Re-added missing pre- and post(un)install scripts to the Linux RPM packages (they were missing after the renaming of the server subpackage).

- Fixed that table locks are not released with multiple-table updates and deletes with InnoDB storage engine.

- Fixed bug in updating BLOB columns with long strings.

- Fixed integer-wraparound when giving big integer (>= 10 digits) to function that requires an unsigned argument, like CREATE TABLE (...) AUTO_INCREMENT=#.

- MIN(key_column) could in some cases return NULL on a column with NULL and other values.

- MIN(key_column) and MAX(key_column) could in some cases return incorrect values when used in OUTER JOIN.

- MIN(key_column) and MAX(key_column) could return incorrect values if one of the tables was empty.

- Fixed rare crash in compressed MyISAM tables with blobs.

- Fixed bug in using aggregate functions as argument for INTERVAL, CASE, FIELD, CONCAT_WS, ELT and MAKE_SET functions.

- When running with --lower-case-table-names (default on Windows) and you had tables or databases with mixed case on disk, then executing SHOW TABLE STATUS followed with DROP DATABASE or DROP TABLE could fail with Errcode 13.

30-C-16 - Changements de la version 4.0.10 (29 janvier 2003)

Fonctionnalité ajoutée ou modifiée :

- Added option --log-error[=file_name] to mysqld_safe and mysqld. This option will force all error messages to be put in a log file if the option --console is not given. On Windows --log-error is enabled as default, with a default name of host_name.err if the name is not specified.

- Changed some things from Warning: to Note: in the log files.

- The mysqld server should now compile on NetWare.

- Added optimization that if one does GROUP BY ... ORDER BY NULL then result is not sorted.

- New --ft-stopword-file command-line option for mysqld to replace/disable the built-in stopword list that is used in full-text searches. Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ».

- Changed default stack size from 64K to 192K; This fixes a core dump problem on Red Hat 8.0 and other systems with a glibc that requires a stack size larger than 128K for gethostbyaddr() to resolve a hostname. You can fix this for earlier MySQL versions by starting mysqld with --thread-stack=192K.

- Added mysql_waitpid to the binary distribution and the MySQL-client RPM subpackage (required for mysql-test-run).

- Renamed the main MySQL RPM package to MySQL-server. When updating from an older version, MySQL-server.rpm will simply replace MySQL.rpm.

- If a slave is configured with replicate_wild_do_table=db.% or replicate_wild_ignore_table=db.%, these rules will be applied to CREATE/DROP DATABASE, too.

- Added timeout value for MASTER_POS_WAIT().

Bogues corrigés :

- Fixed initialization of the random Voird for newly created threads to give a better rand() distribution from the first call.

- Fixed a bug that caused mysqld to hang when a table was opened with the HANDLER command and then dropped without being closed.

- Fixed bug in logging to binary log (which affects replication) a query that inserts a NULL in an AUTO_INCREMENT column and also uses LAST_INSERT_ID().

- Fixed an unlikely bug that could cause a memory overrun when using ORDER BY constant_expression.

- Fixed a table corruption in myisamchk's parallel repair mode.

- Fixed bug in query cache invalidation on simple table renaming.

- Fixed bug in mysqladmin --relative.

- On some 64-bit systems, show status reported a strange number for Open_files and Open_streams.

- Fixed incorrect number of columns in EXPLAIN on empty table.

- Fixed bug in LEFT JOIN that caused zero rows to be returned in the case the WHERE condition was evaluated as FALSE after reading const tables. (Unlikely condition).

- FLUSH PRIVILEGES didn't correctly flush table/column privileges when mysql.tables_priv is empty.

- Fixed bug in replication when using LOAD DATA INFILE one a file that updated an AUTO_INCREMENT column with NULL or 0. This bug only affected MySQL 4.0 masters (not slaves or MySQL 3.23 masters). Note: If you have a slave that has replicated a file with generated AUTO_INCREMENT columns then the slave data is corrupted and you should reinitialize the affected tables from the master.

- Fixed possible memory overrun when sending a BLOB value larger than 16M to the client.

- Fixed incorrect error message when setting a NOT NULL column to an expression that returned NULL.

- Fixed core dump bug in str LIKE "%other_str%" where str or other_str contained characters >= 128.

- Fixed bug: When executing on master LOAD DATA and InnoDB failed with table full error the binary log was corrupted.

30-C-17 - Changements de la version 4.0.9 (09 janvier 2003)

Fonctionnalité ajoutée ou modifiée :

- OPTIMIZE TABLE will for MyISAM tables treat all NULL values as different when calculating cardinality. This helps in optimizing joins between tables where one of the tables has a lot of NULL values in a indexed column:

SELECT * from t1,t2 where t1.a=t2.key_with_a_lot_of_null;

- Added join operator FORCE INDEX (key_list). This acts likes USE INDEX (key_list) but with the addition that a table scan is assumed to be VERY expensive. One bad thing with this is that it makes FORCE a reserved word.

- Reset internal row buffer in MyISAM after each query. This will reduce memory in the case you have a lot of big blobs in a table.

Bogues corrigés :

- A security patch in 4.0.8 causes the mysqld server to die if the remote hostname can't be resolved. This is now fixed.

- Fixed crash when replication big LOAD DATA INFILE statement that caused log rotation.

30-C-18 - Changements de la version 4.0.8 (07 janvier 2003)

Fonctionnalité ajoutée ou modifiée :

- Default max_packet_length for libmysqld.c is now 1024*1024*1024.

- One can now specify max_allowed_packet in a file ready by mysql_options(MYSQL_READ_DEFAULT_FILE). for clients.

- When sending a too big packet to the server with the not compressed protocol, the client now gets an error message instead of a lost connection.

- We now send big queries/result rows in bigger hunks, which should give a small speed improvement.

- Fixed some bugs with the compressed protocol for rows > 16M.

- InnoDB tables now also support ON UPDATE CASCADE in FOREIGN KEY constraints. Voir the InnoDB section in the manual for the InnoDB changelog.

Bogues corrigés :

- Fixed bug in ALTER TABLE with BDB tables.

- Fixed core dump bug in QUOTE() function.

- Fixed a bug in handling communication packets bigger than 16M. Unfortunately this required a protocol change; If you upgrade the server to 4.0.8 and above and have clients that uses packets >= 255*255*255 bytes (=16581375) you must also upgrade your clients to at least 4.0.8. If you don't upgrade, the clients will hang when sending a big packet.

- Fixed bug when sending blobs longer than 16M to client.

- Fixed bug in GROUP BY when used on BLOB column with NULL values.

- Fixed a bug in handling NULL values in CASE ... WHEN ...

30-C-19 - Changements de la version 4.0.7 (20 Décembre 2002)

Fonctionnalité ajoutée ou modifiée :

- mysqlbug now also reports the compiler version used for building the binaries (if the compiler supports the option --version).

Bogues corrigés :

- Fixed compilation problems on OpenUnix and HPUX 10.20.

- Fixed some optimization problems when compiling MySQL with -DBIG_TABLES on a 32-bit system.

- mysql_drop_db() didn't check permissions properly so anyone could drop another users database. DROP DATABASE is checked properly.

30-C-20 - Changements de la version 4.0.6 (14 Décembre 2002 : Gamma)

Fonctionnalité ajoutée ou modifiée :

- Added syntax support for CHARACTER SET xxx and CHARSET=xxx table options (to be able to read table dumps from 4.1).

- Fixed replication bug that caused the slave to loose its position in some cases when the replication log was rotated.

- Fixed that a slave will restart from the start of a transaction if it's killed in the middle of one.

- Moved the manual pages from man to man/man1 in the binary distributions.

- The default type returned by IFNULL(A,B) is now set to be the more 'general' of the types of A and B. (The order is STRING, REAL or INTEGER).

- Moved the mysql.server startup script in the RPM packages from /etc/rc.d/init.d/mysql to /etc/init.d/mysql (which almost all current Linux distributions support for LSB compliance).

- Added Qcache_lowmem_prunes status variable (number of queries that were deleted from cache because of low memory).

- Fixed mysqlcheck so it can deal with table names containing dashes.

- Bulk insert optimization (Voir Section 13.5.3.18, « Syntaxe de SHOW VARIABLES ») is no longer used when inserting small (less than 100) number of rows.

- Optimization added for queries like SELECT ... FROM merge_table WHERE indexed_column=constant_expr.

- Added functions LOCALTIME and LOCALTIMESTAMP as synonyms for NOW().

- CEIL is now an alias for CEILING.

- The CURRENT_USER() function can be used to get a user@host value as it was matched in the GRANT system. Voir Section 12.8.4, « Fonctions diverses ».

- Fixed CHECK constraints to be compatible with SQL-99. This made CHECK a reserved word. (Checking of CHECK constraints is still not implemented).

- Added CAST(... as CHAR).

- Added PostgreSQL compatible LIMIT syntax: SELECT ... LIMIT row_count OFFSET offset

- mysql_change_user() will now reset the connection to the state of a fresh connect (Ie, ROLLBACK any active transaction, close all temporary tables, reset all user variables etc..)

- CHANGE MASTER and RESET SLAVE now require that slave threads be both already stopped; these commands will return an error if at least one of these two threads is running.

Bogues corrigés :

- Fixed number of found rows returned in multi table updates

- Make --lower-case-table-names default on Mac OS X as the default file system (HFS+) is case insensitive. Voir Section 9.2.2, « Sensibilité à la casse pour les noms ».

- Transactions in AUTOCOMMIT=0 mode didn't rotate binary log.

- A fix for the bug in a SELECT with joined tables with ORDER BY and LIMIT clause when filesort had to be used. In that case LIMIT was applied to filesort of one of the tables, although it could not be. This fix also solved problems with LEFT JOIN.

- mysql_server_init() now makes a copy of all arguments. This fixes a problem when using the embedded server in C# program.

- Fixed buffer overrun in libmysqlclient library that allowed a malicious MySQL server to crash the client application.

- Fixed security-related bug in mysql_change_user() handling. All users are strongly recommended to upgrade to version 4.0.6.

- Fixed bug that prevented --chroot command-line option of mysqld from working.

- Fixed bug in phrase operator "..." in boolean full-text search.

- Fixed bug that caused OPTIMIZE TABLE to corrupt the table under some rare circumstances.

- Part rewrite of multiple-table-update to optimize it, make it safer and more bug free.

- LOCK TABLES now works together with multiple-table-update and multiple-table-delete.

- --replicate-do=xxx didn't work for UPDATE commands. (Bug introduced in 4.0.0)

- Fixed shutdown problem on Mac OS X.

- Major InnoDB bugs in REPLACE, AUTO_INCREMENT, INSERT INTO ... SELECT ... were fixed. Voir the InnoDB changelog in the InnoDB section of the manual.

- RESET SLAVE caused a crash if the slave threads were running.

30-C-21 - Changements de la version 4.0.5 (13 novembre 2002)

Fonctionnalité ajoutée ou modifiée :

- Port number was added to host name (if it is known) in SHOW PROCESSLIST command

- Changed handling of last argument in WEEK() so that one can get week number according to the ISO 8601 specification. (Old code should still work).

- Fixed that INSERT DELAYED threads don't hang on Waiting for INSERT when one sends a SIGHUP to mysqld.

- Change that AND works according to SQL-99 when it comes to NULL handling. In practice, this only affects queries where you do something like WHERE ... NOT (NULL AND 0).

- mysqld will now resolve basedir to its full path (with realpath()). This enables one to use relative symlinks to the MySQL installation directory. This will however cause show variables to report different directories on systems where there is a symbolic link in the path.

- Fixed that MySQL will not use index scan on index disabled with IGNORE INDEX or USE INDEX. to be ignored.

- Added --use-frm option to mysqlcheck. When used with REPAIR, it gets the table structure from the .frm file, so the table can be repaired even if the .MYI header is corrupted.

- Fixed bug in MAX() optimization when used with JOIN and ON expressions.

- Added support for reading of MySQL 4.1 table definition files.

- BETWEEN behavior changed (Voir Section 12.1.3, « Opérateurs de comparaison »). Now datetime_col BETWEEN timestamp AND timestamp should work as expected.

- One can create TEMPORARY MERGE tables now.

- DELETE FROM myisam_table now shrinks not only the .MYD file but also the .MYI file.

- When one uses the --open-files-limit=# option to mysqld_safe it's now passed on to mysqld.

- Changed output from EXPLAIN from 'where used' to 'Using where' to make it more in line with other output.

- Removed variable safe_show_database as it was no longer used.

- Updated source tree to be built using automake 1.5 and libtool 1.4.

- Fixed an inadvertently changed option (--ignore-space) back to the original --ignore-spaces in mysqlclient. (Both syntaxes will work).

- Don't require UPDATE privilege when using REPLACE.

- Added support for DROP TEMPORARY TABLE ..., to be used to make replication safer.

- When transactions are enabled, all commands that update temporary tables inside a BEGIN/COMMIT are now stored in the binary log on COMMIT and not stored if one does ROLLBACK. This fixes some problems with non-transactional temporary tables used inside transactions.

- Allow braces in joins in all positions. Formerly, things like SELECT * FROM (t2 LEFT JOIN t3 USING (a)), t1 worked, but not SELECT * FROM t1, (t2 LEFT JOIN t3 USING (a)). Note that braces are simply removed, they do not change the way the join is executed.

- InnoDB now supports also isolation levels READ UNCOMMITTED and READ COMMITTED. For a detailed InnoDB changelog, Voir Section C.9, « Evolutions de InnoDB » in this manual.

Bogues corrigés :

- Fixed bug in MAX() optimization when used with JOIN and ON expressions.

- Fixed that INSERT DELAY threads don't hang on Waiting for INSERT when one sends a SIGHUP to mysqld.

- Fixed that MySQL will not use an index scan on an index that has been disabled with IGNORE INDEX or USE INDEX.

- Corrected test for root user in mysqld_safe.

- Fixed error message issued when storage engine cannot do CHECK or REPAIR.

- Fixed rare core dump problem in complicated GROUP BY queries that didn't return any result.

- Fixed mysqlshow to work properly with wildcarded database names and with database names that contain underscores.

- Portability fixes to get MySQL to compile cleanly with Sun Forte 5.0.

- Fixed MyISAM crash when using dynamic-row tables with huge numbers of packed fields.

- Fixed query cache behavior with BDB transactions.

- Fixed possible floating point exception in MATCH relevance calculations.

- Fixed bug in full-text search IN BOOLEAN MODE that made MATCH to return incorrect relevance value in some complex joins.

- Fixed a bug that limited MyISAM key length to a value slightly less that 500. It is exactly 500 now.

- Fixed that GROUP BY on columns that may have a NULL value doesn't always use disk based temporary tables.

- The filename argument for the --des-key-file argument to mysqld is interpreted relative to the data directory if given as a relative pathname.

- Removed a condition that temp table with index on column that can be NULL has to be MyISAM. This was okay for 3.23, but not needed in 4.*. This resulted in slowdown in many queries since 4.0.2.

- Small code improvement in multiple-table updates.

- Fixed a newly introduced bug that caused ORDER BY ... LIMIT row_count to not return all rows.

- Fixed a bug in multiple-table deletes when outer join is used on an empty table, which gets first to be deleted.

- Fixed a bug in multiple-table updates when a single table is updated.

- Fixed bug that caused REPAIR TABLE and myisamchk to corrupt FULLTEXT indexes.

- Fixed bug with caching the mysql grant table database. Now queries in this database are not cached in the query cache.

- Small fix in mysqld_safe for some shells.

- Give error if a MyISAM MERGE table has more than 2 ^ 32 rows and MySQL was not compiled with -DBIG_TABLES.

- Fixed some ORDER BY ... DESC problems with InnoDB tables.

30-C-22 - Changements de la version 4.0.4 (29 septembre 2002)

- Fixed bug where GRANT/REVOKE failed if hostname was given in non-matching case.

- Don't give warning in LOAD DATA INFILE when setting a timestamp to a string value of '0'.

- Fixed bug in myisamchk -R mode.

- Fixed bug that caused mysqld to crash on REVOKE.

- Fixed bug in ORDER BY when there is a constant in the SELECT statement.

- One didn't get an error message if mysqld couldn't open the privilege tables.

- SET PASSWORD FOR ... closed the connection in case of errors (bug from 4.0.3).

- Increased max possible max_allowed_packet in mysqld to 1 GB.

- Fixed bug when doing a multi-line INSERT on a table with an AUTO_INCREMENT key which was not in the first part of the key.

- Changed LOAD DATA INFILE to not recreate index if the table had rows from before.

- Fixed overrun bug when calling AES_DECRYPT() with incorrect arguments.

- --skip-ssl can now be used to disable SSL in the MySQL clients, even if one is using other SSL options in an option file or previously on the command line.

- Fixed bug in MATCH ... AGAINST( ... IN BOOLEAN MODE) used with ORDER BY.

- Added LOCK TABLES and CREATE TEMPORARY TABLES privilege on the database level. One must run the mysql_fix_privilege_tables script on old installations to activate these.

- In SHOW TABLE ... STATUS, compressed tables sometimes showed up as dynamic.

- SELECT @@[global|session].var_name didn't report global | session in the result column name.

- Fixed problem in replication that FLUSH LOGS in a circular replication setup created an infinite number of binary log files. Now a rotate-binary-log command in the binary log will not cause slaves to rotate logs.

- Removed STOP EVENT from binary log when doing FLUSH LOGS.

- Disable the use of SHOW NEW MASTER FOR SLAVE as this needs to be completely reworked in a future release.

- Fixed a bug with constant expression (for example, field of a one-row table, or field from a table, referenced by a UNIQUE key) appeared in ORDER BY part of SELECT DISTINCT.

- --log-binary=a.b.c now properly strips off .b.c.

- FLUSH LOGS removed numerical extension for all future update logs.

- GRANT ... REQUIRE didn't store the SSL information in the mysql.user table if SSL was not enabled in the server.

- GRANT ... REQUIRE NONE can now be used to remove SSL information.

- AND is now optional between REQUIRE options.

- REQUIRE option was not properly saved, which could cause strange output in SHOW GRANTS.

- Fixed that mysqld --help reports correct values for --datadir and --bind-address.

- Fixed that one can drop UDFs that didn't exist when mysqld was started.

- Fixed core dump problem with SHOW VARIABLES on some 64-bit systems (like Solaris SPARC).

- Fixed a bug in my_getopt(); --set-variable syntax didn't work for those options that didn't have a valid variable in the my_option struct. This affected at least the default-table-type option.

- Fixed a bug from 4.0.2 that caused REPAIR TABLE and myisamchk --recover to fail on tables with duplicates in a unique key.

- Fixed a bug from 4.0.3 in calculating the default datatype for some functions. This affected queries of type CREATE TABLE table_name SELECT expression(),...

- Fixed bug in queries of type SELECT * FROM table-list GROUP BY ... and SELECT DISTINCT * FROM ....

- Fixed bug with the --slow-log when logging an administrator command (like FLUSH TABLES).

- Fixed a bug that OPTIMIZE of locked and modified table, reported table corruption.

- Fixed a bug in my_getopt() in handling of special prefixes (--skip-, --enable-). --skip-external-locking didn't work and the bug may have affected other similar options.

- Fixed bug in checking for output file name of the tee option.

- Added some more optimization to use index for SELECT ... FROM many_tables .. ORDER BY key limit #

- Fixed problem in SHOW OPEN TABLES when a user didn't have access permissions to one of the opened tables.

30-C-23 - Changements de la version 4.0.3 (26 Août 2002 : Beta)

- Fixed problem with types of user variables. (Bug #551)

- Fixed problem with configure ... --localstatedir=....

- Cleaned up mysql.server script.

- Fixed a bug in mysqladmin shutdown when pid file was modified while mysqladmin was still waiting for the previous one to disappear. This could happen during a very quick restart and caused mysqladmin to hang until shutdown_timeout seconds had passed.

- Don't increment warnings when setting AUTO_INCREMENT columns to NULL in LOAD DATA INFILE.

- Fixed all boolean type variables/options to work with the old syntax, for example, all of these work: --lower-case-table-names, --lower-case-table-names=1, -O lower-case-table-names=1, --set-variable=lower-case-table-names=1

- Fixed shutdown problem (SIGTERM signal handling) on Solaris. (Bug from 4.0.2).

- SHOW MASTER STATUS now returns an empty set if binary log is not enabled.

- SHOW SLAVE STATUS now returns an empty set if slave is not initialized.

- Don't update MyISAM index file on update if not strictly necessary.

- Fixed bug in SELECT DISTINCT ... FROM many_tables ORDER BY not-used-column.

- Fixed a bug with BIGINT values and quoted strings.

- Added QUOTE() function that performs SQL quoting to produce values that can be used as data values in queries.

- Changed variable DELAY_KEY_WRITE to an enum to allow one set DELAY_KEY_WRITE for all tables without taking down the server.

- Changed behavior of IF(condition,column,NULL) so that it returns the value of the column type.

- Made safe_mysqld a symlink to mysqld_safe in binary distribution.

- Fixed security bug when having an empty database name in the user.db table.

- Fixed some problems with CREATE TABLE ... SELECT function().

- mysqld now has the option --temp-pool enabled by default as this gives better performance with some operating systems.

- Fixed problem with too many allocated alarms on slave when connecting to master many times (normally not a very critical error).

- Fixed hang in CHANGE MASTER TO if the slave thread died very quickly.

- Big cleanup in replication code (less logging, better error messages, etc..)

- If the --code-file option is specified, the server calls setrlimit() to set the maximum allowed core file size to unlimited, so core files can be generated.

- Fixed bug in query cache after temporary table creation.

- Added --count=N (-c) option to mysqladmin, to make the program do only N iterations. To be used with --sleep (-i). Useful in scripts.

- Fixed bug in multiple-table UPDATE: when updating a table, do_select() became confused about reading records from a cache.

- Fixed bug in multiple-table UPDATE when several fields were referenced from a single table

- Fixed bug in truncating nonexisting table.

- Fixed bug in REVOKE that caused user resources to be randomly set.

- Fixed bug in GRANT for the new CREATE TEMPORARY TABLE privilege.

- Fixed bug in multiple-table DELETE when tables are re-ordered in the table initialization method and ref_lengths are of different sizes.

- Fixed two bugs in SELECT DISTINCT with large tables.

- Fixed bug in query cache initialization with very small query cache size.

- Allow DEFAULT with INSERT statement.

- The startup parameters myisam_max_sort_file_size and myisam_max_extra_sort_file_size are now given in bytes, not megabytes.

- External system locking of MyISAM/ISAM files is now turned off by default. One can turn this on with --external-locking. (For most users this is never needed).

- Fixed core dump bug with INSERT ... SET db_name.table_name.colname=''.

- Fixed client hangup bug when using some SQL commands with incorrect syntax.

- Fixed a timing bug in DROP DATABASE

- New SET [GLOBAL | SESSION] syntax to change thread-specific and global server variables at runtime.

- Added variable slave_compressed_protocol.

- Renamed variable query_cache_startup_type to query_cache_type, myisam_bulk_insert_tree_size to bulk_insert_buffer_size, record_buffer to read_buffer_size and record_rnd_buffer to read_rnd_buffer_size.

- Renamed some SQL variables, but old names will still work until 5.0. Voir Section 2.6.3, « Passer de la version 3.23 à la version 4.0 ».

- Renamed --skip-locking to --skip-external-locking.

- Removed unused variable query_buffer_size.

- Fixed a bug that made the pager option in the mysql client non-functional.

- Added full AUTO_INCREMENT support to MERGE tables.

- Extended LOG() function to accept an optional arbitrary base parameter. Voir Section 12.4.2, « Fonctions mathématiques ».

- Added LOG2() function (useful for finding out how many bits a number would require for storage).

- Added LN() natural logarithm function for compatibility with other databases. It is synonymous with LOG(X).

30-C-24 - Changements de la version 4.0.2 (01 Juillet 2002)

- Cleaned up NULL handling for default values in DESCRIBE table_name.

- Fixed truncate() to round up negative values to the nearest integer.

- Changed --chroot=path option to execute chroot() immediately after all options have been parsed.

- Don't allow database names that contain '\'.

- lower_case_table_names now also affects database names.

- Added XOR operator (logical and bitwise XOR) with ^ as a synonym for bitwise XOR.

- Added function IS_FREE_LOCK("lock_name"). Based on code contributed by Hartmut Holzgraefe <hartmut@six.de>.

- Removed mysql_ssl_clear() from C API, as it was not needed.

- DECIMAL and NUMERIC types can now read exponential numbers.

- Added SHA1() function to calculate 160 bit hash value as described in RFC 3174 (Secure Hash Algorithm). This function can be considered a cryptographically more secure equivalent of MD5(). Voir Section 12.8.4, « Fonctions diverses ».

- Added AES_ENCRYPT() and AES_DECRYPT() functions to perform encryption according to AES standard (Rijndael). Voir Section 12.8.4, « Fonctions diverses ».

- Added --single-transaction option to mysqldump, allowing a consistent dump of InnoDB tables. Voir Section 8.8, « mysqldump, sauvegarde des structures de tables et les données ».

- Fixed bug in innodb_log_group_home_dir in SHOW VARIABLES.

- Fixed a bug in optimizer with merge tables when non-unique values are used in summing up (causing crashes).

- Fixed a bug in optimizer when a range specified makes index grouping impossible (causing crashes).

- Fixed a rare bug when FULLTEXT index is present and no tables are used.

- Added privileges CREATE TEMPORARY TABLES, EXECUTE, LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES and SUPER. To use these, you must have run the mysql_fix_privilege_tables script after upgrading.

- Fixed query cache align data bug.

- Fixed mutex bug in replication when reading from master fails.

- Added missing mutex in TRUNCATE TABLE; This fixes some core dump/hangup problems when using TRUNCATE TABLE.

- Fixed bug in multiple-table DELETE when optimizer uses only indexes.

- Fixed that ALTER TABLE table_name RENAME new_table_name is as fast as RENAME TABLE.

- Fixed bug in GROUP BY with two or more fields, where at least one field can contain NULL values.

- Use Turbo Boyer-Moore algorithm to speed up LIKE "%keyword%" searches.

- Fixed bug in DROP DATABASE with symlink.

- Fixed crash in REPAIR ... USE_FRM.

- Fixed bug in EXPLAIN with LIMIT offset != 0.

- Fixed bug in phrase operator "..." in boolean full-text search.

- Fixed bug that caused duplicated rows when using truncation operator * in boolean full-text search.

- Fixed bug in truncation operator of boolean full-text search (incorrect results when there are only +word*s in the query).

- Fixed bug in boolean full-text search that caused a crash when an identical MATCH expression that did not use an index appeared twice.

- Query cache is now automatically disabled in mysqldump.

- Fixed problem on Windows 98 that made sending of results very slow.

- Boolean full-text search weighting scheme changed to something more reasonable.

- Fixed bug in boolean full-text search that caused MySQL to ignore queries of ft_min_word_len characters.

- Boolean full-text search now supports « phrase searches ».

- New configure option --without-query-cache.

- Memory allocation strategy for « root memory » changed. Block size now grows with number of allocated blocks.

- INET_NTOA() now returns NULL if you give it an argument that is too large (greater than the value corresponding to 255.255.255.255).

- Fix SQL_CALC_FOUND_ROWS to work with UNION. It will work only if the first SELECT has this option and if there is global LIMIT for the entire statement. For the moment, this requires using parentheses for individual SELECT queries within the statement.

- Fixed bug in SQL_CALC_FOUND_ROWS and LIMIT.

- Don't give an error for CREATE TABLE ...(... VARCHAR(0)).

- Fixed SIGINT and SIGQUIT problems in mysql.cc on Linux with some glibc versions.

- Fixed bug in convert.cc, which is caused by having an incorrect net_store_length() linked in the CONVERT::store() method.

- DOUBLE and FLOAT columns now honor the UNSIGNED flag on storage.

- InnoDB now retains foreign key constraints through ALTER TABLE and CREATE/DROP INDEX.

- InnoDB now allows foreign key constraints to be added through the ALTER TABLE syntax.

- InnoDB tables can now be set to automatically grow in size (autoextend).

- Added --ignore-lines=n option to mysqlimport. This has the same effect as the IGNORE n LINES clause for LOAD DATA.

- Fixed bug in UNION with last offset being transposed to total result set.

- REPAIR ... USE_FRM added.

- Fixed that DEFAULT_SELECT_LIMIT is always imposed on UNION result set.

- Fixed that some SELECT options can appear only in the first SELECT.

- Fixed bug with LIMIT with UNION, where last select is in the braces.

- Fixed that full-text works fine with UNION operations.

- Fixed bug with indexless boolean full-text search.

- Fixed bug that sometimes appeared when full-text search was used with const tables.

- Fixed incorrect error value when doing a SELECT with an empty HEAP table.

- Use ORDER BY column DESC now sorts NULL values first. (In other words, NULL values sort first in all cases, whether or not DESC is specified.) This is changed back in 4.0.10.

- Fixed bug in WHERE key_name='constant' ORDER BY key_name DESC.

- Fixed bug in SELECT DISTINCT ... ORDER BY DESC optimization.

- Fixed bug in ... HAVING 'GROUP_FUNCTION'(xxx) IS [NOT] NULL.

- Fixed bug in truncation operator for boolean full-text search.

- Allow value of --user=# option for mysqld to be specified as a numeric user ID.

- Fixed a bug where SQL_CALC_ROWS returned an incorrect value when used with one table and ORDER BY and with InnoDB tables.

- Fixed that SELECT 0 LIMIT 0 doesn't hang thread.

- Fixed some problems with USE/IGNORE INDEX when using many keys with the same start column.

- Don't use table scan with BerkeleyDB and InnoDB tables when we can use an index that covers the whole row.

- Optimized InnoDB sort-buffer handling to take less memory.

- Fixed bug in multiple-table DELETE and InnoDB tables.

- Fixed problem with TRUNCATE and InnoDB tables that produced the error Can't execute the given command because you have active locked tables or an active transaction.

- Added NO_UNSIGNED_SUBTRACTION to the set of flags that may be specified with the --sql-mode option for mysqld. It disables unsigned arithmetic rules when it comes to subtraction. (This will make MySQL 4.0 behave more like 3.23 with UNSIGNED columns).

- The result returned for all bit functions (|, <<, ...) is now of type unsigned integer.

- Added detection of nan values in MyISAM to make it possible to repair tables with nan in float or double columns.

- Fixed new bug in myisamchk where it didn't correctly update number of « parts » in the MyISAM index file.

- Changed to use autoconf 2.52 (from autoconf 2.13).

- Fixed optimization problem where the MySQL Server was in « preparing » state for a long time when selecting from an empty table which had contained a lot of rows.

- Fixed bug in complicated join with const tables. This fix also improves performance a bit when referring to another table from a const table.

- First pre-version of multiple-table UPDATE statement.

- Fixed bug in multiple-table DELETE.

- Fixed bug in SELECT CONCAT(argument_list) ... GROUP BY 1.

- INSERT ... SELECT did a full rollback in case of an error. Fixed so that we only roll back the last statement in the current transaction.

- Fixed bug with empty expression for boolean full-text search.

- Fixed core dump bug in updating full-text key from/to NULL.

- ODBC compatibility: Added BIT_LENGTH() function.

- Fixed core dump bug in GROUP BY BINARY column.

- Added support for NULL keys in HEAP tables.

- Use index for ORDER BY in queries of type: SELECT * FROM t WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC

- Fixed bug in FLUSH QUERY CACHE.

- Added CAST() and CONVERT() functions. The CAST and CONVERT functions are nearly identical and mainly useful when you want to create a column with a specific type in a CREATE ... SELECT statement. For more information, read Section 12.7, « Fonctions de transtypage ».

- CREATE ... SELECT on DATE and TIME functions now create columns of the expected type.

- Changed order in which keys are created in tables.

- Added new columns Null and Index_type to SHOW INDEX output.

- Added --no-beep and --prompt options to mysql command-line client.

- New feature: management of user resources.

GRANT ... WITH MAX_QUERIES_PER_HOUR N1
MAX_UPDATES_PER_HOUR N2
MAX_CONNECTIONS_PER_HOUR N3;

Voir Section 5.6.4, « Limiter les ressources utilisateurs ».

- Added mysql_secure_installation to the scripts/ directory.

30-C-25 - Changements de la version 4.0.1 (23 décembre 2001)

- Added system command to mysql.

- Fixed bug when HANDLER was used with some unsupported table type.

- mysqldump now puts ALTER TABLE tbl_name DISABLE KEYS and ALTER TABLE tbl_name ENABLE KEYS in the sql dump.

- Added mysql_fix_extensions script.

- Fixed stack overrun problem with LOAD DATA FROM MASTER on OSF/1.

- Fixed shutdown problem on HP-UX.

- Added DES_ENCRYPT() and DES_DECRYPT() functions.

- Added FLUSH DES_KEY_FILE statement.

- Added --des-key-file option to mysqld.

- HEX(string) now returns the characters in string converted to hexadecimal.

- Fixed problem with GRANT when using lower_case_table_names=1.

- Changed SELECT ... IN SHARE MODE to SELECT ... LOCK IN SHARE MODE (as in MySQL 3.23).

- A new query cache to cache results from identical SELECT queries.

- Fixed core dump bug on 64-bit machines when it got an incorrect communication packet.

- MATCH ... AGAINST(... IN BOOLEAN MODE) can now work without FULLTEXT index.

- Fixed slave to replicate from 3.23 master.

- Miscellaneous replication fixes/cleanup.

- Got shutdown to work on Mac OS X.

- Added myisam/ft_dump utility for low-level inspection of FULLTEXT indexes.

- Fixed bug in DELETE ... WHERE ... MATCH ....

- Added support for MATCH ... AGAINST(... IN BOOLEAN MODE). Note: you must rebuild your tables with ALTER TABLE tablename TYPE=MyISAM to be able to use boolean full-text search.

- LOCATE() and INSTR() are now case-sensitive if either argument is a binary string.

- Changed RAND() initialization so that RAND(N) and RAND(N+1) are more distinct.

- Fixed core dump bug in UPDATE ... ORDER BY.

- In 3.23, INSERT INTO ... SELECT always had IGNORE enabled. Now MySQL will stop (and possibly roll back) by default in case of an error unless you specify IGNORE.

- Ignore DATA DIRECTORY and INDEX DIRECTORY directives on Windows.

- Added boolean full-text search code. It should be considered early alpha.

- Extended MODIFY and CHANGE in ALTER TABLE to accept the FIRST and AFTER keywords.

- Indexes are now used with ORDER BY on a whole InnoDB table.

30-C-26 - Changements de la version 4.0.0 (Octobre 2001 : alpha)

- Added --xml option to mysql for producing XML output.

- Added full-text variables ft_min_word_len, ft_max_word_len, and ft_max_word_len_for_sort system variables.

- Added full-text variables ft_min_word_len, ft_max_word_len, and ft_max_word_len_for_sort variables to myisamchk.

- Added documentation for libmysqld, the embedded MySQL server library. Also added example programs (a mysql client and mysqltest test program) which use libmysqld.

- Removed all Gemini hooks from MySQL server.

- Removed my_thread_init() and my_thread_end() from mysql_com.h, and added mysql_thread_init() and mysql_thread_end() to mysql.h.

- Support for communication packets > 16MB. In 4.0.1 we will extend MyISAM to be able to handle these.

- Secure connections (with SSL).

- Unsigned BIGINT constants now work. MIN() and MAX() now handle signed and unsigned BIGINT numbers correctly.

- New character set latin1_de which provides correct German sorting.

- STRCMP() now uses the current character set when doing comparisons, which means that the default comparison behavior now is case insensitive.

- TRUNCATE TABLE and DELETE FROM tbl_name are now separate functions. One bonus is that DELETE FROM tbl_name now returns the number of deleted rows, rather than zero.

- DROP DATABASE now executes a DROP TABLE on all tables in the database, which fixes a problem with InnoDB tables.

- Added support for UNION.

- Added support for multiple-table DELETE operations.

- A new HANDLER interface to MyISAM tables.

- Added support for INSERT on MERGE tables. Patch from Benjamin Pflugmann.

- Changed WEEK(date,0) to match the calendar in the USA.

- COUNT(DISTINCT) is about 30% faster.

- Speed up all internal list handling.

- Speed up IS NULL, ISNULL() and some other internal primitives.

- Full-text index creation now is much faster.

- Tree-like cache to speed up bulk inserts and myisam_bulk_insert_tree_size variable.

- Searching on packed (CHAR/VARCHAR) keys is now much faster.

- Optimized queries of type: SELECT DISTINCT * from tbl_name ORDER by key_part1 LIMIT row_count.

- SHOW CREATE TABLE now shows all table attributes.

- ORDER BY ... DESC can now use keys.

- LOAD DATA FROM MASTER « automatically » sets up a slave.

- Renamed safe_mysqld to mysqld_safe to make this name more in line with other MySQL scripts/commands.

- Added support for symbolic links to MyISAM tables. Symlink handling is now enabled by default for Windows.

- Added SQL_CALC_FOUND_ROWS and FOUND_ROWS(). This makes it possible to know how many rows a query would have returned without a LIMIT clause.

- Changed output format of SHOW OPEN TABLES.

- Allow SELECT expression LIMIT ....

- Added ORDER BY syntax to UPDATE and DELETE.

- SHOW INDEXES is now a synonym for SHOW INDEX.

- Added ALTER TABLE tbl_name DISABLE KEYS and ALTER TABLE tbl_name ENABLE KEYS commands.

- Allow use of IN as a synonym for FROM in SHOW commands.

- Implemented « repair by sort » for FULLTEXT indexes. REPAIR TABLE, ALTER TABLE, and OPTIMIZE TABLE for tables with FULLTEXT indexes are now up to 100 times faster.

- Allow standard SQL syntax X'hexadecimal-number'.

- Cleaned up global lock handling for FLUSH TABLES WITH READ LOCK.

- Fixed problem with DATETIME = constant in WHERE optimization.

- Added --master-data and --no-autocommit options to mysqldump. (Thanks to Brian Aker for this.)

- Added script mysql_explain_log.sh to distribution. (Thanks to mobile.de).

30-D - Changements de la version 3.23.x (Recent; still supported)

Please note that since release 4.0 is now production level, only critical fixes are done in the 3.23 release series. You are recommended to upgrade when possible, to take advantage of all speed and feature improvements in 4.0. Voir Section 2.6.3, « Passer de la version 3.23 à la version 4.0 ».

The 3.23 release has several major features that are not present in previous versions. We have added three new table types:

- MyISAM
A new ISAM library which is tuned for SQL and supports large files.

- InnoDB
A transaction-safe storage engine that supports row level locking, and many Oracle-like features.

- BerkeleyDB or BDB
Uses the Berkeley DB library from Sleepycat Software to implement transaction-safe tables.

Note that only MyISAM is available in the standard binary distribution.

The 3.23 release also includes support for database replication between a master and many slaves, full-text indexing, and much more.

All new features are being developed in the 4.x version. Only bug fixes and minor enhancements to existing features will be added to 3.23.

The replication code and BerkeleyDB code is still not as tested and as the rest of the code, so we will probably need to do a couple of future releases of 3.23 with small fixes for this part of the code. As long as you don't use these features, you should be quite safe with MySQL 3.23!

Note that the above doesn't mean that replication or Berkeley DB don't work. We have done a lot of testing of all code, including replication and BDB without finding any problems. It only means that not as many users use this code as the rest of the code and because of this we are not yet 100% confident in this code.

30-D-1 - Changements de la version 3.23.59 (not released yet)

- Fixed a symlink vulnerability in mysqlbug script - vulnerability id CAN-2004-0381. (Bug #3284)

- Fixed bug in privilege checking of ALTER TABLE RENAME. (Bug #3270)

- Fixed bugs in ACOS(), ASIN() (Bug #2338) and in FLOOR() (Bug #3051). The cause of the problem is an overly strong optimization done by gcc in this case.

- Fixed bug in INSERT ... SELECT statements where, if a NOT NULL column is assigned a value of NULL, the following columns in the row might be assigned a value of zero. (Bug #2012)

- If a query was ignored on the slave (because of replicate-ignore-table and other similar rules), the slave still checked if the query got the same error code (0, no error) as on the master. So if the master had an error on the query (for example, « Duplicate entry » in a multiple-row insert), then the slave stopped and warned that the error codes didn't match. This is a backport of the fix for MySQL 4.0. (Bug #797)

- mysqlbinlog now asks for a password at console when the -p/--password option is used with no argument. This is how the other clients (mysqladmin, mysqldump..) already behave. Note that one now has to use mysqlbinlog -p<my_password>; mysqlbinlog -p <my_password> will not work anymore (in other words, put no space after -p). (Bug #1595)

- On some 64-bit machines (some HP-UX and Solaris machines), a slave installed with the 64-bit MySQL binary could not connect to its master (it connected to itself instead). (Bug #1256, Bug #1381)

- Fixed a Windows-specific bug present since MySQL 3.23.57 and 3.23.58 that caused Windows slaves to crash when they started replication if a master.info file existed. (Bug #1720)

- Fixed bug in ALTER TABLE RENAME, when rename to the table with the same name in another database silently dropped destination table if it existed. (Bug #2628)

30-D-2 - Changements de la version 3.23.58 (11 septembre 2003)

- Fixed buffer overflow in password handling which could potentially be exploited by MySQL users with ALTER privilege on the mysql.user table to execute random code or to gain shell access with the UID of the mysqld process (thanks to Jedi/Sector One for spotting and reporting this bug).

- mysqldump now correctly quotes all identifiers when communicating with the server. This assures that during the dump process, mysqldump will never send queries to the server that result in a syntax error. This problem is not related to the mysqldump program's output, which was not changed. (Bug #1148)

- Fixed table/column grant handling - proper sort order (from most specific to less specific, Voir Section 5.5.6, « Contrôle d'accès, étape 2 : Vérification de la requête ») was not honored. (Bug #928)

- Fixed overflow bug in MyISAM and ISAM when a row is updated in a table with a large number of columns and at least one BLOB/TEXT column.

- Fixed MySQL so that field length (in C API) for the second column in SHOW CREATE TABLE is always larger than the data length. The only known application that was affected by the old behavior was Borland dbExpress, which truncated the output from the command. (Bug #1064)

- Fixed ISAM bug in MAX() optimization.

- Fixed Unknown error when doing ORDER BY on reference table which was used with NULL value on NOT NULL column. (Bug #479)

30-D-3 - Changements de la version 3.23.57 (06 juin 2003)

- Fixed problem in alarm handling that could cause problems when getting a packet that is too large.

- Fixed problem when installing MySQL as a service on Windows when one gave 2 arguments (option file group name and service name) to mysqld.

- Fixed kill pid-of-mysqld to work on Mac OS X.

- SHOW TABLE STATUS displayed incorrect Row_format value for tables that have been compressed with myisampack. (Bug #427)

- SHOW VARIABLES LIKE 'innodb_data_file_path' displayed only the name of the first datafile. (Bug #468)

- Fixed security problem where mysqld didn't allow one to UPDATE rows in a table even if one had a global UPDATE privilege and a database SELECT privilege.

- Fixed a security problem with SELECT and wildcarded select list, when user only had partial column SELECT privileges on the table.

- Fixed unlikely problem in optimizing WHERE clause with a constant expression such as in WHERE 1 AND (a=1 AND b=1).

- Fixed problem on IA-64 with timestamps that caused mysqlbinlog to fail.

- The default option for innodb_flush_log_at_trx_commit was changed from 0 to 1 to make InnoDB tables ACID by default. Voir Section 15.5, « Options de démarrage InnoDB ».

- Fixed problem with too many allocated alarms on slave when connecting to master many times (normally not a very critical error).

- Fixed a bug in replication of temporary tables. (Bug #183)

- Fixed 64-bit bug that affected at least AMD hammer systems.

- Fixed a bug when doing LOAD DATA INFILE IGNORE: When reading the binary log, mysqlbinlog and the replication code read REPLACE instead of IGNORE. This could make the slave's table become different from the master's table. (Bug #218)

- Fixed overflow bug in MyISAM when a row is inserted into a table with a large number of columns and at least one BLOB/TEXT column. Bug was caused by incorrect calculation of the needed buffer to pack data.

- The binary log was not locked during TRUNCATE table_name or DELETE FROM table_name statements, which could cause an INSERT to table_name to be written to the log before the TRUNCATE or DELETE statements.

- Fixed rare bug in UPDATE of InnoDB tables where one row could be updated multiple times.

- Produce an error for empty table and column names.

- Changed PROCEDURE ANALYSE() to report DATE instead of NEWDATE.

- Changed PROCEDURE ANALYSE(#) to restrict the number of values in an ENUM column to # also for string values.

- mysqldump no longer silently deletes the binary logs when invoked with the --master-data or --first-slave option; while this behavior was convenient for some users, others may suffer from it. Now one has to explicitly ask for binary logs to be deleted by using the new --delete-master-logs option.

- Fixed a bug in mysqldump when it was invoked with the --master-data option: The CHANGE MASTER TO statements that were appended to the SQL dump had incorrect coordinates. (Bug #159)

30-D-4 - Changements de la version 3.23.56 (13 mars 2003)

- Fixed mysqld crash on extremely small values of sort_buffer variable.

- Fixed a bug in privilege system for GRANT UPDATE on column level.

- Fixed a rare bug when using a date in HAVING with GROUP BY.

- Fixed checking of random part of WHERE clause. (Bug #142)

- Fixed MySQL (and myisamchk) crash on artificially corrupted .MYI files.

- Security enhancement: mysqld no longer reads options from world-writeable config files.

- Security enhancement: mysqld and safe_mysqld now only use the first --user option specified on the command line. (Normally this comes from /etc/my.cnf)

- Security enhancement: Don't allow BACKUP TABLE to overwrite existing files.

- Fixed unlikely deadlock bug when one thread did a LOCK TABLE and another thread did a DROP TABLE. In this case one could do a KILL on one of the threads to resolve the deadlock.

- LOAD DATA INFILE was not replicated by slave if replicate_*_table was set on the slave.

- Fixed a bug in handling CHAR(0) columns that could cause incorrect results from the query.

- Fixed a bug in SHOW VARIABLES on 64-bit platforms. The bug was caused by incorrect declaration of variable server_id.

- The Comment column in SHOW TABLE STATUS now reports that it can contain NULL values (which is the case for a crashed .frm file).

- Fixed the rpl_rotate_logs test to not fail on certain platforms (e.g. Mac OS X) due to a too long file name (changed slave-master-info.opt to .slave-mi).

- Fixed a problem with BLOB NOT NULL columns used with IS NULL.

- Fixed bug in MAX() optimization in MERGE tables.

- Better RAND() initialization for new connections.

- Fixed bug with connect timeout. This bug was manifested on OS's with poll() system call, which resulted in timeout the value specified as it was executed in both select() and poll().

- Fixed bug in SELECT * FROM table WHERE datetime1 IS NULL OR datetime2 IS NULL.

- Fixed bug in using aggregate functions as argument for INTERVAL, CASE, FIELD, CONCAT_WS, ELT and MAKE_SET functions.

- When running with --lower-case-table-names (default on Windows) and you had tables or databases with mixed case on disk, then executing SHOW TABLE STATUS followed with DROP DATABASE or DROP TABLE could fail with Errcode 13.

- Fixed bug in logging to binary log (which affects replication) a query that inserts a NULL in an auto_increment field and also uses LAST_INSERT_ID().

- Fixed bug in mysqladmin --relative.

- On some 64-bit systems, show status reported a strange number for Open_files and Open_streams.

30-D-5 - Changements de la version 3.23.55 (23 janvier 2003)

- Fixed double free'd pointer bug in mysql_change_user() handling, that enabled a specially hacked version of MySQL client to crash mysqld. Note, that one needs to login to the server by using a valid user account to be able to exploit this bug.

- Fixed bug with the --slow-log when logging an administrator command (like FLUSH TABLES).

- Fixed bug in GROUP BY when used on BLOB column with NULL values.

- Fixed a bug in handling NULL values in CASE ... WHEN ....

- Bugfix for --chroot (Voir Section C.4.6, « Changements de la version 3.23.54 (05 décembre 2002) ») is reverted. Unfortunately, there is no way to make it to work, without introducing backward-incompatible changes in my.cnf. Those who need --chroot functionality, should upgrade to MySQL 4.0. (The fix in the 4.0 branch did not break backward-compatibility).

- Make --lower-case-table-names default on Mac OS X as the default file system (HFS+) is case insensitive.

- Fixed a bug in scripts/mysqld_safe.sh in NOHUP_NICENESS testing.

- Transactions in AUTOCOMMIT=0 mode didn't rotate binary log.

- Fixed a bug in scripts/make_binary_distribution that resulted in a remaining @HOSTNAME@ variable instead of replacing it with the correct path to the hostname binary.

- Fixed a very unlikely bug that could cause SHOW PROCESSLIST to core dump in pthread_mutex_unlock() if a new thread was connecting.

- Forbid SLAVE STOP if the thread executing the query has locked tables. This removes a possible deadlock situation.

30-D-6 - Changements de la version 3.23.54 (05 décembre 2002)

- Fixed a bug, that allowed to crash mysqld with a specially crafted packet.

- Fixed a rare crash (double free'd pointer) when altering a temporary table.

- Fixed buffer overrun in libmysqlclient library that allowed malicious MySQL server to crash the client application.

- Fixed security-related bug in mysql_change_user() handling. All users are strongly recommended to upgrade to the version 3.23.54.

- Fixed bug that prevented --chroot command-line option of mysqld from working.

- Fixed bug that made OPTIMIZE TABLE to corrupt the table under some rare circumstances.

- Fixed mysqlcheck so it can deal with table names containing dashes.

- Fixed shutdown problem on Mac OS X.

- Fixed bug with comparing an indexed NULL field with <=> NULL.

- Fixed bug that caused IGNORE INDEX and USE INDEX sometimes to be ignored.

- Fixed rare core dump problem in complicated GROUP BY queries that didn't return any result.

- Fixed a bug where MATCH ... AGAINST () >=0 was treated as if it was >.

- Fixed core dump in SHOW PROCESSLIST when running with an active slave (unlikely timing bug).

- Make it possible to use multiple MySQL servers on Windows (code backported from 4.0.2).

- One can create TEMPORARY MERGE tables now.

- Fixed that --core-file works on Linux (at least on kernel 2.4.18).

- Fixed a problem with BDB and ALTER TABLE.

- Fixed reference to freed memory when doing complicated GROUP BY ... ORDER BY queries. Symptom was that mysqld died in function send_fields.

- Allocate heap rows in smaller blocks to get better memory usage.

- Fixed memory allocation bug when storing BLOB values in internal temporary tables used for some (unlikely) GROUP BY queries.

- Fixed a bug in key optimizing handling where the expression WHERE column_name = key_column_name was calculated as true for NULL values.

- Fixed core dump bug when doing LEFT JOIN ... WHERE key_column=NULL.

- Fixed MyISAM crash when using dynamic-row tables with huge numbers of packed fields.

- Updated source tree to be built using automake 1.5 and libtool 1.4.

30-D-7 - Changements de la version 3.23.53 (09 octobre 2002)

- Fixed crash when SHOW INNODB STATUS was used and skip-innodb was defined.

- Fixed possible memory corruption bug in binary log file handling when slave rotated the logs (only affected 3.23, not 4.0).

- Fixed problem in LOCK TABLES on Windows when one connects to a database that contains upper case letters.

- Fixed that --skip-show-databases doesn't reset the --port option.

- Small fix in safe_mysqld for some shells.

- Fixed that FLUSH STATUS doesn't reset delayed_insert_threads.

- Fixed core dump bug when using the BINARY cast on a NULL value.

- Fixed race condition when someone did a GRANT at the same time a new user logged in or did a USE database.

- Fixed bug in ALTER TABLE and RENAME TABLE when running with -O lower_case_table_names=1 (typically on Windows) when giving the table name in uppercase.

- Fixed that -O lower_case_table_names=1 also converts database names to lower case.

- Fixed unlikely core dump with SELECT ... ORDER BY ... LIMIT.

- Changed AND/OR to report that they can return NULL. This fixes a bug in GROUP BY on AND/OR expressions that return NULL.

- Fixed a bug that OPTIMIZE of locked and modified MyISAM table, reported table corruption.

- Fixed a BDB-related ALTER TABLE bug with dropping a column and shutting down immediately thereafter.

- Fixed problem with configure ... --localstatedir=....

- Fixed problem with UNSIGNED BIGINT on AIX (again).

- Fixed bug in pthread_mutex_trylock() on HPUX 11.0.

- Multi-threaded stress tests for InnoDB.

30-D-8 - Changements de la version 3.23.52 (14 août 2002)

- Wrap BEGIN/COMMIT around transaction in the binary log. This makes replication honor transactions.

- Fixed security bug when having an empty database name in the user.db table.

- Changed initialization of RND() to make it less predicatable.

- Fixed problem with GROUP BY on result with expression that created a BLOB field.

- Fixed problem with GROUP BY on columns that have NULL values. To solve this we now create an MyISAM temporary table when doing a GROUP BY on a possible NULL item. From MySQL 4.0.5 we can use in memory HEAP tables for this case.

- Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.

- Fixed thread bug in SLAVE START, SLAVE STOP and automatic repair of MyISAM tables that could cause table cache to be corrupted.

- Fixed possible thread related key-cache-corruption problem with OPTIMIZE TABLE and REPAIR TABLE.

- Added name of 'administrator command' logs.

- Fixed bug with creating an auto-increment value on second part of a UNIQUE() key where first part could contain NULL values.

- Don't write slave-timeout reconnects to the error log.

- Fixed bug with slave net read timeouting

- Fixed a core-dump bug with MERGE tables and MAX() function.

- Fixed bug in ALTER TABLE with BDB tables.

- Fixed bug when logging LOAD DATA INFILE to binary log with no active database.

- Fixed a bug in range optimizer (causing crashes).

- Fixed possible problem in replication when doing DROP DATABASE on a database with InnoDB tables.

- Fixed mysql_info() to return 0 for Duplicates value when using INSERT DELAYED IGNORE.

- Added -DHAVE_BROKEN_REALPATH to the Mac OS X (darwin) compile options in configure.in to fix a failure under high load.

30-D-9 - Changements de la version 3.23.51 (31 mai 2002)

- Fix bug with closing tags missing slash for mysqldump XML output.

- Remove end space from ENUM values. (This fixed a problem with SHOW CREATE TABLE.)

- Fixed bug in CONCAT_WS() that cut the result.

- Changed name of server variables Com_show_master_stat to Com_show_master_status and Com_show_slave_stat to Com_show_slave_status.

- Changed handling of gethostbyname() to make the client library thread-safe even if gethostbyname_r doesn't exist.

- Fixed core-dump problem when giving a wrong password string to GRANT.

- Fixed bug in DROP DATABASE with symlinked directory.

- Fixed optimization problem with DATETIME and value outside DATETIME range.

- Removed Sleepycat's BDB doc files from the source tree, as they're not needed (MySQL covers BDB in its own documentation).

- Fixed MIT-pthreads to compile with glibc 2.2 (needed for make dist).

- Fixed the FLOAT(X+1,X) is not converted to FLOAT(X+2,X). (This also affected DECIMAL, DOUBLE and REAL types)

- Fixed the result from IF() is case in-sensitive if the second and third arguments are case sensitive.

- Fixed core dump problem on OSF/1 in gethostbyname_r.

- Fixed that underflowed decimal fields are not zero filled.

- If we get an overflow when inserting '+11111' for DECIMAL(5,0) UNSIGNED columns, we will just drop the sign.

- Fixed optimization bug with ISNULL(expression_which_cannot_be_null) and ISNULL(constant_expression).

- Fixed host lookup bug in the glibc library that we used with the 3.23.50 Linux-x86 binaries.

30-D-10 - Changements de la version 3.23.50 (21 avril 2002)

- Fixed buffer overflow problem if someone specified a too long datadir parameter to mysqld

- Add missing <row> tags for mysqldump XML output.

- Fixed problem with crash-me and gcc 3.0.4.

- Fixed that @@unknown_variable doesn't hang server.

- Added @@VERSION as a synonym for VERSION().

- SHOW VARIABLES LIKE 'xxx' is now case-insensitive.

- Fixed timeout for GET_LOCK() on HP-UX with DCE threads.

- Fixed memory allocation bug in the glibc library used to build Linux binaries, which caused mysqld to die in 'free()'.

- Fixed SIGINT and SIGQUIT problems in mysql.

- Fixed bug in character table converts when used with big ( > 64K) strings.

- InnoDB now retains foreign key constraints through ALTER TABLE and CREATE/DROP INDEX.

- InnoDB now allows foreign key constraints to be added through the ALTER TABLE syntax.

- InnoDB tables can now be set to automatically grow in size (autoextend).

- Our Linux RPMS and binaries are now compiled with gcc 3.0.4, which should make them a bit faster.

- Fixed some buffer overflow problems when reading startup parameters.

- Because of problems on shutdown we have now disabled named pipes on Windows by default. One can enable named pipes by starting mysqld with --enable-named-pipe.

- Fixed bug when using WHERE key_column = 'J' or key_column='j'.

- Fixed core-dump bug when using --log-bin with LOAD DATA INFILE without an active database.

- Fixed bug in RENAME TABLE when used with lower_case_table_names=1 (default on Windows).

- Fixed unlikely core-dump bug when using DROP TABLE on a table that was in use by a thread that also used queries on only temporary tables.

- Fixed problem with SHOW CREATE TABLE and PRIMARY KEY when using 32 indexes.

- Fixed that one can use SET PASSWORD for the anonymous user.

- Fixed core dump bug when reading client groups from option files using mysql_options().

- Memory leak (16 bytes per every corrupted table) closed.

- Fixed binary builds to use --enable-local-infile.

- Update source to work with new version of bison.

- Updated shell scripts to now agree with new POSIX standard.

- Fixed bug where DATE_FORMAT() returned empty string when used with GROUP BY.

30-D-11 - Changements de la version 3.23.49

- For a MERGE table, DELETE FROM merge_table used without a WHERE clause no longer clears the mapping for the table by emptying the .MRG file. Instead, it deletes records from the mapped tables.

- Don't give warning for a statement that is only a comment; this is needed for mysqldump --disable-keys to work.

- Fixed unlikely caching bug when doing a join without keys. In this case, the last used field for a table always returned NULL.

- Added options to make LOAD DATA LOCAL INFILE more secure.

- MySQL binary release 3.23.48 for Linux contained a new glibc library, which has serious problems under high load and Red Hat 7.2. The 3.23.49 binary release doesn't have this problem.

- Fixed shutdown problem on NT.

30-D-12 - Changements de la version 3.23.48 (07 février 2002)

- Added --xml option to mysqldump for producing XML output.

- Changed to use autoconf 2.52 (from autoconf 2.13)

- Fixed bug in complicated join with const tables.

- Added internal safety checks for InnoDB.

- Some InnoDB variables were always shown in SHOW VARIABLES as OFF on high-byte-first systems (like SPARC).

- Fixed problem with one thread using an InnoDB table and another thread doing an ALTER TABLE on the same table. Before that, mysqld could crash with an assertion failure in row0row.c, line 474.

- Tuned the InnoDB SQL optimizer to favor index searches more often over table scans.

- Fixed a performance problem with InnoDB tables when several large SELECT queries are run concurrently on a multiprocessor Linux computer. Large CPU-bound SELECT queries will now also generally run faster on all platforms.

- If MySQL binlogging is used, InnoDB now prints after crash recovery the latest MySQL binlog name and the offset InnoDB was able to recover to. This is useful, for example, when resynchronizing a master and a slave database in replication.

- Added better error messages to help in installation problems of InnoDB tables.

- It is now possible to recover MySQL temporary tables that have become orphaned inside the InnoDB tablespace.

- InnoDB now prevents a FOREIGN KEY declaration where the signedness is not the same in the referencing and referenced integer columns.

- Calling SHOW CREATE TABLE or SHOW TABLE STATUS could cause memory corruption and make mysqld crash. Especially at risk was mysqldump, because it frequently calls SHOW CREATE TABLE.

- If inserts to several tables containing an AUTO_INCREMENT column were wrapped inside one LOCK TABLES, InnoDB asserted in lock0lock.c.

- In 3.23.47 we allowed several NULL values in a UNIQUE secondary index for an InnoDB table. But CHECK TABLE was not relaxed: it reports the table as corrupt. CHECK TABLE no longer complains in this situation.

- SHOW GRANTS now shows REFERENCES instead of REFERENCE.

30-D-13 - Changements de la version 3.23.47 (27 décembre 2001)

- Fixed bug when using the following construct: SELECT ... WHERE key=@var_name OR key=@var_name2

- Restrict InnoDB keys to 500 bytes.

- InnoDB now supports NULL in keys.

- Fixed shutdown problem on HP-UX. (Introduced in 3.23.46)

- Fixed core dump bug in replication when using SELECT RELEASE_LOCK().

- Added new command: DO expression,[expression]

- Added slave-skip-errors option.

- Added statistics variables for all MySQL commands. (SHOW STATUS is now much longer.)

- Fixed default values for InnoDB tables.

- Fixed that GROUP BY expr DESC works.

- Fixed bug when using t1 LEFT JOIN t2 ON t2.key=constant.

- mysql_config now also works with binary (relocated) distributions.

30-D-14 - Changements de la version 3.23.46 (29 novembre 2001)

- Fixed problem with aliased temporary table replication.

- InnoDB and BDB tables will now use index when doing an ORDER BY on the whole table.

- Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables.

- One can now kill ANALYZE, REPAIR, and OPTIMIZE TABLE when the thread is waiting to get a lock on the table.

- Fixed race condition in ANALYZE TABLE.

- Fixed bug when joining with caching (unlikely to happen).

- Fixed race condition when using the binary log and INSERT DELAYED which could cause the binary log to have rows that were not yet written to MyISAM tables.

- Changed caching of binary log to make replication slightly faster.

- Fixed bug in replication on Mac OS X.

30-D-15 - Changements de la version 3.23.45 (22 novembre 2001)

- (UPDATE|DELETE) ...WHERE MATCH bugfix.

- shutdown should now work on Darwin (Mac OS X).

- Fixed core dump when repairing corrupted packed MyISAM files.

- --core-file now works on Solaris.

- Fix a bug which could cause InnoDB to complain if it cannot find free blocks from the buffer cache during recovery.

- Fixed bug in InnoDB insert buffer B-tree handling that could cause crashes.

- Fixed bug in InnoDB lock timeout handling.

- Fixed core dump bug in ALTER TABLE on a TEMPORARY InnoDB table.

- Fixed bug in OPTIMIZE TABLE that reset index cardinality if it was up to date.

- Fixed problem with t1 LEFT_JOIN t2 ... WHERE t2.date_column IS NULL when date_column was declared as NOT NULL.

- Fixed bug with BDB tables and keys on BLOB columns.

- Fixed bug in MERGE tables on OS with 32-bit file pointers.

- Fixed bug in TIME_TO_SEC() when using negative values.

30-D-16 - Changements de la version 3.23.44 (31 octobre 2001)

- Fixed Rows_examined count in slow query log.

- Fixed bug when using a reference to an AVG() column in HAVING.

- Fixed that date functions that require correct dates, like DAYOFYEAR(column), will return NULL for 0000-00-00 dates.

- Fixed bug in const-propagation when comparing columns of different types. (SELECT * FROM date_col="2001-01-01" and date_col=time_col)

- Fixed bug that caused error message Can't write, because of unique constraint with some GROUP BY queries.

- Fixed problem with sjis character strings used within quoted table names.

- Fixed core dump when using CREATE ... FULLTEXT keys with other storage engines than MyISAM.

- Don't use signal() on Windows because this appears to not be 100% reliable.

- Fixed bug when doing WHERE col_name=NULL on an indexed column that had NULL values.

- Fixed bug when doing LEFT JOIN ... ON (col_name = constant) WHERE col_name = constant.

- When using replications, aborted queries that contained % could cause a core dump.

- TCP_NODELAY was not used on some systems. (Speed problem.)

- Applied portability fixes for OS/2. (Patch by Yuri Dario.)

The following changes are for InnoDB tables:

- Add missing InnoDB variables to SHOW VARIABLES.

- Foreign keys checking is now done for InnoDB tables.

- DROP DATABASE now works also for InnoDB tables.

- InnoDB now supports datafiles and raw disk partitions bigger than 4 GB on those operating systems that have big files.

- InnoDB calculates better table cardinality estimates for the MySQL optimizer.

- Accent characters in the default character set latin1 are ordered according to the MySQL ordering.
Note: if you are using latin1 and have inserted characters whose code is greater than 127 into an indexed CHAR column, you should run CHECK TABLE on your table when you upgrade to 3.23.44, and drop and reimport the table if CHECK TABLE reports an error!

- A new my.cnf parameter, innodb_thread_concurrency, helps in performance tuning in heavily concurrent environments.

- A new my.cnf parameter, innodb_fast_shutdown, speeds up server shutdown.

- A new my.cnf parameter, innodb_force_recovery, helps to save your data in case the disk image of the database becomes corrupt.

- innodb_monitor has been improved and a new innodb_table_monitor added.

- Increased maximum key length from 500 to 7000 bytes.

- Fixed a bug in replication of AUTO_INCREMENT columns with multiple-line inserts.

- Fixed a bug when the case of letters changes in an update of an indexed secondary column.

- Fixed a hang when there are > 24 datafiles.

- Fixed a crash when MAX(col) is selected from an empty table, and col is not the first column in a multi-column index.

- Fixed a bug in purge which could cause crashes.

30-D-17 - Changements de la version 3.23.43 (04 octobre 2001)

- Fixed a bug in INSERT DELAYED and FLUSH TABLES introduced in 3.23.42.

- Fixed unlikely bug, which returned non-matching rows, in SELECT with many tables and multi-column indexes and 'range' type.

- Fixed an unlikely core dump bug when doing EXPLAIN SELECT when using many tables and ORDER BY.

- Fixed bug in LOAD DATA FROM MASTER when using table with CHECKSUM=1.

- Added unique error message when one gets a DEADLOCK during a transaction with BDB tables.

- Fixed problem with BDB tables and UNIQUE columns defined as NULL.

- Fixed problem with myisampack when using pre-space filled CHAR columns.

- Applied patch from Yuri Dario for OS/2.

- Fixed bug in --safe-user-create.

30-D-18 - Changements de la version 3.23.42 (08 septembre 2001)

- Fixed problem when using LOCK TABLES and BDB tables.

- Fixed problem with REPAIR TABLE on MyISAM tables with row lengths in the range from 65517 to 65520 bytes.

- Fixed rare hang when doing mysqladmin shutdown when there was a lot of activity in other threads.

- Fixed problem with INSERT DELAYED where delayed thread could be hanging on upgrading locks for no apparent reason.

- Fixed problem with myisampack and BLOB.

- Fixed problem when one edited .MRG tables by hand. (Patch from Benjamin Pflugmann).

- Enforce that all tables in a MERGE table come from the same database.

- Fixed bug with LOAD DATA INFILE and transactional tables.

- Fix bug when using INSERT DELAYED with wrong column definition.

- Fixed core dump during REPAIR of some particularly broken tables.

- Fixed bug in InnoDB and AUTO_INCREMENT columns.

- Fixed bug in InnoDB and RENAME TABLE columns.

- Fixed critical bug in InnoDB and BLOB columns. If you have used BLOB columns larger than 8000 bytes in an InnoDB table, it is necessary to dump the table with mysqldump, drop it and restore it from the dump.

- Applied large patch for OS/2 from Yuri Dario.

- Fixed problem with InnoDB when one could get the error Can't execute the given command... even when no transaction was active.

- Applied some minor fixes that concern Gemini.

- Use real arithmetic operations even in integer context if not all arguments are integers. (Fixes uncommon bug in some integer contexts).

- Don't force everything to lowercase on Windows. (To fix problem with Windows and ALTER TABLE). Now --lower_case_names also works on Unix.

- Fixed that automatic rollback is done when thread end doesn't lock other threads.

30-D-19 - Changements de la version 3.23.41 (11 août 2001)

- Added --sql-mode=value[,value[,value]] option to mysqld. Voir Section 4.3.1, « Options de ligne de commande de mysqld ».

- Fixed possible problem with shutdown on Solaris where the .pid file wasn't deleted.

- InnoDB now supports < 4 GB rows. The former limit was 8000 bytes.

- The doublewrite file flush method is used in InnoDB. It reduces the need for Unix fsync() calls to a fraction and improves performance on most Unix flavors.

- You can now use the InnoDB Monitor to print a lot of InnoDB state information, including locks, to the standard output. This is useful in performance tuning.

- Several bugs which could cause hangs in InnoDB have been fixed.

- Split record_buffer to record_buffer and record_rnd_buffer. To make things compatible to previous MySQL versions, if record_rnd_buffer is not set, then it takes the value of record_buffer.

- Fixed optimizing bug in ORDER BY where some ORDER BY parts where wrongly removed.

- Fixed overflow bug with ALTER TABLE and MERGE tables.

- Added prototypes for my_thread_init() and my_thread_end() to mysql_com.h

- Added --safe-user-create option to mysqld.

- Fixed bug in SELECT DISTINCT ... HAVING that caused error message Can't find record in #...

30-D-20 - Changements de la version 3.23.40

- Fixed problem with --low-priority-updates and INSERT statements.

- Fixed bug in slave thread when under some rare circumstances it could get 22 bytes ahead on the offset in the master.

- Added slave_net_timeout for replication.

- Fixed problem with UPDATE and BDB tables.

- Fixed hard bug in BDB tables when using key parts.

- Fixed problem when using GRANT FILE ON database.* ...; previously we added the DROP privilege for the database.

- Fixed DELETE FROM tbl_name ... LIMIT 0 and UPDATE FROM tbl_name ... LIMIT 0, which acted as though the LIMIT clause was not present (they deleted or updated all selected rows).

- CHECK TABLE now checks if an AUTO_INCREMENT column contains the value 0.

- Sending a SIGHUP to mysqld will now only flush the logs, not reset the replication.

- Fixed parser to allow floats of type 1.0e1 (no sign after e).

- Option --force to myisamchk now also updates states.

- Added option --warnings to mysqld. Now mysqld prints the error Aborted connection only if this option is used.

- Fixed problem with SHOW CREATE TABLE when you didn't have a PRIMARY KEY.

- Properly fixed the rename of innodb_unix_file_flush_method variable to innodb_flush_method.

- Fixed bug when converting BIGINT UNSIGNED to DOUBLE. This caused a problem when doing comparisons with BIGINT values outside of the signed range.

- Fixed bug in BDB tables when querying empty tables.

- Fixed a bug when using COUNT(DISTINCT) with LEFT JOIN and there weren't any matching rows.

- Removed all documentation referring to the GEMINI table type. GEMINI is not released under an Open Source license.

30-D-21 - Changements de la version 3.23.39 (12 juin 2001)

- The AUTO_INCREMENT sequence wasn't reset when dropping and adding an AUTO_INCREMENT column.

- CREATE ... SELECT now creates non-unique indexes delayed.

- Fixed problem where LOCK TABLES tbl_name READ followed by FLUSH TABLES put an exclusive lock on the table.

- REAL @variable values were represented with only 2 digits when converted to strings.

- Fixed problem that client « hung » when LOAD TABLE FROM MASTER failed.

- myisamchk --fast --force will no longer repair tables that only had the open count wrong.

- Added functions to handle symbolic links to make life easier in 4.0.

- We are now using the -lcma thread library on HP-UX 10.20 so that MySQL will be more stable on HP-UX.

- Fixed problem with IF() and number of decimals in the result.

- Fixed date-part extraction functions to work with dates where day and/or month is 0.

- Extended argument length in option files from 256 to 512 chars.

- Fixed problem with shutdown when INSERT DELAYED was waiting for a LOCK TABLE.

- Fixed core dump bug in InnoDB when tablespace was full.

- Fixed problem with MERGE tables and big tables (> 4G) when using ORDER BY.

30-D-22 - Changements de la version 3.23.38 (09 mai 2001)

- Fixed a bug when SELECT from MERGE table sometimes results in incorrectly ordered rows.

- Fixed a bug in REPLACE() when using the ujis character set.

- Applied Sleepycat BDB patches 3.2.9.1 and 3.2.9.2.

- Added --skip-stack-trace option to mysqld.

- CREATE TEMPORARY now works with InnoDB tables.

- InnoDB now promotes sub keys to whole keys.

- Added option CONCURRENT to LOAD DATA.

- Better error message when slave max_allowed_packet is too low to read a very long log event from the master.

- Fixed bug when too many rows where removed when using SELECT DISTINCT ... HAVING.

- SHOW CREATE TABLE now returns TEMPORARY for temporary tables.

- Added Rows_examined to slow query log.

- Fixed problems with function returning empty string when used together with a group function and a WHERE that didn't match any rows.

- New program mysqlcheck.

- Added database name to output for administrative commands like CHECK, REPAIR, OPTIMIZE.

- Lots of portability fixes for InnoDB.

- Changed optimizer so that queries like SELECT * FROM tbl_name,tbl_name2 ... ORDER BY key_part1 LIMIT row_count will use index on key_part1 instead of filesort.

- Fixed bug when doing LOCK TABLE to_table WRITE,...; INSERT INTO to_table... SELECT ... when to_table was empty.

- Fixed bug with LOCK TABLE and BDB tables.

30-D-23 - Changements de la version 3.23.37 (17 avril 2001)

- Fixed a bug when using MATCH() in HAVING clause.

- Fixed a bug when using HEAP tables with LIKE.

- Added --mysql-version option to safe_mysqld

- Changed INNOBASE to InnoDB (because the INNOBASE name was already used). All configure options and mysqld start options now use innodb instead of innobase. This means that before upgrading to this version, you have to change any configuration files where you have used innobase options!

- Fixed bug when using indexes on CHAR(255) NULL columns.

- Slave thread will now be started even if master-host is not set, as long as server-id is set and valid master.info is present.

- Partial updates (terminated with kill) are now logged with a special error code to the binary log. Slave will refuse to execute them if the error code indicates the update was terminated abnormally, and will have to be recovered with SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START after a manual sanity check/correction of data integrity.

- Fixed bug that erroneously logged a drop of internal temporary table on thread termination to the binary log --- this bug affected replication.

- Fixed a bug in REGEXP on 64-bit machines.

- UPDATE and DELETE with WHERE unique_key_part IS NULL didn't update/delete all rows.

- Disabled INSERT DELAYED for tables that support transactions.

- Fixed bug when using date functions on TEXT/BLOB column with wrong date format.

- UDFs now also work on Windows. (Patch by Ralph Mason.)

- Fixed bug in ALTER TABLE and LOAD DATA INFILE that disabled key-sorting. These commands should now be faster in most cases.

- Fixed performance bug where reopened tables (tables that had been waiting for FLUSH or REPAIR) would not use indexes for the next query.

- Fixed problem with ALTER TABLE to InnoDB tables on FreeBSD.

- Added mysqld variables myisam_max_sort_file_size and myisam_max_extra_sort_file_size.

- Initialize signals early to avoid problem with signals in InnoDB.

- Applied patch for the tis620 character set to make comparisons case-independent and to fix a bug in LIKE for this character set. Note: All tables that uses the tis620 character set must be fixed with myisamchk -r or REPAIR TABLE !

- Added --skip-safemalloc option to mysqld.

30-D-24 - Changements de la version 3.23.36 (27 mars 2001)

- Fixed a bug that allowed use of database names containing a '.' character. This fixes a serious security issue when mysqld is run as root.

- Fixed bug when thread creation failed (could happen when doing a lot of connections in a short time).

- Fixed some problems with FLUSH TABLES and TEMPORARY tables. (Problem with freeing the key cache and error Can't reopen table....)

- Fixed a problem in InnoDB with other character sets than latin1 and another problem when using many columns.

- Fixed bug that caused a core dump when using a very complex query involving DISTINCT and summary functions.

- Added SET TRANSACTION ISOLATION LEVEL ...

- Added SELECT ... FOR UPDATE.

- Fixed bug where the number of affected rows was not returned when MySQL was compiled without transaction support.

- Fixed a bug in UPDATE where keys weren't always used to find the rows to be updated.

- Fixed a bug in CONCAT_WS() where it returned incorrect results.

- Changed CREATE ... SELECT and INSERT ... SELECT to not allow concurrent inserts as this could make the binary log hard to repeat. (Concurrent inserts are enabled if you are not using the binary or update log.)

- Changed some macros to be able to use fast mutex with glibc 2.2.

30-D-25 - Changements de la version 3.23.35 (15 mars 2001)

- Fixed newly introduced bug in ORDER BY.

- Fixed wrong define CLIENT_TRANSACTIONS.

- Fixed bug in SHOW VARIABLES when using INNOBASE tables.

- Setting and using user variables in SELECT DISTINCT didn't work.

- Tuned SHOW ANALYZE for small tables.

- Fixed handling of arguments in the benchmark script run-all-tests.

30-D-26 - Changements de la version 3.23.34a

- Added extra files to the distribution to allow INNOBASE support to be compiled.

30-D-27 - Changements de la version 3.23.34 (10 mars 2001)

- Added the INNOBASE storage engine and the BDB storage engine to the MySQL source distribution.

- Updated the documentation about GEMINI tables.

- Fixed a bug in INSERT DELAYED that caused threads to hang when inserting NULL into an AUTO_INCREMENT column.

- Fixed a bug in CHECK TABLE / REPAIR TABLE that could cause a thread to hang.

- REPLACE will not replace a row that conflicts with an AUTO_INCREMENT generated key.

- mysqld now only sets CLIENT_TRANSACTIONS in mysql->server_capabilities if the server supports a transaction-safe storage engine.

- Fixed LOAD DATA INFILE to allow numeric values to be read into ENUM and SET columns.

- Improved error diagnostic for slave thread exit.

- Fixed bug in ALTER TABLE ... ORDER BY.

- Added max_user_connections variable to mysqld.

- Limit query length for replication by max_allowed_packet, not the arbitrary limit of 4 MB.

- Allow space around = in argument to --set-variable.

- Fixed problem in automatic repair that could leave some threads in state Waiting for table.

- SHOW CREATE TABLE now displays the UNION=() for MERGE tables.

- ALTER TABLE now remembers the old UNION=() definition.

- Fixed bug when replicating timestamps.

- Fixed bug in bidirectional replication.

- Fixed bug in the BDB storage engine that occurred when using an index on multi-part key where a key part may be NULL.

- Fixed MAX() optimization on sub-key for BDB tables.

- Fixed problem where garbage results were returned when using BDB tables and BLOB or TEXT fields when joining many tables.

- Fixed a problem with BDB tables and TEXT columns.

- Fixed bug when using a BLOB key where a const row wasn't found.

- Fixed that mysqlbinlog writes the timestamp value for each query. This ensures that one gets same values for date functions like NOW() when using mysqlbinlog to pipe the queries to another server.

- Allow --skip-gemini, --skip-bdb, and --skip-innodb options to be specified when invoking mysqld, even if these storage engines are not compiled in to mysqld.

- One can now do GROUP BY ... DESC.

- Fixed a deadlock in the SET code, when one ran SET @foo=bar, where bar is a column reference, an error was not properly generated.

30-D-28 - Changements de la version 3.23.33 (09 février 2001)

- Fixed DNS lookups not to use the same mutex as the hostname cache. This will enable known hosts to be quickly resolved even if a DNS lookup takes a long time.

- Added --character-sets-dir option to myisampack.

- Removed warnings when running REPAIR TABLE ... EXTENDED.

- Fixed a bug that caused a core dump when using GROUP BY on an alias, where the alias was the same as an existing column name.

- Added SEQUENCE() as an example UDF function.

- Changed mysql_install_db to use BINARY for CHAR columns in the privilege tables.

- Changed TRUNCATE tbl_name to TRUNCATE TABLE tbl_name to use the same syntax as Oracle. Until 4.0 we will also allow TRUNCATE tbl_name to not crash old code.

- Fixed « no found rows » bug in MyISAM tables when a BLOB was first part of a multi-part key.

- Fixed bug where CASE didn't work with GROUP BY.

- Added --sort-recover option to myisamchk.

- myisamchk -S and OPTIMIZE TABLE now work on Windows.

- Fixed bug when using DISTINCT on results from functions that referred to a group function, like:

SELECT a, DISTINCT SEC_TO_TIME(SUM(a))
FROM tbl_name GROUP BY a, b;

- Fixed buffer overrun in libmysqlclient library. Fixed bug in handling STOP event after ROTATE event in replication.

- Fixed another buffer overrun in DROP DATABASE.

- Added Table_locks_immediate and Table_locks_waited status variables.

- Fixed bug in replication that broke slave server start with existing master.info. This fixes a bug introduced in 3.23.32.

- Added SET SQL_SLAVE_SKIP_COUNTER=n command to recover from replication glitches without a full database copy.

- Added max_binlog_size variable; the binary log will be rotated automatically when the size crosses the limit.

- Added Last_Error, Last_Errno, and Slave_skip_counter variables to SHOW SLAVE STATUS.

- Fixed bug in MASTER_POS_WAIT() function.

- Execute core dump handler on SIGILL, and SIGBUS in addition to SIGSEGV.

- On x86 Linux, print the current query and thread (connection) id, if available, in the core dump handler.

- Fixed several timing bugs in the test suite.

- Extended mysqltest to take care of the timing issues in the test suite.

- ALTER TABLE can now be used to change the definition for a MERGE table.

- Fixed creation of MERGE tables on Windows.

- Portability fixes for OpenBSD and OS/2.

- Added --temp-pool option to mysqld. Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file. This is to work around a problem in the Linux kernel dealing with creating a bunch of new files with different names. With the old behavior, Linux Voirms to "leak" memory, as it's being allocated to the directory entry cache instead of the disk cache.

30-D-29 - Changements de la version 3.23.32 (22 Jan 2001: Production)

- Changed code to get around compiler bug in Compaq C++ on OSF/1, that broke BACKUP, RESTORE, CHECK, REPAIR, and ANALYZE TABLE.

- Added option FULL to SHOW COLUMNS. Now we show the privilege list for the columns only if this option is given.

- Fixed bug in SHOW LOGS when there weren't any BDB logs.

- Fixed a timing problem in replication that could delay sending an update to the client until a new update was done.

- Don't convert field names when using mysql_list_fields(). This is to keep this code compatible with SHOW FIELDS.

- MERGE tables didn't work on Windows.

- Fixed problem with SET PASSWORD=... on Windows.

- Added missing my_config.h to RPM distribution.

- TRIM("foo" from "foo") didn't return an empty string.

- Added --with-version-suffix option to configure.

- Fixed core dump when client aborted connection without mysql_close().

- Fixed a bug in RESTORE TABLE when trying to restore from a non-existent directory.

- Fixed a bug which caused a core dump on the slave when replicating SET PASSWORD.

- Added MASTER_POS_WAIT().

30-D-30 - Changements de la version 3.23.31 (17 janvier 2001)

- The test suite now tests all reachable BDB interface code. During testing we found and fixed many errors in the interface code.

- Using HAVING on an empty table could produce one result row when it shouldn't.

- Fixed the MySQL RPM so it no longer depends on Perl5.

- Fixed some problems with HEAP tables on Windows.

- SHOW TABLE STATUS didn't show correct average row length for tables larger than 4G.

- CHECK TABLE ... EXTENDED didn't check row links for fixed size tables.

- Added option MEDIUM to CHECK TABLE.

- Fixed problem when using DECIMAL() keys on negative numbers.

- HOUR() (and some other TIME functions) on a CHAR column always returned NULL.

- Fixed security bug in something (please upgrade if you are using an earlier MySQL 3.23 version).

- Fixed buffer overflow bug when writing a certain error message.

- Added usage of setrlimit() on Linux to get -O --open-files-limit=# to work on Linux.

- Added bdb_version variable to mysqld.

- Fixed bug when using expression of type:

SELECT ... FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=t2.a

In this case the test in the WHERE clause was wrongly optimized away.

- Fixed bug in MyISAM when deleting keys with possible NULL values, but the first key-column was not a prefix-compressed text column.

- Fixed mysql.server to read the [mysql.server] option file group rather than the [mysql_server] group.

- Fixed safe_mysqld and mysql.server to also read the server option section.

- Added Threads_created status variable to mysqld.

30-D-31 - Changements de la version 3.23.30 (04 janvier 2001)

- Added SHOW OPEN TABLES command.

- Fixed that myisamdump works against old mysqld servers.

- Fixed myisamchk -k# so that it works again.

- Fixed a problem with replication when the binary log file went over 2G on 32-bit systems.

- LOCK TABLES will now automatically start a new transaction.

- Changed BDB tables to not use internal subtransactions and reuse open files to get more speed.

- Added --mysqld=# option to safe_mysqld.

- Allow hex constants in the --fields-*-by and --lines-terminated-by options to mysqldump and mysqlimport. By Paul DuBois.

- Added --safe-show-database option to mysqld.

- Added have_bdb, have_gemini, have_innobase, have_raid and have_openssl to SHOW VARIABLES to make it easy to test for supported extensions.

- Added --open-files-limit option to mysqld.

- Changed --open-files option to --open-files-limit in safe_mysqld.

- Fixed a bug where some rows were not found with HEAP tables that had many keys.

- Fixed that --bdb-no-sync works.

- Changed --bdb-recover to --bdb-no-recover as recover should be on by default.

- Changed the default number of BDB locks to 10000.

- Fixed a bug from 3.23.29 when allocating the shared structure needed for BDB tables.

- Changed mysqld_multi.sh to use configure variables. Patch by Christopher McCrory.

- Added fixing of include files for Solaris 2.8.

- Fixed bug with --skip-networking on Debian Linux.

- Fixed problem that some temporary files where reported as having the name UNOPENED in error messages.

- Fixed bug when running two simultaneous SHOW LOGS queries.

30-D-32 - Changements de la version 3.23.29 (16 décembre 2000)

- Configure updates for Tru64, large file support, and better TCP wrapper support. By Albert Chin-A-Young.

- Fixed bug in <=> operator.

- Fixed bug in REPLACE with BDB tables.

- LPAD() and RPAD() will shorten the result string if it's longer than the length argument.

- Added SHOW LOGS command.

- Remove unused BDB logs on shutdown.

- When creating a table, put PRIMARY keys first, followed by UNIQUE keys.

- Fixed a bug in UPDATE involving multi-part keys where one specified all key parts both in the update and the WHERE part. In this case MySQL could try to update a record that didn't match the whole WHERE part.

- Changed drop table to first drop the tables and then the .frm file.

- Fixed a bug in the hostname cache which caused mysqld to report the hostname as '' in some error messages.

- Fixed a bug with HEAP type tables; the variable max_heap_table_size wasn't used. Now either MAX_ROWS or max_heap_table_size can be used to limit the size of a HEAP type table.

- Changed the default server-id to 1 for masters and 2 for slaves to make it easier to use the binary log.

- Renamed bdb_lock_max variable to bdb_max_lock.

- Added support for AUTO_INCREMENT on sub-fields for BDB tables.

- Added ANALYZE of BDB tables.

- In BDB tables, we now store the number of rows; this helps to optimize queries when we need an approximation of the number of rows.

- If we get an error in a multi-row statement, we now only roll back the last statement, not the entire transaction.

- If you do a ROLLBACK when you have updated a non-transactional table you will get an error as a warning.

- Added --bdb-shared-data option to mysqld.

- Added Slave_open_temp_tables status variable to mysqld

- Added binlog_cache_size and max_binlog_cache_size variables to mysqld.

- DROP TABLE, RENAME TABLE, CREATE INDEX and DROP INDEX are now transaction endpoints.

- If you do a DROP DATABASE on a symbolically linked database, both the link and the original database is deleted.

- Fixed DROP DATABASE to work on OS/2.

- Fixed bug when doing a SELECT DISTINCT ... table1 LEFT JOIN table2 ... when table2 was empty.

- Added --abort-slave-event-count and --disconnect-slave-event-count options to mysqld for debugging and testing of replication.

- Fixed replication of temporary tables. Handles everything except slave server restart.

- SHOW KEYS now shows whether key is FULLTEXT.

- New script mysqld_multi. Voir Section 5.1.5, « mysqld_multi, un programme pour gérer plusieurs serveurs MySQL ».

- Added new script, mysql-multi.server.sh. Thanks to Tim Bunce <Tim.Bunce@ig.co.uk> for modifying mysql.server to easily handle hosts running many mysqld processes.

- safe_mysqld, mysql.server, and mysql_install_db have been modified to use mysql_print_defaults instead of various hacks to read the my.cnf files. In addition, the handling of various paths has been made more consistent with how mysqld handles them by default.

- Automatically remove Berkeley DB transaction logs that no longer are in use.

- Fixed bug with several FULLTEXT indexes in one table.

- Added a warning if number of rows changes on REPAIR/OPTIMIZE.

- Applied patches for OS/2 by Yuri Dario.

- FLUSH TABLES tbl_name didn't always flush the index tree to disk properly.

- --bootstrap is now run in a separate thread. This fixes a problem that caused mysql_install_db to core dump on some Linux machines.

- Changed mi_create() to use less stack space.

- Fixed bug with optimizer trying to over-optimize MATCH() when used with UNIQUE key.

- Changed crash-me and the MySQL benchmarks to also work with FrontBase.

- Allow RESTRICT and CASCADE after DROP TABLE to make porting easier.

- Reset status variable which could cause problem if one used --slow-log.

- Added connect_timeout variable to mysql and mysqladmin.

- Added connect-timeout as an alias for timeout for option files read by mysql_options().

30-D-33 - Changements de la version 3.23.28 (22 Nov 2000: Gamma)

- Added new options --pager[=...], --no-pager, --tee=... and --no-tee to the mysql client. The new corresponding interactive commands are pager, nopager, tee and notee. Voir Section 8.3, « mysql, l'outil en ligne de commande », mysql --help and the interactive help for more information.

- Fixed crash when automatic repair of MyISAM table failed.

- Fixed a major performance bug in the table locking code when one constantly had a lot of SELECT, UPDATE and INSERT statements running. The symptom was that the UPDATE and INSERT queries were locked for a long time while new SELECT statements were executed before the updates.

- When reading options_files with mysql_options() the return-found-rows option was ignored.

- One can now specify interactive-timeout in the option file that is read by mysql_options(). This makes it possible to force programs that run for a long time (like mysqlhotcopy) to use the interactive_timeout time instead of the wait_timeout time.

- Added to the slow query log the time and the user name for each logged query. If you are using --log-long-format then also queries that do not use an index are logged, even if the query takes less than long_query_time seconds.

- Fixed a problem in LEFT JOIN which caused all columns in a reference table to be NULL.

- Fixed a problem when using NATURAL JOIN without keys.

- Fixed a bug when using a multi-part keys where the first part was of type TEXT or BLOB.

- DROP of temporary tables wasn't stored in the update/binary log.

- Fixed a bug where SELECT DISTINCT * ... LIMIT row_count only returned one row.

- Fixed a bug in the assembler code in strstr() for SPARC and cleaned up the global.h header file to avoid a problem with bad aliasing with the compiler submitted with Red Hat 7.0. (Reported by Trond Eivind Glomsrød)

- The --skip-networking option now works properly on NT.

- Fixed a long outstanding bug in the ISAM tables when a row with a length of more than 65K was shortened by a single byte.

- Fixed a bug in MyISAM when running multiple updating processes on the same table.

- Allow one to use FLUSH TABLE tbl_name.

- Added --replicate-ignore-table, --replicate-do-table, --replicate-wild-ignore-table, and --replicate-wild-do-table options to mysqld.

- Changed all log files to use our own IO_CACHE mechanism instead of FILE to avoid OS problems when there are many files open.

- Added --open-files and --timezone options to safe_mysqld.

- Fixed a fatal bug in CREATE TEMPORARY TABLE ... SELECT ....

- Fixed a problem with CREATE TABLE ... SELECT NULL.

- Added variables large_file_support,net_read_timeout, net_write_timeout and query_buffer_size to SHOW VARIABLES.

- Added status variables created_tmp_files and sort_merge_passes to SHOW STATUS.

- Fixed a bug where we didn't allow an index name after the FOREIGN KEY definition.

- Added TRUNCATE table_name as a synonym for DELETE FROM table_name.

- Fixed a bug in a BDB key compare function when comparing part keys.

- Added bdb_lock_max variable to mysqld.

- Added more tests to the benchmark suite.

- Fixed an overflow bug in the client code when using overly long database names.

- mysql_connect() now aborts on Linux if the server doesn't answer in timeout seconds.

- SLAVE START did not work if you started with --skip-slave-start and had not explicitly run CHANGE MASTER TO.

- Fixed the output of SHOW MASTER STATUS to be consistent with SHOW SLAVE STATUS. (It now has no directory in the log name.)

- Added PURGE MASTER LOGS TO.

- Added SHOW MASTER LOGS.

- Added --safemalloc-mem-limit option to mysqld to simulate memory shortage when compiled with the --with-debug=full option.

- Fixed several core dumps in out-of-memory conditions.

- SHOW SLAVE STATUS was using an uninitialized mutex if the slave had not been started yet.

- Fixed bug in ELT() and MAKE_SET() when the query used a temporary table.

- CHANGE MASTER TO without specifying MASTER_LOG_POS would set it to 0 instead of 4 and hit the magic number in the master binlog.

- ALTER TABLE ... ORDER BY ... syntax added. This will create the new table with the rows in a specific order.

30-D-34 - Changements de la version 3.23.27 (24 octobre 2000)

- Fixed a bug where the automatic repair of MyISAM tables sometimes failed when the datafile was corrupt.

- Fixed a bug in SHOW CREATE when using AUTO_INCREMENT columns.

- Changed BDB tables to use new compare function in Berkeley DB 3.2.3.

- You can now use Unix sockets with MIT-pthreads.

- Added the latin5 (turkish) character set.

- Small portability fixes.

30-D-35 - Changements de la version 3.23.26 (18 octobre 2000)

- Renamed FLUSH MASTER and FLUSH SLAVE to RESET MASTER and RESET SLAVE.

- Fixed <> to work properly with NULL.

- Fixed a problem with SUBSTRING_INDEX() and REPLACE(). (Patch by Alexander Igonitchev)

- Fix CREATE TEMPORARY TABLE IF NOT EXISTS not to produce an error if the table exists.

- If you don't create a PRIMARY KEY in a BDB table, a hidden PRIMARY KEY will be created.

- Added read-only-key optimization to BDB tables.

- LEFT JOIN in some cases preferred a full table scan when there was no WHERE clause.

- When using --log-slow-queries, don't count the time waiting for a lock.

- Fixed bug in lock code on Windows which could cause the key cache to report that the key file was crashed even if it was okay.

- Automatic repair of MyISAM tables if you start mysqld with --myisam-recover.

- Removed the TYPE= keyword from CHECK and REPAIR. Allow CHECK options to be combined. (You can still use TYPE=, but this usage is deprecated.)

- Fixed mutex bug in the binary replication log --- long update queries could be read only in part by the slave if it did it at the wrong time, which was not fatal, but resulted in a performance-degrading reconnect and a scary message in the error log.

- Changed the format of the binary log --- added magic number, server version, binlog version. Added the server ID and query error code for each query event.

- Replication thread from the slave now will kill all the stale threads from the same server.

- Long replication user names were not being handled properly.

- Added --replicate-rewrite-db option to mysqld.

- Added --skip-slave-start option to mysqld.

- Updates that generated an error code (such as INSERT INTO foo(some_key) values (1),(1)) erroneously terminated the slave thread.

- Added optimization of queries where DISTINCT is only used on columns from some of the tables.

- Allow floating-point numbers where there is no sign after the exponent (like 1e1).

- SHOW GRANTS didn't always show all column grants.

- Added --default-extra-file=# option to all MySQL clients.

- Columns referenced in INSERT statements now are initialized properly.

- UPDATE didn't always work when used with a range on a timestamp that was part of the key that was used to find rows.

- Fixed a bug in FULLTEXT index when inserting a NULL column.

- Changed to use mkstemp() instead of tempnam(). Based on a patch from John Jones.

30-D-36 - Changements de la version 3.23.25 (29 septembre 2000)

- Fixed that databasename works as second argument to mysqlhotcopy.

- The values for the UMASK and UMASK_DIR environment variables now can be specified in octal by beginning the value with a zero.

- Added RIGHT JOIN. This makes RIGHT a reserved word.

- Added @@IDENTITY as a synonym for LAST_INSERT_ID(). (This is for MSSQL compatibility.)

- Fixed a bug in myisamchk and REPAIR when using FULLTEXT index.

- LOAD DATA INFILE now works with FIFOs. (Patch by Toni L. Harbaugh-Blackford.)

- FLUSH LOGS broke replication if you specified a log name with an explicit extension as the value of the log-bin option.

- Fixed a bug in MyISAM with packed multi-part keys.

- Fixed crash when using CHECK TABLE on Windows.

- Fixed a bug where FULLTEXT index always used the koi8_ukr character set.

- Fixed privilege checking for CHECK TABLE.

- The MyISAM repair/reindex code didn't use the --tmpdir option for its temporary files.

- Added BACKUP TABLE and RESTORE TABLE.

- Fixed core dump on CHANGE MASTER TO when the slave did not have the master to start with.

- Fixed incorrect Time in the processlist for Connect of the slave thread.

- The slave now logs when it connects to the master.

- Fixed a core dump bug when doing FLUSH MASTER if you didn't specify a filename argument to --log-bin.

- Added missing ha_berkeley.x files to the MySQL Windows distribution.

- Fixed some mutex bugs in the log code that could cause thread blocks if new log files couldn't be created.

- Added lock time and number of selected processed rows to slow query log.

- Added --memlock option to mysqld to lock mysqld in memory on systems with the mlockall() call (as in Solaris).

- HEAP tables didn't use keys properly. (Bug from 3.23.23.)

- Added better support for MERGE tables (keys, mapping, creation, documentation...). Voir Section 14.2, « Tables assemblées MERGE ».

- Fixed bug in mysqldump from 3.23 which caused some CHAR columns not to be quoted.

- Merged analyze, check, optimize and repair code.

- OPTIMIZE TABLE is now mapped to REPAIR with statistics and sorting of the index tree. This means that for the moment it only works on MyISAM tables.

- Added a pre-alloced block to root_malloc to get fewer mallocs.

- Added a lot of new statistics variables.

- Fixed ORDER BY bug with BDB tables.

- Removed warning that mysqld couldn't remove the .pid file under Windows.

- Changed --log-isam to log MyISAM tables instead of isam tables.

- Fixed CHECK TABLE to work on Windows.

- Added file mutexes to make pwrite() safe on Windows.

30-D-37 - Changements de la version 3.23.24 (08 septembre 2000)

- Added created_tmp_disk_tables variable to mysqld.

- To make it possible to reliably dump and restore tables with TIMESTAMP(X) columns, MySQL now reports columns with X other than 14 or 8 to be strings.

- Changed sort order for latin1 as it was before MySQL Version 3.23.23. Any table that was created or modified with 3.23.22 must be repaired if it has CHAR columns that may contain characters with ASCII values greater than 128!

- Fixed small memory leak introduced from 3.23.22 when creating a temporary table.

- Fixed problem with BDB tables and reading on a unique (not primary) key.

- Restored the win1251 character set (it's now only marked deprecated).

30-D-38 - Changements de la version 3.23.23 (01 septembre 2000)

- Changed sort order for 'German'; all tables created with 'German' sortorder must be repaired with REPAIR TABLE or myisamchk before use!

- Added --core-file option to mysqld to get a core file on Linux if mysqld dies on the SIGSEGV signal.

- MySQL client mysql now starts with option --no-named-commands (-g) by default. This option can be disabled with --enable-named-commands (-G). This may cause incompatibility problems in some cases, for example, in SQL scripts that use named commands without a semicolon, etc.! Long format commands still work from the first line.

- Fixed a problem when using many pending DROP TABLE statements at the same time.

- Optimizer didn't use keys properly when using LEFT JOIN on an empty table.

- Added shorter help text when invoking mysqld with incorrect options.

- Fixed non-fatal free() bug in mysqlimport.

- Fixed bug in MyISAM index handling of DECIMAL/NUMERIC keys.

- Fixed a bug in concurrent insert in MyISAM tables. In some contexts, usage of MIN(key_part) or MAX(key_part) returned an empty set.

- Updated mysqlhotcopy to use the new FLUSH TABLES table_list syntax. Only tables which are being backed up are flushed now.

- Changed behavior of --enable-thread-safe-client so that both non-threaded (-lmysqlclient) and threaded (-lmysqlclient_r) libraries are built. Users who linked against a threaded -lmysqlclient will need to link against -lmysqlclient_r now.

- Added atomic RENAME TABLE command.

- Don't count NULL values in COUNT(DISTINCT ...).

- Changed ALTER TABLE, LOAD DATA INFILE on empty tables and INSERT ... SELECT ... on empty tables to create non-unique indexes in a separate batch with sorting. This will make the above calls much faster when you have many indexes.

- ALTER TABLE now logs the first used insert_id correctly.

- Fixed crash when adding a default value to a BLOB column.

- Fixed a bug with DATE_ADD/DATE_SUB where it returned a datetime instead of a date.

- Fixed a problem with the thread cache which made some threads show up as ***DEAD*** in SHOW PROCESSLIST.

- Fixed a lock in our thr_rwlock code, which could make selects that run at the same time as concurrent inserts crash. This only affects systems that don't have the pthread_rwlock_rdlock code.

- When deleting rows with a non-unique key in a HEAP table, all rows weren't always deleted.

- Fixed bug in range optimizer for HEAP tables for searches on a part index.

- Fixed SELECT on part keys to work with BDB tables.

- Fixed INSERT INTO bdb_table ... SELECT to work with BDB tables.

- CHECK TABLE now updates key statistics for the table.

- ANALYZE TABLE will now only update tables that have been changed since the last ANALYZE. Note that this is a new feature and tables will not be marked to be analysed until they are updated in any way with 3.23.23 or newer. For older tables, you have to do CHECK TABLE to update the key distribution.

- Fixed some minor privilege problems with CHECK, ANALYZE, REPAIR and SHOW CREATE commands.

- Added CHANGE MASTER TO statement.

- Added FAST, QUICK EXTENDED check types to CHECK TABLES.

- Changed myisamchk so that --fast and --check-only-changed are also honored with --sort-index and --analyze.

- Fixed fatal bug in LOAD TABLE FROM MASTER that did not lock the table during index re-build.

- LOAD DATA INFILE broke replication if the database was excluded from replication.

- More variables in SHOW SLAVE STATUS and SHOW MASTER STATUS.

- SLAVE STOP now will not return until the slave thread actually exits.

- Full-text search via the MATCH() function and FULLTEXT index type (for MyISAM files). This makes FULLTEXT a reserved word.

30-D-39 - Changements de la version 3.23.22 (31 juillet 2000)

- Fixed that lex_hash.h is created properly for each MySQL distribution.

- Fixed that MASTER and COLLECTION are not reserved words.

- The log generated by --slow-query-log didn't contain the whole queries.

- Fixed that open transactions in BDB tables are rolled back if the connection is closed unexpectedly.

- Added workaround for a bug in gcc 2.96 (intel) and gcc 2.9 (IA-64) in gen_lex_hash.c.

- Fixed memory leak in the client library when using host= in the my.cnf file.

- Optimized functions that manipulate the hours/minutes/seconds.

- Fixed bug when comparing the result of DATE_ADD()/DATE_SUB() against a number.

- Changed the meaning of -F, --fast for myisamchk. Added -C, --check-only-changed option to myisamchk.

- Added ANALYZE tbl_name to update key statistics for tables.

- Changed binary items 0x... to be regarded as integers by default.

- Fix for SCO and SHOW PROCESSLIST.

- Added auto-rehash on reconnect for the mysql client.

- Fixed a newly introduced bug in MyISAM, where the index file couldn't get bigger than 64M.

- Added SHOW MASTER STATUS and SHOW SLAVE STATUS.

30-D-40 - Changements de la version 3.23.21

- Added mysql_character_set_name() function to the MySQL C API.

- Made the update log ASCII 0 safe.

- Added the mysql_config script.

- Fixed problem when using < or > with a char column that was only partly indexed.

- One would get a core dump if the log file was not readable by the MySQL user.

- Changed mysqladmin to use CREATE DATABASE and DROP DATABASE statements instead of the old deprecated API calls.

- Fixed chown warning in safe_mysqld.

- Fixed a bug in ORDER BY that was introduced in 3.23.19.

- Only optimize the DELETE FROM tbl_name to do a drop+create of the table if we are in AUTOCOMMIT mode (needed for BDB tables).

- Added extra checks to avoid index corruption when the ISAM/MyISAM index files get full during an INSERT/UPDATE.

- myisamchk didn't correctly update row checksum when used with -ro (this only gave a warning in subsequent runs).

- Fixed bug in REPAIR TABLE so that it works with tables without indexes.

- Fixed buffer overrun in DROP DATABASE.

- LOAD TABLE FROM MASTER is sufficiently bug-free to announce it as a feature.

- MATCH and AGAINST are now reserved words.

30-D-41 - Changements de la version 3.23.20

- Fixed bug in 3.23.19; DELETE FROM tbl_name removed the .frm file.

- Added SHOW CREATE TABLE.

30-D-42 - Changements de la version 3.23.19

- Changed copyright for all files to GPL for the server code and utilities and to LGPL for the client libraries. Voir http://www.fsf.org/licenses/.

- Fixed bug where all rows matching weren't updated on a MyISAM table when doing update based on key on a table with many keys and some key changed values.

- The Linux MySQL RPMs and binaries are now statically linked with a linuxthread version that has faster mutex handling when used with MySQL.

- ORDER BY can now use REF keys to find subsets of the rows that need to be sorted.

- Changed name of print_defaults program to my_print_defaults to avoid name confusion.

- Fixed NULLIF() to work as required by standard SQL.

- Added net_read_timeout and net_write_timeout as startup parameters to mysqld.

- Fixed bug that destroyed index when doing myisamchk --sort-records on a table with prefix compressed index.

- Added pack_isam and myisampack to the standard MySQL distribution.

- Added the syntax BEGIN WORK (the same as BEGIN).

- Fixed core dump bug when using ORDER BY on a CONV() expression.

- Added LOAD TABLE FROM MASTER.

- Added FLUSH MASTER and FLUSH SLAVE.

- Fixed big/little endian problem in the replication.

30-D-43 - Changements de la version 3.23.18

- Fixed a problem from 3.23.17 when choosing character set on the client side.

- Added FLUSH TABLES WITH READ LOCK to make a global lock suitable for making a copy of MySQL datafiles.

- CREATE TABLE ... SELECT ... PROCEDURE now works.

- Internal temporary tables will now use compressed index when using GROUP BY on VARCHAR/CHAR columns.

- Fixed a problem when locking the same table with both a READ and a WRITE lock.

- Fixed problem with myisamchk and RAID tables.

30-D-44 - Changements de la version 3.23.17

- Fixed a bug in FIND_IN_SET() when the first argument was NULL.

- Added table locks to Berkeley DB.

- Fixed a bug with LEFT JOIN and ORDER BY where the first table had only one matching row.

- Added 4 sample my.cnf example files in the support-files directory.

- Fixed duplicated key problem when doing big GROUP BY operations. (This bug was probably introduced in 3.23.15.)

- Changed syntax for INNER JOIN to match SQL-99.

- Added NATURAL JOIN syntax.

- A lot of fixes in the BDB interface.

- Added handling of --no-defaults and --defaults-file to safe_mysqld.sh and mysql_install_db.sh.

- Fixed bug in reading compressed tables with many threads.

- Fixed that USE INDEX works with PRIMARY keys.

- Added BEGIN statement to start a transaction in AUTOCOMMIT mode.

- Added support for symbolic links for Windows.

- Changed protocol to let client know if the server is in AUTOCOMMIT mode and if there is a pending transaction. If there is a pending transaction, the client library will give an error before reconnecting to the server to let the client know that the server did a rollback. The protocol is still backward-compatible with old clients.

- KILL now works on a thread that is locked on a 'write' to a dead client.

- Fixed memory leak in the replication slave thread.

- Added new log-slave-updates option to mysqld, to allow daisy-chaining the slaves.

- Fixed compile error on FreeBSD and other systems where pthread_t is not the same as int.

- Fixed master shutdown aborting the slave thread.

- Fixed a race condition in INSERT DELAYED code when doing ALTER TABLE.

- Added deadlock detection sanity checks to INSERT DELAYED.

30-D-45 - Changements de la version 3.23.16

- Added SLAVE START and SLAVE STOP statements.

- Added TYPE=QUICK option to CHECK and to REPAIR.

- Fixed bug in REPAIR TABLE when the table was in use by other threads.

- Added a thread cache to make it possible to debug MySQL with gdb when one does a lot of reconnects. This will also improve systems where you can't use persistent connections.

- Lots of fixes in the Berkeley DB interface.

- UPDATE IGNORE will not abort if an update results in a DUPLICATE_KEY error.

- Put CREATE TEMPORARY TABLE commands in the update log.

- Fixed bug in handling of masked IP numbers in the privilege tables.

- Fixed bug with delay_key_write tables and CHECK TABLE.

- Added replicate-do-db and replicate-ignore-db options to mysqld, to restrict which databases get replicated.

- Added SQL_LOG_BIN option.

30-D-46 - Changements de la version 3.23.15 (May 2000: Beta)

- To start mysqld as root, you must now use the --user=root option.

- Added interface to Berkeley DB. (This is not yet functional; play with it at your own risk!)

- Replication between master and slaves.

- Fixed bug that other threads could steal a lock when a thread had a lock on a table and did a FLUSH TABLES command.

- Added the slow_launch_time variable and the Slow_launch_threads status variable to mysqld. These can be examined with mysqladmin variables and mysqladmin extended-status.

- Added functions INET_NTOA() and INET_ATON().

- The default type of IF() now depends on the second and third arguments and not only on the second argument.

- Fixed case when myisamchk could go into a loop when trying to repair a crashed table.

- Don't write INSERT DELAYED to update log if SQL_LOG_UPDATE=0.

- Fixed problem with REPLACE on HEAP tables.

- Added possible character sets and time zone to SHOW VARIABLES output.

- Fixed bug in locking code that could result in locking problems with concurrent inserts under high load.

- Fixed a problem with DELETE of many rows on a table with compressed keys where MySQL scanned the index to find the rows.

- Fixed problem with CHECK on table with deleted keyblocks.

- Fixed a bug in reconnect (at the client side) where it didn't free memory properly in some contexts.

- Fixed problems in update log when using LAST_INSERT_ID() to update a table with an AUTO_INCREMENT key.

- Added NULLIF() function.

- Fixed bug when using LOAD DATA INFILE on a table with BLOB/TEXT columns.

- Optimized MyISAM to be faster when inserting keys in sorted order.

- EXPLAIN SELECT ... now also prints out whether MySQL needs to create a temporary table or use file sorting when resolving the SELECT.

- Added optimization to skip ORDER BY parts where the part is a constant expression in the WHERE part. Indexes can now be used even if the ORDER BY doesn't match the index exactly, as long as all the unused index parts and all the extra ORDER BY columns are constants in the WHERE clause. Voir Section 7.4.5, « Comment MySQL utilise les index ».

- UPDATE and DELETE on a whole unique key in the WHERE part are now faster than before.

- Changed RAID_CHUNKSIZE to be in 1024-byte increments.

- Fixed core dump in LOAD_FILE(NULL).

30-D-47 - Changements de la version 3.23.14

- Added mysqlbinlog program for displaying binary log files in text format.

- Added mysql_real_escape_string() function to the MySQL C API.

- Fixed a bug in CONCAT() where one of the arguments was a function that returned a modified argument.

- Fixed a critical bug in myisamchk, where it updated the header in the index file when one only checked the table. This confused the mysqld daemon if it updated the same table at the same time. Now the status in the index file is only updated if one uses --update-state. With older myisamchk versions you should use --read-only when only checking tables, if there is the slightest chance that the mysqld server is working on the table at the same time!

- Fixed that DROP TABLE is logged in the update log.

- Fixed problem when searching on DECIMAL() key field where the column data contained leading zeros.

- Fix bug in myisamchk when the AUTO_INCREMENT column isn't the first key.

- Allow DATETIME in ISO8601 format: 2000-03-12T12:00:00

- Dynamic character sets. A mysqld binary can now handle many different character sets (you can choose which when starting mysqld).

- Added command REPAIR TABLE.

- Added mysql_thread_safe() function to the MySQL C API.

- Added the UMASK_DIR environment variable.

- Added CONNECTION_ID() function to return the client connection thread ID.

- When using = on BLOB or VARCHAR BINARY keys, where only a part of the column was indexed, the whole column of the result row wasn't compared.

- Fix for sjis character set and ORDER BY.

- When running in ANSI mode, don't allow columns to be used that aren't in the GROUP BY part.

30-D-48 - Changements de la version 3.23.13

- Fixed problem when doing locks on the same table more than 2 times in the same LOCK TABLE command; this fixed the problem one got when running the test-ATIS test with --fast or --check-only-changed.

- Added SQL_BUFFER_RESULT option to SELECT.

- Removed end space from double/float numbers in results from temporary tables.

- Added CHECK TABLE command.

- Added changes for MyISAM in 3.23.12 that didn't get into the source distribution because of CVS problems.

- Fixed bug so that mysqladmin shutdown will wait for the local server to close down.

- Fixed a possible endless loop when calculating timestamp.

- Added print_defaults program to the .rpm files. Removed mysqlbug from the client .rpm file.

30-D-49 - Changements de la version 3.23.12 (07 mars 2000)

- Fixed bug in MyISAM involving REPLACE ... SELECT ... which could give a corrupted table.

- Fixed bug in myisamchk where it incorrectly reset the AUTO_INCREMENT value.

- LOTS of patches for Linux Alpha. MySQL now appears to be relatively stable on Alpha.

- Changed DISTINCT on HEAP temporary tables to use hashed keys to quickly find duplicated rows. This mostly concerns queries of type SELECT DISTINCT ... GROUP BY .... This fixes a problem where not all duplicates were removed in queries of the above type. In addition, the new code is MUCH faster.

- Added patches to make MySQL compile on Mac OS X.

- Added IF NOT EXISTS clause to CREATE DATABASE.

- Added --all-databases and --databases options to mysqldump to allow dumping of many databases at the same time.

- Fixed bug in compressed DECIMAL() index in MyISAM tables.

- Fixed bug when storing 0 into a timestamp.

- When doing mysqladmin shutdown on a local connection, mysqladmin now waits until the PID file is gone before terminating.

- Fixed core dump with some COUNT(DISTINCT ...) queries.

- Fixed that myisamchk works properly with RAID tables.

- Fixed problem with LEFT JOIN and key_field IS NULL.

- Fixed bug in net_clear() which could give the error Aborted connection in the MySQL clients.

- Added options USE INDEX (key_list) and IGNORE INDEX (key_list) as parameters in SELECT.

- DELETE and RENAME should now work on RAID tables.

30-D-50 - Changements de la version 3.23.11

- Allow the ALTER TABLE tbl_name ADD (field_list) syntax.

- Fixed problem with optimizer that could sometimes use incorrect keys.

- Fixed that GRANT/REVOKE ALL PRIVILEGES doesn't affect GRANT OPTION.

- Removed extra ')' from the output of SHOW GRANTS.

- Fixed problem when storing numbers in timestamps.

- Fix problem with timezones that have half hour offsets.

- Allow the syntax UNIQUE INDEX in CREATE statements.

- mysqlhotcopy - fast online hot-backup utility for local MySQL databases. By Tim Bunce.

- New more secure mysqlaccess. Thanks to Steve Harvey for this.

- Added --i-am-a-dummy and --safe-updates options to mysql.

- Added select_limit and max_join_size variables to mysql.

- Added SQL_MAX_JOIN_SIZE and SQL_SAFE_UPDATES options.

- Added READ LOCAL lock that doesn't lock the table for concurrent inserts. (This is used by mysqldump.)

- Changed that LOCK TABLES ... READ no longer allows concurrent inserts.

- Added --skip-delay-key-write option to mysqld.

- Fixed security problem in the protocol regarding password checking.

- _rowid can now be used as an alias for an integer type unique indexed column.

- Added back blocking of SIGPIPE when compiling with --thread-safe-clients to make things safe for old clients.

30-D-51 - Changements de la version 3.23.10

- Fixed bug in 3.23.9 where memory wasn't properly freed when using LOCK TABLES.

30-D-52 - Changements de la version 3.23.9

- Fixed problem that affected queries that did arithmetic on group functions.

- Fixed problem with timestamps and INSERT DELAYED.

- Fixed that date_col BETWEEN const_date AND const_date works.

- Fixed problem when only changing a 0 to NULL in a table with BLOB/TEXT columns.

- Fixed bug in range optimizer when using many key parts and or on the middle key parts: WHERE K1=1 and K3=2 and (K2=2 and K4=4 or K2=3 and K4=5)

- Added source command to mysql to allow reading of batch files inside the mysql client. Original patch by Matthew Vanecek.

- Fixed critical problem with the WITH GRANT OPTION option.

- Don't give an unnecessary GRANT error when using tables from many databases in the same query.

- Added VIO wrapper (needed for SSL support; by Andrei Errapart and Tõnu Samuel).

- Fixed optimizer problem on SELECT when using many overlapping indexes. MySQL should now be able to choose keys even better when there are many keys to choose from.

- Changed optimizer to prefer a range key instead of a ref key when the range key can uses more columns than the ref key (which only can use columns with =). For example, the following type of queries should now be faster: SELECT * from key_part_1=const and key_part_2 > const2

- Fixed bug that a change of all VARCHAR columns to CHAR columns didn't change row type from dynamic to fixed.

- Disabled floating-point exceptions for FreeBSD to fix core dump when doing SELECT FLOOR(POW(2,63)).

- Renamed mysqld startup option from --delay-key-write to --delay-key-write-for-all-tables.

- Added read-next-on-key to HEAP tables. This should fix all problems with HEAP tables when using non-UNIQUE keys.

- Added option to print default arguments to all clients.

- Added --log-slow-queries option to mysqld to log all queries that take a long time to a separate log file with a time indicating how long the query took.

- Fixed core dump when doing WHERE key_col=RAND(...).

- Fixed optimization bug in SELECT ... LEFT JOIN ... key_col IS NULL, when key_col could contain NULL values.

- Fixed problem with 8-bit characters as separators in LOAD DATA INFILE.

30-D-53 - Changements de la version 3.23.8 (02 janvier 2000)

- Fixed problem when handling indexfiles larger than 8G.

- Added latest patches to MIT-pthreads for NetBSD.

- Fixed problem with timezones that are < GMT - 11.

- Fixed a bug when deleting packed keys in NISAM.

- Fixed problem with ISAM when doing some ORDER BY ... DESC queries.

- Fixed bug when doing a join on a text key which didn't cover the whole key.

- Option --delay-key-write didn't enable delayed key writing.

- Fixed update of TEXT column which involved only case changes.

- Fixed that INSERT DELAYED doesn't update timestamps that are given.

- Added function YEARWEEK() and options x, X, v and V to DATE_FORMAT().

- Fixed problem with MAX(indexed_column) and HEAP tables.

- Fixed problem with BLOB NULL keys and LIKE "prefix%".

- Fixed problem with MyISAM and fixed-length rows < 5 bytes.

- Fixed problem that could cause MySQL to touch freed memory when doing very complicated GROUP BY queries.

- Fixed core dump if you got a crashed table where an ENUM field value was too big.

30-D-54 - Changements de la version 3.23.7 (10 décembre 1999)

- Fixed workaround under Linux to avoid problems with pthread_mutex_timedwait(), which is used with INSERT DELAYED. Voir Section 2.8.1, « Notes relatives à Linux (toutes versions) ».

- Fixed that one will get a 'disk full' error message if one gets disk full when doing sorting (instead of waiting until we got more disk space).

- Fixed a bug in MyISAM with keys > 250 characters.

- In MyISAM one can now do an INSERT at the same time as other threads are reading from the table.

- Added max_write_lock_count variable to mysqld to force a READ lock after a certain number of WRITE locks.

- Inverted flag delay_key_write on show variables.

- Renamed concurrency variable to thread_concurrency.

- The following functions are now multi-byte-safe: LOCATE(substr,str), POSITION(substr IN str), LOCATE(substr,str,pos), INSTR(str,substr), LEFT(str,len), RIGHT(str,len), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len), MID(str,pos,len), SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING_INDEX(str,delim,count), RTRIM(str), TRIM([[BOTH | TRAILING] [remstr] FROM] str), REPLACE(str,from_str,to_str), REVERSE(str), INSERT(str,pos,len,newstr), LCASE(str), LOWER(str), UCASE(str) and UPPER(str); patch by Wei He.

- Fix core dump when releasing a lock from a non-existent table.

- Remove locks on tables before starting to remove duplicates.

- Added option FULL to SHOW PROCESSLIST.

- Added option --verbose to mysqladmin.

- Fixed problem when automatically converting HEAP to MyISAM.

- Fixed bug in HEAP tables when doing insert + delete + insert + scan the table.

- Fixed bugs on Alpha with REPLACE() and LOAD DATA INFILE.

- Added interactive_timeout variable to mysqld.

- Changed the argument to mysql_data_Voirk() from ulong to ulonglong.

30-D-55 - Changements de la version 3.23.6

- Added -O lower_case_table_names={0|1} option to mysqld to allow users to force table names to lowercase.

- Added SELECT ... INTO DUMPFILE.

- Added --ansi option to mysqld to make some functions SQL-99 compatible.

- Temporary table names now start with #sql.

- Added quoting of identifiers with ` (" in --ansi mode).

- Changed to use snprintf() when printing floats to avoid some buffer overflows on FreeBSD.

- Made FLOOR() overflow safe on FreeBSD.

- Added --quote-names option to mysqldump.

- Fixed bug that one could make a part of a PRIMARY KEY NOT NULL.

- Fixed encrypt() to be thread-safe and not reuse buffer.

- Added mysql_odbc_escape_string() function to support big5 characters in MyODBC.

- Rewrote the storage engine to use classes. This introduces a lot of new code, but will make table handling faster and better.

- Added patch by Sasha for user-defined variables.

- Changed that FLOAT and DOUBLE (without any length modifiers) no longer are fixed decimal point numbers.

- Changed the meaning of FLOAT(X): Now this is the same as FLOAT if X <= 24 and a DOUBLE if 24 < X <= 53.

- DECIMAL(X) is now an alias for DECIMAL(X,0) and DECIMAL is now an alias for DECIMAL(10,0). The same goes for NUMERIC.

- Added option ROW_FORMAT={DEFAULT | DYNAMIC | FIXED | COMPRESSED} to CREATE_TABLE.

- DELETE FROM table_name didn't work on temporary tables.

- Changed function CHAR_LENGTH() to be multi-byte character safe.

- Added function ORD(string).

30-D-56 - Changements de la version 3.23.5 (20 octobre 1999)

- Fixed some Y2K problems in the new date handling in 3.23.

- Fixed problem with SELECT DISTINCT ... ORDER BY RAND().

- Added patches by Sergei A. Golubchik for text searching on the MyISAM level.

- Fixed cache overflow problem when using full joins without keys.

- Fixed some configure issues.

- Some small changes to make parsing faster.

- Adding a column after the last field with ALTER TABLE didn't work.

- Fixed problem when using an AUTO_INCREMENT column in two keys

- With MyISAM, you now can have an AUTO_INCREMENT column as a key sub part: CREATE TABLE foo (a INT NOT NULL AUTO_INCREMENT, b CHAR(5), PRIMARY KEY (b,a))

- Fixed bug in MyISAM with packed char keys that could be NULL.

- AS on field name with CREATE TABLE table_name SELECT ... didn't work.

- Allow use of NATIONAL and NCHAR when defining character columns. This is the same as not using BINARY.

- Don't allow NULL columns in a PRIMARY KEY (only in UNIQUE keys).

- Clear LAST_INSERT_ID() if one uses this in ODBC: WHERE auto_increment_column IS NULL. This Voirms to fix some problems with Access.

- SET SQL_AUTO_IS_NULL=0|1 now turns on/off the handling of searching after the last inserted row with WHERE auto_increment_column IS NULL.

- Added new variable concurrency to mysqld for Solaris.

- Added --relative option to mysqladmin to make extended-status more useful to monitor changes.

- Fixed bug when using COUNT(DISTINCT ...) on an empty table.

- Added support for the Chinese character set GBK.

- Fixed problem with LOAD DATA INFILE and BLOB columns.

- Added bit operator ~ (negation).

- Fixed problem with UDF functions.

30-D-57 - Changements de la version 3.23.4 (28 septembre 1999)

- Inserting a DATETIME into a TIME column no longer will try to store 'days' in it.

- Fixed problem with storage of float/double on little endian machines. (This affected SUM().)

- Added connect timeout on TCP/IP connections.

- Fixed problem with LIKE "%" on an index that may have NULL values.

- REVOKE ALL PRIVILEGES didn't revoke all privileges.

- Allow creation of temporary tables with same name as the original table.

- When granting a user a GRANT option for a database, he couldn't grant privileges to other users.

- New command: SHOW GRANTS FOR user (by Sinisa).

- New date_add syntax: date/datetime + INTERVAL # interval_type. By Joshua Chamas.

- Fixed privilege check for LOAD DATA REPLACE.

- Automatic fixing of broken include files on Solaris 2.7

- Some configure issues to fix problems with big filesystem detection.

- REGEXP is now case-insensitive if you use non-binary strings.

30-D-58 - Changements de la version 3.23.3

- Added patches for MIT-pthreads on NetBSD.

- Fixed range bug in MyISAM.

- ASC is now the default again for ORDER BY.

- Added LIMIT to UPDATE.

- Added mysql_change_user() function to the MySQL C API.

- Added character set to SHOW VARIABLES.

- Added support of --[whitespace] comments.

- Allow INSERT into tbl_name VALUES (), that is, you may now specify an empty value list to insert a row in which each column is set to its default value.

- Changed SUBSTRING(text FROM pos) to conform to SQL-99. (Before this construct returned the rightmost pos characters.)

- SUM() with GROUP BY returned 0 on some systems.

- Changed output for SHOW TABLE STATUS.

- Added DELAY_KEY_WRITE option to CREATE TABLE.

- Allow AUTO_INCREMENT on any key part.

- Fixed problem with YEAR(NOW()) and YEAR(CURDATE()).

- Added CASE construct.

- New function COALESCE().

30-D-59 - Changements de la version 3.23.2 (09 août 1999)

- Fixed range optimizer bug: SELECT * FROM table_name WHERE key_part1 >= const AND (key_part2 = const OR key_part2 = const). The bug was that some rows could be duplicated in the result.

- Running myisamchk without -a updated the index distribution incorrectly.

- SET SQL_LOW_PRIORITY_UPDATES=1 was causing a parse error.

- You can now update index columns that are used in the WHERE clause. UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100

- Date handling should now be a bit faster.

- Added handling of fuzzy dates (dates where day or month is 0), such as '1999-01-00'.

- Fixed optimization of SELECT ... WHERE key_part1=const1 AND key_part_2=const2 AND key_part1=const4 AND key_part2=const4; indextype should be range instead of ref.

- Fixed egcs 1.1.2 optimizer bug (when using BLOB values) on Linux Alpha.

- Fixed problem with LOCK TABLES combined with DELETE FROM table.

- MyISAM tables now allow keys on NULL and BLOB/TEXT columns.

- The following join is now much faster: SELECT ... FROM t1 LEFT JOIN t2 ON ... WHERE t2.not_null_column IS NULL.

- ORDER BY and GROUP BY can be done on functions.

- Changed handling of 'const_item' to allow handling of ORDER BY RAND().

- Indexes are now used for WHERE key_column = function.

- Indexes are now used for WHERE key_column = col_name even if the columns are not identically packed.

- Indexes are now used for WHERE col_name IS NULL.

- Changed heap tables to be stored in low_byte_first order (to make it easy to convert to MyISAM tables)

- Automatic change of HEAP temporary tables to MyISAM tables in case of « table is full » errors.

- Added --init-file=file_name option to mysqld.

- Added COUNT(DISTINCT value, [value, ...]).

- CREATE TEMPORARY TABLE now creates a temporary table, in its own namespace, that is automatically deleted if connection is dropped.

- New reserved words (required for CASE): CASE, THEN, WHEN, ELSE and END.

- New functions EXPORT_SET() and MD5().

- Support for the GB2312 Chinese character set.

30-D-60 - Changements de la version 3.23.1

- Fixed some compilation problems.

30-D-61 - Changements de la version 3.23.0 (05 Aug 1999: Alpha)

- A new storage engine library (MyISAM) with a lot of new features. Voir Section 14.1, « Le moteur de tables MyISAM ».

- You can create in-memory HEAP tables which are extremely fast for lookups.

- Support for big files (63-bit) on OSs that support big files.

- New function LOAD_FILE(filename) to get the contents of a file as a string value.

- New <=> operator that acts as = but returns TRUE if both arguments are NULL. This is useful for comparing changes between tables.

- Added the ODBC 3.0 EXTRACT(interval FROM datetime) function.

- Columns defined as FLOAT(X) are not rounded on storage and may be in scientific notation (1.0 E+10) when retrieved.

- REPLACE is now faster than before.

- Changed LIKE character comparison to behave as =; This means that 'e' LIKE 'é' is now true. (If the line doesn't display correctly, the latter 'e' is a French 'e' with an acute accent above.)

- SHOW TABLE STATUS returns a lot of information about the tables.

- Added LIKE to the SHOW STATUS command.

- Added Privileges column to SHOW COLUMNS.

- Added Packed and Comment columns to SHOW INDEX.

- Added comments to tables (with CREATE TABLE ... COMMENT "xxx").

- Added UNIQUE, as in CREATE TABLE tbl_name (col INT not null UNIQUE)

- New create syntax: CREATE TABLE tbl_name SELECT ...

- New create syntax: CREATE TABLE IF NOT EXISTS ...

- Allow creation of CHAR(0) columns.

- DATE_FORMAT() now requires '%' before any format character.

- DELAYED is now a reserved word (sorry about that :( ).

- An example procedure is added: analyse, file: sql_analyse.c. This will describe the data in your query. Try the following:

SELECT ... FROM ...
WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])

This procedure is extremely useful when you want to check the data in your table!

- BINARY cast to force a string to be compared in case-sensitive fashion.

- Added --skip-show-database option to mysqld.

- Check whether a row has changed in an UPDATE now also works with BLOB/TEXT columns.

- Added the INNER join syntax. Note: This made INNER a reserved word!

- Added support for netmasks to the hostname in the MySQL grant tables. You can specify a netmask using the IP/NETMASK syntax.

- If you compare a NOT NULL DATE/DATETIME column with IS NULL, this is changed to a compare against 0 to satisfy some ODBC applications. (By <shreeve@uci.edu>.)

- NULL IN (...) now returns NULL instead of 0. This will ensure that null_column NOT IN (...) doesn't match NULL values.

- Fix storage of floating-point values in TIME columns.

- Changed parsing of TIME strings to be more strict. Now the fractional second part is detected (and currently skipped). The following formats are supported:

- [[DAYS] [H]H:]MM:]SS[.fraction]

- [[[[[H]H]H]H]MM]SS[.fraction]

- Detect (and ignore) fractional second part from DATETIME.

- Added the LOW_PRIORITY attribute to LOAD DATA INFILE.

- The default index name now uses the same case as the column name on which the index name is based.

- Changed default number of connections to 100.

- Use bigger buffers when using LOAD DATA INFILE.

- DECIMAL(x,y) now works according to standard SQL.

- Added aggregate UDF functions. Thanks to Andreas F. Bobak (<bobak@relog.ch>) for this!

- LAST_INSERT_ID() is now updated for INSERT INTO ... SELECT.

- Some small changes to the join table optimizer to make some joins faster.

- SELECT DISTINCT is much faster; it uses the new UNIQUE functionality in MyISAM. One difference compared to MySQL 3.22 is that the output of DISTINCT is no longer sorted.

- All C client API macros are now functions to make shared libraries more reliable. Because of this, you can no longer call mysql_num_fields() on a MYSQL object, you must use mysql_field_count() instead.

- Added use of LIBWRAP; patch by Henning P. Schmiedehausen.

- Don't allow AUTO_INCREMENT for other than numerical columns.

- Using AUTO_INCREMENT will now automatically make the column NOT NULL.

- Show NULL as the default value for AUTO_INCREMENT columns.

- Added SQL_BIG_RESULT; SQL_SMALL_RESULT is now default.

- Added a shared library RPM. This enhancement was contributed by David Fox (<dsfox@cogsci.ucsd.edu>).

- Added --enable-large-files and --disable-large-files options to configure. Voir configure.in for some systems where this is automatically turned off because of broken implementations.

- Upgraded readline to 4.0.

- New CREATE TABLE options: PACK_KEYS and CHECKSUM.

- Added --default-table-type option to mysqld.

30-E - Changements de la version 3.22.x (Old; discontinued)

The 3.22 version has faster and safer connect code than version 3.21, as well as a lot of new nice enhancements. As there aren't really any major changes, upgrading from 3.21 to 3.22 should be very easy and painless. Voir Section 2.6.5, « Passer de la version 3.21 à la version 3.22 ».

30-E-1 - Changements de la version 3.22.35

- Fixed problem with STD().

- Merged changes from the newest ISAM library from 3.23.

- Fixed problem with INSERT DELAYED.

- Fixed a bug core dump when using a LEFT JOIN/STRAIGHT_JOIN on a table with only one row.

30-E-2 - Changements de la version 3.22.34

- Fixed problem with GROUP BY on TINYBLOB columns; this caused bugzilla to not show rows in some queries.

- Had to do total recompile of the Windows binary version as VC++ didn't compile all relevant files for 3.22.33 :(

30-E-3 - Changements de la version 3.22.33

- Fixed problems in Windows when locking tables with LOCK TABLE.

- Quicker kill of SELECT DISTINCT queries.

30-E-4 - Changements de la version 3.22.32 (14 février 2000)

- Fixed problem when storing numbers in timestamps.

- Fix problem with timezones that have half hour offsets.

- Added mysqlhotcopy, a fast online hot-backup utility for local MySQL databases. By Tim Bunce.

- New more secure mysqlaccess. Thanks to Steve Harvey for this.

- Fixed security problem in the protocol regarding password checking.

- Fixed problem that affected queries that did arithmetic on GROUP functions.

- Fixed a bug in the ISAM code when deleting rows on tables with packed indexes.

30-E-5 - Changements de la version 3.22.31

- A few small fixes for the Windows version.

30-E-6 - Changements de la version 3.22.30

- Fixed optimizer problem on SELECT when using many overlapping indexes.

- Disabled floating-point exceptions for FreeBSD to fix core dump when doing SELECT FLOOR(POW(2,63)).

- Added print of default arguments options to all clients.

- Fixed critical problem with the WITH GRANT OPTION option.

- Fixed non-critical Y2K problem when writing short date to log files.

30-E-7 - Changements de la version 3.22.29 (02 janvier 2000)

- Upgraded the configure and include files to match the latest 3.23 version. This should increase portability and make it easier to build shared libraries.

- Added latest patches to MIT-pthreads for NetBSD.

- Fixed problem with timezones that are < GMT -11.

- Fixed a bug when deleting packed keys in NISAM.

- Fixed problem that could cause MySQL to touch freed memory when doing very complicated GROUP BY queries.

- Fixed core dump if you got a crashed table where an ENUM field value was too big.

- Added mysqlshutdown.exe and mysqlwatch.exe to the Windows distribution.

- Fixed problem when doing ORDER BY on a reference key.

- Fixed that INSERT DELAYED doesn't update timestamps that are given.

30-E-8 - Changements de la version 3.22.28 (20 octobre 1999)

- Fixed problem with LEFT JOIN and COUNT() on a column which was declared NULL + and it had a DEFAULT value.

- Fixed core dump problem when using CONCAT() in a WHERE clause.

- Fixed problem with AVG() and STD() with NULL values.

30-E-9 - Changements de la version 3.22.27

- Fixed prototype in my_ctype.h when using other character sets.

- Some configure issues to fix problems with big filesystem detection.

- Fixed problem when sorting on big BLOB columns.

- ROUND() will now work on Windows.

30-E-10 - Changements de la version 3.22.26 (16 septembre 1999)

- Fixed core dump with empty BLOB/TEXT column argument to REVERSE().

- Extended /*! */ with version numbers.

- Changed SUBSTRING(text FROM pos) to conform to SQL-99. (Before this construct returned the rightmost 'pos' characters.)

- Fixed problem with LOCK TABLES combined with DELETE FROM table

- Fixed problem that INSERT ... SELECT didn't use BIG_TABLES.

- SET SQL_LOW_PRIORITY_UPDATES=# didn't work.

- Password wasn't updated correctly if privileges didn't change on: GRANT ... IDENTIFIED BY

- Fixed range optimizer bug in SELECT * FROM table_name WHERE key_part1 >= const AND (key_part2 = const OR key_part2 = const).

- Fixed bug in compression key handling in ISAM.

30-E-11 - Changements de la version 3.22.25

- Fixed some small problems with the installation.

30-E-12 - Changements de la version 3.22.24 (05 juillet 1999)

- DATA is no longer a reserved word.

- Fixed optimizer bug with tables with only one row.

- Fixed bug when using LOCK TABLES table_name READ; FLUSH TABLES;

- Applied some patches for HP-UX.

- isamchk should now work on Windows.

- Changed configure to not use big file handling on Linux as this crashes some Red Hat 6.0 systems

30-E-13 - Changements de la version 3.22.23 (08 juin 1999)

- Upgraded to use Autoconf 2.13, Automake 1.4 and libtool 1.3.2.

- Better support for SCO in configure.

- Added option --defaults-file=file_name to option file handling to force use of only one specific option file.

- Extended CREATE syntax to ignore MySQL Version 3.23 keywords.

- Fixed deadlock problem when using INSERT DELAYED on a table locked with LOCK TABLES.

- Fixed deadlock problem when using DROP TABLE on a table that was locked by another thread.

- Add logging of GRANT/REVOKE commands in the update log.

- Fixed isamchk to detect a new error condition.

- Fixed bug in NATURAL LEFT JOIN.

30-E-14 - Changements de la version 3.22.22 (30 avril 1999)

- Fixed problem in the C API when you called mysql_close() directly after mysql_init().

- Better client error message when you can't open socket.

- Fixed delayed_insert_thread counting when you couldn't create a new delayed_insert thread.

- Fixed bug in CONCAT() with many arguments.

- Added patches for DEC 3.2 and SCO.

- Fixed path-bug when installing MySQL as a service on NT.

- MySQL on Windows is now compiled with VC++ 6.0 instead of with VC++ 5.0.

- New installation setup for MySQL on Windows.

30-E-15 - Changements de la version 3.22.21

- Fixed problem with DELETE FROM TABLE when table was locked by another thread.

- Fixed bug in LEFT JOIN involving empty tables.

- Changed the mysql.db column from CHAR(32) to CHAR(60).

- MODIFY and DELAYED are no longer reserved words.

- Fixed a bug when storing days in a TIME column.

- Fixed a problem with Host '...' is not allowed to connect to this MySQL server after one had inserted a new MySQL user with a GRANT command.

- Changed to use TCP_NODELAY also on Linux (should give faster TCP/IP connections).

30-E-16 - Changements de la version 3.22.20 (18 mars 1999)

- Fixed STD() for big tables when result should be 0.

- The update log didn't have newlines on some operating systems.

- INSERT DELAYED had some garbage at end in the update log.

30-E-17 - Changements de la version 3.22.19 (Mar 1999: Production)

- Fixed bug in mysql_install_db (from 3.22.17).

- Changed default key cache size to 8M.

- Fixed problem with queries that needed temporary tables with BLOB columns.

30-E-18 - Changements de la version 3.22.18

- Fixes a fatal problem in 3.22.17 on Linux; after shutdown not all threads died properly.

- Added option -O flush_time=# to mysqld. This is mostly useful on Windows and tells how often MySQL should close all unused tables and flush all updated tables to disk.

- Fixed problem that a VARCHAR column compared with CHAR column didn't use keys efficiently.

30-E-19 - Changements de la version 3.22.17

- Fixed a core dump problem when using --log-update and connecting without a default database.

- Fixed some configure and portability problems.

- Using LEFT JOIN on tables that had circular dependencies caused mysqld to hang forever.

30-E-20 - Changements de la version 3.22.16 (Feb 1999: Gamma)

- mysqladmin processlist could kill the server if a new user logged in.

- DELETE FROM tbl_name WHERE key_column=col_name didn't find any matching rows. Fixed.

- DATE_ADD(column, ...) didn't work.

- INSERT DELAYED could deadlock with status upgrading lock.

- Extended ENCRYPT() to take longer salt strings than 2 characters.

- longlong2str is now much faster than before. For Intel x86 platforms, this function is written in optimized assembler.

- Added the MODIFY keyword to ALTER TABLE.

30-E-21 - Changements de la version 3.22.15

- GRANT used with IDENTIFIED BY didn't take effect until privileges were flushed.

- Name change of some variables in SHOW STATUS.

- Fixed problem with ORDER BY with 'only index' optimization when there were multiple key definitions for a used column.

- DATE and DATETIME columns are now up to 5 times faster than before.

- INSERT DELAYED can be used to let the client do other things while the server inserts rows into a table.

- LEFT JOIN USING (col1,col2) didn't work if one used it with tables from 2 different databases.

- LOAD DATA LOCAL INFILE didn't work in the Unix version because of a missing file.

- Fixed problems with VARCHAR/BLOB on very short rows (< 4 bytes); error 127 could occur when deleting rows.

- Updating BLOB/TEXT through formulas didn't work for short (< 256 char) strings.

- When you did a GRANT on a new host, mysqld could die on the first connect from this host.

- Fixed bug when one used ORDER BY on column name that was the same name as an alias.

- Added BENCHMARK(loop_count,expression) function to time expressions.

30-E-22 - Changements de la version 3.22.14

- Allow empty arguments to mysqld to make it easier to start from shell scripts.

- Setting a TIMESTAMP column to NULL didn't record the timestamp value in the update log.

- Fixed lock handler bug when one did INSERT INTO TABLE ... SELECT ... GROUP BY.

- Added a patch for localtime_r() on Windows so that it will no lonher crash if your date is > 2039, but instead will return a time of all zero.

- Names for user-defined functions are no longer case-sensitive.

- Added escape of ^Z (ASCII 26) to \Z as ^Z doesn't work with pipes on Windows.

- mysql_fix_privileges adds a new column to the mysql.func to support aggregate UDF functions in future MySQL releases.

30-E-23 - Changements de la version 3.22.13

- Saving NOW(), CURDATE() or CURTIME() directly in a column didn't work.

- SELECT COUNT(*) ... LEFT JOIN ... didn't work with no WHERE part.

- Updated config.guess to allow MySQL to configure on UnixWare 7.1.x.

- Changed the implementation of pthread_cond() on the Windows version. get_lock() now correctly times out on Windows!

30-E-24 - Changements de la version 3.22.12

- Fixed problem when using DATE_ADD() and DATE_SUB() in a WHERE clause.

- You can now set the password for a user with the GRANT ... TO user IDENTIFIED BY 'password' syntax.

- Fixed bug in GRANT checking with SELECT on many tables.

- Added missing file mysql_fix_privilege_tables to the RPM distribution. This is not run by default because it relies on the client package.

- Added option SQL_SMALL_RESULT to SELECT to force use of fast temporary tables when you know that the result set will be small.

- Allow use of negative real numbers without a decimal point.

- Day number is now adjusted to maximum days in month if the resulting month after DATE_ADD/DATE_SUB() doesn't have enough days.

- Fix that GRANT compares columns in case-insensitive fashion.

- Fixed a bug in sql_list.h that made ALTER TABLE dump core in some contexts.

- The hostname in user@hostname can now include '.' and '-' without quotes in the context of the GRANT, REVOKE and SET PASSWORD FOR ... statements.

- Fix for isamchk for tables which need big temporary files.

30-E-25 - Changements de la version 3.22.11

- Important: You must run the mysql_fix_privilege_tables script when you upgrade to this version! This is needed because of the new GRANT system. If you don't do this, you will get Access denied when you try to use ALTER TABLE, CREATE INDEX, or DROP INDEX.

- GRANT to allow/deny users table and column access.

- Changed USER() to return a value in user@host format. Formerly it returned only user.

- Changed the syntax for how to set PASSWORD for another user.

- New command FLUSH STATUS that resets most status variables to zero.

- New status variables: aborted_threads, aborted_connects.

- New option variable: connection_timeout.

- Added support for Thai sorting (by Pruet Boonma <pruet@ds90.intanon.nectec.or.th>).

- Slovak and Japanese error messages.

- Configuration and portability fixes.

- Added option SET SQL_WARNINGS=1 to get a warning count also for simple (single-row) inserts.

- MySQL now uses SIGTERM instead of SIGQUIT with shutdown to work better on FreeBSD.

- Added option \G (print vertically) to mysql.

- SELECT HIGH_PRIORITY ... killed mysqld.

- IS NULL on a AUTO_INCREMENT column in a LEFT JOIN didn't work as expected.

- New function MAKE_SET().

30-E-26 - Changements de la version 3.22.10

- mysql_install_db no longer starts the MySQL server! You should start mysqld with safe_mysqld after installing it! The MySQL RPM will, however, start the server as before.

- Added --bootstrap option to mysqld and recoded mysql_install_db to use it. This will make it easier to install MySQL with RPMs.

- Changed +, - (sign and minus), *, /, %, ABS() and MOD() to be BIGINT aware (64-bit safe).

- Fixed a bug in ALTER TABLE that caused mysqld to crash.

- MySQL now always reports the conflicting key values when a duplicate key entry occurs. (Before this was only reported for INSERT.)

- New syntax: INSERT INTO tbl_name SET col_name=value, col_name=value, ...

- Most errors in the .err log are now prefixed with a time stamp.

- Added option MYSQL_INIT_COMMAND to mysql_options() to make a query on connect or reconnect.

- Added option MYSQL_READ_DEFAULT_FILE and MYSQL_READ_DEFAULT_GROUP to mysql_options() to read the following parameters from the MySQL option files: port, socket, compress, password, pipe, timeout, user, init-command, host and database.

- Added maybe_null to the UDF structure.

- Added option IGNORE to INSERT statements with many rows.

- Fixed some problems with sorting of the koi8 character sets; users of koi8 must run isamchk -rq on each table that has an index on a CHAR or VARCHAR column.

- New script mysql_setpermission, by Luuk de Boer. It allows easy creation of new users with permissions for specific databases.

- Allow use of hexadecimal strings (0x...) when specifying a constant string (like in the column separators with LOAD DATA INFILE).

- Ported to OS/2 (thanks to Antony T. Curtis <antony.curtis@olcs.net>).

- Added more variables to SHOW STATUS and changed format of output to be like SHOW VARIABLES.

- Added extended-status command to mysqladmin which will show the new status variables.

30-E-27 - Changements de la version 3.22.9

- SET SQL_LOG_UPDATE=0 caused a lockup of the server.

- New SQL command: FLUSH [ TABLES | HOSTS | LOGS | PRIVILEGES ] [, ...]

- New SQL command: KILL thread_id.

- Added casts and changed include files to make MySQL easier to compile on AIX and DEC OSF/1 4.x

- Fixed conversion problem when using ALTER TABLE from a INT to a short CHAR() column.

- Added SELECT HIGH_PRIORITY; this will get a lock for the SELECT even if there is a thread waiting for another SELECT to get a WRITE LOCK.

- Moved wild_compare() to string class to be able to use LIKE on BLOB/TEXT columns with \0.

- Added ESCAPE option to LIKE.

- Added a lot more output to mysqladmin debug.

- You can now start mysqld on Windows with the --flush option. This will flush all tables to disk after each update. This makes things much safer on the Windows platforms but also much slower.

30-E-28 - Changements de la version 3.22.8

- Czech character sets should now work much better.

- DATE_ADD() and DATE_SUB() didn't work with group functions.

- mysql will now also try to reconnect on USE database commands.

- Fix problem with ORDER BY and LEFT JOIN and const tables.

- Fixed problem with ORDER BY if the first ORDER BY column was a key and the rest of the ORDER BY columns wasn't part of the key.

- Fixed a big problem with OPTIMIZE TABLE.

- MySQL clients on NT will now by default first try to connect with named pipes and after this with TCP/IP.

- Fixed a problem with DROP TABLE and mysqladmin shutdown on Windows (a fatal bug from 3.22.6).

- Fixed problems with TIME columns and negative strings.

- Added an extra thread signal loop on shutdown to avoid some error messages from the client.

- MySQL now uses the next available number as extension for the update log file.

- Added patches for UNIXWARE 7.

30-E-29 - Changements de la version 3.22.7 (Sep 1998: Beta)

- Added LIMIT clause for the DELETE statement.

- You can now use the /*! ... */ syntax to hide MySQL-specific keywords when you write portable code. MySQL will parse the code inside the comments as if the surrounding /*! and */ comment characters didn't exist.

- OPTIMIZE TABLE tbl_name can now be used to reclaim disk space after many deletes. Currently, this uses ALTER TABLE to regenerate the table, but in the future it will use an integrated isamchk for more speed.

- Upgraded libtool to get the configure more portable.

- Fixed slow UPDATE and DELETE operations when using DATETIME or DATE keys.

- Changed optimizer to make it better at deciding when to do a full join and when using keys.

- You can now use mysqladmin proc to display information about your own threads. Only users with the PROCESS privilege can get information about all threads. (In 4.0.2 one needs the SUPER privilege for this.)

- Added handling of formats YYMMDD, YYYYMMDD, YYMMDDHHMMSS for numbers when using DATETIME and TIMESTAMP types. (Formerly these formats only worked with strings.)

- Added connect option CLIENT_IGNORE_SPACE to allow use of spaces after function names and before '(' (Powerbuilder requires this). This will make all function names reserved words.

- Added the --log-long-format option to mysqld to enable timestamps and INSERT_IDs in the update log.

- Added --where option to mysqldump (patch by Jim Faucette).

- The lexical analyzer now uses « perfect hashing » for faster parsing of SQL statements.

30-E-30 - Changements de la version 3.22.6

- Faster mysqldump.

- For the LOAD DATA INFILE statement, you can now use the new LOCAL keyword to read the file from the client. mysqlimport will automatically use LOCAL when importing with the TCP/IP protocol.

- Fixed small optimize problem when updating keys.

- Changed makefiles to support shared libraries.

- MySQL-NT can now use named pipes, which means that you can now use MySQL-NT without having to install TCP/IP.

30-E-31 - Changements de la version 3.22.5

- All table lock handing is changed to avoid some very subtle deadlocks when using DROP TABLE, ALTER TABLE, DELETE FROM TABLE and mysqladmin flush-tables under heavy usage. Changed locking code to get better handling of locks of different types.

- Updated DBI to 1.00 and DBD to 1.2.0.

- Added a check that the error message file contains error messages suitable for the current version of mysqld. (To avoid errors if you accidentally try to use an old error message file.)

- All count structures in the client (affected_rows(), insert_id(), ...) are now of type BIGINT to allow 64-bit values to be used. This required a minor change in the MySQL protocol which should affect only old clients when using tables with AUTO_INCREMENT values > 16M.

- The return type of mysql_fetch_lengths() has changed from uint * to ulong *. This may give a warning for old clients but should work on most machines.

- Change mysys and dbug libraries to allocate all thread variables in one struct. This makes it easier to make a threaded libmysql.dll library.

- Use the result from gethostname() (instead of uname()) when constructing .pid file names.

- New better compressed server/client protocol.

- COUNT(), STD() and AVG() are extended to handle more than 4G rows.

- You can now store values in the range -838:59:59 <= x <= 838:59:59 in a TIME column.

- Warning: incompatible change!! If you set a TIME column to too short a value, MySQL now assumes the value is given as: [[[D ]HH:]MM:]SS instead of HH[:MM[:SS]].

- TIME_TO_SEC() and SEC_TO_TIME() can now handle negative times and hours up to 32767.

- Added new option SET SQL_LOG_UPDATE={0|1} to allow users with the PROCESS privilege to bypass the update log. (Modified patch from Sergey A Mukhin <violet@rosnet.net>.)

- Fixed fatal bug in LPAD().

- Initialize line buffer in mysql.cc to make BLOB reading from pipes safer.

- Added -O max_connect_errors=# option to mysqld. Connect errors are now reset for each correct connection.

- Increased the default value of max_allowed_packet to 1M in mysqld.

- Added --low-priority-updates option to mysqld, to give table-modifying operations (INSERT, REPLACE, UPDATE, DELETE) lower priority than retrievals. You can now use {INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ... You can also use SET SQL_LOW_PRIORITY_UPDATES={0|1} to change the priority for one thread. One side effect is that LOW_PRIORITY is now a reserved word. :(

- Add support for INSERT INTO table ... VALUES(...),(...),(...), to allow inserting multiple rows with a single statement.

- INSERT INTO tbl_name is now also cached when used with LOCK TABLES. (Previously only INSERT ... SELECT and LOAD DATA INFILE were cached.)

- Allow GROUP BY functions with HAVING:

mysql> SELECT col FROM table GROUP BY col HAVING COUNT(*)>0;

- mysqld will now ignore trailing ';' characters in queries. This is to make it easier to migrate from some other SQL servers that require the trailing ';'.

- Fix for corrupted fixed-format output generated by SELECT INTO OUTFILE.

- Warning: incompatible change! Added Oracle GREATEST() and LEAST() functions. You must now use these instead of the MAX() and MIN() functions to get the largest/smallest value from a list of values. These can now handle REAL, BIGINT and string (CHAR or VARCHAR) values.

- Warning: incompatible change! DAYOFWEEK() had offset 0 for Sunday. Changed the offset to 1.

- Give an error for queries that mix GROUP BY columns and fields when there is no GROUP BY specification.

- Added --vertical option to mysql, for printing results in vertical mode.

- Index-only optimization; some queries are now resolved using only indexes. Until MySQL 4.0, this works only for numeric columns. Voir Section 7.4.5, « Comment MySQL utilise les index ».

- Lots of new benchmarks.

- A new C API chapter and lots of other improvements in the manual.

30-E-32 - Changements de la version 3.22.4

- Added --tmpdir option to mysqld, for specifying the location of the temporary file directory.

- MySQL now automatically changes a query from an ODBC client:

SELECT ... FROM table WHERE auto_increment_column IS NULL

to:

SELECT ... FROM table WHERE auto_increment_column == LAST_INSERT_ID()

This allows some ODBC programs (Delphi, Access) to retrieve the newly inserted row to fetch the AUTO_INCREMENT id.

- DROP TABLE now waits for all users to free a table before deleting it.

- Fixed small memory leak in the new connect protocol.

- New functions BIN(), OCT(), HEX() and CONV() for converting between different number bases.

- Added function SUBSTRING() with 2 arguments.

- If you created a table with a record length smaller than 5, you couldn't delete rows from the table.

- Added optimization to remove const reference tables from ORDER BY and GROUP BY.

- mysqld now automatically disables system locking on Linux and Windows, and for systems that use MIT-pthreads. You can force the use of locking with the --enable-external-locking option.

- Added --console option to mysqld, to force a console window (for error messages) when using Windows.

- Fixed table locks for Windows.

- Allow '$' in identifiers.

- Changed name of user-specific configuration file from my.cnf to .my.cnf (Unix only).

- Added DATE_ADD() and DATE_SUB() functions.

30-E-33 - Changements de la version 3.22.3

- Fixed a lock problem (bug in MySQL Version 3.22.1) when closing temporary tables.

- Added missing mysql_ping() to the client library.

- Added --compress option to all MySQL clients.

- Changed byte to char in mysql.h and mysql_com.h.

30-E-34 - Changements de la version 3.22.2

- Searching on multiple constant keys that matched more than 30% of the rows didn't always use the best possible key.

- New functions <<, >>, RPAD() and LPAD().

- You can now save default options (like passwords) in a configuration file (my.cnf).

- Lots of small changes to get ORDER BY to work when no records are found when using fields that are not in GROUP BY (MySQL extension).

- Added --chroot option to mysqld, to start mysqld in a chroot environment (by Nikki Chumakov <nikkic@cityline.ru>).

- Trailing spaces are now ignored when comparing case-sensitive strings; this should fix some problems with ODBC and flag 512!

- Fixed a core dump bug in the range optimizer.

- Added --one-thread option to mysqld, for debugging with LinuxThreads (or glibc). (This replaces the -T32 flag)

- Added DROP TABLE IF EXISTS to prevent an error from occurring if the table doesn't exist.

- IF and EXISTS are now reserved words (they would have to be sooner or later).

- Added lots of new options to mysqldump.

- Server error messages are now in mysqld_error.h.

- The server/client protocol now supports compression.

- All bug fixes from MySQL Version 3.21.32.

30-E-35 - Changements de la version 3.22.1 (Jun 1998: Alpha)

- Added new C API function mysql_ping().

- Added new API functions mysql_init() and mysql_options(). You now MUST call mysql_init() before you call mysql_real_connect(). You don't have to call mysql_init() if you only use mysql_connect().

- Added mysql_options(...,MYSQL_OPT_CONNECT_TIMEOUT,...) so you can set a timeout for connecting to a server.

- Added --timeout option to mysqladmin, as a test of mysql_options().

- Added AFTER column and FIRST options to ALTER TABLE ... ADD columns. This makes it possible to add a new column at some specific location within a row in an existing table.

- WEEK() now takes an optional argument to allow handling of weeks when the week starts on Monday (some European countries). By default, WEEK() assumes the week starts on Sunday.

- TIME columns weren't stored properly (bug in MySQL Version 3.22.0).

- UPDATE now returns information about how many rows were matched and updated, and how many « warnings » occurred when doing the update.

- Fixed incorrect result from FORMAT(-100,2).

- ENUM and SET columns were compared in binary (case-sensitive) fashion; changed to be case-insensitive.

30-E-36 - Changements de la version 3.22.0

- New (backward-compatible) connect protocol that allows you to specify the database to use when connecting, to get much faster connections to a specific database.
The mysql_real_connect() call is changed to:

mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
const char *passwd, const char *db, uint port,
const char *unix_socket, uint client_flag)

- Each connection is handled by its own thread, rather than by the master accept() thread. This fixes permanently the telnet bug that was a topic on the mail list some time ago.

- All TCP/IP connections are now checked with backward-resolution of the hostname to get better security. mysqld now has a local hostname resolver cache so connections should actually be faster than before, even with this feature.

- A site automatically will be blocked from future connections if someone repeatedly connects with an « improper header » (like when one uses telnet).

- You can now refer to tables in different databases with references of the form tbl_name@db_name or db_name.tbl_name. This makes it possible to give a user read access to some tables and write access to others simply by keeping them in different databases!

- Added --user option to mysqld, to allow it to run as another Unix user (if it is started as the Unix root user).

- Added caching of users and access rights (for faster access rights checking)

- Normal users (not anonymous ones) can change their password with mysqladmin password "new_password". This uses encrypted passwords that are not logged in the normal MySQL log!

- All important string functions are now coded in assembler for x86 Linux machines. This gives a speedup of 10% in many cases.

- For tables that have many columns, the column names are now hashed for much faster column name lookup (this will speed up some benchmark tests a lot!)

- Some benchmarks are changed to get better individual timing. (Some loops were so short that a specific test took < 2 seconds. The loops have been changed to take about 20 seconds to make it easier to compare different databases. A test that took 1-2 seconds before now takes 11-24 seconds, which is much better)

- Re-arranged SELECT code to handle some very specific queries involving group functions (like COUNT(*)) without a GROUP BY but with HAVING. The following now works:

mysql> SELECT COUNT(*) as C FROM table HAVING C > 1;

- Changed the protocol for field functions to be faster and avoid some calls to malloc().

- Added -T32 option to mysqld, for running all queries under the main thread. This makes it possible to debug mysqld under Linux with gdb!

- Added optimization of not_null_column IS NULL (needed for some Access queries).

- Allow STRAIGHT_JOIN to be used between two tables to force the optimizer to join them in a specific order.

- String functions now return VARCHAR rather than CHAR and the column type is now VARCHAR for fields saved as VARCHAR. This should make the MyODBC driver better, but may break some old MySQL clients that don't handle FIELD_TYPE_VARCHAR the same way as FIELD_TYPE_CHAR.

- CREATE INDEX and DROP INDEX are now implemented through ALTER TABLE. CREATE TABLE is still the recommended (fast) way to create indexes.

- Added --set-variable option wait_timeout to mysqld.

- Added time column to mysqladmin processlist to show how long a query has taken or how long a thread has slept.

- Added lots of new variables to show variables and some new to show status.

- Added new type YEAR. YEAR is stored in 1 byte with allowable values of 0, and 1901 to 2155.

- Added new DATE type that is stored in 3 bytes rather than 4 bytes. All new tables are created with the new date type if you don't use the --old-protocol option to mysqld.

- Fixed bug in record caches; for some queries, you could get Error from table handler: # on some operating systems.

- Added --enable-assembler option to configure, for x86 machines (tested on Linux + gcc). This will enable assembler functions for the most important string functions for more speed!

30-F - Changements de la version 3.21.x

La version 3.21 est plutôt vieille, et doit être évitée si possible. Les informations de cette section sont conservées à des fins d'archives.

30-F-1 - Changements de la version 3.21.33

- Fixed problem when sending SIGHUP to mysqld; mysqld core dumped when starting from boot on some systems.

- Fixed problem with losing a little memory for some connections.

- DELETE FROM tbl_name without a WHERE condition is now done the long way when you use LOCK TABLES or if the table is in use, to avoid race conditions.

- INSERT INTO TABLE (timestamp_column) VALUES (NULL); didn't set timestamp.

30-F-2 - Changements de la version 3.21.32

- Fixed some possible race conditions when doing many reopen/close on the same tables under heavy load! This can happen if you execute mysqladmin refresh often. This could in some very rare cases corrupt the header of the index file and cause error 126 or 138.

- Fixed fatal bug in refresh() when running with the --skip-external-locking option. There was a « very small » time gap after a mysqladmin refresh when a table could be corrupted if one thread updated a table while another thread did mysqladmin refresh and another thread started a new update ont the same table before the first thread had finished. A refresh (or --flush-tables) will now not return until all used tables are closed!

- SELECT DISTINCT with a WHERE clause that didn't match any rows returned a row in some contexts (bug only in 3.21.31).

- GROUP BY + ORDER BY returned one empty row when no rows where found.

- Fixed a bug in the range optimizer that wrote Use_count: Wrong count for ... in the error log file.

30-F-3 - Changements de la version 3.21.31

- Fixed a sign extension problem for the TINYINT type on Irix.

- Fixed problem with LEFT("constant_string",function).

- Fixed problem with FIND_IN_SET().

- LEFT JOIN core dumped if the second table is used with a constant WHERE/ON expression that uniquely identifies one record.

- Fixed problems with DATE_FORMAT() and incorrect dates. DATE_FORMAT() now ignores '%' to make it possible to extend it more easily in the future.

30-F-4 - Changements de la version 3.21.30

- mysql now returns an exit code > 0 if the query returned an error.

- Saving of command-line history to file in mysql client. By Tommy Larsen <tommy@mix.hive.no>.

- Fixed problem with empty lines that were ignored in mysql.cc.

- Save the pid of the signal handler thread in the pid file instead of the pid of the main thread.

- Added patch by <tommy@valley.ne.jp> to support Japanese characters SJIS and UJIS.

- Changed safe_mysqld to redirect startup messages to 'hostname'.err instead of 'hostname'.log to reclaim file space on mysqladmin refresh.

- ENUM always had the first entry as default value.

- ALTER TABLE wrote two entries to the update log.

- sql_acc() now closes the mysql grant tables after a reload to save table space and memory.

- Changed LOAD DATA to use less memory with tables and BLOB columns.

- Sorting on a function which made a division / 0 produced a wrong set in some cases.

- Fixed SELECT problem with LEFT() when using the czech character set.

- Fixed problem in isamchk; it couldn't repair a packed table in a very unusual case.

- SELECT statements with & or | (bit functions) failed on columns with NULL values.

- When comparing a field = field, where one of the fields was a part key, only the length of the part key was compared.

30-F-5 - Changements de la version 3.21.29

- LOCK TABLES + DELETE from tbl_name never removed locks properly.

- Fixed problem when grouping on an OR function.

- Fixed permission problem with umask() and creating new databases.

- Fixed permission problem on result file with SELECT ... INTO OUTFILE ...

- Fixed problem in range optimizer (core dump) for a very complex query.

- Fixed problem when using MIN(integer) or MAX(integer) in GROUP BY.

- Fixed bug on Alpha when using integer keys. (Other keys worked on Alpha.)

- Fixed bug in WEEK("XXXX-xx-01").

30-F-6 - Changements de la version 3.21.28

- Fixed socket permission (clients couldn't connect to Unix socket on Linux).

- Fixed bug in record caches; for some queries, you could get Error from table handler: # on some operating systems.

30-F-7 - Changements de la version 3.21.27

- Added user level lock functions GET_LOCK(string,timeout), RELEASE_LOCK(string).

- Added Opened_tables to show status.

- Changed connect timeout to 3 seconds to make it somewhat harder for crackers to kill mysqld through telnet + TCP/IP.

- Fixed bug in range optimizer when using WHERE key_part_1 >= something AND key_part_2 <= something_else.

- Changed configure for detection of FreeBSD 3.0 9803xx and above

- WHERE with string_col_key = constant_string didn't always find all rows if the column had many values differing only with characters of the same sort value (like e and e with an accent).

- Strings keys looked up with 'ref' were not compared in case-sensitive fashion.

- Added umask() to make log files non-readable for normal users.

- Ignore users with old (8-byte) password on startup if not using --old-protocol option to mysqld.

- SELECT which matched all key fields returned the values in the case of the matched values, not of the found values. (Minor problem.)

30-F-8 - Changements de la version 3.21.26

- FROM_DAYS(0) now returns "0000-00-00".

- In DATE_FORMAT(), PM and AM were swapped for hours 00 and 12.

- Extended the default maximum key size to 256.

- Fixed bug when using BLOB/TEXT in GROUP BY with many tables.

- An ENUM field that is not declared NOT NULL has NULL as the default value. (Previously, the default value was the first enumeration value.)

- Fixed bug in the join optimizer code when using many part keys on the same key: INDEX (Organization,Surname(35),Initials(35)).

- Added some tests to the table order optimizer to get some cases with SELECT ... FROM many_tables much faster.

- Added a retry loop around accept() to possibly fix some problems on some Linux machines.

30-F-9 - Changements de la version 3.21.25

- Changed typedef 'string' to typedef 'my_string' for better portability.

- You can now kill threads that are waiting on a disk-full condition.

- Fixed some problems with UDF functions.

- Added long options to isamchk. Try isamchk --help.

- Fixed a bug when using 8 bytes long (alpha); filesort() didn't work. Affects DISTINCT, ORDER BY and GROUP BY on 64-bit processors.

30-F-10 - Changements de la version 3.21.24

- Dynamic loadable functions. Based on source from Alexis Mikhailov.

- You couldn't delete from a table if no one had done a SELECT on the table.

- Fixed problem with range optimizer with many OR operators on key parts inside each other.

- Recoded MIN() and MAX() to work properly with strings and HAVING.

- Changed default umask value for new files from 0664 to 0660.

- Fixed problem with LEFT JOIN and constant expressions in the ON part.

- Added Italian error messages from <brenno@dewinter.com>.

- configure now works better on OSF/1 (tested on 4.0D).

- Added hooks to allow LIKE optimization with international character support.

- Upgraded DBI to 0.93.

30-F-11 - Changements de la version 3.21.23

- The following symbols are now reserved words: TIME, DATE, TIMESTAMP, TEXT, BIT, ENUM, NO, ACTION, CHECK, YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, STATUS, VARIABLES.

- Setting a TIMESTAMP to NULL in LOAD DATA INFILE ... didn't set the current time for the TIMESTAMP.

- Fix BETWEEN to recognize binary strings. Now BETWEEN is case-sensitive.

- Added --skip-thread-priority option to mysqld, for systems where mysqld's thread scheduling doesn't work properly (BSDI 3.1).

- Added ODBC functions DAYNAME() and MONTHNAME().

- Added function TIME_FORMAT(). This works like DATE_FORMAT(), but takes a time string ('HH:MM:SS') as argument.

- Fixed unlikely(?) key optimizer bug when using OR operators of key parts inside AND expressions.

- Added variables command to mysqladmin.

- A lot of small changes to the binary releases.

- Fixed a bug in the new protocol from MySQL Version 3.21.20.

- Changed ALTER TABLE to work with Windows (Windows can't rename open files). Also fixed a couple of small bugs in the Windows version.

- All standard MySQL clients are now ported to MySQL for Windows.

- MySQL can now be started as a service on NT.

30-F-12 - Changements de la version 3.21.22

- Starting with this version, all MySQL distributions will be configured, compiled and tested with crash-me and the benchmarks on the following platforms: SunOS 5.6 sun4u, SunOS 5.5.1 sun4u, SunOS 4.14 sun4c, SunOS 5.6 i86pc, Irix 6.3 mips5k, HP-UX 10.20 hppa, AIX 4.2.1 ppc, OSF/1 V4.0 alpha, FreeBSD 2.2.2 i86pc and BSDI 3.1 i386.

- Fix COUNT(*) problems when the WHERE clause didn't match any records. (Bug from 3.21.17.)

- Removed that NULL = NULL is true. Now you must use IS NULL or IS NOT NULL to test whether a value is NULL. (This is according to SQL-99 but may break old applications that are ported from mSQL.) You can get the old behavior by compiling with -DmSQL_COMPLIANT.

- Fixed bug that core dumped when using many LEFT OUTER JOIN clauses.

- Fixed bug in ORDER BY on string formula with possible NULL values.

- Fixed problem in range optimizer when using <= on sub index.

- Added functions DAYOFYEAR(), DAYOFMONTH(), MONTH(), YEAR(), WEEK(), QUARTER(), HOUR(), MINUTE(), SECOND() and FIND_IN_SET().

- Added SHOW VARIABLES command.

- Added support of « long constant strings » from SQL-99:

mysql> SELECT 'first ' 'second';       -> 'first second'

- Upgraded Msql-Mysql-modules to 1.1825.

- Upgraded mysqlaccess to 2.02.

- Fixed problem with Russian character set and LIKE.

- Ported to OpenBSD 2.1.

- New Dutch error messages.

30-F-13 - Changements de la version 3.21.21a

- Configure changes for some operating systems.

30-F-14 - Changements de la version 3.21.21

- Fixed optimizer bug when using WHERE data_field = date_field2 AND date_field2 = constant.

- Added SHOW STATUS command.

- Removed manual.ps from the source distribution to make it smaller.

30-F-15 - Changements de la version 3.21.20

- Changed the maximum table name and column name lengths from 32 to 64.

- Aliases can now be of « any » length.

- Fixed mysqladmin stat to return the right number of queries.

- Changed protocol (downward compatible) to mark if a column has the AUTO_INCREMENT attribute or is a TIMESTAMP. This is needed for the new Java driver.

- Added Hebrew sorting order by Zeev Suraski.

- Solaris 2.6: Fixed configure bugs and increased maximum table size from 2G to 4G.

30-F-16 - Changements de la version 3.21.19

- Upgraded DBD to 1.1823. This version implements mysql_use_result in DBD-Mysql.

- Benchmarks updated for empress (by Luuk).

- Fixed a case of slow range searching.

- Configure fixes (Docs directory).

- Added function REVERSE() (by Zeev Suraski).

30-F-17 - Changements de la version 3.21.18

- Issue error message if client C functions are called in wrong order.

- Added automatic reconnect to the libmysql.c library. If a write command fails, an automatic reconnect is done.

- Small sort sets no longer use temporary files.

- Upgraded DBI to 0.91.

- Fixed a couple of problems with LEFT OUTER JOIN.

- Added CROSS JOIN syntax. CROSS is now a reserved word.

- Recoded yacc/bison stack allocation to be even safer and to allow MySQL to handle even bigger expressions.

- Fixed a couple of problems with the update log.

- ORDER BY was slow when used with key ranges.

30-F-18 - Changements de la version 3.21.17

- Changed documentation string of --with-unix-socket-path to avoid confusion.

- Added ODBC and SQL-99 style LEFT OUTER JOIN.

- The following are new reserved words: LEFT, NATURAL, USING.

- The client library now uses the value of the environment variable MYSQL_HOST as the default host if it's defined.

- SELECT col_name, SUM(expr) now returns NULL for col_name when there are matching rows.

- Fixed problem with comparing binary strings and BLOB values with ASCII characters over 127.

- Fixed lock problem: when freeing a read lock on a table with multiple read locks, a thread waiting for a write lock would have been given the lock. This shouldn't affect data integrity, but could possibly make mysqld restart if one thread was reading data that another thread modified.

- LIMIT offset,count didn't work in INSERT ... SELECT.

- Optimized key block caching. This will be quicker than the old algorithm when using bigger key caches.

30-F-19 - Changements de la version 3.21.16

- Added ODBC 2.0 & 3.0 functions POWER(), SPACE(), COT(), DEGREES(), RADIANS(), ROUND(2 arg) and TRUNCATE().

- Warning : Incompatible change! LOCATE() parameters were swapped according to ODBC standard. Fixed.

- Added function TIME_TO_SEC().

- In some cases, default values were not used for NOT NULL fields.

- Timestamp wasn't always updated properly in UPDATE SET ... statements.

- Allow empty strings as default values for BLOB and TEXT, to be compatible with mysqldump.

30-F-20 - Changements de la version 3.21.15

- Warning: Incompatible change! mysqlperl is now from Msql-Mysql-modules. This means that connect() now takes host, database, user, password arguments! The old version took host, database, password, user.

- Allow DATE '1997-01-01', TIME '12:10:10' and TIMESTAMP '1997-01-01 12:10:10' formats required by SQL-99. Warning: Incompatible change! This has the unfortunate side-effect that you no longer can have columns named DATE, TIME or TIMESTAMP. :( Old columns can still be accessed through tablename.columnname!)

- Changed Makefiles to hopefully work better with BSD systems. Also, manual.dvi is now included in the distribution to avoid having stupid make programs trying to rebuild it.

- readline library upgraded to version 2.1.

- A new sortorder german-1. That is a normal ISO-Latin1 with a german sort order.

- Perl DBI/DBD is now included in the distribution. DBI is now the recommended way to connect to MySQL from Perl.

- New portable benchmark suite with DBD, with test results from mSQL 2.0.3, MySQL, PostgreSQL 6.2.1 and Solid server 2.2.

- crash-me is now included with the benchmarks; this is a Perl program designed to find as many limits as possible in an SQL server. Tested with mSQL, PostgreSQL, Solid and MySQL.

- Fixed bug in range-optimizer that crashed MySQL on some queries.

- Table and column name completion for mysql command-line tool, by Zeev Suraski and Andi Gutmans.

- Added new command REPLACE that works like INSERT but replaces conflicting records with the new record. REPLACE INTO TABLE ... SELECT ... works also.

- Added new commands CREATE DATABASE db_name and DROP DATABASE db_name.

- Added RENAME option to ALTER TABLE: ALTER TABLE name RENAME TO new_name.

- make_binary_distribution now includes libgcc.a in libmysqlclient.a. This should make linking work for people who don't have gcc.

- Changed net_write() to my_net_write() because of a name conflict with Sybase.

- New function DAYOFWEEK() compatible with ODBC.

- Stack checking and bison memory overrun checking to make MySQL safer with weird queries.

30-F-21 - Changements de la version 3.21.14b

- Fixed a couple of small configure problems on some platforms.

30-F-22 - Changements de la version 3.21.14a

- Ported to SCO Openserver 5.0.4 with FSU Pthreads.

- HP-UX 10.20 should work.

- Added new function DATE_FORMAT().

- Added NOT IN.

- Added automatic removal of 'ODBC function conversions': {fn now() }

- Handle ODBC 2.50.3 option flags.

- Fixed comparison of DATE and TIME values with NULL.

- Changed language name from germany to german to be consistent with the other language names.

- Fixed sorting problem on functions returning a FLOAT. Previously, the values were converted to INT values before sorting.

- Fixed slow sorting when sorting on key field when using key_column=constant.

- Sorting on calculated DOUBLE values sorted on integer results instead.

- mysql no longer requires a database argument.

- Changed the place where HAVING should be. According to the SQL standards, it should be after GROUP BY but before ORDER BY. MySQL Version 3.20 incorrectly had it last.

- Added Sybase command USE database to start using another database.

- Added automatic adjusting of number of connections and table cache size if the maximum number of files that can be opened is less than needed. This should fix that mysqld doesn't crash even if you haven't done a ulimit -n 256 before starting mysqld.

- Added lots of limit checks to make it safer when running with too little memory or when doing weird queries.

30-F-23 - Changements de la version 3.21.13

- Added retry of interrupted reads and clearing of errno. This makes Linux systems much safer!

- Fixed locking bug when using many aliases on the same table in the same SELECT.

- Fixed bug with LIKE on number key.

- New error message so you can check whether the connection was lost while the command was running or whether the connection was down from the start.

- Added --table option to mysql to print in table format. Moved time and row information after query result. Added automatic reconnect of lost connections.

- Added != as a synonym for <>.

- Added function VERSION() to make easier logs.

- New multi-user test tests/fork_test.pl to put some strain on the thread library.

30-F-24 - Changements de la version 3.21.12

- Fixed ftruncate() call in MIT-pthreads. This made isamchk destroy the .ISM files on (Free)BSD 2.x systems.

- Fixed broken __P_ patch in MIT-pthreads.

- Many memory overrun checks. All string functions now return NULL if the returned string should be longer than max_allowed_packet bytes.

- Changed the name of the INTERVAL type to ENUM, because INTERVAL is used in SQL-99.

- In some cases, doing a JOIN + GROUP + INTO OUTFILE, the result wasn't grouped.

- LIKE with '_' as last character didn't work. Fixed.

- Added extended SQL-99 TRIM() function.

- Added CURTIME().

- Added ENCRYPT() function by Zeev Suraski.

- Fixed better FOREIGN KEY syntax skipping. New reserved words: MATCH, FULL, PARTIAL.

- mysqld now allows IP number and hostname for the --bind-address option.

- Added SET CHARACTER SET cp1251_koi8 to enable conversions of data to and from the cp1251_koi8 character set.

- Lots of changes for Windows 95 port. In theory, this version should now be easily portable to Windows 95.

- Changed the CREATE COLUMN syntax of NOT NULL columns to be after the DEFAULT value, as specified in the SQL-99 standard. This will make mysqldump with NOT NULL and default values incompatible with MySQL Version 3.20.

- Added many function name aliases so the functions can be used with ODBC or SQL-92 syntax.

- Fixed syntax of ALTER TABLE tbl_name ALTER COLUMN col_name SET DEFAULT NULL.

- Added CHAR and BIT as synonyms for CHAR(1).

- Fixed core dump when updating as a user who has only SELECT privilege.

- INSERT ... SELECT ... GROUP BY didn't work in some cases. An Invalid use of group function error occurred.

- When using LIMIT, SELECT now always uses keys instead of record scan. This will give better performance on SELECT and a WHERE that matches many rows.

- Added Russian error messages.

30-F-25 - Changements de la version 3.21.11

- Configure changes.

- MySQL now works with the new thread library on BSD/OS 3.0.

- Added new group functions BIT_OR() and BIT_AND().

- Added compatibility functions CHECK and REFERENCES. CHECK is now a reserved word.

- Added ALL option to GRANT for better compatibility. (GRANT is still a dummy function.)

- Added partly translated Dutch error messages.

- Fixed bug in ORDER BY and GROUP BY with NULL columns.

- Added function LAST_INSERT_ID() SQL function to retrieve last AUTO_INCREMENT value. This is intended for clients to ODBC that can't use the mysql_insert_id() API function, but can be used by any client.

- Added --flush-logs option to mysqladmin.

- Added command STATUS to mysql.

- Fixed problem with ORDER BY/GROUP BY because of bug in gcc.

- Fixed problem with INSERT ... SELECT ... GROUP BY.

30-F-26 - Changements de la version 3.21.10

- New program mysqlaccess.

- CREATE now supports all ODBC types and the mSQL TEXT type. All ODBC 2.5 functions are also supported (added REPEAT). This provides better portability.

- Added text types TINYTEXT, TEXT, MEDIUMTEXT and LONGTEXT. These are actually BLOBtypes, but all searching is done in case-insensitive fashion.

- All old BLOB fields are now TEXT fields. This only changes that all searching on strings is done in case-sensitive fashion. You must do an ALTER TABLE and change the datatype to BLOB if you want to have tests done in case-sensitive fashion.

- Fixed some configure issues.

- Made the locking code a bit safer. Fixed very unlikely deadlock situation.

- Fixed a couple of bugs in the range optimizer. Now the new range benchmark test-select works.

30-F-27 - Changements de la version 3.21.9

- Added --enable-unix-socket=pathname option to configure.

- Fixed a couple of portability problems with include files.

- Fixed bug in range calculation that could return empty set when searching on multiple key with only one entry (very rare).

- Most things ported to FSU Pthreads, which should allow MySQL to run on SCO. Voir Section 2.8.5.8, « Notes sur SCO ».

30-F-28 - Changements de la version 3.21.8

- Works now in Solaris 2.6.

- Added handling of calculation of SUM() functions. For example, you can now use SUM(column)/COUNT(column).

- Added handling of trigometric functions: PI(), ACOS(), ASIN(), ATAN(), COS(), SIN() and TAN().

- New languages: Norwegian, Norwegian-ny and Portuguese.

- Fixed parameter bug in net_print() in procedure.cc.

- Fixed a couple of memory leaks.

- Now allow also the old SELECT ... INTO OUTFILE syntax.

- Fixed bug with GROUP BY and SELECT on key with many values.

- mysql_fetch_lengths() sometimes returned incorrect lengths when you used mysql_use_result(). This affected at least some cases of mysqldump --quick.

- Fixed bug in optimization of WHERE const op field.

- Fixed problem when sorting on NULL fields.

- Fixed a couple of 64-bit (Alpha) problems.

- Added --pid-file=# option to mysqld.

- Added date formatting to FROM_UNIXTIME(), originally by Zeev Suraski.

- Fixed bug in BETWEEN in range optimizer (did only test = of the first argument).

- Added machine-dependent files for MIT-pthreads i386-SCO. There is probably more to do to get this to work on SCO 3.5.

30-F-29 - Changements de la version 3.21.7

- Changed Makefile.am to take advantage of Automake 1.2.

- Added the beginnings of a benchmark suite.

- Added more secure password handling.

- Added new client function mysql_errno(), to get the error number of the error message. This makes error checking in the client much easier. This makes the new server incompatible with the 3.20.x server when running without --old-protocol. The client code is backward-compatible. More information can be found in the README file!

- Fixed some problems when using very long, illegal names.

30-F-30 - Changements de la version 3.21.6

- Fixed more portability issues (incorrect sigwait and sigset defines).

- configure should now be able to detect the last argument to accept().

30-F-31 - Changements de la version 3.21.5

- Should now work with FreeBSD 3.0 if used with FreeBSD-3.0-libc_r-1.0.diff, which can be found at http://www.mysql.com/downloads/os-freebsd.html.

- Added new -O tmp_table_size=# option to mysqld.

- New function FROM_UNIXTIME(timestamp) which returns a date string in 'YYYY-MM-DD HH:MM:SS' format.

- New function SEC_TO_TIME(seconds) which returns a string in 'HH:MM:SS' format.

- New function SUBSTRING_INDEX(), originally by Zeev Suraski.

30-F-32 - Changements de la version 3.21.4

- Should now configure and compile on OSF/1 4.0 with the DEC compiler.

- Configuration and compilation on BSD/OS 3.0 works, but due to some bugs in BSD/OS 3.0, mysqld doesn't work on it yet.

- Configuration and compilation on FreeBSD 3.0 works, but I couldn't get pthread_create to work.

30-F-33 - Changements de la version 3.21.3

- Added reverse check lookup of hostnames to get better security.

- Fixed some possible buffer overflows if filenames that are too long are used.

- mysqld doesn't accept hostnames that start with digits followed by a '.', because the hostname may look like an IP number.

- Added --skip-networking option to mysqld, to allow only socket connections. (This will not work with MIT-pthreads!)

- Added check of too long table names for alias.

- Added check if database name is okay.

- Added check if too long table names.

- Removed incorrect free() that killed the server on CREATE DATABASE or DROP DATABASE.

- Changed some mysqld -O options to better names.

- Added -O join_cache_size=# option to mysqld.

- Added -O max_join_size=# option to mysqld, to be able to set a limit how big queries (in this case big = slow) one should be able to handle without specifying SET SQL_BIG_SELECTS=1. A # = is about 10 examined records. The default is « unlimited ».

- When comparing a TIME, DATE, DATETIME or TIMESTAMP column to a constant, the constant is converted to a time value before performing the comparison. This will make it easier to get ODBC (particularly Access97) to work with the above types. It should also make dates easier to use and the comparisons should be quicker than before.

- Applied patch from Jochen Wiedmann that allows query() in mysqlperl to take a query with \0 in it.

- Storing a timestamp with a 2-digit year (YYMMDD) didn't work.

- Fix that timestamp wasn't automatically updated if set in an UPDATE clause.

- Now the automatic timestamp field is the FIRST timestamp field.

- SELECT * INTO OUTFILE, which didn't correctly if the outfile already existed.

- mysql now shows the thread ID when starting or doing a reconnect.

- Changed the default sort buffer size from 2M to 1M.

30-F-34 - Changements de la version 3.21.2

- The range optimizer is coded, but only 85% tested. It can be enabled with --new, but it crashes core a lot yet...

- More portable. Should compile on AIX and alpha-digital. At least the isam library should be relatively 64-bit clean.

- New isamchk which can detect and fix more problems.

- New options for isamlog.

- Using new version of Automake.

- Many small portability changes (from the AIX and alpha-digital port) Better checking of pthread(s) library.

- czech error messages by <snajdr@pvt.net>.

- Decreased size of some buffers to get fewer problems on systems with little memory. Also added more checks to handle « out of memory » problems.

- mysqladmin: you can now do mysqladmin kill 5,6,7,8 to kill multiple threads.

- When the maximum connection limit is reached, one extra connection by a user with the process_acl privilege is granted.

- Added -O backlog=# option to mysqld.

- Increased maximum packet size from 512K to 1024K for client.

- Almost all of the function code is now tested in the internal test suite.

- ALTER TABLE now returns warnings from field conversions.

- Port changed to 3306 (got it reserved from ISI).

- Added a fix for Visual FoxBase so that any schema name from a table specification is automatically removed.

- New function ASCII().

- Removed function BETWEEN(a,b,c). Use the standard SQL syntax instead: expr BETWEEN expr AND expr.

- MySQL no longer has to use an extra temporary table when sorting on functions or SUM() functions.

- Fixed bug that you couldn't use tbl_name.field_name in UPDATE.

- Fixed SELECT DISTINCT when using 'hidden group'. For example:

mysql> SELECT DISTINCT MOD(some_field,10) FROM test
->        GROUP BY some_field;

Note: some_field is normally in the SELECT part. Standard SQL should require it.

30-F-35 - Changements de la version 3.21.0

- New reserved words used: INTERVAL, EXPLAIN, READ, WRITE, BINARY.

- Added ODBC function CHAR(num,...).

- New operator IN. This uses a binary search to find a match.

- New command LOCK TABLES tbl_name [AS alias] {READ|WRITE} ...

- Added --log-update option to mysqld, to get a log suitable for incremental updates.

- New command EXPLAIN SELECT ... to get information about how the optimizer will do the join.

- For easier client code, the client should no longer use FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB, FIELD_TYPE_LONG_BLOB or FIELD_TYPE_VAR_STRING (as previously returned by mysql_list_fields). You should instead only use FIELD_TYPE_BLOB or FIELD_TYPE_STRING. If you want exact types, you should use the command SHOW FIELDS.

- Added varbinary syntax: 0x###### which can be used as a string (default) or a number.

- FIELD_TYPE_CHAR is renamed to FIELD_TYPE_TINY.

- Changed all fields to C++ classes.

- Removed FORM struct.

- Fields with DEFAULT values no longer need to be NOT NULL.

- New field types:

- ENUM
A string which can take only a couple of defined values. The value is stored as a 1-3 byte number that is mapped automatically to a string. This is sorted according to string positions!

- SET
A string which may have one or many string values separated with ','. The string is stored as a 1-, 2-, 3-, 4- or 8-byte number where each bit stands for a specific set member. This is sorted according to the unsigned value of the stored packed number.

- Now all function calculation is done with double or long long. This will provide the full 64-bit range with bit functions and fix some conversions that previously could result in precision losses. One should avoid using unsigned long long columns with full 64-bit range (numbers bigger than 9223372036854775807) because calculations are done with signed long long.

- ORDER BY will now put NULL field values first. GROUP BY will also work with NULL values.

- Full WHERE with expressions.

- New range optimizer that can resolve ranges when some keypart prefix is constant. Example:

mysql> SELECT * FROM tbl_name
->          WHERE key_part_1="customer"
->          AND key_part_2>=10 AND key_part_2<=10;

30-G - Changements de la version 3.20.x

La version 3.20 est plutôt vieille, et doit être évitée si possible. Les informations de cette section sont conservées à des fins d'archives.

Les changements des versions 3.20.18 à 3.20.32b ne sont pas documentés ici, car la version 3.21 a commencé ici. Les modifications importantes sont documentés dans l'histoiriqe de la version 3.21.

30-G-1 - Changements de la version 3.20.18

- Added -p# (remove # directories from path) to isamlog. All files are written with a relative path from the database directory Now mysqld shouldn't crash on shutdown when using the --log-isam option.

- New mysqlperl version. It is now compatible with msqlperl-0.63.

- New DBD module available.

- Added group function STD() (standard deviation).

- The mysqld server is now compiled by default without debugging information. This will make the daemon smaller and faster.

- Now one usually only has to specify the --basedir option to mysqld. All other paths are relative in a normal installation.

- BLOB columns sometimes contained garbage when used with a SELECT on more than one table and ORDER BY.

- Fixed that calculations that are not in GROUP BY work as expected (SQL-99 extension). Example:

mysql> SELECT id,id+1 FROM table GROUP BY id;

- The test of using MYSQL_PWD was reversed. Now MYSQL_PWD is enabled as default in the default release.

- Fixed conversion bug which caused mysqld to core dump with Arithmetic error on SPARC-386.

- Added --unbuffered option to mysql, for new mysqlaccess.

- When using overlapping (unnecessary) keys and join over many tables, the optimizer could get confused and return 0 records.

30-G-2 - Changements de la version 3.20.17

- You can now use BLOB columns and the functions IS NULL and IS NOT NULL in the WHERE clause.

- All communication packets and row buffers are now allocated dynamically on demand. The default value of max_allowed_packet is now 64K for the server and 512K for the client. This is mainly used to catch incorrect packets that could trash all memory. The server limit may be changed when it is started.

- Changed stack usage to use less memory.

- Changed safe_mysqld to check for running daemon.

- The ELT() function is renamed to FIELD(). The new ELT() function returns a value based on an index: FIELD() is the inverse of ELT() Example: ELT(2,"A","B","C") returns "B". FIELD("B","A","B","C") returns 2.

- COUNT(field), where field could have a NULL value, now works.

- A couple of bugs fixed in SELECT ... GROUP BY.

- Fixed memory overrun bug in WHERE with many unoptimizable brace levels.

- Fixed some small bugs in the grant code.

- If hostname isn't found by get_hostname, only the IP is checked. Previously, you got Access denied.

- Inserts of timestamps with values didn't always work.

- INSERT INTO ... SELECT ... WHERE could give the error Duplicated field.

- Added some tests to safe_mysqld to make it « safer ».

- LIKE was case-sensitive in some places and case-insensitive in others. Now LIKE is always case-insensitive.

- mysql.cc: Allow '#' anywhere on the line.

- New command SET SQL_SELECT_LIMIT=#. Voir the FAQ for more details.

- New version of the mysqlaccess script.

- Change FROM_DAYS() and WEEKDAY() to also take a full TIMESTAMP or DATETIME as argument. Before they only took a number of type YYYYMMDD or YYMMDD.

- Added new function UNIX_TIMESTAMP(timestamp_column).

30-G-3 - Changements de la version 3.20.16

- More changes in MIT-pthreads to get them safer. Fixed also some link bugs at least in SunOS.

- Changed mysqld to work around a bug in MIT-pthreads. This makes multiple small SELECT operations 20 times faster. Now lock_test.pl should work.

- Added mysql_FetchHash(handle) to mysqlperl.

- The mysqlbug script is now distributed built to allow for reporting bugs that appear during the build with it.

- Changed libmysql.c to prefer getpwuid() instead of cuserid().

- Fixed bug in SELECT optimizer when using many tables with the same column used as key to different tables.

- Added new latin2 and Russian KOI8 character tables.

- Added support for a dummy GRANT command to satisfy Powerbuilder.

30-G-4 - Changements de la version 3.20.15

- Fixed fatal bug packets out of order when using MIT-pthreads.

- Removed possible loop when a thread waits for command from client and fcntl() fails. Thanks to Mike Bretz for finding this bug.

- Changed alarm loop in mysqld.cc because shutdown didn't always succeed in Linux.

- Removed use of termbits from mysql.cc. This conflicted with glibc 2.0.

- Fixed some syntax errors for at least BSD and Linux.

- Fixed bug when doing a SELECT as superuser without a database.

- Fixed bug when doing SELECT with group calculation to outfile.

30-G-5 - Changements de la version 3.20.14

- If one gives -p or --password option to mysql without an argument, the user is solicited for the password from the tty.

- Added default password from MYSQL_PWD (by Elmar Haneke).

- Added command kill to mysqladmin to kill a specific MySQL thread.

- Sometimes when doing a reconnect on a down connection this succeeded first on second try.

- Fixed adding an AUTO_INCREMENT key with ALTER_TABLE.

- AVG() gave too small value on some SELECT statements with GROUP BY and ORDER BY.

- Added new DATETIME type (by Giovanni Maruzzelli <maruzz@matrice.it>).

- Fixed that defining DONT_USE_DEFAULT_FIELDS works.

- Changed to use a thread to handle alarms instead of signals on Solaris to avoid race conditions.

- Fixed default length of signed numbers. (George Harvey <georgeh@pinacl.co.uk>.)

- Allow anything for CREATE INDEX.

- Add prezeros when packing numbers to DATE, TIME and TIMESTAMP.

- Fixed a bug in OR of multiple tables (gave empty set).

- Added many patches to MIT-pthreads. This fixes at least one lookup bug.

30-G-6 - Changements de la version 3.20.13

- Added standard SQL-92 DATE and TIME types.

- Fixed bug in SELECT with AND-OR levels.

- Added support for Slovenian characters. The Contrib directory contains source and instructions for adding other character sets.

- Fixed bug with LIMIT and ORDER BY.

- Allow ORDER BY and GROUP BY on items that aren't in the SELECT list. (Thanks to Wim Bonis <bonis@kiss.de>, for pointing this out.)

- Allow setting of timestamp values in INSERT.

- Fixed bug with SELECT ... WHERE ... = NULL.

- Added changes for glibc 2.0. To get glibc to work, you should add the gibc-2.0-sigwait-patch before compiling glibc.

- Fixed bug in ALTER TABLE when changing a NOT NULL field to allow NULL values.

- Added some SQL-92 synonyms as field types to CREATE TABLE. CREATE TABLE now allows FLOAT(4) and FLOAT(8) to mean FLOAT and DOUBLE.

- New utility program mysqlaccess by <Yves.Carlier@rug.ac.be>. This program shows the access rights for a specific user and the grant rows that determine this grant.

- Added WHERE const op field (by <bonis@kiss.de>).

30-G-7 - Changements de la version 3.20.11

- When using SELECT ... INTO OUTFILE, all temporary tables are ISAM instead of HEAP to allow big dumps.

- Changed date functions to be string functions. This fixed some « funny » side effects when sorting on dates.

- Extended ALTER TABLE for SQL-92 compliance.

- Some minor compatibility changes.

- Added --port and --socket options to all utility programs and mysqld.

- Fixed MIT-pthreads readdir_r(). Now mysqladmin create database and mysqladmin drop database should work.

- Changed MIT-pthreads to use our tempnam(). This should fix the « sort aborted » bug.

- Added sync of records count in sql_update. This fixed slow updates on first connection. (Thanks to Vaclav Bittner for the test.)

30-G-8 - Changements de la version 3.20.10

- New insert type: INSERT INTO ... SELECT ...

- MEDIUMBLOB fixed.

- Fixed bug in ALTER TABLE and BLOB values.

- SELECT ... INTO OUTFILE now creates the file in the current database directory.

- DROP TABLE now can take a list of tables.

- Oracle synonym DESCRIBE (DESC).

- Changes to make_binary_distribution.

- Added some comments to installation instructions about configure's C++ link test.

- Added --without-perl option to configure.

- Lots of small portability changes.

30-G-9 - Changements de la version 3.20.9

- ALTER TABLE didn't copy null bit. As a result, fields that were allowed to have NULL values were always NULL.

- CREATE didn't take numbers as DEFAULT.

- Some compatibility changes for SunOS.

- Removed config.cache from old distribution.

30-G-10 - Changements de la version 3.20.8

- Fixed bug with ALTER TABLE and multi-part keys.

30-G-11 - Changements de la version 3.20.7

- New commands: ALTER TABLE, SELECT ... INTO OUTFILE and LOAD DATA INFILE.

- New function: NOW().

- Added new field File_priv to mysql/user table.

- New script add_file_priv which adds the new field File_priv to the user table. This script must be executed if you want to use the new SELECT ... INTO and LOAD DATA INFILE ... commands with a version of MySQL earlier than 3.20.7.

- Fixed bug in locking code, which made lock_test.pl test fail.

- New files NEW and BUGS.

- Changed select_test.c and insert_test.c to include config.h.

- Added status command to mysqladmin for short logging.

- Increased maximum number of keys to 16 and maximum number of key parts to 15.

- Use of sub keys. A key may now be a prefix of a string field.

- Added -k option to mysqlshow, to get key information for a table.

- Added long options to mysqldump.

30-G-12 - Changements de la version 3.20.6

- Portable to more systems because of MIT-pthreads, which will be used automatically if configure cannot find a -lpthreads library.

- Added GNU-style long options to almost all programs. Test with program --help.

- Some shared library support for Linux.

- The FAQ is now in .texi format and is available in .html, .txt and .ps formats.

- Added new SQL function RAND([init]).

- Changed sql_lex to handle \0 unquoted, but the client can't send the query through the C API, because it takes a str pointer. You must use mysql_real_query() to send the query.

- Added API function mysql_get_client_info().

- mysqld now uses the N_MAX_KEY_LENGTH from nisam.h as the maximum allowable key length.

- The following now works:

mysql> SELECT filter_nr,filter_nr FROM filter ORDER BY filter_nr;

Previously, this resulted in the error: Column: 'filter_nr' in order clause is ambiguous.

- mysql now outputs '\0', '\t', '\n' and '\\' when encountering ASCII 0, tab, newline or '\' while writing tab-separated output. This is to allow printing of binary data in a portable format. To get the old behavior, use -r (or --raw).

- Added german error messages (60 of 80 error messages translated).

- Added new API function mysql_fetch_lengths(MYSQL_RES *), which returns an array of column lengths (of type uint).

- Fixed bug with IS NULL in WHERE clause.

- Changed the optimizer a little to get better results when searching on a key part.

- Added SELECT option STRAIGHT_JOIN to tell the optimizer that it should join tables in the given order.

- Added support for comments starting with '--' in mysql.cc (Postgres syntax).

- You can have SELECT expressions and table columns in a SELECT which are not used in the group part. This makes it efficient to implement lookups. The column that is used should be a constant for each group because the value is calculated only once for the first row that is found for a group.

mysql> SELECT id,lookup.text,SUM(*) FROM test,lookup
->        WHERE test.id=lookup.id GROUP BY id;

- Fixed bug in SUM(function) (could cause a core dump).

- Changed AUTO_INCREMENT placement in the SQL query:

INSERT INTO table (auto_field) VALUES (0);

inserted 0, but it should insert an AUTO_INCREMENT value.

- mysqlshow.c: Added number of records in table. Had to change the client code a little to fix this.

- mysql now allows doubled '' or "" within strings for embedded ' or ".

- New math functions: EXP(), LOG(), SQRT(), ROUND(), CEILING().

30-G-13 - Changements de la version 3.20.3

- The configure source now compiles a thread-free client library -lmysqlclient. This is the only library that needs to be linked with client applications. When using the binary releases, you must link with -lmysql -lmysys -ldbug -lmystrings as before.

- New readline library from bash-2.0.

- LOTS of small changes to configure and makefiles (and related source).

- It should now be possible to compile in another directory using VPATH. Tested with GNU Make 3.75.

- safe_mysqld and mysql.server changed to be more compatible between the source and the binary releases.

- LIMIT now takes one or two numeric arguments. If one argument is given, it indicates the maximum number of rows in a result. If two arguments are given, the first argument indicates the offset of the first row to return, the second is the maximum number of rows. With this it's easy to do a poor man's next page/previous page WWW application.

- Changed name of SQL function FIELDS() to ELT(). Changed SQL function INTERVALL() to INTERVAL().

- Made SHOW COLUMNS a synonym for SHOW FIELDS. Added compatibility syntax FRIEND KEY to CREATE TABLE. In MySQL, this creates a non-unique key on the given columns.

- Added CREATE INDEX and DROP INDEX as compatibility functions. In MySQL, CREATE INDEX only checks if the index exists and issues an error if it doesn't exist. DROP INDEX always succeeds.

- mysqladmin.c: added client version to version information.

- Fixed core dump bug in sql_acl (core on new connection).

- Removed host, user and db tables from database test in the distribution.

- FIELD_TYPE_CHAR can now be signed (-128 to 127) or unsigned (0 to 255) Previously, it was always unsigned.

- Bug fixes in CONCAT() and WEEKDAY().

- Changed a lot of source to get mysqld to be compiled with SunPro compiler.

- SQL functions must now have a '(' immediately after the function name (no intervening space). For example, 'USER(' is regarded as beginning a function call, and 'USER (' is regarded as an identifier USER followed by a '(', not as a function call.

30-G-14 - Changements de la version 3.20.0

- The source distribution is done with configure and Automake. It will make porting much easier. The readline library is included in the distribution.

- Separate client compilation: the client code should be very easy to compile on systems which don't have threads.

- The old Perl interface code is automatically compiled and installed. Automatic compiling of DBD will follow when the new DBD code is ported.

- Dynamic language support: mysqld can now be started with Swedish or English (default) error messages.

- New functions: INSERT(), RTRIM(), LTRIM() and FORMAT().

- mysqldump now works correctly for all field types (even AUTO_INCREMENT). The format for SHOW FIELDS FROM tbl_name is changed so the Type column contains information suitable for CREATE TABLE. In previous releases, some CREATE TABLE information had to be patched when re-creating tables.

- Some parser bugs from 3.19.5 (BLOB and TIMESTAMP) are corrected. TIMESTAMP now returns different date information depending on its create length.

- Changed parser to allow a database, table or field name to start with a number or '_'.

- All old C code from Unireg changed to C++ and cleaned up. This makes the daemon a little smaller and easier to understand.

- A lot of small bug fixes done.

- New INSTALL files (not final version) and some information regarding porting.

30-H - Changements de la version 3.19.x

La version 3.19 est plutôt vieille, et doit être évitée si possible. Les informations de cette section sont conservées à des fins d'archives.

30-H-1 - Changements de la version 3.19.5

- Some new functions, some more optimization on joins.

- Should now compile clean on Linux (2.0.x).

- Added functions DATABASE(), USER(), POW(), LOG10() (needed for ODBC).

- In a WHERE with an ORDER BY on fields from only one table, the table is now preferred as first table in a multi-join.

- HAVING and IS NULL or IS NOT NULL now works.

- A group on one column and a sort on a group function (SUM(), AVG()...) didn't work together. Fixed.

- mysqldump: Didn't send password to server.

30-H-2 - Changements de la version 3.19.4

- Fixed horrible locking bug when inserting in one thread and reading in another thread.

- Fixed one-off decimal bug. 1.00 was output as 1.0.

- Added attribute 'Locked' to process list as information if a query is locked by another query.

- Fixed full magic timestamp. Timestamp length may now be 14, 12, 10, 8, 6, 4 or 2 bytes.

- Sort on some numeric functions could sort incorrectly on last number.

- IF(arg,syntax_error,syntax_error) crashed.

- Added functions CEILING(), ROUND(), EXP(), LOG() and SQRT().

- Enhanced BETWEEN to handle strings.

30-H-3 - Changements de la version 3.19.3

- Fixed SELECT with grouping on BLOB columns not to return incorrect BLOB info. Grouping, sorting and distinct on BLOB columns will not yet work as expected (probably it will group/sort by the first 7 characters in the BLOB). Grouping on formulas with a fixed string size (use MID() on a BLOB) should work.

- When doing a full join (no direct keys) on multiple tables with BLOB fields, the BLOB was garbage on output.

- Fixed DISTINCT with calculated columns.

30-I - Evolutions de InnoDB

Depuis les versions 4.0.22 et 4.1.5, toutes les évolutions de InnoDB sont incluses dans l'historique de MySQL, et cette section ne sera plus gérée indépendamment.

Note : cette section n'est pas traduite en français.

30-I-1 - MySQL/InnoDB-4.0.21, pas publiée

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- If you configure innodb_additional_mem_pool_size so small that InnoDB memory allocation spills over from it, then every 4 billionth spill may cause memory corruption. A symptom is a printout like below in the .err log. The workaround is to make innodb_additional_mem_pool_size big enough to hold all memory allocation. Use SHOW INNODB STATUS to determine that there is plenty of free space available in the additional mem pool, and the total allocated memory stays rather constant.

InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the
InnoDB: previous allocated area!
InnoDB: Apparent memory corruption: mem dump  len 500; hex

30-I-2 - MySQL/InnoDB-4.1.4, 31 Août 2004

Fonctionnalité ajoutée ou modifiée :

- Important: Made internal representation of TIMESTAMP values in InnoDB in 4.1 to be the same as in 4.0. This difference resulted in incorrect datetime values in TIMESTAMP columns in InnoDB tables after an upgrade from 4.0 to 4.1. (Bug #4492) Warning: extra steps during upgrade required! This means that if you are upgrading from 4.1.x, where x <= 3, to 4.1.4 you should use mysqldump for saving and then restoring your InnoDB tables with TIMESTAMP columns. No conversion is needed if you upgrade from 3.23 or 4.0 to 4.1.4 or later.

- Added a new startup option innodb_locks_unsafe_for_binlog. This option forces InnoDB not to use next-key locking in searches and index scans.

- Added innodb_status_file system variable to mysqld to control whether output from SHOW INNODB STATUS is written to a innodb_status.<pid> file in the data directory. By default, the file is not created. To create it, start mysqld with the --innodb_status_file=1 option.

- Changes for NetWare to exit InnoDB gracefully on NetWare even in a case of an assertion failure, instead of intentionally crashing the mysqld server process.

Bogues corrigés :

- Fixed a bug in ON DELETE CASCADE and ON UPDATE CASCADE foreign key constraints: long chains of cascaded operations would cause a stack overflow and crash the server. Cascaded operations are now limited to 15 levels. (Bug #4446)

- Increment the InnoDB watchdog timeout during CHECK TABLE. (Bug #2694)

- If you configure innodb_additional_mem_pool_size so small that InnoDB memory allocation spills over from it, then every 4 billionth spill may cause memory corruption. A symptom is a printout like below in the .err log.

InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the
InnoDB: previous allocated area!
InnoDB: Apparent memory corruption: mem dump  len 500; hex

- Fixed a glitch introduced in 4.0.18 and 4.1.2: in SHOW TABLE STATUS InnoDB systematically overestimated the row count by 1 if the table fit on a single 16 kB data page.

- InnoDB created temporary files with the C library function tmpfile(). On Windows, the files would be created in the root directory of the current file system. To correct this behavior, the invocations of tmpfile() were replaced with code that uses the function create_temp_file() in the MySQL portability layer. (Bug #3998)

- If we RENAMEd a table, InnoDB forgot to load the foreign key constraints that reference the new table name, and forgot to check that they are compatible with the table.

- If there was little file I/O in InnoDB, but the insert buffer was used, it could happen that 'Pending normal aio reads' was bigger than 0, but the I/O handler thread did not get waken up in 600 seconds. This resulted in a hang, and an intentional crashing of mysqld.

30-I-3 - MySQL/InnoDB-4.1.3, 28 Juin 2004

Fonctionnalité ajoutée ou modifiée :

- Important: Starting from MySQL 4.1.3, InnoDB uses the same character set comparison functions as MySQL for non-latin1_swedish_ci character strings that are not BINARY. This changes the sorting order of space and characters < ASCII(32) in those character sets. For latin1_swedish_ci character strings and BINARY strings, InnoDB uses its own pad-spaces-at-end comparison method, which stays unchanged. If you have an InnoDB table created with MySQL 4.1.2 or earlier, with an index on a non-latin1 character set (in the case of 4.1.0 and 4.1.1 with any character set) CHAR/VARCHAR/or TEXT column that is not BINARY but may contain characters < ASCII(32), then you should do ALTER TABLE or OPTIMIZE table on it to regenerate the index, after upgrading to MySQL 4.1.3 or later.

- OPTIMIZE TABLE for InnoDB tables is now mapped to ALTER TABLE rather than to ANALYZE TABLE.

- Added an interface for storing the binlog offset in the InnoDB log and flushing the log.

Bogues corrigés :

- The critical bug in 4.1.2 (crash recovery skipping all .ibd files if you specify innodb_file_per_table on Unix) has been fixed. The bug was a combination of two bugs. Crash recovery ignored the files, because the attempt to lock them in the wrong mode failed. From now on, locks will only be obtained for regular files opened in read/write mode, and crash recovery will stop if an .ibd file for a table exists in a database directory but is unaccessible.

- Do not remember the original select_lock_type inside LOCK TABLES. (Bug #4047)

- The special meaning of the table names innodb_monitor, innodb_lock_monitor, innodb_tablespace_monitor, innodb_table_monitor, and innodb_validate in CREATE TABLE and DROP TABLE statements was accidentally removed in MySQL/InnoDB-4.1.2. The diagnostic functions attached to these special table names (Voir Section 15.12.1, « Le moniteur InnoDB ») are accessible again in MySQL/InnoDB-4.1.3.

- When the private SQL parser of InnoDB was modified in MySQL/InnoDB-4.0.19 in order to allow the use of the apostrophe (''') in table and column names, the fix relied on a previously unused function mem_realloc(), whose implementation was incorrect. As a result, InnoDB can incorrectly parse column and table names as the empty string. The InnoDB realloc() implementation has been corrected in MySQL/InnoDB-4.1.3.

- In a clean-up of MySQL/InnoDB-4.1.2, the code for invalidating the query cache was broken. Now the query cache should be correctly invalidated for tables affected by ON UPDATE CASCADE or ON DELETE CASCADE constraints.

- Fixed a bug : in LIKE 'abc%', the '%' did not match the empty string if the character set was not latin1_swedish_ci. This bug was fixed by changing the sorting order in these character sets. Voir the above note about data conversion in 4.1.3.

30-I-4 - MySQL/InnoDB-4.1.2, pas publiée

Fonctionnalité ajoutée ou modifiée :

- Do not assert in log0log.c, line 856 if ib_logfiles are too small for innodb_thread_concurrency. Instead, print instructions how to adjust my.cnf and call exit(1).

- If MySQL tries to SELECT from an InnoDB table without setting any table locks, print a descriptive error message and assert; some subquery bugs were of this type.

- Added a missing space to the output format of SHOW INNODB STATUS; reported by Jocelyn Fournier.

- Support multiple character sets. Note that tables created in other collations than latin1_swedish_ci cannot be accessed in MySQL/InnoDB 4.0.

- Allow a key path length in InnoDB to be up to 3,500 bytes; this is needed so that one can create an index on a column with 255 UTF-8 characters.

Bogues corrigés :

- Improved portability to 64-bit platforms, especially Win64.

- Fixed an assertion failure when a purge of a table was not possible because of missing .ibd file.

- Fixed a bug : do not retrieve all columns in a table if we only need the 'ref' of the row (usually, the PRIMARY KEY) to calculate an ORDER BY. (Bug #1942)

- On Unix-like systems, obtain an exclusive advisory lock on InnoDB files, to prevent corruption when multiple instances of MySQL are running on the same set of data files. The Windows version of InnoDB already took a mandatory lock on the files. (Bug #3608)

- All bugfixes from InnoDB-4.0.17, InnoDB-4.0.18, InnoDB-4.0.19 and InnoDB-4.0.20.

30-I-5 - MySQL/InnoDB-4.0.20, 18 mai 2004

Bogues corrigés :

- Make LOCK TABLE aware of InnoDB row-level locks. (Bug #3299)

- Fixed race conditions in SHOW INNODB STATUS. (Bug #3596)

30-I-6 - MySQL/InnoDB-4.0.19, 4 mai 2004

Fonctionnalit? ajout?e ou modifi?e :

- Better error message when the server has to crash because the buffer pool is exhausted by the lock table or the adaptive hash index.

- Print always the count of pending pread() and pwrite() calls if there is a long semaphore wait.

- Improve space utilization when rows of 1,500 to 8,000 bytes are inserted in the order of the primary key.

- Remove potential buffer overflow errors by sending diagnostic output to stderr or files instead of stdout or fixed-size memory buffers. As a side effect, the output of SHOW INNODB STATUS will be written to a file <datadir>/innodb.status.<pid> every 15 seconds.

Bogues corrig?s :

- Fixed a bug : DROP DATABASE did not work if FOREIGN KEY references were defined within the database. (Bug #3058)

- Remove unnecessary files, functions and variables. Many of these were needed in the standalone version of InnoDB. Remove debug functions and variables from non-debug build.

- Add diagnostic code to analyze an assertion failure in ha_innodb.cc on line 2020 reported by a user. (Bug #2903)

- Fixed a bug : in a FOREIGN KEY, ON UPDATE CASCADE was not triggered if the update changed a string to another value identical in alphabetical ordering, e.g., 'abc' -> 'aBc'.

- Protect the reading of the latest foreign key error explanation buffer with a mutex; in theory, a race condition could cause SHOW INNODB STATUS print garbage characters after the error info.

- Fixed a bug : The row count and key cardinality estimate was grossly too small if each clustered index page only contained one record.

- Parse CONSTRAINT FOREIGN KEY correctly. (Bug #3332)

- Fixed a memory corruption bug on Windows. The bug is present in all InnoDB versions in Windows, but it depends on how the linker places a static array in srv0srv.c, whether the bug shows itself. 4 bytes were overwritten with a pointer to a statically allocated string 'get windows aio return value'.

- Fix a glitch reported by Philippe Lewicki on the general mailing list: do not print a warning to the .err log if read_key fails with a lock wait timeout error 146.

- Allow quotes to be embedded in strings in the private SQL parser of InnoDB, so that ''' can be used in InnoDB table and column names. Display quotes within identifiers properly.

- Debugging: Allow UNIV_SYNC_DEBUG to be disabled while UNIV_DEBUG is enabled.

- Debugging: Handle magic numbers in a more consistent way.

30-I-7 - MySQL/InnoDB-4.0.18, 13 février 2004

- Do not allow dropping a table referenced by a FOREIGN KEY constraint, unless the user does SET FOREIGN_KEY_CHECKS=0. The error message here is somewhat misleading « Cannot delete or update a parent row... », and must be changed in a future version 4.1.x.

- Make InnoDB to remember the CONSTRAINT name given by a user for a FOREIGN KEY.

- Change the print format of FOREIGN KEY constraints spanning multiple databases to `db_name`.`tbl_name`. But when parsing them, we must also accept `db_name.tbl_name`, because that was the output format in < 4.0.18.

- An optimization in locking: If AUTOCOMMIT=1, then we do not need to make a plain SELECT set shared locks even on the SERIALIZABLE isolation level, because we know that the transaction is read-only. A read-only transaction can always be performed on the REPEATABLE READ level, and that does not endanger the serializability.

- Implement an automatic downgrade from >= 4.1.1 -> 4.0.18 if the user has not created tables in .ibd files or used other 4.1.x features. Consult the manual section on multiple tablespaces carefully if you want to downgrade!

- Fixed a bug : MySQL should not allow REPLACE to internally perform an UPDATE if the table is referenced by a FOREIGN KEY. The MySQL manual states that REPLACE must resolve a duplicate-key error semantically with DELETE(s) + INSERT, and not by an UPDATE. In versions < 4.0.18 and < 4.1.2, MySQL could resolve a duplicate key conflict in REPLACE by doing an UPDATE on the existing row, and FOREIGN KEY checks could behave in a semantically wrong way. (Bug #2418)

- Fixed a bug : generate FOREIGN KEY constraint identifiers locally for each table, in the form db_name/tbl_name_ibfk_number. If the user gives the constraint name explicitly, then remember it. These changes should ensure that foreign key id's in a slave are the same as in the master, and DROP FOREIGN KEY does not break replication. (Bug #2167)

- Fixed a bug : allow quoting of identifiers in InnoDB's FOREIGN KEY definitions with a backtick (`) and a double quote ("). You can now use also spaces in table and column names, if you quote the identifiers. (Bug #1725, Bug #2424)

- Fixed a bug : FOREIGN KEY ... ON UPDATE/DELETE NO ACTION must check the foreign key constraint, not ignore it. Since we do not have deferred constraints in InnoDB, this bugfix makes InnoDB to check NO ACTION constraints immediately, like it checks RESTRICT constraints.

- Fixed a bug : InnoDB crashed in RENAME TABLE if 'db_name.tbl_name' is shorter than 5 characters. (Bug #2689)

- Fixed a bug : in SHOW TABLE STATUS, InnoDB row count and index cardinality estimates wrapped around at 512 million in 32-bit computers. Note that unless MySQL is compiled with the BIG_TABLES option, they will still wrap around at 4 billion.

- Fixed a bug : If there was a UNIQUE secondary index, and NULL values in that unique index, then with the IS NULL predicate, InnoDB returned only the first matching row, though there can be many. This bug was introduced in 4.0.16. (Bug #2483)

30-I-8 - MySQL/InnoDB-5.0.0, 24 décembre 2003

- IMPORTANT NOTE: if you upgrade to InnoDB-4.1.1 or higher, you cannot downgrade to a version lower than 4.1.1 any more! That is because earlier versions of InnoDB are not aware of multiple tablespaces.

- InnoDB in 5.0.0 is essentially the same as InnoDB-4.1.1 with the bug fixes of InnoDB-4.0.17 included.

30-I-9 - MySQL/InnoDB-4.0.17, 17 décembre 2003

- Fixed a bug : if you created a column prefix secondary index and updated it so that the last characters in the column prefix were spaces, InnoDB would assert in row0upd.c, line 713. The same assertion failed if you updated a column in an ordinary secondary index so that the new value was alphabetically equivalent, but had a different length. This could happen, for example, in the utf-8 character set if you updated a letter to its accented or umlaut form.

- Fixed a bug : InnoDB could think that a secondary index record was not locked though it had been updated to an alphabetically equivalent value, e.g., 'abc' -> 'aBc'.

- Fixed a bug : if you updated a secondary index column to an alphabetically equivalent value, and rolled back your update, InnoDB failed to restore the field in the secondary index to its original value.

- There are still several outstanding non-critical bugs reported in the MySQL bugs database. Their fixing has been delayed, because resources were allocated to the 4.1.1 release.

30-I-10 - MySQL/InnoDB-4.1.1, 4 décembre 2003

- IMPORTANT NOTE: if you upgrade to InnoDB-4.1.1 or higher, you cannot downgrade to a version lower than 4.1.1 any more! That is because earlier versions of InnoDB are not aware of multiple tablespaces.

- Multiple tablespaces now available for InnoDB. You can store each InnoDB type table and its indexes into a separate .ibd file into a MySQL database directory, into the same directory where the .frm file is stored.

- The MySQL query cache now works for InnoDB tables also if AUTOCOMMIT=0, or the statements are enclosed inside BEGIN ... COMMIT.

- Reduced InnoDB memory consumption by a few megabytes if one sets the buffer pool size < 8 MB.

- You can use raw disk partitions also in Windows.

30-I-11 - MySQL/InnoDB-4.0.16, 22 octobre 2003

- Fixed a bug : in contrary to what was said in the manual, in a locking read InnoDB set two record locks if a unique exact match search condition was used on a multi-column unique key. For a single column unique key it worked right.

- Fixed a bug : if one used the rename trick #sql... -> rsql... to recover a temporary table, InnoDB asserted in row_mysql_lock_data_dictionary().

- There are several outstanding non-critical bugs reported in the MySQL bugs database. Their fixing has been delayed, because resources are allocated to the upcoming 4.1.1 release.

30-I-12 - MySQL/InnoDB-3.23.58, 15 septembre 2003

- Fixed a bug : InnoDB could make the index page directory corrupt in the first B-tree page splits after mysqld startup. A symptom would be an assertion failure in page0page.c, in function page_dir_find_slot().

- Fixed a bug : InnoDB could in rare cases return an extraneous row if a rollback, purge, and a SELECT coincided.

- Fixed a possible hang over the btr0sea.c latch if SELECT was used inside LOCK TABLES.

- Fixed a bug : If a single DELETE statement first managed to delete some rows and then failed in a FOREIGN KEY error or a Table is full error, MySQL did not roll back the whole SQL statement as it should.

30-I-13 - MySQL/InnoDB-4.0.15, 10 septembre 2003

- Fixed a bug : if you updated a row so that the 8000 byte maximum length (without BLOB and TEXT) was exceeded, InnoDB simply removed the record from the clustered index. In a similar insert, InnoDB would leak reserved file space extents, which would only be freed at the next mysqld startup.

- Fixed a bug : if you used big BLOB values, and your log files were relatively small, InnoDB could in a big BLOB operation temporarily write over the log produced after the latest checkpoint. If InnoDB would crash at that moment, then the crash recovery would fail, because InnoDB would not be able to scan the log even up to the latest checkpoint. Starting from this version, InnoDB tries to ensure the latest checkpoint is young enough. If that is not possible, InnoDB prints a warning to the .err log of MySQL and advises you to make the log files bigger.

- Fixed a bug : setting innodb_fast_shutdown=0 had no effect.

- Fixed a bug introduced in 4.0.13: if a CREATE TABLE ended in a comment, that could cause a memory overrun.

- Fixed a bug : If InnoDB printed Operating system error number .. in a file operation to the .err log in Windows, the error number explanation was wrong. Workaround: look at section 13.2 of http://www.innodb.com/ibman.php about Windows error numbers.

- Fixed a bug : If you created a column prefix PRIMARY KEY like in t(a CHAR(200), PRIMARY KEY (a(10))) on a fixed-length CHAR column, InnoDB would crash even in a simple SELECT. CCHECK TABLE would report the table as corrupt, also in the case where the created key was not PRIMARY.

30-I-14 - MySQL/InnoDB-4.0.14, 22 juillet 2003

- InnoDB now supports the SAVEPOINT and ROLLBACK TO SAVEPOINT SQL statements. Voir http://www.innodb.com/ibman.php#Savepoints for the syntax.

- You can now create column prefix keys like in CREATE TABLE t (a BLOB, INDEX (a(10))).

- You can also use O_DIRECT as the innodb_flush_method on the latest versions of Linux and FreeBSD. Beware of possible bugs in those operating systems, though.

- Fixed the checksum calculation of data pages. Previously most OS file system corruption went unnoticed. Note that if you downgrade from version >= 4.0.14 to an earlier version < 4.0.14 then in the first startup(s) InnoDB will print warnings:

InnoDB: Warning: an inconsistent page in the doublewrite buffer
InnoDB: space id 2552202359 page number 8245, 127'th page in dblwr buf.

but that is not dangerous and can be ignored.

- Modified the buffer pool replacement algorithm so that it tries to flush modified pages if there are no replaceable pages in the last 10 % of the LRU list. This can reduce disk i/o if the workload is a mixture of reads and writes.

- The buffer pool checkpoint flush algorithm now tries to flush also close neighbors of the page at the end of the flush list. This can speed up database shutdown, and can also speed up disk writes if InnoDB log files are very small compared to the buffer pool size.

- In 4.0.13 we made SHOW INNODB STATUS to print detailed info on the latest UNIQUE KEY error, but storing that info could slow down REPLACE significantly. We no longer store or print the info.

- Fixed a bug : SET FOREIGN_KEY_CHECKS=0 was not replicated properly in the MySQL replication. The fix will not be backported to 3.23.

- Fixed a bug : the parameter innodb_max_dirty_pages_pct forgot to take into account the free pages in the buffer pool. This could lead to excessive flushing even though there were lots of free pages in the buffer pool. Workaround: SET GLOBAL innodb_max_dirty_pages_pct = 100.

- Fixed a bug : if there were big index scans then a file read request could starve and InnoDB could assert because of a very long semaphore wait.

- Fixed a bug : if AUTOCOMMIT=1 then inside LOCK TABLES MySQL failed to do the commit after an updating SQL statement if binlogging was not on, and for SELECT statements did not commit regardless of binlogging state.

- Fixed a bug : InnoDB could make the index page directory corrupt in the first B-tree page splits after a mysqld startup. A symptom would be an assertion in page0page.c, in function page_dir_find_slot().

- Fixed a bug : if in a FOREIGN KEY with an UPDATE CASCADE clause the parent column was of a different internal storage length than the child column, then a cascaded update would make the column length wrong in the child table and corrupt the child table. Because of MySQL's 'silent column specification changes' a fixed-length CHAR column can change internally to a VARCHAR and cause this error.

- Fixed a bug : if a non-latin1 character set was used and if in a FOREIGN KEY the parent column was of a different internal storage length than the child column, then all inserts to the child table would fail in a foreign key error.

- Fixed a bug : InnoDB could complain that it cannot find the clustered index record, or in rare cases return an extraneous row if a rollback, purge, and a SELECT coincided.

- Fixed a possible hang over the btr0sea.c latch if SELECT was used inside LOCK TABLES.

- Fixed a bug : contrary to what the release note of 4.0.13 said, the group commit still did not work if the MySQL binlogging was on.

- Fixed a bug : os_event_wait() did not work properly in Unix, which might have caused starvation in various log operations.

- Fixed a bug : if a single DELETE statement first managed to delete some rows and then failed in a FOREIGN KEY error or a 'Table is full error', MySQL did not roll back the whole SQL statement as it should, and also wrote the failed statement to the binlog, reporting there a non-zero error_code.

- Fixed a bug : the maximum allowed number of columns in a table is 1000, but InnoDB did not check that limit in CREATE TABLE, and a subsequent INSERT or SELECT from that table could cause an assertion.

30-I-15 - MySQL/InnoDB-3.23.57, 20 juin 2003

- Changed the default value of innodb_flush_log_at_trx_commit from 0 to 1. If you have not specified it explicitly in your my.cnf, and your application runs much slower with this new release, it is because the value 1 causes a log flush to disk at each transaction commit.

- Fixed a bug : InnoDB forgot to call pthread_mutex_destroy() when a table was dropped. That could cause memory leakage on FreeBSD and other non-Linux Unixes.

- Fixed a bug : MySQL could erroneously return 'Empty set' if InnoDB estimated an index range size to 0 records though the range was not empty; MySQL also failed to do the next-key locking in the case of an empty index range.

- Fixed a bug : GROUP BY and DISTINCT could treat NULL values inequal.

30-I-16 - MySQL/InnoDB-4.0.13, 20 mai 2003

- InnoDB now supports ALTER TABLE DROP FOREIGN KEY. You have to use SHOW CREATE TABLE to find the internally generated foreign key ID when you want to drop a foreign key.

- SHOW INNODB STATUS now prints detailed information of the latest detected FOREIGN KEY and UNIQUE KEY errors. If you do not understand why InnoDB gives the error 150 from a CREATE TABLE, you can use this statement to study the reason.

- ANALYZE TABLE now works also for InnoDB type tables. It makes 10 random dives to each of the index trees and updates index cardinality estimates accordingly. Note that since it is only an estimate, repeated runs of ANALYZE TABLE may produce different numbers. MySQL uses index cardinality estimates only in join optimization. If some join is not optimized in the right way, you may try using ANALYZE TABLE.

- InnoDB group commit capability now works also when MySQL binlogging is switched on. There have to be > 2 client threads for the group commit to become active.

- Changed the default value of innodb_flush_log_at_trx_commit from 0 to 1. If you have not specified it explicitly in your my.cnf, and your application runs much slower with this new release, it is because the value 1 causes a log flush to disk at each transaction commit.

- Added a new global settable MySQL system variable innodb_max_dirty_pages_pct. It is an integer in the range 0 - 100. The default is 90. The main thread in InnoDB tries to flush pages from the buffer pool so that at most this many percents are not yet flushed at any time.

- If innodb_force_recovery=6, do not let InnoDB do repair of corrupt pages based on the doublewrite buffer.

- InnoDB start-up now happens faster because it does not set the memory in the buffer pool to zero.

- Fixed a bug : The InnoDB parser for FOREIGN KEY definitions was confused by the keywords 'foreign key' inside MySQL comments.

- Fixed a bug : If you dropped a table to which there was a FOREIGN KEY reference, and later created the same table with non-matching column types, InnoDB could assert in dict0load.c, in function dict_load_table().

- Fixed a bug : GROUP BY and DISTINCT could treat NULL values as not equal. MySQL also failed to do the next-key locking in the case of an empty index range.

- Fixed a bug : Do not commit the current transaction when a MyISAM table is updated; this also makes CREATE TABLE not to commit an InnoDB transaction, even when binlogging is enabled.

- Fixed a bug : We did not allow ON DELETE SET NULL to modify the same table where the delete was made; we can allow it because that cannot produce infinite loops in cascaded operations.

- Fixed a bug : Allow HANDLER PREV and NEXT also after positioning the cursor with a unique search on the primary key.

- Fixed a bug : If MIN() or MAX() resulted in a deadlock or a lock wait timeout, MySQL did not return an error, but returned NULL as the function value.

- Fixed a bug : InnoDB forgot to call pthread_mutex_destroy() when a table was dropped. That could cause memory leakage on FreeBSD and other non-Linux Unix systems.

30-I-17 - MySQL/InnoDB-4.1.0, 3 avril 2003

- InnoDB now supports up to 64 GB of buffer pool memory in a Windows 32-bit Intel computer. This is possible because InnoDB can use the AWE extension of Windows to address memory over the 4 GB limit of a 32-bit process. A new startup variable innodb_buffer_pool_awe_mem_mb enables AWE and sets the size of the buffer pool in megabytes.

- Reduced the size of buffer headers and the lock table. InnoDB uses 2 % less memory.

30-I-18 - MySQL/InnoDB-3.23.56, 17 mars 2003

- Fixed a major bug in InnoDB query optimization: queries of type SELECT ... WHERE indexcolumn < x and SELECT ... WHERE indexcolumn > x could cause a table scan even if the selectivity would have been very good.

- Fixed a potential bug if MySQL calls store_lock with TL_IGNORE in the middle of a query.

30-I-19 - MySQL/InnoDB-4.0.12, 18 mars 2003

- In crash recovery InnoDB now prints the progress in percents of a transaction rollback.

- Fixed a bug/feature: if your application program used mysql_use_result(), and used >= 2 connections to send SQL queries, it could deadlock on the adaptive hash S-latch in btr0sea.c. Now mysqld releases the S-latch whenever it passes data from a SELECT to the client.

- Fixed a bug : MySQL could erroneously return 'Empty set' if InnoDB estimated an index range size to 0 records though the range was not empty; MySQL also failed to do the next-key locking in the case of an empty index range.

30-I-20 - MySQL/InnoDB-4.0.11, 25 février 2003

- Fixed a bug introduced in 4.0.10: SELECT ... FROM ... ORDER BY ... DESC could hang in an infinite loop.

- An outstanding bug: SET FOREIGN_KEY_CHECKS=0 is not replicated properly in the MySQL replication.

30-I-21 - MySQL/InnoDB-4.0.10, 4 février 2003

- In INSERT INTO t1 SELECT ... FROM t2 WHERE ... MySQL previously set a table level read lock on t2. This lock is now removed.

- Increased SHOW INNODB STATUS max printed length to 200 KB.

- Fixed a major bug in InnoDB query optimization: queries of type SELECT ... WHERE indexcolumn < x and SELECT ... WHERE indexcolumn > x could cause a table scan even if the selectivity would have been very good.

- Fixed a bug : purge could cause a hang in a BLOB table where the primary key index tree was of height 1. Symptom: semaphore waits caused by an X-latch set in btr_free_externally_stored_field().

- Fixed a bug : using InnoDB HANDLER commands on a fresh handle crashed mysqld in ha_innobase::change_active_index().

- Fixed a bug : if MySQL estimated a query in the middle of a SELECT statement, InnoDB could hang on the adaptive hash index latch in btr0sea.c.

- Fixed a bug : InnoDB could report table corruption and assert in page_dir_find_owner_slot() if an adaptive hash index search coincided with purge or an insert.

- Fixed a bug : some file system snapshot tool in Windows 2000 could cause an InnoDB file write to fail with error 33 ERROR_LOCK_VIOLATION. In synchronous writes InnoDB now retries the write 100 times at 1 second intervals.

- Fixed a bug : REPLACE INTO t1 SELECT ... did not work if t1 has an auto-inc column.

- An outstanding bug: SET FOREIGN_KEY_CHECKS=0 is not replicated properly in the MySQL replication.

30-I-22 - MySQL/InnoDB-3.23.55, 24 janvier 2003

- In INSERT INTO t1 SELECT ... FROM t2 WHERE ... MySQL previously set a table level read lock on t2. This lock is now removed.

- Fixed a bug : if the combined size of InnoDB log files was >= 2 GB in a 32-bit computer, InnoDB would write log in a wrong position. That could make crash recovery and InnoDB Hot Backup to fail in log scan.

- Fixed a bug : index cursor restoration could theoretically fail.

- Fixed a bug : an assertion in btr0sea.c, in function btr_search_info_update_slow could theoretically fail in a race of 3 threads.

- Fixed a bug : purge could cause a hang in a BLOB table where the primary key index tree was of height 1. Symptom: semaphore waits caused by an X-latch set in btr_free_externally_stored_field().

- Fixed a bug : if MySQL estimated a query in the middle of a SELECT statement, InnoDB could hang on the adaptive hash index latch in btr0sea.c.

- Fixed a bug : InnoDB could report table corruption and assert in page_dir_find_owner_slot() if an adaptive hash index search coincided with purge or an insert.

- Fixed a bug : some file system snapshot tool in Windows 2000 could cause an InnoDB file write to fail with error 33 ERROR_LOCK_VIOLATION. In synchronous writes InnoDB now retries the write 100 times at 1 second intervals.

- An outstanding bug: SET FOREIGN_KEY_CHECKS=0 is not replicated properly in the MySQL replication. The fix will appear in 4.0.11 and will probably not be backported to 3.23.

- Fixed bug in InnoDB page0cur.c file in function page_cur_search_with_match which caused InnoDB to remain on the same page forever. This bug is evident only in tables with more than one page.

30-I-23 - MySQL/InnoDB-4.0.9, 14 janvier 2003

- Removed the warning message: 'InnoDB: Out of memory in additional memory pool.'

- Fixed a bug : if the combined size of InnoDB log files was >= 2 GB in a 32-bit computer, InnoDB would write log in a wrong position. That could make crash recovery and InnoDB Hot Backup to fail.

- Fixed a bug : index cursor restoration could theoretically fail.

30-I-24 - MySQL/InnoDB-4.0.8, 7 janvier 2003

- InnoDB now supports also FOREIGN KEY (...) REFERENCES ...(...) [ON UPDATE CASCADE | ON UPDATE SET NULL | ON UPDATE RESTRICT | ON UPDATE NO ACTION].

- Tables and indexes now reserve 4 % less space in the tablespace. Also existing tables reserve less space. By upgrading to 4.0.8 you will Voir more free space in "InnoDB free" in SHOW TABLE STATUS.

- Fixed bugs: updating the PRIMARY KEY of a row would generate a foreign key error on all FOREIGN KEYs which referenced secondary keys of the row to be updated. Also, if a referencing FOREIGN KEY constraint only referenced the first columns in an index, and there were more columns in that index, updating the additional columns generated a foreign key error.

- Fixed a bug : if an index contains some column twice, and that column is updated, the table will become corrupt. From now on InnoDB prevents creation of such indexes.

- Fixed a bug : removed superfluous error 149 and 150 printouts from the .err log when a locking SELECT caused a deadlock or a lock wait timeout.

- Fixed a bug : an assertion in btr0sea.c, in function btr_search_info_update_slow could theoretically fail in a race of 3 threads.

- Fixed a bug : one could not switch a session transaction isolation level back to REPEATABLE READ after setting it to something else.

30-I-25 - MySQL/InnoDB-4.0.7, 26 décembre 2002

- InnoDB in 4.0.7 is essentially the same as in 4.0.6.

30-I-26 - MySQL/InnoDB-4.0.6, 19 décembre 2002

- Since innodb_log_arch_dir has no relevance under MySQL, there is no need to specify it any more in my.cnf.

- LOAD DATA INFILE in AUTOCOMMIT=1 mode no longer does implicit commits for each 1 MB of written binlog.

- Fixed a bug introduced in 4.0.4: LOCK TABLES ... READ LOCAL should not set row locks on the rows read. This caused deadlocks and lock wait timeouts in mysqldump.

- Fixed two bugs introduced in 4.0.4: in AUTO_INCREMENT, REPLACE could cause the counter to be left 1 too low. A deadlock or a lock wait timeout could cause the same problem.

- Fixed a bug : TRUNCATE on a TEMPORARY table crashed InnoDB.

- Fixed a bug introduced in 4.0.5: if binlogging was not switched on, INSERT INTO ... SELECT ... or CREATE TABLE ... SELECT ... could cause InnoDB to hang on a semaphore created in btr0sea.c, line 128. Workaround: switch binlogging on.

- Fixed a bug : in replication issuing SLAVE STOP in the middle of a multi-statement transaction could cause that SLAVE START would only perform a part of the transaction. A similar error could occur if the slave crashed and was restarted.

30-I-27 - MySQL/InnoDB-3.23.54, 12 décembre 2003

- Fixed a bug : the InnoDB range estimator greatly exaggerated the size of a short index range if the paths to the endpoints of the range in the index tree happened to branch already in the root. This could cause unnecessary table scans in SQL queries.

- Fixed a bug : ORDER BY could fail if you had not created a primary key to a table, but had defined several indexes of which at least one was a UNIQUE index with all its columns declared as NOT NULL.

- Fixed a bug : a lock wait timeout in connection with ON DELETE CASCADE could cause corruption in indexes.

- Fixed a bug : if a SELECT was done with a unique key from a primary index, and the search matched to a delete-marked record, InnoDB could erroneously return the NEXT record.

- Fixed a bug introduced in 3.23.53: LOCK TABLES ... READ LOCAL should not set row locks on the rows read. This caused deadlocks and lock wait timeouts in mysqldump.

- Fixed a bug : if an index contains some column twice, and that column is updated, the table will become corrupt. From now on InnoDB prevents creation of such indexes.

30-I-28 - MySQL/InnoDB-4.0.5, 18 novembre 2002

- InnoDB now supports also transaction isolation levels READ COMMITTED and READ UNCOMMITTED. READ COMMITTED more closely emulates Oracle and makes porting of applications from Oracle to MySQL easier.

- Deadlock resolution is now selective: we try to pick as victims transactions with less modified or inserted rows.

- FOREIGN KEY definitions are now aware of the lower_case_table_names setting in my.cnf.

- SHOW CREATE TABLE does not output the database name to a FOREIGN KEY definition if the referred table is in the same database as the table.

- InnoDB does a consistency check to most index pages before writing them to a datafile.

- If you set innodb_force_recovery > 0, InnoDB tries to jump over corrupt index records and pages when doing SELECT * FROM table. This helps in dumping.

- InnoDB now again uses asynchronous unbuffered I/O in Windows 2000 and XP; only unbuffered simulated async I/O in NT, 95/98/ME.

- Fixed a bug : the InnoDB range estimator greatly exaggerated the size of a short index range if the paths to the endpoints of the range in the index tree happened to branch already in the root. This could cause unnecessary table scans in SQL queries. The fix will also be backported to 3.23.54.

- Fixed a bug present in 3.23.52, 4.0.3, 4.0.4: InnoDB startup could take very long or even crash on some Windows 95/98/ME computers.

- Fixed a bug : the AUTO-INC lock was held to the end of the transaction if it was granted after a lock wait. This could cause unnecessary deadlocks.

- Fixed a bug : if SHOW INNODB STATUS, innodb_monitor, or innodb_lock_monitor had to print several hundred transactions in one report, and the output became truncated, InnoDB would hang, printing to the error log many waits for a mutex created at srv0srv.c, line 1621.

- Fixed a bug : SHOW INNODB STATUS on Unix always reported average file read size as 0 bytes.

- Fixed a potential bug in 4.0.4: InnoDB now does ORDER BY ... DESC like MyISAM.

- Fixed a bug : DROP TABLE could cause crash or a hang if there was a rollback concurrently running on the table. The fix will only be backported to 3.23 if this appears a real problem for users.

- Fixed a bug : ORDER BY could fail if you had not created a primary key to a table, but had defined several indexes of which at least one was a UNIQUE index with all its columns declared as NOT NULL.

- Fixed a bug : a lock wait timeout in connection with ON DELETE CASCADE could cause corruption in indexes.

- Fixed a bug : if a SELECT was done with a unique key from a primary index, and the search matched to a delete-marked record, InnoDB could return the NEXT record.

- Outstanding bugs: in 4.0.4 two bugs were introduced to AUTO_INCREMENT. REPLACE can cause the counter to be left 1 too low. A deadlock or a lock wait timeout can cause the same problem. These will be fixed in 4.0.6.

30-I-29 - MySQL/InnoDB-3.23.53, 9 octobre 2002

- We again use unbuffered disk I/O to datafiles in Windows. Windows XP and Windows 2000 read performance Voirms to be very poor with normal I/O.

- Tuned range estimator so that index range scans are preferred over full index scans.

- Allow dropping and creating a table even if innodb_force_recovery is set. One can use this to drop a table which would cause a crash in rollback or purge, or if a failed table import causes a runaway rollback in recovery.

- Fixed a bug present in 3.23.52, 4.0.3, 4.0.4: InnoDB startup could take very long or even crash on some Windows 95/98/ME computers.

- Fixed a bug : fast shutdown (which is the default) sometimes was slowed down by purge and insert buffer merge.

- Fixed a bug : doing a big SELECT from a table where no rows were visible in a consistent read could cause a very long (> 600 seconds) semaphore wait in btr0cur.c line 310.

- Fixed a bug : the AUTO-INC lock was held to the end of the transaction if it was granted after a lock wait. This could cause unnecessary deadlocks.

- Fixed a bug : if you created a temporary table inside LOCK TABLES, and used that temporary table, that caused an assertion failure in ha_innobase.cc.

- Fixed a bug : if SHOW INNODB STATUS, innodb_monitor, or innodb_lock_monitor had to print several hundred transactions in one report, and the output became truncated, InnoDB would hang, printing to the error log many waits for a mutex created at srv0srv.c, line 1621.

- Fixed a bug : SHOW INNODB STATUS on Unix always reported average file read size as 0 bytes.

30-I-30 - MySQL/InnoDB-4.0.4, 2 octobre 2002

- We again use unbuffered disk I/O in Windows. Windows XP and Windows 2000 read performance Voirms to be very poor with normal I/O.

- Increased the max key length of InnoDB tables from 500 to 1024 bytes.

- Increased the table comment field in SHOW TABLE STATUS so that up to 16000 characters of foreign key definitions can be printed there.

- The auto-increment counter is no longer incremented if an insert of a row immediately fails in an error.

- Allow dropping and creating a table even if innodb_force_recovery is set. One can use this to drop a table which would cause a crash in rollback or purge, or if a failed table import causes a runaway rollback in recovery.

- Fixed a bug : Using ORDER BY primarykey DESC in 4.0.3 causes an assertion failure in btr0pcur.c, line 203.

- Fixed a bug : fast shutdown (which is the default) sometimes was slowed down by purge and insert buffer merge.

- Fixed a bug : doing a big SELECT from a table where no rows were visible in a consistent read could cause a very long (> 600 seconds) semaphore wait in btr0cur.c line 310.

- Fixed a bug : if the MySQL query cache was used, it did not get invalidated by a modification done by ON DELETE CASCADE or ...SET NULL.

- Fixed a bug : if you created a temporary table inside LOCK TABLES, and used that temporary table, that caused an assertion failure in ha_innodb.cc.

- Fixed a bug : if you set innodb_flush_log_at_trx_commit to 1, SHOW VARIABLES would show its value as 16 million.

30-I-31 - MySQL/InnoDB-4.0.3, 28 août 2002

- Removed unnecessary deadlocks when inserts have to wait for a locking read, update, or delete to release its next-key lock.

- The MySQL HANDLER SQL commands now work also for InnoDB type tables. InnoDB does the HANDLER reads always as consistent reads. HANDLER is a direct access path to read individual indexes of tables. In some cases HANDLER can be used as a substitute of server-side cursors.

- Fixed a bug in 4.0.2: even a simple insert could crash the AIX version.

- Fixed a bug : if you used in a table name characters whose code is > 127, in DROP TABLE InnoDB could assert on line 155 of pars0sym.c.

- Compilation from source now provides a working version both on HP-UX-11 and HP-UX-10.20. The source of 4.0.2 worked only on 11, and the source of 3.23.52 only on 10.20.

- Fixed a bug : if compiled on 64-bit Solaris, InnoDB produced a bus error at startup.

30-I-32 - MySQL/InnoDB-3.23.52, 16 août 2002

- The feature set of 3.23 will be frozen from this version on. New features will go the 4.0 branch, and only bug fixes will be made to the 3.23 branch.

- Many CPU-bound join queries now run faster. On Windows also many other CPU-bound queries run faster.

- A new SQL command SHOW INNODB STATUS returns the output of the InnoDB Monitor to the client. The InnoDB Monitor now prints detailed information on the latest detected deadlock.

- InnoDB made the SQL query optimizer to avoid too much index-only range scans and choose full table scans instead. This is now fixed.

- BEGIN and COMMIT are now added in the binlog around transactions. The MySQL replication now respects transaction borders: a user will no longer Voir half transactions in replication slaves.

- A replication slave now prints in crash recovery the last master binlog position it was able to recover to.

- A new setting innodb_flush_log_at_trx_commit=2 makes InnoDB to write the log to the operating system file cache at each commit. This is almost as fast as the setting innodb_flush_log_at_trx_commit=0, and the setting 2 also has the nice feature that in a crash where the operating system does not crash, no committed transaction is lost. If the operating system crashes or there is a power outage, then the setting 2 is no safer than the setting 0.

- Added checksum fields to log blocks.

- SET FOREIGN_KEY_CHECKS=0 helps in importing tables in an arbitrary order which does not respect the foreign key rules.

- SET UNIQUE_CHECKS=0 speeds up table imports into InnoDB if you have UNIQUE constraints on secondary indexes. This flag should be used only if you are certain that the input records contain no UNIQUE constraint violations.

- SHOW TABLE STATUS now lists also possible ON DELETE CASCADE or ON DELETE SET NULL in the comment field of the table.

- When CHECK TABLE is run on any InnoDB type table, it now checks also the adaptive hash index for all tables.

- If you defined ON DELETE CASCADE or SET NULL and updated the referenced key in the parent row, InnoDB deleted or updated the child row. This is now changed to conform to SQL-92: you get the error 'Cannot delete parent row'.

- Improved the auto-increment algorithm: now the first insert or SHOW TABLE STATUS initializes the auto-increment counter for the table. This removes almost all surprising deadlocks caused by SHOW TABLE STATUS.

- Aligned some buffers used in reading and writing to datafiles. This allows using unbuffered raw devices as datafiles in Linux.

- Fixed a bug : If you updated the primary key of a table so that only the case of characters changed, that could cause assertion failures, mostly in page0page.ic line 515.

- Fixed a bug : If you delete or update a row referenced in a foreign key constraint and the foreign key check has to wait for a lock, then the check may report an erroneous result. This affects also the ON DELETE... operation.

- Fixed a bug : A deadlock or a lock wait timeout error in InnoDB causes InnoDB to roll back the whole transaction, but MySQL could still write the earlier SQL statements to the binlog, even though InnoDB rolled them back. This could, for example, cause replicated databases to get out-of-sync.

- Fixed a bug : If the database happened to crash in the middle of a commit, then the recovery might leak tablespace pages.

- Fixed a bug : If you specified a non-latin1 character set in my.cnf, then, in contrary to what is stated in the manual, in a foreign key constraint a string type column had to have the same length specification in the referencing table and the referenced table.

- Fixed a bug : DROP TABLE or DROP DATABASE could fail if there simultaneously was a CREATE TABLE running.

- Fixed a bug : If you configured the buffer pool bigger than 2 GB in a 32-bit computer, InnoDB would assert in buf0buf.ic line 214.

- Fixed a bug : on 64-bit computers updating rows which contained the SQL NULL in some column could cause the undo log and the ordinary log to become corrupt.

- Fixed a bug : innodb_log_monitor caused a hang if it suppressed lock prints for a page.

- Fixed a bug : in the HP-UX-10.20 version mutexes would leak and cause race conditions and crashes in any part of InnoDB code.

- Fixed a bug : if you ran in the AUTOCOMMIT mode, executed a SELECT, and immediately after that a RENAME TABLE, then RENAME would fail and MySQL would complain about error 1192.

- Fixed a bug : if compiled on 64-bit Solaris, InnoDB produced a bus error at startup.

30-I-33 - MySQL/InnoDB-4.0.2, 10 juillet 2002

- InnoDB is essentially the same as InnoDB-3.23.51.

- If no innodb_data_file_path is specified, InnoDB at the database creation now creates a 10 MB auto-extending datafile ibdata1 to the datadir of MySQL. In 4.0.1 the file was 64 MB and not auto-extending.

30-I-34 - MySQL/InnoDB-3.23.51, 12 juin 2002

- Fixed a bug : a join could result in a seg fault in copying of a BLOB or TEXT column if some of the BLOB or TEXT columns in the table contained SQL NULL values.

- Fixed a bug : if you added self-referential foreign key constraints with ON DELETE CASCADE to tables and a row deletion caused InnoDB to attempt the deletion of the same row twice because of a cascading delete, then you got an assertion failure.

- Fixed a bug : if you use MySQL 'user level locks' and close a connection, then InnoDB may assert in ha_innobase.cc, line 302.

30-I-35 - MySQL/InnoDB-3.23.50, 23 avril 2002

- InnoDB now supports an auto-extending last datafile. You do not need to preallocate the whole datafile at the database startup.

- Made several changes to facilitate the use of the InnoDB Hot Backup tool. It is a separate non-free tool you can use to take online backups of your database without shutting down the server or setting any locks.

- If you want to run the InnoDB Hot Backup tool on an auto-extending datafile you have to upgrade it to version ibbackup-0.35.

- The log scan phase in crash recovery will now run much faster.

- Starting from this server version, the hot backup tool truncates unused ends in the backup InnoDB datafiles.

- To allow the hot backup tool to work, on Windows we no longer use unbuffered I/O or native async I/O; instead we use the same simulated async I/O as on Unix.

- You can now define the ON DELETE CASCADE or ON DELETE SET NULL clause on foreign keys.

- FOREIGN KEY constraints now survive ALTER TABLE and CREATE INDEX.

- We suppress the FOREIGN KEY check if any of the column values in the foreign key or referenced key to be checked is the SQL NULL. This is compatible with Oracle, for example.

- SHOW CREATE TABLE now lists also foreign key constraints. Also mysqldump no longer forgets about foreign keys in table definitions.

- You can now add a new foreign key constraint with ALTER TABLE ... ADD CONSTRAINT FOREIGN KEY (...) REFERENCES ... (...).

- FOREIGN KEY definitions now allow backquotes around table and column names.

- MySQL command SET TRANSACTION ISOLATION LEVEL ... has now the following effect on InnoDB tables: if a transaction is defined as SERIALIZABLE then InnoDB conceptually adds LOCK IN SHARE MODE to all consistent reads. If a transaction is defined to have any other isolation level, then InnoDB obeys its default locking strategy which is REPEATABLE READ.

- SHOW TABLE STATUS no longer sets an x-lock at the end of an auto-increment index if the auto-increment counter has already been initialized. This removes in almost all cases the surprising deadlocks caused by SHOW TABLE STATUS.

- Fixed a bug : in a CREATE TABLE statement the string 'foreign' followed by a non-space character confused the FOREIGN KEY parser and caused table creation to fail with errno 150.

30-I-36 - MySQL/InnoDB-3.23.49, 17 février 2002

- Fixed a bug : if you called DROP DATABASE for a database on which there simultaneously were running queries, the MySQL server could crash or hang. Crashes fixed, but a full fix has to wait some changes in the MySQL layer of code.

- Fixed a bug : on Windows one had to put the database name in lower case for DROP DATABASE to work. Fixed in 3.23.49: case no longer matters on Windows. On Unix the database name remains case-sensitive.

- Fixed a bug : if one defined a non-latin1 character set as the default character set, then definition of foreign key constraints could fail in an assertion failure in dict0crea.c, reporting an internal error 17.

30-I-37 - MySQL/InnoDB-3.23.48, 9 février 2002

- Tuned the SQL optimizer to favor more often index searches over table scans.

- Fixed a performance problem when several large SELECT queries are run concurrently on a multiprocessor Linux computer. Large CPU-bound SELECT queries will now also generally run faster on all platforms.

- If MySQL binlogging is used, InnoDB now prints after crash recovery the latest MySQL binlog file name and the position in that file (= byte offset) InnoDB was able to recover to. This is useful, for example, when resynchronizing a master and a slave database in replication.

- Added better error messages to help in installation problems.

- One can now recover also MySQL temporary tables which have become orphaned inside the InnoDB tablespace.

- InnoDB now prevents a FOREIGN KEY declaration where the signedness is not the same in the referencing and referenced integer columns.

- Fixed a bug : calling SHOW CREATE TABLE or SHOW TABLE STATUS could cause memory corruption and make mysqld to crash. Especially at risk was mysqldump, because it calls frequently SHOW CREATE TABLE.

- Fixed a bug : if on Unix you did an ALTER TABLE to an InnoDB table and simultaneously did queries to it, mysqld could crash with an assertion failure in row0row.c, line 474.

- Fixed a bug : if inserts to several tables containing an auto-inc column were wrapped inside one LOCK TABLES, InnoDB asserted in lock0lock.c.

- In 3.23.47 we allowed several NULLS in a UNIQUE secondary index. But CHECK TABLE was not relaxed: it reports the table as corrupt. CHECK TABLE no longer complains in this situation.

- Fixed a bug : on Sparc and other high-endian processors SHOW VARIABLES showed innodb_flush_log_at_trx_commit and other boolean-valued startup parameters always OFF even if they were switched on.

- Fixed a bug : if you ran mysqld-max-nt as a service on Windows NT/2000, the service shutdown did not always wait long enough for the InnoDB shutdown to finish.

30-I-38 - MySQL/InnoDB-3.23.47, 28 décembre 2001

- Recovery happens now faster, especially in a lightly loaded system, because background checkpointing has been made more frequent.

- InnoDB allows now several similar key values in a UNIQUE secondary index if those values contain SQL NULLs. Thus the convention is now the same as in MyISAM tables.

- InnoDB gives a better row count estimate for a table which contains BLOBs.

- In a FOREIGN KEY constraint InnoDB is now case-insensitive to column names, and in Windows also to table names.

- InnoDB allows a FOREIGN KEY column of CHAR type to refer to a column of VARCHAR type, and vice versa. MySQL silently changes the type of some columns between CHAR and VARCHAR, and these silent changes do not hinder FOREIGN KEY declaration any more.

- Recovery has been made more resilient to corruption of log files.

- Unnecessary statistics calculation has been removed from queries which generate a temporary table. Some ORDER BY and DISTINCT queries will now run much faster.

- MySQL now knows that the table scan of an InnoDB table is done through the primary key. This will save a sort in some ORDER BY queries.

- The maximum key length of InnoDB tables is again restricted to 500 bytes. The MySQL interpreter is not able to handle longer keys.

- The default value of innodb_lock_wait_timeout was changed from infinite to 50 seconds, the default value of innodb_file_io_threads from 9 to 4.

30-I-39 - MySQL/InnoDB-4.0.1, 3 décembre 2001

- InnoDB is the same as in 3.23.47.

- In 4.0.0 the MySQL interpreter did not know the syntax LOCK IN SHARE MODE. This has been fixed.

- In 4.0.0 multiple-table delete did not work for transactional tables. This has been fixed.

30-I-40 - MySQL/InnoDB-3.23.46, 30 novembre 2001

- This is the same as 3.23.45.

30-I-41 - MySQL/InnoDB-3.23.45, 23 novembre 2001

- This is a bugfix release.

- In versions 3.23.42-.44 when creating a table on Windows you have to use lower case letters in the database name to be able to access the table. Fixed in 3.23.45.

- InnoDB now flushes stdout and stderr every 10 seconds: if these are redirected to files, the file contents can be better viewed with an editor.

- Fixed an assertion failure in .44, in trx0trx.c, line 178 when you drop a table which has the .frm file but does not exist inside InnoDB.

- Fixed a bug in the insert buffer. The insert buffer tree could get into an inconsistent state, causing a crash, and also crashing the recovery. This bug could appear especially in large table imports or alterations.

- Fixed a bug in recovery: InnoDB could go into an infinite loop constantly printing a warning message that it cannot find free blocks from the buffer pool.

- Fixed a bug : when you created a temporary table of the InnoDB type, and then used ALTER TABLE to it, the MySQL server could crash.

- Prevented creation of MySQL system tables 'mysql.user', 'mysql.host', or 'mysql.db', in the InnoDB type.

- Fixed a bug which can cause an assertion failure in 3.23.44 in srv0srv.c, line 1728.

30-I-42 - MySQL/InnoDB-3.23.44, 2 novembre 2001

- You can define foreign key constraints on InnoDB tables. An example: FOREIGN KEY (col1) REFERENCES table2(col2).

- You can create > 4 GB datafiles in those file systems that allow it.

- Improved InnoDB monitors, including a new innodb_table_monitor which allows you to print the contents of the InnoDB internal data dictionary.

- DROP DATABASE will now work also for InnoDB tables.

- Accent characters in the default character set latin1 will be ordered according to the MySQL ordering.<br> NOTE: if you are using latin1 and have inserted characters whose code is > 127 to an indexed CHAR column, you should run CHECK TABLE on your table when you upgrade to 3.23.43, and drop and reimport the table if CHECK TABLE reports an error!

- InnoDB will calculate better table cardinality estimates.

- Change in deadlock resolution: in .43 a deadlock rolls back only the SQL statement, in .44 it will roll back the whole transaction.

- Deadlock, lock wait timeout, and foreign key constraint violations (no parent row, child rows exist) now return native MySQL error codes 1213, 1205, 1216, 1217, respectively.

- A new my.cnf parameter innodb_thread_concurrency helps in performance tuning in high concurrency environments.

- A new my.cnf option innodb_force_recovery will help you in dumping tables from a corrupted database.

- A new my.cnf option innodb_fast_shutdown will speed up shutdown. Normally InnoDB does a full purge and an insert buffer merge at shutdown.

- Raised maximum key length to 7000 bytes from a previous limit of 500 bytes.

- Fixed a bug in replication of auto-inc columns with multiline inserts.

- Fixed a bug when the case of letters changes in an update of an indexed secondary column.

- Fixed a hang when there are > 24 datafiles.

- Fixed a crash when MAX(col) is selected from an empty table, and col is a not the first column in a multi-column index.

- Fixed a bug in purge which could cause crashes.

30-I-43 - MySQL/InnoDB-3.23.43, 4 octobre 2001

- This is essentially the same as InnoDB-3.23.42.

30-I-44 - MySQL/InnoDB-3.23.42, 9 septembre 2001

- Fixed a bug which corrupted the table if the primary key of a > 8000-byte row was updated.

- There are now 3 types of InnoDB Monitors: innodb_monitor, innodb_lock_monitor, and innodb_tablespace_monitor. innodb_monitor now prints also buffer pool hit rate and the total number of rows inserted, updated, deleted, read.

- Fixed a bug in RENAME TABLE.

- Fixed a bug in replication with an auto-increment column.

30-I-45 - MySQL/InnoDB-3.23.41, 13 août 2001

- Support for < 4 GB rows. The previous limit was 8000 bytes.

- Use the doublewrite file flush method.

- Raw disk partitions supported as datafiles.

- InnoDB Monitor.

- Several hang bugs fixed and an ORDER BY bug ('Sort aborted') fixed.

30-I-46 - MySQL/InnoDB-3.23.40, 16 juillet 2001

- Only a few rare bugs fixed.

30-I-47 - MySQL/InnoDB-3.23.39, 13 juin 2001

- CHECK TABLE now works for InnoDB tables.

- A new my.cnf parameter innodb_unix_file_flush_method introduced. It can be used to tune disk write performance.

- An auto-increment column now gets new values past the transaction mechanism. This saves CPU time and eliminates transaction deadlocks in new value assignment.

- Several bug fixes, most notably the rollback bug in 3.23.38.

30-I-48 - MySQL/InnoDB-3.23.38, 12 mai 2001

- The new syntax SELECT ... LOCK IN SHARE MODE is introduced.

- InnoDB now calls fsync() after every disk write and calculates a checksum for every database page it writes or reads, which will reveal disk defects.

- Several bug fixes.

30-J - Historique de MySQL Cluster

Note : cette section n'est pas traduite en français.

30-J-1 - MySQL Cluster-4.1.11 (01 Apr 2005)

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- (Bug #9435) TIMESTAMP columns don't update

- (Bug #8753) Invalid schema object version after dropping index (crash fixed, currently retry required)

- (Bug #8557) ndbd does not get same nodeid on restart

- (Bug #8556) corrupt ndb_mgm show printout for certain configurations

- (Bug #8167) cluster shared memory and mysqld signal usage clash

30-J-2 - MySQL Cluster-4.1.10 (12 Feb 2005)

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- (Bug #8284) Out of fragment memory in DBACC

- (Bug #8262) Node crash due to bug in DBLQH

- (Bug #8208) node restart fails on Aix 5.2

- (Bug #8167) cluster shared memory and mysqld signal usage clash

- (Bug #8101) unique index and error 4209 while selecting

- (Bug #8070) (Bug #7937) (Bug #6716) various ndb_restore core dumps on HP-UX

- (Bug #8010) 4006 forces MySQL Node Restart

- (Bug #7928) out of connection objects

- (Bug #7898) mysqld crash with ndb (solaris)

- (Bug #7864) Not possible to have more than 4.5G data memory

30-J-3 - MySQL Cluster-4.1.9 (13 Jan 2005)

Fonctionnalité ajoutée ou modifiée :

- New implementation of shared memory transporter.

- Cluster automatically configures shared memory transporter if possible.

- Cluster prioritizes usage of transporters with shared memory and localhost TCP

- Added switches to control the above functions, ndb-shm and ndb-optimized-node-selection.

Bogues corrigés :

- (Bug #7805) config.ini parsing error

- (Bug #7798) Running range scan after alter table in different thread causes node failure

- (Bug #7761) Alter table does not autocommit

- (Bug #7725) Indexed DATETIME Columns Return Random Results

- (Bug #7660) START BACKUP does not increment BACKUP-ID (Big Endian machines)

- (Bug #7593) Cannot Create A Large NDB Data Warehouse

- (Bug #7480) Mysqld crash in ha_ndbcluster using Query Browser

- (Bug #7470) shared memory transporter does not connect

- (Bug #7396) Primary Key not working in NDB Mysql Clustered table (solaris)

- (Bug #7379) ndb restore fails to handle blobs and multiple databases

- (Bug #7346) ndb_restore enters infinite loop

- (Bug #7340) Problem for inserting data into the Text field on utf8

- (Bug #7124) ndb_mgmd is aborted on startup when using SHM connection

30-J-4 - MySQL Cluster-4.1.8 (14 Dec 2004)

Fonctionnalité ajoutée ou modifiée :

- Default port for ndb_mgmd was changed to 1186 (from 2200) as this port number was officially assigned to MySQL Cluster by IANA.

- New command in ndb_mgm, PURGE STALE SESSIONS, as a workaround for cases where nodes fail to allocate a node id even if it is free to use.

- New command in ndb_mgm, CONNECT.

- The ndb executables have been changed to make use of the regular MySQL command line option parsing features. Voir Section 16.5.5, « Options des commandes pour le cluster MySQL » for notes on changes.

- As bonus of the above you can now specify all command line options in my.cnf using the executable names as sections, i.e. [ndbd], [ndb_mgmd], [ndb_mgm], [ndb_restore] etc.

[ndbd]
ndb-connectstring=myhost.domain.com:1234
[ndb_mgm]
ndb-connectstring=myhost.domain.com:1234

- Added use of section [mysql_cluster] in my.cnf. All cluster executables, including mysqld, parse this section. Convenient place to put e.g. ndb-connectstring so that it only needs to be specified once.

- Added cluster log info events on allocation and deallocation of nodeid's.

- Added cluster log info events on connection refuse as a result of version mismatch.

- Extended connectstring syntax to allow for leaving the port number out. E.g. ndb-connectstring|connect-string=myhost1,myhost2,myhost3 is a valid connectstring and connect occurs on default port 1186.

- Clear text ndb error messages provided also for error codes that are mapped to corresponding mysql error codes, by executing SHOW WARNINGS after an error has occured which relates to the ndb storage engine.

- Significant performance improvements done for read performance, especially for blobs.

- Added some variables for performance tuning, ndb_force_send and ndb_use_exact_count. Do show variables like 'ndb%'; in mysql client for listing. Use set command to alter variables.

- Added variables to set some options, ndb_use_transactions and ndb_autoincrement_prefetch_sz.

Bogues corrigés :

- (Bug #7303) ndb_mgm: Trying to set CLUSTERLOG for a specific node id core dumps

- (Bug #7193) start backup gives false error printout

- (Bug #7153) Cluster nodes don't report error on endianness mismatch

- (Bug #7152) ndb_mgmd segfaults on incorrect HostName in configuration

- (Bug #7104) clusterlog filtering and level setting broken

- (Bug #6995) ndb_recover on varchar fields results in changing case of data

- (Bug #6919) all status only shows 2 nodes on a 8-node cluster

- (Bug #6871) DBD execute failed: Got error 897 'Unknown error code' from ndbcluster

- (Bug #6794) Wrong outcome of update operation of ndb table

- (Bug #6791) Segmentation fault when config.ini is not correctly set

- (Bug #6775) failure in acc when running many mysql clients

- (Bug #6696) ndb_mgm command line options inconsistent with behavior

- (Bug #6684) ndb_restore doesn't give error messages if inproper command given

- (Bug #6677) ndb_mgm can crash on "ALL CLUSTERLOG"

- (Bug #6538) Error code returned when select max() on empty table with index

- (Bug #6451) failing create table givers "ghost" tables which are impossible to remove

- (Bug #6435) strange behavior of left join

- (Bug #6426) update with long pk fails

- (Bug #6398) update of primary key fails

- (Bug #6354) mysql does not complain about --ndbcluster option when NDB is not compiled in

- (Bug #6331) INSERT IGNORE .. SELECT breaks subsequent inserts

- (Bug #6288) cluster nodes crash on data import

- (Bug #6031) To drop database you have to execute DROP DATABASE command twice

- (Bug #6020) LOCK TABLE + delete returns error 208

- (Bug #6018) REPLACE does not work for BLOBs + NDB

- (Bug #6016) Strange crash with blobs + different DATABASES

- (Bug #5973) ndb table belonging to different database shows up in show tables

- (Bug #5872) ALTER TABLE with blob from ndb table to myisam fails

- (Bug #5844) Failing mysql-test-run leaves stray NDB processes behind

- (Bug #5824) HELP text messed up in ndb_mgm

- (Bug #5786) Duplicate key error after restore

- (Bug #5785) lock timeout during concurrent update

- (Bug #5782) Unknown error when using LIMIT with ndb table

- (Bug #5756) RESTART node from ndb_mgm fails

- A few more not reported bugs fixed

30-J-5 - MySQL Cluster-4.1.7, (23 Octobre 2004)

Fonctionnalités ajoutées ou modifiées :

- Optimization 1: Improved performance on index scans. Measured 30% performance increase on query which do large amounts of index scans.

- Optimization 2: Improved performance on primary key lookups. Around double performance for autocommitted primary key lookups.

- Optimization 3: Improved performance when using blobs by avoiding usage of exclusive locks for blobs.

Bogues corrigés :

- A few bugs fixed.

30-J-6 - MySQL Cluster-4.1.6, 10 octobre 2004

Fonctionnalité ajoutée ou modifiée :

- Limited character set support for storage engine NDBCLUSTER:

Char set

Collation

big5

big5_chinese_ci

big5_bin

binary

binary

euckr

euckr_korean_ci

euckr_bin

gb2312

gb2312_chinese_ci

gb2312_bin

gbk

gbk_chinese_ci

gbk_bin

latin1

latin1_swedish_ci

latin1_bin

sjis

sjis_japanese_ci

sjis_bin

tis620

tis620_bin

ucs2

ucs2_general_ci

ucs2_bin

ujis

ujis_japanese_ci

ujis_bin

utf8

utf8_general_ci

utf8_bin

- The SCI Transporter has been brought up-to-date with all changes and now works and has been documented as well.

- Optimizations when several clients to a MySQL Server access ndb tables.

- Added more checks and warnings for erroneous and unappropriate cluster configurations.

- SHOW TABLES now directly shows ndb tables created on a different mysql server, i.e. without a prior table access.

- Enhanced support for starting MySQL Server independently of ndbd and ndb_mgmd.

Bogues corrigés :

- Quite a few bugs fixed.

30-J-7 - MySQL Cluster-4.1.5, 16 septembre 2004

Fonctionnalité ajoutée ou modifiée :

- Many queries in MySQL Cluster are executed as range scans or full table scans. All queries that don't use a unique hash index or the primary hash index will use this access method. In a distributed system it is crucial that batching is properly performed.
In previous version the batch size was fixed to 16 per storage node. In this version it is configurable per MySQL Server. So for queries using lots of large scans it is appropriate to set this parameter rather large and for queries using lots of small scans only fetching a small amount of records it is appropriate to set it low.
The performance of queries can easily change as much as 40% based on how this variable is set.
In future versions more logic will be made to assess the batch size on per query basis. Thus the semantics of this new configuration variable ScanBatchSize is likely to change.

- The fixed size overhead of the ndbd process was greatly decreased. Also overhead per operation record was greatly decreased and also overhead per table and index was greatly decreased.
A number of new configuration variables was introduced to be able to configure more buffers in the system. Configuration variables to specify the number of tables, unique hash indexes and ordered indexes was introduced as well.
New configuration variables: MaxNoOfOrderedIndexes, MaxNoOfUniqueHashIndexes
Configuration variables no longer used: MaxNoOfIndexes (split into the two above).

- In previous versions ALTER TABLE, TRUNCATE TABLE, and LOAD DATA were performed as one big transaction. In this version, all those statements will be automatically separated into a number of transactions.
This removes the limitation that one could not change very large tables due to the MaxNoOfConcurrentOperations parameter.

- The online backup feature of MySQL Cluster now also backs up the indexes such that the restore ensures that both data and indexes are restored.

- In previous versions it was not possible to use NULL in indexes. This is now possible in all indexes.

- Much work has been put onto making AUTO_INCREMENT features work as for other table handlers. Autoincrements as a partial key is still only supported by MyISAM.

- In previous version,s mysqld would crash if the cluster wasn't started and the --ndbcluster option was used. Now mysqld will handle cluster crashes and not started without crashing.

- The -i option for initial startup has been removed from ndbd. Initial startup still can be specified by using the --initial option. The reason is to ensure that it is clearer what takes place when using the --initial option. This option completely removes all data from the disk and should only be used at initial start, in certain software upgrade cases, and in some cases when node restarts don't work as a workaround.

- The management client (ndb_mgm) now has more commands and more information is printed in some commands such as show.

- In previous versions, the files were called ndb_0.. when it wasn't possible to allocate a node ID when starting the node. To ensure that files are not so easily overwritten, these files are now named ndb_pid.., where pid is the process ID assigned by the OS.

- The default parameters have changed for ndb_mgmd and ndbd. Yn particular, they are now started as daemons by default. The -n option was removed since it could confusion as to whether its meaning is nostart or nodaemon.

- In the configuration file, you can now use [NDBD] as an alias for [DB], [MYSQLD] as an alias for [API], and [NDB_MGMD] as an alias for [MGM].

- Many more checks of the consistency of the configuration have been introduced to provide quicker feedback on configuration errors.

- In the connect string, it is now possible to use both ';' and ',' as the separator between entries. So "nodeid=2,host=localhost:2200" is equivalent to "nodeid=2;host=localhost:2200".
In the configuration, it is possible to use ':' or '=' as the assignment symbol. Thus MaxNoOfOrderedIndexes : 128 and MaxNoOfOrderedIndexes = 128 are equivalent.

- The configuration variable names are now case insensitive so MaxNoOfOrderedIndexes: 128 is equivalent to MAXNOOFORDEREDINDEXES = 128.

- It is possible now to set the backup directory separately from the FileSystemPath by using the BackupDir config variable.
Log files and trace files can now be put in any directory by setting the DataDir configuration variable.
FileSystemPath is no longer mandatory and defaults to DataDir.

- It is now supported to perform queries involving tables from different databases in MySQL.

- It is now possible to update the primary key.

- The performance of the ordered index has been greatly improved, particularly the maintenance of the index at updates, inserts and deletes.

Bogues corrigés :

- Quite a few bugs fixed.

30-J-8 - MySQL Cluster-4.1.4, 31 août 2004

Fonctionnalité ajoutée ou modifiée :

- The names of the log files and trace files created by the ndbd and ndb_mgmd processes have changed.

- Support for the many BLOB data types was introduced in this version.

Bogues corrigés :

- Quite a few bugs were fixed in the 4.1.4 release.

30-J-9 - MySQL Cluster-5.0.1, 27 juillet 2004

Fonctionnalité ajoutée ou modifiée :

- This was the first MySQL Cluster release in 5.0. Actually almost all attention was on getting 4.1 stable so it is not recommended to use MySQL 5.0.1 for MySQL Cluster usage.

Bogues corrigés :

30-J-10 - MySQL Cluster-4.1.3, 28 juin 2004

Fonctionnalité ajoutée ou modifiée :

- This was the first MySQL Cluster release so all the functionality was new.

Bogues corrigés :

- Various bugs fixed in the development process leading up to 4.1.3.

30-K - Historique de MyODBC

30-K-1 - Changes in MyODBC 3.51.12

Fonctionnalité ajoutée ou modifiée :

Bogues corrigés :

- SQLColumns() returned no information for tables that had a column named using a reserved word. (Bug #9539)

30-K-2 - Changes in MyODBC 3.51.11

Fonctionnalité ajoutée ou modifiée : No changes.

Bogues corrigés :

- mysql_list_dbcolumns() and insert_fields() were retrieving all rows from a table. Fixed the queries generated by these functions to return no rows. (Bug #8198)

- SQLGetTypoInfo() returned tinyblob for SQL_VARBINARY and nothing for SQL_BINARY. Fixed to return varbinary for SQL_VARBINARY, binary for SQL_BINARY, and longblob for SQL_LONGVARBINARY. (Bug #8138)

31 - Port vers d'autres systèmes

Cet appendice vous aidera à porter MySQL vers un autre système d'exploitation. Vérifiez d'abord la liste des systèmes supportés avant toute chose. Voir Section 2.1.1, « Systèmes d'exploitation supportés par MySQL ». Si vous avez créé un nouveau port de MySQL, merci de nous en avertir pour que nous puissions le lister ici et sur notre site web (http://www.mysql.com/), pour le recommander aux autres utilisateurs.

Note : si vous créez un nouveau port de MySQL, vous êtes libre de le copier et le distribuer sous la licence GPL, mais cela ne signifie pas que vous êtes détenteur de droits sur MySQL.

Une bibliothèque de threads Posix qui fonctionne est requise pour le serveur. Pour Solaris 2.5 nous utilisons Sun PThreads (le support natif des threads de la version 2.4 et plus ancienne est obsolète) et sur Linux nous utilisons LinuxThreads de Xavier Leroy, <Xavier.Leroy@inria.fr>.

La partie la plus difficile du port vers une nouvelle variante Unix ne bénéficiant pas d'un bon support natif des threads est probablement le port de MIT-pthreads. Voyez mit-pthreads/README et Programming POSIX Threads (http://www.humanfactor.com/pthreads/).

La distribution MySQL inclut une version patchée des Pthreads de Provenzano de MIT (voyez la page web des Pthreads MIT http://www.mit.edu/afs/sipb/project/pthreads/ et une introduction à la programmation sur http://www.mit.edu:8001/people/proven/IAP_2000/). Cela peut être utilisé pour certains systèmes d'exploitation qui n'ont pas les threads POSIX. Voir Section 2.4.5, « Notes relatives aux MIT-pthreads ».

Il est aussi possible d'utiliser un autre paquet de threads au niveau utilisateur nommé FSU Pthreads (voir http://moss.csc.ncsu.edu/~mueller/pthreads/). Cette implémentation est utilisée pour le port vers SCO.

Consultez les programmes thr_lock.c et thr_alarm.c dans le dossier mysys pour quelques tests/exemples de ces problèmes.

Le serveur et le client ont besoin d'un compilateur C++ fonctionnel (nous utilisons gcc et avons essayé SPARCworks). Un autre compilateur connu maintenant pour fonctionner est Irix cc.

Pour ne compiler que le client, utilisez ./configure --without-server.

Il n'y a actuellement aucun support pour ne compiler que le serveur, et il n'est pas prévu d'en ajouter un, à moins que quelqu'un n'ait une bonne raison de le faire.

Si vous voulez, ou si vous avez besoin de changer un fichier Makefile ou le script de configuration, vous aurez besoin d'avoir Automake et Autoconf. Voir Section 2.4.3, « Installer à partir de l'arbre source de développement ».

Toutes les étapes dont vous avez besoin pour reconstruire le tout à partir des fichiers de base :

/bin/rm */.deps/*.P
/bin/rm -f config.cache
aclocal
autoheader
aclocal
automake
autoconf
./configure --with-debug=full --prefix='votre dossier installation'

# les fichiers make générés plus haut ont besoin de GNU make 3.75 ou plus récent.
# (appelé gmake ci-dessous)
gmake clean all install init-db

Si vous rencontrez des problèmes avec un nouveau port, vous devrez faire du débogage de MySQL ! Voir Section D.1, « Déboguer un serveur MySQL ».

Note : avant de commencer à déboguer mysqld, faites d'abord fonctionner les programmes de tests mysys/thr_alarm et mysys/thr_lock. Cela assurera que votre installation des threads a une chance de fonctionner !

31-A - Déboguer un serveur MySQL

Si vous utilisez des fonctionnalités qui ont été ajoutées il y a peu de temps à MySQL, vous pouvez essayer de démarrer mysqld avec --skip-new (qui désactivera toutes les fonctionnalités nouvelles, qui sont potentiellement non stables) ou avec --safe-mode qui désactive un tas d'optimisations qui pourraient poser problèmes. Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

Si mysqld ne veut pas démarrer, vous devez vérifier que vous n'avez pas de fichiers my.cnf qui interfèrent avec votre configuration ! Vous pouvez vérifier les arguments de votre my.cnf avec mysqld --print-defaults et éviter de les utiliser en démarrant avec mysqld --no-defaults ....

Si mysqld se met à trop consommer de mémoire ou de processus, ou s'il se bloque, vous pouvez utiliser mysqladmin processlist status pour trouver si quelqu'un utilise une requête qui prend trop de temps à s'exécuter. C'est un bonne idée d'exécuter mysqladmin -i10 processlist status dans un terminal si vous avez des problèmes de performances ou des problèmes à la connexion de nouveaux clients.

La commande mysqladmin debug écrira des informations à propos des verrous en cours d'utilisation, de la mémoire utilisée et des requêtes dans le fichier de log de MySQL. Cela peut vous aider à résoudre certains problèmes. Cette commande fournit aussi des informations utiles même si vous n'avez pas compilé MySQL pour le débogage !

Si le problème vient du fait que certaines tables sont de plus en plus lentes vous devez essayer de les optimiser en utilisant OPTIMIZE TABLE ou myisamchk. Voir Chapitre 5, Administration du serveur. Vous devez aussi vérifier les requêtes qui prennent trop de temps avec la commande EXPLAIN.

Vous devriez aussi consulter les sections spécifiques aux systèmes d'exploitation dans le manuel pour les problèmes pouvant être uniques à votre environnement. Voir Section 2.8, « Notes spécifiques aux systèmes d'exploitation ».

31-A-1 - Compiler MYSQL pour le débogage

Si vous avez un problème spécifique, vous pouvez toujours essayer de déboguer MySQL. Pour ce faire, vous devez configurer MySQL avec l'option --with-debug ou --with-debug=full. Vous pouvez vérifier si MySQL est déjà compilé avec le support du débogage en faisant ceci : mysqld --help. Si l'attribut --debug est listé avec les options, cela veut dire que le support du débogage est activé. Dans ce cas, mysqladmin ver liste aussi la version de mysqld en tant que mysql ... --debug.

Si vous utilisez gcc ou egcs, la ligne de configuration recommandée est :

CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--with-debug --with-extra-charsets=complex

Cela évitera les problèmes avec la bibliothèque libstdc++ et les exceptions C++ (plusieurs compilateurs ont des problèmes avec les exceptions C++ dans le code threadé) et compilera une version MySQL avec le support de tous les jeux de caractères.

Si vous suspectez un dépassement de la mémoire, vous pouvez configurer MySQL avec --with-debug=full, qui installera un vérificateur d'allocation mémoire (SAFEMALLOC). Fonctionner avec SAFEMALLOC est cependant un peu ralentissant, et donc, si vous rencontrez des problèmes de performances, vous devez démarrer mysqld avec l'option --skip-safemalloc. Cela désactivera les vérifications de dépassements de mémoire pour chaque appel à malloc ou free.

Si mysqld ne plante plus lorsque vous le compilez avec --with-debug, vous avez probablement trouvé un bogue du compilateur ou un bogue de temporisation dans MySQL. Dans ce cas, vous pouvez essayer d'ajouter -g aux variables CFLAGS et CXXFLAGS vues plus haut et ne pas utiliser --with-debug. Si mysqld plante maintenant, vous pouvez vous y attacher avec gdb ou utiliser gdb sur le fichier noyau pour trouver ce qui est arrivé.

Lorsque vous configurez MySQL pour le support du débogage, vous activez automatiquement un tas de fonctions de tests supplémentaires qui se chargent de surveiller le bon fonctionnement de mysqld. Si elles trouvent quelque chose d'inattendu (« unexpected »), une entrée sera écrite dans stderr, que safe_mysqld redirige vers le log d'erreurs ! Cela signifie aussi que si vous avez quelques problèmes inattendus avec MySQL et que vous utilisez une distribution des sources, la première chose à faire est de configurer MySQL avec le support du débogage (la seconde, bien sûr, étant d'envoyer un mail sur les listes de diffusion pour demander de l'aide) ! Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ». Merci d'utiliser le script mysqlbug pour tous les rapport de bogues ou questions concernant la version de MySQL que vous utilisez !

Dans la distribution Windows de MySQL, mysqld.exe est par défaut compilé avec le support des fichiers de traçage.

31-A-2 - Créer un fichier de traçage

Si le serveur mysqld ne démarre pas ou que vous pouvez le crasher facilement, vous pouvez essayer de créer un fichier de traçage pour trouver le problème.

Pour ce faire, vous devez avoir un mysqld qui est compilé pour le débogage. Vous pouvez le vérifier en exécutant mysqld -V. Si le numéro de version se termine par -debug, il est compilé avec le support des fichiers de traçage.

Démarrez le serveur mysqld avec un journal de suivi dans /tmp/mysqld.trace (ou C:\mysqld.trace sous Windows) :

shell> mysqld --debug

Sous Windows vous devez aussi utiliser l'option --standalone pour ne pas démarrer mysqld en tant que service.Dans une console DOS entrez :

mysqld --debug --standalone

Après cela, vous pouvez utiliser l'outil en ligne de commande mysql.exe dans une seconde fenêtre pour reproduire le problème. Vous pouvez couper le serveur avec la commande mysqladmin shutdown.

Notez que le fichier de traçage deviendra très gros ! Si vous voulez obtenir un fichier plus petit, utilisez ce qui suit, par exemple :

mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace

qui n'écrit que les informations les plus intéressantes.

Si vous créez un rapport de bogue, merci de n'envoyer que les lignes du fichier de traçage où le problème se concrétise à la liste de diffusion appropriée ! Si vous n'arrivez pas à trouver le bon endroit dans le fichier, vous pouvez envoyer la totalité du fichier ainsi que le rapport de bogue via FTP à ftp://support.mysql.com/pub/mysql/secret/ [ftp://support.mysql.com/pub/mysql/secret/] pour qu'un développeur MySQL y jette un coup d'œil.

Le fichier de traçage est généré avec le paquet DBUG de Fred Fish. Voir Section D.3, « Le paquet DBUG ».

31-A-3 - Déboguer mysqld sous gdb

Sur la plupart des systèmes, vous pouvez démarrer mysqld à partir de gdb pour obtenir plus d'informations si mysqld plante.

Avec quelques anciennes versions de gdb sous Linux vous devez exécuter run --one-thread si vous voulez être capable de déboguer les threads de mysqld threads. Dans ce cas, vous ne pouvez n'avoir qu'un thread actif à la fois. Nous vous recommandons de mettre à jour gdb à la version 5.1 dès que possible, vu que le débogage des threads fonctionne mieux avec cette version !

Lors de l'utilisation de mysqld sous gdb, vous devez désactiver le traçage de la pile avec -skip-stack-trace, pour pouvoir trouver les erreurs de segmentations avec gdb.

Il est très difficile de déboguer MySQL sous gdb si vous effectuez plusieurs nouvelles connexions tout le temps, vu que gdb ne libère pas la mémoire occupée par les anciens threads. Vous pouvez contourner ce problème en démarrant mysqld avec -O thread_cache_size= 'max_connections +1'. Dans la plupart des cas, le simple fait d'utiliser -O thread_cache_size=5' vous aidera beaucoup !

Si vous voulez obtenir un core dump sur Linux, si mysqld se termine avec un signal SIGSEGV, vous pouvez démarrer mysqld avec l'option --core-file. Ce fichier noyau peut être utilisé pour effectuer des traçages qui peuvent vous aider à trouver pourquoi mysqld s'est terminée :

shell> gdb mysqld core
gdb>   backtrace full
gdb>   exit

Voir Section A.4.2, « Que faire si MySQL plante constamment ? ».

Si vous utilisez gdb 4.17.x ou plus récent sous Linux, vous devez installer un fichier .gdb, avec les informations suivantes, dans votre répertoire courant :

set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint

Si vous rencontrez des problèmes lors du débogage des threads avec gdb, vous devez obtenir la version 5.x de gdb et essayer cela à la place. La nouvelle version de gdb a une meilleur gestion des threads !

Voilà un exemple de comment déboguer mysqld :

shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # A faire lorsque mysqld crashe

Incluez la sortie suivante dans un mail généré avec mysqlbug et envoyez-le sur les listes de diffusion. Voir Section 1.4.1.1, « Les listes de diffusion de MySQL ».

Si mysqld ne répond plus, vous pouvez utiliser des outils système tel que strace ou /usr/proc/bin/pstack, pour savoir où mysqld s'est bloqué.

strace /tmp/log libexec/mysqld

Si vous utilisez l'interface DBI de Perl, vous pouvez activer le débogage en utilisant la méthode trace ou en définissant la variable d'environnement DBI_TRACE.

31-A-4 - Utilisation d'un traçage de pile mémoire

Sur quelques systèmes d'exploitation, le log d'erreurs contiendra un fichier de pile mémoire, si mysqld se termine soudainement. Vous pouvez utiliser ceci pour trouver où (et peut-être pourquoi) mysqld s'est terminé. Voir Section 5.9.1, « Le log d'erreurs ». Pour obtenir un traçage de la pile, vous ne devez pas compiler mysqld avec l'option -fomit-frame-pointer de gcc. Voir Section D.1.1, « Compiler MYSQL pour le débogage ».

Si le fichier d'erreurs contient quelque chose qui ressemble à ce qui suit :

mysqld got signal 11;
The manual section 'Debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attemping backtrace. You can use the following information to find out
where mysqld died.  If you Voir no messages after this, something went
terribly wrong
stack range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686

vous pouvez trouver où s'est terminé mysqld en exécutant :

1. Copiez les nombres précédents dans un fichier, mysqld.stack, par exemple ;

2. Créez un fichier symbolique pour le serveur mysqld :

nm -n libexec/mysqld > /tmp/mysqld.sym

Notez que beaucoup de distributions binaires MySQL fournissent le fichier précédent, nommé mysqld.sym.gz. Dans ce cas, décompressez-le en faisant :

gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym

3. Exécutez resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack.
Cela affichera l'endroit où mysqld a planté. Si ce n'est pas le cas, vous devrez créer un rapport de bogue et y inclure le résultat de la commande précédente.
Notez toutefois que dans la plupart des cas le fait de n'avoir que le traçage de la pile ne nous aidera pas à trouver d'où vient le problème. Pour être capable de trouver le bogue, ou fournir une parade, nous aurons besoin dans la plupart des cas, nous aurons besoin de connaître la requête qui a fait planter mysqld et une batterie de tests pour que nous puissions reproduire le problème ! Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

31-A-5 - Utilisation des fichiers de log pour trouver d'où viennent les erreurs de mysqld

Notez qu'avant de démarrer mysqld avec --log vous devez vérifier toutes vos tables avec myisamchk. Voir Chapitre 5, Administration du serveur.

Si mysqld se termine ou se bloque, vous devez démarrer mysqld avec --log. Lorsque mysqld se termine à nouveau, vous pouvez examiner la fin de votre fichier de log pour trouver les requêtes qui ont terminé mysqld.

Si vous utilisez --log sans spécifier un nom de fichier, le log est enregistré dans le dossier des bases de données en tant que host_name.log. Dans la plupart des cas, c'est la dernière requête dans le fichier de log qui a terminé mysqld, mais si possible, vérifiez le en redémarrant mysqld et en exécutant à nouveau la requête en question à partir du client en ligne de commande mysql. Si elle fonctionne, vous devez aussi tester les autres requêtes complexes qui n'ont pas abouti.

Vous pouvez aussi utiliser la commande EXPLAIN sur toutes vos requêtes SELECT qui prennent beaucoup de temps à s'exécuter, pour être sûrs que mysqld utilise les index convenablement. Voir Section 7.2.1, « Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT) ».

Vous pouvez trouver les requêtes qui prennent trop de temps à s'exécuter en démarrant mysqld avec --log-slow-queries. Voir Section 5.9.5, « Le log des requêtes lentes ».

Si vous trouvez le texte mysqld restarted dans le log d'erreurs (normalement nommé hostname.err) vous avez probablement trouvé une requête qui fait planter mysqld. Si tel est le cas, vous devez vérifier toutes vos tables avec myisamchk (voir Chapitre 5, Administration du serveur), et tester les requêtes dans les fichiers de log MySQL pour voir si elles ne fonctionnent toujours pas. Si vous trouvez une requête de ce genre, essayez d'abord de mettre à jour votre version de MySQL en prenant la version la plus récente. Si cela ne vous aide pas et que vous ne pouvez trouver d'aide dans les archives des mails de mysql, vous devez reporter ce bogue sur les listes de diffusion. Des liens vers les archives de mails sont disponibles en ligne à l'adresse suivante : http://lists.mysql.com/.

Si vous avez démarré mysqld avec myisam-recover, MySQL vérifiera et essayera automatiquement de réparer les tables MyISAM, si elles sont marquées comme « not closed properly » ou « crashed ». Si cela arrive, MySQL ajoutera une entrée dans le fichier hostname.err 'Warning: Checking table ...' qui sera suivie de Warning: Repairing table, si la table devait être réparée. Si vous obtenez beaucoup de ces erreurs, sans que mysqld n'ait planté juste avant, alors quelque chose ne va pas et une enquête plus approfondie est nécessaire. Voir Section 4.3.1, « Options de ligne de commande de mysqld ».

Ce n'est bien sûr pas de bon augure si mysqld a crashé, mais dans ce cas, il ne faut pas s'attarder sur les messages Checking table... mais plutôt essayer de savoir pourquoi mysqld a crashé.

31-A-6 - Faire une batterie de tests lorsque vous faites face à un problème de table corrompue

Si vos tables sont corrompues ou que mysqld échoue toujours avec quelques commandes de mises à jour, vous pouvez tester si le bogue est reproductible en effectuant ce qui suit :

- coupez le démon MySQL (avec mysqladmin shutdown) ;

- créez une copie de vos tables (pour prévoir le cas très improbable ou la réparation tournerait mal) ;

- vérifiez toutes les tables avec myisamchk -s base/*.MYI. Réparez toute table corrompue avec myisamchk -r base/table.MYI ;

- créez une seconde copie des tables ;

- effacez (ou déplacez) tous les vieux fichiers de log du répertoire de données de MySQL si vous avez besoin de plus d'espace ;

- démarrez mysqld avec --log-bin. Voir Section 5.9.4, « Le log binaire ». Si vous voulez trouver une requête qui fait planter mysqld, vous devez utiliser --log -log-bin ;

- lorsque vous obtenez une table corrompue, stoppez le serveur mysqld ;

- restaurez les sauvegardes ;

- redémarrez le serveur mysqld sans --log-bin ;

- réexécutez les commandes avec mysqlbinlog update-log-file | mysql. Le log des mises à jour est sauvegardé dans le dossier des données de MySQL avec le nom hostname-bin.# ;

- si les tables sont à nouveau corrompues ou que vous pouvez faire échouer mysqld avec la commande précédente, vous avez trouvé un bogue reproductible qui devrait être facile à corriger ! Envoyez les tables et le log binaire via FTP à ftp://support.mysql.com/pub/mysql/secret/ [ftp://support.mysql.com/pub/mysql/secret/] et envoyez un mail à <bugs@lists.mysql.com>, ou (si vous êtes client du support) à <support@mysql.com> à propos du problème et l'équipe MySQL le corrigera le plus vite possible.

Vous pouvez aussi utiliser le script mysql_find_rows pour n'exécuter que quelques requêtes de mises à jour si vous voulez mieux cerner le problème.

31-B - Débogage un client MySQL

Pour pouvoir déboguer un client MySQL avec le paquet de débogage intégré, vous devez configurer MySQL avec --with-debug ou --with-debug=full. Voir Section 2.4.2, « Options habituelles de configure ».

Avant de mettre en marche un client, vous devez définir la variable d'environnement MYSQL_DEBUG :

shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell> export MYSQL_DEBUG

Cela fait générer au client un fichier de traçage dans /tmp/client.trace.

Si vous avez un problème avec votre propre code client, vous devez essayer de vous connecter au serveur et exécuter vos requêtes en utilisant un client qui fonctionne. Faites-le en utilisant mysql en mode débogage (en supposant que vous ayez compilé MySQL avec le support du débogage) :

shell> mysql --debug=d:t:O,/tmp/client.trace

Il vous fournira des informations utiles si vous voulez envoyer un rapport de bogue. Voir Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

Si votre client se plante au niveau d'un code qui vous paraît « valide », vous devez vérifier que votre fichier mysql.h inclus correspond à votre bibliothèque MySQL. Une erreur très courante est d'utiliser un vieux fichier mysql.h d'une ancienne installation avec la nouvelle bibliothèque MySQL.

31-C - Le paquet DBUG

Le serveur MySQL et la plupart des clients MySQL sont compilés avec le paquet DBUG écrit, à l'origine, par Fred Fish. Lorsque MySQL est compilé avec le support du débogage, ce paquet permet d'obtenir des fichiers de traçage de ce que le programme débogue. Voir Section D.1.2, « Créer un fichier de traçage ».

Le paquet de débogage est utilisé en invoquant le programme avec l'option --debug="..." ou -#....

La plupart des programmes MySQL ont une chaîne de débogage par défaut qui sera utilisée si vous ne spécifiez aucune option à --debug. Le fichier de traçage par défaut est usuellement /tmp/nomprogramme.trace sur Unix et \nomprogramme.trace sur Windows.

La chaîne de caractères de contrôle du débogage est une séquence de champs séparés par des deux-points (:) comme celle qui suit :

<champ_1>:<champ_2>:...:<champ_N>

Chaque champ consiste en un caractère attribut, suivi d'une liste de modificateurs commençant optionnellement par une virgule ',' et séparés par des virgules :

flag[,modificateur,modificateur,...,modificateur]

Les caractères attributs actuellement reconnus sont :

Attribut

Description

d

Active les sorties des macros DBUG_<N> pour l'état courant. Peut être suivi d'une liste de mots clefs, ce qui sélectionne la sortie seulement pour les macros DBUG contenant ces mots. Une liste de mots clefs vides implique les sorties de toutes les macros.

D

Attendre après chaque ligne résultante du débogueur. L'argument est le nombre de dixième de secondes à attendre, sujet aux capacités de la machine. Et donc, -#D,20 est une attente de deux secondes.

f

Limiter le débogage et/ou le traçage aux fonctions citées. Notez qu'une liste nulle désactivera toutes les fonctions. Les attributs appropriés « d » ou « t » doivent quand même être donnés, cet attribut ne limite que leurs actions, si ils sont activés.

F

Identifie le nom du fichier source pour chaque ligne de débogage ou de traçage affichée.

i

Identifie le processus avec son identifiant pour chaque ligne de débogage ou de traçage affichée.

g

Active le profiling. Crée un fichier nommé dbugmon.out contenant des informations qui peuvent être utilisées pour profiler le programme. Peut être suivi d'une liste de mots clefs qui sélectionnent le profiling uniquement pour les fonctions présentes dans cette liste. Une liste nulle implique que toutes les fonctions sont considérées.

L

Identifie le numéro de ligne du fichier source pour chaque ligne renvoyée par le traçage ou le débogage.

n

Imprime le niveau de profondeur de la fonction en cours d'exécution pour la sortie du traçage ou du débogage.

N

Numérote chaque ligne de la sortie du débogage.

o

Redirige le flux de sortie du débogueur vers le fichier spécifié. Par défaut, c'est stderr.

O

Comme o mais le fichier est vraiment écrit entre chaque ajout de contenu. Lorsque le besoin en est, le fichier est fermé puis ré-ouvert entre chaque écriture.

p

Limite les actions du débogueur aux processus spécifiés. Un processus peut être identifié avec la macro DBUG_PROCESS et correspondre à un processus dans la liste pour que le débogage ait lieu.

P

Affiche le nom du processus courant pour chaque ligne de sortie de débogage ou de traçage.

r

Lors du passage à un nouvel état, ne pas hériter le niveau de profondeur de l'état de la fonction précédente. Utile lorsque l'affichage commence à la marge gauche.

S

Exécute la fonction _sanity(_file_,_line_) sur chaque fonction déboguée jusqu'à ce que la valeur de retour de _sanity() diffère de 0. (La plupart du temps utilisée avec safemalloc pour trouver les pertes de mémoire).

t

Active le traçage des appels/sorties des fonctions. Peut être suivi d'une liste (ne contenant qu'un seul modificateur) donnant un maximum numérique du traçage, au delà duquel aucune sortie ne sera affichée pour les macros de débogage ou de traçage. Par défaut, c'est une option de temps de compilation.

Quelques exemples de chaînes de contrôle de débogage pouvant être utilisée en ligne de commande dans le shell (« -# » est typiquement utilisé pour introduire une chaîne de contrôle à un programme d'application), sont :

-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace

En MySQL, les balises communes affichées (avec l'option d) sont : enter,exit,error,warning,info et loop.

31-D - Commentaires à propos des threads RTS

J'ai essayé d'utiliser le paquet de threads RTS avec MySQL, mais je suis resté bloqué au niveau des problèmes suivants :

- ils utilisent une veille version avec beaucoup d'appels POSIX et il est vraiment difficile de créer une couche d'abstraction pour toutes les fonctions. Je pense qu'il serait plus facile de changer la bibliothèque des threads pour qu'elle suive les nouvelles spécifications POSIX ;

- quelques couches d'abstractions sont déjà écrites. Voyez mysys/my_pthread.c pour plus d'informations.

Au minimum, ce qui suit devra être changé :

pthread_get_specific doit utiliser un seul argument. sigwait doit prendre deux arguments. Beaucoup de fonctions (du moins pthread_cond_wait, pthread_cond_timedwait) doivent retourner le code erreur lorsqu'elles en rencontrent. Elle retournent à présent -1 et définissent errno.

Un autre problème est que les threads au niveau utilisateurs utilisent les signaux ALRM et que ceux-ci font échouer beaucoup de fonctions (read, write, open...). MySQL devrait faire une autre tentative à chaque interruption, mais cela n'est pas facile à vérifier.

Le plus gros problème non résolu est le suivant :

pour avoir des alertes au niveau des threads, j'ai changé mysys/thr_alarm.c pour avoir une attente entre les alarmes avec pthread_cond_timedwait(), mais cela échoue avec une erreur EINTR. J'ai essayé de déboguer la bibliothèque des threads pour voir d'où cela venait, mais je n'ai pu trouver aucune solution simple.

Si quelqu'un veut utiliser MySQL avec les threads RTS je suggère ce qui suit :

- changez les fonctions que MySQL utilise à partir de la bibliothèque des threads en POSIX. Cela ne devrait pas vous prendre beaucoup de temps ;

- compilez toutes les bibliothèques avec -DHAVE_rts_threads ;

- compilez thr_alarm ;

- sil y a de petites différences dans l'implémentation, elles peuvent être corrigées en changeant les fichiers my_pthread.h et my_pthread.c ;

- exécutez thr_alarm. S'il tourne sans aucun message du type « warning », « error » ou « aborted », vous êtes sur le bon chemin. Voici une bonne exécution se déroulant sur Solaris :

Main thread: 1
Thread 0 (5) started
Thread: 5  Waiting
process_alarm
Thread 1 (6) started
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 1 (1) sec
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 2 (2) sec
Thread: 6  Simulation of no alarm needed
Thread: 6  Slept for 0 (3) sec
Thread: 6  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 4 (4) sec
Thread: 6  Waiting
process_alarm
thread_alarm
Thread: 5  Slept for 10 (10) sec
Thread: 5  Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6  Slept for 5 (5) sec
Thread: 6  Waiting
process_alarm
process_alarm

...
thread_alarm
Thread: 5  Slept for 0 (1) sec
end

31-E - Différences entre les types de paquets de threads

MySQL est très dépendant du paquet de threads utilisé. Ce qui fait que lors du choix d'une bonne plate-forme pour MySQL, le paquet des threads est très important.

Il y a au moins trois types de paquets de threads :

- Threads utilisateurs dans un processus unique. Le changement de threads est géré avec des alarmes et la bibliothèque des threads gère les fonctions non utilisables avec les threads par des verrouillages. Les opérations de lectures, d'écritures et de sélections sont usuellement gérées avec une sélection spécifique aux threads, qui passe à un autre thread si celui en cours d'exécution attend des données. Si les paquets des threads utilisateurs sont intégrés dans les bibliothèques standards (threads FreeBSD et BSDI) le paquet de thread nécessite moins de ressources que les paquets de thread qui doivent mapper tous les appels non sûrs (MIT-pthreads, FSU Pthreads et RTS threads). Avec quelques environnements, (SCO, par exemple), tous les appels système sont sûrs pour les threads, ce qui fait que la liaison peut se faire très facilement (Pthreads FSU sur SCO). Mauvais côté : tous les appels mappés prennent un peu de temps, et il est assez difficile de pouvoir gérer toutes les situations. Il y a aussi souvent des appels système qui ne sont pas gérés par le paquet de threads (comme MIT-pthreads et les sockets). La gestion des threads n'est pas toujours optimale.

- Threads utilisateurs dans des processus séparés. Les changements de threads sont effectués par le noyau et toutes les données sont partagées entre les threads. Le paquet de thread gère les appels threads standards pour permettre le partage entre les threads. LinuxThreads utilise cette méthode. Mauvais côté : beaucoup de processus. La création des threads est lente. Si un thread s'interrompt, les autres restent en suspens et vous devez tous les terminer avant de redémarrer. Le changement de thread est d'une certaine façon consommateur de ressources.

- Threads noyau. Le changement de threads est géré par la bibliothèque de threads ou le noyau est très rapide. Tout est fait en un seul processus, mais sur certains systèmes, ps peut montrer plusieurs threads. Si un thread échoue, tout le processus échoue. La plupart des appels système sont bons pour les threads et ne devraient avoir besoin que d'une petite perte de performances. Solaris, HP-UX, AIX et OSF/1 ont des threads noyau.

Avec quelques systèmes, les threads du noyau sont gérés en intégrant les threads niveau utilisateur dans les bibliothèques du système. Dans ces cas, le changement de thread ne peut être fait qu'avec la bibliothèque de threads et le noyau n'est pas vraiment « attentif aux threads ».

32 - Variables d'environnement

Voici une liste de toutes les variables d'environnement qui sont directement ou indirectement utilisées par MySQL. La plupart peuvent être retrouvées dans d'autres parties du manuel.

Notez que toute option en ligne de commande prendra la précédence par rapport aux valeurs spécifiées dans les fichiers de configuration et les variables d'environnement, et que les valeurs dans les fichiers de configuration prennent la précédence sur les valeurs des variables d'environnement.

Dans beaucoup de cas, il est préférable d'utiliser un fichier de configuration plutôt que les variables d'environnement pour modifier le comportement de MySQL. Voir Section 4.3.2, « Fichier d'options my.cnf ».

Variable

Description

CCX

À passer au compilateur C++ lors de l'exécution de configure.

CC

À passer au compilateur C lors de l'exécution de configure.

CFLAGS

À passer au compilateur C lors de l'exécution de configure.

CXXFLAGS

À passer au compilateur C++ lors de l'exécution de configure.

DBI_USER

L'utilisateur par défaut pour Perl DBI.

DBI_TRACE

Utilisée lors du traçage de Perl DBI.

HOME

Le chemin par défaut vers les fichiers d'historique de mysql est $HOME/.mysql_history.

LD_RUN_PATH

Utilisé pour spécifier où se trouve libmysqlclient.so.

MYSQL_DEBUG

Options de débogage/traçage lors de la phase de débogage.

MYSQL_HISTFILE

Le chemin vers le fichier d'historique de mysql. Si cette variable existe, sa valeur remplace la valeur par défaut de $HOME/.mysql_history.

MYSQL_HOST

Nom d'hôte par défaut utilisé par le client en ligne de commande mysql.

MYSQL_PS1

Invite de commande à utiliser dans le client en ligne de commande mysql. Voir Section 8.3, « mysql, l'outil en ligne de commande ».

MYSQL_PWD

Le mot de passe par défaut lors de la connexion à mysqld. Notez que cette utilisation n'est pas sécurisée.

MYSQL_TCP_PORT

Le port TCP/IP par défaut.

MYSQL_UNIX_PORT

La socket par défaut; utilisée pour les connexions à localhost.

PATH

Utilisé par le Shell pour trouver les programmes MySQL.

TMPDIR

Le dossier où les tables et fichiers temporaires sont créés.

TZ

Cela devrait être configuré à votre fuseau horaire local. Voir Section A.4.6, « Problèmes de fuseaux horaires ».

UMASK_DIR

Le masque de création des dossiers. Notez que cette valeur est soumise à un ET logique par rapport à UMASK !

UMASK

Le masque de création des fichiers utilisateur lors de la création de fichiers.

USER

L'utilisateur par défaut de Windows utilisé lors de la connexion à mysqld.

33 - Expressions régulières MySQL

Une expression régulière (regex) est la meilleure méthode pour spécifier une recherche complexe.

MySQL utilise l'implémentation de Henry Spencer des expressions régulières qui tend à être conforme à POSIX 1003.2. MySQL en utilise la version étendue. Voir Annexe B, Crédits. La version améliorée de MySQL supporte les expressions régulières effectuées avec REGEXP dans les commandes SQL. Voir Section 3.3.4.7, « Recherche de modèles ».

Ceci est une référence simplifiée qui n'aborde pas les détails. Pour avoir plus d'informations, reportez-vous à la page de manuel regex(7) de Henry Spencer. Ce manuel est inclus dans la distribution MySQL, dans le fichier regex.7 du dossier regex.

Une expression régulière décrit un jeu de chaînes de caractères. La plus simple est celle qui ne comporte pas de caractères spéciaux. Par exemple, l'expression régulière bonjour trouvera bonjour et rien d'autre.

Les expressions régulières non triviales utilisent des constructions spéciales pour pouvoir trouver plus d'une chaîne. Par exemple, l'expression régulière bonjour|monde trouve la chaîne bonjour ou la chaîne monde.

Voici un exemple encore plus complexe : l'expression régulière B[an]*s trouve l'une des chaînes suivantes Bananas, Baaaaas, Bs, et n'importe quelle autre chaîne commençant par un B, se terminant par un s, et contenant n'importe quel nombre de a et de n au milieu.

Une expression régulière peut utiliser l'un des caractères spéciaux ou constructions suivants :

- ^
Correspond au début de la chaîne.

mysql> SELECT "fo\nfo" REGEXP "^fo$";           -> 0
mysql> SELECT "fofo" REGEXP "^fo";              -> 1

- $
Correspond à la fin de la chaîne.

mysql> SELECT "fo\no" REGEXP "^fo\no$";         -> 1
mysql> SELECT "fo\no" REGEXP "^fo$";            -> 0

- .
N'importe quel caractère (nouvelle ligne incluse).

mysql> SELECT "fofo" REGEXP "^f.*";             -> 1
mysql> SELECT "fo\nfo" REGEXP "^f.*";           -> 1

- a*
Correspond à toute séquence de zéro ou plus caractères a.

mysql> SELECT "Ban" REGEXP "^Ba*n";             -> 1
mysql> SELECT "Baaan" REGEXP "^Ba*n";           -> 1
mysql> SELECT "Bn" REGEXP "^Ba*n";              -> 1

- a+
Correspond à toute séquence de un ou plus caractères a.

mysql> SELECT "Ban" REGEXP "^Ba+n";             -> 1
mysql> SELECT "Bn" REGEXP "^Ba+n";              -> 0

- a?
Correspond à zéro ou un caractère a.

mysql> SELECT "Bn" REGEXP "^Ba?n";              -> 1
mysql> SELECT "Ban" REGEXP "^Ba?n";             -> 1
mysql> SELECT "Baan" REGEXP "^Ba?n";            -> 0

- de|abc
Correspond aux séquences de de ou de abc.

mysql> SELECT "pi" REGEXP "pi|apa";             -> 1
mysql> SELECT "axe" REGEXP "pi|apa";            -> 0
mysql> SELECT "apa" REGEXP "pi|apa";            -> 1
mysql> SELECT "apa" REGEXP "^(pi|apa)$";        -> 1
mysql> SELECT "pi" REGEXP "^(pi|apa)$";         -> 1
mysql> SELECT "pix" REGEXP "^(pi|apa)$";        -> 0

- (abc)*
Correspond à zéro ou plus séquences de abc.

mysql> SELECT "pi" REGEXP "^(pi)*$";            -> 1
mysql> SELECT "pip" REGEXP "^(pi)*$";           -> 0
mysql> SELECT "pipi" REGEXP "^(pi)*$";          -> 1

- {1}, {2,3}
Voici une façon plus générale d'écrire les expressions régulières qui correspondent à plusieurs occurrences du dernier atome. m et n sont des entiers.
Pour être plus précis, un atome suivi d'une accolade contenant un entier i et pas de virgule trouve une séquence d'exactement i atomes.
Un atome suivi d'une accolade contenant un entier i et une virgule trouve une séquence de i ou plus atomes.
Un atome suivi d'une accolade contenant deux entiers i et j séparés d'une virgule trouve les séquences de i à j (inclusif) atomes.
Les deux arguments doivent être compris entre 0 et RE_DUP_MAX (par défaut 255), inclusif. S'il y a deux arguments, le second doit être supérieur ou égal au premier.

- a*
Peut être écrit a{0,}.

- a+
Peut être écrit a{1,}.

- a?
Peut être écrit a{0,1}.

mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e';              -> 0
mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e';              -> 1
mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e';           -> 1

- [a-dX], [^a-dX]
Trouve n'importe quel caractère qui est (ou n'est pas, si ^ est utilisé) a, b, c, d ou X. Pour inclure le caractère littéral ], il doit suivre immédiatement le crochet ouvrant [. Pour inclure le caractère littéral -, il doit être écrit en premier ou en dernier. Ce qui fait que [0-9] correspond à n'importe quel chiffre. Chaque caractère qui n'a pas de signification spéciale à l'intérieur une paire de [] ne joue pas de rôle spécial et ne correspond qu'à lui même.

mysql> SELECT 'aXbc' REGEXP '[a-dXYZ]';                 -> 1
mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]$';               -> 0
mysql> SELECT 'aXbc' REGEXP '^[a-dXYZ]+$';              -> 1
mysql> SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$';             -> 0
mysql> SELECT 'gheis' REGEXP '^[^a-dXYZ]+$';            -> 1
mysql> SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$';           -> 0

- [.characters.]
La séquence de caractères de cet élément d'assemblage. La séquence est un élément de la liste contenue entre les crochets. Une telle expression contenant un élément d'assemblage multicaractère peut ainsi trouver plus d'un caractère. Vous trouverez la liste complète des noms de caractères dans regexp/cname.h.

mysql> SELECT '~' REGEXP '[[.~.]]';                     -> 1
mysql> SELECT '~' REGEXP '[[.tilde.]]';                 -> 1

- [=character_class=]
Une classe d'équivalence, remplaçant les séquences de caractères de tous les éléments de l'assemblage équivalents à celui-ci, lui-même inclus.
Par exemple, si o et (+) sont membres d'une classe d'équivalence, alors [[=o=]], [[=(+)=]], et [o(+)] sont tous des synonymes. Une classe d'équivalence ne doit pas être un point final d'intervalle.

- [:character_class:]
Dans une expression entre crochets, le nom d'une classe de caractères entourée de [: et :] remplace la liste de tous les caractères appartenant à cette classe. Les noms des classes de caractères sont :

alnum

Caractères alphanumériques

alpha

Caractères alphabétiques

blank

Caractères espace

cntrl

Caractères de contrôle

digit

Chiffres

graph

Caractères graphiques

lower

Minuscules

print

Caractères graphiques ou espaces

punct

Ponctuation

space

Espace, tabulation, nouvelle ligne et retour chariot

upper

Majuscules

xdigit

Chiffres hexadécimaux

Voilà les classes de caractères définies dans la page de manuel ctype(3). Une locale peut en fournir d'autres. Une classe de caractères ne doit pas être utilisée en tant que point final d'intervalle.

mysql> SELECT "justalnums" REGEXP "[[:alnum:]]+";       -> 1
mysql> SELECT "!!" REGEXP "[[:alnum:]]+";               -> 0

- [[:<:]], [[:>:]]
Ceux-là trouvent la chaîne nulle qui précède et suit chaque mot. Un mot est défini comme étant une séquence de caractères qui n'est ni suivie ni précédée d'un caractère de mot. Un caractère de mot est un caractère alnum (défini par ctype(3)) ou un tiret bas (_).

mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]';   -> 1
mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]';  -> 0

Pour utiliser une instance littérale d'un caractère spécial dans une expression régulière, vous devez la faire précéder de deux caractères anti-slash. L'analyseur MySQL interprète le premier anti-slash, et la bibliothèque d'expressions régulières utilisera le second. Par exemple, pour rechercher l'expression 1+2 qui contient le caractère spécial +, seule la dernière expression régulière sera correcte :

mysql> SELECT '1+2' REGEXP '1+2';                       -> 0
mysql> SELECT '1+2' REGEXP '1\+2';                      -> 0
mysql> SELECT '1+2' REGEXP '1\\+2';                     -> 1

34 - Licence Publique Générale GNU

Notice d'accompagnement de la traduction non officielle à conserver dans toute reproduction de cette traduction

This is an unofficial translation of the GNU General Public License into french. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU GPL--only the original English text of the GNU GPL does that. However, we hope that this translation will help french speakers understand the GNU GPL better.

Ceci est une traduction non officielle de la GNU General Public License en français. Elle n'a pas été publiée par la Free Software Foundation, et ne détermine pas les termes de distribution pour les logiciels qui utilisent la GNU GPL - seul le texte anglais original de la GNU GPL en a le droit. Cependant, nous espérons que cette traduction aidera les francophones à mieux comprendre la GPL.

Cette traduction est sous Copyright 2001 APRIL (http://www.april.org). La version la plus à jour de ce document est disponible sur http://www.april.org/gnu/gpl_french.html.

Il est permis à tout le monde de reproduire et distribuer des copies conformes de cette traduction, mais aucune modification ne doit y être apportée, et la présente notice doit être préservée.

Nous autorisons la FSF à apporter toute modification qu'elle jugera nécessaire pour rendre la traduction plus claire.

Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
Il est permis à tout le monde de reproduire et distribuer des copies conformes
de ce document de licence, mais aucune modification ne doit y être apportée.

Préambule

Les licences relatives à la plupart des logiciels sont destinées à supprimer votre liberté de les partager et de les modifier. Par contraste, la licence publique générale GNU General Public License veut garantir votre liberté de partager et de modifier les logiciels libres, pour qu'ils soient vraiment libres pour tous leurs utilisateurs. La présente licence publique générale s'applique à la plupart des logiciels de la Free Software Foundation, ainsi qu'à tout autre programme dont les auteurs s'engagent à l'utiliser. (Certains autres logiciels sont couverts par la Licence Publique Générale pour Bibliothèques GNU à la place.) Vous pouvez aussi l'appliquer à vos programmes.

Quand nous parlons de logiciels libres, nous parlons de liberté, non de gratuité. Nos licences publiques générales veulent vous garantir que vous avez toute liberté de distribuer des copies des logiciels libres (et de facturer ce service, si vous le souhaitez), que vous recevez les codes sources ou pouvez les obtenir si vous le souhaitez, que vous pouvez modifier les logiciels ou en utiliser des éléments dans de nouveaux programmes libres, et que vous savez que vous pouvez le faire.

Pour protéger vos droits, nous devons apporter des restrictions, qui vont interdire à quiconque de vous dénier ces droits, ou de vous demander de vous en désister. Ces restrictions se traduisent par certaines responsabilités pour ce qui vous concerne, si vous distribuez des copies de logiciels, ou si vous les modifiez.

Par exemple, si vous distribuez des copies d'un tel programme, gratuitement ou contre une rémunération, vous devez transférer aux destinataires tous les droits dont vous disposez. Vous devez vous garantir qu'eux-mêmes, par ailleurs, reçoivent ou peuvent recevoir le code source. Et vous devez leur montrer les présentes dispositions, de façon qu'ils connaissent leurs droits.

Nous protégeons vos droits en deux étapes : (1) nous assurons le droit d'auteur (copyright) du logiciel, et (2) nous vous proposons cette licence, qui vous donne l'autorisation légale de dupliquer, distribuer et/ou modifier le logiciel.

De même, pour la protection de chacun des auteurs, et pour notre propre protection, nous souhaitons nous assurer que tout le monde comprenne qu'il n'y a aucune garantie portant sur ce logiciel libre. Si le logiciel est modifié par quelqu'un d'autre puis transmis à des tiers, nous souhaitons que les destinataires sachent que ce qu'ils possèdent n'est pas l'original, de façon que tous problèmes introduits par d'autres ne se traduisent pas par une répercussion négative sur la réputation de l'auteur original.

Enfin, tout programme libre est en permanence menacé par des brevets de logiciels. Nous souhaitons éviter le danger que des sous-distributeurs d'un programme libre obtiennent à titre individuel des licences de brevets, avec comme conséquence qu'ils ont un droit de propriété sur le programme. Pour éviter cette situation, nous avons fait tout ce qui est nécessaire pour que tous brevets doivent faire l'objet d'une concession de licence qui en permette l'utilisation libre par quiconque, ou bien qu'il ne soit pas concédé du tout.

Nous présentons ci-dessous les clauses et dispositions concernant la duplication, la distribution et la modification.

CONDITIONS D'EXPLOITATION PORTANT SUR LA DUPLICATION, LA DISTRIBUTION ET LA MODIFICATION

1. Le présent contrat de licence s'applique à tout programme ou autre ouvrage contenant un avis, apposé par le détenteur du droit de propriété, disant qu'il peut être distribué au titre des dispositions de la présente Licence Publique Générale. Ci-après, le « Programme » désigne l'un quelconque de ces programmes ou ouvrages, et un « ouvrage fondé sur le programme » désigne soit le programme, soit un ouvrage qui en dérive au titre de la loi sur le droit d'auteur ; plus précisément, il s'agira d'un ouvrage contenant le programme ou une version de ce dernier, soit mot à mot, soit avec des modifications et/ou traduit en une autre langue (ci-après, le terme « modification » englobe, sans aucune limitation, les traductions qui en sont faites). Chaque titulaire de licence sera appelé « concessionnaire ».
Les activités autres que la duplication, la distribution et la modification ne sont pas couvertes par la présente licence ; elles n'entrent pas dans le cadre de cette dernière. L'exécution du programme n'est soumise à aucune restriction, et les résultats du programme ne sont couverts que si son contenu constitue un ouvrage fondé sur le programme (indépendamment du fait qu'il a été réalisé par exécution du programme). La véracité de ce qui précède dépend de ce que fait le programme.

2. Le concessionnaire peut dupliquer et distribuer des copies mot à mot du code source du programme tel qu'il les reçoit, et ce, sur un support quelconque, du moment qu'il appose, d'une manière parfaitement visible et appropriée, sur chaque exemplaire, un avis approprié de droits d'auteur (Copyright) et de renonciation à garantie ; qu'il maintient intacts tous les avis qui se rapportent à la présente licence et à l'absence de toute garantie ; et qu'il transmet à tout destinataire du programme un exemplaire de la présente licence en même temps que le programme.
Le concessionnaire peut facturer l'acte physique de transfert d'un exemplaire, et il peut, à sa discrétion, proposer en échange d'une rémunération une protection en garantie.

3. Le concessionnaire peut modifier son ou ses exemplaires du programme ou de toute portion de ce dernier, en formant ainsi un ouvrage fondé sur le programme, et dupliquer et distribuer ces modifications ou cet ouvrage selon les dispositions de la section 1 ci-dessus, du moment que le concessionnaire satisfait aussi à toutes ces conditions.
Les exigences ci-dessus s'appliquent à l'ouvrage modifié pris en bloc. Si des sections identifiables de cet ouvrage ne dérivent pas du programme et peuvent être considérées raisonnablement comme représentant des ouvrages indépendants et distincts par eux-mêmes, alors la présente licence, et ses dispositions, ne s'appliquent pas à ces sections quand le concessionnaire les distribue sous forme d'ouvrages distincts. Mais quand le concessionnaire distribue ces mêmes sections en tant qu'élément d'un tout qui représente un ouvrage se fondant sur le programme, la distribution de ce tout doit se faire conformément aux dispositions de la présente licence, dont les autorisations, portant sur d'autres concessionnaires, s'étendent à la totalité dont il est question, et ainsi à chacune de ces parties, indépendamment de celui qu'il l'a écrite.
Ainsi, cette section n'a pas pour but de revendiquer des droits ou de contester vos droits sur un ouvrage entièrement écrit par le concessionnaire ; bien plus, l'intention est d'exercer le droit de surveiller la distribution d'ouvrages dérivée ou collective se fondant sur le programme.
De plus, un simple assemblage d'un autre ouvrage ne se fondant pas sur le programme, avec le programme (ou avec un ouvrage se fondant sur le programme) sur un volume d'un support de stockage ou distribution, ne fait pas entrer l'autre ouvrage dans le cadre de la présente licence.

1. Le concessionnaire doit faire en sorte que les fichiers modifiés portent un avis, parfaitement visible, disant que le concessionnaire a modifié les fichiers, avec la date de tout changement.

2. Le concessionnaire doit faire en sorte que tout ouvrage qu'il distribue ou publie, et qui, en totalité ou en partie, contient le programme ou une partie quelconque de ce dernier ou en dérive, soit concédé en bloc, à titre gracieux, à tous tiers au titre des dispositions de la présente licence.

3. Si le programme modifié lit normalement des instructions interactives lors de son exécution, le concessionnaire doit, quand il commence l'exécution du programme pour une telle utilisation interactive de la manière la plus usuelle, faire en sorte que ce programme imprime ou affiche une annonce, comprenant un avis approprié de droits d'auteur, et un avis selon lequel il n'y a aucune garantie (ou autrement, que le concessionnaire fournit une garantie), et que les utilisateurs peuvent redistribuer le programme au titre de ces dispositions, et disant à l'utilisateur comment visualiser une copie de cette licence (exception : si le programme par lui-même est interactif, mais n'imprime normalement pas une telle annonce, l'ouvrage du concessionnaire se fondant sur le programme n'a pas besoin d'imprimer une annonce).

4. Le concessionnaire peut dupliquer et distribuer le programme (ou un ouvrage se fondant sur ce dernier, au titre de la Section 2), en code objet ou sous une forme exécutable, au titre des dispositions des Sections 1 et 2 ci-dessus, du moment que le concessionnaire effectue aussi l'une des opérations suivantes.
Le code source d'un ouvrage représente la forme préférée de l'ouvrage pour y effectuer des modifications. Pour un ouvrage exécutable, le code source complet représente la totalité du code source pour tous les modules qu'il contient, plus tous fichiers de définitions d'interface associés, plus les informations en code machine pour commander la compilation et l'installation du programme exécutable. Cependant, à titre d'exceptions spéciales, le code source distribué n'a pas besoin de comprendre quoi que ce soit qui est normalement distribué (sous forme source ou sous forme binaire) avec les composants principaux (compilateur, noyau de système d'exploitation, etc.) du système d'exploitation sur lequel est exécuté le programme exécutable, à moins que le composant, par lui-même, soit joint au programme exécutable.
Si la distribution de l'exécutable ou du code objet est réalisée de telle sorte qu'elle offre d'accéder à une copie à partir d'un lieu désigné, alors le fait d'offrir un accès équivalent à la duplication du code source à partir de ce même lieu s'entend comme distribution du code source, même si des tiers ne sont pas contraints de dupliquer la source en même temps que le code objet.

1. Lui joindre le code source complet correspondant, exploitable par une machine, code qui doit être distribué au titre des Sections 1 et 2 ci-dessus sur un support couramment utilisé pour l'échange de logiciels ; ou bien

2. Lui joindre une offre écrite, dont la validité se prolonge pendant au moins 3 ans, de transmettre à un tiers quelconque, pour un montant non supérieur au coût pour le concessionnaire, de réalisation physique de la distribution de la source, un exemplaire complet, exploitable par une machine, du code source correspondant, qui devra être distribué au titre des dispositions des Sections 1 et 2 ci-dessus sur un support couramment utilisé pour l'échange des logiciels ; ou bien

3. Lui joindre les informations que le concessionnaire a reçues, pour proposer une distribution du code source correspondant (cette variante n'est autorisée que pour la distribution non commerciale, et seulement si le concessionnaire a reçu le programme sous forme exécutable ou sous forme d'un code objet, avec une telle offre, conformément à l'alinéa b) ci-dessus).

5. Le concessionnaire ne peut dupliquer, modifier, concéder en sous-licence ou distribuer le programme, sauf si cela est expressément prévu par les dispositions de la présente licence. Toute tentative pour autrement dupliquer, modifier, concéder en sous-licence ou distribuer le programme est réputée nulle, et met automatiquement fin aux droits du concessionnaire au titre de la présente licence. Cependant, les parties qui ont reçu des copies, ou des droits, de la part du concessionnaire au titre de la présente licence, ne verront pas expirer leur contrat de licence, tant que ces parties agissent d'une manière parfaitement conforme.

6. Il n'est pas exigé du concessionnaire qu'il accepte la présente licence, car il ne l'a pas signée. Cependant, rien d'autre n'octroie au concessionnaire l'autorisation de modifier ou de distribuer le programme ou ses ouvrages dérivés. Ces actions sont interdites par la loi si le concessionnaire n'accepte pas la présente licence. En conséquence, par le fait de modifier ou de distribuer le programme (ou un ouvrage quelconque se fondant sur le programme), le concessionnaire indique qu'il accepte la présente licence, et qu'il a la volonté de se conformer à toutes les clauses et dispositions concernant la duplication, la distribution ou la modification du programme ou d'ouvrages se fondant sur ce dernier.

7. Chaque fois que le concessionnaire redistribue le programme (ou tout ouvrage se fondant sur le programme), le destinataire reçoit automatiquement une licence de l'émetteur initial de la licence, pour dupliquer, distribuer ou modifier le programme, sous réserve des présentes clauses et dispositions. Le concessionnaire ne peut imposer aucune restriction plus poussée sur l'exercice, par le destinataire, des droits octroyés au titre des présentes. Le concessionnaire n'a pas pour responsabilité d'exiger que des tiers se conforment à la présente licence.

8. Si, en conséquence une décision de justice ou une allégation d'infraction au droit des brevets, ou pour toute autre raison (qui n'est pas limitée à des problèmes de propriétés industrielles), des conditions sont imposées au concessionnaire (par autorité de justice, par convention ou autrement), qui entrent en contradiction avec les dispositions de la présente licence, elles n'exemptent pas le concessionnaire de respecter les dispositions de la présente licence. Si le concessionnaire ne peut procéder à la distribution de façon à satisfaire simultanément à ces obligations au titre de la présente licence et à toutes autres obligations pertinentes, alors, en conséquence de ce qui précède, le concessionnaire peut ne pas procéder du tout à la distribution du programme. Par exemple, si une licence de brevet ne permettait pas une redistribution du programme, sans redevances, par tous ceux qui reçoivent des copies directement ou indirectement par l'intermédiaire du concessionnaire, alors le seul moyen par lequel le concessionnaire pourrait satisfaire tant à cette licence de brevet qu'à la présente licence, consisterait à s'abstenir complètement de distribuer le programme.
Si une partie quelconque de cette section est considérée comme nulle ou non exécutoire dans certaines circonstances particulières, le reste de cette section est réputé s'appliquer, et la section dans son ensemble est considérée comme s'appliquant dans les autres circonstances.
La présente section n'a pas pour objet de pousser le concessionnaire à enfreindre tous brevets ou autres revendications à droit de propriété, ou encore à contester la validité d'une ou plusieurs quelconques de ces revendications ; la présente section a pour objet unique de protéger l'intégrité du système de distribution des logiciels libres, système qui est mis en œuvre par les pratiques liées aux licences publiques. De nombreuses personnes ont apporté une forte contribution à la gamme étendue des logiciels distribués par ce système, en comptant sur l'application systématique de ce système ; c'est à l'auteur/donateur de décider s'il a la volonté de distribuer le logiciel par un quelconque autre système, et un concessionnaire ne peut imposer ce choix.
La présente section veut rendre parfaitement clair ce que l'on pense être une conséquence du reste de la présente licence.

9. Si la distribution et/ou l'utilisation du Programme est restreinte dans certains pays, sous l'effet de brevets ou d'interfaces présentant un droit d'auteur, le détenteur du droit d'auteur original, qui soumet le Programme aux dispositions de la présente licence, pourra ajouter une limitation expresse de distribution géographique excluant ces pays, de façon que la distribution ne soit autorisée que dans les pays ou parmi les pays qui ne sont pas ainsi exclus. Dans ce cas, la limitation fait partie intégrante de la présente licence, comme si elle était écrite dans le corps de la présente licence.

10. La Free Software Foundation peut, de temps à autre, publier des versions révisées et/ou nouvelles du General Public License. Ces nouvelles versions seront analogues, du point de vue de leur esprit, à la présente version, mais pourront en différer dans le détail, pour résoudre de nouveaux problèmes ou de nouvelles situations.
Chaque version reçoit un numéro de version qui lui est propre. Si le programme spécifie un numéro de version de la présente licence, qui s'applique à cette dernière et « à toute autre version ultérieure », le concessionnaire a le choix de respecter les clauses et dispositions de cette version, ou une quelconque version ultérieure publiée par la Free Software Foundation. Si le programme ne spécifie pas de numéro de version de la présente licence, le concessionnaire pourra choisir une version quelconque publiée à tout moment par la Free Software Foundation.

11. Si le concessionnaire souhaite incorporer des parties du programme dans d'autres programmes libres dont les conditions de distribution sont différentes, il devrait écrire à l'auteur pour demander son autorisation. Pour un logiciel soumis à droit d'auteur par la Free Software Foundation, il devra écrire à la Free Software Foundation ; nous faisons quelquefois des exceptions à cette règle. Notre décision va être guidée par le double objectif de protéger le statut libre de tous les dérivés de nos logiciels libres, et de favoriser le partage et la réutilisation des logiciels en général.
ABSENCE DE GARANTIE

12. COMME LA LICENCE DU PROGRAMME EST CONCÉDÉE À TITRE GRATUIT, IL N'Y AUCUNE GARANTIE S'APPLIQUANT AU PROGRAMME, DANS LA MESURE AUTORISÉE PAR LA LOI EN VIGUEUR. SAUF MENTION CONTRAIRE ÉCRITE, LES DÉTENTEURS DU DROIT D'AUTEUR ET/OU LES AUTRES PARTIES METTENT LE PROGRAMME À DISPOSITION « EN L'ÉTAT », SANS AUCUNE GARANTIE DE QUELQUE NATURE QUE CE SOIT, EXPRESSE OU IMPLICITE, Y COMPRIS, MAIS SANS LIMITATION, LES GARANTIES IMPLICITES DE COMMERCIALISATION ET DE L'APTITUDE À UN OBJET PARTICULIER. C'EST LE CONCESSIONNAIRE QUI PREND LA TOTALITÉ DU RISQUE QUANT A LA QUALITÉ ET AUX PERFORMANCES DU PROGRAMME. SI LE PROGRAMME SE RÉVÉLAIT DÉFECTUEUX, C'EST LE CONCESSIONNAIRE QUI PRENDRAIT À SA CHARGE LE COUT DE L'ENSEMBLE DES OPÉRATIONS NÉCESSAIRES D'ENTRETIEN, RÉPARATION OU CORRECTION.

13. EN AUCUN CAS, SAUF SI LA LOI EN VIGUEUR L'EXIGE OU SI UNE CONVENTION ÉCRITE EXISTE À CE SUJET, AUCUN DÉTENTEUR DE DROITS D'AUTEUR, OU AUCUNE PARTIE AYANT LE POUVOIR DE MODIFIER ET/OU DE REDISTRIBUER LE PROGRAMME CONFORMÉMENT AUX AUTORISATIONS CI-DESSUS, N'EST RESPONSABLE VIS-A-VIS DU CONCESSIONNAIRE POUR CE QUI EST DES DOMMAGES, Y COMPRIS TOUS DOMMAGES GÉNÉRAUX, SPÉCIAUX, ACCIDENTELS OU INDIRECTS, RÉSULTANT DE L'UTILISATION OU DU PROGRAMME OU DE L'IMPOSSIBILITÉ D'UTILISER LE PROGRAMME (Y COMPRIS, MAIS SANS LIMITATION, LA PERTE DE DONNÉES, OU LE FAIT QUE DES DONNÉES SONT RENDUES IMPRÉCISES, OU ENCORE LES PERTES ÉPROUVÉES PAR LE CONCESSIONNAIRE OU PAR DES TIERS, OU ENCORE UN MANQUEMENT DU PROGRAMME À FONCTIONNER AVEC TOUS AUTRES PROGRAMMES), MÊME SI CE DÉTENTEUR OU CETTE AUTRE PARTIE A ÉTÉ AVISÉ DE LA POSSIBILITÉ DE TELS DOMMAGES.

FIN DES CONDITIONS D'EXPLOITATION

Comment appliquer ces dispositions à vos nouveaux programmes ?

Si le concessionnaire développe un nouveau programme, et s'il en souhaite l'utilisation la plus large possible dans le public, le meilleur moyen d'y arriver est d'en faire un logiciel libre, que tout le monde pourra redistribuer et modifier au titre des présentes dispositions. Dans ce but, il convient de rattacher au programme les avis suivants. Le moyen le plus sûr consiste à les rattacher au début de chaque fichier source, pour avertir le plus efficacement possible de l'exclusion de garantie ; et chaque fichier doit comporter au moins la ligne « copyright », et un pointeur indiquant où est localisée la totalité de l'avis.

Une ligne pour donner le nom du programme et une idée de ce qu'il fait.
Copyright (C) yyyy  nom de l'auteur

Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le
modifier conformément aux dispositions de la Licence Publique Générale GNU,
telle que publiée par la Free Software Foundation ; version 2 de la licence, ou
encore (à votre choix) toute version ultérieure.

Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE
GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION
À UN OBJET PARTICULIER. Pour plus de détails, voir la Licence Publique Générale
GNU.

Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même
temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software
Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, États-Unis.

Ajoutez aussi des informations sur le moyen permettant d'entrer en contact avec vous par courrier électronique (e-mail) et courrier normal.

Si le programme est interactif, prévoyez en sortie un court avis, tel que celui qui est présenté ci-dessous, lors du démarrage en mode interactif.

Gnomovision version 69, Copyright (C) yyyy nom de l'auteur

Gnomovision est livré absolument SANS AUCUNE GARANTIE ; pour plus de détails,
tapez 'show w'. Il s'agit d'un logiciel libre, et vous avez le droit de le
redistribuer dans certaines conditions ; pour plus de détails, tapez 'show c'.

Les instructions hypothétiques 'show w' et 'show c' doivent présenter les parties appropriées de la Licence Publique Générale. Bien évidemment, les instructions que vous utilisez peuvent porter d'autres noms que 'show w' et 'show c' ; elles peuvent même correspondre à des clics de souris ou à des éléments d'un menu, selon ce qui convient à votre programme.

Si nécessaire, vous devrez aussi demander à votre employeur (si vous travaillez en tant que programmeur) ou à votre éventuelle école ou université, de signer une « renonciation à droits d'auteur » concernant le programme. En voici un échantillon (il suffit de modifier les noms) :

Yoyodyne, Inc., par la présente, renonce à tout intérêt de droits d'auteur dans
le programme 'Gnomovision' (qui fait des passages au niveau des compilateurs)
écrit par James Hacker.

signature de Ty Coon, 1er avril 1989

Ty Coon, President of Vice

La présente Licence Publique Générale n'autorise pas le concessionnaire à incorporer son programme dans des programmes propriétaires. Si votre programme est une bibliothèque de sous-programmes, vous pouvez considérer comme plus intéressant d'autoriser une édition de liens des applications propriétaires avec la bibliothèque. Si c'est ce que vous souhaitez, vous devrez utiliser non pas la présente licence, mais la Licence Publique Générale pour Bibliothèques GNU.

Sauf mention contraire indiquée plus haut, le présent document est soumis aux conditions d'exploitation suivantes :

Copyright 2001 APRIL

Ce document peut être reproduit par n'importe quel moyen que ce soit, pourvu qu'aucune modification ne soit effectuée et que cette notice soit préservée.

35 - Exception de licence MySQL FLOSS

Traduction libre du texte original. Le traducteur prévient le lecteur que l'utilisation de cette version se fait à ses risques et périls. La version anglaise est disponible dans la documentation MySQL originale.

Version 0.2, juillet 2004.

L'exception MySQL AB pour les applications Free/Libre et Open Source qui utilisent les bibliothèques clientes MySQL (l'« Exception FLOSS »).

Objectif de l'exception

Nous voulons que certaines applications Free/Libre et Open Source (« FLOSS ») soient autorisées à utiliser les bibliothèques clientes GPL de MySQL (le « Programme ») malgré le fait que les licences FLOSS soient incompatibles avec la version 2 de la Licence GNU General Public (la « GPL »).

Conditions légales

En exception aux conditions de la version 2.0 de la GPL :

1. Vous êtes libres de distribuer un travail dérivé formé par le Programme et d'un ou plusieurs travaux (chacun, un « Projet FLOSS »), sous l'une ou plusieurs des licences listées ci-dessous, dans la section 1, tant que :
si les conditions ci-dessus ne sont pas satisfaites, alors le Programme peut seulement être copié, modifié, distribué ou utilisé sous les conditions de la licence GPL ou toute autre licence valide autorisée par MySQL AB.

1. le programme et les Projets FLOSS respectent les termes de la GPL sauf pour les sections identifiables du Projet FLOSS qui ne sont pas dérivées du Programme, et qui peuvent être raisonnablement considérées comme indépendantes et séparées,

2. toutes les sections identifiables du travail dérivé qui ne sont pas dérivées du Programme, et qui peuvent être raisonnablement considérées comme indépendantes et séparées en elles-mêmes,

1. sont diffusées sous l'une ou plusieurs des licences FLOSS listées ci-dessous, et

2. les codes objets ou les formes compilées de ces sections sont accompagnées par les sources complètes, traitables par une machine, sur le même médium, et sous la même licence FLOSS que le code objet ou la forme compilée correspondante, et

3. tout travail qui est combiné avec le Programme ou un travail dérivé sur un système de stockage ou un médium de distribution conformément à la licence GPL, peut être considéré raisonnablement comme des projets indépendants et séparés par eux-mêmes, et non pas des dérivés du Programme, des travaux dérivés ou du Projet FLOSS.

2. Liste des licences FLOSS

License name

Version(s)/Copyright Date

Academic Free License

2.0

Apache Software License

1.0/1.1/2.0

Apple Public Source License

2.0

Artistic license

From Perl 5.8.0

BSD license

"July 22 1999"

Common Public License

1.0

GNU Library or "Lesser" General Public License (LGPL)

2.0/2.1

Jabber Open Source License

1.0

MIT license

-

Mozilla Public License (MPL)

1.0/1.1

Open Software License

2.0

PHP License

3.0

Python license (CNRI Python License)

-

Python Software Foundation License

2.1.1

Sleepycat License

"1999"

W3C License

"2001"

X11 License

"2001"

Zlib/libpng License

-

Zope Public License

2.0

À cause des nombreuses variantes de certaines des licences ci-dessus, nous demandons que la version utilisée suive les définitions Free Software Definition version 2003 de la Free Software Foundation (http://www.gnu.org/philosophy/free-sw.html) ou la version 1.9 de la Open Source Definition de l'Open Source Initiative (http://www.opensource.org/docs/definition.php).

3. Définitions

1. Les termes utilisés mais non définis doivent être considérés dans leur définition fournie par la licence GPL.

2. Un travail dérivé est un travail dérivé, dans le cadre de la loi sur les droits d'auteurs.

4. Domaine d'application

Cette exception FLOSS s'applique à tous les Programmes qui contiennent une note placée par MySQL AB, qui indique que le Programme peut être distribué sous les termes de cette exception FLOSS. Si vous créez ou distribuez un travail qui est un travail dérivé du Programme ou d'un autre projet placé sous licence GPL, alors cette exception FLOSS n'est pas disponible pour ce travail, par conséquent, vous devez supprimer la note d'exception FLOSS de ce travail, et vous conformer à toutes les conditions de la licence GPL. Vous pouvez décider de distribuer une copie du Programme uniquement sous les conditions de la licence GPL, en supprimant l'exception FLOSS de cette copie du Programme, tant que cette copie n'a pas été modifiée, par vous-même ou une tierce partie.

36 - Index

Symboles

1. ! (logical NOT), Opérateurs logiques

2. != (not equal), Opérateurs de comparaison

3. ", Noms de bases, tables, index, colonnes et alias

4. % (modulo), Fonctions mathématiques

5. % (wildcard character), Chaînes

6. & (bitwise AND), Fonctions sur les bits

7. && (logical AND), Opérateurs logiques

8. () (parentheses), Parenthèses

9. (Control-Z) '\z', Chaînes

10. * (multiplication), Opérations arithmétiques

11. + (addition), Opérations arithmétiques

12. - (subtraction), Opérations arithmétiques

13. - (unary minus), Opérations arithmétiques

14. --password option, Garder vos mots de passe en lieu sûr

15. --with-raid link errors, Problèmes de compilation?

16. -p option, Garder vos mots de passe en lieu sûr

17. .my.cnf file, MySQL pour Windows face à MySQL pour Unix, Fichier d'options my.cnf, Se connecter au serveur MySQL, Causes des erreurs Access denied, Garder vos mots de passe en lieu sûr, Utiliser les clients dans un environnement multiserveur

18. .mysql_history file, mysql, l'outil en ligne de commande

19. .pid (process ID) file, Mettre en place un régime d'entretien de MySQL

20. / (division), Opérations arithmétiques

21. /etc/passwd, Protéger MySQL contre les attaques, Syntaxe de SELECT

22. < (less than), Opérateurs de comparaison

23. <<, Calcul du nombre de visites par jour

24. << (left shift), Fonctions sur les bits

25. <= (less than or equal), Opérateurs de comparaison

26. <=> (equal to), Opérateurs de comparaison

27. <> (not equal), Opérateurs de comparaison

28. = (equal), Opérateurs de comparaison

29. > (greater than), Opérateurs de comparaison

30. >= (greater than or equal), Opérateurs de comparaison

31. >> (right shift), Fonctions sur les bits

32. \" (double quote), Chaînes

33. \' (single quote), Chaînes

34. \0 (ASCII 0), Chaînes

35. \b (backspace), Chaînes

36. \n (linefeed), Chaînes

37. \n (newline), Chaînes

38. \r (carriage return), Chaînes

39. \t (tab), Chaînes

40. \z (Control-Z) ASCII(26), Chaînes

41. \\ (escape), Chaînes

42. ^ (bitwise XOR), Fonctions sur les bits

43. _ (wildcard character), Chaînes

44. `, Noms de bases, tables, index, colonnes et alias

45. | (bitwise OR), Fonctions sur les bits

46. || (logical OR), Opérateurs logiques

47. ~, Fonctions sur les bits

A

1. aborted clients, Erreurs de communication / Connexion annulée

2. aborted connection, Erreurs de communication / Connexion annulée

3. ABS(), Fonctions mathématiques

4. access control, Contrôle d'accès, étape 1 : Vérification de la connexion

5. access denied errors, Erreur Access denied

6. access privileges, Règles de sécurité et droits d'accès au serveur MySQL

7. Access program, Programs Known to Work With MyODBC

8. account privileges

1. adding, Ajouter de nouveaux utilisateurs à MySQL

9. accounts

1. anonymous user, Création des premiers droits MySQL

2. root, Création des premiers droits MySQL

10. ACID, Transactions et opérations atomiques, Présentation des tables InnoDB

11. ACL, Règles de sécurité et droits d'accès au serveur MySQL

12. ACOS(), Fonctions mathématiques

13. ActiveState Perl, Installer ActiveState Perl sur Windows

14. ADDDATE(), Fonctions de dates et d'heures

15. adding

1. character sets, Ajouter un nouveau jeu de caractères

2. native functions, Ajouter de nouvelles fonctions natives

3. new account privileges, Ajouter de nouveaux utilisateurs à MySQL

4. new functions, Ajouter des fonctions à MySQL

5. new user privileges, Ajouter de nouveaux utilisateurs à MySQL

6. new users, Installer MySQL sur d'autres systèmes type Linux, Installation depuis les sources : présentation

7. procedures, Ajouter une nouvelle procédure à MySQL

8. user-definable functions, Ajouter une nouvelle fonction définie par l'utilisateur (UDF)

16. addition (+), Opérations arithmétiques

17. ADDTIME(), Fonctions de dates et d'heures

18. administration

1. server, mysqladmin, administration d'un serveur MySQL

19. ADO program, Programs Known to Work With MyODBC

20. AES_DECRYPT(), Fonctions de chiffrements

21. AES_ENCRYPT(), Fonctions de chiffrements

22. age

1. calculating, Calcul sur les Dates

23. alias, Problèmes avec les alias

24. alias names

1. case sensitivity, Sensibilité à la casse pour les noms

25. aliases

1. for expressions, GROUP BY avec les champs cachés

2. for tables, Syntaxe de SELECT

3. in GROUP BY clauses, GROUP BY avec les champs cachés

4. in ORDER BY clauses, GROUP BY avec les champs cachés

5. names, Noms de bases, tables, index, colonnes et alias

6. on expressions, Syntaxe de SELECT

26. ALLOW_INVALID_DATES SQL mode, Le mode SQL du serveur

27. ALTER COLUMN, Syntaxe de ALTER TABLE

28. ALTER DATABASE, Syntaxe de ALTER DATABASE

29. ALTER FUNCTION, ALTER PROCEDURE et ALTER FUNCTION

30. ALTER PROCEDURE, ALTER PROCEDURE et ALTER FUNCTION

31. ALTER TABLE, Syntaxe de ALTER TABLE, Problèmes avec ALTER TABLE.

32. ALTER VIEW, Syntaxe ALTER VIEW

33. ANALYZE TABLE, Syntaxe de ANALYZE TABLE

34. AND

1. bitwise, Fonctions sur les bits

2. logical, Opérateurs logiques

35. anonymous user, Création des premiers droits MySQL, Contrôle d'accès, étape 1 : Vérification de la connexion, Contrôle d'accès, étape 2 : Vérification de la requête

36. ANSI mode

1. running, Exécuter MySQL en mode ANSI

37. ANSI SQL

1. differences from, Syntaxe de GRANT et REVOKE

38. ANSI SQL mode, Le mode SQL du serveur

39. ANSI_QUOTES SQL mode, Le mode SQL du serveur

40. answering questions

1. etiquette, Conseils pour répondre sur la liste de diffusion

41. Apache, Utilisation de MySQL avec Apache

42. API's

1. list of, Applications qui supportent MySQL

43. APIs, API MySQL

1. Perl, API Perl pour MySQL

44. approximate-value literals, Mathématiques de précision

45. ARCHIVE storage engine, Le moteur de table ARCHIVE

46. ARCHIVE table type, Le moteur de table ARCHIVE

47. Area(), Fonctions d'analyse des lignes Polygon, Fonctions d'analyse des lignes MultiPolygon

48. argument processing, Traitement des arguments

49. arithmetic expressions, Opérations arithmétiques

50. arithmetic functions, Fonctions sur les bits

51. AS, Syntaxe de SELECT, Syntaxe de JOIN

52. AsBinary(), Fonctions pour convertir les formes de format

53. ASCII(), Fonctions de chaînes de caractères

54. ASIN(), Fonctions mathématiques

55. AsText(), Fonctions pour convertir les formes de format

56. ATAN(), Fonctions mathématiques

57. ATAN2(), Fonctions mathématiques

58. attackers

1. security against, Protéger MySQL contre les attaques

59. AUTO-INCREMENT

1. ODBC, Comment obtenir la valeur d'une colonne AUTO_INCREMENT avec ODBC

60. AUTO_INCREMENT, Utiliser AUTO_INCREMENT

1. and NULL values, Problèmes avec les valeurs NULL

61. AVG(), Fonctions avec GROUP BY

B

1. backing up

1. databases, mysqldump, sauvegarde des structures de tables et les données, mysqlhotcopy, copier les bases et tables MySQL

2. backslash

1. escape character, Littéraux : comment écrire les chaînes et les nombres

3. backspace (\b), Chaînes

4. BACKUP TABLE, Syntaxe de BACKUP TABLE

5. backups, Sauvegardes de base de données

1. database, Syntaxe de BACKUP TABLE

6. batch

1. mysql option, mysql, l'outil en ligne de commande

7. batch mode, Utilisation de mysql en mode batch

8. BDB storage engine, Moteurs de tables MySQL et types de table, Tables BDB ou BerkeleyDB

9. BDB table type, Moteurs de tables MySQL et types de table, Tables BDB ou BerkeleyDB

10. BDB tables, Transactions et opérations atomiques

11. BdMPolyFromText(), Créer des objets géométriques avec les fonctions WKT

12. BdMPolyFromWKB(), Créer des objets géométriques avec les fonctions WKB

13. BdPolyFromText(), Créer des objets géométriques avec les fonctions WKT

14. BdPolyFromWKB(), Créer des objets géométriques avec les fonctions WKB

15. BEGIN, Syntaxes de START TRANSACTION, COMMIT et ROLLBACK, La commande composée BEGIN ... END

16. benchmark suite, La suite de tests MySQL

17. BENCHMARK(), Fonctions d'informations

18. benchmarks, Utiliser vos propres tests de performance

19. BerkeleyDB storage engine, Moteurs de tables MySQL et types de table, Tables BDB ou BerkeleyDB

20. BerkeleyDB table type, Moteurs de tables MySQL et types de table, Tables BDB ou BerkeleyDB

21. BETWEEN ... AND, Opérateurs de comparaison

22. Big5 Chinese character encoding, Sensibilité à la casse dans les recherches

23. BIGINT, Présentation des types numériques of Numeric Types

24. BIN(), Fonctions de chaînes de caractères

25. BINARY data type, Les types BINARY and VARBINARY

26. binary distributions, Binaires compilés par MySQL AB

1. installing, Installer MySQL sur d'autres systèmes type Linux

2. on Linux, Notes relatives à Linux pour les distributions binaires

27. binary log, Le log binaire

28. BIT, Présentation des types numériques of Numeric Types

29. bit functions, Fonctions sur les bits

30. BitKeeper tree, Installer à partir de l'arbre source de développement

31. BIT_AND(), Fonctions avec GROUP BY

32. BIT_COUNT, Calcul du nombre de visites par jour

33. BIT_COUNT(), Fonctions sur les bits

34. bit_functions

1. example, Calcul du nombre de visites par jour

35. BIT_LENGTH(), Fonctions de chaînes de caractères

36. BIT_OR, Calcul du nombre de visites par jour

37. BIT_OR(), Fonctions avec GROUP BY

38. BIT_XOR(), Fonctions avec GROUP BY

39. BLOB, Présentation des types de chaînes, Les types BLOB et TEXT

1. inserting binary data, Chaînes

2. size, Capacités des colonnes

40. BLOB columns

1. default values, Les types BLOB et TEXT

2. indexing, Index de colonnes, Syntaxe de CREATE TABLE

41. blocking_queries

1. mysqlcc option, mysqlcc, MySQL Control Center

42. BOOL, Présentation des types numériques of Numeric Types

43. BOOLEAN, Présentation des types numériques of Numeric Types

44. Borland Builder 4 program, Programs Known to Work With MyODBC

45. Borland C++ compiler, Borland C++

46. Boundary(), Fonctions générales d'analyse géométrique

47. brackets

1. square, Types de colonnes

48. buffer sizes

1. client, API MySQL

49. Buffer(), Opérateurs géométriques

50. bug reports

1. criteria for, Comment rapporter un bogue ou un problème

51. bugs

1. known, Erreurs connues, et limitations de MySQL

2. reporting, Comment rapporter un bogue ou un problème

52. bugs database, Comment rapporter un bogue ou un problème

53. bugs.mysql.com, Comment rapporter un bogue ou un problème

54. building

1. client programs, Compiler les clients

C

1. C API

1. datatypes, API MySQL C

2. functions, Vue d'ensemble des fonctions de l'API C

3. linking problems, Problèmes lors de la liaison avec l'API C

2. C Prepared statements API

1. functions, Présentation des fonctions de l'interface C

3. C++ API, Interface MySQL C++

4. C++ Builder, Programs Known to Work With MyODBC

5. C++ compiler

1. gcc, Options habituelles de configure

6. C++ compiler cannot create executables, Problèmes de compilation?

7. C:\my.cnf file, Utiliser les clients dans un environnement multiserveur

8. CACHE INDEX, Syntaxe de CACHE INDEX

9. caches

1. clearing, Syntaxe de FLUSH

10. calculating

1. dates, Calcul sur les Dates

11. CALL, CALL

12. calling sequences for aggregate functions

1. UDF, Appeler des fonctions utilisateur pour les groupements

13. calling sequences for simple functions

1. UDF, Fonctions utilisateur : appeler des fonctions simples

14. can't create/write to file, Erreur Can't create/write to file

15. carriage return (\r), Chaînes

16. CASE, Les fonctions de contrôle, Commande CASE

17. case sensitivity

1. in identifiers, Sensibilité à la casse pour les noms

2. in names, Sensibilité à la casse pour les noms

3. in string comparisons, Opérateurs de comparaison pour les chaînes de caractères

18. case-sensitivity

1. in access checking, Comment fonctionne le système de droits

2. in searches, Sensibilité à la casse dans les recherches

3. of database names, Extensions MySQL au standard SQL-92

4. of table names, Extensions MySQL au standard SQL-92

19. CAST, Fonctions de transtypage

20. casts, Opérateurs de comparaison

21. CC environment variable, Options habituelles de configure, Problèmes de compilation?, Variables d'environnement

22. cc1plus problems, Problèmes de compilation?

23. CCX environment variable, Variables d'environnement

24. CEILING(), Fonctions mathématiques

25. Centroid(), Fonctions d'analyse des lignes MultiPolygon

26. CFLAGS environment variable, Options habituelles de configure, Problèmes de compilation?, Variables d'environnement

27. CHANGE MASTER TO, CHANGE MASTER TO

28. ChangeLog, Historique des changements MySQL

29. changes

1. log, Historique des changements MySQL

2. version 3.19, Changements de la version 3.19.x

3. version 3.20, Changements de la version 3.20.x

4. version 3.21, Changements de la version 3.21.x

5. version 3.22, Changements de la version 3.22.x (Old; discontinued)

6. version 3.23, Changements de la version 3.23.x (Recent; still supported)

7. version 4.0, Changements de la version 4.0.x (Production)

8. version 4.1, Changements de la version 4.1.x (Alpha)

9. version 5.0, Changements de la version 5.0.0 (Développement)

30. changes to privileges, Contrôle d'accès, étape 2 : Vérification de la requête

31. changing

1. column, Syntaxe de ALTER TABLE

2. column order, Comment changer l'ordre des colonnes dans une table

3. database, Syntaxe de ALTER DATABASE

4. field, Syntaxe de ALTER TABLE

5. table, Syntaxe de ALTER TABLE, Problèmes avec ALTER TABLE.

32. changing socket location, Options habituelles de configure, Lancer et arrêter MySQL automatiquement, Comment protéger ou changer le fichier socket /tmp/mysql.sock

33. CHAR, Présentation des types de chaînes

34. CHAR data type, Les types chaînes

35. CHAR VARYING, Présentation des types de chaînes

36. CHAR(), Fonctions de chaînes de caractères

37. CHARACTER, Présentation des types de chaînes

38. character sets, Options habituelles de configure, Le jeu de caractères utilisé pour les données et le stockage

1. adding, Ajouter un nouveau jeu de caractères

39. Character sets, Jeux de caractères et Unicode

40. CHARACTER VARYING, Présentation des types de chaînes

41. character-sets-dir

1. mysql option, mysql, l'outil en ligne de commande

42. characters

1. multi-byte, Support des caractères multi-octets

43. CHARACTER_LENGTH(), Fonctions de chaînes de caractères

44. CHARACTER_SETS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA CHARACTER_SETS

45. CHARSET(), Fonctions d'informations

46. CHAR_LENGTH(), Fonctions de chaînes de caractères

47. check options

1. myisamchk, Options de vérifications pour myisamchk

48. CHECK TABLE, Syntaxe de CHECK TABLE

49. checking

1. tables for errors, Comment vérifier la cohérence d'une table

50. checksum errors, Notes pour Solaris

51. CHECKSUM TABLE, Syntaxe de CHECKSUM TABLE

52. Chinese, Sensibilité à la casse dans les recherches

53. choosing

1. a MySQL version, Choisir votre version de MySQL

54. choosing types, Choisir le bon type de colonne

55. clearing

1. caches, Syntaxe de FLUSH

56. clefs, Index de colonnes

1. multi-colonnes, Index sur plusieurs colonnes

57. client programs

1. building, Compiler les clients

58. client tools, API MySQL

59. clients

1. de MySQL, Pour quoi avons nous utilisé MySQL ?

2. debugging, Débogage un client MySQL

3. threaded, Comment faire un client MySQL threadé

60. CLOSE, Commande de curseur CLOSE

61. closing

1. tables, Quand MySQL ouvre et ferme les tables

62. COALESCE(), Opérateurs de comparaison

63. COERCIBILITY(), Fonctions d'informations

64. ColdFusion program, Programs Known to Work With MyODBC

65. collating

1. strings, Support d'assemblage des chaînes

66. COLLATION(), Fonctions d'informations

67. COLLATIONS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA COLLATIONS

68. COLLATION_CHARACTER_SET_APPLICABILITY

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY

69. colonnes

1. index, Index de colonnes

70. column

1. changing, Syntaxe de ALTER TABLE

71. column comments, Syntaxe de CREATE TABLE

72. column names

1. case sensitivity, Sensibilité à la casse pour les noms

73. columns

1. changing, Comment changer l'ordre des colonnes dans une table

2. displaying, Afficher les bases, tables et colonnes

3. names, Noms de bases, tables, index, colonnes et alias

4. other types, Utilisation des types de données issues d'autres SGBDR

5. selecting, Sélectionner des colonnes particulières

6. storage requirements, Capacités des colonnes

7. types, Types de colonnes

74. COLUMNS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA COLUMNS

75. COLUMN_PRIVILEGES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA COLUMN_PRIVILEGES

76. command syntax, Conventions utilisées dans ce manuel

77. command-line history

1. mysql, mysql, l'outil en ligne de commande

78. command-line options, Options de ligne de commande de mysqld

1. mysql, mysql, l'outil en ligne de commande

2. mysqladmin, mysqladmin, administration d'un serveur MySQL

3. mysqlcc, mysqlcc, MySQL Control Center

79. command-line tool, mysql, l'outil en ligne de commande

80. commands

1. for binary distribution, Installer MySQL sur d'autres systèmes type Linux

2. replication masters, Requêtes SQL pour contrôler les maîtres de réplication

3. replication slaves, Commandes SQL de contrôle des esclaves de réplication

81. commands out of sync, Erreur du client Commands out of sync

82. Comment syntax, Syntaxe des commentaires

83. comments

1. adding, Syntaxe des commentaires

2. starting, '--' comme début de commentaire

84. COMMIT, Transactions et opérations atomiques, Syntaxes de START TRANSACTION, COMMIT et ROLLBACK

85. comparison operators, Opérateurs de comparaison

86. compatibility

1. between MySQL versions, Passer en de version 4.1 en version 5.0, Passer de la version 4.0 à la version 4.1, Passer de la version 3.23 à la version 4.0, Passer de la version 3.22 à la version 3.23, Passer de la version 3.21 à la version 3.22

2. with mSQL, Opérateurs de comparaison pour les chaînes de caractères

3. with ODBC, Identifiants, Présentation des types numériques of Numeric Types, Opérateurs de comparaison, Syntaxe de JOIN, Syntaxe de CREATE TABLE, Changements de la version 3.21.15

4. with Oracle, Extensions MySQL au standard SQL-92, Fonctions avec GROUP BY, Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

5. with PostgreSQL, Extensions MySQL au standard SQL-92

6. with standard SQL, Quels standards respectent MySQL ?

7. with Sybase, Syntaxe de USE

87. compilation

1. optimisation, Réglage du système, au moment de la compilation, et paramètres du démarrage

88. compiler

1. C++ gcc, Options habituelles de configure

89. compiling

1. on Windows, Compiler les clients MySQL sous Windows

2. problems, Problèmes de compilation?

3. speed, Influences de la compilation et des liaisons sur la vitesse de MySQL

4. statically, Options habituelles de configure

5. user-defined functions, Compiler et installer des fonctions utilisateurs

90. compliance

1. Y2K, Compatibilité an 2000

91. compress

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

92. COMPRESS(), Fonctions de chaînes de caractères

93. compressed tables, myisampack, le générateur de tables MySQL compressées en lecture seule, Caractéristiques des tables compressées

94. CONCAT(), Fonctions de chaînes de caractères

95. CONCAT_WS(), Fonctions de chaînes de caractères

96. concurrent inserts, Méthodes de verrouillage

97. Conditions, DECLARE une condition

98. config-file

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

99. config.cache, Problèmes de compilation ?

100. config.cache file, Problèmes de compilation ?

101. configuration files, Causes des erreurs Access denied

102. configuration options, Options habituelles de configure

103. configure

1. running after prior invocation, Problèmes de compilation ?

104. configure option

1. --with-charset, Options habituelles de configure

2. --with-collation, Options habituelles de configure

3. --with-extra-charsets, Options habituelles de configure

4. --with-low-memory, Problèmes de compilation ?

105. configure script, Options habituelles de configure

106. connecting

1. remotely with SSH, Connexion à MySQL à distance avec Windows et SSH

2. to the server, Connexion et déconnexion au serveur, Se connecter au serveur MySQL

3. verification, Contrôle d'accès, étape 1 : Vérification de la connexion

107. connection

1. aborted, Erreurs de communication / Connexion annulée

108. CONNECTION_ID(), Fonctions d'informations

109. connection_name

1. mysqlcc option, mysqlcc, MySQL Control Center

110. Connector/J, MySQL et Java (JDBC)

111. Connector/JDBC, Pilotes MySQL

112. Connector/ODBC, Pilotes MySQL, Support ODBC de MySQL

113. Connectors

1. MySQL, Pilotes MySQL

114. connect_timeout variable, mysql, l'outil en ligne de commande, mysqladmin, administration d'un serveur MySQL, mysqlcc, MySQL Control Center

115. constant table, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT), Comment MySQL optimise les clauses WHERE

116. constraints, Comment MySQL gère les contraintes

117. CONSTRAINTS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA TABLE_CONSTRAINTS

118. Contains(), Fonctions qui testent les relations géométriques entre les formes

119. contributing companies

1. list of, Supporters de MySQL

120. contributors

1. list of, Contributeurs à MySQL

121. control access, Contrôle d'accès, étape 1 : Vérification de la connexion

122. control flow functions, Les fonctions de contrôle

123. CONV(), Fonctions de chaînes de caractères

124. conventions

1. typographical, Conventions utilisées dans ce manuel

125. CONVERT, Fonctions de transtypage

126. CONVERT TO, Syntaxe de ALTER TABLE

127. ConvexHull(), Opérateurs géométriques

128. copying databases, Migrer depuis une autre architecture

129. copying tables, Syntaxe de CREATE TABLE

130. COS(), Fonctions mathématiques

131. COT(), Fonctions mathématiques

132. COUNT(), Fonctions avec GROUP BY

133. COUNT(DISTINCT), Fonctions avec GROUP BY

134. counting

1. table rows, Compter les lignes

135. crash, Déboguer un serveur MySQL

1. recovery, Utiliser myisamchk pour restaurer une table

2. repeated, Que faire si MySQL plante constamment ?

136. crash-me, La suite de tests MySQL

137. crash-me program, Portabilité, La suite de tests MySQL

138. CRC32(), Fonctions mathématiques

139. CREATE DATABASE, Syntaxe de CREATE DATABASE

140. CREATE FUNCTION, CREATE PROCEDURE et CREATE FUNCTION, Syntaxe de CREATE FUNCTION/DROP FUNCTION

141. CREATE INDEX, Syntaxe de CREATE INDEX

142. CREATE PROCEDURE, CREATE PROCEDURE et CREATE FUNCTION

143. CREATE TABLE, Syntaxe de CREATE TABLE

144. CREATE USER, Syntaxe de CREATE USER

145. CREATE VIEW, Syntaxe de CREATE VIEW

146. creating

1. bug reports, Comment rapporter un bogue ou un problème

2. databases, Création et utilisation d'une base de données

3. default startup options, Fichier d'options my.cnf

4. tables, Création d'une table

147. creating user accounts, Syntaxe de CREATE USER

148. CROSS JOIN, Syntaxe de JOIN

149. Crosses(), Fonctions qui testent les relations géométriques entre les formes

150. CSV storage engine, Le moteur CSV

151. CSV table type, Le moteur CSV

152. CURDATE(), Fonctions de dates et d'heures

153. CURRENT_DATE, Fonctions de dates et d'heures

154. CURRENT_TIME, Fonctions de dates et d'heures

155. CURRENT_TIMESTAMP, Fonctions de dates et d'heures

156. CURRENT_USER(), Fonctions d'informations

157. Cursors, Curseurs

158. CURTIME(), Fonctions de dates et d'heures

159. customer support

1. mailing address, Comment rapporter un bogue ou un problème

160. CVS tree, Installer à partir de l'arbre source de développement

161. CXX environment variable, Options habituelles de configure, Problèmes de compilation ?

162. CXXFLAGS environment variable, Options habituelles de configure, Problèmes de compilation ?, Variables d'environnement

D

1. data

1. character sets, Le jeu de caractères utilisé pour les données et le stockage

2. importing, mysqlimport, importer des données depuis des fichiers texte

3. loading into tables, Charger des données dans une table

4. retrieving, Récupérer des informations à partir d'une table

5. size, Rendre vos tables aussi compactes que possible

2. data type

1. BINARY, Les types BINARY and VARBINARY

2. CHAR, Les types de chaînes

3. DECIMAL, Mathématiques de précision

4. VARBINARY, Les types BINARY and VARBINARY

5. VARCHAR, Les types de chaînes

3. data types, Types de colonnes

4. database

1. changing, Syntaxe de ALTER DATABASE

2. deleting, Syntaxe de DROP DATABASE

3. mysql option, mysql, l'outil en ligne de commande

4. mysqlcc option, mysqlcc, MySQL Control Center

5. database design, Conception

6. Database information

1. obtaining, Syntaxe de SHOW

7. database metadata, La base de données d'informations INFORMATION_SCHEMA

8. database names

1. case sensitivity, Sensibilité à la casse pour les noms

2. case-sensitivity, Extensions MySQL au standard SQL-92

9. DATABASE(), Fonctions d'informations

10. databases

1. backups, Sauvegardes de base de données

2. copying, Migrer depuis une autre architecture

3. creating, Création et utilisation d'une base de données

4. defined, Présentation du système de bases de données MySQL

5. displaying, Afficher les bases, tables et colonnes

6. dumping, mysqldump, sauvegarde des structures de tables et les données, mysqlhotcopy, copier les bases et tables MySQL

7. information about, Obtenir des informations à propos des bases de données et des tables

8. names, Noms de bases, tables, index, colonnes et alias

9. replicating, Réplication de MySQL

10. selecting, Créer et sélectionner une base de données

11. symbolic links, Utiliser les liens symboliques pour les bases

12. using, Création et utilisation d'une base de données

11. DataJunction, Programs Known to Work With MyODBC

12. datatypes

1. C API, API MySQL C

13. DATE, Présentation des types de données temporels : dates et heures, Les types DATETIME, DATE, et TIMESTAMP, Problèmes avec l'utilisation des colonnes DATE

14. date and time functions, Fonctions de dates et d'heures

15. Date and Time types, Les types date et heure

16. date calculations, Calcul sur les Dates

17. DATE columns

1. problems, Problèmes avec l'utilisation des colonnes DATE

18. date functions

1. Y2K compliance, Compatibilité an 2000

19. date types, Capacités des colonnes

1. Y2K issues, An 2000 et les types date

20. date values

1. problems, Les types DATETIME, DATE, et TIMESTAMP

21. DATE(), Fonctions de dates et d'heures

22. DATEDIFF(), Fonctions de dates et d'heures

23. DATETIME, Présentation des types de données temporels : dates et heures, Les types DATETIME, DATE, et TIMESTAMP

24. DATE_ADD(), Fonctions de dates et d'heures

25. DATE_FORMAT(), Fonctions de dates et d'heures

26. DATE_SUB(), Fonctions de dates et d'heures

27. DAY(), Fonctions de dates et d'heures

28. DAYNAME(), Fonctions de dates et d'heures

29. DAYOFMONTH(), Fonctions de dates et d'heures

30. DAYOFWEEK(), Fonctions de dates et d'heures

31. DAYOFYEAR(), Fonctions de dates et d'heures

32. db table

1. sorting, Contrôle d'accès, étape 2 : Vérification de la requête

33. DB2 SQL mode, Le mode SQL du serveur

34. DBI interface, API Perl pour MySQL

35. DBI->quote, Chaînes

36. DBI->trace, Déboguer mysqld sous gdb

37. DBI/DBD interface, API Perl pour MySQL

38. DBI_TRACE environment variable, Déboguer mysqld sous gdb, Variables d'environnement

39. DBI_USER environment variable, Variables d'environnement

40. DBUG package, Le paquet DBUG

41. DEALLOCATE PREPARE, Syntaxe SQL pour les commandes préparées

42. debug

1. mysql option, mysql, l'outil en ligne de commande

43. debug-info

1. mysql option, mysql, l'outil en ligne de commande

44. debugging

1. client, Débogage un client MySQL

2. server, Déboguer un serveur MySQL

45. DEC, Présentation des types numériques of Numeric Types

46. DECIMAL, Présentation des types numériques of Numeric Types

47. decimal arithmetic, Mathématiques de précision

48. DECIMAL data type, Mathématiques de précision

49. decimal point, Types de colonnes

50. DECLARE, La commande DECLARE

51. DECODE(), Fonctions de chiffrements

52. decode_bits myisamchk variable, Options générales de myisamchk

53. default

1. privileges, Création des premiers droits MySQL

54. default hostname, Se connecter au serveur MySQL

55. default installation location, Dispositions d'installation

56. default options, Fichier d'options my.cnf

57. default values, Syntaxe de CREATE TABLE

1. BLOB and TEXT columns, Les types BLOB et TEXT

2. suppression, Contraintes sur les valeurs invalides

58. default-character-set

1. mysql option, mysql, l'outil en ligne de commande

59. defaults

1. embedded, Utilisation de fichiers d'options avec le serveur embarqué

60. DEGREES(), Fonctions mathématiques

61. DELAYED, Syntaxe de INSERT DELAYED

62. delayed_insert_limit, Syntaxe de INSERT DELAYED

63. DELETE, Syntaxe de DELETE

64. deleting

1. database, Syntaxe de DROP DATABASE

2. foreign key, Syntaxe de ALTER TABLE, Contraintes de clés étrangères FOREIGN KEY

3. function, Syntaxe de CREATE FUNCTION/DROP FUNCTION

4. index, Syntaxe de ALTER TABLE, Syntaxe de DROP INDEX

5. primary key, Syntaxe de ALTER TABLE

6. rows, Effacer des lignes de tables reliées

7. table, Syntaxe de DROP TABLE

8. user, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

9. users, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

65. deletion

1. mysql.sock, Comment protéger ou changer le fichier socket /tmp/mysql.sock

66. Delphi program, Programs Known to Work With MyODBC

67. derived tables, Sous-requêtes dans la clause FROM

68. DESC, Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

69. DESCRIBE, Obtenir des informations à propos des bases de données et des tables, Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

70. design

1. choices, Conception

2. issues, Erreurs connues, et limitations de MySQL

3. limitations, Limitations et inconvénients des choix conceptuels de MySQL

71. DES_DECRYPT(), Fonctions de chiffrements

72. DES_ENCRYPT(), Fonctions de chiffrements

73. developers

1. list of, Crédits

74. development source tree, Installer à partir de l'arbre source de développement

75. Difference(), Opérateurs géométriques

76. digits, Types de colonnes

77. Dimension(), Fonctions générales d'analyse géométrique

78. directory structure

1. default, Dispositions d'installation

79. DISCARD TABLESPACE, Syntaxe de ALTER TABLE, Espaces de tables multiples : chaque table InnoDB a son fichier .ibd

80. disconnecting

1. from the server, Connexion et déconnexion au serveur

81. Disjoint(), Fonctions qui testent les relations géométriques entre les formes

82. disk full, Comment MySQL gère un disque plein

83. disk issues, Problèmes avec les disques

84. disks

1. splitting data across, Utiliser des liens symboliques pour les bases de données sous Windows

85. display size, Types de colonnes

86. displaying

1. database information, Afficher les bases, tables et colonnes

2. information

1. SHOW, Syntaxe de SHOW COLUMNS, Syntaxe de SHOW INDEX, Syntaxe de SHOW TABLES

3. table status, SHOW TABLE STATUS

87. Distance(), Fonctions qui testent les relations géométriques entre les formes

88. DISTINCT, Sélectionner des colonnes particulières, Comment MySQL optimise DISTINCT, Fonctions avec GROUP BY

89. DIV, Opérations arithmétiques

90. division (/), Opérations arithmétiques

91. DNS, Comment MySQL utilise le DNS

92. DO, Syntaxe de DO

93. Documenters

1. list of, Documenteurs et traducteurs

94. DOUBLE, Présentation des types numériques of Numeric Types

95. DOUBLE PRECISION, Présentation des types numériques of Numeric Types

96. double quote (\"), Chaînes

97. downgrading, Changer de version de MySQL, Réduire de version de MySQL

98. downloading, Comment obtenir MySQL ?

99. DROP DATABASE, Syntaxe de DROP DATABASE

100. DROP FOREIGN KEY, Syntaxe de ALTER TABLE, Contraintes de clés étrangères FOREIGN KEY

101. DROP FUNCTION, DROP PROCEDURE et DROP FUNCTION, Syntaxe de CREATE FUNCTION/DROP FUNCTION

102. DROP INDEX, Syntaxe de ALTER TABLE, Syntaxe de DROP INDEX

103. DROP PRIMARY KEY, Syntaxe de ALTER TABLE

104. DROP PROCEDURE, DROP PROCEDURE et DROP FUNCTION

105. DROP TABLE, Syntaxe de DROP TABLE

106. DROP USER, Effacer des utilisateurs MySQL

107. DROP VIEW, Syntaxe DROP VIEW

108. dropping

1. user, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

109. DUMPFILE, Syntaxe de SELECT

110. dumping

1. databases, mysqldump, sauvegarde des structures de tables et les données, mysqlhotcopy, copier les bases et tables MySQL

111. dynamic table characteristics, Caractéristiques des tables à format de ligne dynamique

E

1. e-mail lists, Les listes de diffusion de MySQL

2. Eiffel Wrapper, Couche MySQL pour Eiffel

3. ELT(), Fonctions de chaînes de caractères

4. embedded MySQL server library, libmysqld, la bibliothèque du serveur embarqué MySQL

5. ENCODE(), Fonctions de chiffrements

6. ENCRYPT(), Fonctions de chiffrements

7. encryption functions, Fonctions de chiffrements

8. END, La commande composée BEGIN ... END

9. EndPoint(), Fonctions d'analyse des lignes LineString

10. entering

1. queries, Entrer des requêtes

11. ENUM, Présentation des types de chaînes, Le type ENUM

1. size, Capacités des colonnes

12. Envelope(), Fonctions générales d'analyse géométrique

13. environment variable

1. CC, Options habituelles de configure, Problèmes de compilation ?

2. CFLAGS, Options habituelles de configure, Problèmes de compilation ?

3. CXX, Options habituelles de configure, Problèmes de compilation ?

4. CXXFLAGS, Options habituelles de configure, Problèmes de compilation ?

5. HOME, mysql, l'outil en ligne de commande

6. LD_RUN_PATH, Notes sur la distribution source de Linux

7. MYSQL_DEBUG, Présentation des scripts serveur et utilitaires

8. MYSQL_HISTFILE, mysql, l'outil en ligne de commande

9. MYSQL_HOST, Se connecter au serveur MySQL

10. MYSQL_PWD, Se connecter au serveur MySQL, Présentation des scripts serveur et utilitaires

11. MYSQL_TCP_PORT, Utiliser plusieurs serveurs sous Unix, Utiliser les clients dans un environnement multiserveur, Présentation des scripts serveur et utilitaires

12. MYSQL_UNIX_PORT, Utiliser plusieurs serveurs sous Unix, Utiliser les clients dans un environnement multiserveur, Présentation des scripts serveur et utilitaires

13. PATH, Installer MySQL sur d'autres systèmes type Linux

14. USER, Se connecter au serveur MySQL

14. Environment variable

1. CC, Variables d'environnement

2. CCX, Variables d'environnement

3. CFLAGS, Variables d'environnement

4. CXX, Problèmes de compilation ?

5. CXXFLAGS, Variables d'environnement

6. DBI_TRACE, Déboguer mysqld sous gdb, Variables d'environnement

7. DBI_USER, Variables d'environnement

8. HOME, Variables d'environnement

9. LD_LIBRARY_PATH, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

10. LD_RUN_PATH, Notes pour Solaris, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD, Variables d'environnement

11. MYSQL_DEBUG, Débogage un client MySQL, Variables d'environnement

12. MYSQL_HISTFILE, Variables d'environnement

13. MYSQL_HOST, Variables d'environnement

14. MYSQL_PS1, Variables d'environnement

15. MYSQL_PWD, Variables d'environnement

16. MYSQL_TCP_PORT, Variables d'environnement

17. MYSQL_UNIX_PORT, Problèmes d'exécution de mysql_install_db, Variables d'environnement

18. PATH, Variables d'environnement

19. TMPDIR, Problèmes d'exécution de mysql_install_db, Variables d'environnement

20. TZ, Problèmes de fuseaux horaires, Variables d'environnement

21. UMASK, Problèmes avec les permissions sur fichiers, Variables d'environnement

22. UMASK_DIR, Problèmes avec les permissions sur fichiers, Variables d'environnement

23. USER, Variables d'environnement

15. Environment variables

1. CXX, Problèmes de compilation ?

16. environment variables, Utiliser les variables d'environnement pour spécifier des options, Causes des erreurs Access denied, Présentation des scripts serveur et utilitaires

1. list of, Variables d'environnement

17. environment varible

1. PATH, Appeler des programmes MySQL

18. equal (=), Opérateurs de comparaison

19. Equals(), Fonctions qui testent les relations géométriques entre les formes

20. Errcode, perror, expliquer les codes d'erreurs

21. errno, perror, expliquer les codes d'erreurs

22. error mesaages

1. can't find file, Problèmes avec les permissions sur fichiers

23. error messages

1. displaying, perror, expliquer les codes d'erreurs

2. languages, Langue des messages d'erreurs

24. errors

1. access denied, Erreur Access denied

2. checking tables for, Comment vérifier la cohérence d'une table

3. common, Problèmes et erreurs communes

4. directory checksum, Notes pour Solaris

5. handling for UDFs, Valeurs de retour et gestion d'erreurs.

6. known, Erreurs connues, et limitations de MySQL

7. linking, Problèmes lors de la liaison avec la bibliothèque du client MySQL

8. list of, Erreurs communes rencontrées avec MySQL

9. reporting, Informations générales, Listes de diffusion MySQL, Comment rapporter un bogue ou un problème

25. ERROR_FOR_DIVISION_BY_ZERO SQL mode, Le mode SQL du serveur

26. escape (\\), Chaînes

27. escape characters, Littéraux : comment écrire les chaînes et les nombres

28. estimating

1. query performance, Mesurer les performances d'une requête

29. exact-value literals, Mathématiques de précision

30. example

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

31. EXAMPLE storage engine, Le moteur de table EXAMPLE

32. EXAMPLE table type, Le moteur de table EXAMPLE

33. examples

1. compressed tables, myisampack, le générateur de tables MySQL compressées en lecture seule

2. myisamchk output, Obtenir des informations sur une table

3. queries, Exemples de requêtes usuelles

34. Excel, Programs Known to Work With MyODBC

35. execute

1. mysql option, mysql, l'outil en ligne de commande

36. EXECUTE, Syntaxe SQL pour les commandes préparées

37. EXP(), Fonctions mathématiques

38. EXPLAIN, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

39. EXPORT_SET(), Fonctions de chaînes de caractères

40. expression aliases, GROUP BY avec les champs cachés, Syntaxe de SELECT

41. expressions

1. extended, Recherche de modèles

42. extensions

1. to standard SQL, Quels standards respectent MySQL ?

43. EXTRACT(), Fonctions de dates et d'heures

44. extracting

1. dates, Calcul sur les Dates

F

1. FALSE, Nombres

2. fatal signal 11, Problèmes de compilation ?

3. features of MySQL, Les fonctionnalités principales de MySQL

4. FEDERATED storage engine, Le moteur de table FEDERATED

5. FEDERATED table type, Le moteur de table FEDERATED

6. FETCH, Commande de curseur FETCH

7. field

1. changing, Syntaxe de ALTER TABLE

8. FIELD(), Fonctions de chaînes de caractères

9. FILE, Fonctions de chaînes de caractères

10. files

1. binary log, Le log binaire

2. config.cache, Problèmes de compilation ?

3. error messages, Langue des messages d'erreurs

4. log, Options habituelles de configure, Entretien des fichiers de log

5. my.cnf, Fonctionnalités de la réplication et problèmes connus

6. not found message, Problèmes avec les permissions sur fichiers

7. permissions, Problèmes avec les permissions sur fichiers

8. query log, Le log général de requêtes

9. repairing, Options de réparation de myisamchk

10. script, Utilisation de mysql en mode batch

11. size limits, Quelles tailles peuvent atteindre les tables MySQL

12. slow query log, Le log des requêtes lentes

13. text, mysqlimport, importer des données depuis des fichiers texte

14. tmp, Problèmes d'exécution de mysql_install_db

15. update log, Le log de modification

11. FIND_IN_SET(), Fonctions de chaînes de caractères

12. FIXED, Présentation des types numériques of Numeric Types

13. fixed-point arithmetic, Mathématiques de précision

14. FLOAT, Présentation des types numériques of Numeric Types

15. FLOAT(M

1. D), Présentation des types numériques of Numeric Types

16. FLOAT(precision), Présentation des types numériques of Numeric Types

17. floating-point number, Présentation des types numériques of Numeric Types

18. floats, Nombres

19. FLOOR(), Fonctions mathématiques

20. FLUSH, Syntaxe de FLUSH

21. flush tables, mysqladmin, administration d'un serveur MySQL

22. force

1. mysql option, mysql, l'outil en ligne de commande

23. FORCE INDEX, Syntaxe de SELECT, Syntaxe de JOIN

24. FORCE KEY, Syntaxe de SELECT, Syntaxe de JOIN

25. foreign key

1. constraint, Contrainte avec PRIMARY KEY / UNIQUE

2. deleting, Syntaxe de ALTER TABLE, Contraintes de clés étrangères FOREIGN KEY

26. foreign keys, Les clés étrangères, Utiliser les clefs étrangères, Syntaxe de ALTER TABLE

27. FORMAT(), Fonctions diverses

28. Forums, Support de la communauté MySQL sur les forums MySQL

29. FOUND_ROWS(), Fonctions d'informations

30. FreeBSD troubleshooting, Problèmes de compilation ?

31. FROM, Syntaxe de SELECT

32. FROM_DAYS(), Fonctions de dates et d'heures

33. FROM_UNIXTIME(), Fonctions de dates et d'heures

34. ft_max_word_len myisamchk variable, Options générales de myisamchk

35. ft_min_word_len myisamchk variable, Options générales de myisamchk

36. ft_stopword_file myisamchk variable, Options générales de myisamchk

37. full disk, Comment MySQL gère un disque plein

38. full-text search, Recherche en texte intégral (Full-text) dans MySQL

39. FULLTEXT, Recherche en texte intégral (Full-text) dans MySQL

40. function

1. deleting, Syntaxe de CREATE FUNCTION/DROP FUNCTION

41. functions, Fonctions à utiliser dans les clauses SELECT et WHERE

1. arithmetic, Fonctions sur les bits

2. bit, Fonctions sur les bits

3. C API, Vue d'ensemble des fonctions de l'API C

4. C Prepared statements API, Présentation des fonctions de l'interface C

5. control flow, Les fonctions de contrôle

6. date and time, Fonctions de dates et d'heures

7. encryption, Fonctions de chiffrements

8. GROUP BY, Fonctions avec GROUP BY

9. grouping, Parenthèses

10. information, Fonctions d'informations

11. mathematical, Fonctions mathématiques

12. miscellaneous, Fonctions diverses

13. native

1. adding, Ajouter de nouvelles fonctions natives

14. new, Ajouter des fonctions à MySQL

15. string, Fonctions de chaînes de caractères

16. string comparison, Opérateurs de comparaison pour les chaînes de caractères

17. user-definable

1. adding, Ajouter une nouvelle fonction définie par l'utilisateur (UDF)

18. user-defined, Ajouter des fonctions à MySQL

42. Functions

1. user-defined, Syntaxe de CREATE FUNCTION/DROP FUNCTION

43. functions for SELECT and WHERE clauses, Fonctions à utiliser dans les clauses SELECT et WHERE

44. Future development of MySQL CLuster, Cluster MySQL en 5.0 et 5.1

G

1. gcc, Options habituelles de configure

2. gdb

1. using, Déboguer mysqld sous gdb

3. general information, Informations générales

4. General Public License, Présentation du système de bases de données MySQL

5. geographic feature, Introduction à GIS

6. GeomCollFromText(), Créer des objets géométriques avec les fonctions WKT

7. GeomCollFromWKB(), Créer des objets géométriques avec les fonctions WKB

8. geometry, Introduction à GIS

9. GEOMETRY, Types de données géographiques MySQL

10. GEOMETRYCOLLECTION, Types de données géographiques MySQL

11. GeometryCollection(), Création de formes géométriques avec les fonctions spécifiques de MySQL

12. GeometryCollectionFromText(), Créer des objets géométriques avec les fonctions WKT

13. GeometryCollectionFromWKB(), Créer des objets géométriques avec les fonctions WKB

14. GeometryFromText(), Créer des objets géométriques avec les fonctions WKT

15. GeometryFromWKB(), Créer des objets géométriques avec les fonctions WKB

16. GeometryN(), Fonctions d'analyse des lignes GeometryCollection

17. GeometryType(), Fonctions générales d'analyse géométrique

18. GeomFromText(), Créer des objets géométriques avec les fonctions WKT, Fonctions pour convertir les formes de format

19. GeomFromWKB(), Créer des objets géométriques avec les fonctions WKB, Fonctions pour convertir les formes de format

20. geospatial feature, Introduction à GIS

21. getting MySQL, Comment obtenir MySQL ?

22. GET_FORMAT(), Fonctions de dates et d'heures

23. GET_LOCK(), Fonctions diverses

24. GIS, Données spatiales avec MySQL, Introduction à GIS

25. GLength(), Fonctions d'analyse des lignes LineString, Fonctions d'analyse des lignes MultiLineString

26. global privileges, Syntaxe de GRANT et REVOKE

27. goals of MySQL, Présentation du système de bases de données MySQL

28. GPL

1. General Public License, Licence Publique Générale GNU

2. GNU General Public License, Licence Publique Générale GNU

3. MySQL FLOSS License Exception, Exception de licence MySQL FLOSS

29. GRANT, Syntaxe de GRANT et REVOKE

30. GRANT statemenet, Options de GRANT avec SSL

31. GRANT statement, Ajouter de nouveaux utilisateurs à MySQL

32. grant tables, Contrôle d'accès, étape 2 : Vérification de la requête

1. re-creating, Procédures de post-installation sous Unix

2. sorting, Contrôle d'accès, étape 1 : Vérification de la connexion, Contrôle d'accès, étape 2 : Vérification de la requête

3. upgrading, Mise à jour des tables de droits

33. granting

1. privileges, Syntaxe de GRANT et REVOKE

34. GRANTS, SHOW GRANTS

35. graphical tool, mysqlcc, MySQL Control Center

36. greater than (>), Opérateurs de comparaison

37. greater than or equal (>=), Opérateurs de comparaison

38. GREATEST(), Opérateurs de comparaison

39. GROUP BY, Comment MySQL optimise les clauses GROUP BY

1. aliases in, GROUP BY avec les champs cachés

2. extensions to standard SQL, GROUP BY avec les champs cachés, Syntaxe de SELECT

40. GROUP BY functions, Fonctions avec GROUP BY

41. grouping

1. expressions, Parenthèses

42. GROUP_CONCAT(), Fonctions avec GROUP BY

43. GUI tool, mysqlcc, MySQL Control Center

H

1. HANDLER, Syntaxe de HANDLER

2. Handlers, DECLARE un gestionnaire

3. handling

1. errors, Valeurs de retour et gestion d'erreurs

4. HEAP storage engine, Moteurs de tables MySQL et types de table, Le moteur de tables MEMORY (HEAP)

5. HEAP table type, Moteurs de tables MySQL et types de table, Le moteur de tables MEMORY (HEAP)

6. help

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

3. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

7. HEX(), Fonctions de chaînes de caractères

8. hexadecimal values, Valeurs hexadécimales

9. hints, Extensions MySQL au standard SQL-92, Syntaxe de SELECT, Syntaxe de JOIN

10. history of MySQL, Histoire de MySQL

11. history_size

1. mysqlcc option, mysqlcc, MySQL Control Center

12. HOME environment variable, mysql, l'outil en ligne de commande, Variables d'environnement

13. host

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

14. host table, Contrôle d'accès, étape 2 : Vérification de la requête

1. sorting, Contrôle d'accès, étape 2 : Vérification de la requête

15. host.frm

1. problems finding, Procédures de post-installation sous Unix

16. hostname

1. default, Se connecter au serveur MySQL

17. HOUR(), Fonctions de dates et d'heures

18. html

1. mysql option, mysql, l'outil en ligne de commande

I

1. ID

1. unique, Comment lire l'identifiant unique de la dernière ligne insérée

2. identifiers, Noms de bases, tables, index, colonnes et alias

1. case sensitivity, Sensibilité à la casse pour les noms

2. quoting, Noms de bases, tables, index, colonnes et alias

3. IF, Commande IF

4. IF(), Les fonctions de contrôle

5. IFNULL(), Les fonctions de contrôle

6. IGNORE INDEX, Syntaxe de SELECT, Syntaxe de JOIN

7. IGNORE KEY, Syntaxe de SELECT, Syntaxe de JOIN

8. ignore-space

1. mysql option, mysql, l'outil en ligne de commande

9. IGNORE_SPACE SQL mode, Le mode SQL du serveur

10. IMPORT TABLESPACE, Syntaxe de ALTER TABLE, Espaces de tables multiples : chaque table InnoDB a son fichier .ibd

11. importing

1. data, mysqlimport, importer des données depuis des fichiers texte

12. IN, Opérateurs de comparaison

13. increasing

1. performance, FAQ de la réplication

2. speed, Réplication de MySQL

14. index

1. colonnes, Index de colonnes

2. deleting, Syntaxe de ALTER TABLE, Syntaxe de DROP INDEX

3. multi-colonnes, Index sur plusieurs colonnes

15. index multi-colonnes, Index sur plusieurs colonnes

16. indexes, Syntaxe de CREATE INDEX

1. and BLOB columns, Index de colonnes, Syntaxe de CREATE TABLE

2. and IS NULL, Comment MySQL utilise les index

3. and LIKE, Comment MySQL utilise les index

4. and NULL values, Syntaxe de CREATE TABLE

5. and TEXT columns, Index de colonnes, Syntaxe de CREATE TABLE

6. assigning to key cache, Syntaxe de CACHE INDEX

7. block size, Variables serveur système

8. leftmost prefix of, Comment MySQL utilise les index

9. multi-part, Syntaxe de CREATE INDEX

10. names, Noms de bases, tables, index, colonnes et alias

11. use of, Comment MySQL utilise les index

17. INET_ATON(), Fonctions diverses

18. INET_NTOA(), Fonctions diverses

19. information functions, Fonctions d'informations

20. INFORMATION_SCHEMA, La base de données d'informations INFORMATION_SCHEMA, Les tables INFORMATION_SCHEMA

21. INNER JOIN, Syntaxe de JOIN

22. InnoDB, Présentation des tables InnoDB

23. InnoDB storage engine, Moteurs de tables MySQL et types de tables, Le moteur de tables InnoDB

24. InnoDB table type, Moteurs de tables MySQL et types de tables, Le moteur de tables InnoDB

25. InnoDB tables, Transactions et opérations atomiques

26. INSERT, Vitesse des requêtes INSERT, Syntaxe de INSERT

27. INSERT ... SELECT, Syntaxe de INSERT

28. INSERT DELAYED, Syntaxe de INSERT DELAYED

29. INSERT statement

1. grant privileges, Ajouter de nouveaux utilisateurs à MySQL

30. INSERT(), Fonctions de chaînes de caractères

31. inserting

1. speed of, Vitesse des requêtes INSERT

32. installation layouts, Dispositions d'installation

33. installation overview, Installation de MySQL avec une distribution source

34. installing

1. binary distribution, Installer MySQL sur d'autres systèmes type Linux

2. Linux RPM packages, Installer MySQL sous Linux

3. Mac OS X PKG packages, Installer MySQL sur Mac OS X

4. overview, Installer MySQL

5. Perl, Commentaires sur l'installation de Perl

6. Perl on Windows, Installer ActiveState Perl sur Windows

7. source distribution, Installation de MySQL avec une distribution source

8. user-defined functions, Compiler et installer des fonctions utilisateur

35. INSTR(), Fonctions de chaînes de caractères

36. INT, Présentation des types numériques of Numeric Types

37. INTEGER, Présentation des types numériques of Numeric Types

38. integer arithmetic, Mathématiques de précision

39. integers, Nombres

40. InteriorRingN(), Fonctions d'analyse des lignes Polygon

41. internal compiler errors, Problèmes de compilation ?

42. internal locking, Méthodes de verrouillage

43. internals, Rouages de MySQL

44. Internet Relay Chat, Support de la communauté MySQL sur IRC (Internet Relay Chat)

45. Intersection(), Opérateurs géométriques

46. Intersects(), Fonctions qui testent les relations géométriques entre les formes

47. INTERVAL(), Opérateurs de comparaison

48. introducer

1. string literal, Chaînes, Jeu de caractères et collation des chaînes littérales

49. IRC, Support de la communauté MySQL sur IRC (Internet Relay Chat)

50. IS NOT NULL, Opérateurs de comparaison

51. IS NULL, Comment MySQL optimise IS NULL, Opérateurs de comparaison

1. and indexes, Comment MySQL utilise les index

52. ISAM storage engine, Moteurs de tables MySQL et types de tables, Tables ISAM

53. ISAM table type, Moteurs de tables MySQL et types de tables, Tables ISAM

54. IsClosed(), Fonctions d'analyse des lignes LineString, Fonctions d'analyse des lignes MultiLineString

55. IsEmpty(), Fonctions générales d'analyse géométrique

56. ISNULL(), Opérateurs de comparaison

57. ISOLATION LEVEL, Syntaxe de SET TRANSACTION

58. IsRing(), Fonctions d'analyse des lignes LineString

59. IsSimple(), Fonctions générales d'analyse géométrique

60. IS_FREE_LOCK(), Fonctions diverses

61. IS_USED_LOCK(), Fonctions diverses

62. ITERATE, Commande ITERATE

J

1. Java connectivity, MySQL et Java (JDBC)

2. JDBC, MySQL et Java (JDBC)

3. JOIN, Syntaxe de JOIN

K

1. Key cache

1. MyISAM, Le cache de clés des tables MyISAM

2. key cache

1. assigning indexes to, Syntaxe de CACHE INDEX

3. key space

1. MyISAM, Espace nécessaire pour stocker les index

4. keys

1. foreign, Les clés étrangères, Utiliser les clés étrangères

2. searching on two, Recherche sur deux clés

5. keywords, Cas des mots réservés MySQL

6. key_buffer_size myisamchk variable, Options générales de myisamchk

7. KEY_COLUMN_USAGE

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA KEY_COLUMN_USAGE

8. KILL, Syntaxe de KILL

9. known errors, Erreurs connues, et limitations de MySQL

L

1. language support, Langue des messages d'erreurs

2. last row

1. unique ID, Comment lire l'identifiant unique de la dernière ligne insérée

3. LAST_DAY(), Fonctions de dates et d'heures

4. LAST_INSERT_ID(), Transactions et opérations atomiques, Syntaxe de INSERT

5. LAST_INSERT_ID([expr]), Fonctions d'informations

6. layout of installation, Dispositions d'installation

7. LCASE(), Fonctions de chaînes de caractères

8. LD_LIBRARY_PATH environment variable, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

9. LD_RUN_PATH environment variable, Notes sur la distribution source de Linux, Notes pour Solaris, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD, Variables d'environnement

10. LEAST(), Opérateurs de comparaison

11. LEAVE, Commande LEAVE

12. LEFT JOIN, Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN, Syntaxe de JOIN

13. LEFT OUTER JOIN, Syntaxe de JOIN

14. LEFT(), Fonctions de chaînes de caractères

15. leftmost prefix of indexes, Comment MySQL utilise les index

16. legal names, Noms de bases, tables, index, colonnes et alias

17. LENGTH(), Fonctions de chaînes de caractères

18. less than (<), Opérateurs de comparaison

19. less than or equal (<=), Opérateurs de comparaison

20. libmysqld, libmysqld, la bibliothèque du serveur embarqué MySQL

21. libraries

1. list of, Bibliothèques utilisées et incluses dans MySQL

22. library

1. mysqlclient, API MySQL

23. License, Exception de licence MySQL FLOSS

24. LIKE, Opérateurs de comparaison pour les chaînes de caractères

1. and indexes, Comment MySQL utilise les index

2. and wildcards, Comment MySQL utilise les index

25. LIMIT, Comment MySQL optimise LIMIT, Fonctions d'informations

26. limitations

1. design, Limitations et inconvénients des choix conceptuels de MySQL

2. replication, Fonctionnalités de la réplication et problèmes connus

27. limits

1. file-size, Quelles tailles peuvent atteindre les tables MySQL

28. linefeed (\n), Chaînes

29. LineFromText(), Créer des objets géométriques avec les fonctions WKT

30. LineFromWKB(), Créer des objets géométriques avec les fonctions WKB

31. LINESTRING, Types de données géographiques MySQL

32. LineString(), Création de formes géométriques avec les fonctions spécifiques de MySQL

33. LineStringFromText(), Créer des objets géométriques avec les fonctions WKT

34. LineStringFromWKB(), Créer des objets géométriques avec les fonctions WKB

35. linking, Compiler les clients

1. errors, Problèmes lors de la liaison avec la bibliothèque du client MySQL

2. problems, Problèmes lors de la liaison avec l'API C

3. speed, Influences de la compilation et des liaisons sur la vitesse de MySQL

36. links

1. symbolic, Utiliser des liens symboliques

37. Linux

1. binary distribution, Notes relatives à Linux pour les distributions binaires

2. source distribution, Notes sur la distribution source de Linux

38. literals, Littéraux : comment écrire les chaînes et les nombres

39. LN(), Fonctions mathématiques

40. LOAD DATA FROM MASTER, LOAD DATA FROM MASTER

41. LOAD DATA INFILE, Syntaxe de LOAD DATA INFILE, Problèmes avec les valeurs NULL

42. LOAD TABLE FROM MASTER, Syntaxe de LOAD TABLE tbl_name FROM MASTER

43. loading

1. tables, Charger des données dans une table

44. LOAD_FILE(), Fonctions de chaînes de caractères

45. local-infile

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

46. LOCALTIME, Fonctions de dates et d'heures

47. LOCALTIMESTAMP, Fonctions de dates et d'heures

48. LOCATE(), Fonctions de chaînes de caractères

49. LOCK TABLES, Syntaxe de LOCK TABLES/UNLOCK TABLES

50. locking

1. page-level, Méthodes de verrouillage

2. row-level, Transactions et opérations atomiques, Méthodes de verrouillage

3. table-level, Méthodes de verrouillage

51. locking methods, Méthodes de verrouillage

52. log

1. changes, Historique des changements MySQL

2. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

53. log files, Options habituelles de configure

1. maintaining, Entretien des fichiers de log

2. names, Sauvegardes de base de données

54. Log files, Les fichiers de log de MySQL

55. LOG(), Fonctions mathématiques

56. LOG10(), Fonctions mathématiques

57. LOG2(), Fonctions mathématiques

58. Logical operators, Opérateurs logiques

59. LONG, Les types BLOB et TEXT

60. LONGBLOB, Présentation des types de chaînes

61. LONGTEXT, Présentation des types de chaînes

62. LOOP, Commande LOOP

63. LOWER(), Fonctions de chaînes de caractères

64. LPAD(), Fonctions de chaînes de caractères

65. LTRIM(), Fonctions de chaînes de caractères

M

1. Mac OS X

1. installation, Installer MySQL sur Mac OS X

2. mailing address

1. for customer support, Comment rapporter un bogue ou un problème

3. mailing list address, Informations générales

4. mailing lists, Les listes de diffusion de MySQL

1. archive location, Poser des questions ou rapporter un bogue

2. guidelines, Conseils pour répondre sur la liste de diffusion

5. main features of MySQL, Les fonctionnalités principales de MySQL

6. maintaining

1. log files, Entretien des fichiers de log

2. tables, Mettre en place un régime d'entretien de MySQL

7. MAKEDATE(), Fonctions de dates et d'heures

8. MAKETIME(), Fonctions de dates et d'heures

9. make_binary_distribution, Présentation des scripts serveur et des utilitaires

10. MAKE_SET(), Fonctions de chaînes de caractères

11. manual

1. available formats, À propos du manuel

2. online location, À propos du manuel

3. typographical conventions, Conventions utilisées dans ce manuel

12. master-slave setup, Présentation de l'implémentation de la réplication

13. MASTER_POS_WAIT(), Fonctions diverses, MASTER_POS_WAIT()

14. MATCH ... AGAINST(), Recherche en texte intégral (Full-text) dans MySQL

15. matching

1. patterns, Recherche de modèles

16. math, Mathématiques de précision

17. mathematical functions, Fonctions mathématiques

18. MAX(), Fonctions avec GROUP BY

19. MAXDB SQL mode, Le mode SQL du serveur

20. maximum memory used, mysqladmin, administration d'un serveur MySQL

21. max_allowed_packet variable, mysql, l'outil en ligne de commande, mysqlcc, MySQL Control Center

22. max_join_size variable, mysql, l'outil en ligne de commande, mysqlcc, MySQL Control Center

23. MBR, Relations avec les Rectangles enveloppes (MBRs)

24. MBRContains(), Relations avec les Rectangles enveloppes (MBRs)

25. MBRDisjoint(), Relations avec les Rectangles enveloppes (MBRs)

26. MBREquals(), Relations avec les Rectangles enveloppes (MBRs)

27. MBRIntersects(), Relations avec les Rectangles enveloppes (MBRs)

28. MBROverlaps(), Relations avec les Rectangles enveloppes (MBRs)

29. MBRTouches(), Relations avec les Rectangles enveloppes (MBRs)

30. MBRWithin(), Relations avec les Rectangles enveloppes (MBRs)

31. MD5(), Fonctions de chiffrements

32. MEDIUMBLOB, Présentation des types de chaînes

33. MEDIUMINT, Présentation des types numériques of Numeric Types

34. MEDIUMTEXT, Présentation des types de chaînes

35. MEMORY storage engine, Moteurs de tables MySQL et types de tables, Le moteur de tables MEMORY (HEAP)

36. MEMORY table type, Moteurs de tables MySQL et types de tables, Le moteur de tables MEMORY (HEAP)

37. memory usage

1. myisamchk, Utilisation de la mémoire par myisamchk

38. memory use, Comment MySQL gère la mémoire, mysqladmin, administration d'un serveur MySQL

39. MERGE storage engine, Moteurs de tables MySQL et types de tables, Tables assemblées MERGE

40. MERGE table type, Moteurs de tables MySQL et types de tables, Tables assemblées MERGE

41. MERGE tables

1. defined, Tables assemblées MERGE

42. messages

1. languages, Langue des messages d'erreurs

43. metadata

1. database, La base de données d'informations INFORMATION_SCHEMA

44. methods

1. locking, Méthodes de verrouillage

45. MICROSECOND(), Fonctions de dates et d'heures

46. MID(), Fonctions de chaînes de caractères

47. MIN(), Fonctions avec GROUP BY

48. Minimum Bounding Rectangle, Relations avec les Rectangles enveloppes (MBRs)

49. minus

1. unary (-), Opérations arithmétiques

50. MINUTE(), Fonctions de dates et d'heures

51. mirror sites, Comment obtenir MySQL ?

52. miscellaneous functions, Fonctions diverses

53. Mise en cache des noms d'hôte, Comment MySQL utilise le DNS

54. MIT-pthreads, Notes relatives aux MIT-pthreads

55. MLineFromText(), Créer des objets géométriques avec les fonctions WKT

56. MLineFromWKB(), Créer des objets géométriques avec les fonctions WKB

57. MOD (modulo), Fonctions mathématiques

58. MOD(), Fonctions mathématiques

59. modes

1. batch, Utilisation de mysql en mode batch

60. modules

1. list of, Jusqu'à quel point MySQL est-il stable ?

61. modulo (%), Fonctions mathématiques

62. modulo (MOD), Fonctions mathématiques

63. monitor

1. terminal, Tutoriels d'introduction

64. MONTH(), Fonctions de dates et d'heures

65. MONTHNAME(), Fonctions de dates et d'heures

66. MPointFromText(), Créer des objets géométriques avec les fonctions WKT

67. MPointFromWKB(), Créer des objets géométriques avec les fonctions WKB

68. MPolyFromText(), Créer des objets géométriques avec les fonctions WKT

69. MPolyFromWKB(), Créer des objets géométriques avec les fonctions WKB

70. mSQL compatibility, Opérateurs de comparaison pour les chaînes de caractères

71. msql2mysql, Utilitaires de développement des programmes MySQL

72. MSSQL SQL mode, Le mode SQL du serveur

73. multi mysqld, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

74. multi-byte character sets, Erreur Can't initialize character set xxx

75. multi-byte characters, Support des caractères multi-octets

76. multi-part index, Syntaxe de CREATE INDEX

77. MULTILINESTRING, Types de données géographiques MySQL

78. MultiLineString(), Création de formes géométriques avec les fonctions spécifiques de MySQL

79. MultiLineStringFromText(), Créer des objets géométriques avec les fonctions WKT

80. MultiLineStringFromWKB(), Créer des objets géométriques avec les fonctions WKB

81. multiple servers, Faire fonctionner plusieurs serveurs MySQL sur la même machine

82. multiplication (*), Opérations arithmétiques

83. MULTIPOINT, Types de données géographiques MySQL

84. MultiPoint(), Création de formes géométriques avec les fonctions spécifiques de MySQL

85. MultiPointFromText(), Créer des objets géométriques avec les fonctions WKT

86. MultiPointFromWKB(), Créer des objets géométriques avec les fonctions WKB

87. MULTIPOLYGON, Types de données géographiques MySQL

88. MultiPolygon(), Création de formes géométriques avec les fonctions spécifiques de MySQL

89. MultiPolygonFromText(), Créer des objets géométriques avec les fonctions WKT

90. MultiPolygonFromWKB(), Créer des objets géométriques avec les fonctions WKB

91. My

1. derivation, Histoire de MySQL

92. my.cnf file, Fonctionnalités de la réplication et problèmes connus

93. MyISAM

1. compressed tables, myisampack, le générateur de tables MySQL compressées en lecture seule, Caractéristiques des tables compressées

2. size, Capacités des colonnes

94. MyISAM key cache, Le cache de clés des tables MyISAM

95. MyISAM storage engine, Moteurs de tables MySQL et types de tables, Le moteur de tables MyISAM

96. MyISAM table type, Moteurs de tables MySQL et types de tables, Le moteur de tables MyISAM

97. myisamchk, Options habituelles de configure, Présentation des scripts serveur et des utilitaires

1. example output, Obtenir des informations sur une table

2. options, Options générales de myisamchk

98. myisampack, Présentation des scripts serveur et utilitaires, myisampack, le générateur de tables MySQL compressées en lecture seule, Modification automatique du type de colonnes, Caractéristiques des tables compressées

99. myisam_block_size myisamchk variable, Options générales de myisamchk

100. MyODBC, Support ODBC de MySQL

1. reporting problems, Rapporter des problèmes avec MYODBC

101. MySQL

1. defined, Présentation du système de bases de données MySQL

2. introduction, Présentation du système de bases de données MySQL

3. pronunciation, Présentation du système de bases de données MySQL

102. mysql, Présentation des scripts serveur et utilitaires, mysql, l'outil en ligne de commande

103. MySQL binary distribution, Choisir votre version de MySQL

104. MYSQL C type, Types de données de l'API C

105. MySQL C type, Types de données de l'API C

106. MySQL Cluster in MySQL 5.0 and 5.1, Cluster MySQL en 5.0 et 5.1

107. mysql command-line options, mysql, l'outil en ligne de commande

108. mysql commands

1. list of, Commandes mysql

109. MySQL Dolphin name, Histoire de MySQL

110. MySQL history, Histoire de MySQL

111. mysql history file, mysql, l'outil en ligne de commande

112. MySQL mailing lists, Listes de diffusion MySQL

113. MySQL name, Histoire de MySQL

114. mysql prompt command, Commandes mysql

115. MySQL source distribution, Choisir votre version de MySQL

116. MySQL storage engines, Moteurs de tables MySQL et types de tables

117. MySQL table types, Moteurs de tables MySQL et types de tables

118. MySQL version, Comment obtenir MySQL ?

119. MySQL++, Interface MySQL C++

120. mysql.server, Présentation des scripts serveur et des utilitaires

121. mysql.sock

1. changing location of, Options habituelles de configure

2. protection, Comment protéger ou changer le fichier socket /tmp/mysql.sock

122. MYSQL323 SQL mode, Le mode SQL du serveur

123. MYSQL40 SQL mode, Le mode SQL du serveur

124. mysqlaccess, Présentation des scripts serveur et utilitaires

125. mysqladmin, Présentation des scripts serveur et utilitaires, mysqladmin, administration d'un serveur MySQL, Syntaxe de CREATE DATABASE, Syntaxe de DROP DATABASE, Syntaxe de SHOW STATUS, Syntaxe de SHOW VARIABLES, Syntaxe de FLUSH, Syntaxe de KILL

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

126. mysqladmin command-line options, mysqladmin, administration d'un serveur MySQL

127. mysqlbinlog, Présentation des scripts serveur et utilitaires, mysqlbinlog, Exécuter des requêtes dans le log binaire

128. mysqlbug, Présentation des scripts serveur et des utilitaires

129. mysqlbug script, Comment rapporter un bogue ou un problème

1. location, Informations générales

130. mysqlcc, Présentation des scripts serveur et utilitaires, mysqlcc, MySQL Control Center

131. mysqlcc command-line options, mysqlcc, MySQL Control Center

132. mysqlcheck, Présentation des scripts serveur et utilitaires

133. mysqlclient library, API MySQL

134. mysqld, Présentation des scripts serveur et des utilitaires

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

2. starting, Comment exécuter MySQL comme un utilisateur normal

135. mysqld options, Options de ligne de commande de mysqld

136. mysqld-max, Présentation des scripts serveur et des utilitaires, mysqld-max, la version étendue du serveur mysqld

137. mysqldump, Migrer depuis une autre architecture, Présentation des scripts serveur et utilitaires, mysqldump, sauvegarde des structures de tables et les données

138. mysqld_multi, Présentation des scripts serveur et des utilitaires, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

139. mysqld_safe, Présentation des scripts serveur et des utilitaires, safe_mysqld, le script père de mysqld

140. mysqlhotcopy, Présentation des scripts serveur et utilitaires

141. mysqlimport, Migrer depuis une autre architecture, Présentation des scripts serveur et utilitaires, mysqlimport, importer des données depuis des fichiers texte, Syntaxe de LOAD DATA INFILE

142. mysqlshow, Présentation des scripts serveur et utilitaires

143. mysqltest

1. MySQL Test Suite, Suite de test de MySQL

144. mysql_affected_rows(), mysql_affected_rows()

145. mysql_autocommit()., mysql_autocommit()

146. MYSQL_BIND C type, Types de données de l'API C

147. mysql_change_user(), mysql_change_user()

148. mysql_character_set_name(), mysql_character_set_name()

149. mysql_close(), mysql_close()

150. mysql_commit()., mysql_commit()

151. mysql_config, Utilitaires de développement des programmes MySQL

152. mysql_connect(), mysql_connect()

153. mysql_create_db(), mysql_create_db()

154. mysql_data_seek(), mysql_data_seek()

155. MYSQL_DEBUG environment variable, Présentation des scripts serveur et utilitaires, Débogage un client MySQL, Variables d'environnement

156. mysql_debug(), mysql_debug()

157. mysql_drop_db(), mysql_drop_db()

158. mysql_dump_debug_info(), mysql_dump_debug_info()

159. mysql_eof(), mysql_eof()

160. mysql_errno(), mysql_errno()

161. mysql_error(), mysql_error()

162. mysql_escape_string(), mysql_escape_string()

163. mysql_fetch_field(), mysql_fetch_field()

164. mysql_fetch_fields(), mysql_fetch_fields()

165. mysql_fetch_field_direct(), mysql_fetch_field_direct()

166. mysql_fetch_lengths(), mysql_fetch_lengths()

167. mysql_fetch_row(), mysql_fetch_row()

168. MYSQL_FIELD C type, Types de données de l'API C

169. mysql_field_count(), mysql_field_count(), mysql_num_fields()

170. MYSQL_FIELD_OFFSET C type, Types de données de l'API C

171. mysql_field_seek(), mysql_field_seek()

172. mysql_field_tell(), mysql_field_tell()

173. mysql_fix_privilege_tables, Présentation des scripts serveur et des utilitaires, Causes des erreurs Access denied

174. mysql_free_result(), mysql_free_result()

175. mysql_get_client_info(), mysql_get_client_info()

176. mysql_get_client_version(), mysql_get_client_version()

177. mysql_get_host_info(), mysql_get_host_info()

178. mysql_get_proto_info(), mysql_get_proto_info()

179. mysql_get_server_info(), mysql_get_server_info()

180. mysql_get_server_version(), mysql_get_server_version()

181. mysql_hex_string(), mysql_hex_string()

182. MYSQL_HISTFILE environment variable, mysql, l'outil en ligne de commande, Variables d'environnement

183. MYSQL_HOST environment variable, Se connecter au serveur MySQL, Variables d'environnement

184. mysql_info(), Syntaxe de INSERT, Syntaxe de LOAD DATA INFILE, Syntaxe de UPDATE, Syntaxe de ALTER TABLE, mysql_info()

185. mysql_init(), mysql_init()

186. mysql_insert_id(), Transactions et opérations atomiques, Syntaxe de INSERT, mysql_insert_id()

187. mysql_install_db, Présentation des scripts serveur et des utilitaires

188. mysql_install_db script, Problèmes d'exécution de mysql_install_db

189. mysql_kill(), mysql_kill()

190. mysql_library_end(), mysql_library_end()

191. mysql_library_init(), mysql_library_end()

192. mysql_list_dbs(), mysql_list_dbs()

193. mysql_list_fields(), mysql_list_fields()

194. mysql_list_processes(), mysql_list_processes()

195. mysql_list_tables(), mysql_list_tables()

196. mysql_more_results()., mysql_more_results()

197. mysql_next_result()., mysql_next_result()

198. mysql_num_fields(), mysql_num_fields()

199. mysql_num_rows(), mysql_num_rows()

200. mysql_options(), mysql_options()

201. mysql_ping(), mysql_ping()

202. MYSQL_PS1 environment variable, Variables d'environnement

203. MYSQL_PWD environment variable, Se connecter au serveur MySQL, Présentation des scripts serveur et utilitaires, Variables d'environnement

204. mysql_query(), mysql_query(), Questions courantes sur la bibliothèque C

205. mysql_real_connect(), mysql_real_connect()

206. mysql_real_escape_string(), Chaînes, mysql_real_escape_string()

207. mysql_real_query(), mysql_real_query()

208. mysql_reload(), mysql_reload()

209. MYSQL_RES C type, Types de données de l'API C

210. mysql_rollback()., mysql_rollback()

211. MYSQL_ROW C type, Types de données de l'API C

212. mysql_row_seek(), mysql_row_seek()

213. mysql_row_tell(), mysql_row_tell()

214. mysql_select_db(), mysql_select_db()

215. mysql_server_end(), mysql_server_end()

216. mysql_server_init(), mysql_server_init()

217. mysql_set_sever_option(), mysql_set_server_option()

218. mysql_shutdown(), mysql_shutdown()

219. mysql_sqlstate(), mysql_sqlstate()

220. mysql_ssl_set(), mysql_ssl_set()

221. mysql_stat(), mysql_stat()

222. MYSQL_STMT C type, Types de données de l'API C

223. mysql_stmt_affected_rows(), mysql_stmt_affected_rows()

224. mysql_stmt_attr_get(), mysql_stmt_attr_get()

225. mysql_stmt_attr_set(), mysql_stmt_attr_set()

226. mysql_stmt_bind_param(), mysql_stmt_bind_param()

227. mysql_stmt_bind_result(), mysql_stmt_bind_result()

228. mysql_stmt_close(), mysql_stmt_close()

229. mysql_stmt_data_seek(), mysql_stmt_data_seek()

230. mysql_stmt_errno(), mysql_stmt_errno()

231. mysql_stmt_error()., mysql_stmt_error()

232. mysql_stmt_execute(), mysql_stmt_execute()

233. mysql_stmt_fetch(), mysql_stmt_fetch()

234. mysql_stmt_fetch_column(), mysql_stmt_fetch_column()

235. mysql_stmt_field_count(), mysql_stmt_field_count()

236. mysql_stmt_free_result(), mysql_stmt_free_result()

237. mysql_stmt_init(), mysql_stmt_init()

238. mysql_stmt_insert_id(), mysql_stmt_insert_id()

239. mysql_stmt_num_rows(), mysql_stmt_num_rows()

240. mysql_stmt_param_count(), mysql_stmt_param_count()

241. mysql_stmt_param_metadata(), mysql_stmt_param_metadata()

242. mysql_stmt_prepare(), mysql_stmt_prepare()

243. mysql_stmt_reset(), mysql_stmt_reset()

244. mysql_stmt_result_metadata., mysql_stmt_result_metadata()

245. mysql_stmt_row_seek(), mysql_stmt_row_seek()

246. mysql_stmt_row_tell(), mysql_stmt_row_tell()

247. mysql_stmt_send_long_data()., mysql_stmt_send_long_data()

248. mysql_stmt_sqlstate(), mysql_stmt_sqlstate()

249. mysql_stmt_store_result(), mysql_stmt_store_result()

250. mysql_store_result(), mysql_store_result(), Questions courantes sur la bibliothèque C

251. MYSQL_TCP_PORT environment variable, Utiliser plusieurs serveurs sous Unix, Utiliser les clients dans un environnement multiserveur, Présentation des scripts serveur et utilitaires, Variables d'environnement

252. mysql_thread_end(), mysql_thread_end()

253. mysql_thread_id(), mysql_thread_id()

254. mysql_thread_init(), mysql_thread_init()

255. mysql_thread_safe(), mysql_thread_safe()

256. MYSQL_UNIX_PORT environment variable, Problèmes d'exécution de mysql_install_db, Utiliser plusieurs serveurs sous Unix, Utiliser les clients dans un environnement multiserveur, Présentation des scripts serveur et utilitaires, Variables d'environnement

257. mysql_use_result(), mysql_use_result()

258. mysql_warning_count()., mysql_warning_count()

259. my_init(), my_init()

260. my_ulonglong C type, Types de données de l'API C

261. my_ulonglong values

1. printing, Types de données de l'API C

N

1. named pipes, Choisir un serveur MySQL sur Windows, Tester son installation MySQL

2. named-commands

1. mysql option, mysql, l'outil en ligne de commande

3. names, Noms de bases, tables, index, colonnes et alias

1. case sensitivity, Sensibilité à la casse pour les noms

2. variables, Variables utilisateur

4. naming

1. releases of MySQL, Quelle version de MySQL utiliser ?

5. NATIONAL CHAR, Présentation des types de chaînes

6. native functions

1. adding, Ajouter de nouvelles fonctions natives

7. native thread support, Systèmes d'exploitation supportés par MySQL

8. NATURAL LEFT JOIN, Syntaxe de JOIN

9. NATURAL LEFT OUTER JOIN, Syntaxe de JOIN

10. NATURAL RIGHT JOIN, Syntaxe de JOIN

11. NATURAL RIGHT OUTER JOIN, Syntaxe de JOIN

12. NCHAR, Présentation des types de chaînes

13. negative values, Nombres

14. nested queries, Sous-sélections (SubSELECT)

15. nested query, Sous-sélections (SubSELECT)

16. nesting queries, Sous-sélections (SubSELECT)

17. net etiquette, Poser des questions ou rapporter un bogue, Conseils pour répondre sur la liste de diffusion

18. netmask notation

1. in mysql.user table, Contrôle d'accès, étape 1 : Vérification de la connexion

19. NetWare, Installer MySQL sur NetWare

20. net_buffer_length variable, mysql, l'outil en ligne de commande, mysqlcc, MySQL Control Center

21. New features in MySQL Cluster, Cluster MySQL en 5.0 et 5.1

22. new procedures

1. adding, Ajouter une nouvelle procédure à MySQL

23. new users

1. adding, Installer MySQL sur d'autres systèmes type Linux, Installation depuis les sources : présentation

24. newline (\n), Chaînes

25. no matching rows, Résoudre les problèmes des lignes non retournées

26. no-auto-rehash

1. mysql option, mysql, l'outil en ligne de commande

27. no-beep

1. mysql option, mysql, l'outil en ligne de commande

28. no-log

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

29. no-named-commands

1. mysql option, mysql, l'outil en ligne de commande

30. no-pager

1. mysql option, mysql, l'outil en ligne de commande

31. no-tee

1. mysql option, mysql, l'outil en ligne de commande

32. non-delimited strings, Les types DATETIME, DATE, et TIMESTAMP

33. Non-transactional tables, Erreur Some non-transactional changed tables couldn't be rolled back

34. NOT

1. logical, Opérateurs logiques

35. NOT BETWEEN, Opérateurs de comparaison

36. not equal (!=), Opérateurs de comparaison

37. not equal (<>), Opérateurs de comparaison

38. NOT IN, Opérateurs de comparaison

39. NOT LIKE, Opérateurs de comparaison pour les chaînes de caractères

40. NOT NULL

1. constraint, Contraintes sur les valeurs invalides

41. NOT REGEXP, Opérateurs de comparaison pour les chaînes de caractères

42. Novell NetWare, Installer MySQL sur NetWare

43. NOW(), Fonctions de dates et d'heures

44. NO_AUTO_VALUE_ON_ZERO SQL mode, Le mode SQL du serveur

45. NO_DIR_IN_CREATE SQL mode, Le mode SQL du serveur

46. NO_FIELD_OPTIONS SQL mode, Le mode SQL du serveur

47. NO_KEY_OPTIONS SQL mode, Le mode SQL du serveur

48. NO_TABLE_OPTIONS SQL mode, Le mode SQL du serveur

49. NO_UNSIGNED_SUBTRACTION SQL mode, Le mode SQL du serveur

50. NO_ZERO_DATE SQL mode, Le mode SQL du serveur

51. NO_ZERO_IN_DATE SQL mode, Le mode SQL du serveur

52. NUL, Chaînes

53. NULL, Travailler avec la valeur NULL, Problèmes avec les valeurs NULL

1. testing for null, Opérateurs de comparaison, Les fonctions de contrôle

54. NULL value, Travailler avec la valeur NULL, Valeurs NULL

55. NULL values

1. and AUTO_INCREMENT columns, Problèmes avec les valeurs NULL

2. and indexes, Syntaxe de CREATE TABLE

3. and TIMESTAMP columns, Problèmes avec les valeurs NULL

4. vs. empty values, Problèmes avec les valeurs NULL

56. NULLIF(), Les fonctions de contrôle

57. numbers, Nombres

58. NUMERIC, Présentation des types numériques of Numeric Types

59. numeric types, Capacités des colonnes

60. NumGeometries(), Fonctions d'analyse des lignes GeometryCollection

61. NumInteriorRings(), Fonctions d'analyse des lignes Polygon

62. NumPoints(), Fonctions d'analyse des lignes LineString

O

1. OCT(), Fonctions de chaînes de caractères

2. OCTET_LENGTH(), Fonctions de chaînes de caractères

3. ODBC, Support ODBC de MySQL

4. ODBC compatibility, Identifiants, Présentation des types numériques of Numeric Types, Opérateurs de comparaison, Syntaxe de JOIN, Syntaxe de CREATE TABLE, Changements de la version 3.21.15

5. odbcadmin program, Programs Known to Work With MyODBC

6. OLAP, Options de GROUP BY

7. OLD_PASSWORD(), Fonctions de chiffrements

8. one-database

1. mysql option, mysql, l'outil en ligne de commande

9. online location of manual, À propos du manuel

10. ONLY_FULL_GROUP_BY SQL mode, Le mode SQL du serveur

11. OPEN, Commande de curseur OPEN

12. Open Source

1. defined, Présentation du système de bases de données MySQL

13. open tables, Comment MySQL compte les tables ouvertes, mysqladmin, administration d'un serveur MySQL

14. OpenGIS, Introduction à GIS

15. opening

1. tables, Quand MySQL ouvre et ferme les tables

16. opens, mysqladmin, administration d'un serveur MySQL

17. OpenSSL, Utilisation des connexions sécurisées

18. open_files_limit variable, mysqlbinlog, Exécuter des requêtes dans le log binaire

19. operating systems

1. file-size limits, Quelles tailles peuvent atteindre les tables MySQL

2. supported, Systèmes d'exploitation supportés par MySQL

3. Windows versus Unix, MySQL pour Windows face à MySQL pour Unix

20. operations

1. arithmetic, Opérations arithmétiques

21. operators, Fonctions à utiliser dans les clauses SELECT et WHERE

1. cast, Opérations arithmétiques

22. Operators

1. logical, Opérateurs logiques

23. optimisation

1. tips, Autres conseils d'optimisation

24. optimisation du système, Réglage du système, au moment de la compilation, et paramètres du démarrage

25. optimisations, Comment MySQL optimise les clauses WHERE

26. optimising

1. DISTINCT, Comment MySQL optimise DISTINCT

2. LEFT JOIN, Comment MySQL optimise les clauses LEFT JOIN et RIGHT JOIN

3. LIMIT, Comment MySQL optimise LIMIT

4. tables, Optimisation de tables

27. optimizations, Optimisation de combinaison d'index

28. OPTIMIZE TABLE, Syntaxe de OPTIMIZE TABLE

29. optimizer

1. controlling, Contrôle des performances de l'optimisateur de requêtes

30. optimizing

1. GROUP BY, Comment MySQL optimise les clauses GROUP BY

31. option files, Fichier d'options my.cnf, Causes des erreurs Access denied

32. options

1. command-line, Options de ligne de commande de mysqld

1. mysql, mysql, l'outil en ligne de commande

2. mysqladmin, mysqladmin, administration d'un serveur MySQL

3. mysqlcc, mysqlcc, MySQL Control Center

2. configure, Options habituelles de configure

3. myisamchk, Options générales de myisamchk

4. provided by MySQL, Tutoriels d'introduction

5. replication, Fonctionnalités de la réplication et problèmes connus

33. options de mysqld, Réglage des paramètres du serveur

34. OR, Optimisation de combinaison d'index

1. bitwise, Fonctions sur les bits

2. logical, Opérateurs logiques

35. OR Index Merge optimization, Optimisation de combinaison d'index

36. Oracle compatibility, Extensions MySQL au standard SQL-92, Fonctions avec GROUP BY, Syntaxe de DESCRIBE (obtenir des informations sur les colonnes)

37. ORACLE SQL mode, Le mode SQL du serveur

38. ORD(), Fonctions de chaînes de caractères

39. ORDER BY, Trier les enregistrements, Syntaxe de SELECT, Syntaxe de ALTER TABLE

1. aliases in, GROUP BY avec les champs cachés

40. Overlaps(), Fonctions qui testent les relations géométriques entre les formes

41. overview, Informations générales

P

1. packages

1. list of, Applications qui supportent MySQL

2. pack_isam, myisampack, le générateur de tables MySQL compressées en lecture seule

3. page-level locking, Méthodes de verrouillage

4. pager

1. mysql option, mysql, l'outil en ligne de commande

5. paramètres

1. serveur, Réglage des paramètres du serveur

6. paramètres de démarrage, Réglage des paramètres du serveur

1. réglages, Réglage du système, au moment de la compilation, et paramètres du démarrage

7. parentheses ( and ), Parenthèses

8. password

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

3. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

4. root user, Création des premiers droits MySQL

9. password encryption

1. reversibility of, Fonctions de chiffrements

10. PASSWORD(), Contrôle d'accès, étape 1 : Vérification de la connexion, Configurer les mots de passe, Fonctions de chiffrements, Erreur Ignoring user

11. passwords

1. for users, Nom d'utilisateurs MySQL et mots de passe

2. forgotten, Comment réinitialiser un mot de passe Root oublié

3. lost, Comment réinitialiser un mot de passe Root oublié

4. resetting, Comment réinitialiser un mot de passe Root oublié

5. security, Rôle du système de privilèges

6. setting, Configurer les mots de passe, Syntaxe de GRANT et REVOKE, Syntaxe de SET PASSWORD

12. PATH environment variable, Installer MySQL sur d'autres systèmes type Linux, Appeler des programmes MySQL, Variables d'environnement

13. pattern matching, Recherche de modèles

14. performance

1. benchmarks, Utiliser vos propres tests de performance

2. disk issues, Problèmes avec les disques

3. estimating, Mesurer les performances d'une requête

4. improving, FAQ de la réplication, Rendre vos tables aussi compactes que possible

15. PERIOD_ADD(), Fonctions de dates et d'heures

16. PERIOD_DIFF(), Fonctions de dates et d'heures

17. Perl

1. installing, Commentaires sur l'installation de Perl

2. installing on Windows, Installer ActiveState Perl sur Windows

18. Perl API, API Perl pour MySQL

19. Perl DBI/DBD

1. installation problems, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

20. permission checks

1. effect on speed, Optimisation des commandes SELECT et autres requêtes

21. perror, Présentation des scripts serveur et utilitaires, perror, expliquer les codes d'erreurs

22. PHP API, API PHP pour MySQL

23. PI(), Fonctions mathématiques

24. PIPES_AS_CONCAT SQL mode, Le mode SQL du serveur

25. plugins_path

1. mysqlcc option, mysqlcc, MySQL Control Center

26. POINT, Types de données géographiques MySQL

27. Point(), Création de formes géométriques avec les fonctions spécifiques de MySQL

28. PointFromText(), Créer des objets géométriques avec les fonctions WKT

29. PointFromWKB(), Créer des objets géométriques avec les fonctions WKB

30. PointN(), Fonctions d'analyse des lignes LineString

31. PointOnSurface(), Fonctions d'analyse des lignes MultiPolygon

32. PolyFromText(), Créer des objets géométriques avec les fonctions WKT

33. PolyFromWKB(), Créer des objets géométriques avec les fonctions WKB

34. POLYGON, Types de données géographiques MySQL

35. Polygon(), Création de formes géométriques avec les fonctions spécifiques de MySQL

36. PolygonFromText(), Créer des objets géométriques avec les fonctions WKT

37. PolygonFromWKB(), Créer des objets géométriques avec les fonctions WKB

38. port

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

39. portability, Portabilité

1. types, Utilisation des types de données issues d'autres SGBDR

40. porting

1. to other systems, Port vers d'autres systèmes

41. POSITION(), Fonctions de chaînes de caractères

42. post-install

1. multiple servers, Faire fonctionner plusieurs serveurs MySQL sur la même machine

43. post-installation

1. setup and testing, Procédure de post-installation

44. PostgreSQL compatibility, Extensions MySQL au standard SQL-92

45. POSTGRESQL SQL mode, Le mode SQL du serveur

46. POW(), Fonctions mathématiques

47. POWER(), Fonctions mathématiques

48. precision

1. arithmetic, Mathématiques de précision

49. precision math, Mathématiques de précision

50. PREPARE, Syntaxe SQL pour les commandes préparées

51. PRIMARY KEY, Syntaxe de ALTER TABLE, Syntaxe de CREATE TABLE

1. constraint, Contrainte avec PRIMARY KEY / UNIQUE

52. primary key

1. deleting, Syntaxe de ALTER TABLE

53. privilege

1. changes, Contrôle d'accès, étape 2 : Vérification de la requête

54. privilege information

1. location, Droits fournis par MySQL

55. privilege system, Rôle du système de privilèges

1. described, Comment fonctionne le système de droits

56. privileges

1. access, Règles de sécurité et droits d'accès au serveur MySQL

2. adding, Ajouter de nouveaux utilisateurs à MySQL

3. default, Création des premiers droits MySQL

4. deleting, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

5. display, SHOW GRANTS

6. dropping, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

7. granting, Syntaxe de GRANT et REVOKE

8. revoking, Syntaxe de GRANT et REVOKE

57. problems

1. access denied errors, Erreur Access denied

2. common errors, Problèmes et erreurs communes

3. compiling, Problèmes de compilation ?

4. DATE columns, Problèmes avec l'utilisation des colonnes DATE

5. date values, Les types DATETIME, DATE, et TIMESTAMP

6. installing on IBM-AIX, Notes relatives à IBM-AIX

7. installing on Solaris, Notes pour Solaris

8. installing Perl, Problèmes lors de l'utilisation des interfaces Perl DBI et DBD

9. linking, Problèmes lors de la liaison avec la bibliothèque du client MySQL

10. ODBC, Rapporter des problèmes avec MYODBC

11. reporting, Comment rapporter un bogue ou un problème

12. starting the server, Problèmes de démarrage du serveur MySQL

13. table locking, Problème de verrouillage de tables

14. timezone, Problèmes de fuseaux horaires

58. procedures

1. adding, Ajouter une nouvelle procédure à MySQL

2. stored, Procédures stockées et triggers, Procédures stockées et fonctions

59. process support, Systèmes d'exploitation supportés par MySQL

60. processes

1. display, Syntaxe de SHOW PROCESSLIST

61. processing

1. arguments, Traitement des arguments

62. PROCESSLIST, Syntaxe de SHOW PROCESSLIST

63. program variables

1. setting, Utiliser les options pour configurer des variables de programme

64. programs

1. client, Compiler les clients

2. crash-me, Portabilité

3. list of, Présentation des scripts serveur et des utilitaires

65. prompt

1. mysql option, mysql, l'outil en ligne de commande

66. prompts

1. meanings, Entrer des requêtes

67. pronunciation

1. MySQL, Présentation du système de bases de données MySQL

68. protocol

1. mysql option, mysql, l'outil en ligne de commande

69. Protocol mismatch, Passer de la version 3.20 à la version 3.21

70. PURGE MASTER LOGS, PURGE MASTER LOGS

71. Python APIs, MySQL Python API

Q

1. QUARTER(), Fonctions de dates et d'heures

2. queries

1. entering, Entrer des requêtes

2. estimating performance, Mesurer les performances d'une requête

3. examples, Exemples de requêtes usuelles

4. speed of, Optimisation des commandes SELECT et autres requêtes

5. Twin Studeis project, Requêtes du projet Twin

3. query

1. mysqlcc option, mysqlcc, MySQL Control Center

4. Query Cache, Cache de requêtes MySQL

5. query log, Le log général de requêtes

6. questions, mysqladmin, administration d'un serveur MySQL

1. answering, Conseils pour répondre sur la liste de diffusion

7. quick

1. mysql option, mysql, l'outil en ligne de commande

8. QUOTE(), Fonctions de chaînes de caractères

9. quotes

1. in strings, Chaînes

10. quoting, Chaînes

11. quoting binary data, Chaînes

12. quoting of identifiers, Noms de bases, tables, index, colonnes et alias

R

1. RADIANS(), Fonctions mathématiques

2. RAID

1. compile errors, Problèmes de compilation ?

2. table type, Syntaxe de CREATE TABLE

3. RAND(), Fonctions mathématiques

4. raw

1. mysql option, mysql, l'outil en ligne de commande

5. re-creating

1. grant tables, Procédures de post-installation sous Unix

6. read_buffer_size myisamchk variable, Options générales de myisamchk

7. REAL, Présentation des types numériques of Numeric Types

8. REAL_AS_FLOAT SQL mode, Le mode SQL du serveur

9. reconfiguring, Problèmes de compilation ?

10. reconnect

1. mysql option, mysql, l'outil en ligne de commande

11. recovery

1. from crash, Utiliser myisamchk pour restaurer une table

12. reducing

1. data size, Rendre vos tables aussi compactes que possible

13. references, Syntaxe de ALTER TABLE

14. ref_or_null, Comment MySQL optimise IS NULL

15. regex, Expressions régulières MySQL

16. REGEXP, Opérateurs de comparaison pour les chaînes de caractères

17. register

1. mysqlcc option, mysqlcc, MySQL Control Center

18. regular expression syntax

1. described, Expressions régulières MySQL

19. Related(), Fonctions qui testent les relations géométriques entre les formes

20. relational databases

1. defined, Présentation du système de bases de données MySQL

21. release numbers, Choisir votre version de MySQL

22. releases

1. naming scheme, Quelle version de MySQL utiliser ?

2. testing, Quelle version de MySQL utiliser ?

3. updating, Quand et comment sont publiées les nouvelles versions de MySQL

23. RELEASE_LOCK(), Fonctions diverses

24. RENAME TABLE, Syntaxe de RENAME TABLE

25. RENAME USER, Syntaxe de RENAME USER

26. renaming user accounts, Syntaxe de RENAME USER

27. reordering

1. columns, Comment changer l'ordre des colonnes dans une table

28. repair options

1. myisamchk, Options de réparation de myisamchk

29. REPAIR TABLE, Syntaxe de REPAIR TABLE

30. repairing

1. tables, Comment réparer des tables

31. REPEAT, Commande REPEAT

32. REPEAT(), Fonctions de chaînes de caractères

33. replace, Présentation des scripts serveur et utilitaires

34. REPLACE, Syntaxe de REPLACE

35. REPLACE ... SELECT, Syntaxe de INSERT

36. replace utility, L'utilitaire de remplacement de chaînes replace

37. REPLACE(), Fonctions de chaînes de caractères

38. replication, Réplication de MySQL

39. replication limitations, Fonctionnalités de la réplication et problèmes connus

40. replication masters

1. commands, Requêtes SQL pour contrôler les maîtres de réplication

41. replication options, Fonctionnalités de la réplication et problèmes connus

42. replication slaves

1. commands, Commandes SQL de contrôle des esclaves de réplication

43. reporting

1. bugs, Comment rapporter un bogue ou un problème

2. errors, Informations générales, Listes de diffusion MySQL

3. MyODBC problems, Rapporter des problèmes avec MYODBC

44. REQUIRE GRANT option, Options de GRANT avec SSL, Syntaxe de GRANT et REVOKE

45. reserved words

1. exceptions, Cas des mots réservés MySQL

46. RESET MASTER, RESET MASTER

47. RESET SLAVE, RESET SLAVE

48. restarting

1. the server, Procédures de post-installation sous Unix

49. RESTORE TABLE, Syntaxe de RESTORE TABLE

50. retrieving

1. data from tables, Récupérer des informations à partir d'une table

51. return (\r), Chaînes

52. return values

1. UDFs, Valeurs de retour et gestion d'erreurs

53. REVERSE(), Fonctions de chaînes de caractères

54. REVOKE, Syntaxe de GRANT et REVOKE

55. revoking

1. privileges, Syntaxe de GRANT et REVOKE

56. RIGHT JOIN, Syntaxe de JOIN

57. RIGHT OUTER JOIN, Syntaxe de JOIN

58. RIGHT(), Fonctions de chaînes de caractères

59. RLIKE, Opérateurs de comparaison pour les chaînes de caractères

60. ROLLBACK, Transactions et opérations atomiques, Syntaxes de START TRANSACTION COMMIT et ROLLBACK

61. ROLLBACK TO SAVEPOINT, Syntaxe de SAVEPOINT et ROLLBACK TO SAVEPOINT

62. ROLLUP, Options de GROUP BY

63. root password, Création des premiers droits MySQL

64. root user

1. password resetting, Comment réinitialiser un mot de passe Root oublié

65. ROUND(), Fonctions mathématiques

66. rounding, Mathématiques de précision

67. rounding errors, Présentation des types numériques of Numeric Types, Fonctions mathématiques

68. ROUTINES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA ROUTINES

69. row-level locking, Méthodes de verrouillage

70. rows

1. counting, Compter les lignes

2. deleting, Effacer des lignes de tables reliées

3. locking, Transactions et opérations atomiques

4. matching problems, Résoudre les problèmes des lignes non retournées

5. selecting, Sélectionner des lignes particulières

6. sorting, Trier les enregistrements

71. RPAD(), Fonctions de chaînes de caractères

72. RPM file, Installer MySQL sous Linux

73. RPM Package Manager, Installer MySQL sous Linux

74. RTRIM(), Fonctions de chaînes de caractères

75. RTS-threads, Commentaires à propos des threads RTS

76. running

1. ANSI mode, Exécuter MySQL en mode ANSI

2. batch mode, Utilisation de mysql en mode batch

3. multiple servers, Faire fonctionner plusieurs serveurs MySQL sur la même machine

4. queries, Entrer des requêtes

77. running configure after prior invocation, Problèmes de compilation ?

S

1. safe-updates

1. mysql option, mysql, l'outil en ligne de commande

2. safe-updates option, Utilisation de l'option --safe-updates

3. safe_mysqld, safe_mysqld, le script père de mysqld

4. Sakila, Histoire de MySQL

5. SAVEPOINT, Syntaxe de SAVEPOINT et ROLLBACK TO SAVEPOINT

6. scale

1. arithmetic, Mathématiques de précision

7. SCHEMATA

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA SCHEMATA

8. SCHEMA_PRIVILEGES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA SCHEMA_PRIVILEGES

9. script files, Utilisation de mysql en mode batch

10. scripts, safe_mysqld, le script père de mysqld, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

1. mysqlbug, Comment rapporter un bogue ou un problème

2. mysql_install_db, Problèmes d'exécution de mysql_install_db

3. SQL, mysql, l'outil en ligne de commande

11. searching

1. and case-sensitivity, Sensibilité à la casse dans les recherches

2. full-text, Recherche en texte intégral (Full-text) dans MySQL

3. MySQL web pages, Poser des questions ou rapporter un bogue

4. two keys, Recherche sur deux clés

12. SECOND(), Fonctions de dates et d'heures

13. security

1. against attackers, Protéger MySQL contre les attaques

14. security system, Règles de sécurité et droits d'accès au serveur MySQL

15. SEC_TO_TIME(), Fonctions de dates et d'heures

16. SELECT, Syntaxe de SELECT

1. optimizing, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

2. Query Cache, Cache de requêtes MySQL

17. SELECT INTO, Syntaxe de SELECT ... INTO

18. SELECT INTO TABLE, SELECT INTO TABLE

19. SELECT speed, Vitesse des requêtes SELECT

20. selecting

1. databases, Créer et sélectionner une base de données

21. select_limit variable, mysql, l'outil en ligne de commande, mysqlcc, MySQL Control Center

22. SEQUENCE, Utiliser AUTO_INCREMENT

23. sequence emulation, Fonctions d'informations

24. sequences, Utiliser AUTO_INCREMENT

25. server

1. connecting, Connexion et déconnexion au serveur, Se connecter au serveur MySQL

2. debugging, Déboguer un serveur MySQL

3. disconnecting, Connexion et déconnexion au serveur

4. mysqlcc option, mysqlcc, MySQL Control Center

5. restart, Procédures de post-installation sous Unix

6. shutdown, Procédures de post-installation sous Unix

7. starting, Procédures de post-installation sous Unix

8. starting and stopping, Lancer et arrêter MySQL automatiquement

9. starting problems, Problèmes de démarrage du serveur MySQL

26. server administration, mysqladmin, administration d'un serveur MySQL

27. server variables, Variables serveur système, Variables système, Syntaxe de SHOW VARIABLES

28. servers

1. multiple, Faire fonctionner plusieurs serveurs MySQL sur la même machine

29. serveur mysqld

1. taille des tampons, Réglage des paramètres du serveur

30. SESSION_USER(), Fonctions d'informations

31. SET, Présentation des types de chaînes, Le type SET, Syntaxe de SET, Commande d'affectation de variables SET

1. size, Capacités des colonnes

32. SET GLOBAL SQL_SLAVE_SKIP_COUNTER, SET GLOBAL SQL_SLAVE_SKIP_COUNTER

33. SET OPTION, Syntaxe de SET

34. SET PASSWORD, Syntaxe de SET PASSWORD

35. SET PASSWORD statement, Configurer les mots de passe

36. SET SQL_LOG_BIN, SET SQL_LOG_BIN

37. SET TRANSACTION, Syntaxe de SET TRANSACTION

38. setting

1. passwords, Configurer les mots de passe

39. setting passwords, Syntaxe de SET PASSWORD

40. setting program variables, Utiliser les options pour configurer des variables de programme

41. setup

1. post-installation, Procédure de post-installation

42. SHA(), Fonctions de chiffrements

43. SHA1(), Fonctions de chiffrements

44. shell syntax, Conventions utilisées dans ce manuel

45. SHOW BINLOG EVENTS, Syntaxe de SHOW, SHOW BINLOG EVENTS

46. SHOW COLLATION, Syntaxe de SHOW COLLATION

47. SHOW COLUMNS, Syntaxe de SHOW, Syntaxe de SHOW COLUMNS

48. SHOW CREATE DATABASE, Syntaxe de SHOW, Syntaxe de SHOW CREATE DATABASE

49. SHOW CREATE FUNCTION, SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION

50. SHOW CREATE PROCEDURE, SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION

51. SHOW CREATE TABLE, Syntaxe de SHOW, Syntaxe de SHOW CREATE TABLE

52. SHOW CREATE VIEW, Syntaxe SHOW CREATE VIEW

53. SHOW DATABASES, Syntaxe de SHOW, Syntaxe de SHOW DATABASES

54. SHOW ENGINES, Syntaxe de SHOW, Syntaxe SHOW ENGINES

55. SHOW ERRORS, Syntaxe de SHOW, Syntaxe de SHOW ERRORS

56. SHOW extensions, Extensions à la commande SHOW

57. SHOW FIELDS, Syntaxe de SHOW

58. SHOW FUNCTION STATUS, SHOW PROCEDURE STATUS et SHOW FUNCTION STATUS

59. SHOW GRANTS, Syntaxe de SHOW, SHOW GRANTS

60. SHOW INDEX, Syntaxe de SHOW, Syntaxe de SHOW INDEX

61. SHOW INNODB STATUS, Syntaxe de SHOW

62. SHOW KEYS, Syntaxe de SHOW, Syntaxe de SHOW INDEX

63. SHOW MASTER LOGS, Syntaxe de SHOW, SHOW MASTER LOGS

64. SHOW MASTER STATUS, Syntaxe de SHOW, SHOW MASTER STATUS

65. SHOW PRIVILEGES, Syntaxe de SHOW, SHOW PRIVILEGES

66. SHOW PROCEDURE STATUS, SHOW PROCEDURE STATUS et SHOW FUNCTION STATUS

67. SHOW PROCESSLIST, Syntaxe de SHOW, Syntaxe de SHOW PROCESSLIST

68. SHOW SCHEMAS, Syntaxe de SHOW DATABASES

69. SHOW SLAVE HOSTS, Syntaxe de SHOW, SHOW SLAVE HOSTS

70. SHOW SLAVE STATUS, Syntaxe de SHOW, SHOW SLAVE STATUS

71. SHOW STATUS, Syntaxe de SHOW

72. SHOW STORAGE ENGINES, Syntaxe SHOW ENGINES

73. SHOW TABLE STATUS, Syntaxe de SHOW

74. SHOW TABLE TYPES, Syntaxe de SHOW, Syntaxe SHOW ENGINES

75. SHOW TABLES, Syntaxe de SHOW, Syntaxe de SHOW TABLES

76. SHOW VARIABLES, Syntaxe de SHOW

77. SHOW WARNINGS, Syntaxe de SHOW, SHOW WARNINGS | ERRORS

78. SHOW with WHERE, La base de données d'informations INFORMATION_SCHEMA, Extensions à la commande SHOW

79. showing

1. database information, Afficher les bases, tables et colonnes

80. shutdown_timeout variable, mysqladmin, administration d'un serveur MySQL

81. shutting down

1. the server, Procédures de post-installation sous Unix

82. SIGN(), Fonctions mathématiques

83. silent

1. mysql option, mysql, l'outil en ligne de commande

84. silent column changes, Modification automatique du type de colonnes

85. SIN(), Fonctions mathématiques

86. single quote (\'), Chaînes

87. size of tables, Quelles tailles peuvent atteindre les tables MySQL

88. sizes

1. display, Types de colonnes

89. skip-column-names

1. mysql option, mysql, l'outil en ligne de commande

90. skip-line-numbers

1. mysql option, mysql, l'outil en ligne de commande

91. slow queries, mysqladmin, administration d'un serveur MySQL

92. slow query log, Le log des requêtes lentes

93. SMALLINT, Présentation des types numériques of Numeric Types

94. socket

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

95. socket location

1. changing, Options habituelles de configure

96. Solaris installation problems, Notes pour Solaris

97. Solaris troubleshooting, Problèmes de compilation ?

98. sorting

1. character sets, Le jeu de caractères utilisé pour les données et le stockage

2. data, Trier les enregistrements

3. grant tables, Contrôle d'accès, étape 1 : Vérification de la connexion, Contrôle d'accès, étape 2 : Vérification de la requête

4. table rows, Trier les enregistrements

99. sort_buffer_size myisamchk variable, Options générales de myisamchk

100. sort_key_blocks myisamchk variable, Options générales de myisamchk

101. SOUNDEX(), Fonctions de chaînes de caractères

102. SOUNDS LIKE, Fonctions de chaînes de caractères

103. source distribution

1. installing, Installation de MySQL avec une distribution source

104. source distributions

1. on Linux, Notes sur la distribution source de Linux

105. SPACE(), Fonctions de chaînes de caractères

106. Spatial Extensions in MySQL, Introduction à GIS

107. speed

1. compiling, Influences de la compilation et des liaisons sur la vitesse de MySQL

2. increasing, Réplication de MySQL

3. inserting, Vitesse des requêtes INSERT

4. linking, Influences de la compilation et des liaisons sur la vitesse de MySQL

5. of queries, Optimisation des commandes SELECT et autres requêtes, Vitesse des requêtes SELECT

108. SQL

1. defined, Présentation du système de bases de données MySQL

109. SQL commands

1. replication masters, Requêtes SQL pour contrôler les maîtres de réplication

2. replication slaves, Commandes SQL de contrôle des esclaves de réplication

110. SQL scripts, mysql, l'outil en ligne de commande

111. SQL-92

1. extensions to, Quels standards respecte MySQL ?

112. SQL_CACHE, Options relatives au cache de requêtes dans un SELECT

113. SQL_NO_CACHE, Options relatives au cache de requêtes dans un SELECT

114. sql_yacc.cc problems, Problèmes de compilation ?

115. SQRT(), Fonctions mathématiques

116. square brackets, Types de colonnes

117. SRID(), Fonctions générales d'analyse géométrique

118. SSH, Connexion à MySQL à distance avec Windows et SSH

119. SSL and X509 Basics, Utilisation des connexions sécurisées

120. SSL command-line options, Options SSL en ligne de commande

121. SSL related options, Options de GRANT avec SSL, Syntaxe de GRANT et REVOKE

122. stability, Jusqu'à quel point MySQL est-il stable ?

123. standard SQL

1. extensions to, Quels standards respecte MySQL ?

124. standards compatibility, Quels standards respecte MySQL ?

125. START SLAVE, START SLAVE

126. START TRANSACTION, Syntaxes de START TRANSACTION, COMMIT et ROLLBACK

127. starting

1. comments, '--' comme début de commentaire

2. mysqld, Comment exécuter MySQL comme un utilisateur normal

3. the server, Procédures de post-installation sous Unix

4. the server automatically, Lancer et arrêter MySQL automatiquement

128. Starting many servers, Faire fonctionner plusieurs serveurs MySQL sur la même machine

129. StartPoint(), Fonctions d'analyse des lignes LineString

130. startup options

1. default, Fichier d'options my.cnf

131. startup parameters

1. mysql, mysql, l'outil en ligne de commande

2. mysqladmin, mysqladmin, administration d'un serveur MySQL

3. mysqlcc, mysqlcc, MySQL Control Center

132. statements

1. GRANT, Ajouter de nouveaux utilisateurs à MySQL

2. INSERT, Ajouter de nouveaux utilisateurs à MySQL

133. statically

1. compiling, Options habituelles de configure

134. STATISTICS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA STATISTICS

135. status

1. tables, SHOW TABLE STATUS

136. status command, Commandes mysql

1. results, mysqladmin, administration d'un serveur MySQL

137. status variables, Variables de statut du serveur, Syntaxe de SHOW STATUS

138. STD(), Fonctions avec GROUP BY

139. STDDEV(), Fonctions avec GROUP BY

140. STOP SLAVE, STOP SLAVE

141. stopping

1. the server, Lancer et arrêter MySQL automatiquement

142. storage engines

1. choosing, Moteurs de tables MySQL et types de tables

143. storage of data, Conception

144. storage requirements

1. column type, Capacités des colonnes

145. storage space

1. minimising, Rendre vos tables aussi compactes que possible

146. stored procedures, Procédures stockées et fonctions

147. stored procedures and triggers

1. defined, Procédures stockées et triggers

148. STRAIGHT_JOIN, Syntaxe de JOIN

149. STRCMP(), Opérateurs de comparaison pour les chaînes de caractères

150. STRICT SQL mode, Le mode SQL du serveur

151. STRICT_ALL_TABLES SQL mode, Le mode SQL du serveur

152. STRICT_TRANS_TABLES SQL mode, Le mode SQL du serveur

153. string collating, Support d'assemblage des chaînes

154. string comparison functions, Opérateurs de comparaison pour les chaînes de caractères

155. string comparisons

1. case sensitivity, Opérateurs de comparaison pour les chaînes de caractères

156. string functions, Fonctions de chaînes de caractères

157. string literal introducer, Chaînes, Jeu de caractères et collation des chaînes littérales

158. string replacement

1. replace utility, L'utilitaire de remplacement de chaînes replace

159. string types, Les types chaînes

160. strings

1. defined, Littéraux : comment écrire les chaînes et les nombres

2. escaping characters, Littéraux : comment écrire les chaînes et les nombres

3. non-delimited, Les types DATETIME, DATE, et TIMESTAMP

161. striping

1. defined, Problèmes avec les disques

162. STR_TO_DATE(), Fonctions de dates et d'heures

163. SUBDATE(), Fonctions de dates et d'heures

164. subqueries, Sous-sélections (SubSELECT)

165. subquery, Sous-sélections (SubSELECT)

166. subselects, Sous-sélections (SubSELECT)

167. SUBSTRING(), Fonctions de chaînes de caractères

168. SUBSTRING_INDEX(), Fonctions de chaînes de caractères

169. SUBTIME(), Fonctions de dates et d'heures

170. subtraction (-), Opérations arithmétiques

171. SUM(), Fonctions avec GROUP BY

172. superuser, Création des premiers droits MySQL

173. support

1. for operating systems, Systèmes d'exploitation supportés par MySQL

2. mailing address, Comment rapporter un bogue ou un problème

174. suppression

1. default values, Contraintes sur les valeurs invalides

175. Sybase compatibility, Syntaxe de USE

176. symbolic links, Utiliser des liens symboliques, Utiliser des liens symboliques pour les bases de données sous Windows

177. SymDifference(), Opérateurs géométriques

178. syntax

1. mysqlcc option, mysqlcc, MySQL Control Center

2. regular expression, Expressions régulières MySQL

179. syntax_file

1. mysqlcc option, mysqlcc, MySQL Control Center

180. SYSDATE(), Fonctions de dates et d'heures

181. system

1. privilege, Rôle du système de privilèges

2. security, Sécurité générale du serveur

182. system table, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

183. system variables, Variables serveur système, Variables système, Syntaxe de SHOW VARIABLES

184. SYSTEM_USER(), Fonctions d'informations

T

1. tab (\t), Chaînes

2. table

1. changing, Syntaxe de ALTER TABLE, Problèmes avec ALTER TABLE.

2. deleting, Syntaxe de DROP TABLE

3. mysql option, mysql, l'outil en ligne de commande

3. table aliases, Syntaxe de SELECT

4. table cache, Quand MySQL ouvre et ferme les tables

5. table is full, Syntaxe de SET, Erreur The table is full

6. table names

1. case sensitivity, Sensibilité à la casse pour les noms

2. case-sensitivity, Extensions MySQL au standard SQL-92

7. Table scan, Comment éviter les analyses de tables

8. table types

1. choosing, Moteurs de tables MySQL et types de table

9. table-level locking, Méthodes de verrouillage

10. tables

1. ARCHIVE, Le moteur de table ARCHIVE

2. BDB, Tables BDB ou BerkeleyDB

3. Berkeley DB, Tables BDB ou BerkeleyDB

4. changing column order, Comment changer l'ordre des colonnes dans une table

5. checking, Options de vérifications pour myisamchk

6. closing, Quand MySQL ouvre et ferme les tables

7. compressed, myisampack, le générateur de tables MySQL compressées en lecture seule

8. compressed format, Caractéristiques des tables compressées

9. constant, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT), Comment MySQL optimise les clauses WHERE

10. copying, Syntaxe de CREATE TABLE

11. counting rows, Compter les lignes

12. creating, Création d'une table

13. CSV, Le moteur CSV

14. defragment, Mettre en place un régime d'entretien de MySQL, Caractéristiques des tables à format de ligne dynamique

15. defragmenting, Syntaxe de OPTIMIZE TABLE

16. deleting rows, Effacer des lignes de tables reliées

17. displaying, Afficher les bases, tables et colonnes

18. displaying status, SHOW TABLE STATUS

19. dumping, mysqldump, sauvegarde des structures de tables et les données, mysqlhotcopy, copier les bases et tables MySQL

20. dynamic, Caractéristiques des tables à format de ligne dynamique

21. error checking, Comment vérifier la cohérence d'une table

22. EXAMPLE, Le moteur de table EXAMPLE

23. FEDERATED, Le moteur de table FEDERATED

24. flush, mysqladmin, administration d'un serveur MySQL

25. fragmentation, Syntaxe de OPTIMIZE TABLE

26. grant, Contrôle d'accès, étape 2 : Vérification de la requête

27. HEAP, Le moteur de table MEMORY (HEAP)

28. host, Contrôle d'accès, étape 2 : Vérification de la requête

29. improving performance, Rendre vos tables aussi compactes que possible

30. information, Obtenir des informations sur une table

31. information about, Obtenir des informations à propos des bases de données et des tables

32. InnoDB, Le moteur de tables InnoDB

33. ISAM, Tables ISAM

34. loading data, Charger des données dans une table

35. maintenance regimen, Mettre en place un régime d'entretien de MySQL

36. maximum size, Quelles tailles peuvent atteindre les tables MySQL

37. MEMORY, Le moteur de table MEMORY (HEAP)

38. MERGE, Tables assemblées MERGE

39. merging, Tables assemblées MERGE

40. multiple, Utiliser plus d'une table

41. MyISAM, Le moteur de tables MyISAM

42. names, Noms de bases, tables, index, colonnes et alias

43. open, Comment MySQL compte les tables ouvertes

44. opening, Quand MySQL ouvre et ferme les tables

45. optimising, Optimisation de table

46. partitioning, Tables assemblées MERGE

47. RAID, Syntaxe de CREATE TABLE

48. repairing, Comment réparer des tables

49. retrieving data, Récupérer des informations à partir d'une table

50. selecting columns, Sélectionner des colonnes particulières

51. selecting rows, Sélectionner des lignes particulières

52. sorting rows, Trier les enregistrements

53. symbolic links, Utiliser les liens symboliques avec les tables sous Unix

54. system, Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT)

55. too many, Inconvénients de la création d'un grand nombre de tables dans la même base de données

56. unique ID for last row, Comment lire l'identifiant unique de la dernière ligne insérée

57. updating, Transactions et opérations atomiques

11. TABLES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA TABLES

12. table_cache, Quand MySQL ouvre et ferme les tables

13. TABLE_PRIVILEGES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA TABLE_PRIVILEGES

14. taille des tampons

1. serveur mysqld, Réglage des paramètres du serveur

15. TAN(), Fonctions mathématiques

16. tar

1. problems on Solaris, Notes pour Solaris

17. Tcl APIs, MySQL Tcl API

18. tcp-ip

1. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

19. TCP/IP, Choisir un serveur MySQL sur Windows, Tester son installation MySQL

20. technical support

1. mailing address, Comment rapporter un bogue ou un problème

21. tee

1. mysql option, mysql, l'outil en ligne de commande

22. temporary file

1. write access, Problèmes d'exécution de mysql_install_db

23. temporary tables

1. problems, Problèmes avec les tables temporaires

24. terminal monitor

1. defined, Tutoriels d'introduction

25. testing

1. connection to the server, Contrôle d'accès, étape 1 : Vérification de la connexion

2. installation, Procédures de post-installation sous Unix

3. of MySQL releases, Quelle version de MySQL utiliser ?

4. post-installation, Procédure de post-installation

26. testing mysqld

1. mysqltest, Suite de test de MySQL

27. Texinfo, À propos du manuel

28. TEXT, Présentation des types de chaînes, Les types BLOB et TEXT

1. size, Capacités des colonnes

29. TEXT columns

1. default values, Les types BLOB et TEXT

2. indexing, Index de colonnes, Syntaxe de CREATE TABLE

30. text files

1. importing, mysqlimport, importer des données depuis des fichiers texte

31. thread packages

1. differences between, Différences entre les différents paquets de threads

32. thread support, Systèmes d'exploitation supportés par MySQL

1. non-native, Notes relatives aux MIT-pthreads

33. threaded clients, Comment faire un client MySQL threadé

34. threads, mysqladmin, administration d'un serveur MySQL, Syntaxe de SHOW PROCESSLIST, Rouages de MySQL

1. display, Syntaxe de SHOW PROCESSLIST

2. RTS, Commentaires à propos des threads RTS

35. TIME, Présentation des types de données temporels : dates et heures, Le type TIME

36. time types, Capacités des colonnes

37. TIME(), Fonctions de dates et d'heures

38. TIMEDIFF(), Fonctions de dates et d'heures

39. timeout, Variables serveur système, Fonctions diverses, Syntaxe de INSERT DELAYED

1. connect_timeout variable, mysql, l'outil en ligne de commande, mysqladmin, administration d'un serveur MySQL, mysqlcc, MySQL Control Center

2. shutdown_timeout variable, mysqladmin, administration d'un serveur MySQL

40. TIMESTAMP, Présentation des types de données temporels : dates et heures, Les types DATETIME, DATE, et TIMESTAMP

1. and NULL values, Problèmes avec les valeurs NULL

41. TIMESTAMP(), Fonctions de dates et d'heures

42. TIMESTAMPADD(), Fonctions de dates et d'heures

43. TIMESTAMPDIFF(), Fonctions de dates et d'heures

44. timezone problems, Problèmes de fuseaux horaires

45. TIME_FORMAT(), Fonctions de dates et d'heures

46. TIME_TO_SEC(), Fonctions de dates et d'heures

47. TINYBLOB, Présentation des types de chaînes

48. TINYINT, Présentation des types numériques of Numeric Types

49. TINYTEXT, Présentation des types de chaînes

50. tips

1. optimisation, Autres conseils d'optimisation

51. TMPDIR environment variable, Problèmes d'exécution de mysql_install_db, Variables d'environnement

52. TODO

1. embedded server, Choses à faire pour le serveur embarqué (TODO)

2. symlinks, Utiliser les liens symboliques avec les tables sous Unix

53. ToDo list for MySQL, Les évolutions de MySQL (la liste des tâches)

54. tools

1. command-line, mysql, l'outil en ligne de commande

2. graphical, mysqlcc, MySQL Control Center

3. GUI, mysqlcc, MySQL Control Center

4. list of, Outils utilisés pour créer MySQL

5. mysqld_multi, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

6. mysqld_safe, safe_mysqld, le script père de mysqld

7. safe_mysqld, safe_mysqld, le script père de mysqld

55. Touches(), Fonctions qui testent les relations géométriques entre les formes

56. TO_DAYS(), Fonctions de dates et d'heures

57. trace DBI method, Déboguer mysqld sous gdb

58. TRADITIONAL SQL mode, Le mode SQL du serveur

59. TRADITONAL SQL mode, Le mode SQL du serveur

60. transaction-safe tables, Transactions et opérations atomiques, Présentation des tables InnoDB

61. transactions

1. support, Transactions et opérations atomiques, Présentation des tables InnoDB

62. translations_path

1. mysqlcc option, mysqlcc, MySQL Control Center

63. Translators

1. list of, Documenteurs et traducteurs

64. triggers, Déclencheurs

1. stored, Procédures stockées et triggers

65. TRIM(), Fonctions de chaînes de caractères

66. troubleshooting

1. FreeBSD, Problèmes de compilation ?

2. Solaris, Problèmes de compilation ?

67. TRUE, Nombres

68. TRUNCATE, Syntaxe de TRUNCATE

69. TRUNCATE(), Fonctions mathématiques

70. tutorial, Tutoriels d'introduction

71. Twin Studies

1. queries, Requêtes du projet Twin

72. type conversions, Opérateurs de comparaison

73. types

1. columns, Types de colonnes, Choisir le bon type de colonnes

2. data, Types de colonnes

3. date, Capacités des colonnes

4. Date and Time, Les types date et heure

5. numeric, Capacités des colonnes

6. of tables, Moteurs de tables MySQL et types de tables

7. portability, Utilisation des types de données issues d'autres SGBDR

8. strings, Les types chaînes

9. time, Capacités des colonnes

74. typographical conventions, Conventions utilisées dans ce manuel

75. TZ environment variable, Problèmes de fuseaux horaires, Variables d'environnement

U

1. UCASE(), Fonctions de chaînes de caractères

2. UCS-2, Jeux de caractères et Unicode

3. UDF functions, Syntaxe de CREATE FUNCTION/DROP FUNCTION

4. UDFs

1. compiling, Compiler et installer des fonctions utilisateurs

2. defined, Ajouter des fonctions à MySQL

3. return values, Valeurs de retour et gestion d'erreurs.

5. ulimit, Fichier non trouvé

6. UMASK environment variable, Problèmes avec les permissions sur fichiers, Variables d'environnement

7. UMASK_DIR environment variable, Problèmes avec les permissions sur fichiers, Variables d'environnement

8. unary minus (-), Opérations arithmétiques

9. unbuffered

1. mysql option, mysql, l'outil en ligne de commande

10. UNCOMPRESS(), Fonctions de chaînes de caractères

11. UNCOMPRESSED_LENGTH(), Fonctions de chaînes de caractères

12. UNHEX(), Fonctions de chaînes de caractères

13. Unicode, Jeux de caractères et Unicode

14. UNION, Recherche sur deux clés, Syntaxe de UNION

15. Union(), Opérateurs géométriques

16. UNIQUE, Syntaxe de ALTER TABLE

1. constraint, Contrainte avec PRIMARY KEY / UNIQUE

17. unique ID, Comment lire l'identifiant unique de la dernière ligne insérée

18. UNIX_TIMESTAMP(), Fonctions de dates et d'heures

19. unloading

1. tables, Récupérer des informations à partir d'une table

20. UNLOCK TABLES, Syntaxe de LOCK TABLES/UNLOCK TABLES

21. unnamed views, Sous-requêtes dans la clause FROM

22. UNTIL, Commande REPEAT

23. UPDATE, Syntaxe de UPDATE

24. update log, Le log de modification

25. updating

1. releases of MySQL, Quand et comment sont publiées les nouvelles versions de MySQL

2. tables, Transactions et opérations atomiques

26. upgrading, Changer de version de MySQL

1. 3.20 to 3.21, Passer de la version 3.20 à la version 3.21

2. 3.21 to 3.22, Passer de la version 3.21 à la version 3.22

3. 3.22 to 3.23, Passer de la version 3.22 à la version 3.23

4. 3.23 to 4.0, Passer de la version 3.23 à la version 4.0

5. 4.0 to 4.1, Passer de la version 4.0 à la version 4.1

6. different architecture, Migrer depuis une autre architecture

7. grant tables, Mise à jour des tables de droits

8. to 5.0, Passer en de version 4.1 en version 5.0

27. UPPER(), Fonctions de chaînes de caractères

28. uptime, mysqladmin, administration d'un serveur MySQL

29. URLS for downloading MySQL, Comment obtenir MySQL ?

30. USE, Syntaxe de USE

31. USE INDEX, Syntaxe de SELECT, Syntaxe de JOIN

32. USE KEY, Syntaxe de SELECT, Syntaxe de JOIN

33. user

1. mysql option, mysql, l'outil en ligne de commande

2. mysqlcc option, mysqlcc, MySQL Control Center

3. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

34. user accounts

1. creating, Syntaxe de CREATE USER

2. renaming, Syntaxe de RENAME USER

35. USER environment variable, Se connecter au serveur MySQL, Variables d'environnement

36. user names

1. and passwords, Nom d'utilisateurs MySQL et mots de passe

37. user privileges

1. adding, Ajouter de nouveaux utilisateurs à MySQL

2. deleting, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

3. dropping, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

38. user table

1. sorting, Contrôle d'accès, étape 1 : Vérification de la connexion

39. user variables, Variables utilisateur

40. USER(), Fonctions d'informations

41. user-defined functions

1. adding, Ajouter des fonctions à MySQL, Ajouter une nouvelle fonction définie par l'utilisateur (UDF)

42. User-defined functions, Syntaxe de CREATE FUNCTION/DROP FUNCTION

43. users

1. adding, Installer MySQL sur d'autres systèmes type Linux, Installation depuis les sources : présentation

2. deleting, Supprimer un compte utilisateur de MySQL, Effacer des utilisateurs MySQL

3. root, Création des premiers droits MySQL

44. USER_PRIVILEGES

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA USER_PRIVILEGES

45. using multiple disks to start data, Utiliser des liens symboliques pour les bases de données sous Windows

46. UTC_DATE(), Fonctions de dates et d'heures

47. UTC_TIME(), Fonctions de dates et d'heures

48. UTC_TIMESTAMP(), Fonctions de dates et d'heures

49. UTF-8, Jeux de caractères et Unicode

50. UTF8, Jeux de caractères et Unicode

51. utilisation

1. de MySQL, Pour quoi avons nous utilisé MySQL ?

52. UUID(), Fonctions diverses

V

1. valeurs par défaut, Limitations et inconvénients des choix conceptuels de MySQL

2. Valeurs par défaut, Syntaxe de INSERT

3. valid numbers

1. examples, Nombres

4. VARBINARY data type, Les types BINARY and VARBINARY

5. VARCHAR, Présentation des types de chaînes

1. size, Capacités des colonnes

6. VARCHAR data type, Les types chaînes

7. VARCHARACTER, Présentation des types de chaînes

8. variables

1. mysqld, Réglage des paramètres du serveur

2. server, Variables serveur système, Syntaxe de SHOW VARIABLES

3. status, Variables de statut du serveur, Syntaxe de SHOW STATUS

4. system, Variables serveur système, Syntaxe de SHOW VARIABLES

5. System, Variables système

6. user, Variables utilisateur

7. values, Variables serveur système

9. VARIANCE(), Fonctions avec GROUP BY

10. verbose

1. mysql option, mysql, l'outil en ligne de commande

11. version

1. choosing, Choisir votre version de MySQL

2. latest, Comment obtenir MySQL ?

3. mysql option, mysql, l'outil en ligne de commande

4. mysqlcc option, mysqlcc, MySQL Control Center

5. mysqld_multi option, mysqld_multi, un programme pour gérer plusieurs serveurs MySQL

12. VERSION(), Fonctions d'informations

13. vertical

1. mysql option, mysql, l'outil en ligne de commande

14. views, Les vues, Vues, Syntaxe de CREATE VIEW

1. updatable, Syntaxe de CREATE VIEW

15. VIEWS

1. INFORMATION_SCHEMA table, La table INFORMATION_SCHEMA VIEWS

16. virtual memory

1. problems while compiling, Problèmes de compilation ?

17. Visual Basic, Programs Known to Work With MyODBC

18. vérrouillage, Réglage du système, au moment de la compilation, et paramètres du démarrage

W

1. wait

1. mysql option, mysql, l'outil en ligne de commande

2. WEEK(), Fonctions de dates et d'heures

3. WEEKDAY(), Fonctions de dates et d'heures

4. WEEKOFYEAR(), Fonctions de dates et d'heures

5. Well-Known Binary format, Le format Well-Known Binary (WKB)

6. Well-Known Text format, Format Well-Known Text (WKT)

7. What is encryption, Introduction aux connexions sécurisées

8. What is X509/Certificate?, Introduction aux connexions sécurisées

9. WHERE, Comment MySQL optimise les clauses WHERE

1. with SHOW, La base de données d'informations INFORMATION_SCHEMA, Extensions à la commande SHOW

10. WHILE, Syntaxe WHILE

11. Wildcard character (%), Chaînes

12. Wildcard character (_), Chaînes

13. wildcards

1. and LIKE, Comment MySQL utilise les index

2. in mysql.columns_priv table, Contrôle d'accès, étape 2 : Vérification de la requête

3. in mysql.db table, Contrôle d'accès, étape 2 : Vérification de la requête

4. in mysql.host table, Contrôle d'accès, étape 2 : Vérification de la requête

5. in mysql.tables_priv table, Contrôle d'accès, étape 2 : Vérification de la requête

6. in mysql.user table, Contrôle d'accès, étape 1 : Vérification de la connexion

14. Windows, Support ODBC de MySQL

1. compiling on, Compiler les clients MySQL sous Windows

2. open issues, MySQL pour Windows face à MySQL pour Unix

3. upgrading, Mettre à jour MySQL sous Windows

4. versus Unix, MySQL pour Windows face à MySQL pour Unix

15. Within(), Fonctions qui testent les relations géométriques entre les formes

16. without-server option, Options habituelles de configure

17. WKB, Le format Well-Known Binary (WKB)

18. WKT, Format Well-Known Text (WKT)

19. Word, Programs Known to Work With MyODBC

20. wrappers

1. Eiffel, Couche MySQL pour Eiffel

21. write access

1. tmp, Problèmes d'exécution de mysql_install_db

22. write_buffer_size myisamchk variable, Options générales de myisamchk

X

1. X(), Fonctions d'analyse des Points

2. xml

1. mysql option, mysql, l'outil en ligne de commande

3. XOR

1. bitwise, Fonctions sur les bits

2. logical, Opérateurs logiques

Y

1. Y(), Fonctions d'analyse des Points

2. YEAR, Présentation des types de données temporels : dates et heures, Le type YEAR

3. Year 2000 compliance, Compatibilité an 2000

4. Year 2000 issues, An 2000 et les types date

5. YEAR(), Fonctions de dates et d'heures