Olá,
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.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> 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 '05/03/2010 15:21:45'; 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. 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'; 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 /]$ 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) 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 <<<-- 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 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!
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.