LOCK

LOCK — bloqueia uma tabela

Sinopse

LOCK [ TABLE ] [ ONLY ] nome_da_tabela [ * ] [, ...]
     [ IN modo_de_bloqueio MODE ] [ NOWAIT ]

onde modo_de_bloqueio é um entre:

      ACCESS SHARE
    | ROW SHARE
    | ROW EXCLUSIVE
    | SHARE UPDATE EXCLUSIVE
    | SHARE
    | SHARE ROW EXCLUSIVE
    | EXCLUSIVE
    | ACCESS EXCLUSIVE

Descrição

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 nome_da_tabela IN SHARE MODE irá aguardar até que quaisquer detentores de bloqueios no modo ROW 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.

Parâmetros

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_bloqueio

O 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.

Notas

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.

Exemplos

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;

Conformidade

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.)