Flashback Query ExampleExpert Oracle Database Tips by Donald BurlesonMarch 25, 2015 |
RMAN - Oracle Flashback Query
Using Oracle flashback query, you can retrieve the committed data as it was at a past point in time. As most of other flashback technologies, this feature retrieves data from the undo tablespace. It is possible to get undo data based on a specific time or scn number. Using the select as of statement with both OF TIMESTAMP and OF SCN clauses, you can use this feature easily. It can even be performed by any application developer without any DBA intervention. Developers can use the dbms_flashback package to perform flashback query directly from their applications, but the execute privilege should be granted on the dbms_flashback package. Now see it in action through the following scenario:- Scenario 1: At 12.00, Bob got a call from an application developer who told him that somebody deleted all the rows from one of the tables by omitting the WHERE clause and committing the transaction. He wanted to know which rows were deleted from the table. Bob decided to use flashback query to get the before image of the deleted rows.
- Create a table as it was created by the application developer and query it as follows:
SQL>
create
table tbl_seg_tbs as
2 select
segment_name, tablespace_name
from
dba_segments
3 where
rownum<7
order by
bytes desc;
Table created.
SQL>
select
count(*)
from
tbl_seg_tbs;
COUNT(*)
----------
6
SQL>
create
table tbl_seg_tbs as
2 select
segment_name, tablespace_name
from
dba_segments
3 where
rownum<7
order by
bytes desc;
Table created.
SQL>
select
count(*)
from
tbl_seg_tbs;
COUNT(*)
----------
6
SQL>
- In order to return back to this state of the table anytime, get the current scn number and timestamp:
SQL>
select
to_char(sysdate,'dd-mm-yyyy hh24:mi:ss') ddate,
dbms_flashback.get_system_change_number() scn from dual;
DDATE SCN
-------------------- ----------
07-02-2010 15:14:21 460141
select
to_char(sysdate,'dd-mm-yyyy hh24:mi:ss') ddate,
dbms_flashback.get_system_change_number() scn from dual;
DDATE SCN
-------------------- ----------
07-02-2010 15:14:21 460141
- Now run the delete command to clear the table and commit the transaction:
SQL>
delete from
tbl_seg_tbs;
6 rows deleted.
SQL>
commit;
Commit complete.
SQL>
select * from
tbl_seg_tbs;
no rows selected
delete from
tbl_seg_tbs;
6 rows deleted.
SQL>
commit;
Commit complete.
SQL>
select * from
tbl_seg_tbs;
no rows selected
- As Bob knows the exact time of the correct state of the table, he uses flashback query and retrieves the before state of deleted rows from the undo tablespace as follows:
SQL>
select
count(*)
from tbl_seg_tbs
2 as of
timestamp to_timestamp('07-02-2010 15:14:21','dd-mm-yyyy hh24:mi:ss');
COUNT(*)
----------
6
SQL>
select
count(*)
from tbl_seg_tbs
2 as of
timestamp to_timestamp('07-02-2010 15:14:21','dd-mm-yyyy hh24:mi:ss');
COUNT(*)
----------
6
SQL>
SQL>
select * from
tbl_seg_tbs
2 as of scn 460135;
COUNT(*)
----------
6
SQL>
select * from
tbl_seg_tbs
2 as of scn 460135;
COUNT(*)
----------
6
SQL>
SQL>
select
count(*)
from tbl_seg_tbs
2 as of timestamp (systimestamp -interval '15' minute);
COUNT(*)
----------
6
SQL>
select
count(*)
from tbl_seg_tbs
2 as of timestamp (systimestamp -interval '15' minute);
COUNT(*)
----------
6
SQL>
SQL>
select scn_to_timestamp(460141) ddate,
timestamp_to_scn(to_timestamp('07-02-2010 15:14:21','dd-mm-yyyy
hh24:mi:ss')) scn from dual;
DDATE SCN
------------------------------------ ----------
07-FEB-10 03.14.21.000000000 PM 460141
SQL>
select scn_to_timestamp(460141) ddate,
timestamp_to_scn(to_timestamp('07-02-2010 15:14:21','dd-mm-yyyy
hh24:mi:ss')) scn from dual;
DDATE SCN
------------------------------------ ----------
07-FEB-10 03.14.21.000000000 PM 460141
SQL>
You can retrieve any dropped PL/SQL object using flashback query. How? It is very easy. The source of these objects is stored in an internal table: sys.source$. It means that when you create a trigger, the line that contains its source is added to that table. The same works for dropping the procedure. Please note that recreating the objects relies on the dependencies being valid; thus, any tables/views referenced in the procedure must be present or recreated before recreating the procedure. So see how it works:
- Create a simple trigger and get the current scn valueof the database:
SQL>
create or replace
trigger trg_logon
2 after logon on database
3 begin
4 insert into tbl_logons values(sysdate, user);
5 end;
6 /
Trigger created.
SQL>
select
current_scn
from
v$database;
CURRENT_SCN
-----------
528857
SQL>
create or replace
trigger trg_logon
2 after logon on database
3 begin
4 insert into tbl_logons values(sysdate, user);
5 end;
6 /
Trigger created.
SQL>
select
current_scn
from
v$database;
CURRENT_SCN
-----------
528857
SQL>
- Now drop the trigger.
SQL>
drop
trigger trg_logon;
Trigger dropped.
SQL>
drop
trigger trg_logon;
Trigger dropped.
SQL>
- Using the scn value that has been noted before dropping the trigger, query the dba_source view as follows:
SQL>
select
text
from dba_source
as of
scn 528857
2 where name='trg_logon';
TEXT
---------------------------------------------------
trigger trg_logon
after logon on database
begin
insert into tbl_logons values(sysdate, user);
end;
SQL>
select
text
from dba_source
as of
scn 528857
2 where name='trg_logon';
TEXT
---------------------------------------------------
trigger trg_logon
after logon on database
begin
insert into tbl_logons values(sysdate, user);
end;
SQL>