mk-prg-net \ ms-sql \ tsql \queries \transactions

Transaktionen

Transaktion

Eine Transaktion ist eine Folge von T-SQL Anweisungen, die mit dem Befehl Begin Transaction eingeleitet, und mit den Befehlen Commit Transaction oder Rollback Transaction beendet werden.

Werden alle Anweisungen innerhalb einer Transaktion erfolgreich ausgeführt, dann muß die Tranwsaktion mit Commit Transaction abschließen, und die durch Anweisungen bewirkten Datenänderungen werden dauerhaft in der Datenbank übernommen.

Andernfalls muß die Transaktion durch Rollback Transaction beendet werden. In diesem Falle werden alle Datenänderungen wieder zurückgenommen, und die Datenbank befindet sich in dem Zustand wie vor der Ausführung der Transaktion.

ACID

ACID ist ein Akronym und steht für die vier Anforderungen, die eine Transaktion erfüllen muß: Atomicity (Unteilbarkeit), Consistency (Konsistenz), Isolation (Isolation), Durability (Dauerhaftigkeit).

Unteilbarkeit
Unteilbarkeit bedeutet, das ein Transaktion entweder erfolgreich durchgeführt wird (Commit), oder nach Abbruch das System sich wieder im Zustand unmittelbar vor Beginn der Transaktion befindet (Rollback).
Konsitenz
Befindet sich die Datenbank vor der Ausführung einer Transaktion in einem Konsitenten Zustand, dann wird sie es auch nach der Transaktion wieder sein.
Isoloation

Isolation beschreibt, wie unabhängig parallel ablaufende Transaktionen voneinander sind.

Kann eingestellt werden über die Option SET trANSACTION ISOLATION LEVEL.

Dauerhaftigkeit
Wird ein Commit ausgeführt, dann sind die Datenänderungen, auch bei plötzlich auftretenden Systemfehlern definitiv in die Datenbank zu übernehmen.

Transaktionsmodi

Expliziter Modus

Im expliziten Modus werden Transaktionen durch spezielle Anweisungen im Script eröffnet und abgeschlossen.

  BEGIN TRANSACTION <Transaktionsname>
...
if <alles ok>
   COMMIT trANSAKTION <Transaktionsname>
else 
   ROLLBACK TRANSACTION <Transaktionsname | Sicherungspunktname>   
  

Beispiel:

  create table Sparkonto (
        ktnr    int primary key,
        guthaben money not null default(0)
)
go
create table Girokonto (
        ktnr    int primary key,
        guthaben money not null default(0)
)
go
insert into Sparkonto values(4711, 1000)
insert into Sparkonto values(6969, 2000)
insert into Girokonto values(4711, 1500)
insert into Girokonto (ktnr) values(6969)
go
select * from Sparkonto
select * from Girokonto
begin try
        print 'Anz Transaktionen: ' + Cast(@@trancount as varchar(20))
        BEGIN trANSACTION ueberweisung          
                print 'Anz Transaktionen: ' + Cast(@@trancount as varchar(20))
                BEGIN trANSACTION innerTrans
                        print 'Anz Transaktionen: ' + Cast(@@trancount as varchar(20))
                Commit transaction                      
                update Sparkonto Set guthaben = guthaben - 1000 where ktnr = 4711
                --RAISERROR ('Fehler in einer Transaktion', 15, 1)
                update Girokonto Set guthaben = guthaben + 1000 where ktnr = 4711
                update Sparkonto Set guthaben = guthaben - 1000 where ktnr = 6969       
                SAVE trANSACTION spt1
                print 'Anz Transaktionen: ' + Cast(@@trancount as varchar(20))
                update Girokonto Set guthaben = guthaben + 1000 where ktnr = 6969
                RAISERROR ('Fehler in einer Transaktion', 15, 2)
        Commit Transaction 
end try 
begin catch
        if Error_state() = 2    
                begin 
                        ROLLBACK trANSACTION  spt1              
                        -- In jedem Fall wird die Transaktion beendet
                        Commit Transaction
                end 
        else 
                ROLLBACK trANSACTION
        
    SELECT
                ERROR_NUMBER() AS ErrorNumber,
                ERROR_SEVERITY() AS ErrorSeverity,
                ERROR_STATE() AS ErrorState,
                ERROR_PROCEDURE() AS ErrorProcedure,
                ERROR_LINE() AS ErrorLine,
                ERROR_MESSAGE() AS ErrorMessage
end catch
print 'Anz Transaktionen: ' + Cast(@@trancount as varchar(20))
go
select * from Sparkonto
select * from Girokonto
Verbotene Anweisungen in expliziten Transaktionen

Folgende Anweisungen sind innerhalb von Transaktionen verboten:

  1. ALTER DATABASE
  2. BACKUP LOG
  3. CREATE DATABASE
  4. DROP DATABASE
  5. RECONFIGURE
  6. RESTORE DATABASE
  7. RESTORE LOG
  8. UPDATE STATISTICS
Sicherungspunkte

Innerhalb einer Transaktion können Sicherungspunkte gesetzt werden. Sicherungspunkte stellen Markierungen im Transaktionsprotokoll dar. Ein Rollback kann in seiner Wirkung eingeschränkt werden, indem im Rollback- Befehl der Name des Sicherungspunktes angegeben wird, bis zu dem der Rollback erfolgen soll.

  BEGIN TRANSACTION <Transaktionsname>
...
SAVE TRANSACTION spt1
if <alles ok>
    ...
   if @@error > 0
      ROLLBACK trANSACTION spt1          -– Alle Änderungen nach spt1 werden zurückgenommen
   COMMIT trANSAKTION <Transaktionsname> -- Alles bis dato nicht zurückgenommenewird bestätigt
else 
   ROLLBACK TRANSACTION <Transaktionsname | Sicherungspunktname>   

Autocommit

Jede Anweisung, die Daten ändert, ist automatisch in eine Transaktion eingeschlossen. Die Anweisung:

  insert into tab1 values('Anto', 'm')
go

wird vom Server automatisch in eine Transaktion wie folgt verpackt:

  begin transaction
insert into tab1 values('Anto', 'm')
commit transaction
go

Werden eine Vielzahl von Datenänderungsanweisungen in Folge abgesetzt, so kann die Serverlast minimiert werden, indem alle in ein explizite Transaktion verpackt werden wie folgt:

  begin transaction
insert into tab1 values('Anto', 'm')
insert into tab1 values('Berta', 'm')
insert into tab1 values('Cäsar', 'm')
commit transaction

Anstatt 9 Einträge, wie es im Autocommit- Modus der Fall wäre, erfolgen jetzt nur noch 5 Einträge im Transaktionsprotokoll.

Impliziter Modus

Implizite Transaktionen werden im SQL- Server bereitgestellt, um ANSI- Konformität zu erreichen. Der Implizite Modus muss mit folgender Anweisung aktiviert bzw. deaktiviert werden:

SET IMPLICIT_trANSACTIONS ON | OFF

Folgende Anweisungen müssen dann mittels COMMIT trAN oder ROLLBACK trAN quittiert werden:

  1. ALTER TABLE
  2. CREATE TABLE
  3. DROP
  4. INSERT
  5. UPDATE
  6. DELETE
  7. FETCH
  8. GRANT
  9. REVOKE
  10. SELECT
  11. trUNCATE TABLE
  12. OPEN
  SET IMPLICIT_trANSACTIONS ON
insert into tab1 values('Anto', 'm')
// Das Commit ist hier notwendig, da implizit eine Transation eröffnet wurde 
// (darf nicht vergessen werden !)
commit transaction

Anzahl der aktiven Transaktionen pro Verbindung

Select @@trANCOUNT

Isolationsstufen

Für alle in einer Transaktion eingeschlossenen Abfragen können Sperrhinweise definiert werden durch den Transaction Isolation Level. Dieser wird gesetzt durch folgendes Kommando

SET TRANSACTION ISOLATION LEVEL {READ COMMITED | READ UNCOMMITED | REPEATEBLE READ | SERIALIZABLE }

Der Standardwert ist READ COMMITED.

Die Isolationsstufen im Einzelnen:

Isolationsstufe

Details

READ COMMITED

Nur Daten werden gelesen, die zuvor mit einer Lesesperre belegt werden konnten. Dirty Reads sind nicht möglich.

READ UNCOMMITED

Es werden keine Sperren gesetzt. Dirty Reads sind möglich

REPEATABLE READ

Lesesperren werden erst nach dem Ende der Transaktion aufgehoben. Wiederholte Select- Abfragen innerhalb einer Transaktion führen zu identischen Resultsets, wenn zwischen diesen keine Änderungsoperationen innerhalb der Transaktion vorgenommen wurden. Änderungsoperationen andere Transaktionen sind während der gesamten Verarbeitung einer Transaktion blockiert.

SERIALIZABLE

Wie REPEATABLE READ, zusätzlich werden noch Einfügeoperationen anderer Transaktionen verhindert.