1.1 Introducere

Și acum începe distracția - teoria modului în care funcționează tranzacțiile. Cum să mențineți sistemul să funcționeze când modificați aceleași date în fire diferite? Sau doriți să executați o tranzacție în alta? Vom începe să căutăm răspunsuri la aceste întrebări studiind izolarea tranzacțiilor...

Nivelul de izolare a tranzacției este o valoare condiționată care determină măsura în care, ca urmare a executării tranzacțiilor paralele logic în SGBD, sunt permise date inconsistente. Scara nivelurilor de izolare a tranzacțiilor conține un număr de valori, clasificate de la cel mai mic la cel mai mare; un nivel de izolare mai ridicat corespunde unei mai bune coerențe a datelor, dar utilizarea acestuia poate reduce numărul de tranzacții paralele fizic.

În schimb, un nivel de izolare mai scăzut permite mai multe tranzacții paralele, dar reduce acuratețea datelor. Astfel, alegând nivelul de izolare a tranzacțiilor utilizat, dezvoltatorul sistemului informațional, într-o anumită măsură, oferă o alegere între viteza de lucru și asigurarea consistenței garantate a datelor primite de la sistem.

Probleme de acces concurent folosind tranzacții

Când tranzacțiile sunt executate în paralel, sunt posibile următoarele probleme:

  • actualizare pierdută - dacă un bloc de date este schimbat simultan prin diferite tranzacții, toate modificările sunt pierdute, cu excepția ultimei;
  • citire „murdară” (ing. Dirty read) - citirea datelor adăugate sau modificate de o tranzacție, care ulterior nu vor fi confirmate (retrocedate);
  • non-repeatable read (ing. non-repeatable read) - la recitirea în cadrul aceleiași tranzacții, datele citite anterior sunt modificate;
  • citiri fantomă - o tranzacție în timpul executării ei selectează de mai multe ori mai multe rânduri conform acelorași criterii. O altă tranzacție între aceste preluari adaugă rânduri sau modifică coloane ale unora dintre rândurile utilizate în criteriile de preluare ale primei tranzacții și se încheie cu succes. Ca rezultat, se va dovedi că aceleași selecții din prima tranzacție dau seturi diferite de rânduri.

Luați în considerare situațiile în care pot apărea aceste probleme.

1.2 Actualizare pierdută

Situația în care, atunci când un bloc de date este schimbat simultan prin diferite tranzacții, una dintre modificări se pierde.

Să presupunem că există două tranzacții care rulează în același timp:

Tranzacția 1 Tranzacția 2
UPDATE tbl1 SET f2=f2+20 UNDE f1=1; UPDATE tbl1 SET f2=f2+25 UNDE f1=1;

În ambele tranzacții, valoarea câmpului f2 se modifică, la finalizare, valoarea câmpului trebuie mărită cu 45. De fapt, poate apărea următoarea secvență de acțiuni:

  1. Ambele tranzacții citesc simultan starea curentă a câmpului. Concurența fizică exactă nu este necesară aici, este suficient ca a doua operație de citire în ordine să fie finalizată înainte ca o altă tranzacție să-și scrie rezultatul.
  2. Ambele tranzacții calculează noua valoare a câmpului adăugând 20 și, respectiv, 25 la valoarea citită anterior.
  3. Tranzacțiile încearcă să scrie rezultatul calculului înapoi în câmpul f2. Deoarece este fizic imposibil să efectuați două scrieri în același timp, în realitate una dintre operațiunile de scriere va fi efectuată mai devreme, cealaltă mai târziu. A doua operație de scriere va suprascrie rezultatul primei.

Ca urmare, valoarea câmpului f2, la finalizarea ambelor tranzacții, poate crește nu cu 45, ci cu 20 sau 25, adică una dintre tranzacțiile de schimbare a datelor va „dispără”.

1.3 Citirea „murdară”.

Citirea datelor adăugate sau modificate de o tranzacție care nu va reuși ulterior să se comite (rollback).

Să presupunem că avem două tranzacții deschise de aplicații diferite care execută următoarele instrucțiuni SQL:

Tranzacția 1 Tranzacția 2
UPDATE tbl1 SET f2=f2+1 UNDE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
LUCRARE ROLLBACK;

În tranzacția 1, valoarea câmpului f2 este modificată, iar apoi în tranzacția 2, valoarea acestui câmp este selectată. După aceea, tranzacția 1 este anulată. Ca urmare, valoarea primită de a doua tranzacție va diferi de valoarea stocată în baza de date.

1.4 Lectură nerepetabilă

Situația în care, la recitirea în cadrul aceleiași tranzacții, datele citite anterior se dovedește a fi modificată.

Să presupunem că avem două tranzacții deschise de aplicații diferite care execută următoarele instrucțiuni SQL:

Tranzacția 1 Tranzacția 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+3 UNDE f1=1;
COMIT;
SELECT f2 FROM tbl1 WHERE f1=1;

În tranzacția 2, valoarea câmpului f2 este selectată, apoi în tranzacția 1, valoarea câmpului f2 este modificată. Dacă încercați din nou să selectați o valoare din câmpul f2 din tranzacția 2, se va obține un rezultat diferit. Această situație este mai ales inacceptabilă atunci când datele sunt citite pentru a le modifica parțial și a le scrie înapoi în baza de date.

1.5 Citirea „fantome”

Situația în care, în timpul citirii repetate în cadrul aceleiași tranzacții, aceeași selecție dă seturi diferite de rânduri.

Să presupunem că există două tranzacții deschise de aplicații diferite care execută următoarele instrucțiuni SQL:

Tranzacția 1 Tranzacția 2
SELECTARE SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES(15,20);
COMIT;
SELECTARE SUM(f2) FROM tbl1;

Tranzacția 2 execută o instrucțiune SQL care utilizează toate valorile câmpului f2. Apoi, un nou rând este inserat în tranzacția 1, determinând ca reexecuția instrucțiunii SQL din tranzacția 2 să producă un rezultat diferit. Această situație se numește citire fantomă (lectura fantomă). Diferă de citirea nerepetabilă prin faptul că rezultatul accesului repetat la date s-a modificat nu datorită modificării/ștergerii datelor în sine, ci datorită apariției unor date noi (fantomă).