PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Bug no mecanismo de bloqueio do PostgreSQL ou incompreensão do mecanismo


Não há bug, e não acho que você esteja entendendo mal alguma coisa; você está apenas perdendo algumas peças do quebra-cabeça.

As chaves estrangeiras são implementadas internamente usando o bloqueio em nível de linha; a partir do Postgres 8.1 e até 9.2, sempre que você atualizar a tabela de referência (apples neste caso), é acionada uma consulta que faz SELECT FOR SHARE na tabela referenciada (trees ). Para que SELECT FOR UPDATE na primeira transação bloqueia o SELECT FOR SHARE da integridade referencial para a segunda transação. Isso é o que causa o bloqueio no segundo comando.

Agora eu ouço você gritar:“Espere! Como é que ele bloqueia no segundo comando e não no primeiro? A explicação é simples, na verdade -- isso é só porque há uma otimização simples que pula o SELECT FOR SHARE interno quando a chave não está sendo modificada. No entanto, isso é simplista, pois se você atualizar uma tupla uma segunda vez, essa otimização não será acionada porque é mais difícil rastrear os valores originais. Daí o bloqueio.

Você também pode estar se perguntando por que eu disse que isso é até 9,2 --- o que há com 9,3? A principal diferença é que no 9.3 ele usa SELECT FOR KEY SHARE , que é um novo nível de bloqueio mais leve; permite uma melhor concorrência. Se você tentar seu exemplo em 9.3 e também alterar o SELECT FOR UPDATE para SELECT FOR NO KEY UPDATE (que é um modo mais leve que SELECT FOR UPDATE que diz que talvez você vá atualizar a tupla, mas promete não modificar a chave primária e promete não excluí-la), você deve ver que ela não bloqueia. (Além disso, você pode tentar um UPDATE na linha referenciada e, se não modificar a chave primária, ela também não será bloqueada.)

Este material 9.3 foi introduzido por um patch seu verdadeiramente como http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=0ac5ad5134f2769ccbaefec73844f8504c4d6182 e eu acho que foi um hack bem legal (A mensagem do commit tem mais alguns detalhes, se você se importa com esse tipo de coisa). Mas cuidado, não use versões anteriores a 9.3.4 porque esse patch era tão complexo que alguns bugs sérios passaram despercebidos e só corrigimos recentemente.