Para melhor visualização, recomendo resolução de no mínimo 1280 x 800 e navegador Mozilla Firefox


sábado, 6 de março de 2010

RMAN - Database Point-In-Time Recovery (DBPITR) e Tablespace Point-in-Time Recovery (TSPITR)

Por Eduardo Legatti

Olá,

Ao longo do tempo, já foram abordados neste blog, alguns temas relacionados à recuperação de dados fazendo uso de algumas funcionalidades do recurso de Flashback disponíveis à partir das versões do Oracle 9i/10g, entre outras formas, conforme publicados nos artigos de Maio/2007, Junho/2007, Novembro/2007, Maio/2008, Julho/2008, Dezembro/2008 e Abril/2009. Bom, 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 8 e 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 (Transport Tablespaces), 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;

Tablespace criado.

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ário criado.

SQL> create user usuario_02 identified by senha default tablespace tbs_02;

Usuário criado.

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);

Tabela criada.

SQL> insert into usuario_01.tabela_01 select rownum id from dual connect by level <=10;

10 linhas criadas.

SQL> create table 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.  All rights reserved.

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.dbf
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> select systimestamp from dual;

SYSTIMESTAMP
-------------------------------
05/03/10 15:21:45,423501 -03:00

SQL> drop table 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> select systimestamp from 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.  All rights reserved.

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 "to_date('05/03/2010 15:21:45','dd/mm/yyyy hh24:mi:ss')";
2> restore database;
3> recover database;
4> alter database open resetlogs;}
executando comando: SET until clause

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> select systimestamp from dual;

SYSTIMESTAMP
-------------------------------
06/03/10 10:26:34,707082 -03:00

SQL> drop table 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> select systimestamp from 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 - 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, 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 TSPITR conforme demonstração abaixo:

[oracle@linux1 u01]$ 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.  All rights reserved.

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';  

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 auxiliary parameter 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 until clause

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: alter database mount clone database

instrução sql: alter system archive log current

instrução sql: 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 <<<-- -01539="" :="alter tablespace " begin="" declare="" end="" exception="" exception_init="" immediate="" krmicd.execsql="" krmicd.writemsg="" null="" offline="" offline_not_needed="" pragma="" sqlstatement="" then="" tspitr_2="" varchar2="" when="">>>;
# 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 until clause

instrução sql: 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 until clause

instrução sql: alter database datafile  1 online

instrução sql: alter database datafile  2 online

instrução sql: alter database datafile  3 online

instrução sql: alter database datafile  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ção sql: alter tablespace  TBS_01 read only

instrução sql: create or replace directory TSPITR_DIROBJ_DPDIR as ''/u01/aux_dest''

instrução sql: 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ção sql: 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ção sql: alter tablespace  TBS_01 read write

instrução sql: alter tablespace  TBS_01 offline

instrução sql: 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 linhas selecionadas.

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> alter database datafile 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!



9 comentários:

Rodrigo Santana disse...

Olá Eduardo, gostaria de parabenizá-lo pelo artigo, muito didático.
Já tinha visto como fazer esse processo de forma manual (restore em outra base, export e import, etc)
Uma dúvida, é possível fazer o processo dessa forma automatizada usando o 10g? (TSPITR)
Se não se importar vou colocar um Link do seu blog no meu blog ok ?
Abraço!

Eduardo Legatti disse...

Olá Rodrigo,

Seja bem vindo e parabéns pelo seu blog. Respondendo à sua pergunta, no Oracle 10g o RMAN também automatiza totalmente o processo de recovery (TSPITR). No mais, fique à vontade para disseminar o meu blog ;-)

Abraços e até mais ...

Anônimo disse...

Oi Eduardo, muito bom o artigo.
O erro abaixo não tem solução ?
RMAN-06455: point-in-time tablespace recovery requires Enterprise Edition
Sds,
Enchaves

Eduardo Legatti disse...

Olá Enchaves,

Realmente não tem solução. Esta operação só poderá ser realizada em um banco de dados Oracle Enterprise Edition.

No mais, veja a resolução desta mensagem abaixo:

Oracle Error : RMAN-06455: point-in-time tablespace recovery requires Enterprise Edition

Cause: A point-in-time tablespace recovery was attempted, but Enterprise Edition is not installed.

Action: Do not do point-in-time tablespace recovery.

Abraços e até mais ...

Sidney França disse...

Parabéns!! Eduardo, mais um artigo muito bom! aliás estou acompanhando seus artigos sobre RMAN e estou aprendendo muito. Obrigado!! Ao acompanhar com um Oracle 11g no windows xp, tive um problema com a data.

C:\>sqlplus / as sysdba

SQL*Plus: Release 11.2.0.1.0 Production on Ter Nov 13 23:56:45 2012

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

Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> shutdown immediate;
Banco de dados fechado.
Banco de dados desmontado.
InstÔncia ORACLE desativada.
SQL>
SQL> exit
Desconectado de Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

C:\>rman target /

Gerenciador de RecuperaþÒo: Release 11.2.0.1.0 - Production on Qua Nov 14 00:13:23 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

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 535662592 bytes

Fixed Size 1375792 bytes
Variable Size 293601744 bytes
Database Buffers 234881024 bytes
Redo Buffers 5804032 bytes

RMAN> run {set until time '13/11/2012 22:37:12';
2> restore database;
3> recover database;
4> alter database open resetlogs;}

executando comando: SET until clause

Iniciando restore em 14/11/12
usar o arquivo de controle do banco de dados de destino em vez do catßlogo de recuperaþÒo
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: falha do comando restore em 11/14/2012 00:16:16
ORA-01830: a imagem do formato da data termina antes de converter a string de entrada inteira

RMAN>

Estou pesquisando uma solução, se tiver uma dica te agradeço demais. Mais uma vez parabéns o artigo ficou muito bom!

Eduardo Legatti disse...

Olá Sidney,

O problema deve ser no NLS_DATE_FORMAT do seu ambiente. Neste caso, sem problemas, é só forçar a máscara com a função TO_DATE.

set until time = "to_date('13/11/2012 22:37:12','DD/MM/YYYY:HH24:MI:SS')";

Abraços

Legatti

Sidney França disse...

Valeu Eduardo,

Sua dica funcionou perfeitamente!Muito obrigado e parabéns pelo blog!!

Abraços.

Sidney França

Anônimo disse...

Olá Eduardo, parabéns pelo post.
A minha dúvida é, por exemplo, ter três tabelas na mesma tablespace, então eu dropo somente uma delas, as outras duas continuam sendo alteradas, percebo que preciso recuperar a tabela dropada mas sem alterar os dados atualizados nas outras duas. Vc conhece uma solução para esse problema?

Abraços.

Fabrício.

Eduardo Legatti disse...

Olá Fabrício,

Dizem que no Oracle 12c que estar por vir, com o RMAN será possível recuperar as tabelas diretamente dos backupsets. Estou doido pra ver isso. ;-) No mais, a solução para esse problema é simples. Use o DUPLICATE DATABASE fazendo "point in time recovery" em um instância auxiliar. Dá uma olhada no artigo Clonando um banco de dados Oracle com o RMAN - DUPLICATE DATABASE (10g vs 11g). A diferença é que em vez de clonar o banco de dados até o estado mais recente, você irá fazer um clone até o momento antes da tabela ter sido dropada. Depois você exporta a tabela do banco de dados auxiliar e importa a mesma para o banco de dados principal.

Exemplo:

duplicate target database to AUX until time 'sysdate-1';

ou

run {
set until time = "to_date('09/01/2013 22:00','DD/MM/YYYY:HH24:MI:SS')";
duplicate target database to AUX;
}

Abraços

Legatti

Postagens populares