Hoje quero abordar um assunto que acompanhei recentemente em um fórum sobre banco de dados Oracle. Em uma discussão um DBA pergunta como acelerar uma importação de dados usando o antigo utilitário de importação “imp”. Esse DBA recebeu várias sugestões inclusive a sugestão de alterar o modo de archivamento de logs do banco de dados para noarchivelog e fazer a importação dos dados, logo em seguida alterar novamente o modo de arquivamento de logs para archive log mode.
- Backup Full diário às 00:00 Horas.
- Backup dos archive logs três vezes ao dia (às 09:00,às 15:00 e às 19:00horas)
Para cumprir com a estratégia de backup, vou fazer um backup full do banco de dados antes de alterá-lo, esse backup full é o backup diário descrito acima, no nosso cenário ele é feito às 00:00horas. Fazendo backup full do banco de dados e dos archive logs:
1: RMAN> run {2: 2> allocate channel c1 type disk format '/u03/oradata/bkpfull_%s.rman';3: 3> backup database plus archivelog;4: 4> }
Antes de desligar a instância e alterar o modo de arquivamento de logs vou confirmar o modo atual:
1: SQL> select log_mode from v$database;2: LOG_MODE3: ------------4: ARCHIVELOG5: SQL>
1: SQL> select group#,thread#,sequence#,archived,status2: 2 from v$log;3: GROUP# THREAD# SEQUENCE# ARC STATUS4: ---------- ---------- ---------- --- ----------------5: 1 1 21 YES INACTIVE6: 2 1 22 NO CURRENT7: SQL>
Vamos imaginar que ás 01 da manha o DBA resolve fazer a importação dos dados. Esse horário é tranqüilo, pois não tem usuários conectados ao banco de dados, nenhum acesso simultâneo, e a importação pode ser feita na velocidade da luz. :)
Desligando a instância e alterando o modo de arquivamento do banco de dados para iniciar a carga de dados.
1: SQL> shutdown immediate;2: Database closed.3: Database dismounted.4: ORACLE instance shut down
Abrindo o banco de dados em modo mount
1: SQL> startup mount;2: ORACLE instance started.
Alterando o modo de arquivamento de logs
1: SQL> alter database noarchivelog;2: Database altered.3: SQL>
Abrindo o banco de dados
1: SQL> alter database open;2: Database altered.3: SQL>
Com o banco de dados aberto e em modo noarchivelog, o DBA inicia a importação dos dados. A importação a ser feita usa o utilitário de importação antigo, conforme foi a discussão descrita acima. A titulo de exemplo faço uma importação de duas tabelas com dados aleatórios:
1: imp userid=rodrigo/eumesmo file=t1andt2.dmp tables=table1,table2
Monitorando o alertlog podemos ver que o banco de dados está importando os dados e as seqüências dos redo logs estão sendo incrementadas, mas nenhum archive log está sendo gerado, pois o modo de arquivamento está configurado para noarchivelog.
1: tail -f /u01/app/oracle/admin/producao/bdump/alert_producao.log2: Thread 1 advanced to log sequence 233: Current log# 1 seq# 23 mem# 0: /u02/oradata/producao/redo01a.log4: Current log# 1 seq# 23 mem# 1: /u03/oradata/producao/redo01b.log5: Mon Apr 11 09:23:07 20116: Thread 1 cannot allocate new log, sequence 247: Checkpoint not complete8: Current log# 1 seq# 23 mem# 0: /u02/oradata/producao/redo01a.log9: Current log# 1 seq# 23 mem# 1: /u03/oradata/producao/redo01b.log10: Thread 1 advanced to log sequence 2411: Current log# 2 seq# 24 mem# 0: /u02/oradata/producao/redo02a.log12: Current log# 2 seq# 24 mem# 1: /u03/oradata/producao/redo02b.log13: Mon Apr 11 09:23:18 201114: Thread 1 cannot allocate new log, sequence 2515: Checkpoint not complete16: Current log# 2 seq# 24 mem# 0: /u02/oradata/producao/redo02a.log17: Current log# 2 seq# 24 mem# 1: /u03/oradata/producao/redo02b.log18: Thread 1 advanced to log sequence 2519: Current log# 1 seq# 25 mem# 0: /u02/oradata/producao/redo01a.log20: Current log# 1 seq# 25 mem# 1: /u03/oradata/producao/redo01b.log
Às 03 da manha a importação é concluída. Vamos visualizar qual é a seqüência corrente do banco de dados e então voltar o banco de dados para o modo de arquivamento archivelog.
1: SQL> select group#,thread#,sequence#,archived,status from v$log;2: GROUP# THREAD# SEQUENCE# ARC STATUS3: ---------- ---------- ---------- --- ----------------4: 1 1 29 NO ACTIVE5: 2 1 30 NO CURRENT
Desligado a instância
Iniciando o banco em modo mount1: SQL> shutdown immediate;
Alterando para archivelog mode1: SQL> startup mount;2: ORACLE instance started
1: SQL> alter database archivelog;2: Database altered.3: SQL>
Abrindo o banco..
1: SQL> alter database open;2: Database altered.3: SQL>
Pronto, importação concluída com sucesso e agora o banco de dados volta ao seu estado incial, no modo archivelog. Então às 07horas da manha o banco de dados começa a receber transações, usuários trabalhando normalmente. Vou inserir alguns registros a fim de simular essas transações.
1: SQL> begin2: 2 for i in 1..5000003: 3 loop4: 4 insert into rodrigo.valor values(i);5: 5 end loop;6: 6 end;7: 7 /8: PL/SQL procedure successfully completed.9: SQL>
Conforme a estratégia de backup e recover, ás 09horas é feito um backup dos archivelogs, vamos ao backup.
1: RMAN> run{2: 2> allocate channel ch1 type disk format '/u03/oradata/bkp-archives_%s.rman';3: 3> sql 'alter system archive log current';4: 4> backup archivelog all delete input;5: 5> }
Depois do backup das 09horas vou inserir mais alguns registros e simular o backup das 15horas e mais alguns registros e por último o backup das 19horas. Inseri esses registros para simular um ambiente de produção, onde o banco de dados está sendo alterado o tempo todo e a estratégia de backup está funcionando perfeitamente.
1: SQL> begin2: 2 for i in 1..3000003: 3 loop4: 4 insert into rodrigo.valor values(i);5: 5 end loop;6: 6 end;7: 7 /
Backup das 15horas....
1: RMAN> run{2: 2> allocate channel ch1 type disk format '/u03/oradata/bkp-archives_%s.rman';3: 3> sql 'alter system archive log current';4: 4> backup archivelog all delete input;5: 5> }
Mais registros inseridos...
1: SQL> begin2: 2 for i in 1..2500003: 3 loop4: 4 insert into rodrigo.valor values(i);5: 5 end loop;6: 6 end;7: 7 /
E por fim o backup das 19horas..
1: RMAN> run{2: 2> allocate channel ch1 type disk format '/u03/oradata/bkp-archives_%s.rman';3: 3> sql 'alter system archive log current';4: 4> backup archivelog all delete input;5: 5> }
Com a estratégia de backup concluída, o banco de dados se encontra operacional. Agora como recuperar esse banco de dados caso aconteça uma falha de mídia e todos os datafiles são perdidos? Simples, só voltar o backup full e todos os backups de archivelogs. Bom, vamos simular essa situação.
Desligando a instância abruptamente.
1: SQL> shutdown abort2: ORACLE instance shut down.
Então irei remover os datafiles via sistema operacional
1: [oracle@oracle10g-01 producao]$ rm -rf *.dbf
Iniciando a instância…
1: SQL> startup;2: ORACLE instance started.3: Total System Global Area 536870912 bytes4: Fixed Size 1220432 bytes5: Variable Size 138412208 bytes6: Database Buffers 394264576 bytes7: Redo Buffers 2973696 bytes8: Database mounted.9: ORA-01157: cannot identify/lock data file 1 - see DBWR trace file10: ORA-01110: data file 1: '/u02/oradata/producao/system01.dbf'
O banco parou no estado mount, vamos então conectar ao RMAN e iniciar o restore e recover do banco, conforme estratégia mostrada acima.
1: [oracle@oracle10g-01 ~]$ rman target /
Listando os backups disponíveis vemos que temos um backup full e três backups de achivelogs o que é normal, conforme a estratégia de backup mostrada acima.
1: RMAN> list backup summary;2: List of Backups3: ===============4: Key TY LV S Device Type Completion Time #Pieces #Copies Compressed Tag5: ------- -- -- - ----------- --------------- ------- ------- ---------- ---6: 9 B A A DISK 11-APR-11 1 1 NO TAG201104 11T0848067: 10 B F A DISK 11-APR-11 1 1 NO TAG201104 11T0848098: 11 B F A DISK 11-APR-11 1 1 NO TAG201104 11T0848099: 12 B A A DISK 11-APR-11 1 1 NO TAG201104 11T08493710: 13 B A A DISK 11-APR-11 1 1 NO TAG201104 11T10064811: 14 B A A DISK 11-APR-11 1 1 NO TAG201104 11T10145412: 15 B A A DISK 11-APR-11 1 1 NO TAG201104 11T10195113: RMAN>
Vou iniciar fazendo o restore do backup full e logo em seguida, farei o recover usando os backups de archivelos feitos na seqüência...
1: RMAN> restore database;2: Starting restore at 11-APR-113: using channel ORA_DISK_14: channel ORA_DISK_1: starting datafile backupset restore5: channel ORA_DISK_1: specifying datafile(s) to restore from backup set6: restoring datafile 00001 to /u02/oradata/producao/system01.dbf7: restoring datafile 00002 to /u02/oradata/producao/undotbs01.dbf8: restoring datafile 00003 to /u02/oradata/producao/sysaux01.dbf9: restoring datafile 00004 to /u02/oradata/producao/data01.dbf10: channel ORA_DISK_1: reading from backup piece /u03/oradata/bkpfull_10.rman11: channel ORA_DISK_1: restored backup piece 112: piece handle=/u03/oradata/bkpfull_10.rman tag=TAG20110411T08480913: channel ORA_DISK_1: restore complete, elapsed time: 00:01:0614: Finished restore at 11-APR-11
Banco restaurado com sucesso, agora o recover...
1: RMAN> recover database;2: starting media recovery3: channel ORA_DISK_1: starting archive log restore to default destination4: channel ORA_DISK_1: restoring archive log5: archive log thread=1 sequence=216: channel ORA_DISK_1: restoring archive log7: archive log thread=1 sequence=308: channel ORA_DISK_1: restoring archive log9: archive log thread=1 sequence=3110: channel ORA_DISK_1: restoring archive log11: archive log thread=1 sequence=3212: channel ORA_DISK_1: restoring archive log13: archive log thread=1 sequence=3314: channel ORA_DISK_1: restoring archive log15: archive log thread=1 sequence=3416: channel ORA_DISK_1: reading from backup piece /u03/oradata/bkp-archives_13.rman17: channel ORA_DISK_1: restored backup piece 118: piece handle=/u03/oradata/bkp-archives_13.rman tag=TAG20110411T10064819: channel ORA_DISK_1: restore complete, elapsed time: 00:00:1620: archive log filename=/u02/oradata/producao/archives/log1_21_748157061.arc thread=1 sequence=2121: unable to find archive log22: archive log thread=1 sequence=2223: RMAN-00571: ===========================================================24: RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============25: RMAN-00571: ===========================================================26: RMAN-03002: failure of recover command at 04/11/2011 11:21:0127: RMAN-06054: media recovery requesting unknown log: thread 1 seq 22 lowscn 16906928: RMAN>
Erro! O RMAN começa a recuperar o banco de dados mas não encontra a sequência de archives de número 22 essa seqüência não foi arquivada pois o banco foi colocado em noarchivelog para realizar a importação dos dados. Mas e os backups de 9horas, 15horas e 19horas não podem ser usados para recuperar o banco de dados? Não, pois a seqüência de logs foi interrompida, veja que no backup das 09horas estão incluídas as sequências 20,21,31,32,33 e 34 a seqüência 22 e posteriores não foram arquivadas durante a importação.
1: RMAN> list backupset 13;2: List of Backup Sets3: ===================4: BS Key Size Device Type Elapsed Time Completion Time5: ------- ---------- ----------- ------------ ---------------6: 13 169.91M DISK 00:00:20 11-APR-117: BP Key: 13 Status: AVAILABLE Compressed: NO Tag: TAG20110411T1006488: Piece Name: /u03/oradata/bkp-archives_13.rman9:10: List of Archived Logs in backup set 1311: Thrd Seq Low SCN Low Time Next SCN Next Time12: ---- ------- ---------- --------- ---------- ---------13: 1 20 165074 11-APR-11 169033 11-APR-1114: 1 21 169033 11-APR-11 169069 11-APR-1115: 1 30 171376 11-APR-11 172026 11-APR-1116: 1 31 172026 11-APR-11 172690 11-APR-1117: 1 32 172690 11-APR-11 173319 11-APR-1118: 1 33 173319 11-APR-11 174273 11-APR-1119: 1 34 174273 11-APR-11 174278 11-APR-1120: RMAN>
Vamos simular essa alternativa, farei o mesmo processo, a diferença é que farei um backup full após a importação dos dados. Para iniciar os testes criei um novo banco de dados, verificando o modo de arquivamento do banco de dados:
1: SQL> select log_mode from v$database;2: LOG_MODE3: ------------4: ARCHIVELOG5: SQL>
Fazendo o backup diário dessa vez com a tag BKPFULL-01
1: RMAN> run {2: 2> allocate channel c2 type disk format '/u03/oradata/producao/bkp-full_%s.rman';3: 3> backup database plus archivelog tag='BKPFULL-01';4: 4> }
Depois de fazer o backup full, vamos alterar o modo de arquivamento do banco de dados e em seguida fazer a importação.
Desligando a instância e demontando o banco de dados
1: SQL> shutdown immediate;2: Database closed.3: Database dismounted.4: ORACLE instance shut down.
Iniciando o banco em modo mount
1: SQL> startup mount;2: ORACLE instance started.
Alterando o modo de arquivamento para noarchivelog
1: SQL> alter database noarchivelog;2: Database altered.3: SQL>
Abrindo o banco de dados novamente...
1: SQL> alter database open;2: Database altered.3: SQL>
Antes de iniciar a importação vamos visualizar a seqüência corrente dos redo logs
1: SQL> select group#,thread#,sequence#,archived,status from v$log;2: GROUP# THREAD# SEQUENCE# ARC STATUS3: ---------- ---------- ---------- --- ----------------4: 1 1 11 NO CURRENT5: 2 1 10 NO ACTIVE6: 2 rows selected.7: SQL>
Iniciando a importação dos dados
1: imp userid=rodrigo/eumesmo file=t1andt2.dmp tables=table1,table2
Vamos acompanha o alertlog novamente, e perceba que como estamos no modo noarchivelog não foi gerado nenhum log.
1: [oracle@oracle10g-01 ~]$ tail -f /u01/app/oracle/admin/producao/bdump/alert_producao.log2: Current log# 2 seq# 12 mem# 1: /u03/oradata/producao/redo02b.log3: Thread 1 cannot allocate new log, sequence 134: Checkpoint not complete5: Current log# 2 seq# 12 mem# 0: /u02/oradata/producao/redo02a.log6: Current log# 2 seq# 12 mem# 1: /u03/oradata/producao/redo02b.log7: Mon Apr 11 13:09:35 20118: Thread 1 advanced to log sequence 139: Current log# 1 seq# 13 mem# 0: /u02/oradata/producao/redo01a.log10: Current log# 1 seq# 13 mem# 1: /u03/oradata/producao/redo01b.log11: Thread 1 cannot allocate new log, sequence 14
Depois de importado os dados, vamos visualizar a seqüência de redo logs corrente.
1: SQL> select group#,thread#,sequence#,archived,status from v$log;2: GROUP# THREAD# SEQUENCE# ARC STATUS3: ---------- ---------- ---------- --- ----------------4: 1 1 19 NO CURRENT5: 2 1 18 NO INACTIVE6: 2 rows selected.7: SQL>
Percebam que agora a seqüência corrente é de número 19, ou seja, o banco de dados já sobrescreveu os redo logs 8 vezes e não gerou os archives pois está no modo noarchivelog. È agora que o DBA deve fazer um backup full do banco de dados, justamente para que o backup full contemple as alterações feitas pela importação. Como não foi gerado nenhum archive log o primeiro backup full não poderá ser recuperado, pois a seqüência de logs foi quebrada, conforme explicado acima. Vamos então voltar o banco para archive log e fazer um backup full novamente.
Desligando a instância e demontando o banco de dados
1: SQL> shutdown immediate;2: Database closed.3: Database dismounted.4: ORACLE instance shut down.
Iniciando o banco em modo mount
1: SQL> startup mount;2: ORACLE instance started.3: Database mounted.
Alterando o modo de arquivamento para noarchivelog
1: SQL> alter database archivelog;2: Database altered.
Abrindo o banco de dados
1: SQL> alter database open;2: Database altered.3: SQL>
Fazendo backup full
1: RMAN> run {2: 2> allocate channel c3 type disk format '/u03/oradata/producao/bkp-full-02_%s.rman';3: 3> backup database plus archivelog;4: 4> }
Pronto agora vou inserir alguns registros a fim de simular a carga de dados e fazer os dois backups de archivelogs como exemplo mostrado acima. Inserindo 300.000 registros em uma tabela simbólica
1: SQL> begin2: 2 for i in 1..3000003: 3 loop4: 4 insert into rodrigo.valor values(i);5: 5 end loop;6: 6 end;7: 7 /
Agora o primeiro backup de archivelogs
1: RMAN> run {2: 2> allocate channel ch1 type disk format '/u03/oradata/bkp-archives-01_%s.rman';3: 3> sql 'alter system archive log current';4: 4> backup archivelog all delete input;5: 5> }
Inserindo mais registros
1: SQL> begin2: 2 for i in 1..2500003: 3 loop4: 4 insert into rodrigo.valor values(i);5: 5 end loop;6: 6 end;7: 7 /
Agora o segundo backup de archivelogs
1: RMAN> run {2: 2> allocate channel ch1 type disk format '/u03/oradata/bkp-archives-01_%s.rman';3: 3> sql 'alter system archive log current';4: 4> backup archivelog all delete input;5: 5> }
Bom agora vou simular a perda de disco, vou excluir os datafiles novamente. Desligando a instância abruptamente.
1: RMAN> shutdown abort;2: Oracle instance shut down3: RMAN>
Removendo os datafiles via sistema operacional
1: [oracle@oracle10g-01 producao]$ rm -rf *.dbf
Agora vamos iniciar a instância e ver o erro
1: SQL> startup2: ORACLE instance started.3: Total System Global Area 536870912 bytes4: Fixed Size 1220432 bytes5: Variable Size 142606512 bytes6: Database Buffers 390070272 bytes7: Redo Buffers 2973696 bytes8: Database mounted.9: ORA-01157: cannot identify/lock data file 1 - see DBWR trace file10: ORA-01110: data file 1: '/u02/oradata/producao/system01.dbf'
O erro emitido nos diz que não possível encontrar o datafile 1, vamos usar a estratégia normal, restaurar o backup full depois os backups de archivelogs para recuperar o banco de dados. A diferença principal é que dessa vez devemos restaurar o segundo backup full, o backup full feito após a importação dos dados, pois este contém as alterações que não foram arquivadas e que são necessárias para seqüência de logs que estão nos backups de archivelogs.
Ao emitir o comando restore database o RMAN por padrão já restaura o backup mais recente. No nosso caso é o backup correto, ou seja, o backup feito após a importação dos dados
1: RMAN> restore database;2: Starting restore at 11-APR-113: using channel ORA_DISK_14: channel ORA_DISK_1: starting datafile backupset restore5: channel ORA_DISK_1: specifying datafile(s) to restore from backup set6: restoring datafile 00001 to /u02/oradata/producao/system01.dbf7: restoring datafile 00002 to /u02/oradata/producao/undotbs01.dbf8: restoring datafile 00003 to /u02/oradata/producao/sysaux01.dbf9: restoring datafile 00004 to /u02/oradata/producao/data01.dbf10: channel ORA_DISK_1: reading from backup piece /u03/oradata/producao/bkp-full-02_9.rman11: channel ORA_DISK_1: restored backup piece 112: piece handle=/u03/oradata/producao/bkp-full-02_9.rman tag=TAG20110411T13365713: channel ORA_DISK_1: restore complete, elapsed time: 00:01:0614: Finished restore at 11-APR-1115: RMAN>
Note que o RMAN restaurou o backup full correto, conforme dito acima. Vamos ao recover, nesse caso o RMAN irá verificar se existem backups de archivelogs disponíveis e usá-los para o recover do banco de dados.
1: RMAN> recover database;2: Starting recover at 11-APR-113: using channel ORA_DISK_14: starting media recovery5: channel ORA_DISK_1: starting archive log restore to default destination6: channel ORA_DISK_1: restoring archive log7: archive log thread=1 sequence=208: channel ORA_DISK_1: restoring archive log9: archive log thread=1 sequence=2110: channel ORA_DISK_1: restoring archive log11: archive log thread=1 sequence=2212: channel ORA_DISK_1: restoring archive log13: archive log thread=1 sequence=2314: channel ORA_DISK_1: reading from backup piece /u03/oradata/bkp-archives-01_12.rman15: channel ORA_DISK_1: restored backup piece 116: piece handle=/u03/oradata/bkp-archives-01_12.rman tag=TAG20110411T13483817: channel ORA_DISK_1: restore complete, elapsed time: 00:00:0818: archive log filename=/u02/oradata/producao/archives/log1_20_748182662.arc thread=1 sequence=2019: archive log filename=/u02/oradata/producao/archives/log1_21_748182662.arc thread=1 sequence=2120: archive log filename=/u02/oradata/producao/archives/log1_22_748182662.arc thread=1 sequence=2221: archive log filename=/u02/oradata/producao/archives/log1_23_748182662.arc thread=1 sequence=2322: channel ORA_DISK_1: starting archive log restore to default destination23: channel ORA_DISK_1: restoring archive log24: archive log thread=1 sequence=2425: channel ORA_DISK_1: restoring archive log26: archive log thread=1 sequence=2527: channel ORA_DISK_1: restoring archive log28: archive log thread=1 sequence=2629: channel ORA_DISK_1: reading from backup piece /u03/oradata/bkp-archives-02_13.rman30: channel ORA_DISK_1: restored backup piece 131: piece handle=/u03/oradata/bkp-archives-02_13.rman tag=TAG20110411T13552432: channel ORA_DISK_1: restore complete, elapsed time: 00:00:0733: archive log filename=/u02/oradata/producao/archives/log1_24_748182662.arc thread=1 sequence=2434: archive log filename=/u02/oradata/producao/archives/log1_25_748182662.arc thread=1 sequence=2535: media recovery complete, elapsed time: 00:00:0636: Finished recover at 11-APR-1137: RMAN>
Abrindo o banco de dados
1: RMAN> alter database open;2: database opened3: RMAN>
Agora sim o banco de dados restaurado e recuperado com sucesso :)
Como mostrado nos logs do RMAN os backups dos archivelogs foram usados para recuperar o banco de dados. O segundo backup full (feito após a importação) continha as alterações necessárias para dar seqüência aos archive logs que estavam nos backups. Com isso podemos perceber que alterações no modo de arquivamento do banco de dados podem causar problemas e devem ser bem planejadas, para que não venha causar danos a integridade das informações.