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:
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:
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
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.
(4.0)
© Diciembre de 2003 Salvador Pozo, salvador@conclase.net