Veritabanı İşlemi (Transaction) Nedir?
Kısa tanım
Veritabanı işlemi (transaction), birden fazla okuma ve yazma adımını tek bir bölünmez birim olarak çalıştıran mekanizmadır. İşlem COMMIT ile onaylandığında tüm değişiklikler kalıcı olur; ROLLBACK edildiğinde veya bir hata oluştuğunda hiçbiri uygulanmaz. İlişkisel veritabanları işlemlerin güvencelerini ACID ilkeleriyle tanımlar; eşzamanlı işlemlerin birbirini ne ölçüde göreceği ise seçilen yalıtım seviyesine bağlıdır.
Diğer adları: transaction, database transaction, ACID, işlem, commit ve rollback

Bir işlemin yaşam döngüsü
Bir işlem BEGIN ile açılır, içinde istenen kadar komut çalıştırılır ve COMMIT ile onaylanır ya da ROLLBACK ile tamamen geri alınır. İşlem açılmadığında çoğu veritabanı “autocommit” modunda çalışır: her komut kendi başına küçük bir işlemdir. Asıl değer, birbirine bağlı adımları birlikte çalıştırmaktan gelir. Bir sipariş oluşturulurken stok düşülmesi, siparişin ve satırlarının yazılması ya hep birlikte gerçekleşmeli ya da hiç gerçekleşmemelidir:
BEGIN;
-- Stok yeterliyse düş; etkilenen satır 0 ise uygulama ROLLBACK eder
UPDATE products SET stock = stock - 2
WHERE id = 42 AND stock >= 2;
INSERT INTO orders (customer_id, total)
VALUES (77, 699.80) RETURNING id; -- ör. 9131 döner
INSERT INTO order_items (order_id, product_id, qty)
VALUES (9131, 42, 2);
COMMIT;İlk komuttaki stock >= 2 koşulu küçük ama önemli bir ayrıntıdır: kontrolü ve güncellemeyi tek komutta birleştirdiği için aynı anda gelen iki sipariş son ürünü birlikte satamaz.
ACID: her harf neyi garanti eder, neyi etmez?
ACID'in dört harfinin kısa tanımları veritabanı maddesinde yer alıyor. Pratikte daha önemli olan, her güvencenin nasıl sağlandığı ve nerede bittiğidir:
| İlke | Nasıl sağlanır? | Sınırı |
|---|---|---|
| Atomicity | Değişiklikler önce bir günlüğe (WAL, undo log) yazılır; işlem yarıda kalırsa geri sarılır | Yalnızca veritabanının içini kapsar; gönderilen bir e-posta geri alınamaz |
| Consistency | Tanımlı kısıtlar (yabancı anahtar, CHECK, UNIQUE) her işlem sonunda doğrulanır | Veritabanı yalnızca kendisine tarif edilen kuralları bilir; kodda kalan iş kuralları korunmaz |
| Isolation | Kilitler ve çok sürümlü eşzamanlılık denetimi (MVCC) | Varsayılan seviyeler tam yalıtım sağlamaz |
| Durability | COMMIT, günlük diske yazıldıktan sonra onaylanır | Performans için gevşetilebilen ayarlar ve tek diske bağlı kurulumlar bu güvenceyi zayıflatır |
Yalıtım seviyeleri kısaca
SQL standardı dört yalıtım seviyesi tanımlar. Seviye yükseldikçe eşzamanlı işlemlerin birbirini etkileme biçimleri azalır, ama bekleme ve yeniden deneme ihtiyacı artar:
- Read Uncommitted: Başka bir işlemin onaylanmamış değişiklikleri görülebilir. PostgreSQL bu seviyeyi istendiğinde Read Committed gibi davranır.
- Read Committed: Her komut, o ana kadar onaylanmış veriyi görür; aynı sorgu işlem içinde iki kez çalıştırılırsa farklı sonuç dönebilir. PostgreSQL'in varsayılanıdır.
- Repeatable Read: İşlem boyunca aynı satırlar aynı görünür. MySQL InnoDB'nin varsayılanıdır.
- Serializable: Sonuç, işlemler tek tek sırayla çalışmış gibidir. Çakışma olduğunda veritabanı işlemlerden birini serileştirme hatasıyla (SQLSTATE 40001) iptal eder ve uygulamanın işlemi baştan yeniden denemesi gerekir.
Varsayılan seviyelerde en sık yaşanan sorun kayıp güncellemedir: iki istek stoğu 5 olarak okur, ikisi de uygulamada 1 çıkarıp 4 yazar ve bir satış kaybolur. Çözüm, değeri tek bir atomik UPDATE ile değiştirmek, satırı SELECT ... FOR UPDATE ile kilitlemek ya da bir sürüm sütunu kullanarak iyimser kilitleme (optimistic locking) uygulamaktır. Seviyelerin ayrıntılı karşılaştırması PostgreSQL belgelerinde bulunabilir.
Uygulama tarafında işlem tasarımı
- İşlemleri kısa tutun. Açık bir işlem kilit tutar ve bağlantı havuzundaki bir bağlantıyı meşgul eder. Ödeme sağlayıcısına HTTP isteği atmak gibi dış çağrılar işlemin dışında yapılmalıdır.
- Yeniden denemeye hazır olun. Serileştirme hataları ve kilitlenmeler (deadlock) normal işletim durumlarıdır. Yeniden denenecek işlemin iki kez çalıştığında zarar vermemesi, yani idempotent olması gerekir.
- Kilitleri hep aynı sırayla alın. Farklı sıralarla aynı satırlara dokunan iki işlem birbirini sonsuza kadar bekleyebilir; veritabanı bunu fark edip birini iptal eder.
- İşlem sınırı veritabanında biter. Siparişi kaydedip bir kuyruğa mesaj göndermek tek işlemde yapılamaz. Yaygın çözüm “outbox” desenidir: mesaj, siparişle aynı işlem içinde bir tabloya yazılır, ayrı bir süreç onu mesaj kuyruğuna iletir.

