1.7 Quels standards respecte MySQL?
1 Informations générales
Manuel de Référence MySQL 4.1 : Version Française
. Quels standards suit MySQL ? . Exécuter MySQL en mode ANSI . Extensions de MySQL à la norme ANSI SQL92 . Différences de MySQL avec ANSI SQL92 ->Erreurs connues et problèmes de conceptions de MySQL
|
1.7.5 Erreurs connues et problèmes de conceptions de MySQL
Les problèmes suivants sont connus, et sont en tête de liste pour
être corrigés :
-
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
|
-
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 court 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.
Les problèmes suivants sont connus et seront corrigés en leur temps :
-
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. Remarques sur 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înes, hormis les
BLOB
et
TEXT
,
voient automatiquement leurs caractères blancs finaux 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
extensivement, vous devriez éditer
safe_mysqld
pour loger 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 faite 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 colonnes 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 ou 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 pas 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
.
-
Les valeurs négatives passées à
LIMIT
sont traitées comme des valeurs
positives.
-
Si vous utilisez la commande
ALTER TABLE
pour ajouter un index de type
UNIQUE
à un 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.
|