Database Transactions
TeoriEn logisk enhed af arbejde der grupperer flere database operationer til en atomic unit med ACID garantier.
Beskrivelse
Database transactions er fundamentale for at sikre data integritet i multi-user database systemer. En transaktion er en sekvens af operationer der udføres som en enkelt logisk unit of work - enten succeeder alle operationer, eller ingen af dem gør. Dette 'alt eller intet' princip kaldes atomicity. Transactions følger ACID properties: Atomicity (alt eller intet), Consistency (databasen går fra en valid state til en anden valid state), Isolation (concurrent transactions påvirker ikke hinanden), og Durability (committed changes overlever system crashes). Transactions starter med BEGIN eller START TRANSACTION, indeholder en eller flere SQL statements (INSERT, UPDATE, DELETE, SELECT), og slutter med enten COMMIT (gem ændringer permanent) eller ROLLBACK (fortryd alle ændringer). Savepoints tillader partial rollback indenfor en transaktion. Transactions er kritiske i scenarios som bank transfers (debit fra én konto, credit til anden - begge skal ske), inventory management (tjek stock, reducer quantity - skal være atomic), og booking systems.
Problem
Uden transactions kan database operationer fejle midway, efterladende databasen i en inconsistent state. For eksempel: hvis en bank transfer fejler efter debit men før credit, er penge tabt. Concurrent users kan også se partial updates eller overskrive hinandens ændringer.
Løsning
Transactions grupperer relaterede operationer og garanterer at enten alle succeeder (COMMIT) eller alle fortrudes (ROLLBACK). Dette sikrer data consistency selv ved failures. Isolation levels kontrollerer hvordan concurrent transactions ser hinandens changes.
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
- ✓Data consistency garanteret
- ✓Atomicity - alt eller intet
- ✓Recovery fra failures
- ✓Concurrent access kontrol
- ✓Audit trail muligheder
Udfordringer
- ⚠Performance overhead (locking)
- ⚠Deadlocks kan opstå
- ⚠Long-running transactions kan blokere andre
- ⚠Kompleksitet i distributed systems
- ⚠Memory og log overhead
Anvendelsesområder
- •Financial transfers og payments
- •E-commerce order processing
- •Inventory management
- •Booking systems (flights, hotels)
- •Multi-step data modifications
Eksempler fra den virkelige verden
- •Bank transfers (debit og credit skal begge ske)
- •Online shopping (reduce stock, create order, charge card)
- •Flybooking (reserve seat, create booking, send confirmation)
- •Payroll processing (update multiple accounts atomically)
- •Double-entry accounting systems