Lock:transactionid - Amazon Relational Database Service

Lock:transactionid

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.

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 Usar o Amazon RDS Proxy.

  • Projete a aplicação ou o modelo de dados para evitar a contenção de instruções UPDATE e SELECT … FOR UPDATE. Também é possível diminuir o número de chaves estrangeiras acessadas por instruções SELECT … 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 ou ROLLBACK.

  • Procure caminhos de código que não contenham COMMIT, ROLLBACK ou END.

  • 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 ou ROLLBACK.

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.