Flashback Table et DDL…

Si l’article précédent présente Oracle Total Recall, c’est, certes pour illustrer une options simplissime pour résoudre un problème de plus en plus commun… C’est aussi pour soutenir que son utilisation peut amener à des situations étonnantes lorsque vous utiliser la commande flashback table. C’est l’objet de ce nouvel article.

Notes:
Ce comportement a été observé en version 11.2.0.2 sur Linux 32 bits et est différent selon les versions.
Pour rappel, la fonctionnalité de flashback table est une encapsulation de flashback query versions pour ré-appliquer à l’envers les modifications ; il n’est donc, ni étonnant que cela fonctionne avec Total Recall, ni étonnant que, en 11.2, elle traverse certains ordres DDL. Ceci parait assez naturel, même si la combinaison n’est pas décrite explicitement dans la documentation.

Flashback Table ne supporte pas le DDL

Pour parler de choses « naturelles », il parait assez évident que, sans utiliser Total Recall, la fonctionnalité de Flashback Table ne supporte pas le DDL. On peut illustrer ce fonctionnement avec le script suivant :

connect demo/demo

create table T1 (
id number,
col1 number);

insert into T1 values (1,1);
commit;

alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
col sysdate new_value tsp
select sysdate from dual;

SYSDATE
-------------------
25/10/2011 07:31:27


select id, col1
from T1;

ID COL1
--- ----------
1 1


delete from T1;
commit;

alter table T1 add (col2 number);


col myscn format 999999999999999 new_value myscn
select timestamp_to_scn(cast(
to_date('&&tsp',
'DD/MM/YYYY HH24:MI:SS')
as timestamp)) myscn
from dual;

MYSCN
---------
1176499


alter table T1 enable row movement;
flashback table T1 to scn &&myscn;
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed


drop table T1 purge;

Flashback Table et Total Recall

Avec des Flashback Data Archives actives, c’est une autre histoire. Si vous ajoutez une colonne par exemple, flashback table est capable de faire revenir en arrière le DML sans changer le DDL comme l’illustre le script ci-dessous :

connect demo/demo

create table T1 (
id number,
col1 number)
flashback archive;

insert into T1 values (1,1);
commit;

alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
col sysdate new_value tsp
select sysdate from dual;

SYSDATE
-------------------
25/10/2011 07:41:13


select id, col1
from T1;

ID COL1
--- ----------
1 1


delete from T1;
commit;

alter table T1 add (col2 number);

col myscn format 999999999999999 new_value myscn
select timestamp_to_scn(cast(
to_date('&&tsp',
'DD/MM/YYYY HH24:MI:SS')
as timestamp)) myscn
from dual;

MYSCN
---------
1177513


alter table T1 enable row movement;
flashback table T1 to scn &&myscn;

Flashback complete.

select id, col1, col2
from T1;

ID COL1 COL2
--- ---------- ----------
1 1


alter table T1 no flashback archive;
drop table T1 purge;

Evidemment, ce n’est pas toujours vrai ! Supprimer une colonne aura pour effet de faire échouer la commande de flashback :

connect demo/demo

create table T1 (
id number,
col1 number)
flashback archive;

insert into T1 values (1,1);
commit;

alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
col sysdate new_value tsp
select sysdate from dual;

SYSDATE
-------------------
25/10/2011 07:37:36


select id, col1
from T1;

ID COL1
--- ----------
1 1


delete from T1;
commit;

alter table T1 add (col2 number);
alter table T1 drop column col1;

col myscn format 999999999999999 new_value myscn
select timestamp_to_scn(cast(
to_date('&&tsp',
'DD/MM/YYYY HH24:MI:SS')
as timestamp)) myscn
from dual;

MYSCN
---------
1177025


alter table T1 enable row movement;
flashback table T1 to scn &&myscn;
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed


alter table T1 no flashback archive;
drop table T1 purge;

Et maintenant, la bizarreté

Là où les choses passent dans le paranormal, c’est lorsque vous faite du flashback table sur une table non archivée mais impliquée dans Total Recall. Suivez bien qui est qui :

connect demo/demo

create table T1 (
id number,
col1 number)
flashback archive;

create table T2 (
id number,
col1 number);

insert into T1 values (1,1);
insert into T2 values (1,1);
commit;

alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
col sysdate new_value tsp
select sysdate from dual;

SYSDATE
-------------------
25/10/2011 07:49:30


select id, col1
from T2;

ID COL1
--- ----------
1 1


delete from T1;
delete from T2;
commit;

alter table T2 add (col2 number);

col myscn format 999999999999999 new_value myscn
select timestamp_to_scn(cast(
to_date('&&tsp',
'DD/MM/YYYY HH24:MI:SS')
as timestamp)) myscn
from dual;

MYSCN
---------
1179058


alter table T2 enable row movement;
flashback table T2 to scn &&myscn;

Flashback complete.

select id, col1, col2
from T2;

ID COL1 COL2
--- ---------- ----------
1 1


drop table T2 purge;
alter table T1 no flashback archive;
drop table T1 purge;

Etonnant ? Pas tant que ça quand on sait comment l’activation de Total Recall modifie le fonctionnement des UNDO en 11.2 !