24 Sep

MySQL de transaction kullanımı

Bir önceki yazıda bulunan örnek ile devam edeceğim için, ilk önce bu örnekteki kodları edinip çalıştırmanız gerekli.

Transction, kelime anlamı ile işlem demektir. Fakat bu kelime anlamının haricinde, veritabanına doğru gerçekleştirilen işlemlerin, veritabanına kalıcı olarak işlenip işlenmemesini yöneten muazzam bir sistemdir. Ve kullandığınızda göreceksiniz ki çok hayat kurtaran bir sistemdir . MySQL 4.0 ve yukarısı InnoDB ve BDB saklama motorları transaction desteklemektedir.

Örneğimizde bir kullanıcı tablomuz var ve bir de gönderi tablomuz. Şöyle bir senaryo çizelim:
Bir kullanıcımızı silmek istiyoruz ve haliyle bu kullanıcının girdiği bütün gönderileri de silmek istiyoruz. Bunu basit bir sorgu ile kolayca gerçekleştirebiliriz:

baglan();
kullaniciSil($kullaniciId);
baglantiyiKapat();

Durum kabaca bundan ibaret. Ama ya işler ters gittiğinde. Kullanıcıyı sildik, ama bir terslik oldu, tam kullanıcı gönderileri silinirken hata oluştu ve gönderileri silemedik. O zaman ne yapacağız ? Gönderi tablosunda kullanıcısı olmayan gönderileri bulup silmek için bir işlem daha yaptırabiliriz. Ama bu ne performans açısından kabul edilebilir, ne de uygulamanın sağlamlığı ve kararlılığı açısından. İşte burada devreye transaction giriyor , tabi bu yapıyı kullanmanın en iyi yolunun PDO dan geçtiğini söylemek gerekir. Dönelim örneğimize:

try
{
   $veritabani = new PDO ( 'mysql:dbname=testdb;host=127.0.0.1', $kullanici, $sifre );
   $veritabani->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
   $veritabani->beginTransaction ();
   try
   {
      if ($veritabani->exec ( $sorgu1 ) == 0)
         throw new Exception ( 'birinci
sorgu çalışmadı'
);
      echo 'sorgu 1 çalıştı
<br />
'
;
      if ($veritabani->exec ( $sorgu2 ) == 0)
         throw new Exception ( 'ikinci
sorgu çalışmadı'
);
      echo 'sorgu 2 çalıştı';
      $veritabani->commit ();
   } catch ( Exception $istisna )
   {
      echo $istisna->getMessage ();
      $veritabani->rollBack ();
   }
} catch ( Exception $baglantiIstistisnasi )
{
   echo 'bağlantı sağlanamadı sebep :
<br />
<b>'
. $baglantiIstistisnasi->getMessage () . '</b>
'
;
}

Normal şartlar altında, aksini belirmedikçe PDO bütün sorgularınızı otomatikman veritabanına iletir. beginTransaction () metodu ile PDO ya işlemlerin sonuçlandırılması için bizim onayımızı almasını söylüyoruz. Daha sonra try bloğu sağlıklı çalışır ise commit() metodu ile PDO ya işlemlerimizin istediğimiz gibi gittiğini ve işlemleri sonuçlandırmasını söylüyoruz. Eğer catch bloğuna düşer ise, ters giden birşeyler olduğunu bildiğimiz için rollBack() metodu ile yaptığımız bütün işlemlerin geri alınmasını söylüyoruz.
Bunu en iyi şöyle test edebilirsiniz. Örnekteki veritabanı ve tabloları oluşturun. User tablosuna veri girin ve user_posts tablosuna hiçbirşey girmeyin. $sorgu1 deki yere kullanıcının id sini doğru girin ve $sorgu2 ye dokunmadan örneği çalıştırın, bakın bakalım ne olmuş.
Şimdi normal şartlar altında,kullanıcı olduğu için kullanıcının silinmesi gerekirdi, kullanıcı gönderilerinin silinmesi için verdiğimiz kullanıcı id si yanlış olduğu için silinecek herhangi birşey olmayacaktı. Kullanıcı uçmuş gitmiş ama kullanıcı gönderileri öyle kalacak idi. Ama kalmayacak, sorgu çalıştıktan sonra gidip tabloya baktığınızda şaşırmayın, bir hata yapmadınız. Kullanıcı orda duruyor ,silinmedi.
Çünkü try bloğumuz sonuna kadar çalışmadı, kullanıcı gönderisini silemediği için istisna fırlattı ve bu yüzden catch blokuna düştü, burda da işlem ters gittiği için yapılan işlemler geri alındı. İşte hayat kurtaran bu güzell işlevi kullanmak bu kadar kolay.

Güzel günler dileği ile, hoşça kalın.