LOCK [ TABLE ] name LOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE LOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE |
El nombre de una tabla existente para bloquear.
A este modo de bloqueo se accede automáticamente sobre tablas que estan siendo consultadas. Postgres libera automáticamente los bloqueos accedidos ACCESS SHARE despues de que se haya hecho la sentencia. |
Este es el modo de bloqueo menos restrictivo el cual entra en conflicto sólo con el modo ACCESS EXCLUSIVE . Se pretende proteger una tabla que está siendo consultada de sentencias concurrentes ALTER TABLE, DROP TABLE y VACUUM sobre la misma tabla.
Se accede automáticamente por cualquier declaración SELECT FOR UPDATE. |
Conflictos con los modos de bloqueo EXCLUSIVE y ACCESS EXCLUSIVE.
Se accede automáticamente por cualquier sentencia UPDATE, DELETE, INSERT. |
Conflictos con los modos SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE ACCESS EXCLUSIVE. Generalmente significa que una transacción actualiza o inserta algunas tuplas en una tabla.
Se accede automáticamente por cualquier sentencia CREATE INDEX |
Conflictos con los modos ROW EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE y ACCESS EXCLUSIVE . Este modo protege una tabla contra actualizaciones concurrentes.
Conflictos con los modos ROW EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE y ACCESS EXCLUSIVE. Este modo es más restrictivo que el modo SHARE debido a que sólo puede soportar este bloqueo una transacción por vez .
Conflictos con los modos ROW SHARE, ROW EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE y ACCESS EXCLUSIVE modes. Este modo es aún más restrictivo que ése de SHARE ROW EXCLUSIVE; bloquea todas las consultas concurrentes SELECT FOR UPDATE .
Se accede automáticamente por las sentencias ALTER TABLE, DROP TABLE, VACUUM . |
Este es el modo de bloqueo más restrictivo y es incompatible con todos los demás modos de bloqueo y protege una tabla bloqueada de cualquier otra operación concurrente.
Este modo de bloqueo se accede también por un LOCK TABLE sin cualificar. (i.e. el comando sin una opción de bloqueo explícita). |
Postgres siempre usa el modo de bloqueo menos restrictivo cuando le es posible. LOCK TABLE toma medidas para cuando se pueda necesitar un modo de bloqueo mas restrictivo.
Por ejemplo, una aplicación ejecuta una transacción en el nivel de aislamiento READ COMMITTED y necesita asegurar la existencia de datos en una tabla para la duracion de la transacción. Para ello tú podrías usar el modo de bloqueo SHARE sobre la tabla antes de la consulta. Esto protegerá los datos de cambios concurrentes y proporcionará cualquier otra operación de escritura sobre la tabla con datos en su verdadero estado actual, porque el modo de bloqueo SHARE es incompatible con cualquier ROW EXCLUSIVE accedido por los que esriben, y LOCK TABLE "tabla" en sentencia IN SHARE MODE esperará hasta que se produzca o se "baje" cualquier operación de escritura concurrente.
Para leer datos en su verdadero estado actual cuando ejecutas una transacción en el nivel de aislamiento SERIALIZABLE tienes que ejecutar una declaración LOCK TABLE antes de la ejecución de cualquier sentencia DML, cuando la transacción define qué cambios concurrentes serán visibles por ellos mismos. |
Además de los requerimientos precedentes, si una transacción va a cambiar datos en una tabla entonces se debería acceder al modo SHARE ROW EXCLUSIVE para evitar condiciones de punto muerto cuando dos transacciones coincidentes intentan bloquear la tabla en modo SHARE y entonces intentan cambiar datos en esta tabla, ambas (implicitamente) accediendo al modo de bloqueo ROW EXCLUSIVE que es incompatible con el bloqueo SHARE .
Para continuar con los puntos muertos (cuando dos transacciones se esperan la una a la otra) tema tratado arriba, deberías seguir dos reglas generales para evitar condiciones de punto muerto :
Las transacciones tienen que acceder a bloqueos de los mismos objetos en el mismo orden.
Por ejemplo, si una aplicación actualiza la fila R1 y después actualiza la fila R2 (en la misma transacción) entonces la segunda aplicación no debería actualizar la fila R2 si ello va a actualizar la fila R1 más tarde (en una transacción simple). En cambio, debería actualizar la fila R1 y R2 en el mismo orden como en la primera aplicación.
Las transacciones deberían procurarse dos modos de bloqueo conflictivos sólo si uno de ellos es auto-conflictivo (i.e. podría ser soportado por sólo una transacción cada vez). Si estan involucrados modos de bloqueo múltiples, entonces las transacciones deberían siempre acceder primero al modo más restrictivo.
Un ejemplo para esta regla se dió antes cuando se discutió el uso del modo SHARE ROW EXCLUSIVE mejor que el modo SHARE.
Postgres no detecta puntos muertos "bajará" una transacción a la espera para resolver el punto muerto. |
Illustrate a SHARE lock on a primary key table when going to perform inserts into a foreign key table:
BEGIN WORK; LOCK TABLE películas IN SHARE MODE; SELECT id FROM películas WHERE name = 'Star Wars: Episodio I - La amenaza fantasma'; -- Haz ROLLBACK si el registro no fue devuelto INSERT INTO comentarios_usuario_películas VALUES (_id_, 'GUAY! Llevaba tanto tiempo esperándola!'); COMMIT WORK; |
Toma un bloqueo SHARE ROW EXCLUSIVE clave de tabla primaria cuando vayas a hacer una operación de borrado:
BEGIN WORK; LOCK TABLE películas IN SHARE ROW EXCLUSIVE MODE; DELETE FROM comentarios_usuario_películas WHERE id IN (SELECT id FROM películas WHERE clasificación < 5); DELETE FROM películas WHERE clasificación < 5; COMMIT WORK; |
No hay LOCK TABLE en SQL92, que usa en cambio SET TRANSACTION para especificar niveles de concurrencia en transacciones. Nosotros también la tenemos; ver SET para más detalles.