Uma das features mais aguardadas da versão 12C do Oracle era justamente a possibilidade de fazer um recover de tabela a partir do backup de RMAN. Neste artigo, vamos demonstrar o funcionamento do processo, bem como todas as implicações e requisitos necessários para o sucesso do procedimento.
Até agora, sempre que fosse necessário realizar um recover de uma ou mais tabelas, mas não de toda a base, seria necessário utilizar o backup lógico (exp ou datapump) para essa atividade. Esse procedimento possui a limitação de somente ser possível restaurar a tabela no ponto em que foi realizado o backup da mesma. Se o backup foi realizado durante a madrugada, mas um registro foi indevidamente alterado às 10h00 por exemplo, um recover dessa tabela só traria os registros, obviamente, até a madrugada, excluindo tudo que foi feito durante o período até às 10h00.
Outra possibilidade era restaurar o backup físico, mas isso implica em voltar toda a base, incluindo todos os schemas existentes, e não somente a tabela que se deseja restaurar.
Uma terceira possibilidade era o de duplicar o banco a partir do backup físico, realizar um export lógico da tabela, e restaurá-la na base de produção, ou importar numa base de testes para comparação.
O que a nova feature de recover de tabelas via RMAN, no Oracle 12C faz, é automatizar essa última opção em um processo único e totalmente gerenciado pelo RMAN. O processo é exatamente esse; 1)Faz um duplicate a partir do backup físico; 2) Exporta a tabela ou conjunto de tabelas via datapump; 3) Importa a(s) tabela(s) na base, podendo realizar um remap_table; 4) Exclui a instância clonada, datafiles, controlfiles, arquivos de parâmetro e o dump gerado no processo.
Confesso que quando entendi como o processo funcionava, fiquei um pouco decepcionado. Esperava que, ao realizar um processo de restore da tabela, a “mágica” ocorresse diretamente nos blocos do backup, e não um conjunto de ações que, em seu núcleo de execução, não altera em nada a arquitetura do RMAN como a conhecemos hoje. No entanto, ao executar o processo em meus testes, verifiquei que o processo é bem interessante, e realmente agiliza e facilita muito o trabalho, tirando várias preocupações que o DBA teria ao realizar manualmente todas as etapas mencionadas.
Mas deixemos de conversa de “grupinho de DBA na hora do café”, e vamos demonstrar como a coisa toda funciona.
Em uma instância Oracle 12C Enterprise, tenho uma tablespace chamada TESTE_DATA, que foi criada com 4 datafiles. Tenho um owner chamado TESTE, que possui privilégio de armazenamento ilimitado nesta tablespace. Criei uma tabela para esse owner chamada TABELA_TESTE, fazendo um “CREATE TABLE ….. AS SELECT *” da view DBA_OBJECTS, do SYS. Queria que a tabela tivesse um volume de dados suficiente para que as extensões da tabela ocupassem mais do que 1 datafile, mas não todos. O motivo desta particularidade, compartilharei mais para frente. Como podemos ver a seguir, a tabela se extendeu por 3 dos 4 datafiles da tablespace TESTE_DATA. Mais especificamente nos datafiles de ID 5,7 e 8:
SQL> SELECT distinct(FILE_ID), SEGMENT_NAME, TABLESPACE_NAME from dba_extents where owner='TESTE';
FILE_ID SEGMENT_NAME TABLESPACE_NAME
---------- -------------------- ------------------------------
5 TABELA_TESTE TESTE_DATA
7 TABELA_TESTE TESTE_DATA
8 TABELA_TESTE TESTE_DATA
Para fins de demonstração e análise do processo, criei uma nova tablespace, que chamei de CONTROLE_DATA, com 1 datafile:
SQL> create tablespace CONTROLE_DATA datafile '+DGDATA' size 100m; Tablespace created.
O próximo passo é fazer um backup do banco via RMAN, pois no meu caso, por se tratar de uma instância que utilizo para testes, não possuo nenhuma rotina de backup físico, e portanto, nenhum conjunto de backups.
RMAN> backup database; Starting backup at 20-FEB-14 using channel ORA_DISK_1 channel ORA_DISK_1: starting full datafile backup set channel ORA_DISK_1: specifying datafile(s) in backup set input datafile file number=00001 name=+DGDATA/DBPROD/DATAFILE/system.271.839926541 input datafile file number=00003 name=+DGDATA/DBPROD/DATAFILE/sysaux.270.839926235 input datafile file number=00009 name=+DGDATA/DBPROD/DATAFILE/controle_data.293.840013943 input datafile file number=00004 name=+DGDATA/DBPROD/DATAFILE/undotbs1.273.839926845 input datafile file number=00002 name=+DGDATA/DBPROD/DATAFILE/teste.287.839954981 input datafile file number=00005 name=+DGDATA/DBPROD/DATAFILE/teste_data.288.840013323 input datafile file number=00007 name=+DGDATA/DBPROD/DATAFILE/teste_data.291.840013325 input datafile file number=00008 name=+DGDATA/DBPROD/DATAFILE/teste_data.292.840013327 input datafile file number=00010 name=+DGDATA/DBPROD/DATAFILE/teste_data.285.840020271 input datafile file number=00006 name=+DGDATA/DBPROD/DATAFILE/users.272.839926837 channel ORA_DISK_1: starting piece 1 at 20-FEB-14 channel ORA_DISK_1: finished piece 1 at 20-FEB-14 piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t105806_0.284.840020291 tag=TAG20140220T105806 comment=NONE channel ORA_DISK_1: backup set complete, elapsed time: 00:01:25 channel ORA_DISK_1: starting full datafile backup set channel ORA_DISK_1: specifying datafile(s) in backup set including current control file in backup set including current SPFILE in backup set channel ORA_DISK_1: starting piece 1 at 20-FEB-14 channel ORA_DISK_1: finished piece 1 at 20-FEB-14 piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/ncsnf0_tag20140220t105806_0.296.840020379 tag=TAG20140220T105806 comment=NONE channel ORA_DISK_1: backup set complete, elapsed time: 00:00:07 Finished backup at 20-FEB-14
De volta à instância, habilitei o time para melhor entendimento do processo. Fiz um “select count” na tabela, seguido da exclusão de mais da metade dos registros da mesma, simulando um erro, acidental ou não, que demande um recover desta tabela para um momento antes da exclusão dos registros:
11:00:08 SQL> select count(1) from TESTE.TABELA_TESTE;
COUNT(1)
----------
90829
11:00:43 SQL> DELETE from TESTE.TABELA_TESTE where OWNER='SYS';
41785 rows deleted.
11:00:52 SQL> commit;
Commit complete.
11:00:56 SQL> select count(1) from TESTE.TABELA_TESTE;
COUNT(1)
----------
49044
Conectado ao RMAN, emito o comando RECOVER TABLE, informando no parâmetro UNTIL TIME o momento exato em que desejo que a tabela seja recuperada. Informo na string a área que o RMAN utilizará para criação da instância temporária, e também a área de geração do arquivo de exportação do datapump:
[oracle@orazety12c ~]$ rman target /
Recovery Manager: Release 12.1.0.1.0 - Production on Thu Feb 20 11:02:13 2014
Copyright (c) 1982, 2013, Oracle and/or its affiliates. All rights reserved.
connected to target database: DBPROD (DBID=939006448)
RMAN> RECOVER TABLE TESTE.tabela_teste UNTIL TIME "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')" AUXILIARY DESTINATION '/orateste/oradata' DATAPUMP DESTINATION '/orateste/oradata' DUMP FILE 'TABELAS_RECOVER.dat';
Starting recover at 20-FEB-14
using target database control file instead of recovery catalog
current log archived
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of recover command at 02/20/2014 11:02:25
RMAN-05063: Cannot recover specified tables
RMAN-05112: table "TESTE"."TABELA_TESTE" already exists
RMAN>
Opa, erro de tabela existente. Sim, o RMAN não exclui a tabela para substituí-la pelo recover. Se o DBA deseja recuperar a tabela diretamente na produção, deve excluí-la antes do processo:
SQL> DROP table TESTE.TABELA_TESTE; Table dropped.
Agora sim, podemos executar o procedimento no RMAN com sucesso:
RMAN> RECOVER TABLE TESTE.tabela_teste UNTIL TIME "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')" AUXILIARY DESTINATION '/orateste/oradata' DATAPUMP DESTINATION '/orateste/oradata' DUMP FILE 'TABELAS_RECOVER.dat';
Starting recover at 20-FEB-14
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=66 device type=DISK
RMAN-05026: WARNING: presuming following set of tablespaces applies to specified Point-in-Time
List of tablespaces expected to have UNDO segments
Tablespace SYSTEM
Tablespace UNDOTBS1
Creating automatic instance, with SID='yvDv'
initialization parameters used for automatic instance:
db_name=DBPROD
db_unique_name=yvDv_pitr_DBPROD
compatible=12.1.0.0.0
db_block_size=8192
db_files=200
sga_target=1G
processes=80
diagnostic_dest=/u01/app/oracle
db_create_file_dest=/orateste/oradata
log_archive_dest_1='location=/orateste/oradata'
#No auxiliary parameter file used
starting up automatic instance DBPROD
Oracle instance started
Total System Global Area 1068937216 bytes
Fixed Size 2296576 bytes
Variable Size 281019648 bytes
Database Buffers 780140544 bytes
Redo Buffers 5480448 bytes
Automatic instance created
contents of Memory Script:
{
# set requested point in time
set until time "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd: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';
}
executing Memory Script
executing command: SET until clause
Starting restore at 20-FEB-14
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=7 device type=DISK
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: restoring control file
channel ORA_AUX_DISK_1: reading from backup piece +DGDATA/DBPROD/BACKUPSET/2014_02_20/ncsnf0_tag20140220t105806_0.296.840020379
channel ORA_AUX_DISK_1: piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/ncsnf0_tag20140220t105806_0.296.840020379 tag=TAG20140220T105806
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:08
output file name=/orateste/oradata/DBPROD/controlfile/o1_mf_9jd390ph_.ctl
Finished restore at 20-FEB-14
sql statement: alter database mount clone database
sql statement: alter system archive log current
contents of Memory Script:
{
# set requested point in time
set until time "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')";
# set destinations for recovery set and auxiliary set datafiles
set newname for clone datafile 1 to new;
set newname for clone datafile 4 to new;
set newname for clone datafile 3 to new;
set newname for clone tempfile 1 to new;
# switch all tempfiles
switch clone tempfile all;
# restore the tablespaces in the recovery set and the auxiliary set
restore clone datafile 1, 4, 3;
switch clone datafile all;
}
executing Memory Script
executing command: SET until clause
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
renamed tempfile 1 to /orateste/oradata/DBPROD/datafile/o1_mf_temp_%u_.tmp in control file
Starting restore at 20-FEB-14
using channel ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_AUX_DISK_1: restoring datafile 00003 to /orateste/oradata/DBPROD/datafile/o1_mf_sysaux_%u_.dbf
channel ORA_AUX_DISK_1: reading from backup piece +DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t091315_0.294.840014001
channel ORA_AUX_DISK_1: piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t091315_0.294.840014001 tag=TAG20140220T091315
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:46
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_AUX_DISK_1: restoring datafile 00001 to /orateste/oradata/DBPROD/datafile/o1_mf_system_%u_.dbf
channel ORA_AUX_DISK_1: restoring datafile 00004 to /orateste/oradata/DBPROD/datafile/o1_mf_undotbs1_%u_.dbf
channel ORA_AUX_DISK_1: reading from backup piece +DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t105806_0.284.840020291
channel ORA_AUX_DISK_1: piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t105806_0.284.840020291 tag=TAG20140220T105806
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:46
Finished restore at 20-FEB-14
datafile 1 switched to datafile copy
input datafile copy RECID=4 STAMP=840021208 file name=/orateste/oradata/DBPROD/datafile/o1_mf_system_9jd3bvjj_.dbf
datafile 4 switched to datafile copy
input datafile copy RECID=5 STAMP=840021208 file name=/orateste/oradata/DBPROD/datafile/o1_mf_undotbs1_9jd3bvjo_.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=6 STAMP=840021208 file name=/orateste/oradata/DBPROD/datafile/o1_mf_sysaux_9jd39f2q_.dbf
contents of Memory Script:
{
# set requested point in time
set until time "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')";
# online the datafiles restored or switched
sql clone "alter database datafile 1 online";
sql clone "alter database datafile 4 online";
sql clone "alter database datafile 3 online";
# recover and open database read only
recover clone database tablespace "SYSTEM", "UNDOTBS1", "SYSAUX";
sql clone 'alter database open read only';
}
executing Memory Script
executing command: SET until clause
sql statement: alter database datafile 1 online
sql statement: alter database datafile 4 online
sql statement: alter database datafile 3 online
Starting recover at 20-FEB-14
using channel ORA_AUX_DISK_1
starting media recovery
archived log for thread 1 with sequence 12 is already on disk as file /orateste/oradata/arch_1_12_839926904.arc
archived log for thread 1 with sequence 13 is already on disk as file /orateste/oradata/arch_1_13_839926904.arc
archived log for thread 1 with sequence 14 is already on disk as file /orateste/oradata/arch_1_14_839926904.arc
archived log file name=/orateste/oradata/arch_1_12_839926904.arc thread=1 sequence=12
archived log file name=/orateste/oradata/arch_1_13_839926904.arc thread=1 sequence=13
archived log file name=/orateste/oradata/arch_1_14_839926904.arc thread=1 sequence=14
media recovery complete, elapsed time: 00:00:04
Finished recover at 20-FEB-14
sql statement: alter database open read only
contents of Memory Script:
{
sql clone "create spfile from memory";
shutdown clone immediate;
startup clone nomount;
sql clone "alter system set control_files =
''/orateste/oradata/DBPROD/controlfile/o1_mf_9jd390ph_.ctl'' comment=
''RMAN set'' scope=spfile";
shutdown clone immediate;
startup clone nomount;
# mount database
sql clone 'alter database mount clone database';
}
executing Memory Script
sql statement: create spfile from memory
database closed
database dismounted
Oracle instance shut down
connected to auxiliary database (not started)
Oracle instance started
Total System Global Area 1068937216 bytes
Fixed Size 2296576 bytes
Variable Size 285213952 bytes
Database Buffers 775946240 bytes
Redo Buffers 5480448 bytes
sql statement: alter system set control_files = ''/orateste/oradata/DBPROD/controlfile/o1_mf_9jd390ph_.ctl'' comment= ''RMAN set'' scope=spfile
Oracle instance shut down
connected to auxiliary database (not started)
Oracle instance started
Total System Global Area 1068937216 bytes
Fixed Size 2296576 bytes
Variable Size 285213952 bytes
Database Buffers 775946240 bytes
Redo Buffers 5480448 bytes
sql statement: alter database mount clone database
contents of Memory Script:
{
# set requested point in time
set until time "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')";
# set destinations for recovery set and auxiliary set datafiles
set newname for datafile 5 to new;
set newname for datafile 7 to new;
set newname for datafile 8 to new;
set newname for datafile 10 to new;
# restore the tablespaces in the recovery set and the auxiliary set
restore clone datafile 5, 7, 8, 10;
switch clone datafile all;
}
executing Memory Script
executing command: SET until clause
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
executing command: SET NEWNAME
Starting restore at 20-FEB-14
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=27 device type=DISK
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_AUX_DISK_1: restoring datafile 00005 to /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_%u_.dbf
channel ORA_AUX_DISK_1: restoring datafile 00007 to /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_%u_.dbf
channel ORA_AUX_DISK_1: restoring datafile 00008 to /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_%u_.dbf
channel ORA_AUX_DISK_1: restoring datafile 00010 to /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_%u_.dbf
channel ORA_AUX_DISK_1: reading from backup piece +DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t105806_0.284.840020291
channel ORA_AUX_DISK_1: piece handle=+DGDATA/DBPROD/BACKUPSET/2014_02_20/nnndf0_tag20140220t105806_0.284.840020291 tag=TAG20140220T105806
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:03
Finished restore at 20-FEB-14
datafile 5 switched to datafile copy
input datafile copy RECID=11 STAMP=840021295 file name=/orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw5x_.dbf
datafile 7 switched to datafile copy
input datafile copy RECID=12 STAMP=840021295 file name=/orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw67_.dbf
datafile 8 switched to datafile copy
input datafile copy RECID=13 STAMP=840021295 file name=/orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw6l_.dbf
datafile 10 switched to datafile copy
input datafile copy RECID=14 STAMP=840021295 file name=/orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw8y_.dbf
contents of Memory Script:
{
# set requested point in time
set until time "to_date('2014-02-20:11:00:00', 'yyyy-mm-dd:hh24:mi:ss')";
# online the datafiles restored or switched
sql clone "alter database datafile 5 online";
sql clone "alter database datafile 7 online";
sql clone "alter database datafile 8 online";
sql clone "alter database datafile 10 online";
# recover and open resetlogs
recover clone database tablespace "TESTE_DATA", "SYSTEM", "UNDOTBS1", "SYSAUX" delete archivelog;
alter clone database open resetlogs;
}
executing Memory Script
executing command: SET until clause
sql statement: alter database datafile 5 online
sql statement: alter database datafile 7 online
sql statement: alter database datafile 8 online
sql statement: alter database datafile 10 online
Starting recover at 20-FEB-14
using channel ORA_AUX_DISK_1
starting media recovery
archived log for thread 1 with sequence 14 is already on disk as file /orateste/oradata/arch_1_14_839926904.arc
archived log file name=/orateste/oradata/arch_1_14_839926904.arc thread=1 sequence=14
media recovery complete, elapsed time: 00:00:01
Finished recover at 20-FEB-14
database opened
contents of Memory Script:
{
# create directory for datapump import
sql "create or replace directory TSPITR_DIROBJ_DPDIR as ''
/orateste/oradata''";
# create directory for datapump export
sql clone "create or replace directory TSPITR_DIROBJ_DPDIR as ''
/orateste/oradata''";
}
executing Memory Script
sql statement: create or replace directory TSPITR_DIROBJ_DPDIR as ''/orateste/oradata''
sql statement: create or replace directory TSPITR_DIROBJ_DPDIR as ''/orateste/oradata''
Performing export of tables...
EXPDP> Starting "SYS"."TSPITR_EXP_yvDv_wCFg":
EXPDP> Estimate in progress using BLOCKS method...
EXPDP> Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
EXPDP> Total estimation using BLOCKS method: 13 MB
EXPDP> Processing object type TABLE_EXPORT/TABLE/TABLE
EXPDP> Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
EXPDP> Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
EXPDP> . . exported "TESTE"."TABELA_TESTE" 10.36 MB 90829 rows
EXPDP> Master table "SYS"."TSPITR_EXP_yvDv_wCFg" successfully loaded/unloaded
EXPDP> ******************************************************************************
EXPDP> Dump file set for SYS.TSPITR_EXP_yvDv_wCFg is:
EXPDP> /orateste/oradata/TABELAS_RECOVER.dat
EXPDP> Job "SYS"."TSPITR_EXP_yvDv_wCFg" successfully completed at Thu Feb 20 11:18:19 2014 elapsed 0 00:02:01
Export completed
contents of Memory Script:
{
# shutdown clone before import
shutdown clone abort
}
executing Memory Script
Oracle instance shut down
Performing import of tables...
IMPDP> Master table "SYS"."TSPITR_IMP_yvDv_jrcp" successfully loaded/unloaded
IMPDP> Starting "SYS"."TSPITR_IMP_yvDv_jrcp":
IMPDP> Processing object type TABLE_EXPORT/TABLE/TABLE
IMPDP> Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
IMPDP> . . imported "TESTE"."TABELA_TESTE" 10.36 MB 90829 rows
IMPDP> Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
IMPDP> Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
IMPDP> Job "SYS"."TSPITR_IMP_yvDv_jrcp" successfully completed at Thu Feb 20 11:20:33 2014 elapsed 0 00:01:47
Import completed
Removing automatic instance
Automatic instance removed
auxiliary instance file /orateste/oradata/DBPROD/datafile/o1_mf_temp_9jd3dqym_.tmp deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/onlinelog/o1_mf_3_9jd3hdz0_.log deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/onlinelog/o1_mf_2_9jd3hb34_.log deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/onlinelog/o1_mf_1_9jd3h6l9_.log deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw8y_.dbf deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw6l_.dbf deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw67_.dbf deleted
auxiliary instance file /orateste/oradata/YVDV_PITR_DBPROD/datafile/o1_mf_teste_da_9jd3gw5x_.dbf deleted
auxiliary instance file /orateste/oradata/DBPROD/datafile/o1_mf_sysaux_9jd39f2q_.dbf deleted
auxiliary instance file /orateste/oradata/DBPROD/datafile/o1_mf_undotbs1_9jd3bvjo_.dbf deleted
auxiliary instance file /orateste/oradata/DBPROD/datafile/o1_mf_system_9jd3bvjj_.dbf deleted
auxiliary instance file /orateste/oradata/DBPROD/controlfile/o1_mf_9jd390ph_.ctl deleted
auxiliary instance file TABELAS_RECOVER.dat deleted
Finished recover at 20-FEB-14
Veja na leitura deste extenso log, todas as etapas que mencionei no inicio deste artigo, totalmente evidenciadas. Perceba que o RMAN cria uma instância DUMMY utilizando apenas os datafiles da SYSTEM, SYSAUX, UNDO e os datafiles da tablespace TESTE_DATA, além de criar uma tablespace temporária. Aqui eu chamo atenção para o fato dos 4 datafiles da tablespace TESTE_DATA, que foram recuperados na base, mesmo a tabela só ocupando 3 deles. Outro detalhe é a tablespace CONTROLE_DATA e USERS. Nenhum datafile dessas tablespaces foi recuperado, poupando espaço utilizado no processo. Destas 2 constatações, tiramos 2 lições importantes na utilização deste recurso; A primeira é o fato de que, como o duplicate é realizado apenas da tablespace envolvida mais as de sistema, o espaço demandado é otimizado, evitando que,por exemplo, em uma instância com 10 tablespaces de 1TB no total, precisemos alocar 1TB de espaço apenas para recuperar 1 tabela. A segunda questão é que, apesar de só duplicar as tablespaces de sistema mais a tablespace da tabela, o processo recupera toda a tablespace. Isso quer dizer que, se a tabela possui 5mb, mas a tablespace possui 100GB, teremos que disponibilizar esse tamanho, mais o espaço utilizado para as tablespaces de sistema, a tablespace temporária e área para os archivelogs utilizados. Essa questão é muito importante, e deve ser levada em conta no processo de recover da tabela.
Ao final do processo, no qual o RMAN duplicou a base, acionou o DATAPUMP para exportar a tabela e depois para importar na instância, os arquivos utilizados são excluídos.
Antes do processo ser executado, monitorei os processos de pmon no servidor, e a área do disco /orateste, que utilizei para ser realizada a duplicação e exportação:
oracle 1318 1315 0 11:23 pts/0 00:00:00 grep ora_pm
oracle 3390 1 0 08:44 ? 00:00:04 ora_pmon_dbprod
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
25G 17G 7.5G 69% /
/dev/sda1 99M 24M 71M 25% /boot
tmpfs 1.3G 626M 619M 51% /dev/shm
/dev/sdb1 22G 265M 21G 2% /orateste
Durante o processo, o cenário era o seguinte:
oracle 376 372 0 11:15 pts/0 00:00:00 grep ora_pm
oracle 3390 1 0 08:44 ? 00:00:04 ora_pmon_dbprod
oracle 32307 1 0 11:14 ? 00:00:00 ora_pmon_yvDv
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
25G 17G 7.5G 69% /
/dev/sda1 99M 24M 71M 25% /boot
tmpfs 1.3G 626M 619M 51% /dev/shm
/dev/sdb1 22G 2.0G 19G 10% /orateste
Veja a instância yvDv criada com o duplicate, e 2gb utilizados no processo.
De volta à instância DBPROD, verificamos se a tabela foi recuperada para a quantidade de registros existentes antes doa exclusão acidental:
11:24:23 SQL> SELECT count(1) from TESTE.TABELA_TESTE;
COUNT(1)
----------
90829
Um detalhe importante que o DBA deve ficar atento; Após o processo, a instância dummy é eliminada, os datafiles, controlfile e dump são excluídos, mas a estrutura de pastas e archives utilizados no duplicate não! Veja abaixo que, todos os testes anteriores, mais este que realizei para este artigo, geraram estruturas nesta área que não foram eliminadas pelo processo. Perceba também que cada estrutura recebe um nome atribuído pelo RMAN á instância criada, e este sempre é diferente:
[oracle@orazety12c oradata]$ pwd /orateste/oradata [oracle@orazety12c oradata]$ ls -ltr total 94980 -rw-r----- 1 oracle asmadmin 5948416 Feb 19 16:09 arch_1_6_839926904.arc -rw-r----- 1 oracle asmadmin 877056 Feb 19 16:34 arch_1_7_839926904.arc -rw-r----- 1 oracle asmadmin 17920 Feb 19 16:36 arch_1_8_839926904.arc drwxr-x--- 5 oracle asmadmin 4096 Feb 19 16:36 DBPROD drwxr-x--- 4 oracle asmadmin 4096 Feb 19 16:39 GAMH_PITR_DBPROD -rw-r----- 1 oracle asmadmin 5312000 Feb 19 16:53 arch_1_9_839926904.arc -rw-r----- 1 oracle asmadmin 442368 Feb 19 16:54 arch_1_10_839926904.arc drwxr-x--- 4 oracle asmadmin 4096 Feb 19 16:57 RIUS_PITR_DBPROD -rw-r----- 1 oracle asmadmin 6773248 Feb 20 08:44 arch_1_11_839926904.arc -rw-r----- 1 oracle asmadmin 35577344 Feb 20 09:23 arch_1_12_839926904.arc -rw-r----- 1 oracle asmadmin 86016 Feb 20 09:26 arch_1_13_839926904.arc drwxr-x--- 4 oracle asmadmin 4096 Feb 20 09:29 SEKV_PITR_DBPROD -rw-r----- 1 oracle asmadmin 41875968 Feb 20 11:02 arch_1_14_839926904.arc -rw-r----- 1 oracle asmadmin 173056 Feb 20 11:11 arch_1_15_839926904.arc drwxr-x--- 4 oracle asmadmin 4096 Feb 20 11:15 YVDV_PITR_DBPROD
E assim chegamos ao fim deste artigo, com essa simples demonstração de uma funcionalidade bem interessante da versão 12C. Vale registrar que apenas a versão Enterprise fornece suporte à esta operação. Temos algumas outras opções para este processo, como apenas gerar o dump (sem exlusão do mesmo ao final do procedimento) e recuperar todo um schema.
Veja que, quando existe o espaço suficiente para a duplicação da base e geração do dump, em apenas 1 único comando (RECOVER TABLE …), o DBA tem todos os 4 processos mencionados no início do artigo, realizados e gerenciados pelo RMAN.
Para mais detalhes destas operações, recomendo a leitura da documentação oficial da Oracle sobre este tema.
Abraços e até mais
Autor: Bruno Zehetmeyr bruno.zehe
Bacharel em Ciência da Computação pela UNORP-SP, Pós-graduado em Administração de Sistemas de Informação pela UFLA-MG e pós-graduado em Administração de Banco de Dados Oracle pela VERIS-SP. Analista DBA na Teiko Soluções em TI e professor universitário no Centro Universitário de Brusque – UBIFEBE. Certificado OCP 10g e OCP 11g, OCE Linux. Residente em Blumenau-SC.






