28 Aralık 2010 Salı

Commit Rollback Savepoint - Transaction ve Undo'nun Gücü

Selamlar,


Bir transaction nasıl sonlanır, nedir ve neden önemlidir sorularına cevap arayacağız. Öncelikle "transaction" kelimesini bundan sonra "işlem" olarak analım. Bir işlemi SQL sorgusu yazarak başlatabiliriz ve commit veya rollback göndererek ya da bir DDL komutu çalıştırarak sonlandırabiliriz. Unutmadan hemen belirteyim, bir işlem içerisindeyken bilinçli olarak çıkış yaparsanız yarıda bıraktığınız işlem commit edilir ancak isteğiniz dışında bir sonlandırma olursa da rollback ile işleminiz sonlandırılır. Bir örnek;



$ sqlplus ogan/password


SQL*Plus: Release 10.2.0.4.0 - Production on Tue Dec 28 12:34:00 2010


Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options


SQL> set line 100
SQL> set pagesize 1000
SQL> drop table ogan_deneme purge;
drop table ogan_deneme purge
           *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL> create table ogan_deneme
  2  as
  3  select * from all_users;


Table created.


SQL> select tr.XIDUSN "Undo Segment Numarasi", tr.UBAFIL "Undo Blok Adresi", tr.START_TIME "Baslangic Zamani",
  2  tr.USED_UBLK "Kullanilan Undo Bloklari", tr.USED_UREC "Kullanilan Undo Kayitlari", LOG_IO "Mantiksal I/O", PHY_IO "Fiziksel I/O"
  3  from v$transaction tr, v$session se
  4  where tr.ses_addr = se.saddr
  5  and username='OGAN';


no rows selected



SQL> select count(*) from ogan_deneme;


  COUNT(*)
----------
       126



SQL> insert into ogan_deneme
  2  select * from ogan_deneme;


126 rows created.



SQL> select count(*) from ogan_deneme;


  COUNT(*)
----------
       252


SQL> select tr.XIDUSN "Undo Segment Numarasi", tr.UBAFIL "Undo Blok Adresi", tr.START_TIME "Baslangic Zamani",
  2  tr.USED_UBLK "Kullanilan Undo Bloklari", tr.USED_UREC "Kullanilan Undo Kayitlari", LOG_IO "Mantiksal I/O", PHY_IO "Fiziksel I/O"
  3  from v$transaction tr, v$session se
  4  where tr.ses_addr = se.saddr
  5  and username='OGAN';

Undo Segment Numarasi Undo Blok Adresi Baslangic Zamani     Kullanilan Undo Bloklari
--------------------- ---------------- -------------------- ------------------------
Kullanilan Undo Kayitlari Mantiksal I/O Fiziksel I/O
------------------------- ------------- ------------
                    8                2 12/28/10 12:34:30                           1
                        1            15            1

--> Henüz rollback veya commit ile işlemimizi bitirmek istemedik ve derken;

SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
$ sqlplus ogan/password

SQL*Plus: Release 10.2.0.4.0 - Production on Tue Dec 28 12:37:40 2010

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       252

--> Yaptığımız değişiklik commit edilmiş ve işlemimiz sonlandırılmış. Bu noktada belirtmeliyim ki bu bir OCA sertifikasyon sorusu olarak karşınıza çıkabilir. Bir de diğer yönden bakalım?

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

252 rows created.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       504

--> Bir veri girişinde bulunduk ancak henüz commit veya rollback göndermedik. Tam bu sırada işgüzarlık yapıp yemeğe gittiğimizi düşünelim. Aksi bir veritabanı yöneticisi bunun farkına vardı ve bizim henüz commit veya rollback göndermediğimiz işlemimizi sonlandırmak istedi (çok kızgın);

$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.4.0 - Production on Tue Dec 28 12:38:52 2010

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select sid, serial# from v$session where username='OGAN';

       SID    SERIAL#
---------- ----------
      1371       7716

SQL> alter system kill session '1371,7716';

System altered.

--> Bağlantımızı sonlandırdı! Aradan döndüğümüz ise göreceğimiz görüntü;

SQL> select count(*) from ogan_deneme;
select count(*) from ogan_deneme
*
ERROR at line 1:
ORA-00028: your session has been killed

SQL> conn ogan/password
Connected.
SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       252

--> Çok kötü! Yaptığımız ama commit etmediğimiz değişiklik rollback edilerek, bağlantımızı kaydetmeden önceki durumuna getirilmiş. Olsun diyerek devam ediyoruz;

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

252 rows created.

SQL> savepoint ogan_1;

Savepoint created.

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

504 rows created.

SQL> savepoint ogan_2;

Savepoint created.

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

1008 rows created.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
      2016

--> Henüz rollback veya commit göndermedik ve karar vermek için bekliyoruz. ogan_1 savepoint'ine geri dönmek istedik diyelim;

SQL> rollback to ogan_1;

Rollback complete.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       504

--> İstediğimiz noktaya geri döndük ancak şunu unutmayın, bu işlemlerin olduğu yerde commit kullanırsanız savepoint'leriniz yok olur. Savepoint'ler rollback yapılması için bulunmaktadır ve commit edilen bir bilgiyi size geri veremezler. Bunu flashback query yapabilir. Bunu da göstereceğim ancak sırada commit edilirse ne olacağı var;

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

504 rows created.

SQL> savepoint ogan_2;

Savepoint created.

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

1008 rows created.

SQL> savepoint ogan_3;

Savepoint created.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
      2016

SQL> commit;

Commit complete.

SQL> rollback to ogan_2;
rollback to ogan_2
*
ERROR at line 1:
ORA-01086: savepoint 'OGAN_2' never established

--> Commit gönderdikten sonra yapılacak değişiklikleri kaçırdık ama üzülmeyin bizim için tutan birisi var. Kim? Undo!

SQL> insert into ogan_deneme
  2  select * from ogan_deneme as of timestamp sysdate - 0.10/24;

252 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       252

--> Undo segment'leri için ne kadar teşekkür etsek azdır. Yalnız hiç DDL kullanmadık? Hep DML kullandık ve sonuç elde ettik. Ya DDL kullansaydık?

SQL> select to_char(current_scn) current_scn from v$database;

CURRENT_SCN
------------------
27633924126

SQL> truncate table ogan_deneme;

Table truncated.

SQL> insert into ogan_deneme
  2  select * from ogan_deneme as of scn 27633924126;
insert into ogan_deneme
            *
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed

--> Geçmişler olsun, DDL gönderdiğimiz tablodan flashback query yapma şansımızı kaybetmiş olduk.

İşlemler (transaction) atomik yapılardır ve sonlandırırken de başlandırırken de dikkatli olmak zorundayız. Örneğin bir banka veritabanını düşünün. Müşteriniz para göndermek istiyor ve gönderme tuşuna bastığı sırada bir problem oluştu ve siz de hesabından parayı çekmiş oldunuz. Para karşı tarafa aktarılamadı ama müşterinizin hesabından çekildi. Bunun kabul edilebilir olacağına inanmıyorsanız, parayı çekme ve gönderme aksiyonlarını aynı atomik işlem yapısı içerisinde geliştirmeniz gerekmektedir. Aksi halde "kaos" kaçınılmazdır. Eğer para gitmediyse hesaptan da düşmemeli. Eğer para karşıya ulaştıysa, hesaptan da düşmeli. Oracle dokümantasyonundan güzel bir örnek;

Description of Figure 10-1 follows

3 adet DML işlemi arasında işlem sonlandırılmıyor ancak arada bir yerde sonlanması halinde yeniden hatırlayalım, UPDATE ile başlayan işlem rollback yapılıyor. COMMIT WORK = COMMIT.

Bir işlem ne zaman başlar? Veritabanına bağlandığınız zaman işlem başlatmış sayılmazsınız. Bir DML veya DDL işlemi yapmanız veya SET TRANSACTION komutunu kullanmanız gerekmektedir. Bir işlemi sonlandırmak içinse COMMIT, ROLLBACK veya bir DDL kullanmanız gerekmektedir. Bir DDL komutu gönderildiği zaman gizli bir commit çalıştırıldığını unutmayalım.

Peki bir işlemi ile SCN (system change number) arasındaki bağlantı nedir? Her işlem başladığı zaman veritabanı bu işlem bloğu için bir SCN atamasında bulunur. Bu SCN atamasının amacı veritabanı geri dönüşlerinde veya yedeklemelerinde mantıksal hedef belirlemektir. Atanmış olan SCN, işlem sonlanıncaya kadar o bağlantı ve işlem için aynı kalır. İşlem sonlandırılıncaya kadar gerçekleşen bütün DML komutları için aynı SCN kullanılır.

Son olaraksa aklınıza şu soru gelebilir, neden işlem mantığı var? Cevap: "okuma tutarlılığı";

İlk Bağlantı - İşlem:

SQL> drop table ogan_deneme purge;

Table dropped.

SQL> create table ogan_deneme
  2  as
  3  select * from all_users;

Table created.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       126

İkinci Bağlantı - İşlem:

SQL> select count(*) from ogan.ogan_deneme;

  COUNT(*)
----------
       126

--> Her iki bağlantı da aynı veriyi okumaktalar.

İlk Bağlantı - İşlem:

SQL> insert into ogan_deneme
  2  select * from ogan_deneme;

126 rows created.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
       252

İkinci Bağlantı - İşlem:

SQL> select count(*) from ogan.ogan_deneme;

  COUNT(*)
----------
       126

--> İkinci bağlantı hala 126 görmekte çünkü ilk bağlantı commit veya rollback göndermedi. 

İlk Bağlantı - İşlem:

SQL> commit work;

Commit complete.

İkinci Bağlantı - İşlem:

SQL> select count(*) from ogan.ogan_deneme;

  COUNT(*)
----------
       252

İlk Bağlantı - İşlem:

SQL> drop table ogan_deneme purge;

Table dropped.

İkinci Bağlantı - İşlem:

SQL> select count(*) from ogan.ogan_deneme;
select count(*) from ogan.ogan_deneme
                          *
ERROR at line 1:
ORA-00942: table or view does not exist

İyi çalışmalar dilerim.

Ogan

1 yorum:

www.canersecgin.net dedi ki...

Hocam elinize sağlık linklerinizi takip ederek okuyorum yazılarınızı çok faydalı oluyor. İyi Çalışmalar

Takip et: @oganozdogan