Transaksjon er et begrep som omfatter metoder for å utføre databaseoperasjoner som sikrer korrekt utførelse. Metodene skal beskytte mot at det kan oppstå feil i data som følge av at databasen har mange samtidige brukere eller feil som fører til uventet stopp i utførelsen av alle eller et enkelt brukerprogram. 

Tilsynelatende riktige programmer kan gå feil fordi en database normalt har mange samtidige brukere. Hvorfor kan illustreres ved to banktjenester som utføres omtrent samtidig. Kunde A skal ta ut 1000 kroner fra konto X. Kunde B skal overføre 2500 kr fra konto Y til konto X. Programmene kan se slik ut: 

\(\begin{array}{rr}\begin{array}{|lll|}\hline &\texttt{Kunde A} & \\ \hline\texttt{tid}&\texttt{operasjon}&\texttt{kommentar} \\ \hline 1 & \texttt{s=les(X)} & \texttt{les X }\\2 & \texttt{s=s+1000} & \texttt{sett inn 1000}\\ 3 & \texttt{skriv(X,s)}& \texttt{oppdater X }\\ \hline\end{array} &\begin{array}{|lll|} \hline &\texttt{Kunde B} & \\ \hline\texttt{tid}&\texttt{operasjon}&\texttt{kommentar} \\ \hline1 & \texttt{r=les(Y)} & \texttt{les Y}\\2 & \texttt{r=r-2500} & \texttt{ta ut 2500}\\ 3 & \texttt{skriv(Y,r)}& \texttt{oppdater Y} \\ 4 & \texttt{r=les(X)} & \texttt{les X}\\5 & \texttt{r=r+2500} & \texttt{sett inn 2500}\\ 6 & \texttt{skriv(X,r)}& \texttt{oppdater X} \\ \hline \end{array} \end{array}\)

Når programmene skal utføres i praksis blir operasjonene fra forskjellige programmer flettet sammen for å oppnå god total ytelse og for at store programmer ikke skal stenge små programmer ute over lang tid.  Seksvensen av operasjonene innenfor samme program endres ikke. En aktuell utførelse kan se slik ut: 

\( \begin{array}{rr}\begin{array}{|lll|}\hline &\texttt{Kunde A} & \\ \hline\texttt{tid}&\texttt{operasjon}&\texttt{kommentar} \\ \hline 1 & & \\2 & & \\3 & & \\4 & & \\5 & \texttt{s=les(X)} & \texttt{les X (5000)}\\6 & \texttt{s=s+1000} & \texttt{sett inn 1000}\\ 7 & \texttt{skriv(X,s)}& \texttt{oppdater X(6000)}\\8 & & \\9 & & \\ \hline\end{array} &\begin{array}{|lll|} \hline &\texttt{Kunde B} & \\ \hline\texttt{tid}&\texttt{operasjon}&\texttt{kommentar} \\ \hline1 & \texttt{r=les(Y)} & \texttt{les Y}\\2 & \texttt{r=r-2500} & \texttt{ta ut 2500}\\ 3 & \texttt{skriv(Y,r)}& \texttt{oppdater Y} \\ 4 & \texttt{r=les(X)} & \texttt{les X (5000)}\\5 & & \\6 & & \\7 & & \\8 & \texttt{r=r+2500} & \texttt{sett inn 2500}\\ 9 & \texttt{skriv(X,r)}& \texttt{oppdater X (7500)} \\ \hline \end{array} \end{array}\)

Resultatet er ikke riktig. 1000 kroner som ble satt inn av kunde A er ikke kommet inn i databasen. Etter at begge programmer er utført burde konto X hatt 8500 kroner. 

Vi ser også at hvis kunde B sitt program hadde blitt avbrudt etter linje 4, ville 2500 kroner ha forsvunnet fra banken. 

Slike forhold er årsaken til at en grupperer databaseoperasjoner i transaksjoner. En transaksjon blir enten gjennomført eller annulert - alt eller intet. I eksemplet vil kunde B sin transaksjon bli annullert ved operasjonen i linje 9. Programmet vil da oppdage at det prøver å skrive over en post som er endret siden den ble lest.

 For å kunne annullere en transaksjon må utførelsen være gjenopprettbar, det vil si at alle endringer som er gjort av den annullerte transaksjon må kunne oppheves. Det er utviklet metoder som sikrer at transaksjoner blir korrekt utført. Det innebærer i praksis at databaseprogrammet har en strategi for hvordan operasjonene i forskjellige transaksjoner kan "flettes" sammen uten at det blir feil i databasen. 

Definisjonen av korrekt utførte transaksjoner er: 

  1. Utførelsen skal være ekvivalent med en seriell utførelse, og 
  2. transaksjonen må være gjenopprettbar.

En seriell utførelse er at hver transaksjon blir utført i sin helhet, den ene etter den andre. Hvis en har \(n\) samtidige transaksjoner finnes det \( n! = 1 \times 2 \times 3 \times \cdots \times n\) mulige sekvenser. For \(n=5\) er \(n!=120\). For \(n=10\) er \(n!=3\,628\,800\). Spillerommet øker voldsomt med høyere trafikk.

Ekvivalent seriell utførelse innebærer at alle konflikterende operasjoner i to transaksjoner må komme i samme sekvens. Det er bare operasjoner som endrer innholdet i databasen som kan skape konflikt. Vi forenkler det til en skriv-operasjon \(skriv_i(x)\) - transaksjon \(i\) skriver objekt \(x\). Hvis vi har operasjonene \( skriv_i(x), les_j(x) \) innebærer det at transaksjonen \(i\) utføres før transaksjon \(j\); \( T_i<T_j\). Operasjonene \(les_i(x), les_j(x)\) definerer ingen rekkefølge.  Sekvensen \(les_i(x), les_j(x), skriv_i(x), skriv_j(x)\) er ikke ekvivalent en seriell utførelse. Transaksjon \(j\) kommer foran \(i\)  på grunn av første skrivoperasjon og transaksjon \(i\) kommer foran \(j\) på grunn av den siste skrivoperasjonen. Begge kan ikke være først samtidig og sekvensen er ulovlig. 

Vi kan sette opp en sekvensgraf mellom alle transaksjoner, og hvis det er lukkede sløyfer i grafen så er ikke situasjonen forenlig med "ekvivalent seriell utførelse". 

Metoder for å oppnå ekvivalent seriell utførelse (serialiseringsalgoritmer) er basert på:

  1. Låsing av dataobjekter, se tofaselåsing. 
  2. Tidsstempling; når objektet blir skrevet registreres transaksjonenes identitet sammen med objektet, se varsom venting og såring/venting. Transaksjoner får et entydig transaksjonsnummer ved oppstart. Transaksjonsnummer tildeles fortløpende, derfor er en transaksjon med et større nummer yngre enn en transaksjon med et lavere nummer.
Ved låsing holder databasesystemet en liste over objekter som er i lest eller skrevet av hvilke transaksjoner. Når en transaksjon avsluttes (abort/komitt) frigjøres transaksjonens låser. 

Den andre betingelsen for at en transaksjon utføres korrekt er at den er gjenopprettbar (eng.: recoverable). Egentlig betyr det at databasen skal være gjenopprettbar. I tillegg til årsaker for avbrudt utførelse som er nevnt tidligere, kommer at en transaksjon må avbrytes (aborteres) fordi databaseprogrammet (serialiseringsalgoritmen) ikke er i stand til å gjennomføre en ekvivalent seriell utførelse.

Hovedregelen for å oppnå gjenopprettbarhet er at en ikke skal lese eller skrive over data som er skrevet av en fortsatt aktiv transaksjon, en såkalt ukommitert (eng.: uncommitted) transaksjon. Hvis transaksjonen skulle bli avbrudt vil skrevne objekter føres tilbake til det innhold de hadde når transaksjonen startet og da har en lest data som "aldri har eksistert". En transaksjon som skal lese eller skrive vil måtte vente hvis skriveren av objektet fortsatt "lever". Når den produserende transaksjonen avsluttes med enten abort eller komitt vil ventende transaksjoner starte opp igjen. 

Foreslå endringer i tekst

Foreslå bilder til artikkelen

Kommentarer

Har du spørsmål om artikkelen? Skriv her, så får du svar fra fagansvarlig eller redaktør.

Du må være logget inn for å kommentere.