Oracle SQL: bloqueio de Linha na instrução select

O objetivo deste post é explicar como bloquear um registro em um Banco de dados Oracle, utilizando uma instrução select.

Introdução

O objetivo deste post é explicar como bloquear um registro em um Banco de dados Oracle, utilizando uma instrução select. Isso nos permite bloquear um registro sem a necessidade de alterá-lo.

Embora isto possa não parecer muito comum de caso de uso, a verdade é que podemos precisar para programas mais complexos (implementada, por exemplo, no PL/SQL), onde precisamos fazer algumas validações complexas, antes de decidir a atualização de um determinado registo, e precisamos mantê-lo bloqueado durante essas validações, portanto, nenhuma outra transação em simultâneo podem modificá-lo.

usaremos o SQL Developer para interagir com o banco de dados e realizar as consultas para este tutorial.

travando o mesmo registro

como de costume, começaremos criando uma tabela fictícia simples, para manter nossos dados. Verifique o exemplo create abaixo.

create table Worker(WorkerID varchar(20),WorkerName varchar(255),WorkerJob varchar(255),CONSTRAINT PK_Worker PRIMARY KEY (WorkerID));

depois disso, vamos inserir alguns registros fictícios, então temos dados para trabalhar. Vamos inserir três registros e, em seguida, confirmar a transação. Você pode usar o botão commit no menu SQL Developer ou confirmar explicitamente a transação com uma instrução SQL.

insert into worker values ('1','John', 'nurse');insert into worker values ('2','Grace', 'farmer');insert into worker values ('3','Smith', 'doctor');

agora vamos abrir uma nova planilha não compartilhada, para que possamos testar as instruções SQL em transações independentes. Verifique a figura 1 sobre como fazer isso. Você pode ler mais sobre planilhas não compartilhadas do SQL Developer neste post anterior.

planilha não compartilhada do SQL Developer

Figura 1-abrindo uma nova planilha não compartilhada.

agora, a primeira coisa que vamos fazer é executar uma seleção regular em ambas as planilhas. Faremos um select para obter o registro onde o WorkerID é igual a 1. Não faça nenhum commit ou rollbacks, basta executar a mesma consulta em ambas as planilhas.

select * from worker where WorkerID = 1;

como esperado, não há problema com a concorrência e receberemos o registro em ambas as transações (com o nome de trabalho igual a “John”).

Agora, voltaremos à primeira planilha (a mesma em que criamos a tabela) e adicionaremos uma cláusula “for update” no final da instrução select, conforme indicado abaixo. Novamente, não faça nenhum commit ou rollback.

select * from worker where WorkerID = 1 for update;

quando fazemos isso, estamos bloqueando os registros do conjunto de resultados, sem a necessidade de atualizá-los . Em outras palavras, estamos bloqueando explicitamente os registros. Claro que, uma vez que os tenhamos trancados, podemos atualizá-los se quisermos. Os bloqueios nos registros são liberados quando fazemos o próximo commit ou rollback .

portanto, para testar se os bloqueios estão funcionando, agora vamos para a segunda planilha (a planilha não compartilhada que abrimos). Lá, se fizermos uma seleção regular, sem a frase “para atualização”, obteremos o registro sem nenhum problema.

select * from worker where WorkerID = 1;

Mas então, se repetimos a escolha, agora, com a “atualização” frase no final, ele vai travar, uma vez que outros transação tem o registro com WorkerID igual a 1 bloqueado, e estamos tentando bloqueá-lo novamente.

select * from worker where WorkerID = 1 for update;

para desbloqueá-lo, basta voltar à primeira planilha e confirmar ou reverter a transação. Agora, volte para a planilha não compartilhada e a instrução SQL deve ter sido executada, retornando o registro desejado.

bloqueio de registros diferentes

uma coisa importante a ter em mente é que apenas os registros que fazem parte do conjunto de resultados são bloqueados pela transação. Portanto, diferentes transações podem fazer “selecionar para atualização” em diferentes registros.

para testar isso, vá para a primeira planilha e selecione o registro 1 e 3, com a seguinte frase select:

select * from worker where WorkerID = 1 or WorkerID = 3 for update;

agora vá para a planilha não compartilhada e tente bloquear o registro 2.

select * from worker where WorkerID = 2 for update;

deve funcionar e retornar um resultado, uma vez que o registro com WorkerID igual a 2 não foi bloqueado pela primeira transação. Agora, se na mesma planilha não compartilhada tentarmos bloquear o registro com ID do Trabalhador igual a 1 ou o registro com ID do Trabalhador igual a 3 (ou ambos) ele travará até que confirmemos ou revertamos a transação da primeira planilha.

conteúdo Relacionado

  • Oracle Select for update statment

Write a Comment

O seu endereço de email não será publicado.