INSERT DELAYED ...
La opción DELAYED
para el comando
INSERT
es una extensión de MySQL del
estándar SQL muy útil si tiene clientes que no pueden
esperar a que se complete el INSERT
. Este
es un problema común cuando usa MySQL para loguear y
periódicamente ejecuta comandos SELECT
y
UPDATE
que tardan mucho tiempo en
completarse.
Cuando un cliente usa INSERT DELAYED
,
obtiene un ok del servidor una vez, y el registro se encola
para insertarse cuando la tabla no está en uso por otro
flujo.
Otro beneficio de usar INSERT DELAYED
es
que las inserciones desde varios clientes se tratan juntas y
se escriben en un bloque. Esto es mucho más rápido que
realizar inserciones separadas.
Hay algunas restricciones al uso de
DELAYED
:
En MySQL 5.0, INSERT DELAYED
funciona
sólo con tablas MyISAM
y
MEMORY
. Para tablas
MyISAM
, si no hay bloques libres en
medio del fichero de datos, se soportan comandos
SELECT
y INSERT
concurrentes. Bajo estas circunstáncias, muy raramente
necesitará usar INSERT DELAYED
con
MyISAM
. Consulte
Sección 14.1, “El motor de almacenamiento MyISAM
” y
Sección 14.3, “El motor de almacenamiento MEMORY
(HEAP
)”.
En MySQL 5.0, INSERT DELAYED
debe
usarse sólo para comandos INSERT
que
especifiquen una lista de valores. El servidor ignora
DELAYED
para comandos INSERT
DELAYED ... SELECT
.
El servidor ignora DELAYED
para
comandos INSERT DELAYED ... ON DUPLICATE
UPDATE
.
Debido a que el comando retorna inmediatamente antes que
los registros se inserten, no puede usar
LAST_INSERT_ID()
para obtener el valor
AUTO_INCREMENT
que el comando genera.
Los registros DELAYED
no son visibles
por los comandos SELECT
hasta que se
hayan insertado realmente.
DELAYED
se ignora en la replicación de
esclavos porque puede causar que el esclavo tenga
distintos datos que el maestro.
Tenga en cuenta que los registros encolados se tratan sólo en
memoria hasta que se insertan en la tabla. Esto significa que
si termina mysqld forzadamente (por
ejemplo, con kill -9
) o si
mysqld muere inesperadamente, cualquier
registro encolado que no se escriba en disco se pierde.
A continuación se describe en detalle qué ocurre cuando usa
la opción DELAYED
con
INSERT
o REPLACE
. En
esta descriión, el “flujo” es el flujo que
recibe un comando INSERT DELAYED
y
“handler” es el flujo que trata todos los
comandos INSERT DELAYED
para una tabla
particular.
Cuando un flujo ejecuta un comando
DELAYED
para una tabla, un flujo
handler se crea para procesar todos los comandos
DELAYED
para la tabla, si tal handler
no existía préviamente.
El flujo chequea si el handler ha adquirido préviamente
un bloqueo DELAYED
; si no, le dice al
flujo handler que lo haga. El bloqueo
DELAYED
puede obtenerse incluso si
otros flujos tienen el bloqueo READ
o
WRITE
en la tabla. Sin embargo, el
handler espera a todos los bloqueos ALTER
TABLE
o FLUSH TABLES
para
asegurar que la estructura de tabla está actualizada.
El flujo ejecuta el comando INSERT
,
pero en lugar de escribir el registro en la tabla, pone
una copia del registro final en una cola administrada por
el flujo handler. Cualquier error de sintaxis es detectado
por el flujo y se reporta al programa cliente.
El cliente no puede obtener del servidor el número de
registros duplicados o el valor
AUTO_INCREMENT
del registro resultante,
ya que INSERT
retorna antes que se
complete la operación de inserción. (Si usa la API C, la
función mysql_info()
no retorna nada
inteligible por la misma razón.)
El log binario se actualiza por parte del flujo handler cuando el registro se inserta en la tabla. En caso de inserciones de múltiples registros, el log binario se actualiza cuando el primer registro se inserta.
Tras cada delayed_insert_limit
los
registros se escriben, el handler chequea si algún
comando SELECT
todavía está
pendiente. Si es así, les permite ejecutarse antes de
continuar.
Cuando el handler no tiene más registros en su cola, la
tabla se desbloquea. Si no se reciben nuevos comandos
INSERT DELAYED
en
delayed_insert_timeout
segundos, el
handler termina.
Si más de delayed_queue_size
registros
están pendientes en una cola de handler específica, el
flujo que pida el INSERT DELAYED
espera
hasta que haya espacio en la cola. Esto se hace para
asegurar que mysqld no usa toda la
memoria para la cola de memoria retrasada.
El flujo handler se muestra en l lista de procesos MySQL
con delayed_insert
en la columna
Command
. Si muere si ejecuta un
comando FLUSH TABLES
o puede matarlo
con KILL thread_id
. Sin embargo, antes
de salir, primero almacena todos los registros encolados
en la tabla. Durante esta operación no acepta ningún
nuevo comando INSERT
de otros flujos.
Si ejecuta un comando INSERT DELAYED
a
continuación, se crea un nuevo flujo handler.
Tenga en cuenta que esto significa que comandos
INSERT DELAYED
tienen mayor prioridad
que comandos INSERT
normales si hay un
handler INSERT DELAYED
en ejecución.
Otros comandos de actualización tienen que esperar hast
que la cola INSERT DELAYED
está
vacía, alguien termine el flujo handler (con
KILL thread_id
), o alguien ejecute un
FLUSH TABLES
.
Las siguientes variables de estado proporcionan
información acerca de comandos INSERT
DELAYED
:
Variable de estado | Significado |
Delayed_insert_threads |
Número de flujos handler |
Delayed_writes |
Número de registros escritos con INSERT DELAYED
|
Not_flushed_delayed_rows |
Número de registros esperando a ser escritos |
Puede ver estas variables ejecutando un comando
SHOW STATUS
o mysqladmin
extended-status.
Tenga en cuenta que INSERT DELAYED
es más
lento que un INSERT
normal si la tabla no
está en uso. También hay una sobrecarga adicional para el
servidor debido a que tiene que tratar un flujo separado para
cada tabla en que haya registros retardados. Esto significa
que debe usar INSERT DELAYED
sólo cuando
esté realmente seguro que lo necesita.
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.