1.8.7 Erreurs connues, et limitations de MySQL
1.8 Quels standards respecte MySQL?
1 Informations générales
Manuel de Référence MySQL 4.1 : Version Française
. Erreurs connues en 3.23 et corrigées ultérieurement . Erreurs de la version 4.0, corrigées plus tard ->Bugs connus / limitations de MySQL
|
1.8.7.3 Bugs 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
a 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édent 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 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.
-
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é 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 fait 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ées 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, le maître utiliser
InnoDB
et 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 base,
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éterministe, pour
s'assure 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
. L'utilitaire binaire
mysqlbinlog
.
-
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 table 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.
-
A cause de la méthode de stockage des tables de définitions 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. 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
, 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 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 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
à 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.
Installer MySQL à partir des sources .
Port vers d'autres systèmes .
|