LOCK [ TABLE ] nome [, ...] LOCK [ TABLE ] nome [, ...] IN modo_de_bloqueio MODE onde modo_de_bloqueio é um entre: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
O nome de uma tabela existente a ser bloqueada.
Note: Este modo de bloqueio é obtido automaticamente nas tabelas sendo consultadas.
Este é o modo de bloqueio menos restritivo. Somente conflita com o modo ACCESS EXCLUSIVE. É utilizado para proteger a tabela de ser modificada por um comando ALTER TABLE, DROP TABLE ou VACUUM FULL concorrente.
Note: Automaticamente obtido pelo comando SELECT ... FOR UPDATE.
Conflita com os modos de bloqueio EXCLUSIVE e ACCESS EXCLUSIVE.
Note: Automaticamente obtido pelos comandos UPDATE, DELETE, e INSERT.
Conflita com os modos de bloqueio SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE.
Note: Automaticamente obtido pelo comando VACUUM (sem a opção FULL).
Conflita com os modos de bloqueio SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Este modo de bloqueio protege a tabela contra alterações concorrentes do esquema e VACUUM.
Note: Automaticamente obtido pelo comando CREATE INDEX. Bloqueia o compartilhamento de toda a tabela.
Conflita com os modos de bloqueio ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Este modo de bloqueio protege a tabela contra atualização concorrente dos dados.
Note: Semelhante ao EXCLUSIVE MODE, mas permite o bloqueio ROW SHARE por outros.
Conflita com os modos de bloqueio ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE.
Note: Este modo é ainda mais restritivo do que SHARE ROW EXCLUSIVE. Bloqueia todas as consultas ROW SHARE/SELECT...FOR UPDATE concorrentes.
Conflita com os modos de bloqueio ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Este modo de bloqueio permite somente o ACCESS SHARE concorrente, ou seja, somente leituras na tabela podem ocorrer em paralelo a uma transação contendo este tipo de bloqueio.
Note: Automaticamente obtido pelos comandos ALTER TABLE, DROP TABLE e VACUUM FULL. Este é o modo de bloqueio mais restritivo, o qual protege uma tabela bloqueada de qualquer operação concorrente.
Note: Este modo de bloqueio também é obtido por um comando LOCK TABLE não qualificado (ou seja, o comando sem a opção do modo de bloqueio explicitado).
Conflita com todos os outros modos de bloqueio.
O comando LOCK TABLE controla o acesso concorrente à tabela durante o tempo de execução da transação. O PostgreSQL sempre utiliza o modo de bloqueio menos restritivo quando é possível. O comando LOCK TABLE é usado nos casos onde se necessita de um modo de bloqueio mais restritivo.
Os bloqueios dos SGBDR utilizam a seguinte terminologia:
Um bloqueio exclusivo impede a concessão de outros bloqueios do mesmo tipo (Nota: O modo ROW EXCLUSIVE não segue esta convenção de nome perfeitamente, porque é compartilhado no nível de tabela; é exclusivo apenas com relação às linhas específicas que estão sendo atualizadas).
Um bloqueio compartilhado permite que outros também obtenham o mesmo tipo de bloqueio, mas impede que o bloqueio EXCLUSIVE correspondente seja concedido.
Bloqueia o esquema da tabela.
Bloqueia linhas individualmente.
Por exemplo, suponha que um aplicativo processe uma transação no nível de isolamento READ COMMITTED e precise garantir a persistência dos dados da tabela durante a transação. Para conseguir esta persistência, pode-se obter o modo de bloqueio SHARE na tabela antes de realizar a consulta. Este procedimento impede alterações de dados concorrentes e garante que as operações de leitura posteriores na tabela acessam os dados no estado atual, porque o modo de bloqueio SHARE conflita com qualquer modo de bloqueio ROW EXCLUSIVE necessário para escrever. O comando LOCK TABLE nome IN SHARE MODE aguarda até que todas as operações de escrita concorrentes terminem efetivando ou desfazendo suas transações. Portanto, quando este bloqueio é conseguido, não existe nenhuma operação de escrita sendo executada.
Note: Para ler os dados em seu estado corrente atual ao executar uma transação no nível de isolamento SERIALIZABLE, é necessário executar o comando LOCK TABLE antes de executar qualquer comando da DML. A visão dos dados de uma transação serializável é congelada no momento em que o primeiro comando da DML começa a executar.
Além dos requisitos acima, se uma transação altera os dados da tabela, então o modo de bloqueio SHARE ROW EXCLUSIVE deve ser obtido para prevenir a ocorrência da condição de "impasse" (deadlock), quando duas transações concorrentes bloqueiam a tabela em modo SHARE e depois tentam mudar os dados desta tabela, as duas (implicitamente) solicitando o modo de bloqueio ROW EXCLUSIVE que conflita com o modo de bloqueio SHARE concorrente.
Para que não ocorra a situação de "impasse" (quando duas transações ficam aguardando uma pela outra) descrita acima, devem ser seguidas duas regras gerais que evitam as condições de impasse:
As transações têm que obter o bloqueio dos mesmos objetos na mesma ordem.
Por exemplo, se um aplicativo atualiza a linha R1 e depois atualiza a linha R2 (na mesma transação), então um segundo aplicativo não deve atualizar a linha R2 se for atualizar a linha R1 depois (na mesma transação). Em vez disto, o segundo aplicativo deve atualizar as linha R1 e R2 na mesma ordem do primeiro aplicativo.
As transações devem obter dois modos de bloqueio conflitantes somente se um deles é auto-conflitante (ou seja, pode ser obtido por somente uma única transação de cada vez). Se diversos modos de bloqueio estão envolvidos, então as transações devem sempre solicitar o modo mais restritivo primeiro.
Um exemplo desta regra foi dado anteriormente ao se discutir o uso do modo SHARE ROW EXCLUSIVE em vez do modo SHARE.
Note: O PostgreSQL detecta "impasses" (deadlocks) e desfaz pelo menos uma das transações em espera para resolver o impasse.
Ao se bloquear várias tabelas, o comando LOCK a, b; é equivalente a LOCK a; LOCK b;. As tabelas são bloqueadas uma por uma na ordem especificada pelo comando LOCK.
O comando LOCK ... IN ACCESS SHARE MODE requer o privilégio SELECT na tabela especificada. Todas as outras formas de LOCK requerem os privilégios UPDATE e/ou DELETE.
O comando LOCK é útil apenas dentro de um bloco de transação (BEGIN...COMMIT), porque o bloqueio é liberado logo que a transação termina. Um comando LOCK aparecendo fora de um bloco de transação forma uma transação auto-contida, portanto o bloqueio será liberado tão logo seja obtido.
Este exemplo mostra o bloqueio no modo SHARE da tabela que contém a chave primária, antes de fazer uma inserção na tabela que contém a chave estrangeira:
BEGIN WORK;
LOCK TABLE filmes IN SHARE MODE;
SELECT id FROM filmes
WHERE nome = 'Star Wars: Episode I - The Phantom Menace';
-- Fazer o ROLLBACK se a linha não for encontrada
INSERT INTO filmes_comentarios VALUES
(_id_, 'Maravilhoso! Eu estava aguardando por isto há muito tempo!');
COMMIT WORK;
Obter o bloqueio no modo SHARE ROW EXCLUSIVE da tabela que contém a chave primária antes de realizar a operação de exclusão:
BEGIN WORK;
LOCK TABLE filmes IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM filmes_comentarios WHERE id IN
(SELECT id FROM filmes WHERE avaliacao < 5);
DELETE FROM filmes WHERE avaliacao < 5;
COMMIT WORK;
Não existe o comando LOCK TABLE no SQL92, que em seu lugar usa o comando SET TRANSACTION para especificar os níveis de concorrência das transações. O PostgreSQL também suporta esta funcionalidade; Consulte o comando SET TRANSACTION para obter mais detalhes.
Exceto pelos modos de bloqueio ACCESS SHARE, ACCESS EXCLUSIVE e SHARE UPDATE EXCLUSIVE, os modos de bloqueio do PostgreSQL e a sintaxe do comando LOCK TABLE são compatíveis com as presentes no Oracle(TM).