mysql.h


INSERT DELAYED

INSERT DELAYED ...

La opción DELAYED para la sentencia INSERT es una extensión de MySQL al SQL estándar que es muy práctica si se tienen clientes que no pueden esperar a que el INSERT se complete. Este es un problema frecuente cuando se usa MySQL y además se ejecutan periódicamente sentencias SELECT y UPDATE que necesitan mucho tiempo para completarse. DELAYED se añadió en MySQL 3.22.15.

Cuando un cliente usa INSERT DELAYED, obtiene una confirmación por parte del servidor de forma inmediata, y la fila se almacena en una cola para ser insertada cuando la tabla no esté en uso por ningún otro proceso.

Otra gran ventaja de usar INSERT DELAYED es que las inserciones desde muchos clientes son ligadas juntas y escritas en un bloque. Esto es mucho más rápido que hacer muchas inserciones separdas.

Existen algunas limitaciones en el uso de DELAYED:

  • INSERT DELAYED funciona sólo con tabls MyISAM y ISAM. Para tablas MyISAM, si no existen bloques libres en el interior del fichero de datos, se soportan sentencias SELECT e INSERT concurrentes. Bajo esas circunstancias, raramente será necesario el uso de INSERT DELAYED con MyISAM.
  • INSERT DELAYED debe ser usado sólo con sentecias INSERT que especifiquen listas de valores. Esto está forzado desde MySQL 4.0.18. El servidor ignora el DELAYED para sentencias INSERT DELAYED ... SELECT.
  • El servidor también ignora el DELAYED para sentencias INSERT DELAYED ... ON DUPLICATE UPDATE.
  • Ya que la sentencia regresa inmediatamente, antes de que las filas sean insertadas, no se puede usar LAST_INSERT_ID() para obtener el valor AUTO_INCREMENT que la sentencia generará.
  • Las filas DELAYED no son visibles para sentencias SELECT hasta que hayan sido insertadas.

Hay que tener en cuenta que las filas actualmente en la cola se almacenan sólo en memoria hasta que sean insertadas en la tabla. Eso significa que si se fuerza la terminación de mysqld (por ejemplo, con kill -9) o si mysqld termina de forma inesperada, cualquier fila en la cola que no haya sido escrita en disco se perderá.

A continuación se describe con detalle qué ocurre cuando se usa la opción DELAYED con INSERT o REPLACE. En esta descripción, el "proceso" es el que recibe una sentencia INSERT DELAYED y el "manipulador" es el proceso que manipula todas las rentencias INSERT DELAYED para una tabla concreta.

  • Cuando un proceso ejecuta una sentencia DELAYED para una tabla, se crea un proceso manipulador para procesar todas las sentencias DELAYED para esa tabla, si es que no existe ya tal manipulador.
  • El proceso verifica si el manipulador ha adquirido ya un bloqueo DELAYED; si no lo ha hecho, le indica al proces manipulador que lo haga. El bloqueo DELAYED puede ser obtenido incluso si otro proceso tiene un bloque READ o WRITE sobre la tabla. No obstante, el manipulador esperará a que terminen todos los bloqueos ALTER TABLE y FLUSH TABLES para asegurarse de que la estructura de la tabla esté lista para usarse.
  • El proceso ejecuta la sentencia INSERT, pero en lugar de escribir la fila en la tabla, coloca una copia de la fila final en una cola que es manejada por el proceso manipulador. Cualquier error de sintaxis se notifica al proceso y enviado al proceso cliente.
  • El cliente no puede obtener el número de registros duplicados desde el servidor o el valor AUTO_INCREMENT de la fila resultante, porque la sentencia INSERT regresa antes de que la operación de inserción haya sido completada. (Si se usa el API C, la función mysql_info() tampoco devuelve nada con significado, por la misma razón.)
  • El diario binario se actualiza por el proceso manipulador cuando la fila es insertada en la tabla. En caso de inserciones de varias filas, el diario binario se acutaliza cuando la primera fila es insertada.
  • Después de cada escritura de every delayed_insert_limit filas, el manipulador comprueba si hay pendiente alguna sentencia SELECT. Si es así, permite su ejecución antes de continuar.
  • Cuando el manipulador no tiene más filas en su cola, desbloquea la tabla. Si no se reciben nuevas sentencias INSERT DELAYED en el intervalo de delayed_insert_timeout segundos, el manipulador termina.
  • Si hay más de delayed_queue_size filas pendientes en una cola de manipulador, el proceso que ha lanzado el INSERT DELAYED espera hasta que haya espacio en la cola. Esto se hace para asegurarse que el servidor mysqld no use toda la memoria para la cola de inserciones retrasadas.
  • El proceso manipulador aparece en la lista de procesos MySQL con delayed_insert en la columna 'Command'. Puede ser terminado si se ejecuta la sentencia FLUSH TABLES o con KILL thread_id. Sin embargo, antes de salir, primero almacenará todas las filas en la tabla. Durante este tiempo no aceptará ninguna nueva sentencia INSERT desde otro proceso. Si se ejecuta una sentencia INSERT DELAYED después, se creará un nuevo proceso manipulador. Esto significa que las sentencias INSERT DELAYED tienen mayor prioridad que las sentencias INSERT normales si existe un manipulador de INSERT DELAYED en ejecución. Otras sentencias de actualización tendrán que esperar a que la cola de INSERT DELAYED se vacíe, alguien finalice el proceso manipulador (con KILL thread_id), o alguien ejecute FLUSH TABLES.
  • Las siguientes variables de estado proporcionan información sobre sentencias INSERT DELAYED:
    Variable de estado Significado
    Delayed_insert_threads Número de procesos manipuladores
    Delayed_writes Número de filas escritas con INSERT DELAYED
    Not_flushed_delayed_rows Número de filas esperando a ser escritas
  • Se pueden ver estas variables mediante una sentencia SHOW STATUS o ejecutando un comando mysqladmin extended-status.

Hay que tener en cuenta que INSERT DELAYED es más lenta que un INSERT normal si la tabla no está en uso. Hay algo de trabajo adicional para el servidor al manipular un proceso separado para cada tabla para la que haya inserciones de filas retrasadas. Esto significa que sólo se debe usar INSERT DELAYED cuando se esté realmente seguro de que es necesario.