Oracle SQL: Row locking on select statement

L’obiettivo di questo post è quello di spiegare come bloccare un record su un database Oracle, utilizzando un’istruzione select.

Introduzione

L’obiettivo di questo post è quello di spiegare come bloccare un record su un database Oracle, utilizzando un’istruzione select. Questo ci permette di bloccare un record senza la necessità di cambiarlo.

Anche se questo potrebbe non sembrare un caso d’uso molto comune, la verità è che potremmo averne bisogno per programmi più complessi (implementati, ad esempio, in PL/SQL), dove abbiamo bisogno di eseguire alcune convalide complesse prima di decidere di aggiornare un determinato registro, e abbiamo bisogno di mantenerlo bloccato durante quelle convalide, quindi nessuna altra transazione può modificarlo contemporaneamente.

Useremo SQL Developer per interagire con il database e per eseguire le query per questo tutorial.

Bloccando lo stesso record

Come al solito, inizieremo creando una semplice tabella fittizia, per contenere i nostri dati. Controlla l’esempio crea qui sotto.

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

Dopo di che, inseriremo alcuni record fittizi, quindi abbiamo dati su cui lavorare. Inseriremo tre record e quindi commetteremo la transazione. È possibile utilizzare il pulsante commit nel menu SQL Developer o eseguire esplicitamente il commit della transazione con un’istruzione SQL.

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

Ora apriremo un nuovo foglio di lavoro non condiviso, in modo da poter testare le istruzioni SQL nelle transazioni indipendenti. Controllare figura 1 su come farlo. Si può leggere di più su SQL Developer unshared fogli di lavoro in questo post precedente.

SQL Developer unshared worksheet

Figura 1 – Apertura di un nuovo foglio di lavoro non condiviso.

Ora, la prima cosa che faremo è eseguire una selezione regolare in entrambi i fogli di lavoro. Faremo una selezione per ottenere il record in cui il WorkerID è uguale a 1. Non eseguire commit o rollback, basta eseguire la stessa query in entrambi i fogli di lavoro.

select * from worker where WorkerID = 1;

Come previsto, non ci sono problemi con la concorrenza e riceveremo il record in entrambe le transazioni (con il nome del lavoro uguale a “John”).

Ora, torneremo al primo foglio di lavoro (lo stesso in cui abbiamo creato la tabella) e aggiungeremo una clausola “for update” alla fine dell’istruzione select, come indicato di seguito. Ancora una volta, non fare alcun commit o rollback.

select * from worker where WorkerID = 1 for update;

Quando lo facciamo, stiamo bloccando i record del set di risultati, senza la necessità di aggiornarli . In altre parole, stiamo bloccando esplicitamente i record. Naturalmente, una volta che li abbiamo bloccati, possiamo aggiornarli se vogliamo. I blocchi sui record vengono rilasciati quando eseguiamo il prossimo commit o rollback .

Quindi, per verificare se i blocchi funzionano, stiamo ora andando al secondo foglio di lavoro (il foglio di lavoro non condiviso che abbiamo aperto). Lì, se facciamo una selezione regolare, senza la “frase per l’aggiornamento”, otterremo il record senza alcun problema.

select * from worker where WorkerID = 1;

Ma poi, se ripetiamo la selezione, ora con la frase “for update” alla fine, si bloccherà, poiché un’altra transazione ha il record con WorkerID uguale a 1 bloccato, e stiamo cercando di bloccarlo di nuovo.

select * from worker where WorkerID = 1 for update;

Per sbloccarlo, basta tornare al primo foglio di lavoro e commit o rollback della transazione. Ora, torna al foglio di lavoro non condiviso e l’istruzione SQL dovrebbe essere eseguita, restituendo il record desiderato.

Blocco di record diversi

Una cosa importante da tenere a mente è che solo i record che fanno parte del set di risultati sono bloccati dalla transazione. Quindi, diverse transazioni possono fare “seleziona per l’aggiornamento” in diversi record.

Per testarlo, vai al primo foglio di lavoro e seleziona sia record 1 che 3, con la seguente frase di selezione:

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

Ora vai al foglio di lavoro non condiviso e prova a bloccare il record 2.

select * from worker where WorkerID = 2 for update;

Dovrebbe funzionare e restituire un risultato, poiché il record con WorkerID uguale a 2 non è stato bloccato dalla prima transazione. Ora, se nello stesso foglio di lavoro non condiviso proviamo a bloccare il record con Worker ID uguale a 1 o il record con Worker ID uguale a 3 (o entrambi), si bloccherà fino a quando non eseguiremo il commit o il rollback della transazione dal primo foglio di lavoro.

Contenuto correlato

  • Oracle Select for update statment

Write a Comment

Il tuo indirizzo email non sarà pubblicato.