Database Point-In-Time Recovery (DBPITR) e Tablespace Point-in-Time Recovery (TSPITR) na prática com o RMAN

Por Eduardo Legatti
Postado em Junho 2014

Neste artigo irei abordar um pouco da técnica de recuperação pontual de dados já bem conhecida entre os DBAs Oracle chamada de Tablespace Point-in-Time Recovery (TSPITR) disponível desde a versão do Oracle 8e também uma outra técnica chamada Database Point-in-Time Recovery (DBPITR).
Basicamente o TSPITR (Recuperação Pontual de Tablespace) é uma funcionalidade que fornece ao DBA a opção de recuperar um conjunto de dados em um ponto específico no tempo sem afetar o restante do banco de dados. Por isso a importância de separar aplicações distintas em tablespaces separados, no qual acredito ser uma boa prática. Em um primeiro momento esta técnica é útil para recuperar dados que foram erroneamente afetados por alguma operação DML ou até mesmo DDL (insert, delete, update, drop, truncate, etc...). A vantagem de utilizar esta técnica é a possibilidade que o DBA tem de "voltar no tempo" os dados de uma determinada aplicação deixando outras aplicações e o restante do banco de dados intacto, ou seja, "no tempo atual" e acessível aos usuários.
Já o DBPITR possibilita um banco de dados inteiro "voltar no tempo" da mesma forma que o recurso Flashback Database (10g) possibilita. A diferença é que este último possibilita uma operação muito mais prática e significativamente mais rápida, conforme estudo realizado e apresentado no fim deste artigo. Portanto, é necessário que o DBA saiba analisar cuidadosamente o impacto desta ação no banco de dados ao escolher cada uma das duas técnicas (DBPITR vs TSPITR) para que, assim, o mesmo possa decidir qual e quando usar uma ou outra abordagem.
Os conceitos por trás do TSPITR requer alguns conhecimentos como Incomplete Recovery, TTS (TransportTablespaces), DBPITR, banco de dados auxiliar, que, se realizado manualmente, com certeza daria muito mais trabalho. Felizmente, o utilitário RMAN (Recovery Manager) consegue automatizar toda esta tarefa com apenas alguns comandos.
No mais, neste artigo irei simular através do RMAN uma operação de DBPITR e outra de TSPITR de forma a demonstrar o conceito por trás de cada abordagem. Ao final, poderemos verificar a vantagem do uso de ambas as técnicas.
Para realizar a simulação, utilizarei o Oracle 11g R2 instalado e configurado em uma máquina virtual usando o sistema operacional Linux - Centos 5.2 como poderemos ver logo abaixo:

[oracle@linux1 ~]$ sqlplus / as sysdba
 
SQL*Plus: Release 11.2.0.1.0 Production on Sex Mar 5 14:44:22 2010
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
 
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
 
SQL> select * from v$version;
 
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

Vale a pena salientar que é de fundamental importância que o banco de dados esteja operando no modo de arquivamento (ARCHIVELOG) e que os backups físicos do mesmo estejam consistentes e disponíveis para uso.

-- Verificando o modo de operação do banco de dados
SQL>archive log list
 
Modo log de banco de dados     Modo de Arquivamento
Arquivamento automático        Ativado
Destino de arquivamento        USE_DB_RECOVERY_FILE_DEST
A sequência de log on-line mais antiga     60
Próxima sequência de log a arquivar   62
Sequência de log atual           62

 

Irei criar abaixo dois tablespaces de forma a simular duas aplicações distintas em uso no banco de dados. Irei supor que o tablespace TBS_01 possui objetos (segmentos) referente aos dados de uma aplicação de Recursos Humanos, e que o tablespace TBS_02 possui objetos (segmentos) referente aos dados de uma aplicação de Vendas.

SQL> create tablespace tbs_01 datafile '/u01/app/oracle/oradata/BD01/tbs01.dbf' size 5m;
 
Tablespacecriado.
 
SQL> create tablespace tbs_02 datafile '/u01/app/oracle/oradata/BD01/tbs02.dbf' size 5m;
 
Tablespace criado.
 
 

Agora irei criar dois usuários de banco de dados, cada um associado ao seu tablespace, de forma a simular as aplicações distintas em uso no banco de dados. Irei supor que o usuário USUARIO_01 associado ao tablespace TBS_01, possui objetos referentes aos dados da aplicação de Recursos Humanos, e que o usuário USUARIO_02 associado ao tablespace TBS_02 possui objetos referente aos dados de uma aplicação de Vendas.

SQL> create user usuario_01 identified by senha default tablespace tbs_01;
 
Usuáriocriado.
 
SQL> create user usuario_02 identified by senha default tablespace tbs_02;
 
Usuáriocriado.
 
SQL> grant connect,resource to usuario_01,usuario_02;
 
Concessão bem-sucedida.
 
 

Por fim, irei criar uma tabela em cada usuário e popular as mesmas com 10 registros cada uma como demonstrado abaixo:

SQL> create table usuario_01.tabela_01 (id number);
 
Tabelacriada.
 
SQL> insert into usuario_01.tabela_01 select rownum id from dual connect by level <=10;
 
10 linhas criadas.
 
SQL>createtable usuario_02.tabela_02 (id number);
 
Tabela criada.
 
SQL> insert into usuario_02.tabela_02 select rownum id from dual connect by level <=10;
 
10 linhas criadas.
 
SQL>commit;
 
Commit concluído. 

 

Ao final da execução dos procedimentos acima podemos visualizar abaixo o esquema do banco de dados gerado, supondo que o usuário USUARIO_01 é o proprietário da tabela do sistema de Recursos Humanos e o usuário USUARIO_02 o proprietário da tabela do sistema de Vendas:

SQL> select owner,table_name,tablespace_name
  2  from dba_tables
  3  where owner in ('USUARIO_01','USUARIO_02');
 
OWNER                        TABLE_NAME                   TABLESPACE_NAME
---------------------------- ---------------------------- ----------------------------
USUARIO_01                   TABELA_01                    TBS_01
USUARIO_02                   TABELA_02                    TBS_02
 
SQL>exit
Desconectado de Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

Como parte da demonstração da simulação, irei realizar um backup do banco de dados utilizando o RMAN.

[oracle@linux1 ~]$ rman target /
 
Gerenciador de Recuperação: Release 11.2.0.1.0 - Production on Sex Mar 5 15:02:15 2010
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  Allrightsreserved.
 
conectado ao banco de dados de destino: BD01 (DBID=2967836454)
 
RMAN>backup database;
 
Iniciando backup em 05/03/2010
usar o arquivo de controle do banco de dados de destino em vez do catálogo de recuperação
canal alocado: ORA_DISK_1
canal ORA_DISK_1: SID=16 tipo de dispositivo=DISK
canal ORA_DISK_1: iniciando conjunto de backup completo de arquivo de dados
canal ORA_DISK_1: especificando arquivo[s] de dados no conjunto de backups
número do arquivo=00001 nome=/u01/app/oracle/oradata/BD01/system01.db
número do arquivo=00003 nome=/u01/app/oracle/oradata/BD01/sysaux01.dbf
número do arquivo=00002 nome=/u01/app/oracle/oradata/BD01/undotbs01.dbf
número do arquivo=00004 nome=/u01/app/oracle/oradata/BD01/users01.dbf
número do arquivo=00005 nome=/u01/app/oracle/oradata/BD01/tbs01.dbf
número do arquivo=00006 nome=/u01/app/oracle/oradata/BD01/tbs02.dbf
canal ORA_DISK_1: iniciando o componente 1 em 05/03/2010
canal ORA_DISK_1: componente 1 finalizado em 05/03/2010
handle de componente=/u01/app/oracle/flash_recovery_area/BD01/backupset/2010_03_05/
o1_mf_nnndf_TAG20100305T150232_5q8g1cv5_.bkp tag=TAG20100305T150232 comentário=NONE
canal ORA_DISK_1: conjunto de backups concluído, tempo decorrido: 00:01:57
canal ORA_DISK_1: iniciando conjunto de backup completo de arquivo de dados
canal ORA_DISK_1: especificando arquivo[s] de dados no conjunto de backups
incluindo arquivo de controle atual no conjunto de backups
incluindo SPFILE atual do conjunto de backups
canal ORA_DISK_1: iniciando o componente 1 em 05/03/2010
canal ORA_DISK_1: componente 1 finalizado em 05/03/2010
handle de componente=/u01/app/oracle/flash_recovery_area/BD01/backupset/2010_03_05/
o1_mf_ncsnf_TAG20100305T150232_5q8g52yc_.bkp tag=TAG20100305T150232 comentário=NONE
canal ORA_DISK_1: conjunto de backups concluído, tempo decorrido: 00:00:01
Finalizado backup em 05/03/2010
 
RMAN>exit
 
Recovery Manager completo. 

Após a realização do backup físico do banco de dados, irei simular um erro ocasionado por um comando DDL emitido no schema de banco de dados do sistema de Recursos Humanos (USUARIO_01), onde inadvertidamente a tabela TABELA_01 foi dropada utilizando a cláusula PURGE, ou seja, sem chance de a mesma ser recuperada da lixeira (recyclebin).

[oracle@linux1 ~]$ sqlplus usuario_01/senha
 
SQL*Plus: Release 11.2.0.1.0 Production on Sex Mar 5 15:21:13 2010
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
 
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
 
SQL> select * from tabela_01;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.
 
SQL>selectsystimestampfrom dual;
 
SYSTIMESTAMP
-------------------------------
05/03/10 15:21:45,423501 -03:00
 
SQL>droptable tabela_01 purge;
 
Tabela eliminada.

 

Apenas para fins didáticos, antes de ter dropado a tabela TABELA_01 (do sistema de Recursos Humanos), eu consultei a data e hora atual para sinalizar um momento no tempo em que a tabela existia. Este horário será útil logo mais a frente. Agora irei simular abaixo uma atualização na tabela TABELA_02 (do sistema de Vendas).

SQL>connect usuario_02/senha;
Conectado.
 
SQL> select * from tabela_02;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.
 
SQL>update tabela_02 set id=id*100;
 
10 linhas atualizadas.
 
SQL>commit;
 
Commit concluído.
 
SQL> select * from tabela_02;
 
        ID
----------
       100
       200
       300
       400
       500
       600
       700
       800
       900
      1000
 
10 linhas selecionadas.
 
SQL>selectsystimestampfrom dual;
 
SYSTIMESTAMP
-------------------------------
05/03/10 15:25:31,423501 -03:00

 

Pronto. O cenário está montado. Uma tabela importante do sistema de Recursos Humanos foi dropada acidentalmente e uma operação importante foi realizada na tabela do sistema de Vendas. Note que todas as linhas da tabela TABELA_02 do sistema de Vendas foram atualizadas tendo o valor da coluna ID multiplicada por 100.

Se eu utilizar a técnica DBPITR para restaurar a tabela TABELA_01 do usuário USUARIO_01 (sistema Recursos Humanos), vejamos o que acontece.

Após realizar o shutdown do banco de dados, irei realizar uma conexão através do RMAN, montar o banco de dados e iniciar o processo de DBPITR conforme demonstração abaixo:

Database Point-In-Time Recovery (DBPITR)

[oracle@linux1 ~]$ export NLS_DATE_FORMAT='dd/mm/yyyy hh24:mi:ss'
[oracle@linux1 ~]$ rman target /
 
Gerenciador de Recuperação: Release 11.2.0.1.0 - Production on Sex Mar 5 16:51:43 2010
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  Allrightsreserved.
 
conectado ao banco de dados de destino (não iniciado)
 
RMAN>startup mount
 
instância Oracle iniciada
banco de dados montado
 
Total da Área Global do Sistema     133906432 bytes
 
Fixed Size                     1335024 bytes
Variable Size                113246480 bytes
Database Buffers              16777216 bytes
Redo Buffers                   2547712 bytes

 

Sabendo-se que a tabela TABELA_01 não fora dropada antes das 05/03/2010 15:21:45, utilizarei este horário para "voltar o banco neste tempo". O processo de DBPITR se resume aos comandos a seguir:

 

RMAN> run {set until time '05/03/2010 15:21:45'; 
2>restoredatabase;
3>recoverdatabase;
4>alterdatabase open resetlogs;}
 
executando comando: SET untilclause
 
Iniciando restore em 05/03/2010 16:52:41
usar o arquivo de controle do banco de dados de destino em vez do catálogo de recuperação
canal alocado: ORA_DISK_1
canal ORA_DISK_1: SID=18 tipo de dispositivo=DISK
 
canal ORA_DISK_1: iniciando restauração de conjunto de backups de arquivo de dados
canal ORA_DISK_1: especificando arquivo(s) de dados para restauração a partir do conjunto
                  de backups
canal ORA_DISK_1: restaurando o arquivo de dados 00001 em /u01/app/oracle/oradata/BD01/
                  system01.dbf
canal ORA_DISK_1: restaurando o arquivo de dados 00002 em /u01/app/oracle/oradata/BD01/
                  undotbs01.dbf
canal ORA_DISK_1: restaurando o arquivo de dados 00003 em /u01/app/oracle/oradata/BD01/
                  sysaux01.dbf
canal ORA_DISK_1: restaurando o arquivo de dados 00004 em /u01/app/oracle/oradata/BD01/
                  users01.dbf
canal ORA_DISK_1: restaurando o arquivo de dados 00005 em /u01/app/oracle/oradata/BD01/
                  tbs01.dbf
canal ORA_DISK_1: restaurando o arquivo de dados 00006 em /u01/app/oracle/oradata/BD01/
tbs02.dbf
canal ORA_DISK_1: lendo da parte de backup /u01/app/oracle/flash_recovery_area/BD01/
                  backupset/2010_03_05/o1_mf_nnndf_TAG20100305T150232_5q8g1cv5_.bkp
canal ORA_DISK_1: handle de componente=/u01/app/oracle/flash_recovery_area/BD01/
                  backupset/2010_03_05/o1_mf_nnndf_TAG20100305T150232_5q8g1cv5_.bkp
tag=TAG20100305T150232
canal ORA_DISK_1: restaurada a parte de backup 1
canal ORA_DISK_1: restauração concluída, tempo decorrido: 00:02:17
Finalizado restore em 05/03/2010 16:55:01
 
Iniciando recover em 05/03/2010 16:55:01
utilizando o canal ORA_DISK_1
 
iniciar recuperação de mídia
recuperação da mídia concluída, tempo decorrido: 00:00:15
 
Finalizado recover em 05/03/2010 16:55:19
 
banco de dados aberto
 
RMAN>exit
 
Recovery Manager completo.

Após finalizado o processo de recuperação, irei conectar com o usuário USUARIO_01 para verificar se a tabela TABELA_01 foi restaurada.

[oracle@linux1 ~]$ sqlplus usuario_01/senha
 
SQL*Plus: Release 11.2.0.1.0 Production on Sex Mar 5 17:01:07 2010
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
 
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
 
SQL> select * from tabela_01;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.

 

Perfeito. A tabela foi restaurada exatamente como estava às 05/03/2010 15:21:45. Mas, e quanto aos dados da tabela TABELA_02 do sistema de Vendas? Vejamos abaixo:

SQL>connect usuario_02/senha
Conectado.
 
SQL>select * from tabela_02;
 
        ID
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.

 

Hum... podemos perceber que a atualização realizada na tabela TABELA_02 às 05/03/2010 15:25:31 onde multiplicamos o valor da coluna ID por 100 foi perdida. Isto aconteceu porque o processo de recuperação restaurou e recuperou os dados até às 05/03/2010 15:21:45 como solicitado e, neste horário, os dados da tabela TABELA_02 não tinham ainda sido atualizados. Em resumo, realizar o DBPITR não seria a melhor solução para este cenário pois a solução de um problema ocasionou o aparecimento de outro problema, ou seja, os usuários do sistema de Recursos Humanos ficariam super satisfeitos, enquanto os usuários do sistema de Vendas ficariam totalmente insatisfeitos, inclusive exigindo mil e uma explicações sobre o que teria provocado a perda de informações no sistema e o porquê. Daí a importância de o DBA saber analisar cuidadosamente o impacto de qualquer opção de recuperação antes de qualquer coisa.

Bom, este foi o cenário onde realizei o DBPITR. E quanto ao TSPITR? Esta técnica será demonstrada abaixo onde o cenário é igual ao que foi demonstrado acima. Após a realização do backup físico do banco de dados, novamente irei realizar as mesmas operações nas tabelas envolvidas nos dois sistemas, ou seja, irei dropar a tabela TABELA_01 de propriedade do usuário USUARIO_01 (sistema de Recursos Humanos) e realizar a alteração na tabela TABELA_02 (sistema de Venda) com o comando UPDATE que realiza a multiplicação do valor da coluna ID por 100.


Tablespace Point-in-Time Recovery (TSPITR)

SQL>connect usuario_01/senha
Conectado.
 
SQL> select * from tabela_01;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.
 
SQL>selectsystimestampfrom dual;
 
SYSTIMESTAMP
-------------------------------
06/03/10 10:26:34,707082 -03:00
 
SQL>droptable tabela_01 purge;
 
Tabela eliminada.
 
 
SQL>connect usuario_02/senha;
Conectado.
 
SQL> select * from tabela_02;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.
 
SQL>update tabela_02 set id=id*100;
 
10 linhas atualizadas.
 
SQL>commit;
 
Commit concluído.
 
SQL> select * from tabela_02;
 
        ID
----------
       100
       200
       300
       400
       500
       600
       700
       800
       900
      1000
 
10 linhas selecionadas.
 
SQL>selectsystimestampfrom dual;
 
SYSTIMESTAMP
-------------------------------
06/03/10 10:30:43,707082 -03:00
 
 

Bom, sabemos que a tabela TABELA_01 foi dropada às 06/03/2010 10:26:34, enquanto os dados da tabela TABELA_02 foi atualizada às 06/03/2010 10:30:43. O objetivo então será restaurar a tabela TABELA_01 de propriedade do usuário USUARIO_01 e pertencente ao tablespace TBS_01, sem afetar o resto do banco de dados, ou seja, sem afetar os dados do sistema de Vendas de propriedade do usuário USUARIO_02 no tablespace TBS_02.

Para que o processo de recuperação utilizando a técnica TSPITR seja possível, será necessário criar um diretório de sistema operacional que será utilizado para a realização do processo de recuperação.

[oracle@linux1 /]$ mkdir /u01/aux_dest

 

No caso do TSPITR, o banco de dados precisa estar aberto (no estado OPEN). Apenas para fins de demonstração, se eu tentar realizar o TSPITR (Recuperação Pontual de Tablespace) com o banco de dados montado, a mensagem abaixo será emitida:

[oracle@linux1 u01]$ rman target /
 
Gerenciador de Recuperação: Release 11.2.0.1.0 - Productionon Sab Mar 6 10:28:27 2010
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  Allrightsreserved.
 
conectado ao banco de dados de destino: BD01 (DBID=2967836454, não aberto)
 
RMAN> recover tablespace tbs_01 
2> until time "to_date('06/03/2010 10:26:34','dd/mm/yyyy hh24:mi:ss')" 
3> auxiliary destination '/u01/aux_dest'; 
 
Iniciando recover em 06/03/2010 10:28:52
usar o arquivo de controle do banco de dados de destino em vez do catálogo de recuperação
canal alocado: ORA_DISK_1
canal ORA_DISK_1: SID=18 tipo de dispositivo=DISK
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: falha do comando recover em 06/03/2010 10:28:54
RMAN-05010: banco de dados de destino deve ser aberto no modo READ WRITE para Recuperação
            Pontual de Tablespace

 

Com o banco de dados aberto, irei realizar uma conexão através do RMAN, e iniciar o processo de TSPITRconforme demonstração abaixo:

[oracle@linux1 /]$ rman target /
 
Gerenciador de Recuperação: Release 11.2.0.1.0 - Production on Sab Mar 6 10:28:27 2010
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  Allrightsreserved.
 
conectado ao banco de dados de destino: BD01 (DBID=2967836454)
 
RMAN> recover tablespace tbs_01 
2> until time "to_date('06/03/2010 10:26:34','dd/mm/yyyy hh24:mi:ss')" 
3> auxiliary destination '/u01/aux_dest'; 

 

Após a execução do comando acima, o RMAN fará todo o trabalho de recuperação pontual do tablespace TBS_01 sem qualquer intervenção minha. Portanto, abaixo todos os comandos são executados e emitidos pelo RMAN:

Iniciando recover em 06/03/2010 10:28:52
usar o arquivo de controle do banco de dados de destino em vez do catálogo de recuperação
canal alocado: ORA_DISK_1
canal ORA_DISK_1: SID=30 tipo de dispositivo=DISK
RMAN-05026: ADVERTÊNCIA: pressupõe-se que o conjunto de tablespaces a seguir se aplica a
                         um ponto específico no tempo
 
Espera-se que a lista de tablespaces tenha segmentos UNDO
Tablespace SYSTEM
Tablespace UNDOTBS1
 
Criando uma instância automática, com SID='alhg'
 
parâmetros de inicialização usados para instância automática:
db_name=BD01 
db_unique_name=alhg_tspitr_BD01 
compatible=10.2.0.1.0 
db_block_size=8192 
db_files=200 
sga_target=280M 
processes=50 
db_create_file_dest=/u01/aux_dest 
log_archive_dest_1='location=/u01/aux_dest' 
#No auxiliaryparameter file used
 
 
inicializando instância automática BD01
 
instância Oracle iniciada
 
Total da Área Global do Sistema     292933632 bytes
 
Fixed Size                     1336092 bytes 
Variable Size                100666596 bytes 
Database Buffers             184549376 bytes 
Redo Buffers                   6381568 bytes 
Instância automática criada
Executando TRANSPORT_SET_CHECK nos tablespaces do conjunto de recuperação
TRANSPORT_SET_CHECK concluído com sucesso
 
conteúdo do Script de Memória:
{ 
# set requested point in time 
set until  time "to_date('06/03/2010 10:26:34','dd/mm/yyyy hh24:mi:ss')"; 
# restore the controlfile 
restore clone controlfile; 
# mount the controlfile 
sql clone 'alter database mount clone database'; 
# archive current online log 
sql 'alter system archive log current'; 
# avoid unnecessary autobackups for structural changes during TSPITR 
sql 'begin dbms_backup_restore.AutoBackupFlag(FALSE); end;'; 
}
executando Script de Memória
 
executando comando: SET untilclause
 
Iniciando restore em 06/03/2010 10:29:47
canal alocado: ORA_AUX_DISK_1
canal ORA_AUX_DISK_1: SID=19 tipo de dispositivo=DISK
 
canal ORA_AUX_DISK_1: iniciando restauração de conjunto de backups de arquivo de dados
canal ORA_AUX_DISK_1: restaurando arquivo de controle
canal ORA_AUX_DISK_1: lendo da parte de backup /u01/app/oracle/flash_recovery_area/BD01/
autobackup/2010_03_06/o1_mf_s_710763266_5qbkk4m7_.bkp
canal ORA_AUX_DISK_1: handle de componente=/u01/app/oracle/flash_recovery_area/ 
                      BD01/autobackup/2010_03_06/o1_mf_s_710763266_5qbkk4m7_.bkp 
tag=TAG20100306T101426
canal ORA_AUX_DISK_1: restaurada a parte de backup 1
canal ORA_AUX_DISK_1: restauração concluída, tempo decorrido: 00:00:04
nome do arquivo de saída=/u01/aux_dest/BD01/controlfile/o1_mf_5qblg0ld_.ctl
Finalizado restore em 06/03/2010 10:29:55
 
instrução sql: alterdatabasemount clone database
 
instruçãosql: alter system archive log current 
 
instruçãosql: begin dbms_backup_restore.AutoBackupFlag(FALSE); end; 
 
conteúdo do Script de Memória:
{ 
# set requested point in time 
set until  time "to_date('06/03/2010 10:26:34','dd/mm/yyyy hh24:mi:ss')"; 
plsql<<<-- tspitr_2 
declare 
sqlstatement       varchar2(512); 
offline_not_needed exception; 
  pragma exception_init(offline_not_needed, -01539); 
begin 
sqlstatement := 'alter tablespace '||  'TBS_01' ||' offline immediate'; 
krmicd.writeMsg(6162, sqlstatement); 
krmicd.execSql(sqlstatement); 
exception 
  when offline_not_needed then 
    null; 
end; >>>; 
# set destinations for recovery set and auxiliary set datafiles 
set newname for clone datafile  1 to new; 
set newname for clone datafile  2 to new; 
set newname for clone datafile  3 to new; 
set newname for clone tempfile  1 to new; 
set newname for datafile  5 to 
 "/u01/app/oracle/oradata/BD01/tbs01.dbf"; 
# switch all tempfiles 
switch clone tempfile all; 
# restore the tablespaces in the recovery set and the auxiliary set 
restore clone datafile  1, 2, 3, 5; 
switch clone datafile all; 
}
executando Script de Memória
 
executando comando: SET untilclause
 
instruçãosql: alter tablespace TBS_01 offline immediate 
 
executando comando: SET NEWNAME
 
executando comando: SET NEWNAME
 
executando comando: SET NEWNAME
 
executando comando: SET NEWNAME
 
executando comando: SET NEWNAME
 
arquivo temporário renomeado 1 para /u01/aux_dest/BD01/datafile/o1_mf_temp_%u_.tmp
 
Iniciando restore em 06/03/2010 10:30:13
utilizando o canal ORA_AUX_DISK_1
 
canal ORA_AUX_DISK_1: iniciando restauração de conjunto de backups de arquivo de dados
canal ORA_AUX_DISK_1: especificando arquivo(s) de dados para restauração a partir do
                      conjunto de backups
canal ORA_AUX_DISK_1: restaurando o arquivo de dados 00001 em /u01/aux_dest/BD01/datafile/
                      o1_mf_system_%u_.dbf
canal ORA_AUX_DISK_1: restaurando o arquivo de dados 00002 em /u01/aux_dest/BD01/datafile/
                      o1_mf_undotbs1_%u_.dbf
canal ORA_AUX_DISK_1: restaurando o arquivo de dados 00003 em /u01/aux_dest/BD01/datafile/
                      o1_mf_sysaux_%u_.dbf
canal ORA_AUX_DISK_1: restaurando o arquivo de dados 00005 em /u01/app/oracle/oradata/
                      BD01/tbs01.dbf
canal ORA_AUX_DISK_1: lendo da parte de backup /u01/app/oracle/flash_recovery_area/BD01/
                      backupset/2010_03_06/o1_mf_nnndf_TAG20100306T101155_5qbkdd9g_.bkp
canal ORA_AUX_DISK_1: handle de componente=/u01/app/oracle/flash_recovery_area/BD01/ 
                      backupset/2010_03_06/o1_mf_nnndf_TAG20100306T101155_5qbkdd9g_.bkp 
tag=TAG20100306T101155
canal ORA_AUX_DISK_1: restaurada a parte de backup 1
canal ORA_AUX_DISK_1: restauração concluída, tempo decorrido: 00:01:46
Finalizado restore em 06/03/2010 10:32:00
 
arquivo de dados 1 alternado para a cópia do arquivo de dados
cópia do arquivo de dados de entrada RECID=4 STAMP=710764321 file name=/u01/aux_dest/BD01/
datafile/o1_mf_system_5qblgq4w_.dbf
arquivo de dados 2 alternado para a cópia do arquivo de dados
cópia do arquivo de dados de entrada RECID=5 STAMP=710764321 file name=/u01/aux_dest/BD01/
datafile/o1_mf_undotbs1_5qblgq6p_.dbf
arquivo de dados 3 alternado para a cópia do arquivo de dados
cópia do arquivo de dados de entrada RECID=6 STAMP=710764321 file name=/u01/aux_dest/BD01/
datafile/o1_mf_sysaux_5qblgq6d_.dbf
 
conteúdo do Script de Memória:
{ 
# set requested point in time 
set until  time "to_date('06/03/2010 10:26:34','dd/mm/yyyy hh24:mi:ss')"; 
# online the datafiles restored or switched 
sql clone "alter database datafile  1 online"; 
sql clone "alter database datafile  2 online"; 
sql clone "alter database datafile  3 online"; 
sql clone "alter database datafile  5 online"; 
# recover and open resetlogs 
recover clone database tablespace "TBS_01","SYSTEM","UNDOTBS1","SYSAUX" delete archivelog; 
alter clone database open resetlogs; 
} 
executando Script de Memória 
 
executando comando: SET untilclause 
 
instrução sql: alterdatabasedatafile  1 online 
 
instrução sql: alterdatabasedatafile  2 online 
 
instrução sql: alterdatabasedatafile  3 online
 
instrução sql: alterdatabasedatafile  5 online
 
Iniciando recover em 06/03/2010 10:32:02
utilizando o canal ORA_AUX_DISK_1
 
iniciar recuperação de mídia
 
o log arquivado para thread 1 com sequência 63 já está no disco como arquivo /u01/app/
oracle/flash_recovery_area/BD01/archivelog/2010_03_06/o1_mf_1_63_5qblg9mk_.arc 
nome do arquivo de log arquivado=/u01/app/oracle/flash_recovery_area/BD01/archivelog/ 
2010_03_06/o1_mf_1_63_5qblg9mk_.arc thread=1 sequência=63 
recuperação da mídia concluída, tempo decorrido: 00:00:04
Finalizado recover em 06/03/2010 10:32:10
 
banco de dados aberto
 
conteúdo do Script de Memória:
{ 
# make read only the tablespace that will be exported 
sql clone 'alter tablespace  TBS_01 read only'; 
# create directory for datapump import 
sql "create or replace directory TSPITR_DIROBJ_DPDIR as '' 
/u01/aux_dest''"; 
# create directory for datapump export 
sql clone "create or replace directory TSPITR_DIROBJ_DPDIR as '' 
/u01/aux_dest''";
}
executando Script de Memória
 
instruçãosql: alter tablespace  TBS_01 read only 
 
instruçãosql: create or replace directory TSPITR_DIROBJ_DPDIR as ''/u01/aux_dest'' 
 
instruçãosql: create or replace directory TSPITR_DIROBJ_DPDIR as ''/u01/aux_dest'' 
 
Exportando metadados...
   EXPDP> Iniciando "SYS"."TSPITR_EXP_liyq":
   EXPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/PLUGTS_BLK
   EXPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/TABLE
   EXPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/POST_INSTANCE/PLUGTS_BLK
   EXPDP> Tabela-mestre "SYS"."TSPITR_EXP_liyq" carregada/descarregada com sucesso
   EXPDP> ******************************************************************************
   EXPDP> Conjunto de arquivos de dump para SYS.TSPITR_EXP_liyq é:
   EXPDP>   /u01/aux_dest/tspitr_liyq_47871.dmp
   EXPDP> ******************************************************************************
   EXPDP> Os arquivos de dados necessários para o tablespace transportável TBS_01:
   EXPDP>   /u01/app/oracle/oradata/BD01/tbs01.dbf
   EXPDP> O job "SYS"."TSPITR_EXP_liyq" foi concluído com sucesso em 10:34:53
Exportação concluída
 
 
conteúdo do Script de Memória:
{ 
# shutdown clone before import 
shutdown clone immediate 
# drop target tablespaces before importing them back 
sql 'drop tablespace  TBS_01 including contents keep datafiles'; 
}
executando Script de Memória
 
banco de dados fechado
banco de dados desmontado
encerramento de instância Oracle
 
instruçãosql: drop tablespace  TBS_01 including contents keep datafiles 
 
Importando metadados...
   IMPDP> Tabela-mestre "SYS"."TSPITR_IMP_liyq" carregada/descarregada com sucesso
   IMPDP> Iniciando "SYS"."TSPITR_IMP_liyq":
   IMPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/PLUGTS_BLK
   IMPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/TABLE
   IMPDP> Processando o tipo de objeto TRANSPORTABLE_EXPORT/POST_INSTANCE/PLUGTS_BLK
   IMPDP> O job "SYS"."TSPITR_IMP_liyq" foi concluído com sucesso em 10:36:35
Importação concluída
 
 
conteúdo do Script de Memória:
{ 
# make read write and offline the imported tablespaces 
sql 'alter tablespace  TBS_01 read write'; 
sql 'alter tablespace  TBS_01 offline'; 
# enable autobackups after TSPITR is finished 
sql 'begin dbms_backup_restore.AutoBackupFlag(TRUE); end;'; 
} 
executando Script de Memória 
 
instruçãosql: alter tablespace  TBS_01 read write 
 
instruçãosql: alter tablespace  TBS_01 offline 
 
instruçãosql: begin dbms_backup_restore.AutoBackupFlag(TRUE); end; 
 
Removendo instância automática
Instância automática removida
arquivo auxiliar /u01/aux_dest/BD01/datafile/o1_mf_temp_5qblm062_.tmp deletado
arquivo auxiliar /u01/aux_dest/BD01/onlinelog/o1_mf_3_5qbllp52_.log deletado
arquivo auxiliar /u01/aux_dest/BD01/onlinelog/o1_mf_2_5qbllko0_.log deletado
arquivo auxiliar /u01/aux_dest/BD01/onlinelog/o1_mf_1_5qbllc1f_.log deletado
arquivo auxiliar /u01/aux_dest/BD01/datafile/o1_mf_sysaux_5qblgq6d_.dbf deletado
arquivo auxiliar /u01/aux_dest/BD01/datafile/o1_mf_undotbs1_5qblgq6p_.dbf deletado
arquivo auxiliar /u01/aux_dest/BD01/datafile/o1_mf_system_5qblgq4w_.dbf deletado
arquivo auxiliar /u01/aux_dest/BD01/controlfile/o1_mf_5qblg0ld_.ctl deletado
Finalizado recover em 06/03/2010 10:36:47
 
RMAN>exit
 
Recovery Manager completo.
 

Pronto. O processo de recuperação foi finalizado. Vejamos os resultados ... Bom, após a tentativa mal sucedida de selecionar o dados da tabela TABELA_01, percebi que tanto o arquivo de dados associado ao tablespapce TBS_01 como o próprio tablespace TBS_01 estavam OFFLINE.

 

[oracle@linux1 /]$ sqlplus / as sysdba
 
SQL*Plus: Release 11.2.0.1.0 Production on Sab Mar 6 10:42:46 2010
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
 
Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
 
SQL> select file#,name,status from v$datafile;
 
     FILE# NAME                                                       STATUS
---------- ---------------------------------------------------------- -------
         1 /u01/app/oracle/oradata/BD01/system01.dbf                  SYSTEM
         2 /u01/app/oracle/oradata/BD01/undotbs01.dbf                 ONLINE
         3 /u01/app/oracle/oradata/BD01/sysaux01.dbf                  ONLINE
         4 /u01/app/oracle/oradata/BD01/users01.dbf                   ONLINE
         5 /u01/app/oracle/oradata/BD01/tbs01.dbf                     OFFLINE
         6 /u01/app/oracle/oradata/BD01/tbs02.dbf                     ONLINE
 
6 linhasselecionadas.
 
SQL> select tablespace_name,status from dba_tablespaces where tablespace_name='TBS_01';
 
TABLESPACE_NAME                STATUS
------------------------------ ---------
TBS_01                         OFFLINE

 

Agora irei alterar o status do arquivo de dados e do tablespace TBS_01 para ONLINE conforme a execução dos comandos abaixo:

 

SQL>alterdatabasedatafile 5 online;
 
Banco de dados alterado.
 
SQL>alter tablespace tbs_01 online;
 
Tablespace alterado.


Vejamos novamente o resultado da operação ...

SQL>connect usuario_01/senha
Conectado.
 
SQL> select * from tabela_01;
 
        ID
----------
	 1
         2
         3
         4
         5
         6
         7
         8
         9
        10
 
10 linhas selecionadas.

 

Pronto. A tabela TABELA_01 foi restaurada com sucesso. Os usuários do sistema de Recursos Humanos estão satisfeitos. Irei agora realizar uma consulta na tabela do sistema de Vendas:

 

SQL>connect usuario_02/senha
Conectado.
 
SQL> select * from tabela_02;
 
        ID
----------
       100
       200
       300
       400
       500
       600
       700
       800
       900
      1000
 
10 linhas selecionadas.

Perfeito. Os dados da tabela TABELA_02 estão como deveriam estar, ou seja, os mesmos não foram tocados durante o processo de TSPITR. Em resumo, para este cenário com certeza a melhor solução seria a execução da técnica TSPITR, embora, um backup lógico (se disponível) para restaurar a tabela TABELA_01 não seria nada ruim. Por isso, acho extremamente interessante que uma estratégia de backup inclua tanto backups físicos quanto backups lógicos.

Abaixo está uma figura que demonstra alguns dos passos realizados pelo RMAN ao realizar uma recuperação pontual de tablespace.


Como mencionado no início do artigo, em muitos casos uma falha lógica causada por erro humano pode facilmente ser resolvida através da técnica DBPITR. Antes do Oracle 10g, o único jeito de realizar tal operação era fazendo uma recuperação incompleta de media. (Media Incomplete Recovery) em que, dependendo do caso, poderia consumir muito tempo. Por outro lado, fazendo uso do Flashback Database à partir do Oracle 10g, uma operação de DBPITR pode ser executada de forma bastante rápida: 25 a 105 vezes mais rápida do que uma operação de recuperação incompleta, segundo o artigo publicado por Ron Weiss. Como resultado, o tempo de inatividade do banco de dados durante o processo de recuperação, será significativamente menor como mostra a figura abaixo:


Para finalizar, não custa nada dizer como é bom saber que a Oracle forneceu uma solução rápida de recovery onde tablespaces individuais possam ser recuperados para um tempo específico no passado, enquanto o restante do banco de dados ainda continua acessível aos usuários!



Eduardo Legatti é Analista de Sistemas e Administrador de banco de dados. É pós graduado em Gerência da Tecnologia da Informação, possui as certificações OCA 9i - OCP 9i/10g/11g – OCE SQL Expert, e vem trabalhando como DBA Oracle desde a versão 8.0.5. Se interessa particularmente em planejar estratégias de backup/recovery, performance tuning e projetos de bancos de dados (modelagem física e lógica) atuando como consultor. Como Oracle ACE, ele tem o hábito de disseminar seu conhecimento através de artigos, grupos de discussão (Oracle OTN Forums) e dedica-se a compartilhar informações de forma a motivar novos DBAs. Frequentemente posta artigos em seu Oracle blog http://eduardolegatti.blogspot.com.