Entenda o bloqueio
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;