Compreenda o bloqueamento
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;