LOCK

LOCK — bloquear una tabla

Synopsis

LOCK [ TABLE ] [ ONLY ] nombre [ * ] [, ...] [ IN modo_bloqueo MODE ] [ NOWAIT ]

donde modo_bloqueo es uno de:

    ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
    | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE

Descripción

LOCK TABLE obtiene un bloqueo a nivel de tabla, esperando si es necesario a que se liberen los bloqueos en conflicto. Si NOWAIT is especifica, LOCK TABLE no espera para adquirir el bloqueo deseado: si no se puede adquirir de inmediato, el comando se aborta y se emite un error. Una vez obtenido, el bloqueo se mantiene durante el resto de la transacción actual. (No existe el comando UNLOCK TABLE; los bloqueos siempre se liberan al final de la transacción).

Cuando se bloquea una vista, todas las relaciones que aparecen en la consulta de definición de la vista también se bloquean de forma recursiva con el mismo modo de bloqueo.

Al adquirir bloqueos automáticamente para comandos que hacen referencia a tablas, PostgreSQL siempre utiliza el modo de bloqueo menos restrictivo posible. LOCK TABLE se utiliza en los casos en que se pueda necesitar un bloqueo más restrictivo. Por ejemplo, supón que una aplicación ejecuta una transacción en el nivel de aislamiento READ COMMITTED y necesita garantizar que los datos de una tabla permanezcan estables durante la transacción. Para lograr esto, podrías obtener el modo de bloqueo SHARE sobre la tabla antes de realizar la consulta. Esto evitará cambios de datos concurrentes y garantizará que las lecturas posteriores de la tabla vean una vista de datos estable de los datos confirmados, porque el modo de bloqueo SHARE entra en conflicto con el bloqueo ROW EXCLUSIVE adquirido por los escritores, y tu sentencia LOCK TABLE nombre IN SHARE MODE esperará hasta que cualquier poseedor concurrente de bloqueos en modo ROW EXCLUSIVE confirme o deshaga su transacción. Por lo tanto, una vez obtenido el bloqueo, no hay escrituras no confirmadas pendientes; además, ninguna puede comenzar hasta que liberes el bloqueo.

Para lograr un efecto similar cuando se ejecuta una transacción en el nivel de aislamiento REPEATABLE READ o SERIALIZABLE, debes ejecutar la sentencia LOCK TABLE antes de ejecutar cualquier SELECT o sentencia de modificación de datos. La vista de datos de una transacción REPEATABLE READ o SERIALIZABLE se congelará cuando comience su primer SELECT o sentencia de modificación de datos. Un LOCK TABLE posterior en la transacción seguirá evitando escrituras concurrentes, pero no garantizará que lo que lee la transacción corresponda a los últimos valores confirmados.

Si una transacción de este tipo va a cambiar los datos en la tabla, entonces debería usar el modo de bloqueo SHARE ROW EXCLUSIVE en lugar del modo SHARE. Esto asegura que solo se ejecute una transacción de este tipo a la vez. Sin esto, es posible un bloqueo mutuo (deadlock): dos transacciones podrían adquirir el modo SHARE, y luego no poder adquirir también el modo ROW EXCLUSIVE para realizar realmente sus actualizaciones. (Ten en cuenta que los propios bloqueos de una transacción nunca entran en conflicto, por lo que una transacción puede adquirir el modo ROW EXCLUSIVE cuando posee el modo SHARE, pero no si alguien más posee el modo SHARE). Para evitar bloqueos mutuos, asegúrate de que todas las transacciones adquieran bloqueos en los mismos objetos en el mismo orden, y si hay múltiples modos de bloqueo involucrados para un solo objeto, las transacciones siempre deben adquirir primero el modo más restrictivo.

Se puede encontrar más información sobre los modos de bloqueo y las estrategias de bloqueo en la Section 13.3.

Parámetros

nombre

El nombre (opcionalmente calificado por esquema) de una tabla existente para bloquear. Si se especifica ONLY antes del nombre de la tabla, solo se bloquea esa tabla. Si no se especifica ONLY, se bloquea la tabla y todas sus tablas descendientes (si las hay). Opcionalmente, se puede especificar * después del nombre de la tabla para indicar explícitamente que se incluyen las tablas descendientes.

El comando LOCK TABLE a, b; es equivalente a LOCK TABLE a; LOCK TABLE b;. Las tablas se bloquean una por una en el orden especificado en el comando LOCK TABLE.

modo_bloqueo

El modo de bloqueo especifica con qué bloqueos entra en conflicto este bloqueo. Los modos de bloqueo se describen en la Section 13.3.

Si no se especifica ningún modo de bloqueo, se utiliza ACCESS EXCLUSIVE, el modo más restrictivo.

NOWAIT

Especifica que LOCK TABLE no debe esperar a que se liberen los bloqueos en conflicto: si el/los bloqueo(s) especificado(s) no se pueden adquirir de inmediato sin esperar, la transacción se aborta.

Notas

Para bloquear una tabla, el usuario debe tener el privilegio adecuado para el modo_bloqueo especificado. Si el usuario tiene privilegios MAINTAIN, UPDATE, DELETE o TRUNCATE en la tabla, se permite cualquier modo_bloqueo. Si el usuario tiene privilegios INSERT en la tabla, se permite ROW EXCLUSIVE MODE (o un modo de menor conflicto como se describe en la Section 13.3). Si un usuario tiene privilegios SELECT en la tabla, se permite ACCESS SHARE MODE.

El usuario que realiza el bloqueo en la vista debe tener el privilegio correspondiente sobre ella. Además, por omisión, el propietario de la vista debe tener los privilegios pertinentes en las relaciones base subyacentes, mientras que el usuario que realiza el bloqueo no necesita ningún permiso en las relaciones base subyacentes. Sin embargo, si la vista tiene security_invoker establecido en true (consulta la CREATE VIEW), el usuario que realiza el bloqueo, en lugar del propietario de la vista, debe tener los privilegios correspondientes en las relaciones base subyacentes.

LOCK TABLE es inútil fuera de un bloque de transacción: el bloqueo se mantendría solo hasta la finalización de la sentencia. Por lo tanto, PostgreSQL informa un error si se utiliza LOCK fuera de un bloque de transacción. Usa BEGIN y COMMIT (o ROLLBACK) para definir un bloque de transacción.

LOCK TABLE solo se ocupa de los bloqueos a nivel de tabla, por lo que los nombres de los modos que involucran ROW son todos denominaciones erróneas. Estos nombres de modos generalmente deben leerse como una indicación de la intención del usuario de adquirir bloqueos a nivel de fila dentro de la tabla bloqueada. Además, el modo ROW EXCLUSIVE es un bloqueo de tabla que se puede compartir. Ten en cuenta que todos los modos de bloqueo tienen una semántica idéntica en lo que respecta a LOCK TABLE, difiriendo solo en las reglas sobre qué modos entran en conflicto con cuáles. Para obtener información sobre cómo adquirir un bloqueo a nivel de fila real, consulta la Section 13.3.2 y la The Locking Clause en la documentación de SELECT.

Ejemplos

Obtener un bloqueo SHARE en una tabla de clave primaria cuando se van a realizar inserciones en una tabla de clave foránea:

BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
    WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- Hacer ROLLBACK si no se devolvió el registro
INSERT INTO films_user_comments VALUES
    (_id_, 'GREAT! I was waiting for it for so long!');
COMMIT WORK;

Tomar un bloqueo SHARE ROW EXCLUSIVE en una tabla de clave primaria cuando se va a realizar una operación de eliminación:

BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
    (SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;

Compatibilidad

No existe LOCK TABLE en el estándar SQL, el cual en su lugar utiliza SET TRANSACTION para especificar los niveles de concurrencia en las transacciones. PostgreSQL también admite eso; consulta la SET TRANSACTION para obtener detalles.

A excepción de los modos de bloqueo ACCESS SHARE, ACCESS EXCLUSIVE, y SHARE UPDATE EXCLUSIVE, los modos de bloqueo de PostgreSQL y la sintaxis de LOCK TABLE son compatibles con los presentes en Oracle.