Entenda o bloqueio

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á consultando dados com uma instrução SELECT e um bloqueio ACCESS SHARE, mas ao mesmo tempo outra transação tenta soltar a mesma tabela. Soltar 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 LINHAS Comandos SELECT FOR UPDATE e SELECT FOR SHARE
LINHA EXCLUSIVA Comandos UPDATE, DELETE e INSERT
PARTILHAR ATUALIZAÇÃO EXCLUSIVA ANALISE, CRIE ÍNDICE SIMULTANEAMENTE, CRIE ESTATÍSTICAS, COMENTE, REINDEXE COMANDOS SIMULTANEAMENTE, 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 bloqueia outros bloqueios solicitados que estão sendo adquiridos. 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 Existente ACESSO EXCLUSIVO
PARTILHA DE ACESSO solicitada Bloqueado
COMPARTILHAMENTO DE LINHA solicitado Bloqueado Bloqueado
LINHA EXCLUSIVA solicitada Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado SHARE UPDATE EXCLUSIVE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
PARTILHAR SOLICITADO Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado SHARE ROW EXCLUSIVE Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado Bloqueado
Solicitado EXCLUSIVO 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:

-- Existente PARA PARTILHA DE CHAVES Existente FOR SHARE Existente PARA NENHUMA ATUALIZAÇÃO DE CHAVE Existente FOR UPDATE
Solicitado para compartilhamento de chaves Bloqueado
Solicitado PARA PARTILHA Bloqueado Bloqueado
Solicitado PARA NENHUMA 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.

Aplicação manual de bloqueios e visualização de 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;