Transaction Yönetimi

ACID, BEGIN, COMMIT, ROLLBACK, SAVEPOINT

Transaction ve ACID

ÖzellikAçıklama
AtomicityYa hep ya hiç - tüm işlemler başarılı veya hiçbiri
ConsistencyVeri tutarlılığı korunur
IsolationEşzamanlı işlemler birbirini etkilemez
DurabilityCommit edilen veri kalıcıdır

Temel Transaction

BEGIN;  -- veya START TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- Hata yoksa kaydet
COMMIT;

-- veya hata varsa geri al
ROLLBACK;

Para Transferi Örneği

BEGIN;

-- Gönderenin bakiyesini kontrol et
DO $$
DECLARE
    sender_balance NUMERIC;
BEGIN
    SELECT balance INTO sender_balance FROM accounts WHERE id = 1;
    
    IF sender_balance < 100 THEN
        RAISE EXCEPTION 'Yetersiz bakiye';
    END IF;
END $$;

-- Transfer işlemi
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- Log kaydı
INSERT INTO transfer_log (from_id, to_id, amount) VALUES (1, 2, 100);

COMMIT;

SAVEPOINT - Kısmi Geri Alma

BEGIN;

INSERT INTO orders (user_id, total_amount) VALUES (1, 500);
SAVEPOINT order_created;

INSERT INTO order_items (order_id, product_id, quantity) VALUES (1, 10, 2);
-- Hata oluşursa sadece item'ı geri al
ROLLBACK TO order_created;

-- Order hala mevcut, yeni denemeler yapılabilir
INSERT INTO order_items (order_id, product_id, quantity) VALUES (1, 20, 1);

COMMIT;

Isolation Levels

-- Transaction isolation level ayarla
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
LevelDirty ReadNon-RepeatablePhantom
Read Uncommitted❌ PostgreSQL'de yok--
Read Committed✅ Engeller⚠️ Olabilir⚠️ Olabilir
Repeatable Read✅ Engeller✅ Engeller⚠️ Olabilir
Serializable✅ Engeller✅ Engeller✅ Engeller

Deadlock Önleme

-- Her zaman aynı sırada kilitle
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
SELECT * FROM accounts WHERE id = 2 FOR UPDATE;
-- İşlemler...
COMMIT;

-- Timeout ayarla
SET lock_timeout = '10s';
SET statement_timeout = '30s';

Autocommit

-- PostgreSQL varsayılan autocommit açıktır
-- Her sorgu kendi transaction'ında çalışır

-- Autocommit kapatmak için (psql)
\set AUTOCOMMIT off