Digamos que você tenha uma grande tabela com dezenas de milhões de linhas.
Você deseja UPDATE large_table SET col=value WHERE col=other_value
... mas col
não está indexado e EXPLAIN
mostra que essa consulta fará uma varredura seq em toda a tabela.
Qual é o comportamento de bloqueio aqui? De acordo com a maioria das contas, o Postgres bloqueia apenas as linhas afetadas de uma consulta UPDATE e não possui escalonamento de bloqueio. Então, ele procura as linhas para atualizar primeiro e depois bloqueia apenas as linhas encontradas? Parece que potencialmente haveria problemas de outras consultas atualizando linhas simultaneamente nesse caso. Ele bloqueia cada linha "como as encontra", ou seja, bloqueia as linhas progressivamente à medida que passa pela varredura seq?
Portanto, acho que o melhor caso aqui é bloquear as linhas à medida que as encontra, e as linhas afetadas (somente) serão bloqueadas pelo tempo que a consulta UPDATE levar para ser concluída.
Mas estou preocupado que essa consulta possa acabar bloqueando todas as gravações na tabela até que seja concluída.
Eu li isso: https://habr.com/en/company/postgrespro/blog/503008/ e acho que o pior caso não vai acontecer, mas aqui https://blog.heroku.com/curious-case-table -locking-update-query é uma representação possivelmente imprecisa de informações semelhantes que me dão algumas dúvidas.
O aplicativo usa apenas SELECT
, SELECT FOR UPDATE
e UPDATE
consultas (ou seja, nenhum outro bloqueio explícito separado desses). A tabela possui chaves estrangeiras para outras tabelas e outras tabelas possuem chaves estrangeiras para esta tabela.
Estamos no Postgres 11.
Para a discussão, vamos supor que seu plano de execução se parece com
Também presumo que você esteja usando o
READ COMMITTED
nível de isolamento padrão.Então o PostgreSQL lerá sequencialmente a tabela.
Sempre que encontrar uma linha que corresponda ao filtro, essa linha será bloqueada e atualizada.
Se o bloqueio de uma linha for bloqueado por uma consulta simultânea, o PostgreSQL espera até que o bloqueio desapareça. Em seguida, ele reavalia a condição do filtro e avança (se a condição não se aplicar mais devido a uma modificação simultânea) ou bloqueia e atualiza a linha modificada.
Veja a documentação :
Em particular, é possível que duas
UPDATE
instruções, cada uma modificando várias linhas, entrem em deadlock, uma vez que adquirem bloqueios à medida que prosseguem e os bloqueios são sempre mantidos até o final da transação.