← Tilbage til koncepter

Database Transactions

Teori

En logisk enhed af arbejde der grupperer flere database operationer til en atomic unit med ACID garantier.

Beskrivelse

Databasetransaktioner er fundamentale for at sikre dataintegritet i flerbrugerdatabasesystemer. En transaktion er en sekvens af operationer der udføres som en enkelt logisk arbejdsenhed - enten succeeder alle operationer, eller ingen af dem gør. Dette 'alt eller intet'-princip kaldes atomicitet. Transaktioner følger ACID-egenskaber: Atomicitet (alt eller intet), Konsistens (databasen går fra en gyldig tilstand til en anden gyldig tilstand), Isolation (samtidige transaktioner påvirker ikke hinanden) og Varighed (committede ændringer overlever systemnedbrud). Transaktioner starter med BEGIN eller START TRANSACTION, indeholder en eller flere SQL-sætninger (INSERT, UPDATE, DELETE, SELECT) og slutter med enten COMMIT (gem ændringer permanent) eller ROLLBACK (fortryd alle ændringer). Savepoints tillader delvis rollback indenfor en transaktion. Transaktioner er kritiske i scenarier som bankoverførsler (debitering fra én konto, kreditering til anden - begge skal ske), lagerstyring (tjek lager, reducer mængde - skal være atomisk) og bookingsystemer.

Problem

Uden transaktioner kan databaseoperationer fejle midtvejs og efterlade databasen i en inkonsistent tilstand. For eksempel: hvis en bankoverførsel fejler efter debitering men før kreditering, er penge tabt. Samtidige brugere kan også se delvise opdateringer eller overskrive hinandens ændringer.

Løsning

Transaktioner grupperer relaterede operationer og garanterer at enten alle succeeder (COMMIT) eller alle fortrudes (ROLLBACK). Dette sikrer datakonsistens selv ved fejl. Isolationsniveauer kontrollerer hvordan samtidige transaktioner ser hinandens ændringer.

Eksempel

-- Klassisk bank transfer eksempel
BEGIN TRANSACTION;

-- Tjek om der er nok balance
SELECT balance FROM accounts WHERE account_id = 123;
-- Antag balance er 1000

-- Deduct fra sender
UPDATE accounts 
SET balance = balance - 500 
WHERE account_id = 123;

-- Add til receiver
UPDATE accounts 
SET balance = balance + 500 
WHERE account_id = 456;

-- Hvis begge updates succeed:
COMMIT;

-- Hvis noget fejler:
-- ROLLBACK;

-- E-commerce inventory eksempel
BEGIN TRANSACTION;

-- Tjek stock
SELECT stock FROM products WHERE product_id = 789;
-- Antag stock = 10

IF stock >= quantity_ordered THEN
  -- Reducer stock
  UPDATE products 
  SET stock = stock - 3 
  WHERE product_id = 789;
  
  -- Opret order
  INSERT INTO orders (customer_id, product_id, quantity) 
  VALUES (101, 789, 3);
  
  COMMIT;
ELSE
  ROLLBACK;
END IF;

-- Savepoints (partial rollback)
BEGIN TRANSACTION;

INSERT INTO users (name) VALUES ('User 1');
SAVEPOINT sp1;

INSERT INTO users (name) VALUES ('User 2');
SAVEPOINT sp2;

INSERT INTO users (name) VALUES ('User 3');

-- Rollback til sp2 (kun User 3 fortrudes)
ROLLBACK TO SAVEPOINT sp2;

COMMIT; -- User 1 og 2 gemmes

-- Node.js med SQL transaction
const connection = await pool.getConnection();

try {
  await connection.beginTransaction();
  
  // Multiple operations
  await connection.query(
    'UPDATE accounts SET balance = balance - ? WHERE id = ?',
    [amount, fromAccount]
  );
  
  await connection.query(
    'UPDATE accounts SET balance = balance + ? WHERE id = ?',
    [amount, toAccount]
  );
  
  // Log transfer
  await connection.query(
    'INSERT INTO transfers (from_account, to_account, amount) VALUES (?, ?, ?)',
    [fromAccount, toAccount, amount]
  );
  
  await connection.commit();
  console.log('Transfer successful');
  
} catch (error) {
  await connection.rollback();
  console.error('Transfer failed, rolled back:', error);
  throw error;
  
} finally {
  connection.release();
}

-- MongoDB transactions (replica set required)
const session = client.startSession();

try {
  session.startTransaction();
  
  await accountsCollection.updateOne(
    { _id: fromAccountId },
    { $inc: { balance: -amount } },
    { session }
  );
  
  await accountsCollection.updateOne(
    { _id: toAccountId },
    { $inc: { balance: amount } },
    { session }
  );
  
  await session.commitTransaction();
  
} catch (error) {
  await session.abortTransaction();
  throw error;
  
} finally {
  await session.endSession();
}

Fordele

  • Datakonsistens garanteret
  • Atomicitet - alt eller intet
  • Genopretning fra fejl
  • Samtidig adgangskontrol
  • Revisionsspor-muligheder

Udfordringer

  • Ydeevne-overhead (låsning)
  • Deadlocks kan opstå
  • Langvarige transaktioner kan blokere andre
  • Kompleksitet i distribuerede systemer
  • Hukommelses- og log-overhead

Anvendelsesområder

  • Finansielle overførsler og betalinger
  • E-handels ordrebehandling
  • Lagerstyring
  • Bookingsystemer (fly, hoteller)
  • Flertrins datamodifikationer

Eksempler fra den virkelige verden

  • Bankoverførsler (debitering og kreditering skal begge ske)
  • Online shopping (reducer lager, opret ordre, debitér kort)
  • Flybooking (reserver sæde, opret booking, send bekræftelse)
  • Lønbehandling (opdater flere konti atomisk)
  • Dobbelt-bogføringssystemer