Oracle SQL: row locking on select statement

Obiectivul acestui post este de a explica modul de blocare a unei înregistrări pe o bază de date Oracle, folosind o declarație select.

Introducere

Obiectivul acestei postări este de a explica cum să blocați o înregistrare într-o bază de date Oracle, folosind o instrucțiune select. Acest lucru ne permite să blocăm o înregistrare fără a fi nevoie să o schimbăm.

deși acest lucru poate să nu pară un caz de utilizare foarte obișnuit, adevărul este că este posibil să avem nevoie de el pentru programe mai complexe (implementate, de exemplu, în PL/SQL), unde trebuie să facem unele validări complexe înainte de a decide să actualizăm un anumit registru și trebuie să îl menținem blocat în timpul acestor validări, astfel încât nicio altă tranzacție să nu o poată modifica simultan.

vom folosi SQL Developer pentru a interacționa cu baza de date și pentru a efectua interogările pentru acest tutorial.

blocarea aceeași înregistrare

ca de obicei, vom începe prin crearea unui tabel fals simplu, să dețină datele noastre. Verificați exemplul creare de mai jos.

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

după aceea, vom introduce câteva înregistrări fictive, deci avem date la care să lucrăm. Vom introduce trei înregistrări și apoi vom comite tranzacția. Puteți utiliza butonul commit din meniul SQL Developer sau puteți comite în mod explicit tranzacția cu o instrucțiune SQL.

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

acum vom deschide o nouă foaie de lucru nepartajată, pentru a putea testa declarațiile SQL în tranzacții independente. Verificați figura 1 cu privire la modul de a face acest lucru. Puteți citi mai multe despre SQL Developer unshared foi de lucru în acest post anterior.

SQL Developer unshared foaie de lucru

Figura 1 – deschiderea unei noi foi de lucru unshared.

acum, primul lucru pe care îl vom face este să executăm o selecție obișnuită în ambele foi de lucru. Vom face o selectați pentru a obține înregistrarea în cazul în care WorkerID este egal cu 1. Nu face orice comiteri sau rollbacks, doar executa aceeași interogare în ambele foi de lucru.

select * from worker where WorkerID = 1;

după cum era de așteptat, nu există nicio problemă cu concurența și vom primi înregistrarea în ambele tranzacții (cu numele de lucru egal cu „John”).

acum, vom reveni la prima foaie de lucru (aceeași în care am creat tabelul) și vom adăuga o clauză „pentru actualizare” la sfârșitul instrucțiunii select, așa cum este indicat mai jos. Din nou, nu face nici un angajament sau rollback.

select * from worker where WorkerID = 1 for update;

când facem acest lucru, blocăm înregistrările setului de rezultate, fără a fi nevoie să le actualizăm . Cu alte cuvinte, blocăm în mod explicit înregistrările. Desigur, odată ce le-am blocat, le putem actualiza dacă dorim. Încuietorile de pe înregistrările sunt eliberate atunci când facem următoarea comite sau rollback .

deci, pentru a testa dacă blocările funcționează, mergem acum la a doua foaie de lucru (foaia de lucru neîmpărțită pe care am deschis-o). Acolo, dacă facem o selecție regulată, fără „pentru propoziția de actualizare”, vom obține înregistrarea fără nicio problemă.

select * from worker where WorkerID = 1;

dar apoi, dacă repetăm select, acum cu propoziția „pentru actualizare” în cele din urmă, se va închide, deoarece altă tranzacție are înregistrarea cu WorkerID egal cu 1 blocat și încercăm să o blocăm din nou.

select * from worker where WorkerID = 1 for update;

pentru a debloca, du-te înapoi la prima foaie de lucru și comite sau rollback tranzacția. Acum, reveniți la foaia de lucru nepartajată și instrucțiunea SQL ar fi trebuit executată, returnând înregistrarea dorită.

blocarea diferitelor înregistrări

un lucru important de reținut este că numai înregistrările care fac parte din setul de rezultate sunt blocate de tranzacție. Deci, diferite tranzacții pot face „Selectați pentru actualizare” în diferite înregistrări.

pentru a testa acest lucru, accesați prima foaie de lucru și selectați atât înregistrarea 1, cât și 3, cu următoarea propoziție select:

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

acum mergeți la foaia de lucru nepartajată și încercați să blocați înregistrarea 2.

select * from worker where WorkerID = 2 for update;

ar trebui să funcționeze și să returneze un rezultat, deoarece înregistrarea cu WorkerID egală cu 2 nu a fost blocată de prima tranzacție. Acum, dacă în aceeași foaie de lucru nepartajată încercăm să blocăm înregistrarea cu ID-ul lucrătorului egal cu 1 sau înregistrarea cu ID-ul lucrătorului egal cu 3 (sau ambele), aceasta va atârna până când comitem sau revenim tranzacția din prima foaie de lucru.

conținut înrudit

  • Oracle Select for update statment

Write a Comment

Adresa ta de email nu va fi publicată.