Compreender o bloqueio
O MVCC (Controle de Simultaneidade de Várias Versões) fornece as configurações de simultaneidade apropriadas para a maioria dos cenários. No entanto, se um aplicativo exigir 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ícitos 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 de linha e bloqueios no nível da página. A transação inicial solicita um bloqueio e, se aceita, o bloqueio solicitado torna-se o bloqueio existente. Se outra transação tentar realizar um bloqueio nos mesmos dados, o bloqueio será concedido se ele 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. Essas solicitações usariam um bloqueio ACCESS SHARE e ambas seriam permitidas. 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 remover a mesma tabela. Remover uma tabela requer um bloqueio do tipo ACCESS EXCLUSIVE, que não seria concedido, neste cenário.
Bloqueios no nível da tabela
Os bloqueios no nível da 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 tabela em si estiver sendo modificada ou pode ser mais eficiente do que remover muitos bloqueios de nível de linha.
Há oito tipos de bloqueio no nível da 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 |
COMPARTILHAMENTO DE LINHA | COMANDOS SELECT FOR UPDATE e SELECT FOR SHARE |
LINHA EXCLUSIVA | Comandos UPDATE, DELETE e INSERT |
COMPARTILHAR ATUALIZAÇÃO EXCLUSIVA | COMANDOS ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, alguns comandos ALTER INDEX e ALTER TABLE e VACUUM (não FULL) |
COMPARTILHAR | Comando CREATE INDEX (não CONCURRENTLY) |
COMPARTILHAR LINHA EXCLUSIVA | Comando CREATE TRIGGER e alguns comandos ALTER TABLE |
EXCLUSIVO | Comando REFRESH MATERIALIZED VIEW CONCURRENTLY |
Acesso Exclusivo | COMANDOS DROP TABLE, REINDEX, TRUNCATE, CLUSTER, REFRESH MATERIALIZED VIEW (não CONCURRENTLY), 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:
-- | COMPARTILHAMENTO DE ACESSO Existente | COMPARTILHAMENTO DE LINHA existente | EXCLUSIVO DE LINHA EXISTENTE | ATUALIZAÇÃO EXISTENTE DE COMPARTILHAMENTO EXCLUSIVO | COMPARTILHAMENTO EXISTENTE | "EXCL de LINHA COMPARTILHADA EXISTENTE" | EXCLUSIVO existente | ACESSO EXCLUSIVO existente |
---|---|---|---|---|---|---|---|---|
COMPARTILHAMENTO DE ACESSO Solicitado | Bloqueado | |||||||
COMPARTILHAMENTO DE LINHA solicitado | Bloqueado | Bloqueado | ||||||
LINHA EXCLUSIVA solicitada | Bloqueado | Bloqueado | Bloqueado | Bloqueado | ||||
Atualização Exclusiva de Ações Solicitada | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |||
Compartilhamento solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |||
Solicitação de SHARE ROW EXCLUSIVE | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | ||
EXCLUSIVO solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | |
ACESSO EXCLUSIVO solicitado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado | Bloqueado |
Bloqueios em 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 remover muitos bloqueios afeta negativamente o desempenho. Os bloqueios no 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 COMPARTILHAMENTO DE CHAVE | Disponível PARA COMPARTILHAR | Existente PARA SEM ATUALIZAÇÃO DE CHAVE | Existente PARA ATUALIZAÇÃO |
---|---|---|---|---|
SOLICITADO PARA KEY SHARE | Bloqueado | |||
SOLICITAÇÃO DE COMPARTILHAMENTO | Bloqueado | Bloqueado | ||
SOLICITAÇÃO 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.
Aplicar bloqueios manualmente e exibir 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 que estão 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;