Rezumat: În această prelegere vom analiza mai atent noțiunea de "tranzacție", vom învăța cum InterBase asigură operarea tranzacțiilor, se familiarizează cu arhitectura multi-versiune și învață nivelurile de izolare a tranzacțiilor. Într-un exemplu practic, vom crea o aplicație care funcționează simultan cu două tranzacții.
De-a lungul cursului, am întâlnit adesea acest termen. Subiectul "tranzacțiilor" în InterBase nu este simplu, dar este foarte necesar pentru înțelegere. Această prelegere este dedicată teoriei tranzacțiilor. și practica aplicațiilor lor în aplicații.
În "Introducere în bazele de date client-server, InterBase" am menționat că tranzacțiile reprezintă un pachet de interogări care modifică în mod consecvent modificările bazei de date și fie sunt acceptate dacă toate modificările înregistrate sunt confirmate sau respinse dacă cel puțin o cerere eșuează. Interogările pot consta în instrucțiuni SELECT / INSERT / UPDATE / DELETE. iar în contextul unei tranzacții poate exista o astfel de solicitare. și o mulțime de cereri. Cu toate acestea, conceptul de "tranzacție" este mult mai profund decât această definiție scurtă.
Tranzacțiile sunt executate pe partea de server și pornesc numai la comenzile aplicației client. Acestea sunt, de asemenea, terminate de ordinul cererii clientului și, după finalizarea cu succes, tranzacția este confirmată și, dacă nu, este respinsă. În declanșatoare sau proceduri, tranzacția nu poate fi pornită.
Transaction. de fapt, acesta este un mecanism care vă permite să efectuați diverse acțiuni pe baza de date, ca un singur bloc logic și care traduce baza de date dintr-o stare holistică în alta. Sau nu se traduce dacă tranzacția a fost respinsă.
Să explicăm acest punct pe exemplul clasic de transfer de bani de la un cont la altul într-o bancă.
Să presupunem că baza noastră de date funcționează fără tranzacții. și trebuie să facem traducerea menționată. Aici putem acționa în două moduri diferite:
- În primul rând, retragem bani dintr-un cont, apoi le adăugăm la alt cont.
- Mai întâi adăugăm bani în alt cont, apoi le eliminăm din primul cont.
Acum, să presupunem că în mijlocul acestei operațiuni a existat un fel de eșec: serverul bazei de date a fost deconectat. de exemplu. În primul caz, banii vor fi pierduți - au plecat cu un cont, dar nu au ajuns la celălalt. În cel de-al doilea caz, banii "se înmulțesc" - apar în cel de-al doilea cont, dar în același timp rămân pe primul. Și în acest caz și într-un alt caz va exista o încălcare a integrității bazei de date - datele vor deveni nesigure.
Cu toate acestea, toate serverele de baze de date SQL funcționează cu utilizarea tranzacțiilor. Se mai spune că toate modificările aduse bazei de date apar în contextul uneia sau mai multor tranzacții. InterBase nu face excepție. În plus, InterBase oferă instrumente mult mai flexibile pentru gestionarea tranzacțiilor. decât multe alte servere SQL. Dacă a existat un eșec în transferarea banilor, tranzacția nu a fost confirmată, iar baza de date a rămas în aceeași stare - integritatea și fiabilitatea bazei de date nu au fost încălcate.
Atomicitate (atomicitate)
Atomicitatea implică faptul că tranzacția este o unitate de lucru cu baza de date. În interiorul tranzacției pot apărea multe modificări ale bazei de date. Cu toate acestea, tranzacția funcționează pe principiul "tot sau nimic". Atunci când o tranzacție este confirmată (Commit), atunci toate modificările de date făcute în contextul său sunt confirmate. Când este respins (returnare, returnare), toate modificările sunt respinse. În caz de eșec, sistemul, recuperarea, elimină consecințele tranzacțiilor. fără să aibă timp să fie finalizat.
Consistența (consistență)
Se înțelege consistența că integritatea bazei de date nu este încălcată, indiferent dacă tranzacția a fost confirmată. sau respins. Ca urmare a tranzacției, baza de date se mută dintr-o stare coerentă și consecventă la alta. Dacă tranzacția este respinsă, nu există nicio modificare a bazei de date.
Pe partea de server, constrângerile CHECK sunt responsabile de coerență. constrângerile și declanșatoarele de integritate referențială. Programatorul, cu toate acestea, trebuie să elaboreze cu atenție mecanismele logicii de afaceri.
Izolarea (izolare)
Un număr de tranzacții pot fi efectuate simultan în baza de date. Se întâmplă ca două sau mai multe tranzacții să încerce să schimbe aceeași înregistrare. Pentru a asigura integritatea datelor, tranzacțiile se efectuează separat unele de altele. Puteți spune că fiecare tranzacție funcționează cu copia (versiunea) datelor. Există mai multe grade de izolare a tranzacțiilor. despre ce vom mai vorbi în detaliu.
Stabilitate (durabilitate)
În cazul în care tranzacția se încheie cu succes, modificările aduse în contextul său ar trebui să fie stabile și menținute, indiferent de erorile din alte tranzacții. erorile hardware sau închiderea serverului. Cu alte cuvinte, rezultatele unei tranzacții finalizate cu succes sunt stocate fizic în baza de date.
Implicarea și începerea explicită a tranzacțiilor
Toate acțiunile din baza de date efectuate în aplicația client apar în contextul tranzacției. În exemplele prelegerilor precedente, am conectat aplicațiile client la baza de date, fără a utiliza deloc tranzacții. Cu toate acestea, acest lucru nu înseamnă că nu au fost. Pur și simplu tranzacțiile au fost lansate implicit, automat. Și cu parametrii creați de Delphi "implicit". În aplicațiile serioase de baze de date, acest lucru este inacceptabil, deoarece poate duce la numeroase conflicte.
Puteți începe tranzacția în mod explicit. Din mecanismele standard de acces, vom folosi în principal InterBase Express (IBX). Cererea trebuie să fie prezentă cel puțin. o componentă a tranzacției IBT. Cu această componentă, puteți specifica în mod explicit parametrii tranzacției. controlați începerea, confirmarea sau revocarea unei tranzacții. Acest lucru se face folosind următoarele metode componente:
- StartTransaction - Începeți tranzacția.
- Commit - Confirmarea tranzacției cu închiderea ulterioară.
- CommitRetaining - Confirmarea unei tranzacții fără ao închide.
- Rollback - Revocarea tranzacției cu închiderea ulterioară.
- RollbackRetaining - Revocare fără închidere.
Cu toate acestea, componentele de acces la date execută implicit tranzacția. prin urmare, StartTransaction este, de obicei, omis. Dar confirmarea sau revocarea tranzacției este verificată, de regulă, în încercarea ... cu excepția blocului din aplicația client:
În acest exemplu, dacă tranzacția a avut succes, datele sunt în mod normal stocate. În cazul unei erori, se afișează un mesaj și tranzacția este derulată înapoi.
Cum funcționează tranzacția
Există o zonă specială în baza de date numită TIP (Pagina de inventariere a tranzacțiilor). Când începe tranzacția. i se atribuie un identificator (TID, ID de tranzacție) - un număr de inventar stocat în TIP. Cea mai recentă tranzacție va avea cel mai mare identificator. În TIP. în plus față de numărul tranzacției inițiate. Starea sa este de asemenea conservată, care poate fi activă, angajată, înfășurată în spate și în limbo.
Activ este numit o tranzacție. care rulează în prezent.
Confirmat este tranzacția. care și-a finalizat cu succes activitatea, de obicei pe comanda Commit.
Se solicită tranzacția anulată. care sa încheiat fără succes. În acest caz, acțiunile întreprinse de acesta sunt derulate înapoi, de obicei prin comanda RollBack.
O tranzacție nedefinită (Limbo) este o tranzacție. care funcționează simultan cu două sau mai multe baze de date. La încheierea unei astfel de tranzacții. InterBase efectuează o confirmare în două faze a comitetului. asigurându-se că vor fi efectuate modificări ale întregii baze de date. sau nu. În acest caz, confirmările din bazele de date vor fi furnizate la rândul lor. Dacă în acest moment va exista un accident de sistem, atunci se poate întâmpla ca într-un fel de bază de date s-au făcut modificări, dar în care nu există. În acest caz, tranzacția intră într-o stare nedefinită, atunci când serverul nu știe dacă să confirme această tranzacție. sau răsturnarea.
Fiecare tranzacție. începerea lucrării, creează propria versiune a înregistrărilor tabelelor cu care funcționează. Versiunea de înregistrare este o copie a înregistrării create atunci când tranzacția încearcă să o modifice. Astfel, fiecare intrare tabelă poate avea mai multe versiuni, fiecare tranzacție funcționând cu propria versiune a acestei înregistrări. Dacă o tranzacție modifică date, le schimbă în propria versiune a înregistrării, și nu în original. Apoi tranzacția poate fi confirmată sau anulată.
Dacă tranzacția este confirmată, InterBase va încerca să marcheze intrarea originală anterioară. ca distanță, iar versiunea tranzacției finalizată ca fiind originală. Când InterBase salvează modificări, ID-ul tranzacției este, de asemenea, plasat în noua înregistrare. care a făcut aceste modificări (orice rând din tabel conține identificatorul tranzacției care a creat-o).
Dacă tranzacția nu reușește, originalul înregistrării rămâne originalul.
Dacă tranzacția citește doar înregistrarea. nu încercând să o schimbe, atunci nu creează propria versiune.
Cu toate acestea, pot exista conflicte de tranzacții. Să presupunem că tranzacția T1 a început. Ea a creat versiunea înregistrării și și-a schimbat datele. În acel moment, tranzacția concurente T2 a început și a creat o versiune a aceleiași înregistrări. Deoarece T1 nu a fost încă finalizată, T2 nu a putut vedea modificările date de T1 și, prin urmare, și-a creat versiunea proprie de pe originalul vechi. Acum, T1 termină lucrul la Commit. Ce ar trebui să facă InterBase? Dacă marchează versiunea înregistrării T1 ca originală, dar vechea înregistrare. ca distanță, atunci versiunea T2 va fi date false! Acțiunile InterBase în acest caz vor depinde de parametrii acestor tranzacții. despre care mai jos vom vorbi în detaliu.
Dacă o tranzacție șterge un rând, șirul nu este îndepărtat fizic din baza de date. dar marcat doar ca distanță, economisind și numărul tranzacției care a șters-o. În cazul în care tranzacția nu reușește, nu există nicio ștergere efectivă a liniei, deoarece nu a existat nicio confirmare.
Astfel, ei spun că InterBase are o arhitectură multi-versiune (MGA - Multi-Generation Architecture). Această arhitectură vă permite să organizați lucrul cu baza de date, astfel încât utilizatorii de lectură să nu blocheze scriitorii. În plus, atunci când un sistem se blochează, InterBase este foarte rapid restaurat, grație MGA. Apropo, InterBase este primul server SQL care suporta arhitectura multi-versiune.
Împreună cu avantajele acestei abordări, "gunoi" se acumulează în baza de date în timp. Fiecare tranzacție. încercarea de a schimba datele, creează propria versiune a liniilor, iar dacă nu avea grijă de eliminarea la timp a mai vechi, versiuni deja inutile ale bazei de date va fi în curând doar înfundate moloz.
Dar cum să eliminați gunoi? Pot șterge versiunea tranzacției. care sa încheiat, cu succes sau fără succes? Nu, dacă această versiune este utilizată în prezent de alte tranzacții. Mai târziu, vom vorbi despre nivelurile de izolare a tranzacțiilor. până acum doar spun că unele tranzacții pot vedea modificările aduse de alte persoane care nu au fost încă confirmate de tranzacțiile active.
Să presupunem că tranzacția T1 a început. Această tranzacție a creat versiunea înregistrării și a modificat-o. Ulterior, a început tranzacția T2, care este configurată pentru a vedea toate modificările de date, chiar și cele neconfirmate. Sa întors la aceeași înregistrare și, din moment ce dorește să vadă cele mai recente modificări, i se oferă o versiune a tranzacției T1. Apoi, T1 și-a încheiat activitatea, dar T2 continuă să funcționeze cu versiunea sa a înregistrării, prin urmare această versiune nu poate fi ștearsă.
InterBase are un mecanism de eliminare a versiunilor vechi, care este inițiat de noi tranzacții. Noua tranzacție. solicitând o înregistrare. citește toate versiunile acestei înregistrări. Aceasta verifică dacă tranzacția a fost. versiunea care a făcut această versiune este anulată (RollBack) sau confirmată (Commit). Dacă tranzacția a fost anulată, atunci această versiune este gunoi, care trebuie șters. Dacă există mai multe versiuni efectuate prin tranzacții confirmate. versiunea cu cel mai mare identificator de tranzacție este considerată relevantă. Versiunile rămase sunt considerate învechite și sunt, de asemenea, supuse eliminării.
Astfel, tranzacțiile tinere ordonază baza de date din gunoiul lăsat de tranzacțiile mai vechi. Dar nu curăță toate versiunile vechi la rând, ci doar versiuni ale acelei înregistrări (sau înregistrări) la care se adresează ei înșiși.
Deoarece multe tranzacții pot fi efectuate pe server în același timp. există o terminologie pentru determinarea acestor tranzacții.
- O tranzacție activă este o tranzacție care a început, dar nu este încă finalizată.
- O tranzacție de interes este o tranzacție care concurează cu tranzacția curentă.
- Cea mai veche tranzacție activă este o astfel de tranzacție activă. care a început în fața altora. Sau este o tranzacție activă cu cel mai mic identificator.
- Cea mai veche tranzacție interesată este o astfel de tranzacție interesată. care a început în fața altora. Sau altfel, este o tranzacție interesată cu cel mai mic identificator.
În acest context, cea mai veche tranzacție activă este angajată în colectarea gunoiului. Deoarece versiunile înregistrate se fac prin tranzacții mai tinere. ea nu poate vedea, atunci ea elimină gunoi de stânga de tranzacții chiar mai mari. Când această tranzacție își încheie activitatea, statutul de "cel mai vechi activ" se referă la o altă tranzacție. Astfel, tranzacțiile își transferă reciproc responsabilitatea pentru colectarea gunoiului.