Ce chapitre liste quelques problèmes et erreurs communes 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.
Lorsque vous faite face à un problème, la première chose à faire et de trouver quel programme / pièce de l'équipement pose ce problème :
kbd_mode -a.
top, ps, taskmanager, ou des programmes similaires,
pour voir quel programme utilise trop de ressources ou bloque la machine.
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 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 est-ce que vous pensez 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 :
top
Laissez le programme fonctionne un bout de temps, il se peut qu'il soit entrain de
traiter une tâche lourde.
mysqld qui pose problème, pouvez vous essayer un
mysqladmin -u root ping ou mysqladmin -u root processlist ?
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. See section 1.7.1.2 Poser des questions ou rapporter un bogue.
Cette section couvre les erreurs les plus fréquement rencontrées par les utilisateurs. Vous trouverez ici une description de ces erreurs et un moyen de les corriger.
Access denied
Voir section 4.2.6 Comment fonctionne le système de droits et plus particulièrement section 4.2.11 Causes des erreurs Access denied.
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 8 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 emis 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. |
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 examinant la date de mise en route. Si le problème
est que mysqld a crashé, vous devriez vous concentrer sur la résolution du problème.
Vous devez dans ce cas commencer par vérifier si emmètre la même requête fera à
nouveau crasher MySQL. See section A.4.1 Que faire si MySQL crashe 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=# (1M 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 emmétrez une grande requête ou qu'il aura à retourner de
grandes réponses !
Si vous voulez rapporter un bogue concernant ce problème, merci d'inclure les informations suivantes :
hostname.err. See section A.4.1 Que faire si MySQL crashe constamment ?.
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 ? See section D.1.6 Faire une batterie de tests lorsque vous faites face à un problème de table corrompue.
wait_timeout dans le serveur MySQL ?
mysqladmin variables vous donnera une réponse
mysqld avec --log et vérifié si la
requête apparaît bien dans le log ?
See section 1.7.1.2 Poser des questions ou rapporter un bogue.
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ée 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 connectez 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 utiliser 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. See section 2.4.2 Problèmes de démarrage du serveur MySQL.
Si un processus mysqld est actif, vous pouvez testerle 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.
mysqld utilises le package MIT-pthreads.
See section 2.2.5 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 pour vérifier la
connexion au serveur :
shell> mysqladmin -h `hostname` version
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 quelque part d'autre.
See section A.4.5 Comment protéger ou changer le fichier socket `/tmp/mysql.sock'.
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. See section A.4.5 Comment protéger ou changer le fichier socket `/tmp/mysql.sock'.
mysqld (par exemple, avec le script mysql_zap avant de pouvoir
démarrer un nouveau serveur MySQL. See section A.4.1 Que faire si MySQL crashe constamment ?.
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 :
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é.
mysqld sur la machine locale et vérifiez
le port TCP/IP de la configuration de mysqld (variable port) avec
mysqladmin variables.
mysqld n'est pas configuré avec l'option
--skip-networking.
Host '...' is blocked ErrorSi 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 (max_connect_errors)
tentatives de connexions à l'hôte 'hostname' qui ont été interrompus
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.
Par défaut, mysqld bloque le serveur après 10 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!
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 connexion 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. See section 4.5.6 Syntaxe de SHOW.
Le nombre maximal de connexion MySQL dépend de la qualité de la librairie des threads sur une plate-forme donnée. Linux et Solaris devraient être capables de supporter jusqu'à 500-1000 connexion simultanées, cela dépend évidemment de la quantité de RAM que vous avez et de ce que font les clients.
Some non-transactional changed tables couldn't be rolled back
Si vous obtenez l'erreur / avertissement : 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é dans la transaction
ne supportent pas les transactions. Ces tables non-transactionneles ne seront
pas affectées par la commande ROLLBACK.
Le cas le plus typique pour que cela arrive est que vous avez essayé de
créer une table d'nu type non supporté par votre binaire mysqld.
Si mysqld ne supporte pas un type de table (ou si le type de table
est désactivé par une option de démarrage), il créera une table avec le type
qui se rapproche le plus de celui que vous aviez choisi, probablement MyISAM.
Vous pouvez vérifier le type d'une table en faisant :
SHOW TABLE STATUS LIKE 'nom_de_table'. See section 4.5.6.2 SHOW TABLE STATUS.
Vous pouvez vérifier les extensions que votre binaire mysqld supporte en
faisant :
show variables like 'have_%'. See section 4.5.6.4 Syntaxe de SHOW VARIABLES.
Out of memorySi 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 simplememnt 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 solicittera moins le client (mais plus le serveur).
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 16M (à 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 2G).
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.
Il n'est pas dangereux d'augmenter cette valeur étant donné que la mémoire n'est alloué 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.
A 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'
See section 4.9.1 Le log d'erreurs.
Cela signifie qu'un problème est survenu :
mysql_close() avant de quitter.
wait_timeout ou
interactive_timeout secondes sans aucune requête.
See section 4.5.6.4 Syntaxe de SHOW VARIABLES.
See section 4.5.6.4 Syntaxe de SHOW VARIABLES.
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 :
connect_timeout secondes pour obtenir un
paquet de communication.
section 4.5.6.4 Syntaxe de SHOW VARIABLES
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 echoués / connexions interrompues :
max_allowed_packet est trop petit ou les requêtes ont besoin
de plus de mémoire que celle que vous avez alloué à mysqld.
See section A.2.8 Erreur Packet too large.
The table is fullIl y a différents cas où vous pouvez obtenir cette erreur :
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.
See section 5.5.6 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 physique MyISAM après qu'elles
n'aient dépassé tmp_table_size.
InnoDB et avez dépassé leur taille.
Dans ce cas, la solution est d'augmenter les tailles des tables.
ISAM ou MyISAM sur un système
d'exploitation qui ne supporte pas les fichiers de plus de 2G et vous
avez atteint cette limite dans le fichier de données ou d'index.
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 4G de données).
Vous pouvez obtenir la taille maximale des données / index en faisant :
SHOW TABLE STATUS FROM database LIKE 'nom_de_table';or using
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.
Can't create/write to fileSi 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 de 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 :
[mysqld] tmpdir=C:/temp
en supposant que le dossier `c:\\temp' existe. See section 4.1.2 Fichier d'options `my.cnf'.
Vérifiez aussi le code erreur que vous obtenez avec perror. Une autre
rasion peut être une erreur de disque saturé.
shell> perror 28 Error code 28: No space left on device
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.
Ignoring userSi vous obtenez l'erreur suivante :
Found wrong password for user: 'some_user@some_host'; ignoring user
cela signifie que lors du démarrage de mysqld ou lorsqu'il a
rechargé les tables de permissions, il 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 :
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 16 caractères. Si c'est le cas, vous
pouvez le corriger en exécutant le script scripts/add_long_password.
mysqld avec l'option --old-protocol.
Mettez à jour le mot de passe dans la table user ou redémarrez mysqld
avec --old-protocol.
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';
Table 'xxx' doesn't exist
Si vous obtenez l'erreur Table 'xxx' doesn't exist ou Can't
find file: 'xxx' (errno: 2), cela signifie qu'aucune table portant le nom
xxx n'existe dans la base de données courante.
Notez que comme MySQL utilise des dossiers et des fichiers pour stocker les bases de données et les tables, les noms sont sensibles à la casse ! (Sous Windows les noms ne sont pas sensibles à la casse, mais vous devez utiliser la même casse dans une même requête !)
Vous pouvez obtenir la liste des tables que vous avez dans la base de données
courante avec la commande SHOW TABLES. See section 4.5.6 Syntaxe de SHOW.
Can't initialize character set xxxSi vous obtenez l'erreur suivante :
MySQL Connection Failed: Can't initialize character set xxx
Cela signifie l'une des choses suivantes :
--with-charset=xxx
ou avec --with-extra-charsets=xxx.
See section 2.3.3 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 multi-octets. See section 4.6.1 Le jeu de caractères utilisé pour les données et le stockage.
mysqld et les fichiers de définition du jeu ne sont pas à l'endroit où le
client si attend.
Dans ce cas vous avez besoin de :
configure.
--character-sets-dir=chemin-vers-dossier-jeu-caractères.
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 de 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. See section 4.5.6.4 Syntaxe de SHOW VARIABLES.
La façon la plus facile de faire cela est d'ajouter cette option dans votre
fichiers d'options. See section 4.1.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.
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 !
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 -Lchemin-vers-la-librairie-mysql
-lmysqlclient last dans votre ligne de liaison.
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 de manuel de la fonction en question, pour les librairies 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 librairie est compilé sur un système qui n'est pas à 100% compatible avec le votre. Dans ce cas, vous devez obtenir la dernière distribution des sources de MySQL et compiler vous-mêmes. See section 2.3 Installer MySQL à partir des sources.
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 librairie mysqlclient ne peut être trouvée,
cela signifie que votre système n'arrive pas à trouver la librairie partagée
`libmysqlclient.so'.
La solution est de dire à votre système de chercher les librairies partagées là où la librairie est située avec l'une des méthodes suivantes :
LD_LIBRARY_PATH.
LD_LIBRARY.
ldconfig.
Un autre moyen de résoudre ce problème est de lier votre programme statiquement,
avec -static, ou en effaçant les librairies dynamiques de MySQL avant de
lier votre code. Dans le second cas vous devez vous assurer qu'aucun autre programme
n'utilise les librairies dynamiques !
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 :
mysqladmin shutdown).
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/datadirSi 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.
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.
user qui spécifie
le nom de l'utilisateur 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
A 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. A 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é des noms d'utilisateurs et des mots de passes 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.
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 faite, les nouveaux
dossiers seront crées en combinant UMASK et UMASK_DIR.
Par exemple, si vous voulez donner un accès de groupe à tout les nouveaux
dossiers, vous pouvez faire :
shell> UMASK_DIR=504 # = 770 en octal shell> export UMASK_DIR shell> /chemin/vers/safe_mysqld &
A 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.
See section E Variables d'environnement.
Toutes les versions de MySQL sont testées sur plusieurs plate-formes avant leur publication. Cela ne signifie pas qu'elles sont exemptées de bogues, cela signifie juste que si il y a des bogues, il y'en a très peu et sont durs à trouver. Si vous avez un problème, cela nous aidera toujours si vous essayez de trouver d'où vient exactement le crashage 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
`mysql-data-directory/`hostname`.err'. See section 4.9.1 Le log d'erreurs.
Plusieurs crashes 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 seul
les données sont écrites.)
Cela signifie que les données sont intègres même si mysqld crashe, puisque
le système d'exploitation s'assurera que les données non sorties du tampon ne sont
pas enregistrée 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 :
mysqld ou la machine au milieu d'une mise
à jour.
mysqld qui le termine au milieu d'une mise à jour.
mysqld avec les mêmes données sur un
système qui ne gère pas bien les vérrous de fichiers (normalement gérés par le démon
lockd) ou que vous le faites avec --skip-external-locking
mysqld à confusion.
ALTER TABLE
sur une copie réparée de la table !
Parce qu'il est très difficile de savoir pourquoi quelque chose crashe, 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 :
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.
See section 4 Administration du serveur.
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é.
See section 4.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 !
See section 1.7.1.3 Comment rapporter un bogue ou un problème.
fork_test.pl et fork2_test.pl.
--with-debug ou
--with-debug=full de configure puis recompilez.
See section D.1 Déboguer un serveur MySQL.
--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 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.)
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 status.
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.
mysqld à partir de gdb (ou d'un autre débogueur).
See section D.1.3 Déboguer mysqld sous gdb.
mysqld
a crashé à l'intérieur de gdb :
backtrace info local up info local up info localAvec gdb vous pouvez aussi savoir quels threads existent avec
info
threads et en prendre un avec thread #, où # est l'identifiant
du thread.
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érants aux corruptions !
Le code courant des lignes dynamiques est utilisé chez MySQL AB depuis au moins
3 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 !
Si vous n'avez jamais configuré un mot de passe root pour MySQL,
le serveur n'en demendera jamais un pour toutes les connexions de cet
utilisateur. Il est recommandé de toujours assigner un mot de passe à
chaque utilisateur. See section 4.2.2 Comment protéger MySQL contre les pirates.
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 :
mysqld en lui envoyant un kill (pas un
kill -9). L'identifiant du processus est stocké dans un fichier `.pid',
qui est normalement situé dans le dossier des bases de données de MySQL :
shell> kill `cat /dossier-donnees-mysql/hote.pid`Vous devez être l'utiliateur Unix
root ou l'utilisateur qui fait tourner
mysqld pour pouvoir le faire.
mysqld avec l'option --skip-grant-tables.
mysqladmin password :
shell> mysqladmin -u root password 'nouveaumotdepasse'
mysqld et le redémarrer normalement,
ou bien juste charger les tables de privilèges avec :
shell> mysqladmin -h hote flush-privileges
Vous pouvez aussi choisir le nouveau mot de passe en utilisant le client
mysql :
mysqld avec l'option --skip-grant-tables
comme décrit plus haut.
mysqld avec :
shell> mysql -u root mysql
mysql :
mysql> UPDATE user SET Password=PASSWORD('nouveaumotdepasse')
-> WHERE User='root';
mysql> FLUSH PRIVILEGES;
mysqld de façon normale.
Lorsqu'il n'y a plus d'espace disque, MySQL fait ce qui suit :
Pour contourner ce problème, vous pouvez effectuer les actions suivantes :
mysqladmin kill.
Le thread sera annulé la prochaine fois qu'il vérifiera le disque (dans 1 minute).
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 crashée (à part pour ALTER TABLE,
où l'ancienne table sera restaurée).
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' 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.
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.
Si vous avez un problème avec le fait que n'importe qui peut effacer le
fichier de socket de communication MySQL `/tmp/mysql.sock', vous pouvez,
dans la plupart des versions d'Unix, protéger votre système de fichiers `/tmp'
en lui assignant le bit sticky. Connectez vous en root et faite ce
qui suit :
shell> chmod +t /tmp
Cela protégera votre système de fichiers `/tmp' de sorte que les fichiers ne
pourront être effacés que par leurs propriétaires ou le super utilisateur (root).
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 :
/etc/my.cnf :
[client] socket=chemin-vers-fichier-socket [mysqld] socket=chemin-vers-fichier-socketSee section 4.1.2 Fichier d'options `my.cnf'.
safe_mysqld et à la plupart
des clients avec l'option --socket=chemin-vers-fichier-socket.
MYSQL_UNIX_PORT.
configure
--with-unix-socket-path=chemin-vers-fichier-socket. See section 2.3.3 Options habituelles de configure.
Vous pouvez vérifier que la socket fonctionne avec cette commande :
shell> mysqladmin --socket=/chemin/vers/socket version
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.
See section E Variables d'environnement.
Par défaut, les recherchez 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 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
là en tant que BINARY. See section 6.5.3 Syntaxe de CREATE TABLE.
Si vous utilisez des donneés 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.
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, il convertit donc
idate en une chaîne et effectue une comparaison de chaînes. Il 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 :
DATE et DATETIME
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.
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.
See section 6.4.9 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().
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é.
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 inclues
dans la partie GROUP BY tandis que HAVING est utilisé pour décider quelles
lignes du jeu de résultats doivent être utilisé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 :
SELECT) les lignes de la table principale en vous basant sur une
condition WHERE.
DELETE) les lignes de la table principale en vous basant sur la même
condition.
DELETE FROM table_liée WHERE colonne_liée IN (lignes_séléctionné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.
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 :
EXPLAIN et vérifiez si vous trouvez quelque chose
qui vous parait fausse. See section 5.2.1 Syntaxe de EXPLAIN (Obtenir des informations sur les SELECT).
WHERE :
LIMIT 10 dans la requête.
SELECT pour les colonnes qui auraient du trouver des lignes dans la
dernière table supprimée de la requête.
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.
See section A.5.7 Problèmes de comparaisons avec nombres à virgule flottante.
mysql test < query.sql montrant votre problème.
Vous pouvez créer un fichier de test avec mysqldump --quick base tables > query.sql.
Editez le fichier et supprimez quelques lignes d'insertions (s'il y'en a trop), et ajoutez
votre requête de séléction à la fin du fichier.
Vérifiez que vous avez encore le problème en faisant :
shell> mysqladmin create test2 shell> mysql test2 < query.sqlEnvoyez le fichier de test, en utilisant
mysqlbug, à mysql@lists.mysql.com.
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 correcte. Même si les cinq premiers enregistrements ne devraient pas passer le test à 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 'correctes' en multipliant les deux arguments par 1, l'exemple suivant illustre cela.
ATTENTION : NE FAITES JAMAIS CONFIANCE A 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 sur la machine en particulier où 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 nombre à virgule flottante est d'en premier lieu décider du degré de tolérance voulu entre les nombres puis d'effectuer la comparaison selon le nombre de tolérance. Par exemple, si nous décidons que les nombres à virgule flottante sont considérés comme égaux si 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 |
+------+-------+-------+
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
clef dupliquée, alors la cause est soit que le nouveau jeu de caractères
interprète deux clefs à la même valeur ou que la table est corrompue,
au quel 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 crashé 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, déplacez-vous dans le dossier
des données MySQL et effacez tout 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 :
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 renommage au niveau système devrait restaurer vos données.
Le but de SQL est de séparer l'application du format de stockage des données. Vous devriez toujours spécifier l'ordre dans lequel vous voulez récupérer vos données. Par exemple :
SELECT nom_colonne1, nom_colonne2, nom_colonne3 FROM nom_de_table;
retournera les colonnes dans l'ordre nom_colonne1, nom_colonne2,
nom_colonne3, tandis que :
SELECT nom_colonne1, nom_colonne3, nom_colonne2 FROM nom_de_table;
retournera les colonnes dans l'ordre nom_colonne1, nom_colonne3,
nom_colonne2.
Vous ne devez jamais, dans une application, utiliser SELECT *
et récupérer l'ordre des colonnes en vous basant sur leurs positions, car
l'ordre dans lequel elles sont retournées ne peut-être garantit tout le temps.
Une simple modification dans votre base de données peut endommager gravement
vos applications.
Si vous voulez changer l'ordre de vos colonnes, vous pouvez faire ce qui suit :
INSERT INTO nouvelle_table SELECT champs-dans-nouvel-ordre FROM ancienne_table.
ancienne_table.
ALTER TABLE nouvelle_table RENAME ancienne_table.
Voici une liste des limitations avec TEMPORARY TABLES.
HEAP, ISAM,
MyISAM ou InnoDB.
mysql> SELECT * FROM temporary_table, temporary_table AS t2;Nous allons corriger ce qui précède dans la version 4.0.
RENAME sur une table TEMPORARY.
Notez que ALTER TABLE nom_origine RENAME nouveau_nom fonctionne !
Nous allons corriger ce qui précède dans la version 4.0.
Go to the first, previous, next, last section, table of contents.