Compreenda o bloqueamento

Concluído

O MVCC (Multi-Version Concurrency Control) fornece as configurações de simultaneidade apropriadas para a maioria dos cenários. No entanto, se um aplicativo requer bloqueios específicos que controlam exatamente quais linhas são afetadas e com um nível de bloqueio específico, os modos de bloqueio explícito habilitam esse controle refinado.

No Banco de Dados do Azure para PostgreSQL, há três tipos de bloqueio explícito, bloqueios no nível da tabela, bloqueios no nível da linha e bloqueios no nível da página. A transação inicial pede um bloqueio e, se aceito, o bloqueio solicitado torna-se o bloqueio existente. Se outra transação tentar remover um bloqueio nos mesmos dados, o bloqueio será concedido se não entrar em conflito com a transação original.

Por exemplo, duas transações podem consultar os mesmos dados ao mesmo tempo com uma instrução SELECT. Estes pedidos utilizariam um bloqueio ACCESS SHARE e ambos seriam permitidos. Em outro cenário, uma transação está a consultar dados com uma instrução SELECT e um bloqueio de partilha de acesso, mas ao mesmo tempo outra transação tenta eliminar a mesma tabela. Eliminar uma tabela requer um bloqueio ACCESS EXCLUSIVE, que não seria concedido neste cenário.

Bloqueios ao nível da tabela

Os bloqueios de nível de tabela adquirem bloqueios em uma tabela inteira, mesmo que tenham ROW em seu nome. O bloqueio de uma tabela inteira pode ser necessário se a própria tabela estiver sendo modificada ou pode ser mais eficiente do que remover muitos bloqueios no nível da linha.

Há oito tipos de bloqueio no nível de tabela no Banco de Dados do Azure para PostgreSQL e os comandos SQL que adquirem esses tipos de bloqueios são:

Modo de bloqueio Adquirido por
COMPARTILHAMENTO DE ACESSO Comando SELECT
PARTILHA DE REGISTOS Comandos SELECT FOR UPDATE e SELECT FOR SHARE
LINHA EXCLUSIVA Comandos UPDATE, DELETE e INSERT
PARTILHAR ATUALIZAÇÃO EXCLUSIVA ANALISAR, CRIAR ÍNDICE CONCORRENTEMENTE, CRIAR ESTATÍSTICAS, COMENTÁRIO SOBRE, REINDEXAR CONCORRENTEMENTE, alguns comandos ALTER INDEX e ALTER TABLE e VACUUM (NÃO COMPLETO)
PARTILHAR Comando CREATE INDEX (não CONSIMULTANEAMENTE)
COMPARTILHAR LINHA EXCLUSIVA Comando CREATE TRIGGER e alguns comandos ALTER TABLE
EXCLUSIVO Comando REFRESH MATERIALIZED VIEW CONSIMULTANEAMENTE
ACESSO EXCLUSIVO DROP TABLE, REINDEX, TRUNCATE, CLUSTER, REFRESH MATERIALIZED VIEW (não SIMULTANEAMENTE), a maioria dos comandos ALTER INDEX e ALTER TABLE e VACUUM FULL

Cada tipo de bloqueio existente impede a aquisição de outros bloqueios solicitados. A tabela a seguir lista quais bloqueios impedem que outros bloqueios sejam adquiridos:

-- PARTILHA DE ACESSO existente PARTILHA DE LINHAS existente Existente ROW EXCLUSIVE Existente SHARE UPDATE EXCLUSIVE SHARE existente SHARE ROW EXCL existente Existente EXCLUSIVE ACESSO EXCLUSIVO Existente
ACESSO PARTILHADO solicitado Bloqueado
COMPARTILHAMENTO DE LINHA solicitado Bloqueado Bloqueado
LINHA EXCLUSIVA solicitada Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado Atualização Exclusiva de SHARE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
PARTILHAR SOLICITADO Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado SHARE ROW EXCLUSIVE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
EXCLUSIVO solicitado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado ACESSO EXCLUSIVO Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado

Bloqueios de nível de linha

Os bloqueios de nível de linha são mais granulares e afetam apenas outra transação que está acessando a mesma linha. Esse tipo de bloqueio melhora a simultaneidade, mas adquirir e soltar muitos bloqueios afeta negativamente o desempenho. Os bloqueios em nível de linha são adquiridos automaticamente pelo PostgreSQL e não são aplicados manualmente.

Há quatro tipos de bloqueio em nível de linha no Banco de Dados do Azure para PostgreSQL e eles são adquiridos dependendo de quais outros tipos de bloqueio precisam ser bloqueados:

-- Disponível PARA PARTILHA DE CHAVES Existente para partilha Existente PARA NENHUMA ATUALIZAÇÃO DE CHAVE Atualização Existente FOR UPDATE
Solicitado para compartilhamento de chaves Bloqueado
Solicitado para partilhar Bloqueado Bloqueado
Solicitado SEM ATUALIZAÇÃO DE CHAVE Bloqueado Bloqueado Bloqueado
Solicitado PARA ATUALIZAÇÃO Bloqueado Bloqueado Bloqueado Bloqueado

Bloqueios no nível da página

Os bloqueios no nível da página afetam uma página de dados, que normalmente consiste em várias linhas. Embora os processos do PostgreSQL usem bloqueios no nível da página, os desenvolvedores de aplicativos normalmente não exigem esse tipo de bloqueio.

Aplicar bloqueios manualmente e visualizar bloqueios atuais

Para aplicar manualmente um bloqueio no nível da tabela, você pode usar o comando LOCK com o modo de bloqueio necessário. O comando LOCK deve estar dentro de uma transação e os bloqueios são liberados quando a transação é concluída. Por exemplo:

BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;

Para exibir bloqueios atualmente mantidos no banco de dados, use pg_locks. Por exemplo, para exibir todos os bloqueios atuais, use o seguinte comando:

SELECT * FROM pg_locks;