mysql.h


LOCK TABLES, UNLOCK TABLES

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
            [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES

LOCK TABLES bloquea tablas para el hilo actual. UNLOCK TABLES libera cualquier bloqueo para el hilo actual. Todas las tablas bloqueadas por el hilo actual serán implícitamente desbloqueadas cuando el hilo realize otro LOCK TABLES, o cuando la conexión con el servidor se cierre.

Para usar LOCK TABLES en MySQL 4.0.2 se necesita el privilegio global LOCK TABLES y un privilegio SELECT en las tablas involucradas. En MySQL 3.23 se necesitan los privilegios SELECT, INSERT, DELETE y UPDATE para las tablas.

El principal motivo para usar LOCK TABLES es para la emulación de transacciones o para obtener mayor velocidad en la actualización de tablas. Esto se explica con más detalle más tarde.

Si el hilo obtiene un bloqueo READ en la tabla, ese hilo (y todos los demás) sólo pueden leer de la tabla. Si obtiene un bloqueo WRITE, entonce sólo el hilo que tiene el bloqueo puede leer de o escribie en la tabla. El resto de los hilos serán bloqueados.

La diferencia entre READ LOCAL y READ es que READ LOCAL permite ejecutar sentencias INSERT no conflictivas mientras el bloqueo esté activo. Esto no podrá ser usado si se van a manipular los ficheros de la base de datos fuera de MySQL mientras se mantiene el bloqueo.

Cuando se usa LOCK TABLES, se deben bloquear todas las tablas que se vayan a usar y se debe usar el mismo alias que se vaya a usar en las consultas. Si se está usando una tabla muchas veces en una consulta (con alias), se debe tener un bloqueo para cada alias.

El bloqueo WRITE normalmente tiene mayor prioridad que el bloqueo READ, para asegurar que las actualizaciones se procesan tan más pronto como sea posible. Esto significa que si un hilo obtiene un bloqueo READ y después otro hilo requiere un bloqueo WRITE, subsiguientes peticiones de bloqueos READ esperarán hasta que el hilo que solicitó el bloqueo WRITE lo obtenga y lo libere. Se puede usar el bloqueo LOW_PRIORITY WRITE para permitir a otros hilos obtener bloqueos READ mientras el hilo espera al bloqueo WRITE. Sólo se debe usar el bloqueo LOW_PRIORITY WRITE si se está seguro de que existirá un tiempo en el que no habrá hilos que pidan un bloqueo READ.

LOCK TABLES trabaja del modo siguiente:

  1. Ordena todas las tablas a bloquear en un orden interno definido (desde el punto de vista del usuario el orden es indefinido).
  2. Si una tabla está bloqueada para lectura y escritura, pone el bloqueo de escritura antes que el de lectura.
  3. Bloquea una tabla cada vez hasta que el hilo obtenga el bloqueo para todas las tablas.

Esta política asegura que el bloqueo de tabla está libre de puntos muertos. Sin embargo hay otras cosas a tener en cuenta con este esquema:

Si se está usando un bloqueo LOW_PRIORITY WRITE para una tabla, sólo significa que MySQL esperará para este bloqueo particular hasta que no existan hilos que quieran un bloqueo READ. Cuando el hilo ha obtenido el bloqueo WRITE y está esperando para obtener el bloqueo para la siguiente tabla en la lista de tablas a bloquear, el resto de los hilos esperarán a que el bloqueo WRITE se libered. Si esto se convierte en un problema serio para una aplicación, se debe considerar la conversión de algunas tablas a tablas de transacción segura.

Se puede matar un hilo de forma segura cuando está esperando un bloqueo de tabla usando KILL.

No se debe bloquear ninguna tabla para la que se esté usando INSERT DELAYED, porque en ese caso INSERT se ejecuta en un hilo separado.

Normalmente, no se deben bloquear tablas, ya que todas las sentencias UPDATE simples son atómicas; ningún otro hilo puede interferir con otro que esté ejecutando actualmente una sentecia SQL. Hay unos pocos casos en los que puede ser necesario bloquear tablas:

  • Si se van a realizar muchas operaciones en un puñado de tablas, es mucho más rápido bloquear las tablas que se van a usar. La desventaja es, por supuesto, que ningún hilo puede actualizar una tabla bloqueada para lectura (incluyendo aquel que tiene el bloqueo) y ningún hilo puede leer una tabla bloqueada para escritura salvo aquella que tiene el bloqueo. El motivo por el que algunas cosas son más rápidas con LOCK TABLES es que MySQL no vuelca en disco el caché de claves para las tablas bloqueadas hasta que se llama a UNLOCK TABLES (normalmente, el caché de claves se excribe en disco después de cada sentencia SQL). Esto acelera la inserción, actualización o borrado en tablas MyISAM.
  • Si se usa un motor de almacenamiento en MySQL que no soporte transacciones, se debe usar LOCK TABLES si se quiere asegurar que ningún otro hilo entra entre una sentencia SELECT y una UPDATE. Esl siguiente ejemplo require LOCK TABLES para que se ejecute de forma segura:
    mysql> LOCK TABLES trans READ, customer WRITE;
    mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
    mysql> UPDATE customer SET total_value=sum_from_previous_statement
        ->        WHERE customer_id=some_id;
    mysql> UNLOCK TABLES;
    Sin LOCK TABLES, hay una oportunidad de que otro hilo pueda insertar una nueva fila en la tabla "trans" entre la ejecución de las sentencias SELECT y UPDATE.

Usando actualizaciones graduales (UPDATE customer SET value=value+new_value) o la función LAST_INSERT_ID, se puede evitar el uso de LOCK TABLES en muchos casos.

También se pueden resolver algunos casos usando las funciones de bloqueo a nivel de ususario GET_LOCK y RELEASE_LOCK. Estos bloqueos se guardan en una tabla hash en el servidor u se implementan mediante pthread_mutex_lock() y pthread_mutex_unlock() para mayor velocidad.

Se pueden bloquear todas las tablas en todas las bases de datoscon bloqueo de lectura con el comando FLUSH TABLES WITH READ LOCK. Este es un modo muy conveniente para hacer copias de seguridad si se poseer un sistema de ficheros, como Veritas, que puede hacer instantaneas regularmente.

NOTA: LOCK TABLES no es seguro a nivel de transacción y realizará implícitamente cualquier transacción activa antes de intentar bloquear las tablas.