Konunun geçmişi
İş mantığı işleme işlemlerinde genellikle birden fazla ilişkili tablodaki verilerin değiştirilmesi gerekir. Herhangi bir şey başarısız olduğunda (örneğin, ihlal edilen bir kısıtlama nedeniyle), sadece son işlemi değil, mantık kapsamındaki tüm eylemleri iptal etmek önemlidir. Bunun için işlem mekanizması ve hata yönetimi kullanılır.
Sorun
Tüm DBMS'leri, çok aşamalı prosedürlerde hata meydana geldiğinde otomatik olarak geri alma işlemi sağlamaz (özellikle TRY/CATCH, EXCEPTION işleyicileri kullanılıyorsa). İşlem mantığı yanlış yazılırsa, "parçalı" değişiklikler meydana gelir (bir kısım veri güncellenir, bir kısmı güncellenmez), bu da iş bütünlüğünü tehdit eder.
Çözüm
Doğru hata yönetimi için işlemleri açıkça başlatmak ve sonlandırmak (BEGIN TRANSACTION, COMMIT/ROLLBACK) ve hataları yakalamak gerekir. Farklı DBMS'lerde sözdizimi ve olanaklar farklılık gösterir.
MS SQL Server için örnek:
CREATE PROCEDURE update_balances(@from INT, @to INT, @amount DECIMAL(10,2)) AS BEGIN BEGIN TRY BEGIN TRANSACTION; UPDATE accounts SET balance = balance - @amount WHERE id = @from; UPDATE accounts SET balance = balance + @amount WHERE id = @to; COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; INSERT INTO error_log(err_message, err_date) VALUES(ERROR_MESSAGE(), GETDATE()); THROW; -- hatayı ileri gönder END CATCH END;
PostgreSQL için:
CREATE OR REPLACE FUNCTION update_balances(from_id INT, to_id INT, amount NUMERIC) RETURNS void AS $$ BEGIN UPDATE accounts SET balance = balance - amount WHERE id = from_id; UPDATE accounts SET balance = balance + amount WHERE id = to_id; -- Hata otomatik olarak işlemi geri alır EXCEPTION WHEN OTHERS THEN INSERT INTO error_log(err_message, err_date) VALUES(SQLERRM, NOW()); RAISE; END; $$ LANGUAGE plpgsql;
Ana özellikler:
Saklı prosedürde bir hata her zaman işlemi otomatik olarak geri alabilir mi? Hayır! Örneğin, MS SQL Server'da böyle bir geri alma garanti edilmez — açık bir ROLLBACK gereklidir. PostgreSQL'de herhangi bir hata durumunda tüm işlem "bozulur" ve tamamlanması gerekir.
Tek bir prosedür içinde "kısmi" bir commit yapılabilir mi? Kötü bir uygulama. Commit/rollback'in yalnızca iş işleminin sonunda bir kez yapılması önerilir. Bazı platformlar "savepoint" sağlar, ancak bu özel görevler içindir.
TRY/CATCH/EXCEPTION ile yakalanmayan hata türleri nelerdir? Bazı sistem arızaları (örneğin, sunucuyla bağlantının kesilmesi) işleyiciye düşmez ve geri almayı imkansız hale getirebilir.
Saklı prosedür üç tabloyu güncelledi ve hata yakalamadan COMMIT ile sona erdi. Sonuç olarak, ikinci tablodaki hata nedeniyle birinci tablonun verileri değişmişti ve yedeklerden verileri manuel olarak "geri almak" saatler sürdü.
Artıları:
Basit ve "çalışıyor", hata meydana gelene kadar.
Eksileri:
Tutarsızlık riski; hatalarda hızlı bir şekilde geri dönüş yapılamaz.
Etkili hata yönetimi ve hata kayıtlarıyla birlikte işlemleri geri alma uygulaması getirildi. Veritabanını bütünlük durumuna döndürmek birkaç saniye sürüyor, hatalar analiz ediliyor ve en aza indiriliyor.
Artıları:
Hatalarda bile verilerin değişmezliği garantisi; şeffaf bir mantık.
Eksileri:
Yeni başlayanlar için biraz daha karmaşık, kodda disiplin gerektirir.