Antipadrões do PostgreSQL: combatendo as hordas de “mortos”

Os recursos dos mecanismos internos do PostgreSQL permitem que seja muito rápido em algumas situações e não tão rápido em outras. Hoje, vamos nos debruçar sobre um exemplo clássico de um conflito entre como um DBMS funciona e o que um desenvolvedor faz com ele - princípios UPDATE vs MVCC .

Resumo de um excelente artigo :
Quando uma linha é modificada com o comando UPDATE, duas operações são realmente executadas: DELETE e INSERT. Na versão atual da linha , xmax é definido igual ao número da transação que executou UPDATE. Em seguida, uma nova versão da mesma linha é criada; seu valor xmin corresponde ao valor xmax da versão anterior.
Algum tempo após a conclusão desta transação, a versão antiga ou nova, dependendo da qual COMMIT/ROOLBACK, será reconhecida como "morta" (tuplas mortas) ao passar VACUUMpela tabela e limpa.



Mas isso não acontecerá imediatamente, mas os problemas com os "mortos" podem ser adquiridos muito rapidamente - com atualizações múltiplas ou em massa de registros em uma tabela grande e, um pouco mais tarde, diante de uma situação que a VACUUM não poderá ajudar .

# 1: Eu gosto de movê-lo


Suponha que seu método de lógica de negócios funcione por si mesmo e subitamente perceba que seria necessário atualizar o campo X em algum registro:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Então, à medida que avança, ele descobre que o campo Y também deve ser atualizado:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... e depois também Z - por que brincar algo?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Quantas versões desse registro agora têm no banco de dados? Sim, 4 peças! Destes, um é relevante e 3 terão que pegar o [auto] VACUUM para você.

Não faça assim! Use a atualização de todos os campos em uma solicitação - quase sempre a lógica do método pode ser alterada assim:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

# 2: Use IS DISTINCT FROM, Luke!


Portanto, você ainda queria atualizar muitos registros na tabela (durante o uso de um script ou conversor, por exemplo). E algo assim voa para o script:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Aproximadamente nesse formulário, uma consulta é encontrada com bastante frequência e quase sempre para não preencher um novo campo vazio, mas para corrigir alguns erros nos dados. Além disso, a correção dos dados já existentes não é levada em consideração, mas em vão! Ou seja, o disco está sendo reescrito, mesmo que fosse exatamente o que eu queria - por quê? Corrigir:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Muitas pessoas não estão cientes da existência de um operador tão maravilhoso, então aqui está uma folha de dicas para IS DISTINCT FROMoutros operadores lógicos ajudarem:

... e um pouco sobre operações em ROW()expressões complexas :

# 3: vou reconhecer minha querida ... bloqueando


Execute dois processos paralelos idênticos , cada um deles voltado para a marca de gravação, que está "em operação":

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Mesmo que esses processos façam coisas substancialmente independentes, mas dentro da estrutura de um ID, nessa solicitação, o segundo cliente irá "travar" até a conclusão da primeira transação.

Solução 1 : a tarefa é reduzida à anterior,

basta adicionar novamente IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Nesse formulário, a segunda solicitação simplesmente não altera nada no banco de dados, já existe "tudo está como deveria" - portanto, o bloqueio não ocorrerá. Além disso, o fato da "inexistência" do registro já é processado no algoritmo aplicado.

Decisão número 2 : bloqueios de aviso

Um tópico amplo para um artigo separado, no qual você pode ler sobre os métodos de aplicação e o "rake" dos bloqueios de recomendação .

Solução # 3 : sem [d] chamadas inteligentes

Mas exatamente, exatamente, você deve ter um trabalho simultâneo com o mesmo registro ? Ou você ainda mexeu nos algoritmos de chamada da lógica de negócios do lado do cliente, por exemplo? E se você pensar sobre isso? ..

All Articles