O evento Lock:transactionid
ocorre quando uma transação está aguardando um bloqueio em nível de linha.
Versões compatíveis do mecanismo
Essas informações de eventos de espera são compatíveis com todas as versões do RDS para PostgreSQL.
Contexto
O evento Lock:transactionid
ocorre quando uma transação está tentando adquirir um bloqueio em nível de linha já concedido a uma transação que está sendo executada simultaneamente. A sessão que mostra o evento de espera Lock:transactionid
está bloqueada devido a esse bloqueio. Depois que a transação de bloqueio terminar em uma instrução COMMIT
ou ROLLBACK
, a transação bloqueada pode continuar.
A semântica de controle de simultaneidade de várias versões do RDS para PostgreSQL garante que os leitores não bloqueiem gravadores e que os gravadores não bloqueiem os leitores. Para que ocorram conflitos em nível de linha, transações de bloqueio e bloqueadas devem emitir instruções conflitantes dos seguintes tipos:
-
UPDATE
-
SELECT … FOR UPDATE
-
SELECT … FOR KEY SHARE
A instrução SELECT … FOR KEY SHARE
é um caso especial. O banco de dados usa a cláusula FOR KEY
SHARE
para otimizar a performance da integridade referencial. Um bloqueio em nível de linha em uma linha pode bloquear comandos INSERT
, UPDATE
e DELETE
em outras tabelas que fazem referência à linha.
Possíveis causas do maior número de esperas
Quando esse evento aparece mais do que o normal, a causa geralmente envolve instruções UPDATE
, SELECT …
FOR UPDATE
ou SELECT … FOR KEY SHARE
combinadas com as seguintes condições.
Alta simultaneidade
O RDS para PostgreSQL pode utilizar semântica de bloqueio granular em nível de linha. A probabilidade de conflitos em nível de linha aumenta quando as condições a seguir são atendidas:
-
Uma workload altamente simultânea controla as mesmas linhas.
-
A simultaneidade aumenta.
Ocioso na transação
Às vezes, a coluna pg_stat_activity.state
mostra o valor idle in transaction
. Esse valor aparece para sessões que iniciaram uma transação, mas ainda não emitiram um COMMIT
ou ROLLBACK
. Se o valor de pg_stat_activity.state
não for active
, a consulta mostrada em pg_stat_activity
será a mais recente a terminar a execução. A sessão de bloqueio não está processando uma consulta ativamente porque uma transação aberta está mantendo um bloqueio.
Se uma transação ociosa adquiriu um bloqueio em nível de linha, talvez ela esteja impedindo que outras sessões o adquiram. Essa condição leva à ocorrência frequente do evento de espera Lock:transactionid
. Para diagnosticar o problema, examine a saída proveniente de pg_stat_activity
e pg_locks
.
Transações de longa execução
Transações executadas por um longo tempo recebem bloqueios por um longo tempo. Esses bloqueios de longa duração podem impedir que outras transações sejam executadas.
Ações
O bloqueio de linhas é um conflito entre instruções UPDATE
, SELECT … FOR
UPDATE
ou SELECT … FOR KEY SHARE
. Antes de tentar uma solução, descubra quando essas instruções estão sendo executadas na mesma linha. Use essas informações para escolher uma estratégia descrita nas seguintes seções.
Tópicos
Responder a alta simultaneidade
Se a simultaneidade for o problema, tente uma das seguintes técnicas:
-
Reduza a simultaneidade na aplicação. Por exemplo, reduza o número de sessões ativas.
-
Implemente um pool de conexões. Para saber como agrupar conexões com o RDS Proxy, consulte Amazon RDS Proxy.
-
Projete a aplicação ou o modelo de dados para evitar a contenção de instruções
UPDATE
eSELECT … FOR UPDATE
. Também é possível diminuir o número de chaves estrangeiras acessadas por instruçõesSELECT … FOR KEY SHARE
.
Responder a transações ociosas
Se pg_stat_activity.state
mostrar idle in transaction
, utilize as seguintes estratégias:
-
Ative a confirmação automática sempre que possível. Essa abordagem impede que transações bloqueiem outras transações enquanto aguardam
COMMIT
ouROLLBACK
. -
Procure caminhos de código que não contenham
COMMIT
,ROLLBACK
ouEND
. -
Assegure-se de que a lógica de tratamento de exceções na seu aplicação sempre tenha um caminho para um
end of transaction
válido. -
Assegure-se de que a sua aplicação processe os resultados da consulta depois de encerrar a transação com
COMMIT
ouROLLBACK
.
Responder a transações de longa duração
Se transações de longa duração estiverem causando a ocorrência frequente de Lock:transactionid
, tente as estratégias a seguir:
-
Mantenha os bloqueios de linha fora de transações de longa execução.
-
Limite o comprimento das consultas implementando a confirmação automática sempre que possível.