Comprender el bloqueo

Completado

El Control de simultaneidad de varias versiones (MVCC) proporciona la configuración de simultaneidad adecuada para la mayoría de los escenarios. Sin embargo, si una aplicación requiere bloqueos específicos que controlan exactamente qué filas se ven afectadas y con un nivel de bloqueo específico, los modos de bloqueo explícitos habilitan este control específico.

En Azure Database for PostgreSQL, hay tres tipos de bloqueo explícitos, bloqueos de nivel de tabla, bloqueos de nivel de fila y bloqueos de nivel de página. La transacción inicial solicita un bloqueo y, si se acepta, el bloqueo solicitado se convierte en el bloqueo existente. Si otra transacción intenta sacar un bloqueo en los mismos datos, se concede el bloqueo si no entra en conflicto con la transacción original.

Por ejemplo, dos transacciones pueden consultar los mismos datos al mismo tiempo con una instrucción SELECT. Estas solicitudes utilizarían un bloqueo de tipo ACCESS SHARE y se permitirían ambos. En otro escenario, una transacción está consultando datos con una instrucción SELECT y un bloqueo ACCESS SHARE, pero al mismo tiempo otra transacción intenta quitar la misma tabla. Eliminar una tabla requiere un bloqueo exclusivo de acceso, que no se concedería en este escenario.

Bloqueos de nivel de tabla

Los bloqueos de nivel de tabla adquieren bloqueos en toda una tabla, aunque tengan ROW en su nombre. Es posible que se bloquee toda una tabla si se está modificando la propia tabla o puede ser más eficaz que quitar muchos bloqueos de nivel de fila.

Hay ocho tipos de bloqueo de nivel de tabla en Azure Database for PostgreSQL y los comandos SQL que adquieren estos tipos de bloqueos son:

Modo de bloqueo Adquirido por
ACCESO COMPARTIDO Comando SELECT
COMPARTICIÓN DE FILAS COMANDOS SELECT FOR UPDATE y SELECT FOR SHARE
ROW EXCLUSIVE Comandos UPDATE, DELETE e INSERT
ACTUALIZACIÓN COMPARTIDA EXCLUSIVA comandos ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, algunos comandos ALTER INDEX y ALTER TABLE, y VACUUM (no FULL)
COMPARTIR Comando CREATE INDEX (no SIMULTÁNEAMENTE)
ACCESO EXCLUSIVO A LA FILA Comando CREATE TRIGGER y algunos comandos ALTER TABLE
EXCLUSIVO Comando REFRESH MATERIALIZED VIEW SIMULTÁNEAMENTE
ACCESO EXCLUSIVO COMANDOS DROP TABLE, REINDEX, TRUNCATE, CLUSTER, REFRESH MATERIALIZED VIEW (no SIMULTÁNEAMENTE), la mayoría de los comandos ALTER INDEX y ALTER TABLE y VACUUM FULL

Cada tipo de bloqueo existente impide que se adquieran otros bloqueos solicitados. En la tabla siguiente se muestra qué bloqueos impiden la adquisición de otros bloqueos.

-- Compartición de ACCESO existente RECURSO COMPARTIDO DE FILA existente Exclusividad de fila existente Actualización exclusiva de compartir existente Un RECURSO COMPARTIDO existente SHARE ROW EXCL existente Exclusividad actual Acceso exclusivo existente
Solicitud de COMPARTIR ACCESO Bloqueado
Solicitado COMPARTICIÓN DE FILA Bloqueado Bloqueado
Exclusividad de fila solicitada Bloqueado Bloqueado Bloqueado Bloqueado
Se solicitó SHARE UPDATE EXCLUSIVE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Recurso compartido solicitado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Se solicitó SHARE ROW EXCLUSIVE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Exclusivo solicitado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
ACCESO EXCLUSIVO solicitado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado

Bloqueos de nivel de fila

Los bloqueos de nivel de fila son más granulares y solo afectan a otra transacción que accede a la misma fila. Este tipo de bloqueo mejora la simultaneidad, pero la adquisición y eliminación de muchos bloqueos afectan negativamente al rendimiento. PostgreSQL adquiere automáticamente los bloqueos de nivel de fila y no se aplican manualmente.

Hay cuatro tipos de bloqueo de nivel de fila en Azure Database for PostgreSQL y se adquieren en función de qué otros tipos de bloqueo deben bloquearse:

-- existente para clave compartida EXISTENTE PARA COMPARTIR EXISTENTE SIN ACTUALIZACIÓN DE CLAVE EXISTENTE PARA ACTUALIZAR
Se solicitó FOR KEY SHARE Bloqueado
Solicitado para compartir Bloqueado Bloqueado
Se solicitó PARA NINGUNA ACTUALIZACIÓN DE CLAVE Bloqueado Bloqueado Bloqueado
Solicitado PARA ACTUALIZACIÓN Bloqueado Bloqueado Bloqueado Bloqueado

Bloqueos de nivel de página

Los bloqueos de nivel de página afectan a una página de datos, que normalmente consta de varias filas. Aunque los procesos de PostgreSQL usan bloqueos de nivel de página, los desarrolladores de aplicaciones normalmente no requieren este tipo de bloqueo.

Aplicación manual de bloqueos y visualización de bloqueos actuales

Para aplicar manualmente un bloqueo de nivel de tabla, puede usar el comando LOCK con el modo de bloqueo necesario. El comando LOCK debe estar dentro de una transacción y los bloqueos se liberan cuando se completa la transacción. Por ejemplo:

BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;

Para ver los bloqueos que se mantienen actualmente en la base de datos, use pg_locks. Por ejemplo, para ver todos los bloqueos actuales, use el siguiente comando:

SELECT * FROM pg_locks;