Transaction Nedir, Nasıl Kullanılır?
Çoğu zaman bir transaction yalnızca bir türde işlem yapar, yani sadece veri silme, veri güncelleme veya veri ekleme gibi tek türde işlem yapar. Ama bir transaction içinde birden fazla da işlem yapılabilir. Yine transaction içinde SELECT işlemleri de yapılabilmektedir. Peki bunlar bizim bildiğimiz şeyler, neden transaction çıktı ki birden dediğinizi duyar gibiyim.
Burada dikkat edilecek nokta, transaction var çünkü, transaction içinde yer alan tüm işlemler veritabanı server üzerinde yapılmak zorunda, aksi halde transaction içindeki işlemlerin tek bi adımı dahi başarısız olsa, tüm yapılan işlemler yapılmamış gibi eski haline döner. Peki bunun yararı nedir?
Şimdi çok klasik olacak ama tabiri caizse cuk diye oturan bir örnek olduğu için ATM örneğini vermek istiyorum bende. Bir kullanıcı olarak ATM’ye gittiniz diyelim, yapmak istediğiniz işlem para çekmek olsun. Kartınızı taktınız, şifrenizi girdiniz, para çekmeyi seçtiniz, miktarı belirlediniz ve çekmek istiyorum dediniz. ATM arka planda tüm bu işlemleri yaptı, çekmek istediğiniz para miktarını kontrol etti, paranın var olduğunu gördü, paranızı size vermek üzere para çekilecek alana yansıttı. Kartınızı da daha önceden verdi (artık genelde önce kart, sonra para veriliyor çünkü, parayı unutma ihtimali daha az mantığı ile bakılıyor olaya) Bu esnada arka planda hesabınızdan bu miktar düştü. Para şimdi parayı alacağınız alanda ama olduki dalgınlık oldu, hemen alamadınız bir kaç saniye geçti ve bankamatikte güvenlik icabı bu parayı geri aldı. Yani parayı hesaptan çektiniz ama elinize alamadınız para geri gitti eee ne olacak şimdi, benim hesabımdaki para azalacak mı? Ben parayı almadım ki daha
İşte burada Transaction işleminin önemi devreye giriyor. Kullanıcı parasını alamadığı için Transaction sonlanmamış olur ve her şeyi eski haline geri çevirir. Yani çekilen miktar tekrar kullanıcının hesabına geri döner. Transaction işleminin önemi budur. Aynı durumu bankaya para yatıran bir şahıs içinde düşenebilirsiniz. Banka önce yatırılacak miktarı sorar, sonra kullanıcıdan parayı ister, tüm işlemler sonlandığında yani en son onay alındığında işlem aslında tamamlanmış olur.
BEGIN TRANSACTION
(kısaca BEGIN TRAN
) komutu Microsoft SQL Server (MSSQL) üzerinde bir işlem (transaction) başlatmak için kullanılır. Bu, bir grup SQL ifadesinin bir bütün olarak çalıştırılmasını sağlar ve her şey başarılı olursa COMMIT
, başarısız olursa ROLLBACK
ile tamamlanır. Bu sayede bir dizi işlem sırasında tutarlılık ve bütünlük sağlanmış olur.
Bildiğiniz üzere SQL Server’da default transaction türü “Auto Commit” dir. Yani yapılan işlemler anında kalıcı hale getirilir. Bu durumun avantajları olduğu gibi dez avantajları da vardır. Örneğin yapılan bir işlem sonucunda bir hata olursa ya da bu işlemi takip eden işlem hata alırsa veri tabanında verilerde uyuşmazlıklar meydana gelecektir.
Şimdi bir transaction nasıl oluşturulur buna değinelim. Bir transaction içinde yer alan tablolar ile alakalı işlem yapılırken kullanılan bu tablolar başka sorgular içinde kullanılmasın diye ilgili transaction çalışması bitene kadar kilitlenirler. SQL Server otomatik olarak bu işi yapar. Bir transaction oluşturmak için söz dizimi aşağıdaki gibidir. TRAN veya TRANSACTION her iki ifade de kullanılabilir.
durum1
durum2
COMMIT TRAN veya TRANSACTION
Transaction Scope
Bir transaction’ın başlangıcından bitişine kadar olan aralıktır.
Transaction Türleri
Explicit Transactions
BEGIN, COMMIT, ROLLBACK komutlarıyla transactionların kontrol edilmesidir.
AutoCommit Transactions
Yapılan işlemin anında ve kalıcı olarak sisteme yansıtılmasıdır. Hata durumunda rollback otomatik gerçekleşir. Sql Server default olarak bu yapıyı kullanır.
Imlicit Transactions
Mevcut transaction biter bitmez(commit,rollback) yenisinin açılmasıdır. Oracle veri tabanında default yapı budur.
Not: Bir transaction açıldığı zaman, transaction scope içerisinde değişiklik gören kayıtlar var ise bu kayıtlar “lock” durumuna alınır. Aksini belirtmediğiniz sürece transaction bitene kadar başka bir kullanıcı bu kayıtlara ulaşamaz, okuyamaz,üzerinde değişiklik yapamaz.
İç İçe Transactionlar(Nested Transactions)
DELETE FROM orders WHERE OrderID=10248
BEGIN tran abc
DELETE FROM Orders WHERE OrderID=10249
commit tran xyz
Burada en dış transactionda yapılan Rollback veya Commit işlemi içerideki tüm transactionları da Rollback veya Commit eder.
Transaction Örnek1:
INSERT INTO dbo.demoTransaction (col1) VALUES (1);
INSERT INTO dbo.demoTransaction (col1) VALUES (2);
COMMIT TRANSACTION
Şimdi ben bu transaction ile dbo.demoTransaction tablosunda col1 kolonuna 1 ve 2 değerlerini atıyorum. Bir bakalım olmuş mu?
Görüleceği üzere transaction içinde yer alan iki adet veri kaydetme işlemi gerçekleştirilmiş durumda.
Bir başka transaction yazalım.
INSERT INTO dbo.demoTransaction (col1) VALUES (3);
INSERT INTO dbo.demoTransaction (col1) VALUES ('a');
COMMIT TRANSACTION
Bu sorgu sonucunda aşağıdaki gibi bir mesaj alırız.
(1 row(s) affected)
Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value ‘a’ to data type int.
Burada ise diyor ki, 1 satır eklendi, diğeri olmadı çünkü a değeri int tipinde bir değişken değil. Yani mesaja göre 3 değerini de eklenmiş olması gerek. Benim tablomda col1 alanı için int tipinde değişken olması gerekiyor, çünkü tbalomu oluştururken üstte de görüleceği üzere şartım bu. Ama 3 eklendi diyor bu mesajda. Bir bakalım cidden eklenmiş mi?
Eee hani eklenmişti, (1 row(s) affected) dedi ama bana Şimdi biz yazımızın üstte en başlarına doğru ne dedik. Bir Transaction içindeki her işlem adımının gerçekleşmesi gerekir, adımlardan herhangi birinde dahi bir hata meydana gelse ilgili transaction içindeki tüm adımlar, diğerleri gerçekleşmiş olsa dahi iptal edilir, eski haline döner. İşte buradaki durumda bu, 3 değeri tamam uygun ancak a uymuyor, yalnız bu iki işlem adımı da tek bir transaction içinde. Dolayısı ile bu ikinci yazılan transaction çalışmıyor.
Transaction Örnek 2:
$objDB = mssql_select_db("mydatabase");
mssql_query("BEGIN TRAN");
//**** Process 1 ****//
$strSQL = "INSERT INTO customer ";
$strSQL .="(CustomerID,Name,Email,CountryCode,Budget,Used) ";
$strSQL .="VALUES ";
$strSQL .="('".$_POST["txtCustomerID"]."','".$_POST["txtName"]."','".$_POST["txtEmail"]."' ";
$strSQL .=",'".$_POST["txtCountryCode"]."','".$_POST["txtBudget"]."','".$_POST["txtUsed"]."') ";
$objQuery1 = mssql_query($strSQL);
if(!$objQuery1) {
mssql_query("ROLLBACK");
echo "Error Save [".$strSQL."]";
exit();
}
//**** Process 2 ****//
$strSQL = "INSERT INTO customer ";
$strSQL .="(CustomerID,Name,Email,CountryCode,Budget,Used) ";
$strSQL .="VALUES ";
$strSQL .="('".$_POST["txtCustomerID"]."','".$_POST["txtName"]."','".$_POST["txtEmail"]."' ";
$strSQL .=",'".$_POST["txtCountryCode"]."','".$_POST["txtBudget"]."','".$_POST["txtUsed"]."') ";
$objQuery2 = mssql_query($strSQL);
if(!$objQuery2) {
mssql_query("ROLLBACK");
echo "Error Save [".$strSQL."]";
exit();
}
//**** Process 3 ****//
$strSQL = "INSERT INTO customer ";
$strSQL .="(CustomerID,Name,Email,CountryCode,Budget,Used) ";
$strSQL .="VALUES ";
$strSQL .="('".$_POST["txtCustomerID"]."','".$_POST["txtName"]."','".$_POST["txtEmail"]."' ";
$strSQL .=",'".$_POST["txtCountryCode"]."','".$_POST["txtBudget"]."','".$_POST["txtUsed"]."') ";
$objQuery3 = mssql_query($strSQL);
if(!$objQuery3) {
mssql_query("ROLLBACK");
echo "Error Save [".$strSQL."]";
exit();
}
//**** Commit Transaction ****//
if(($objQuery1) and ($objQuery2) and ($objQuery3)) {
mssql_query("COMMIT");
}
mssql_close($objConnect);
Transaction Örnek 3:
UPDATE dbo.Hesap SET Bakiye-=100 WHERE TCKimlikNo='23456789101'
RAISERROR('Elektrikler Kesildi',16,2)
UPDATE dbo.Hesap SET Bakiye+=100 WHERE TCKimlikNo='12345678910'
END TRY
BEGIN CATCH
PRINT 'Beklenmedik bir hata olustu'
END CATCH
BEGIN TRAN
Kullanımı
Aşağıda BEGIN TRAN
, COMMIT
ve ROLLBACK
komutlarının nasıl kullanıldığına dair bir örnek bulunmaktadır:
SQL sorguları burada yapılır
UPDATE Customers SET Balance = Balance - 100 WHERE CustomerID = 1;
UPDATE Orders SET STATUS = 'Completed' WHERE OrderID = 123;
Eğer sorgular başarılı olursa
COMMIT; İşlemi başarılı bir şekilde bitirir
Eğer bir hata olursa
ROLLBACK; Tüm değişiklikleri geri alır
Örnek Senaryo
Bir müşteri hesabından bir miktar para düşülmesi ve bir siparişin durumunun güncellenmesi gibi bir işlem düşünelim. Bu işlem sırasında iki adım var ve her iki adımın da başarılı olması gerekiyor. Eğer herhangi bir adım başarısız olursa, yapılan değişiklikler geri alınmalıdır.
BEGIN TRY
İlk işlem: Müşterinin bakiyesini güncelle
UPDATE Customers
SET Balance = Balance - 100
WHERE CustomerID = 1;
İkinci işlem: Sipariş durumunu güncelle
UPDATE Orders
SET STATUS = 'Completed'
WHERE OrderID = 123;
Eğer tüm sorgular başarılı olursa
COMMIT; İşlemi onayla
END TRY
BEGIN CATCH
Hata durumunda işlemi geri al
ROLLBACK;
Hata mesajını gösterebilir veya loglayabilirsiniz
PRINT 'İşlem başarısız oldu. Değişiklikler geri alındı.';
END CATCH;
Açıklamalar
-
BEGIN TRANSACTION
:- Bu komut bir işlem başlatır. İşlem tamamlanana kadar yapılan değişiklikler geçici olarak tutulur.
-
COMMIT
:- Eğer tüm sorgular başarıyla tamamlanırsa,
COMMIT
komutu ile değişiklikler kalıcı hale getirilir.
- Eğer tüm sorgular başarıyla tamamlanırsa,
-
ROLLBACK
:- Eğer herhangi bir hata olursa,
ROLLBACK
komutu tüm değişiklikleri geri alır ve veritabanı işlemden önceki durumuna döner.
- Eğer herhangi bir hata olursa,
-
BEGIN TRY
veBEGIN CATCH
:- Bu yapılar, SQL Server'da hata yönetimi için kullanılır.
TRY
bloğunda hata olmadan çalışan sorgularCOMMIT
ile tamamlanır, eğerTRY
bloğunda bir hata oluşursaCATCH
bloğuna geçilir veROLLBACK
yapılır.
- Bu yapılar, SQL Server'da hata yönetimi için kullanılır.
Daha Gelişmiş Örnek
Birden fazla tabloya veri ekleme işlemi:
BEGIN TRY
İlk tabloya veri ekle
INSERT INTO Customers (CustomerName, Balance)
VALUES ('Ali Veli', 1000);
İkinci tabloya veri ekle
INSERT INTO Orders (CustomerID, ProductName, OrderDate)
VALUES (SCOPE_IDENTITY(), 'Laptop', GETDATE());
Eğer tüm işlemler başarılı olursa
COMMIT;
PRINT 'İşlem başarılı bir şekilde tamamlandı.';
END TRY
BEGIN CATCH
Hata durumunda tüm işlemleri geri al
ROLLBACK;
PRINT 'Bir hata oluştu. İşlem geri alındı.';
END CATCH;
Önemli Noktalar:
SCOPE_IDENTITY()
: Bu fonksiyon, bir tabloya yapılan sonINSERT
işleminden sonra eklenen son kimlik (ID) değerini almak için kullanılır. Bu, aynı işlem içinde başka bir tabloya ekleme yaparken kullanışlıdır.GETDATE()
: Şu anki tarihi ve saati almak için kullanılır.
BEGIN TRANSACTION
Kullanımının Faydaları:
- Veri Bütünlüğü: Eğer bir işlem sırasında bir hata oluşursa, tüm işlem geri alınarak verilerin tutarlı kalması sağlanır.
- Güvenlik: Büyük ve kritik işlemler sırasında bir adımda hata olduğunda, işlemin tamamı geri alınabilir.
- Kontrol: Birden fazla işlem yaparken her adımın başarıyla tamamlandığından emin olunmasını sağlar.
SQL işlemlerinde BEGIN TRAN
yapısı, karmaşık veri güncellemeleri ve eklemeleri sırasında veritabanı bütünlüğünü korumak için kritik öneme sahiptir.
Kaynak
- http://www.ismailgursoy.com.tr/transaction-nedir-nasil-kullanilir/
- http://www.shotdev.com/php/php-sql-server/php-sql-server-mssql-and-transaction-begin-tran-commit-rollback/
- http://www.yazilimdevi.com/Makaleler-230-sql-server-transaction-yonetimi.aspx
- http://gaffarsalkim.blogspot.com.tr/2012/05/ms-sql-de-transactions.html
- https://chatgpt.com