Flashback

Nesse post iremos começar a ver um pouco sobre FLASHBACK, veremos um pouco mais do que o necessário para o exame, mas que é fundamental para um bom entendimento. Mais pra frente farei outro tópico sobre FLASHBACK. Podemos fazer várias operações conforme listadas abaixo:

  • Recuperar tabelas que sofreram um DROP
  • Recuperar dados em tabelas que foram alterados por DML
  • Analisas dados que foram mudando com o tempo
  • Comparar dados em uma tabela em um ponto do tempo com outro período
  • Fazer querys em uma tabela como ela era em um determinado ponto do tempo

São realmente operações bem poderosas, poder recuperar tabelas que foram excluídas, ou vários usuários acessando a mesma tabela mas em pontos diferentes do histórico dela. Tudo isso é o que o Oracle pode fazer, como o melhor bando de dados do mundo! Primeiro, vejamos a operação que vamos nos focar aqui.

Recovering Dropped Tables

Podemos recuperar uma tabela que sofreu um drop em um determinado ponto no tempo. Mas nem sempre isso é possível, um exemplo disso seria tentar recuperar a tabela antes de uma determinada mudança na estrutura da tabela.

Podemos especificar o ponto no tempo para a recuperação de diversas maneiras.

  • Imediatamente antes do DROP
  • Uma data especificada por um TIMESTAMP
  • SCN, System Change Number
  • Restore Point

Podemos manter o mesmo nome da tabela ou renomear ela. Todas as constraints, índices, grants serão recuperados também, menos as constraints referenciais, ou seja, FK. A sintaxe é bem simples e fácil, conforme poderá verificar abaixo.

FLASHBACK TABLE tabela1[, mais_tabelas] TO … (BEFORE DROP
[RENAME TO novo_nome] | TIMESTAMP … | SCN …) ;

Bem simples, podem fazer um teste, em ambientes de teste claro! Façam um DROP em uma determinada tabela e depois executem um flashback, vejam um exemplo abaixo:

DROP TABLE exemplo;
FLASHBACK TABELA exemplo TO BEFORE DROP;
SELECT * FROM exemplo;

O código irá executar sem erros e conseguiremos ver tudo o que a tabela exemplo tinha perfeitamente antes do DROP.

Recicly Bin

Sempre que emitimos um DROP contra qualquer tabela, ela será colocada automaticamente no Recibly Bin, ou seja, na lixeira. Então, se a tabela ainda estiver na lixeira, podemos recuperar ela através de um FLASHBACK. Todos os objetos que estiverem dentro da lixeira não são contados como espaço usado de um determinado usuário. Podemos verificar tudo que tem nela do seguinte modo:

SELECT * FROM USER_RECICLYBIN;
OU
SELECT * FROM RECICLYBIN;

RECICLYBIN é um synonym de USER_RECICLYBIN. Com isto poderemos ver os objetos do usuário da seção atual que estão na lixeira. Existe também a DBA_RECICLYBIN onde poderemos ver os objetos de todos os usuários, mas para isto deveremos ter o privilégio neste objeto. Podemos desligar o ligar a RECICLY BIN pelo parâmetro mostrado a seguir:

ALTER SESSION SET reciclybin = (ON | OFF);

Purge

Para remover os objetos da lixeira, podemos utilizar o comando PURGE. Por exemplo, se dermos um DROP em uma tabela chamada PESSOAL, essa tabela irá para a lixeira. Para remover da lixeira seria o seguinte comando:

PURGE TABLE pessoal;

É bom estar bem atento que o PURGE poderá ocorrer de forma automática pelo Oracle por problemas de espaço, caso isso aconteça não será possível recuperar os itens via FLASHBACK.

Recovering Tables in Time

Mais acima, vimos como recuperar a tabela logo antes do DROP dela. Vejamos agora como recuperar ela em um determinado ponto do tempo. Podemos fazer de três maneiras. A primeira seria informando uma data válida por intermédio de um TIMESTAMP. A segunda através de um RESTORE POINT, um ponto que salvamos em um determinado tempo. E a terceira e última seria través do SCN, que é a recomendação do Oracle.

Veja um exemplo com TIMESTAMP:

CREATE TABLE exemplo (coluna NUMBER);
INSERT INTO exemplo(coluna) VALUES(1);
COMMIT;
EXECUTE DBMS_LOCK.SLEEP(15);
DELETE FROM exemplo;
COMMIT;
EXECUTE DBMS_LOCK.SLEEP(15);
FLASHBACK TABLE exemplo TO TIMESTAMP SYSTIMESTAMP – INTERVAL ‘0 00:00:20’ DAY TO SECOND;

Acabamos de criar uma tabela exemplo e inserimos uma linha. Após o COMMIT fizemos uma pausa de 15 segundos e logo depois apagamos todas as linhas da tabela. Depois do COMMIT fizemos novamente a mesma pausa. E depois disso executamos um FLASHBACK com um TIMESTAMP da hora atual com 20 segundos atrás, ou seja, entre as duas pausas de 15 segundos. O efeito final foi que a nossa tabela tem novamente a mesma única linha que tinha anteriormente.

Talvez o resultado não seja esse, e no momento da execução do código acima seja lançado um erro. Pois essa habilidade de restaurar a tabela para um estado anterior não é ativado por padrão no Oracle. Para ativar é bem simples como podem verificar abaixo:

CREATE TABLE exemplo (coluna NUMBER) ENABLE ROW MOVEMENT;

ou

ALTER TABLE exemplo ENABLE ROW MOVEMENT;

SCN

System Change Number é um número que é incrementado pelo banco de dados a cada COMMIT que ocorre. Então cada transação com commit é atribuída a um SCN. Se quisermos saber o SCN atual é só fazer igual a query abaixo:

SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER FROM dual;

Toda vez que uma transação sofre um commit, o SCN é incrementado e salvo em cada linha de todas as tabelas. Podemos verificar isso fazendo uma query em qualquer tabela e selecionando a coluna ORA_ROWSCN.

Funções de Conversão

Podemos converter um TIMESTAMP para um SCN e um SCN para um TIMESTAMP. Lembrando que essa conversão não é exata, apenas aproximada. As funções são as seguintes:

SCN_TO_TIMESTAMP(scn);
TIMESTAMP_TO_SCN(timestamp);

Restore Point

O último assunto desse post é sobre RESTORE POINT, que é um objeto no banco de dados que representa um certo momento no tempo. Por exemplo, podemos criar um restore point como ilustrado abaixo:

CREATE RESTORE POINT rp_exemplo;

Depois podemos usá-lo como a seguir:

FLASHBACK TABLE exemplo TO RESTORE POINT rp_exemplo;

Assim a tabela exemplo irá retornar a ser como era no momento da criação do RESTORE POINT rp_exemplo. Se não quisermos mais esse restore point podemos excluir da seguinte maneira:

DROP RESTORE POINT rp_exemplo;

4 comentários sobre “Flashback

  1. Renan A. Chaparro

    Olá Tércio,
    estou estudando para o OCA e logo vou agendar minha prova.
    te adicionei hoje no linkedIn

    só um detalhe:
    CREATE TABLE exemplo (coluna NUMBER) ENABLE ROW MOVIMENT;

    troca aí o moviment por movEment
    é pq tentei executar e não tava indo daí pesquisei como era a sintaxe.

    parabéns pelo Blog, show de bola! tem me ajudado muito.
    flw abraço.

    Curtir

  2. Renan A. Chaparro

    Só o BEFORE DROP tem [RENAME TO] como opcional.
    fonte:
    https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9012.htm#SQLRF01802

    outra coisa, não entendi bem o porquê do EXECUTE DBMS_LOCK.SLEEP(15);
    não consegui executar ele, eu to usando o livesql.oracle.com pra fazer os testes e parece que tem que ter algum GRANT execute pra ele funcionar.
    Mas eu consegui usar o FLASHBACK com TIMESTAMP pra recuperar dados deletados da tabela sem precisar do execute dbms_lock.sleep().

    Curtir

Deixar mensagem para Tércio Costa Cancelar resposta

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.