quinta-feira, 10 de maio de 2007

Utilizando o Flashback Query a partir do Oracle 9i

Olá,
Em tempos de Oracle 10g na qual o mesmo implementa várias tecnologias de Flashback como Flashback Database, Flashback Table, Flashback Drop entre outros, abordarei o uso do recurso de Flashback Query para administradores de banco de dados Oracle 9i.

Introduzido com o Oracle 9i, este recurso fornece a habilidade de visualizar os dados como eles estavam em um determinado tempo no passado. Por padrão, operações no banco de dados usam os dados disponíveis mais recentemente "comitados". Se você quiser pesquisar determinados dados em algum ponto no passado, você precisará utilizar o recurso de Flashback Query na qual será necessário especificar um "horário" ou um SCN (System change Number) para efetuar a pesquisa.

Este recurso também é muito útil, quando você precisa restaurar dados que foram erroneamente deletados ou alterados. Antes da versão Oracle 9i, você tinha que recuperar o banco de dados até um determinado ponto que lhe interessasse. Dependendo do tamanho do banco de dados, este processo poderia ser lento e demorado.

Antes de mais nada, para você poder usar o recurso de Flashback Query, é necessário configurar o seu banco de dados para usar o gerenciamento automático de UNDO (Automatic Undo Management).

Portando, verifique se o seu banco de dados já está com esta configuração setada, caso contrário, altere o parâmetro com o valor e privilégios apropriados.

SYSTEM> show parameter undo_management

NAME                       TYPE        VALUE
-------------------------- ----------- ------------------------------
undo_management            string      AUTO


Depois, verifique o parâmetro undo_retention, na qual especifica quanto tempo os blocos de dados Oracle alterados ficarão disponíveis no segmento de undo até serem sobregravados, e certifique-se que o tablespace de UNDO é grande o suficiente para que alterações realizadas no banco de dados geradas durante o período não sejam sobrescritas.

SYSTEM@teste> show parameter undo_retention

NAME                       TYPE        VALUE
-------------------------- ----------- ------------------------------
undo_retention             integer     10800


No parâmetro acima, o valor é especificado (em segundos) e no meu caso eu coloquei o valor 10800 que significa 180 minutos ou 3 horas. O valor padrão para este parâmetro é 900 o que significa 15 minutos de retenção de dados de undo.


Criarei um usuário no banco de dados para exemplificar o uso do recurso de Flashback Query no Oracle 9i.

C:\>sqlplus system/*****

SQL*Plus:  Release 10.1.0.2.0 - Production on Ter Nov 7 11:38:35 2006

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

Conectado  a:
Oracle9i  Enterprise Edition Release 9.2.0.4.0 - Production
With the  Partitioning, OLAP and Oracle Data Mining options
JServer  Release 9.2.0.4.0 - Production

SYSTEM> create user legatti identified by legatti
      2 default tablespace USERS
      3 quota unlimited on USERS; 

Usuário criado.

SYSTEM> grant connect to legatti;

Concessão bem-sucedida.
 
Agora, darei o privilégio de EXECUTE no pacote dbms_flashback para o usuário que realizará o flashback.

-- Conexão realizada como sys (sysdba)

SYSTEM> connect / as sysdba

Conectado.

SYS> grant execute on dbms_flashback to legatti;

Concessão bem-sucedida.

-- Conectarei com o usuário criado anteriormente e criarei uma tabela de exemplo

SYS> connect legatti/legatti

Conectado.

LEGATTI> create table produto (
       2 cod  number primary key,
       3 data date,
       4 descricao varchar2 (100));

Tabela criada.

-- Inserir dados para teste

LEGATTI> INSERT INTO produto VALUES (101,SYSDATE,'Computador');

1 linha criada.

LEGATTI> INSERT INTO produto VALUES (102,SYSDATE,'Laptop');

1 linha criada.

LEGATTI> INSERT INTO produto VALUES (103,SYSDATE,'Impressora');

1 linha criada.

LEGATTI> INSERT INTO produto VALUES (104,SYSDATE,'Monitor');

1 linha  criada.

LEGATTI> INSERT INTO produto VALUES (105,SYSDATE,'Mouse');

1 linha criada.

-- Commit das alterações

LEGATTI> commit;

Validação completa.

-- Irei selecionar os dados da tabela

LEGATTI> select cod, to_char(data,'dd/mm/yyyy hh24:mi:ss') data,
       2 descricao from produto;

  COD DATA                DESCRICAO
----- ------------------- -------------------------
  101 07/08/2006 10:41:15 Computador
  102 07/08/2006 10:41:15 Laptop
  103 07/08/2006 10:41:15 Impressora
  104 07/08/2006 10:41:15 Monitor
  105 07/08/2006 10:41:15 Mouse

5 linhas selecionadas.

-- Criarei uma nova linha na tabela

LEGATTI> INSERT INTO produto VALUES (106,SYSDATE,'Teclado');

1 linha criada.

-- Commit das alterações

LEGATTI> commit;

Validação completa.

-- Irei selecionar os dados da tabela

LEGATTI> select cod, to_char(data,'dd/mm/yyyy hh24:mi:ss') data,
       2 descricao from produto;

  COD DATA                DESCRICAO
----- ------------------- -------------------------
  101 07/08/2006 10:41:15 Computador
  102 07/08/2006 10:41:15 Laptop
  103 07/08/2006 10:41:15 Impressora
  104 07/08/2006 10:41:15 Monitor
  105 07/08/2006 10:41:15 Mouse
  106 07/08/2006 10:52:06 Teclado

6 linhas selecionadas.
 
Vou dizer ao Oracle que quero ver apenas os registros anteriores ao último registro, que no caso foi o produto de código 106.

LEGATTI> EXECUTE DBMS_FLASHBACK.ENABLE_AT_TIME
      2 (TO_TIMESTAMP('07/08/2006  10:52:06','DD/MM/YYYY:HH24:MI:SS'));

Procedimento PL/SQL concluído com sucesso.

-- Irei selecionar os dados da tabela

LEGATTI> select * from produto;

  COD DATA       DESCRICAO
----- ---------- --------------------------
  101 07/08/2006 Computador
  102 07/08/2006 Laptop
  103 07/08/2006 Impressora
  104 07/08/2006 Monitor
  105 07/08/2006 Mouse

5 linhas selecionadas.
 
Neste momento, percebemos que o produto teclado não foi selecionado, pelo fato de o mesmo ter sido inserido após às 10:52:05. Abaixo irei desabilitar o recurso de FLASHBACK.

LEGATTI> EXECUTE DBMS_FLASHBACK.DISABLE;

Procedimento PL/SQL concluído com sucesso.

-- Irei selecionar os dados da tabela

LEGATTI> select * from produto;

  COD DATA       DESCRICAO
----- ---------- -------------------------
  101 07/08/2006 Computador
  102 07/08/2006 Laptop
  103 07/08/2006 Impressora
  104 07/08/2006 Monitor
  105 07/08/2006 Mouse
  106 07/08/2006 Teclado

6 linhas selecionadas. 
 
Vale a pena salientar que poderemos usar também o recurso "AS OF" que é uma forma mais simplificada.

LEGATTI> SELECT * FROM produto
       2 AS OF TIMESTAMP TO_TIMESTAMP('07/08/2006 10:52:06','DD/MM/YYYY:HH24:MI:SS'));

  COD DATA       DESCRICAO
----- ---------- --------------------------
  101 07/08/2006 Computador
  102 07/08/2006 Laptop
  103 07/08/2006 Impressora
  104 07/08/2006 Monitor
  105 07/08/2006 Mouse

6 linhas selecionadas.