Satır bazında yapılan
flashback 3 şekilde yapılabilir;
Flashback Query ; Bir tabloda ki
verilerin geçmiş bir zamandaki durumunlarını select etmek için kullanırız.
Örneğin, bir tablo üzerinde yanlışlıkla yapılan ve commit edilen bir update
işlemi sonrasında, update öncesindeki değerlerin neler olduğunu görebilmemizi
sağlar.
Flashback Versions Query ; Version query, bir kaydın, belirlenen iki zaman aralığındaki almış olduğu
değerleri select eder. Yani a personelinin 2010, 1 Aralık saat 09:00
tarihindeki maaşı ile 2010 1 Kasım saat 09:00 daki maaşlarını
karşılaştırabilirsiniz.
Flashback Transaction Query ; Bir transaction
tarafından yapılan DML işlemlerine ait yapılan değişiklikleri veya belli bir
zaman aralığında yapılan tüm değişiklikleri, undo sql leri ile birlikte
gösterir.
Şimdi bu 3 koşulu örneklendirmeye çalışalım. Öncelikle üzerinde
çalışacabileceğimiz bir sample data oluşturalım. İşlemin yapıldı tarih aralığı
ise 21.12.2010 13:19:30 ve 13:25 arasına ait. Bu bilgiye sahip olmamız
istediğimiz datayı bulmamızda yardım edecektir.
create table kamil.deneme (
id number(5),
ad varchar2(20),
soyad varchar2(30) ) ;
insert into kamil.deneme values (1,'aaa','bbb') ;
insert into kamil.deneme values (1,'ccc','ddd') ;
insert into kamil.deneme values (1,'eee','fff') ;
insert into kamil.deneme values (1,'ggg','kkk') ;
commit ;
update kamil.deneme set ad = 'xxx';
commit ;
insert into kamil.deneme values (1,'lll','mmm') ;
insert into kamil.deneme values (1,'nnn','ooo') ;
commit;
update kamil.deneme set ad = 'yyy';
commit;
Tablomuz hazır.
Flashback Query’ i test edelim. Tabloda son durumda en
son yapılan update işlemi ile tüm kayıtların ad’ ı ‘yyy’ olarak set edilmiş
gözüküyor. Eğer, tablonun 13:20 deki halini görmek istersek eğer;
SELECT * FROM kamil.deneme AS OF TIMESTAMP TO_TIMESTAMP('2010-12-21 13:20:00',
'YYYY-MM-DD HH24:MI:SS')
==> SELECT * FROM kamil.deneme AS OF TIMESTAMP TO_TIMESTAMP('2010-12-21
13:20:00', 'YYYY-MM-DD HH24:MI:SS')
ID AD SOYAD
-- -------------------- ------------------------------
1 xxx bbb
1 xxx ddd
1 xxx fff
1 xxx kkk
4 rows selected.
Update işleminden önceki bir zaman aralığını select ettiğimiz için tablonun son
durumunda tüm ad alanları ‘yyy’ olmasına rağmen burada önceki hallerini ‘xxx’
görüyoruz.
Burada tablodaki tüm kayıtları select etmek yerine sadece bir kayıtı select
etmek isterseniz ;
Where soyad = ‘bbb’
satırını ekleyebilirsiniz. Milyonlarca kayıt olan bir tabloda tüm kayıtları
elde etmek yerine sadece bir kayda bakmanız gerekebilir. Veya zaman aralığını
tam olarak kestiremiyorsak, aşağıdaki deneyerek bulabiliriz. Veya scn number’ I
biliyorsak ona göre where kriteri belirleyip select edebiliriz.
==> select * from kamil.deneme as of timestamp (systimestamp - interval '25'
minute)
ID AD SOYAD
-- ----- ------------------------------
1 xxx bbb
1 xxx ddd
1 xxx fff
1 xxx kkk
4 rows selected.
Son bir not olarak flashback query ile select çalıştırdığımızda aşağıdaki gibi
ora-01466 hatası alırsak bunun anlamı girmiş olduğumuz zaman aralığına ait
herhangi DML işlemi olmadığı anlamına gelmektedir. Flashback DDL işlemlerini
desteklememektedir.
==> select * from kamil.deneme as of timestamp (systimestamp - interval '55'
minute)
select * from kamil.deneme as of timestamp (systimestamp - interval '55'
minute)
*
Error at line 1
ORA-01466: unable to read data - table definition has changed
Flashback Versions Query test edelim. Tabloya son yapılan update işleminin
13:25 de yapıldığını varsayarsak 13:20 ile 13:26 daki tablo kayıtlarını select
ettiğimde ad alanında yapılan değişikliği görebilmeliyim diye düşünüyorum.
Sorguyu ilk çalıştırdığımda aşağıdaki gibi bir hata aldım. Hatanın nedeni
select etmeye çalıştığım zaman aralığının undo_retention dışında kalmasından
dolayı idi. Parametreyi artırdığımda sorun
giderilmiş oldu.
==> SELECT versions_xid,
versions_startscn,
versions_endscn,
versions_operation,
VERSIONS_STARTTIME,
VERSIONS_ENDTIME,
id,
ad,
soyad
FROM kamil.deneme VERSIONS BETWEEN TIMESTAMP
TO_TIMESTAMP ('2010-12-21 13:20:00',
'YYYY-MM-DD HH24:MI:SS')
AND TO_TIMESTAMP ('2010-12-21 13:30:00',
'YYYY-MM-DD HH24:MI:SS') ;
Error at line 1
ORA-30052: invalid lower limit snapshot expression
==> alter system set undo_retention = 5000
System altered.
Tekrar çalıştırıyoruz.
==> SELECT versions_xid,
versions_startscn,
versions_endscn,
versions_operation,
VERSIONS_STARTTIME,
VERSIONS_ENDTIME,
id,
ad,
soyad
FROM kamil.deneme VERSIONS BETWEEN TIMESTAMP
TO_TIMESTAMP ('2010-12-21 13:20:00',
'YYYY-MM-DD HH24:MI:SS')
AND TO_TIMESTAMP ('2010-12-21 13:30:00',
'YYYY-MM-DD HH24:MI:SS')
Çıktıyı biraz sadeleştirip (düzgün okunması için bazı alanları çıkartıp)
ekliyorum;
ID AD SOYAD
1 yyy ooo
1 yyy mmm
1 yyy kkk
1 yyy fff
1 yyy ddd
1 yyy bbb
1 nnn ooo
1 lll mmm
1 xxx bbb
1 xxx ddd
1 xxx fff
1 xxx kkk
Flashback Transaction Query’ i test edelim. Örneğimizde yapılan son update
işleminin yanlışlıkla yapıldığını varsayalım. Bu tarz bir durumla
karşılaşıldığında aşağıdaki query ile update’ in yapıldığı zamanı sorgulayıp
yapılan her update işlemi için sistem tarafından otomatik olarak hazırlanmış
olan undo_sql’ lerini çalıştırmamız yeterli olacaktır.
select start_scn, start_timestamp,
commit_scn, commit_timestamp,
operation,
table_name, table_owner,
undo_sql
from flashback_transaction_query
where table_owner='KAMIL'
and table_name = 'DENEME'
and start_timestamp > to_date('2010-12-21 13:25:00', 'YYYY-MM-DD
HH24:MI:SS')
OPERATION UNDO_SQL
INSERT delete from "KAMIL"."DENEME" where ROWID =
'AAAV6AAAEAAAADIAAF';
INSERT delete from "KAMIL"."DENEME" where ROWID =
'AAAV6AAAEAAAADIAAE';
UPDATE update "KAMIL"."DENEME" set "AD" = 'nnn'
where ROWID = 'AAAV6AAAEAAAADIAAF';
UPDATE update "KAMIL"."DENEME" set "AD" = 'lll'
where ROWID = 'AAAV6AAAEAAAADIAAE';
UPDATE update "KAMIL"."DENEME" set "AD" = 'xxx'
where ROWID = 'AAAV6AAAEAAAADIAAD';
UPDATE update "KAMIL"."DENEME" set "AD" = 'xxx'
where ROWID = 'AAAV6AAAEAAAADIAAC';
UPDATE update "KAMIL"."DENEME" set "AD" = 'xxx'
where ROWID = 'AAAV6AAAEAAAADIAAB';
UPDATE update "KAMIL"."DENEME" set "AD" = 'xxx'
where ROWID = 'AAAV6AAAEAAAADIAAA';
Flashback Query' nin çalıştırılması için ya üzerinde işlem yapılacak olan
tabloya yada tüm tablolar için aşağıdaki yetkilerin ilgili kullanıcıya
verilmesi lazım;
grant flashback on table_name to user_name;
grant flashback on any
table to user_name;
Flasback transaction
query için ise aşağıdaki yetkinin verilmesi yeterli olacaktır;
grant select any
transaction to user_name;
Çıkan sonuçdan da görüleceği üzere yapılan insert işlemine karşılık delete,
update işlemine karşılık ters update scriptleri oluşdu. Bunu çalıştırmanız son
yapılan işlemi geri almak için yeterli olacaktır. Production ortamlarda
flashback komutları ile çalışırken dikkatli olmanız gerektiğini hatırlatmaya
gerek yok diye düşünüyorum:)
Kamil TÜRKYILMAZ