Lock:Relation - Amazon Aurora

Lock:Relation

O evento Lock:Relation ocorre quando uma consulta está aguardando para adquirir um bloqueio em uma tabela ou visualização (relação) que está atualmente bloqueada por outra transação.

Versões compatíveis do mecanismo

Essas informações de eventos de espera têm suporte para todas as versões do Aurora PostgreSQL.

Contexto

A maioria dos comandos PostgreSQL utiliza bloqueios implicitamente para controlar o acesso simultâneo aos dados em tabelas. Também é possível utilizar esses bloqueios explicitamente no código da aplicação com o comando LOCK. Vários modos de bloqueio não são compatíveis entre si e podem bloquear transações quando tentam acessar o mesmo objeto. Quando isso acontece, o Aurora PostgreSQL gera um evento Lock:Relation. Veja a seguir alguns exemplos comuns:

  • Bloqueios exclusivos, como ACCESS EXCLUSIVE, podem bloquear todo o acesso simultâneo. Operações de linguagem de definição de dados (DDL), como DROP TABLE, TRUNCATE, VACUUM FULL e CLUSTER, adquirem bloqueios ACCESS EXCLUSIVE implicitamente. ACCESS EXCLUSIVE também é o modo de bloqueio padrão para instruções LOCK TABLE que não especificam um modo explicitamente.

  • Usar CREATE INDEX (without CONCURRENT) em uma tabela gera conflito com instruções de linguagem de manipulação de dados (DML) UPDATE, DELETE e INSERT, que adquirem bloqueios ROW EXCLUSIVE.

Para obter mais informações sobre bloqueios em nível da tabela e modos de bloqueio conflitantes, consulte o tópico sobre Bloqueio explícito na documentação do PostgreSQL.

Normalmente, o bloqueio de consultas e transações é liberado de uma das seguintes maneiras:

  • Consulta de bloqueio: a aplicação pode cancelar a consulta ou o usuário pode encerrar o processo. O mecanismo também pode forçar a finalização da consulta devido a um tempo limite de declaração de uma sessão ou um mecanismo de detecção de deadlock.

  • Transação de bloqueio: uma transação para de bloquear quando executa uma instrução ROLLBACK ou COMMIT. Reversões também acontecem automaticamente quando as sessões são desconectadas por um cliente ou por problemas de rede, ou quando são encerradas. As sessões podem ser encerradas quando o mecanismo de banco de dados é desligado, quando o sistema está sem memória e assim por diante.

Possíveis causas do maior número de esperas

Quando o evento Lock:Relation ocorre com maior frequência do que o normal, pode indicar um problema de performance. As causas típicas incluem:

Maior número de sessões simultâneas com bloqueios de tabela conflitantes

Pode haver um aumento no número de sessões simultâneas com consultas que bloqueiam a mesma tabela com modos de bloqueio conflitantes.

Operações de manutenção

Operações de manutenção de integridade, como VACUUM e ANALYZE, podem aumentar significativamente o número de bloqueios conflitantes. VACUUM FULL adquire um bloqueio ACCESS EXCLUSIVE e ANALYSE adquire um bloqueio SHARE UPDATE EXCLUSIVE. Ambos os tipos de bloqueios podem causar um evento de espera Lock:Relation. Operações de manutenção de dados de aplicações, como atualizar uma visualização materializada, também podem aumentar as consultas e transações bloqueadas.

Bloqueios em instâncias de leitor

Pode haver um conflito entre os bloqueios de relação mantidos pelo gravador e os leitores. No momento, só bloqueios de relação do ACCESS EXCLUSIVE são replicados para instâncias do leitor. No entanto, o bloqueio de relação do ACCESS EXCLUSIVE entrará em conflito com qualquer bloqueio de relação do ACCESS SHARE mantido pelo leitor. Isso pode causar um aumento nos eventos de espera de relação de bloqueio no leitor.

Ações

Recomenda-se ações distintas, dependendo dos motivos do evento de espera.

Reduzir o impacto do bloqueio de instruções SQL

Para reduzir o impacto do bloqueio de instruções SQL, modifique o código da aplicação sempre que possível. Veja a seguir duas técnicas comuns para reduzir bloqueios:

  • Usar a opção NOWAIT: alguns comandos SQL, como instruções SELECT e LOCK, oferecem suporte a essa opção. A diretiva NOWAIT cancela a consulta de solicitação de bloqueio quando o bloqueio não pode ser adquirido imediatamente. Essa técnica pode evitar que uma sessão de bloqueio cause um empilhamento de sessões bloqueadas por detrás dela.

    Por exemplo: suponha que a transação A esteja aguardando um bloqueio mantido pela transação B. Se B solicitar um bloqueio em uma tabela bloqueada pela transação C, a transação A poderá ser bloqueada até a conclusão da transação C. Porém, se a transação B utilizar um NOWAIT quando solicitar o bloqueio em C, ela pode falhar rapidamente e garantir que a transação A não precise aguardar indefinidamente.

  • Usar SET lock_timeout: defina um valor de lock_timeout para limitar o tempo de espera de uma instrução SQL para adquirir um bloqueio em uma relação. Se o bloqueio não for adquirido dentro do tempo limite definido, a transação que o está solicitando será cancelada. Defina o valor no nível da sessão.

Minimizar o efeito de operações de manutenção

Operações de manutenção, como VACUUM e ANALYZE, são importantes. Recomendamos que você não as desative ao encontrar eventos de espera Lock:Relation relacionados a essas operações de manutenção. As abordagens a seguir podem minimizar o efeito dessas operações:

  • Execute operações de manutenção manualmente fora do horário de pico.

  • Para reduzir esperas Lock:Relation causadas por tarefas de autovacuum, realize qualquer ajuste de autovacuum necessário. Para obter mais informações sobre ajuste de autovacuum, consulte Trabalhar com o autovacuum do PostgreSQL no Amazon RDS, no Guia do usuário do Amazon RDS.

Verificar se há bloqueios de leitor

É possível ver como as sessões simultâneas em um gravador e leitores podem estar mantendo bloqueios que são aplicáveis uns aos outros. Uma maneira de fazer isso é executando consultas que retornem o tipo de bloqueio e a relação. Na tabela, você pode encontrar uma sequência de consultas para duas dessas sessões simultâneas, uma sessão de gravador (coluna à esquerda) e uma sessão de leitor (coluna à direita).

O processo de repetição aguarda a duração de max_standby_streaming_delay antes de cancelar a consulta do leitor. Como mostrado no exemplo, o tempo limite de bloqueio de 100 ms está bem abaixo do max_standby_streaming_delay padrão de 30 segundos. O bloqueio esgota-se antes que seja um problema.

Sessão de gravador Sessão de leitor
export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com psql -h $WRITER psql (15devel, server 10.14) Type "help" for help.
export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com psql -h $READER psql (15devel, server 10.14) Type "help" for help.
A sessão do gravador cria a tabela t1 na instância de gravador. O bloqueio do ACCESS EXCLUSIVE é adquirido no gravador imediatamente, supondo-se que não haja consultas conflitantes no gravador.
postgres=> CREATE TABLE t1(b integer); CREATE TABLE
A sessão do leitor especifica um intervalo de tempo limite de bloqueio igual a 100 milissegundos.
postgres=> SET lock_timeout=100; SET
A sessão do leitor tenta ler dados da tabela t1 na instância de leitor.
postgres=> SELECT * FROM t1; b --- (0 rows)
A sessão do gravador descarta t1.
postgres=> BEGIN; BEGIN postgres=> DROP TABLE t1; DROP TABLE postgres=>
A consulta atinge o tempo limite e é cancelada no leitor.
postgres=> SELECT * FROM t1; ERROR: canceling statement due to lock timeout LINE 1: SELECT * FROM t1; ^
A sessão do leitor consulta pg_locks e pg_stat_activity para determinar a causa do erro. O resultado indica que o processo aurora wal replay está mantendo um bloqueio ACCESS EXCLUSIVE na tabela t1.
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; locktype | relation | mode | backend_type ----------+----------+---------------------+------------------- relation | 68628525 | AccessExclusiveLock | aurora wal replay (1 row)