Transactionlar bir dizi işlemin başarılı sonuçlanana kadar saklanmasını, başarılı olduğu durumda işlemi en baştan tekrarlıyıp gerçekleştirmesini, başarısız olduğu durumda ise işlemi geri almasını sağlayan SQL yapısıdır.
Söz Dizimi:
BEGIN { TRAN | TRANSACTION } [ { transaction_name | @tran_name_variable } [ WITH MARK [ 'description' ] ] ] [ ; ]
Parametreler :
transaction_name : Oluşturulacak transaction’un adını tanımladığımız alandır. Tanımlayıcı kurallarına uygun bir şekilde tanımlanması gerekir. 32 karakterden uzun olmamalıdır. transaction_name’i yalnızca BEGIN,COMMIT veya ROLLBACK (tran) çiftlerinin en dışında kullanmalısınız.
@tran_name_variable : Kullanıcı tanımlı transaction adıdır. Değişken char, varchar, nchar yada nvarchar veri türlerinden biriyle kullanılmalıdır. Eğer değişkenin uzunluğu 32 karakterden fazla olursa, ilk 32 karakter değişken adı için kullanılır; geri kalan kısım yok edilir.
WITH MARK [ ‘description’ ] : transaction’ın günlüğe işaretlendiğini belirtir. description işaretçiyi açıklar. 128 karakterden uzun olamaz. 128 karakteri geçen karakterler yok edilir.
eğer WITH MARK kullanılırsa, transaction name tanımlanmak zorundadır. WITH MARK bir işlem günlüğünü adlandırılmış bir işarete geri döndürmeye izin verir.
Örnek bir senaryo üzerinden transaction’ı pekiştirmeye çalışacağım. Bir bankada havale işlemi yaptığımızı düşünelim. Ben paramı havale yolu ile birisine aktarırken hata oluşursa bendeki para azalacak ve karşı tarafa da bu para gitmeyecektir. Hata oluştuğu için para hesabıma geri de yüklenemeyecektir. Bu sorunu çözmenin en kolay yolu işlem başında bu işlemi simüle edecek bir yapıdır. Eğer başarılı gerçekleşiyorsa işlemi gerçekleştirecek hata oluşursa da en başa alacak ve para kaybına yol açmayacaktır.
Şimdi bir banka veritabanı ve içinde Hesaplar tablosunu oluşturalım. Bu tabloya da iki değer ekleyelim.
create database Bank go use Bank go create Table Hesaplar(Id int identity(1,1) primary key,HesapAdi nvarchar(50),Miktar money) go insert into Hesaplar(HesapAdi,Miktar) values('Serkan Yarbaş',5000) go insert into Hesaplar values('Ayhan Atız',5000) go
Senaryomuz gereği benim hesabımdan Ayhan abi’nin hesabına 3000 tl aktaracağımızı düşünelim ve aşağıdaki şekilde bir prosedür yazalım.
create proc HavaleYap @kimden nvarchar(50), @kime nvarchar(50), @miktar money as Begin try Begin tran havale update Hesaplar set Miktar += @miktar where HesapAdi = @kime -- parayı yatır. set @miktar = @miktar / 0 -- bu satır hata oluşması içiin yazılmıştır. update Hesaplar set Miktar -= @miktar where HesapAdi = @kimden -- parayı çek. commit tran havale End try begin catch rollback tran havale print 'Kelli felli bir hata oluştu' end catch
Yukarıdaki şekilde hata oluşturan bir prosedür yazdığımızı düşünelim.
select * from Hesaplar
Yukarıdaki şekilde hesaplarımızı görüntülediğimizde ikimizde de 5000 tl olduğu görülür..
Aşağıdaki şekilde havale yaptığımızda ise olması gereken aslında benim hesabımdan Ayhan’ın hesabına 3bin tl eklenip benim hesabımdan 3000 tl azalmasıdır. Olaylar her zaman böyle kolay gerçekleşmiyor tabiki. Varsayalım ki tam bu anda bağlantı koptu ve işlem sırasında hata meydana geldi. O zaman benim hesabımdan 3bin tl eksilmeli mi ? ” Hata verdi o yüzden sizin paranız da gitti 😀 ” diye bir mesaj ile müşterisini bilgilendirmeli mi sizce ? Sanırım ne böyle bir banka olurdu ne de 3bin tlsinin gitmesini isteyecek bir müşteri.
exec HavaleYap 'Serkan Yarbaş','Ayhan Atız',3000
Gördüğünüz gibi transaction sırasında kelli felli bir hata oluşuyor ve bundan müşteri etkilenmemesi için yapılan işlemlerin yukarıda oluşturduğumuz transaction mekanızması kuruyoruz. Böylece yapılan tüm işlemleri ve ya istenilen işleme geri de alabiliyoruz.
begin tran --Commit tek transaction onaylar commit tran --Rollback açık bütün transactionları kapatır. rollback tran --Save tran kullanarak transaction içerisinde durak noktası oluşturulabilikr. save tran
--Açık transatcion sayısı select @@TRANCOUNT
begin tran insert Hesaplar values('Sefa Akmemis',5000) save tran a update Hesaplar set Miktar = 5100 where HesapAdi = 'Sefa Akmemis' save tran b delete Hesaplar where HesapAdi = 'Serkan Yarbas' rollback tran b -- Serkan yarbas geri gelir. rollback tran a -- Sefa akmemisin hesabı geri alınır. rollback tran -- başa alır. --Açık trans sayısı select @@TRANCOUNT begin tran insert Hesaplar values('Erman Avluk',5000) -- Tran başladı update işlemi bekletilir. Yeni bir sayfada açılırsa bekletir. -- bu işleme izolasyon denir. update Hesaplar set Miktar = 7000 where HesapAdi = 'Erman Avluk' rollback tran set tran isolation level serializable-- en sıkı izolasyon levelidir. diğer hiç bir işleme izin vermez. select * from Hesaplar-- farklı query sayfasında çalışmaz. commit tran -- ile diğer sayfalardaki işlemlere sıra gelmiş olur.
Bir sonraki yazımda görüşmek dileğiyle. Kendinize iyi bakın.