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 aquitement, 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és, et écrits d'un
seul bloc. C'est beaucoup plus rapide que de faire des
insertions séparés.
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
. See
Section 14.1, « Le moteur de tables MyISAM
».
INSERT DELAYED
doit être utilisé
uniquement avec les commandes INSERT
qui spécifie une liste de valeur. 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ére, 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'elle 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
ans ``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 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 avertit 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 modification 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és.
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!
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.