PostgreSQL'de doğru izolasyon seviyesini seçmek, genellikle veri tutarlılığı ile sistem geçişi arasında bir denge kurma eylemidir. READ COMMITTED varsayılan olup yüksek performans sunar, ancak tekrarlanabilir okumalara ve hayalet okumalara karşı hassastır. Spektrumun diğer ucunda, SERIALIZABLE seviyesi en güçlü garantileri sağlar ancak geleneksel olarak serializasyon doğrulama kontrolleri nedeniyle ciddi bir performans cezasıyla gelir.
Bununla birlikte, PostgreSQL güçlü bir orta yol sunar: Serializable Snapshot Isolation (SSPI). Bu blog yazısı, SSPI'nin geleneksel serializasyon kontrolleriyle ilişkili aşırı yükü minimize ederken sıkı serializasyon garantilerini nasıl koruduğunuzu ve bunu yüksek geçişli ortamlar için uygun hale getirdiğinizi inceler.
Serializable Snapshot Isolation'ı Anlamak
Geleneksel serializasyon izolasyonu, satırları kilitleyerek çalışır; bu da yüksek eşzamanlılık senaryolarında önemli bir rekabete (contention) yol açabilir. PostgreSQL 9.1'de tanıtılan ve sonraki sürümlerde rafine edilen SSPI, farklı bir mekanizma kullanır. Paralel olarak işlemleri çalıştırdığınızda, sonucun bazı sıralı yürütme sıralarına eşdeğer olmasını sağlar; ancak bunu, satır kilitleme yerine serializasyon anormalliklerini (okuma-yazma veya yazma-yazma bağımlılıkları gibi) algılayıp çakışan işlemleri engellemek yerine sonlandırarak gerçekleştirir.
Bu yaklaşım, yüksek geçişli uygulamalar için özellikle faydalıdır çünkü kilitlenme tespiti aşırı yükünü önler ve kilit rekabetini azaltır. Kilitler için beklemek yerine, işlemler başarısız olabilir ve yeniden denenmesi gerekebilir; bu durum, kilitleri açık tutmaktan genellikle daha ucuzdur.
PostgreSQL'de SSPI Yapılandırma
SSPI uygulamak basittir. İşlem izolasyon seviyesini işlem başına veya küresel olarak ayarlayabilirsiniz. Çoğu uygulama için oturum düzeyinde ayarlamak yeterlidir, ancak bireysel işlem kontrolü daha ince taneli bir yönetim sunar.
SSPI ile bir işlemi başlatmanın yolu şöyledir:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Alternatif olarak, bunu tüm oturum için değiştirebilirsiniz:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Serializasyon Hatalarını Yönetme
SSPI ile ilgili temel zorluk, kontrollerin kendisinin performans aşırı yükü değil, işlem yeniden denemelerini yönetme zorunluluğudur. PostgreSQL bir serializasyon çakışması algıladığında, işlemi geri alır ve bir 40001 SQLSTATE hata kodu (genellikle serializable_failure) döndürür. Uygulama kodunuz, bu belirli istisnayı yakalayıp işlemi yeniden deneyecek şekilde tasarlanmalıdır.
Yeniden denemeleri yönetmek için psycopg2 kütüphanesiyle Python kullanarak pratik bir örnek:
import psycopg2
from psycopg2 import errors
def execute_serializable_transaction(conn):
while True:
try:
with conn.cursor() as cur:
cur.execute("BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE")
# Veritabanı işlemlerini burada gerçekleştirin
cur.execute("SELECT balance FROM accounts WHERE id = 1")
row = cur.fetchone()
cur.execute("UPDATE accounts SET balance = %s WHERE id = 1", (row[0] - 10,))
conn.commit()
break
except errors.SerializationFailure:
conn.rollback()
continue
except Exception as e:
conn.rollback()
raise
Bu desen, uygulamanızın çakışmaları zarif bir şekilde yönetmesini sağlar. SSPI, çakışmaları işlem yaşam döngüsünün son aşamalarında algıladığından, maliyet öncelikle yeniden deneme işlemidir, işlem sırasında kilitlenmenin maliyeti değildir.
Performans Ödünleri ve En İyi Uygulamalar
SSPI, geleneksel serializasyon izolasyonundan daha hızlı olsa da, yine de READ COMMITTED'den daha yavaştır. Bu nedenle, dikkatli kullanılmalıdır. Aşağıdaki en iyi uygulamaları göz önünde bulundurun:
- İşlem Kapsamını Minimize Edin: Çakışmalar için pencereyi azaltmak için işlemleri mümkün olduğunca kısa tutun.
- Uzun Süreli Okumalardan Kaçının: Uzun okuma sorguları, diğer işlemlerin ilerlemesini engelleyebilir ve serializasyon hatalarının olasılığını artırabilir.
- Basit Durumlar için Optimistik Kilitleme Kullanın: Yalnızca kayıp güncellemeleri önlemeniz gerekiyorsa, tam SSPI'den daha hafif olan uygulama düzeyinde sürümleme ile
SELECT ... FOR UPDATEkullanmayı düşünün. - Yeniden Deneme Oranlarını İzleyin: Uygulamanız yüksek bir serializasyon hatası oranı yaşıyorsa, işlem mantığınızı optimize etmeniz veya veri modelinizi yeniden gözden geçirmeniz gerekebilir.
Sonuç
Serializable Snapshot Isolation, geleneksel kilitlemenin yıkıcı performans cezası olmadan PostgreSQL'de veri tutarlılığını sağlamak için sağlam bir yol sunar. Ödünleri anlamak ve uygun yeniden deneme mantığı uygulamak suretiyle geliştiriciler, SSPI'den yararlanarak yüksek eşzamanlı ve tutarlı uygulamalar oluşturabilir. İster finansal işlemlerle ister karmaşık envanter sistemleriyle uğraşın, SSPI yüksek geçişli ortamlarda güçlü tutarlılık için ölçeklenebilir bir yol sunar.