Lock:Relation - Amazon Aurora

Lock:Relation

El evento Lock:Relation ocurre cuando una consulta espera adquirir un bloqueo en una tabla o vista (relación) que se encuentra bloqueada por otra transacción.

Versiones del motor admitidas

Esta información de eventos de espera es compatible con todas las versiones de Aurora PostgreSQL.

Context

La mayoría de los comandos de PostgreSQL utilizan implícitamente bloqueos para controlar el acceso concurrente a los datos de las tablas. También puede utilizar estos bloqueos explícitamente en su código de aplicación con el comando LOCK. Muchos modos de bloqueo no son compatibles entre sí, y pueden bloquear las transacciones cuando intentan acceder al mismo objeto. Cuando esto sucede, Aurora PostgreSQL genera un evento Lock:Relation. Algunos ejemplos comunes son los siguientes:

  • Los bloqueos exclusivos como ACCESS EXCLUSIVE pueden bloquear todos los accesos concurrentes. Las operaciones del lenguaje de definición de datos (DDL) como DROP TABLE, TRUNCATE, VACUUM FULL y CLUSTER adquieren bloqueos ACCESS EXCLUSIVE implícitamente. ACCESS EXCLUSIVE es también el modo de bloqueo por defecto para las instrucciones LOCK TABLE que no especifican un modo explícitamente.

  • El uso de CREATE INDEX (without CONCURRENT) en una tabla entra en conflicto con las instrucciones de lenguaje de manipulación de datos (DML) UPDATE, DELETE e INSERT, que adquieren bloqueos ROW EXCLUSIVE.

Para más información sobre los bloqueos a nivel de tabla y los modos de bloqueo conflictivos, consulte Explicit Locking en la documentación de PostgreSQL.

Las consultas y transacciones que se bloquean normalmente se desbloquean de una de las siguientes maneras:

  • Consulta de bloqueo: la aplicación puede cancelar la consulta o el usuario puede terminar el proceso. El motor también puede forzar la finalización de la consulta debido al tiempo de espera de una sesión o a un mecanismo de detección de bloqueos.

  • Transacción bloqueada: una transacción deja de bloquearse cuando se ejecuta una instrucción ROLLBACK o COMMIT. Las restauraciones también ocurren de forma automática cuando las sesiones se desconectan por un cliente o por problemas de red, o se terminan. Las sesiones se pueden terminar cuando el motor de base de datos se apaga, cuando el sistema se queda sin memoria, etc.

Causas probables del aumento del tiempo de espera

Cuando el evento Lock:Relation se produce con más frecuencia de lo normal, puede indicar un problema de rendimiento. Las causas típicas son las siguientes:

Aumento de las sesiones concurrentes con bloqueos de tablas en conflicto

Puede haber un aumento en el número de sesiones concurrentes con consultas que bloquean la misma tabla con modos de bloqueo conflictivos.

Operaciones de mantenimiento

Las operaciones de mantenimiento de estado como VACUUM y ANALYZE pueden aumentar significativamente el número de bloqueos conflictivos. VACUUM FULL adquiere un bloqueo ACCESS EXCLUSIVE, y ANALYZE adquiere un bloqueo SHARE UPDATE EXCLUSIVE. Ambos tipos de bloqueos pueden causar un evento de espera Lock:Relation. Las operaciones de mantenimiento de datos de la aplicación, como la actualización de una vista materializada, también pueden aumentar las consultas y transacciones bloqueadas.

Bloqueos en instancias de lectura

Puede haber un conflicto entre los bloqueos de relaciones que mantienen el escritor y los lectores. En la actualidad, solo los bloqueos de relaciones de ACCESS EXCLUSIVE se replican en instancias de lector. Sin embargo, el bloqueo de relaciones ACCESS EXCLUSIVE entrará en conflicto con cualquier bloqueo de relaciones ACCESS SHARE que mantenga el lector. Esto puede provocar un aumento de los eventos de espera de las relaciones de bloqueo en el lector.

Acciones

Recomendamos diferentes acciones en función de las causas del evento de espera.

Reducir el impacto de las instrucciones SQL que se bloquean

Para reducir el impacto de las instrucciones SQL que se bloquean, modifique el código de su aplicación cuando sea posible. A continuación se presentan dos técnicas comunes para reducir los bloqueos:

  • Utilizar la opción NOWAIT: algunos comandos SQL, como las instrucciones SELECT y LOCK, admiten esta opción. La directiva NOWAIT cancela la consulta que solicita el bloqueo si éste no puede adquirirse inmediatamente. Esta técnica puede ayudar a evitar que una sesión bloqueada provoque una acumulación de sesiones bloqueadas detrás de ella.

    Por ejemplo: Supongamos que la transacción A espera un bloqueo que tiene la transacción B. Ahora, si B solicita un bloqueo en una tabla que está bloqueada por la transacción C, la transacción A podría quedar bloqueada hasta que la transacción C finalice. Pero si la transacción B utiliza un NOWAIT cuando solicita el bloqueo en C, puede fallar rápido y asegurar que la transacción A no tenga que esperar de forma indefinida.

  • Utilice SET lock_timeout: establezca un valor de lock_timeout para limitar el tiempo que una sentencia SQL espera para adquirir un bloqueo en una relación. Si el bloqueo no se adquiere en el intervalo de tiempo de espera especificado, se cancelará la transacción que solicita el bloqueo. Establezca este valor en la sesión.

Minimizar el efecto de las operaciones de mantenimiento

Las operaciones de mantenimiento como VACUUM y ANALYZE son importantes. Le recomendamos que no las desactive ya que encontrará eventos de espera Lock:Relation relacionados con estas operaciones de mantenimiento. Los siguientes enfoques pueden minimizar el efecto de estas operaciones:

  • Ejecute las operaciones de mantenimiento de forma manual durante las horas de menor actividad.

  • Para reducir las esperas de Lock:Relation causadas por las tareas de autovacuum, realice los ajustes de autovacuum necesarios. Para obtener información sobre el ajuste de autovacuum, consulte Trabajo con Autovacuum de PostgreSQL en Amazon RDS en la Guía del usuario de Amazon RDS.

Verificar los bloqueos de los lectores

Puede ver cómo las sesiones concurrentes en un escritor y los lectores se pueden bloquear mutuamente. Una forma de hacer esto consiste en ejecutar consultas que devuelvan el tipo de bloqueo y la relación. En la tabla encontrará una secuencia de consultas en dos sesiones simultáneas de este tipo, una sesión de escritor y una sesión de lector.

El proceso de repetición espera el tiempo que dura max_standby_streaming_delay antes de cancelar la consulta del lector. Como se muestra en el ejemplo, el tiempo de espera de bloqueo de 100 ms está muy por debajo del max_standby_streaming_delay predeterminado de 30 segundos. El tiempo de espera del bloqueo se agota antes de que sea un problema.

Evento de secuencia Sesión Comando o salida

Establece una variable de entorno denominada READER con el valor especificado e intenta conectarse a la instancia de base de datos con este punto de conexión.

Sesión de lector

Comando de la CLI:

export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com psql -h $READER

Salida:

psql (15devel, server 10.14)
Type "help" for help.

Establece una variable de entorno denominada WRITER e intenta conectarse a la instancia de base de datos con este punto de conexión.

Sesión de escritor

Comando de la CLI:

export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com psql -h $WRITER

Salida:

psql (15devel, server 10.14) 
Type "help" for help. 

La sesión de escritor crea la tabla t1 en la instancia de escritor.

Sesión de escritor

Consulta de PostgreSQL:

postgres=> CREATE TABLE t1(b integer); CREATE TABLE

Si no hay consultas en conflicto en el escritor, se adquirirá inmediatamente en el escritor el bloqueo de ACCESS EXCLUSIVE.

Sesión de escritor

Bloqueo de ACCESS EXCLUSIVE habilitado

La sesión de lector establece un intervalo de bloqueo de 100 milisegundos.

Sesión de lector

Consulta de PostgreSQL:

postgres=> SET lock_timeout=100; SET

La sesión de lector intenta leer datos de la tabla t1 en la instancia de lector.

Sesión de lector

Consulta de PostgreSQL:

postgres=> SELECT * FROM t1;

Resultado de ejemplo:

b
---
(0 rows)

La sesión de escritor elimina la tabla t1.

Sesión de escritor

Consulta de PostgreSQL:

postgres=> BEGIN; BEGIN postgres=> DROP TABLE t1; DROP TABLE postgres=>

Se agota el tiempo de espera de la consulta y se cancela en la sesión de lector.

Sesión de lector

Consulta de PostgreSQL:

postgres=> SELECT * FROM t1;

Resultado de ejemplo:

ERROR:  canceling statement due to lock timeout
LINE 1: SELECT * FROM t1;
                      ^

Para determinar la causa del error, la sesión de lector consulta pg_locks y pg_stat_activity.

Sesión de lector

Consulta de PostgreSQL:

postgres=> SELECT locktype, relation, mode, backend_type postgres=> FROM pg_locks l, pg_stat_activity t1 postgres=> WHERE l.pid=t1.pid AND relation = 't1'::regclass::oid;

El resultado indica que el proceso de aurora wal replay mantiene un bloqueo de ACCESS EXCLUSIVE en la tabla t1.

Sesión de lector

Resultado de la consulta:

locktype | relation | mode | backend_type ----------+----------+---------------------+------------------- relation | 68628525 | AccessExclusiveLock | aurora wal replay (1 row)