SQL Server’da veri modifikasyon işlemleri TCL ifadeleri kullanarak denetlenebilmektedir. BEGIN TRANSACTION ile COMMIT veya ROLLBACK TRANSACTION ifadeleri arasına batch yerleştirerek transaction işlemiyle birlikte çalışacak işlemler tanımlayabilir ve kod içerisinde kurtarma noktaları belirleyebilirsiniz. Önceki yazımızda transaction yapısından bahsetmiştik. Şimdi de transaction kontrolünden bahsedeceğiz.


BEGIN TRANSACTION

SQL Server, veri işleme ifadelerini (INSERT, UPDATE ve DELETE gibi) otomatik olarak kendi kendilerini kapsar hale getirerek işlemin başarıya ulaşma olasılığını artırmaktadır. Hata durumunda otomatik olarak rollback yapılmaktadır. Veri işleme ifadelerinin batch şeklinde çalıştırırken hata oluştuğunda batch’in hâlâ çalışmaya devam ettiğini görürüz. Başarılı INSERT işlemleri sonucunda hedef tablolara veriler başarıyla eklenirken, başarısız işlemlerde ise tablolarda herhangi bir şey değişmeyecektir.

Çalıştırılacak ifadeleri transaction birimi olarak tanımlamak gerektiğinde, transaction işlemi otomatik bir süreç olduğu için bu sürece tam olarak güvenmemek gerekir. Bu birimin sınırlarını manuel olarak belirlemeniz gereklidir. Transaction’ın başlangıç noktasını oluşturmak için BEGIN TRANSACTION (BEGIN TRAN) ifadesi kullanılır.

Yapılandırılmış exception handling ile transaction’ı TRY bloğu içerisinde başlatabilirsiniz. Exception handling içerisinde de, dönen sonuca bağlı olarak COMMIT veya ROLLBACK işlemlerine karar verebilirsiniz.

BEGIN TRANSACTION ile transaction tanımlarken aşağıdakileri göz önünde bulundurmak gereklidir:

  • Bir transaction başlattıktan sonra düzgün bir şekilde sonlandırmanız gereklidir. Transaction başarıyla çalıştığında COMMIT TRANSACTION, başarısız olursa da ROLLBACK TRANSACTION kullanmalısınız.
  • Transaction’lar iç içe olabilirken, dıştaki transaction rollback edilirse içteki transaction commit edildiyse bile o da roll-back edilecektir. Bu nedenle, iç içe transaction’lar genellikle kullanıcı tanımlı kodda pek kullanışlı değildir.
  • Transaction, COMMIT TRANSACTION veya ROLLBACK TRANSACTION kullanılıncaya veya SQL Server tarafından kaynak bağlantısı kesilip rollback edilinceye kadar çalışmaya devam edecektir.
  • Bir transaction’ın kapsamı, başlatıldığı çalışma scope’udur. Transaction’lar bağlantıları geremez (kullanımdan kaldırılmış olan bound session özelliğinde gerebilir).
  • SQL Server, transaction çalışması son buluncaya kadar kaynakları tutabilir ve kilitleyebilir. Paralellikten doğan sorunları azaltmak için transaction’ların çalışmasını mümkün olduğunca kısa tutmanız önerilir.


COMMIT TRANSACTION

Transaction süreci hatasız tamamlandığında, SQL Server’ın işlemi sonlandırmasını, değişiklikleri kalıcı hale getirmesini ve kaynakları serbest bırakmasını sağlamak gereklidir. Bunun için COMMIT TRANSACTION (COMMIT TRAN) ifadesi kullanılır.

T-SQL yapılandırılmış exception handling kullanıyorsanız, transaction’ı başladığınız TRY bloğu içerisinde COMMIT edebilirsiniz.

Örnekte COMMIT TRANSACTION kullanımı gösterilmiştir:

BEGIN TRY
 BEGIN TRANSACTION
 INSERT INTO dbo.SimpleOrders(custid, empid, orderdate)
 VALUES (68,9,'2006-07-12');
 INSERT INTO dbo.SimpleOrderDetails(orderid,productid,unitprice,qty)
 VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION
END TRY 


ROLLBACK TRANSACTION

Başarısız bir transaction’ı sonlandırmak için ROLLBACK komutu kullanılır. ROLLBACK ile transaction’ın yaptığı değişiklikler geri alınarak veriler transaction başladığındaki ilk haline geri döndürülür. Rollback işlemin oluşturulan nesneleri, eklenen, silinen ve güncellenen satırlar gibi yapılan değişiklikler geri alınır. Ayrıca kullanılan kaynakların (lock’lar gibi) salınması sağlanır.

Yapılandırılmış exception handling kullanılıyorsa, BEGIN ve COMMIT’in yer aldığı TRY ifadesinin CATCH bloğunda transaction ROLL BACK edilebilir.

Aşağıdaki sorguda CATCH bloğu içerisinde ROLLBACK TRANSACTION kullanılmıştır. Burada transaction, yalnızca bir hata oluştuğunda rollback edilecektir:

BEGIN TRY
 BEGIN TRANSACTION;
 INSERT INTO dbo.SimpleOrders(custid, empid, orderdate)
 VALUES (68,9,'2006-07-12');
 INSERT INTO dbo.SimpleOrderDetails(orderid,productid,unitprice,qty)
 VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION;
END TRY
BEGIN CATCH
 SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
 ROLLBACK TRANSACTION;
END CATCH; 

Rollback etmeden önce, transaction’ın etkin olup olmadığını test edebilirsiniz. Etkin bir transaction olup olmadığını öğrenmek için T-SQL ifadesi olan XACT_STATE ifadesi kullanılır. Bu ifade, CATCH bloğu içinde ortaya çıkan hataların önlenmesinde yardımcı olacaktır.

XACT_STATE işleminde aşağıdaki değerler dönecektir:

XACT_STATE SonucuAçıklaması
0Etkin herhangi bir transaction yok.
1Hali hazırda aktif olan ve commit edilebilir bir transaction var.
-1Aktif transaction var fakat hata oluşmuş. Transaction sadece rollback edilebilir.

Aşağıdaki örnekte XACT_STATE ifadesi kullanılmıştır:

BEGIN TRY
 BEGIN TRANSACTION;
 INSERT INTO dbo.SimpleOrders(custid, empid, orderdate)
 VALUES (68,9,'2006-07-12');
 INSERT INTO dbo.SimpleOrderDetails(orderid,productid,unitprice,qty)
 VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION;
END TRY
BEGIN CATCH
 SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
 IF (XACT_STATE()) = -1
 BEGIN
 ROLLBACK TRANSACTION;
 END;
 ELSE .... -- provide for other outcomes of XACT_STATE()
END CATCH;


XACT_ABORT Kullanımı

Görüldüğü üzere SQL Server, transaction işleminde herhangi bir hata oluştuğunda otomatik rollback yapmaz. Bu ve önceki bölümde, commit ve rollback işlemleri için yoğunlukla TRY/CATCH kullanılmıştır. TRY/CATCH kullanılmayan durumlarda bir hata oluştuğunda otomatik rollback edebilmek için başka bir yöntem daha bulunmaktadır. XACT_ABORT ayarı ile, transaction çalışırken hata oluştuğunda rollback edilip edilmeyeceği ayarlanabilmektedir.

Varsayılan olarak, XACT_ABORT devre dışıdır. SET ile XACT_ABORT etkin hale getirilebilir:

SET XACT_ABORT ON; 

SET XACT_ABORT ayarı ON durumundayken, TRY bloğu haricinde bir hata meydana gelirse tüm transaction işlemi sonlandırılarak rollback edilir. TRY bloğunda oluşan bir hatada ise, XACT_ABORT ayarına rağmen transaction açık tutulur fakat commit edilemez hale getirilmektedir.

Kaynak:
BEGIN TRANSACTION (Transact-SQL)
Nesting Transactions
Transaction Statements (Transact-SQL)
SET XACT_ABORT (Transact-SQL)