LOCK — bloqueia uma tabela
LOCK [ TABLE ] [ ONLY ]nome_da_tabela[ * ] [, ...] [ INmodo_de_bloqueioMODE ] [ NOWAIT ] ondemodo_de_bloqueioé um entre: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
O comando LOCK TABLE obtém um bloqueio no
nível de tabela, aguardando, se necessário, que quaisquer bloqueios
conflitantes sejam liberados.
Se for especificado NOWAIT, o comando
LOCK TABLE não irá aguardar para adquirir
o bloqueio desejado: se o bloqueio não puder ser adquirido
imediatamente, o comando será interrompido e relatado um erro.
Uma vez obtido, o bloqueio é mantido pelo restante da transação corrente.
(Não existe o comando UNLOCK TABLE; os bloqueios
são sempre liberados no final da transação.)
Quando é bloqueada uma visão, todas as relações que aparecem na consulta de definição da visão também são bloqueadas recursivamente, com o mesmo modo de bloqueio.
Ao adquirir bloqueios automaticamente para comandos que fazem
referência a tabelas, o PostgreSQL
sempre usa o modo de bloqueio menos restritivo possível.
O comando LOCK TABLE atende aos casos em que é
necessário um bloqueio mais restritivo.
Por exemplo, vamos supor que uma aplicação execute uma transação no
nível de isolamento READ COMMITTED, e precise
garantir que os dados em uma tabela permaneçam estáveis durante a
transação.
Para conseguir isto, deve ser obtido o modo de bloqueio
SHARE sobre a tabela antes de realizar a consulta,
para evitar alterações concorrentes dos dados, garantindo que as
leituras subsequentes da tabela tenham uma visão estável dos dados
efetivados, porque o modo de bloqueio SHARE
conflita com o modo de bloqueio ROW EXCLUSIVE
necessário para escrever, e o comando
LOCK TABLE
irá aguardar até que quaisquer detentores de bloqueios no modo
nome_da_tabela IN SHARE MODEROW EXCLUSIVE concorrentes efetivem ou desfaçam
sua transação.
Portanto, após obter o bloqueio não existe escrita não efetivada
pendente; além disso, nenhuma pode começar até o bloqueio ser liberado.
Para obter um efeito semelhante ao executar uma transação no nível de
isolamento REPEATABLE READ ou
SERIALIZABLE, é necessário executar
LOCK TABLE antes de executar qualquer comando
SELECT ou comando de modificação de dados.
A visão dos dados de uma transação REPEATABLE READ
ou SERIALIZABLE será congelada quando seu primeiro
comando SELECT ou de modificação de dados começar.
O comando LOCK TABLE executado mais tarde na
transação ainda impedirá escrita concorrente — mas não irá
garantir que o que for lido pela transação corresponde aos últimos
valores efetivados.
Se uma transação desse tipo for alterar os dados da tabela, então
deverá usar o modo de bloqueio SHARE ROW EXCLUSIVE
em vez do modo SHARE.
Isto garante que apenas uma transação desse tipo seja executada por vez.
Sem isto, um impasse(deadlock) é possível:
duas transações podem adquirir o modo SHARE, e
depois não conseguirem adquirir também o modo
ROW EXCLUSIVE para realizar suas atualizações.
(Note que os bloqueios da própria transação nunca entram em
conflito, portanto, uma transação pode adquirir o modo
ROW EXCLUSIVE enquanto mantém o modo
SHARE — mas não pode se mais alguma tiver
o modo SHARE.)
Para evitar impasses, deve-se certificar de que todas as transações
adquirem bloqueios nos mesmos objetos na mesma ordem e, se vários
modos de bloqueio estiverem envolvidos para um único objeto, as
transações devem sempre adquirir o modo mais restritivo primeiro.
Mais informações sobre os modos de bloqueio e estratégias de bloqueio podem ser encontradas em Bloqueio explícito.
nome_da_tabela
O nome (opcionalmente qualificado pelo esquema) da tabela
existente a ser bloqueada.
Se for especificado ONLY antes do nome da
tabela, apenas esta tabela será bloqueada.
Se não for especificado ONLY, a tabela e todas
as suas tabelas descendentes (se houver) serão bloqueadas.
Opcionalmente, pode ser especificado um * após
o nome da tabela para indicar explicitamente que as tabelas
descendentes estão incluídas.
O comando LOCK TABLE a, b; é equivalente a
LOCK TABLE a; LOCK TABLE b;.
As tabelas são bloqueadas uma a uma na ordem especificada no
comando LOCK TABLE.
modo_de_bloqueioO modo de bloqueio especifica com quais bloqueios este bloqueio entra em conflito. Os modos de bloqueio são descritos em Bloqueio explícito.
Se não for especificado nenhum modo de bloqueio, então será usado
ACCESS EXCLUSIVE, o modo mais restritivo.
NOWAIT
Especifica que LOCK TABLE não deve esperar que
nenhum bloqueio conflitante seja liberado: se o(s) bloqueio(s)
especificado(s) não puder(em) ser adquirido(s) imediatamente
sem aguardar, a transação é interrompida.
Para bloquear uma tabela, o usuário deve ter o privilégio correto
para o modo_de_bloqueio
especificado.
Se o usuário possuir os privilégios MAINTAIN,
UPDATE, DELETE ou
TRUNCATE na tabela, será permitido qualquer
modo_de_bloqueio.
Se o usuário possuir o privilégio INSERT na tabela,
será permitido o bloqueio ROW EXCLUSIVE MODE
(ou um modo menos restritivo, conforme descrito em
Bloqueio explícito).
Se o usuário possuir o privilégio SELECT na tabela,
será permitido o bloqueio ACCESS SHARE MODE.
O usuário que realiza o bloqueio na visão deve ter o privilégio
correspondente na visão.
Além disso, por padrão, o dono da visão deve ter os privilégios
relevantes nas relações base subjacentes, enquanto o usuário que
realiza o bloqueio não precisa de nenhuma permissão nas relações
base subjacentes.
Entretanto, se a visão possuir security_invoker
definido como true
(veja CREATE VIEW),
o usuário que realiza o bloqueio, e não o dono da visão, deverá
ter os privilégios relevantes nas relações base subjacentes.
O comando LOCK TABLE é inútil fora de um bloco
de transação: o bloqueio permaneceria mantido apenas até a conclusão
do comando.
Portanto, o PostgreSQL relata um erro se
for usado LOCK fora de um bloco de transação.
Deve ser usado BEGIN e
COMMIT (ou ROLLBACK)
para definir um bloco de transação.
O comando LOCK TABLE lida apenas com bloqueios no
nível de tabela, portanto, os nomes de modo envolvendo
ROW são todos nomes impróprios.
Geralmente, estes nomes de modo devem ser lidos como indicando a
intenção do usuário em adquirir bloqueios no nível de linha na
tabela bloqueada.
Além disso, o modo ROW EXCLUSIVE é um bloqueio
de tabela compartilhável.
Deve-se ter em mente que todos os modos de bloqueio têm semântica
idêntica no que diz respeito a LOCK TABLE,
diferindo apenas nas regras sobre quais modos entram em conflito
com quais outros modos.
Para obter informações sobre como adquirir um bloqueio no nível
de linha real, veja Modos de bloqueio no nível de linha e
Cláusula de bloqueio na documentação do comando
SELECT.
Obter o bloqueio SHARE na tabela com a chave
primária, ao realizar inserções na tabela com a chave estrangeira:
BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- Efetuar ROLLBACK se o registro não for retornado
INSERT INTO films_user_comments VALUES
(_id_, 'GREAT! I was waiting for it for so long!');
COMMIT WORK;
Obter o bloqueio SHARE ROW EXCLUSIVE na tabela
com a chave primária, ao executar uma operação de exclusão:
BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
(SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;
Não existe o comando LOCK TABLE no padrão
SQL, que em vez deste usa o comando
SET TRANSACTION para especificar níveis de
concorrência em transações.
O PostgreSQL também oferece suporte a este
comando; veja SET TRANSACTION para obter detalhes.
Exceto pelos modos de bloqueio ACCESS SHARE,
ACCESS EXCLUSIVE, e
SHARE UPDATE EXCLUSIVE, os modos de bloqueio e
a sintaxe do comando LOCK TABLE do
PostgreSQL são compatíveis com as
presentes no Oracle.
[148]
[149]
[148]
Use o comando LOCK TABLE para bloquear uma ou
mais tabelas, partições de tabela ou subpartições de tabela em um
modo especificado.
Este bloqueio substitui manualmente o bloqueio automático, e
permite ou nega o acesso a uma tabela, ou visão, por outros
usuários durante a operação.
Uma tabela bloqueada permanece bloqueada até que se confirme sua
transação ou a desfaça, totalmente ou até o ponto de salvamento
antes de bloquear a tabela.
Oracle 21 – LOCK TABLE (N. T.)
[149]
O comando LOCK TABLE impede que processos
de aplicações concorrentes usem ou alterem a tabela.
O bloqueio é liberado quando a unidade de trabalho que executou
o comando LOCK TABLE é efetivada ou termina.
IBM DB2 12.1.x – LOCK TABLE statement (N. T.)