28 Aralık 2010 Salı

Enterprise Manager / SQL Tuning Advisor ve V$SQL

Selamlar,

Bugün iş, yüksek lisans derken biraz kendime vakit ayırabildim ve birçok giriş yapma fırsatı buldum. Bu şekilde yeni makale girişleri yapabildiğim için açıkçası çok memnunum. Umarım okuyan insanlar için faydalı olmuştur.

"SQL Tuning Advisor" olarak bildiğimiz aracın, Enterprise Manager aracılığı ile nasıl koşturulacağını göstermek istiyorum. Öncelikle EM'ye giriş yapıyoruz;


Ardından "Performance" sekmesine geçiyoruz;


"Additional Monitoring Links" kısmından "Top Activity" tuşuna tıklıyoruz ve veritabanı üzerindeki aktivitelere bakıyoruz;


Ekranın sol altındaki grupta yer alan işlemlerden bir veya birkaç tanesini seçerek "Schedule SQL Tuning Advisor"a tıklıyoruz. Karşımıza çıkan ekranda talep ettiğimiz işlemin nasıl ve ne zaman yapılacağı gösterilmekte. Detaylı bilgiye sahip olabilmek için "Scope"u "Comprehensive" olarak seçiyoruz ve "Schedule"ı da "Immediately" yani hemen olarak işaretliyoruz. İsterseniz bu işlem için Oracle'ın tanımladığının dışında da bir isim verebilirsiniz;


Ardından karşınıza aşağıdaki şekilde bir çalışma ekranı gelecek. Bu ekran seçtiğiniz sorgunun veya sorguların karmaşıklığına göre çok kısa da sürebilir uzun da.


Karşımıza gelen sonuç ekranında Oracle'ın bize tavsiye ettiği değişiklikleri görmekteyiz;


Tavsiye ettiği değişiklikler, indeks yaratmak, istatistik toplamak veya yeni bir SQL profili oluşturarak, ilgili sorgunun hangi çalıştırma planı kullanacağını belirlemek olabilir. Bir tanesini seçiyoruz ve devam ediyoruz. Örneğin istatistikleri toplayalım (Implement tuşuna basıyoruz);


"Immediately" seçeneğini seçebilir veya başka bir zamana ayarlayabiliyoruz ve buna ek olarak "Show SQL" tuşuna bastığımızda ise aslında Oracle'ın bizim için ne yaptığını görebiliyoruz. "OK" tuşuna basarak devam ediyoruz ve sonuca ulaşıyoruz;


Bir de SQL Profili ekleme durumuna bakalım. "View Recommendations" tuşuna tıklayarak devam ediyoruz;


"SQL Profile" seçip "Implement" tuşuna basmadan önce yeni planın nasıl olacağına bir göz atalım. Bunu yapabilmek içinse yukarıdaki ekran görüntüsündeki gözlüğe :) tıklıyoruz;


Solda oluşturulacak yeni planı, sağda ise şu anda geçerli planı görmekteyiz. Bir önceki ekrana geri dönüyoruz ve tekrar SQL Profile'ı seçip Implement tuşuna basıyoruz;


Yukarıda da gördüğünüz gibi yeni profilimiz oluşturuldu. SQL Tuning Advisor eğer bizden bir indeks yaratarak bize sağlayacağı faydayı gösterseydi, indeks yaratmayı da düşünebilirdik. Sonuçta geçeceğimiz yol aynı olacak ve Oracle bizim için yaratmak istediği indeksi yaratacaktır. Oracle'ın burada talep ettiği indeksleri ben şiddetle yaratmanızı tavsiye ediyorum (tabii yeterli fiziksel alanınız varsa) çünkü gerçekten ciddi boyutlarda fayda sağlayabiliyor. Başınıza dert olan bir sorgudan (kötü performans gösteren) kısa sürede sizi kurtaracak sonuçları önünüze serebiliyor. İndeks yaratmak da bunlardan yalnızca biri.

"Top Activity" kısmında gördüğünüz SQL'lere de bağlı kalmak zorunda değilsiniz. V$SQL görüntüsü içerisindeki "SQL_ID" sütununa ait bilgi üzerinden de hangi sorgunun "SQL Tuning Advisor" tarafından kontrol edilmesini istediğinizi Enterprise Manager'a söyleyebilirsiniz.

İyi akşamlar.

Ogan

Küçük Bir Flashback Örneği

Merhaba,

Aşağıda birkaç flashback örneği göstermek istiyorum. Aslında flashback database, query, drop gibi özellikler yani flashback özelliğinin, 10g ile birlikte gelen en faydalı özellik olduğuna inanıyorum. Gerçi 9i - 10g geçişi devrim niteliğinde oldu ve birçok yeni özellik tanımlandı. Benim burada göstermek istediğim bu flashback özelliğinin neler yapabileceği. Daha önceki yazılarımda da flashback'ten bahsetmiştim.

Öncelikle düşürülmüş bir tabloya nasıl flashback query yapabiliriz buna bakalım;


SQL> create table ogan_flashback
  2  as
  3  select * from all_objects;

Table created.

SQL> drop table ogan_flashback;

Table dropped.

SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
OGAN_FLASHBACK   BIN$mHxMCwWFUpHgRAAhWi9f6A==$0 TABLE        2010-12-28:20:05:26

SQL> select count(*) from "BIN$mHxMCwWFUpHgRAAhWi9f6A==$0";

  COUNT(*)
----------
    106179

SQL> flashback table ogan_flashback to before drop rename to ogan_deneme;

Flashback complete.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
    106179

--> Görüyoruz ki çöp kutusu içerisinde olan bir tablodan da veri sorgulayabiliyoruz.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
    106179

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

CURRENT_SCN
----------------------------------------
27633995906

SQL> drop table ogan_deneme;

Table dropped.

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

CURRENT_SCN
----------------------------------------
27633995933

SQL> flashback table ogan_deneme to before drop;

Flashback complete.

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

CURRENT_SCN
----------------------------------------
27633995947

SQL> insert into ogan_deneme
  2  select * from ogan_deneme as of scn 27633995906;

106179 rows created.

--> Burada da gördük ki bir tablo düşürüldüğü zaman, purge edilmediği sürece undo segmentlerinde hala tutulmakta. "DROP" komutundan önceki haline çöp kutusundan çıkarılması durumunda bile sorgu gönderebildik. 

SQL> rollback;

Rollback complete.

SQL> select count(*) from ogan_deneme;

  COUNT(*)
----------
    106179

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

CURRENT_SCN
----------------------------------------
27633996599

SQL> drop table ogan_deneme purge;

Table dropped.

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

Table created.

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

CURRENT_SCN
----------------------------------------
27633996897

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

--> Burada da görüyoruz ki purge edildiği zaman flashback query çalıştıramıyoruz. Peki çöp kutusunda duran bir objeye flashback query yapabilir miyiz? Neden olmasın!

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

Table created.

SQL> drop table ogan_deneme;

Table dropped.

SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
OGAN_DENEME      BIN$mHxMCwWRUpHgRAAhWi9f6A==$0 TABLE        2010-12-28:20:16:56

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

CURRENT_SCN
----------------------------------------
27633997753

SQL> select count(*) from "BIN$mHxMCwWRUpHgRAAhWi9f6A==$0" as of scn 27633997753;

  COUNT(*)
----------
    106179

--> Tabloyu düşürdükten sonra bile çöp kutusundaki tablo üzerinde flashback query kullanabiliyoruz. Bir yerde birilerinin bize dur demesi gerekiyor tabii ki;

SQL> insert into "BIN$mHxMCwWRUpHgRAAhWi9f6A==$0"
  2  select * from all_objects;
insert into "BIN$mHxMCwWRUpHgRAAhWi9f6A==$0"
*
ERROR at line 1:
ORA-38301: can not perform DDL/DML over objects in Recycle Bin

SQL> purge recyclebin;

Recyclebin purged.

--> Bu kadarına da fazla cevabını ORA-38301 kodu ile aldık :) Bir başka örnek;

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

Table created.

SQL> create bitmap index idx_ogan_deneme
  2  on ogan_deneme(object_type)
  3  storage (buffer_pool keep);

Index created.

SQL>set autotrace traceonly explain;
SQL> select count(*) from ogan_deneme;

Execution Plan
----------------------------------------------------------
Plan hash value: 1928270016

--------------------------------------------------------------------------------
---------

| Id  | Operation                     | Name            | Rows  | Cost (%CPU)| T
ime     |

--------------------------------------------------------------------------------
---------

|   0 | SELECT STATEMENT              |                 |     1 |     7   (0)| 0
0:00:01 |

|   1 |  SORT AGGREGATE               |                 |     1 |            |
        |

|   2 |   BITMAP CONVERSION COUNT     |                 |   140K|     7   (0)| 0
0:00:01 |

|   3 |    BITMAP INDEX FAST FULL SCAN| IDX_OGAN_DENEME |       |            |
        |

--------------------------------------------------------------------------------
---------

Note
-----
   - dynamic sampling used for this statement

SQL> drop table ogan_deneme;

Table dropped.

SQL> set autotrace off;
SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
OGAN_DENEME      BIN$mHxMCwWlUpHgRAAhWi9f6A==$0 TABLE        2010-12-28:20:31:38

SQL> set autotrace traceonly explain;
SQL> select count(*) from "BIN$mHxMCwWlUpHgRAAhWi9f6A==$0";

Execution Plan
----------------------------------------------------------
Plan hash value: 3423696234

--------------------------------------------------------------------------------
------------------------

| Id  | Operation                     | Name                           | Rows  |
 Cost (%CPU)| Time     |

--------------------------------------------------------------------------------
------------------------

|   0 | SELECT STATEMENT              |                                |     1 |
     7   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE               |                                |     1 |
            |          |

|   2 |   BITMAP CONVERSION COUNT     |                                |   111K|
     7   (0)| 00:00:01 |

|   3 |    BITMAP INDEX FAST FULL SCAN| BIN$mHxMCwWkUpHgRAAhWi9f6A==$0 |       |
            |          |

--------------------------------------------------------------------------------
------------------------

Note
-----
   - dynamic sampling used for this statement

--> Çöp kutusundaki tablo için de indeks kullanımı söz konusu oldu.

SQL> flashback table ogan_deneme to before drop;

Flashback complete.

SQL> drop index idx_ogan_deneme;
drop index idx_ogan_deneme
           *
ERROR at line 1:
ORA-01418: specified index does not exist

--> İyi de yarattığımız idx_ogan_deneme'ye ne oldu? Yalnız adı değişti!

SQL> set autotrace traceonly explain;
SQL> select count(*) from ogan_deneme;

Execution Plan
----------------------------------------------------------
Plan hash value: 3423696234

--------------------------------------------------------------------------------
------------------------

| Id  | Operation                     | Name                           | Rows  |
 Cost (%CPU)| Time     |

--------------------------------------------------------------------------------
------------------------

|   0 | SELECT STATEMENT              |                                |     1 |
     7   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE               |                                |     1 |
            |          |

|   2 |   BITMAP CONVERSION COUNT     |                                |   140K|
     7   (0)| 00:00:01 |

|   3 |    BITMAP INDEX FAST FULL SCAN| BIN$mHxMCwWkUpHgRAAhWi9f6A==$0 |       |
            |          |

--------------------------------------------------------------------------------
------------------------

Note
-----
   - dynamic sampling used for this statement

--> Çöp kutusundan gelen tablonun indeks ismi de yine çöp kutusundan gelen indeks ismi oldu. Buraya dikkat etmelisiniz.

SQL> drop index "BIN$mHxMCwWkUpHgRAAhWi9f6A==$0";

Index dropped.

SQL> set autotrace off;
SQL> show recyclebin;
SQL> select * from user_recyclebin;

no rows selected

--> Çöp kutusundan gelen indeksi yeniden düşürmek istediğimiz zaman düşürebildik ama çöp kutusunda yeniden bulamadık!

İyi çalışmalar.

Ogan

FLASHBACK TABLE ... DROP - Recyclebin

Selamlar,


Bu yazıyı yazmama ilham kaynağı olan Kamil kardeşime buradan teşekkür ederim :)


Flashback drop, bir çeşit flashback özelliğidir ve bildiğiniz üzere flashback özelliği 10g versiyonu ile aramıza katıldı. Ne zaman ve nasıl kullanılması gerektiğini anlatmaya çalışacağım. Öncelikle bir takım koşulları yerine getirmemiz gerekiyor. Bu koşullar "RECYCLEBIN" kullanımı ile ilgili olan koşullar.

RECYCLEBIN

Recyclebin parametresi FLASHBACK DROP özelliğinin devrede olup olmadığını kontrol eden parametredir. ON veya OFF değerlerini alabilir. Varsayılan değeri ON olarak kurulum sırasında tanımlanır. Eğer OFF yani kapalı değerini verdiyseniz düşürdüğünüz tabloları çöp kutusunda (recyclebin) bulamazsınız. Hemen bir örnek;

SQL> conn ogan/password
Connected.
SQL> create table deneme_tahtasi
  2  as
  3  select * from all_objects;

Table created.

SQL> select count(*) from deneme_tahtasi;

  COUNT(*)
----------
      6201

SQL> drop table deneme_tahtasi;

Table dropped.

SQL> select * from recyclebin;

no rows selected

SQL> show parameter recyclebin;

NAME                                 TYPE                             VALUE
-------------------------------------------------------------
recyclebin                           string                           off

RECYCLEBIN bir çeşit data dictionary tablosudur ve düşürülmüş (drop edilmiş) tabloların bilgisini içerir. Tablolar, indeksler bu çöp kutusunda durdukları sürece hala yer kaplamaya devam ederler taa ki "purge" edilene kadar yani tamamen veritabanından silininceye kadar. Her kullanıcının kendi çöp kutusu bulunmaktadır ve yukarıdaki örnekte ogan kullanıcısının nasıl çöp kutusunu incelediği görülmektedir. Eğer kullanıcıyı düşürürseniz, o kullanıcıya ait olan bütün daha önce düşürülmüş olan objeler de çöp kutusundan silinir ve kullanıcının var olan tabloları veya indeksleri çöp kutusuna gönderilmez.

Oracle veritabanı 11g ve Oracle veritabanı 10g arasındaki fark, 10g'de RECYCLEBIN'i aktive edebilmek için veritabanını yeniden başlatmaya gerek kalmıyordu ancak 11g'de SPFILE'a yazım yapılıyor ve veritabanı yeniden başlatılıyor.

Bir obje veritabanından düşürüldüğü zaman çöp kutusunda sistem tarafından oluşturulan bir özel isimlendirme ile tutulur. Bunun nedeni olası isim çakışmalarını engellemek içindir. İsimlendirme biçimi aşağıdaki gibidir;

BIN$unique_id$version
 
RECYCLEBIN özelliğini veritabanı genelinde veya o anki bağlantıya özel değiştirebiliyoruz.
 
SQL> conn / as sysdba 
Connected.
 
SQL> alter session set recyclebin = on; 
 
Session altered.
 
SQL> show parameter recyclebin; 
 NAME TYPE VALUE 
------------------------------------------------------- 
recyclebin string ON
 
SQL> alter system set recyclebin = on scope=both; 
 
System altered.
 
SQL> show parameter recyclebin; 
 
 NAME TYPE VALUE 
---------------------- 
recyclebin string ON
 
Çok çok önemli bir nokta, SYS'nin gerçekleştirdiği drop komutları kesindir ve çöp kutusuna gönderilmez! Veritabanını yeniden başlatmadan da recyclebin kullanımı devreye alınmaz(11g).
 
SQL> create table deneme_tahtasi 
as 
3 select * from dba_users; 
 
Table created. 
 
SQL> select count(*) from deneme_tahtasi; 
 
COUNT(*) 
---------- 
126 
 
SQL> drop table deneme_tahtasi; 
 
Table dropped. 
 
SQL> select * from recyclebin; 
 
no rows selected
 
--> Şimdi ise Ogan kullanıcısı ile deneyelim;
 
SQL> create table deneme_tahtasi
 2  as
 3  select * from all_objects;
 
Table created.
 
SQL> select count(*) from deneme_tahtasi;
 
  COUNT(*)
----------
    469702
 
SQL> drop table deneme_tahtasi;
 
Table dropped.
 
SQL> select * from recyclebin where ORIGINAL_NAME = 'DENEME_TAHTASI';
 
OBJECT_NAME                    ORIGINAL_NAME                    OPERATION TYPE
----------------------------------------------------------------------------------
TS_NAME                        CREATETIME          DROPTIME               DROPSCN
----------------------------------------------------------------------------------
BIN$mHfFVCmFdQngRAAfKW6e2g==$0 DENEME_TAHTASI                   DROP      TABLE
CODESD                         2010-12-28:14:39:36 2010-12-28:14:41:26 3.9736E+10
 
Sistemin tanımladığı obje ismi ile düşürdüğümüz tablonun ilişkisini yukarıda görebilirsiniz. Bu tabloyu eski haline geri alabilmek için yapılması gereken;
 
SQL> flashback table deneme_tahtasi to before drop;
 
Flashback complete.
 
SQL> select count(*) from deneme_tahtasi;
 
  COUNT(*)
----------
    469702
 
--> Veya tamamen yok edebilmek için 2 yol;
 
SQL> drop table deneme_tahtasi;
 
Table dropped.
 
SQL> purge table deneme_tahtasi;
 
Table purged.
 
SQL> select * from recyclebin where ORIGINAL_NAME = 'DENEME_TAHTASI';
 
no rows selected
 
--> VEYA
 
SQL> drop table deneme_tahtasi purge;
 
Table dropped.
 
SQL> select * from recyclebin where ORIGINAL_NAME = 'DENEME_TAHTASI';
 
no rows selected

İyi çalışmalar.

Ogan

RMAN ile Unix Üzerinden Yedekleme (Crontab)

Merhaba,

Oracle OTN forumlarını karıştırırken şu şekilde bir soru ile karşılaştım;

"
Linux crontab'ında RMAN yedekleme zamanlamak istiyorum, nasıl yapabilirim?
"

Soru özel olarak crontab'a yönelik olduğu için nasıl yapılabileceğini paylaşacağım. Tabii crontab dışında da yedekleme şansınız bulunmakta;

Öncelikle kendimize bir shell script hazırlamamız gerekiyor. Aşağıdaki şekilde olduğunu varsayalım;


$ cat /backup/RMAN/backup_full.sh
connect target sys/password@opttest
backup incremental level 0 database format '/backup/DB_FULL_%d_%t_%s';
backup archivelog all delete all input format '/backup/ARC_%d_%t_%s';
exit;
$

1) Veritabanına giriş yaptık.
2) Level 0, yani bir full yedekleme işlemi yapmak istediğimizi gösterdik ve bunu yaparken formatının da nasıl şekilleceğini de belirttik.
3) Veritabanının oluşturduğu archivelog'ların da yedeklenmesini istedik ve formatının nasıl olması gerektiğini de gösterdik.
4) Çıkış talebinde bulunduk.

Bu script'i tanımladıktan sonra crontab'da ne yapmamız gerektiğine bakalım ama bunu yapmadan önce crontab'daki meşhur rakamların ne anlama geldiğini hatırlayalım;

$ man crontab

           minute         The minute of the hour, 0-59

           hour           The hour of the day, 0-23

           monthday       The day of the month, 1-31

           month          The month of the year, 1-12

           weekday        The day of the week, 0-6, 0=Sunday

Crontab işlemlerinden önceki 5 rakam veya sayının anlamının Türkçeleri;

1) Dakika
2) Saat
3) Gün
4) Ay
5) Hafta Günü

Şimdi ise crontab'da nasıl konumlandığını göstereceğim;

$ crontab -l
# ORACLE BACKUP JOBS #
######################

0 1 * * 0 export LD_LIBRARY_PATH=/opt/oracle/product/10.2.0/db_1/lib:/usr/dt/lib:/usr/lib ; export ORACLE_HOME=/opt/oracle/product/10.2.0/db_1/ ; /opt/oracle/product/10.2.0/db_1/bin/rman cmdfile /backup/RMAN/backup_full.sh log /backup/RMAN/backup_full.log

Yukarıdaki görüntüyü sırasıyla açıklamam gerekirse;

Veritabanının yedeği her Pazar günü ( 0 1 * * 0 ), gece saat 01:00'de ( 0 1 * * 0 ) alınacaktır. Recovery Manager'a bir shell script'ini gönderirken cmdfile komutunu kullanıyoruz, log işlemesini de istiyorsak log bilgisini de ekliyoruz. Crontab işe ne zaman başlayacağını ve gerekli library dosyalarını nerede bulacağını ve ORACLE_HOME parametresinin ne olduğunu artık biliyor (LD_LIBRARY_PATH, ORACLE_HOME). RMAN ise ne yapması gerektiğini artık biliyor (cmdfile, log).

Son olarak yukarıdaki yedeğin nasıl bir log dosyası üretmiş olabileceğine bakalım;

$ cat /backup/RMAN/backup_full.log

Recovery Manager: Release 10.2.0.4.0 - Production on Sun Dec 26 01:00:01 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

RMAN> connect target *
2> backup incremental level 0 database format '/backup/DB_FULL_%d_%t_%s';
3> backup archivelog all delete all input format '/backup/ARC_%d_%t_%s';
4> exit;
connected to target database: OPTTEST (DBID=750193206)

Starting backup at 26-DEC-10
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=1386 devtype=DISK
channel ORA_DISK_1: starting compressed incremental level 0 datafile backupset
channel ORA_DISK_1: specifying datafile(s) in backupset
input datafile fno=00002 name=/db/OPTIMA/oradata/opttest/opttest/UNDOTBS1.dbf
input datafile fno=00341 name=/db/OPTIMA/oradata/opttest/data/NORS_OWCTTS_D_02.dbf
input datafile fno=00369 name=/db/OPTIMA/oradata/opttest/data/NORS_ISUP_GROUP_D_03.dbf
input datafile fno=00307 name=/db/OPTIMA/oradata/opttest/data/NORS_TONES_D_02.dbf
input datafile fno=00311 name=/db/OPTIMA/oradata/opttest/data/NORS_SINGLE_UNIT_PM_D_02.dbf
input datafile fno=00313 name=/db/OPTIMA/oradata/opttest/data/NORS_PM_D_02.dbf
input datafile fno=00318 name=/db/OPTIMA/oradata/opttest/data/NORS_RTLTSUM_D_02.dbf
input datafile fno=00319 name=/db/OPTIMA/oradata/opttest/data/NORS_SOTS_D_02.dbf
input datafile fno=00320 name=/db/OPTIMA/oradata/opttest/data/NORS_SYSPERF_D_02.dbf
input datafile fno=00328 name=/db/OPTIMA/oradata/opttest/data/NORS_TREATMENT_D_02.dbf
channel ORA_DISK_1: starting piece 1 at 26-DEC-10
channel ORA_DISK_1: finished piece 1 at 26-DEC-10
piece handle=/backup/DB_FULL_OPTTEST_738731834_4120 tag=TAG20101226T010021 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:08:46
Finished backup at 26-DEC-10

Starting Control File and SPFILE Autobackup at 26-DEC-10
piece handle=/backup/c-750193206-20101226-00 comment=NONE
Finished Control File and SPFILE Autobackup at 26-DEC-10

Starting backup at 26-DEC-10
current log archived
using channel ORA_DISK_1
channel ORA_DISK_1: starting compressed archive log backupset
channel ORA_DISK_1: specifying archive log(s) in backup set
input archive log thread=1 sequence=546 recid=7882 stamp=738451102
input archive log thread=1 sequence=547 recid=7883 stamp=738532873
input archive log thread=1 sequence=548 recid=7884 stamp=738550821
input archive log thread=1 sequence=549 recid=7885 stamp=738622852
input archive log thread=1 sequence=550 recid=7886 stamp=738646398
input archive log thread=1 sequence=551 recid=7887 stamp=738714019
input archive log thread=1 sequence=552 recid=7888 stamp=738732388
channel ORA_DISK_1: starting piece 1 at 26-DEC-10
channel ORA_DISK_1: finished piece 1 at 26-DEC-10
piece handle=/backup/ARC_OPTTEST_738732389_4122 tag=TAG20101226T032628 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:02:36
channel ORA_DISK_1: deleting archive log(s)
archive log filename=/backup/OPTTEST/archivelog/2010_12_22/o1_mf_1_546_6k4mqk7w_.arc recid=7882 stamp=738451102
archive log filename=/backup/OPTTEST/archivelog/2010_12_23/o1_mf_1_547_6k73lz3b_.arc recid=7883 stamp=738532873
archive log filename=/backup/OPTTEST/archivelog/2010_12_24/o1_mf_1_548_6k7o3th2_.arc recid=7884 stamp=738550821
archive log filename=/backup/OPTTEST/archivelog/2010_12_24/o1_mf_1_549_6k9vgs5q_.arc recid=7885 stamp=738622852
archive log filename=/backup/OPTTEST/archivelog/2010_12_25/o1_mf_1_550_6kblgot5_.arc recid=7886 stamp=738646398
archive log filename=/backup/OPTTEST/archivelog/2010_12_25/o1_mf_1_551_6kdnhqyo_.arc recid=7887 stamp=738714019
archive log filename=/backup/OPTTEST/archivelog/2010_12_26/o1_mf_1_552_6kf6fx5w_.arc recid=7888 stamp=738732388
Finished backup at 26-DEC-10

Starting Control File and SPFILE Autobackup at 26-DEC-10
piece handle=/backup/c-750193206-20101226-01 comment=NONE
Finished Control File and SPFILE Autobackup at 26-DEC-10

Recovery Manager complete.

İyi çalışmalar.

Ogan

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
Takip et: @oganozdogan