

# Lock:Relation
<a name="apg-waits.lockrelation"></a>

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.

**Topics**
+ [Versões compatíveis do mecanismo](#apg-waits.lockrelation.context.supported)
+ [Contexto](#apg-waits.lockrelation.context)
+ [Possíveis causas do maior número de esperas](#apg-waits.lockrelation.causes)
+ [Ações](#apg-waits.lockrelation.actions)

## Versões compatíveis do mecanismo
<a name="apg-waits.lockrelation.context.supported"></a>

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

## Contexto
<a name="apg-waits.lockrelation.context"></a>

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](https://www.postgresql.org/docs/13/explicit-locking.html) 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
<a name="apg-waits.lockrelation.causes"></a>

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 `ANALYZE` 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
<a name="apg-waits.lockrelation.actions"></a>

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

**Topics**
+ [Reduzir o impacto do bloqueio de instruções SQL](#apg-waits.lockrelation.actions.reduce-blocks)
+ [Minimizar o efeito de operações de manutenção](#apg-waits.lockrelation.actions.maintenance)
+ [Verificar se há bloqueios de leitor](#apg-waits.lockrelation.actions.readerlocks)

### Reduzir o impacto do bloqueio de instruções SQL
<a name="apg-waits.lockrelation.actions.reduce-blocks"></a>

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 obtido 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
<a name="apg-waits.lockrelation.actions.maintenance"></a>

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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html), no *Guia do usuário do Amazon RDS*.

### Verificar se há bloqueios de leitor
<a name="apg-waits.lockrelation.actions.readerlocks"></a>

É 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 de gravador e uma de leitor.

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. 


| Evento de sequência | Sessão | Comando ou saída | 
| --- | --- | --- | 
|  Define uma variável de ambiente chamada READER com o valor especificado e tenta se conectar à instância de banco de dados com esse endpoint.  |  Sessão de leitor  |  Comando da CLI: <pre>export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com<br /><br />psql -h $READER</pre> Resultado: 

```
psql (15devel, server 10.14)
Type "help" for help.
```  | 
|  Define uma variável de ambiente chamada WRITER e tenta se conectar à instância de banco de dados com esse endpoint.  |  Sessão de gravador  |  Comando da CLI: <pre>export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com<br />psql -h $WRITER</pre> Resultado: 

```
psql (15devel, server 10.14) 
Type "help" for help.
```  | 
|  A sessão do gravador cria a tabela t1 na instância de gravador.  |  Sessão de gravador  |  Consulta do PostgreSQL: <pre>postgres=> CREATE TABLE t1(b integer);<br />CREATE TABLE</pre>  | 
|  Se não houver consultas conflitantes no gravador, o bloqueio ACCESS EXCLUSIVE é obtido no gravador imediatamente.  |  Sessão de gravador  |  Bloqueio `ACCESS EXCLUSIVE` habilitado  | 
|  A sessão do leitor especifica um intervalo de tempo limite de bloqueio igual a 100 milissegundos.  |  Sessão de leitor  |  Consulta do PostgreSQL: <pre>postgres=> SET lock_timeout=100;<br />SET</pre>  | 
|  A sessão do leitor tenta ler dados da tabela t1 na instância de leitor.  |  Sessão de leitor  |  Consulta do PostgreSQL: <pre>postgres=> SELECT * FROM t1;</pre> Exemplo de resultado: 

```
b
---
(0 rows)
```  | 
|  A sessão do gravador descarta t1.  |  Sessão de gravador  |  Consulta do PostgreSQL: <pre>postgres=> BEGIN;<br />BEGIN<br />postgres=> DROP TABLE t1;<br />DROP TABLE<br />postgres=></pre>  | 
|  A consulta atinge o tempo limite e é cancelada no leitor.  |  Sessão de leitor  |  Consulta do PostgreSQL: <pre>postgres=> SELECT * FROM t1;</pre> Exemplo de resultado: 

```
ERROR:  canceling statement due to lock timeout
LINE 1: SELECT * FROM t1;
                      ^
```  | 
|  Para determinar a causa do erro, a sessão do leitor consulta `pg_locks` e `pg_stat_activity`  |  Sessão de leitor  |  Consulta do PostgreSQL: <pre>postgres=> SELECT locktype, relation, mode, backend_type<br />postgres=> FROM pg_locks l, pg_stat_activity t1<br />postgres=> WHERE l.pid=t1.pid AND relation = 't1'::regclass::oid;</pre>  | 
|  O resultado indica que o processo `aurora wal replay` está mantendo um bloqueio `ACCESS EXCLUSIVE` na tabela t1.  |  Sessão de leitor  |  Resultado da consulta: <pre> locktype | relation |        mode         |   backend_type<br />----------+----------+---------------------+-------------------<br /> relation | 68628525 | AccessExclusiveLock | aurora wal replay<br />(1 row)</pre>  | 