Existem algumas fontes na internet que insistem que idle in transaction
as conexões podem impedir que o vácuo limpe tuplas mortas. Abaixo estão alguns exemplos:
Uma transação no estado inativo em transação pode conter bloqueios que bloqueiam outras consultas. Ele também pode impedir que VACUUM (incluindo autovacuum) limpe linhas mortas, levando ao inchaço do índice ou da tabela ou ao wraparound do ID da transação .
Na verdade, uma transação longa não é um problema – o problema começa se for necessária uma transação longa e muitas pequenas alterações. Lembre-se: a transação longa pode fazer com que o VACUUM não limpe suas linhas mortas .
Na verdade, existem muitos deles, mas do meu ponto de vista isso parece absolutamente ridículo: na maioria dos casos, o nível de isolamento da transação é lido como confirmado, o que, por sua vez, significa que não há necessidade de manter tuplas mortas para tais transações, além disso, encontrei alternativas opinião sobre esse assunto :
Na verdade, não se trata de transações de longa duração, mas de instantâneos de longa duração . Certamente uma instrução select ou insert de longa duração fará isso. Para níveis de isolamento superiores aos de leitura confirmada, toda a transação reterá o instantâneo até que seja inativo ; portanto, se alguém abrir uma transação de leitura repetível e depois sair de férias sem confirmá-la, isso seria um problema. As transações preparadas suspensas também funcionarão (se você não sabe o que é uma transação preparada, provavelmente não as está usando).
ou o comentário de Pavel Luzanov na postagem do blog Cybertec :
Acredito que esse exemplo de transação longa seja verdadeiro apenas para o nível de isolamento de leitura repetível (ou serializável). Mas por padrão BEGIN usou Read Commited. Portanto, após o término de SELECT na primeira sessão, VACUUM removerá as linhas mortas em uma tabela após os comandos UPDATE, DELETE subsequentes na sessão 2.
o que foi confirmado por @ Bill Karwin em sua resposta (obrigado!)
A questão é: existem cenários “válidos” “não ficcionais” em que idle in transaction
as conexões devem ser consideradas prejudiciais? (Não estou perguntando sobre transações com nível de isolamento superior a leitura confirmada, vazamentos de transação ou conexão, longos bloqueios de transação, etc.).
É verdade que uma transação em si não bloqueia o progresso de
VACUUM
. Uma transação só é bloqueadaVACUUM
se uma destas duas condições for satisfeita:A transação possui um ID de transação atribuído (ou seja, algo foi modificado naquele banco de dados).
A transação contém um instantâneo do banco de dados. Um instantâneo é uma estrutura de dados que determina quais outras transações são visíveis para determinadas transações. Os instantâneos são mantidos abertos
contanto que uma instrução SQL esteja em execução (portanto, uma consulta de longa duração pode bloquear
VACUUM
o progresso)enquanto houver um cursor aberto
no nível
REPEATABLE READ
ouSERIALIZABLE
isolamento, durante toda a duração da transaçãoVocê pode usar a consulta do meu artigo sobre o assunto para ver se há uma transação que bloqueia
VACUUM
o progresso de:Na verdade, as transações confirmadas por leitura não bloqueiam o vácuo.
Demonstração:
Criei uma tabela com 2 20 linhas. Podemos ver que ele tem muitas tuplas vivas e 0 tuplas mortas.
Então eu consulto em uma transação, mas não confirmo ainda. Isso estabelece um instantâneo.
Em uma segunda janela, excluo metade das linhas.
Como a transação da minha primeira janela é confirmada por leitura por padrão, ela atualiza seu instantâneo para ver os resultados das exclusões.
Ainda não cometi essa transação.
Se eu medir as tuplas mortas rapidamente, verei que elas ainda estão na mesa.
Tudo o que preciso fazer é esperar que
autovacuum_naptime
o autovacuum seja executado. Este é 1 minuto por padrão.