Descripción del bloqueo
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ícito: de nivel de tabla, de nivel de fila y 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 usarían un bloqueo ACCESS SHARE y ambos se permitirían. En otro escenario, una transacción consulta datos con una instrucción SELECT y un bloqueo ACCESS SHARE, pero al mismo tiempo otra transacción intenta quitar la misma tabla. Quitar una tabla requiere un bloqueo ACCESS EXCLUSIVE, que no se concedería, en este escenario.
Bloqueos de tabla
Los bloqueos de nivel de tabla adquieren bloqueos en toda una tabla, incluso si incluyen ROW en su nombre. Es posible que sea necesario bloquear una tabla completa si se está modificando la propia tabla, o podría 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 |
---|---|
ACCESS SHARE | Comando SELECT |
ROW SHARE | Comandos SELECT FOR UPDATE y SELECT FOR SHARE |
ROW EXCLUSIVE | Comandos UPDATE, DELETE e INSERT |
SHARE UPDATE EXCLUSIVE | Comandos ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON y REINDEX CONCURRENTLY, algunos comandos ALTER INDEX y ALTER TABLE, y VACUUM (no FULL) |
COMPARTIR | Comando CREATE INDEX (no CONCURRENTLY) |
SHARE ROW EXCLUSIVE | Comando CREATE TRIGGER y algunos comandos ALTER TABLE |
EXCLUSIVE | Comando REFRESH MATERIALIZED VIEW CONCURRENTLY |
ACCESS EXCLUSIVE | Comandos DROP TABLE, REINDEX, TRUNCATE, CLUSTER, REFRESH MATERIALIZED VIEW (no CONCURRENTLY), la mayoría de los comandos ALTER INDEX y ALTER TABLE, y VACUUM FULL |
Cada tipo de bloqueo existente bloquea otros bloqueos solicitados que se adquieren. En la tabla siguiente se muestra qué bloqueos bloquean la adquisición de otros:
-- | ACCESS SHARE existente | ROW SHARE existente | ROW EXCLUSIVE existente | SHARE UPDATE EXCLUSIVE existente | SHARE existente | SHARE ROW EXCL existente | EXCLUSIVE existente | ACCESS EXCLUSIVE existente |
---|---|---|---|---|---|---|---|---|
ACCESS SHARE solicitado | Bloqueado | |||||||
ROW SHARE solicitado | Bloqueado | Bloqueado | ||||||
ROW EXCLUSIVE solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | ||||
SHARE UPDATE EXCLUSIVE solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |||
SHARE solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |||
SHARE ROW EXCLUSIVE solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | ||
EXCLUSIVE solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |
ACCESS EXCLUSIVE 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 afecta negativamente al rendimiento. PostgreSQL adquiere automáticamente los bloqueos de nivel de fila; 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:
-- | FOR KEY SHARE existente | FOR SHARE existente | FOR NO KEY UPDATE existente | FOR UPDATE existente |
---|---|---|---|---|
FOR KEY SHARE solicitado | Bloqueado | |||
FOR SHARE solicitado | Bloqueado | Bloqueado | ||
FOR NO KEY UPDATE solicitado | Bloqueado | Bloqueado | Bloqueado | |
FOR UPDATE solicitado | 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 los 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. 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 aplican actualmente en la base de datos, use pg_locks. Por ejemplo, para ver todos los bloqueos actuales, use el comando siguiente:
SELECT * FROM pg_locks;