LOCK [ TABLE ] nome [, ...] [ 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
O comando LOCK TABLE obtém um bloqueio no nível de tabela aguardando, quando necessário, pela liberação de qualquer bloqueio conflitante. Se for especificado NOWAIT, então o comando LOCK TABLE não ficará aguardando para obter o bloqueio desejado: se não conseguir obter o bloqueio imediatamente, o comando será interrompido e será emitido 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). [1] [2]
Ao obter automaticamente o bloqueio para os comandos que fazem referência a tabelas, o PostgreSQL sempre utiliza o modo de bloqueio menos restritivo possível. O comando LOCK TABLE serve para os casos onde é necessário um modo de bloqueio mais restritivo.
Por exemplo, suponha que um aplicativo executa uma transação no nível de isolamento READ COMMITTED, e precisa garantir que os dados da tabela permaneçam estáveis durante a transação. Para conseguir esta situação pode ser obtido o bloqueio no modo SHARE na tabela antes de realizar a consulta. Isto impede a alteração simultânea dos dados, garantindo que as próximas operações de leitura na tabela irão enxergar uma visão estável de dados efetivados, porque o modo de bloqueio SHARE conflita com o modo de bloqueio ROW EXCLUSIVE obtido por quem está escrevendo, fazendo com que o comando LOCK TABLE nome IN SHARE MODE aguarde todas as transações simultâneas que obtiveram bloqueio no modo ROW EXCLUSIVE efetivarem ou desfazerem suas modificações. Portanto, quando este bloqueio é obtido não existem escritas não efetivadas pendentes; além disso, nenhuma escrita poderá começar enquanto o bloqueio não for liberado.
Para obter um efeito semelhante ao executar uma transação no nível de isolamento serializável, é necessário executar o comando LOCK TABLE antes de executar qualquer comando SELECT ou de modificação de dado. A visão dos dados de uma transação serializável é congelada no momento em que seu primeiro comando SELECT ou de modificação de dados começa. Um comando LOCK TABLE posterior na transação ainda vai impedir escritas simultâneas — mas não vai garantir que o que é lido pela transação corresponde aos últimos valores efetivados.
Se uma transação deste tipo altera os dados da tabela, então deverá ser utilizado o modo de bloqueio SHARE ROW EXCLUSIVE em vez do modo SHARE, para garantir que somente uma transação deste tipo executa de cada vez. Sem isto, é possível ocorrer um impasse (deadlock): duas transações podem obter o bloqueio no modo SHARE, e depois ficarem impossibilitadas de obter o bloqueio no modo ROW EXCLUSIVE para realizar suas modificações (Deve ser observado que os bloqueios da própria transação nunca entram em conflito e, portanto, a transação pode obter o modo ROW EXCLUSIVE enquanto mantém o modo de bloqueio SHARE — mas não se outra transação estiver com o modo de bloqueio SHARE). Para evitar os impasses, deve ser garantido que as transações obtêm o bloqueio dos mesmos objetos na mesma ordem e, se vários modos de bloqueio estiverem envolvidos para um único objeto, as transações deverão obter sempre o modo mais restritivo primeiro.
Podem ser encontradas mais informações sobre os modos de bloqueio e estratégias de bloqueio na Seção 12.3.
O nome (opcionalmente qualificado pelo esquema) da tabela existente a ser bloqueada.
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.
O modo de bloqueio especifica os bloqueios com os quais este modo conflita. Os modos de bloqueio estão descritos na Seção 12.3.
Se não for especificado nenhum modo de bloqueio então será utilizado ACCESS EXCLUSIVE, que é o modo mais restritivo.
Especifica que o comando LOCK TABLE não deve aguardar pela liberação dos bloqueios conflitantes: se os bloqueios especificados não puderem ser obtidos imediatamente, a transação será interrompida.
O comando LOCK TABLE ... IN ACCESS SHARE MODE requer o privilégio SELECT na tabela de destino. Todas as outras formas do comando LOCK requerem os privilégios UPDATE e/ou DELETE.
O comando LOCK TABLE é útil apenas dentro de um bloco de transação (par BEGIN/COMMIT), uma vez que o bloqueio é liberado tão logo a transação termine. Um comando LOCK TABLE aparecendo fora de um bloco de transação forma uma transação auto-contida e, portanto, o bloqueio será liberado tão logo seja obtido.
O comando LOCK TABLE trata apenas de bloqueios no nível de tabela e, portanto, os nomes dos modos contendo ROW são todos equivocados. Os nomes destes modos devem ser lidos geralmente como indicando a intenção de obter um bloqueio no nível de linha dentro da tabela bloqueada. Também, o modo ROW EXCLUSIVE é um bloqueio de tabela compartilhável. Deve-se ter em mente que todos os modos de bloqueio possuem semântica idêntica no que diz respeito ao comando LOCK TABLE, diferindo apenas nas regras sobre quais modos conflitam com quais modos. Para obter informações sobre como obter um bloqueio no nível de linha real deve ser consultada a Seção 12.3.2 e a Cláusulas FOR UPDATE/FOR SHARE na documentação de referência do comando SELECT.
Obter o bloqueio no modo SHARE da tabela que contém a chave primária, antes de fazer inserções na tabela que contém a chave estrangeira:
BEGIN WORK; LOCK TABLE filmes IN SHARE MODE; SELECT id FROM filmes WHERE nome = 'Guerra Nas Estrelas - Episódio I - A Ameaça Fantasma'; -- Executar ROLLBACK se a linha não for encontrada INSERT INTO filmes_comentarios_usuario 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_usuario 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 padrão SQL, que em seu lugar usa o comando SET TRANSACTION para especificar os níveis de simutaneidade das transações. O PostgreSQL também suporta este comando; Para obter detalhes deve ser consultado o comando SET TRANSACTION.
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 o Oracle.
[1] |
Oracle — O comando LOCK TABLE é utilizado para bloquear uma ou mais tabelas, partições de tabela, ou subpartições de tabela no modo especificado. O bloqueio manual substitui o bloqueio automático e permite ou nega acesso à tabela ou visão pelos outros usuários pela duração de sua operação. Algumas formas de bloqueio podem ser colocadas na mesma tabela ao mesmo tempo. Outros bloqueios permitem apenas um bloqueio por tabela. A tabela bloqueada permanece bloqueada até que a transação seja efetivada ou desfeita, tanto inteiramente quanto a um ponto de salvamento anterior ao bloqueio da tabela. O bloqueio nunca impede que os outros usuários consultem a tabela. A consulta nunca coloca um bloqueio na tabela. Quem lê não bloqueia quem escreve, e quem escreve não bloqueia quem lê. Modos de bloqueio: ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE, SHARE, SHARE ROW EXCLUSIVE e EXCLUSIVE. Oracle® Database SQL Reference 10g Release 1 (10.1) Part Number B10759-01 (N. do T.) |
[2] |
DB2 — O comando LOCK TABLE impede que processos aplicativos simultâneos utilizem ou alterem a tabela. O modo de bloqueio IN SHARE MODE impede que os processos aplicativos simultâneos executem qualquer operação na tabela que não seja apenas de leitura. O modo de bloqueio IN EXCLUSIVE MODE impede que os processos aplicativos simultâneos executem qualquer operação na tabela. Deve ser observado que o EXCLUSIVE MODE não impede que os processos aplicativos simultâneos executando no nível de isolamento Uncommitted Read (UR) executem operações somente de leitura na tabela. DB2 Version 9 for Linux, UNIX, and Windows (N. do T.) |