Oracle e MAA – Artigo I

Este artigo é o primeiro de uma série sobre Maximum Availability Architecture (MAA), com os passos, dicas e afins para configurar e manter um ambiente deste porte. No final da série teremos um ambiente com Oracle RAC tanto no primary quanto no standby. Ambos sincronizados com Data Guard (DG) rodando em alta disponibilidade.

Não é a intenção aqui mostrar com configurar um ambiente RAC, já partirei de um ambiente com o RAC instalado e um banco rodando. Utilizarei o Oracle 11GR2 versão 11.2.0.3, já que a intenção também é mostrar como atualizar um ambiente em DG. Além disso, tentarei cobrir alguns pontos como “real-time apply” e criação do banco standby usando Media Management Layer (MML).

Tentarei ser o mais didático e claro possível e caso tenha alguma dúvida, pergunte. Todos os comandos que executei estarão no artigo. Infelizmente este primeiro artigo será extenso (muito) e cheio de detalhes técnicos, não tem como montar um ambiente assim de forma rápida e sem os diversos detalhes envolvidos. Infelizmente não existe um guia rápido de 10 passos para MAA com RAC, isso não existe. Você verá aqui um guia detalhado do início ao fim sobre como configurar MAA com RAC em ambos os lados.

Provavelmente alguns passos utilizados aqui para a configuração do ambiente podem ser mais simples na prática. Espero no final cobrir boa parte de um ambiente DG e MAA: switchover, failover, reisntate, broker, observer e afins.

Uma configuração como esta seria a aplicada em um ambiente Exadata que necessita de alta disponibilidade. Você teria que configurar MAA com DG entre dois Exadatas, como é RAC seria um DG sobre RAC.

PRIMEIRO ARTIGO

Neste primeiro artigo iremos configurar um ambiente DG em dois sites, somente o banco será replicado. Neste artigo não iremos ver a configuração do Broker nem failover, switchover e reinstate; isso ficará para próximos artigos.

AMBIENTE

A primeira coisa a ser feita em qualquer ambiente MAA é entender o ambiente que estamos trabalhando. Aqui, já partimos de um ambiente que chamamos inicialmente de primary com Oracle RAC 11.2.0.3 sobre 2 nós. No ASM temos dois diskgroups DATA e FRA para hospedar o banco de dados. Também temos um banco de dados chamado “maa”. Como dito acima, a intenção aqui não é mostrar a instalação de um RAC, existem ótimos artigos na internet sobre como fazer isso.

A imagem abaixo ilustra o ambiente, no servidor você pode descobrir isso através do comando “crsctl stat res –t”:

Ambiente-Primary

O segundo ambiente chamarei de standby onde temos um RAC instalado, mas sem nenhum banco de dados criado, somente o Grid Infrastricture está instalado e uma instância ASM está criada. O banco de dados será criado aqui através da configuração do DG. A imagem abaixo demonstra este ambiente.

Ambiente-StandbyAqui temos uma mudança interessante, no ambiente standby não temos o diskgroup DATA e sim o DG01. Essa é uma mudança intencional, deixei assim para que fosse possível explicar alguns detalhes na configuração do DG. Preferencialmente tenha os mesmos diskgroups em ambos os lados, primary e standby. Isso não será um problema, vamos ver a frente como contornar.

ARCHIVES, FLASHBACK E LOGMODE

De forma bem resumida DG utiliza archivelogs para sincronizar o primary com o standby, enviando todo e qualquer archive gerado no primary para o standby. Para isso, precisamos que a base esteja em modo ARCHIVELOG. Basta verificar e configurar caso não esteja. Observe nos passos abaixo:

SQL> SELECT instance_name FROM gv$instance;

INSTANCE_NAME
----------------
maa1
maa2

SQL> SELECT log_mode, flashback_on FROM v$database;

LOG_MODE     FLASHBACK_ON
------------ ------------------
NOARCHIVELOG NO

SQL> ARCHIVE LOG LIST;
Database log mode              No Archive Mode
Automatic archival             Disabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     13
Current log sequence           14
SQL>

Como visto acima a base não está em modo archivelog e nem está com o flashback habilitado. Habilitar flashback é fundamental, ele permite recuperar o banco de dados (fazer o reinstate) do primary em caso de failover de maneira muito (mas muito) mais rápida. Isso será tópico de um próximo artigo, mas no failover a troca entre os papeis entre primary e standby é feita de maneira abrupta. Se você tiver habilitado flashback as suas noites serão mais tranquilas e as horas extras menores.

Para configurar tudo corretamente, verifique o parâmetro de destino dos archives e o tamanho que ele pode usar. Dependendo da sua base de dados e da carga sobre ela, recomendo aumentar um pouco o limite da db_recovery_file_dest_size. Você até pode configurar outro caminho para o destino dos archives, mas recomendo deixar tudo gerenciado pelo mesmo parâmetro e apontando para o db_recovery_file_dest. Caso queira ajustar algo, utilize:

ALTER SYSTEM SET db_recovery_file_dest='+FRA' SCOPE=SPFILE SID='*';
ALTER SYSTEM SET db_recovery_file_dest_size=4096M  SCOPE=SPFILE SID='*'; 

Com tudo configurado, basta fazer um restart do banco e habilitar flashback e archivelog. Como estamos em um RAC, acostume-se com seus comandos:

[oracle@rac11pri01 ~]$ srvctl stop database -d maa -o immediate
[oracle@rac11pri01 ~]$ 
[oracle@rac11pri01 ~]$ srvctl start instance -d maa -i maa1 -o mount
[oracle@rac11pri01 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Sat Mar 29 12:15:01 2014

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters and Automatic Storage Management options

SQL> ALTER DATABASE ARCHIVELOG;

Database altered.

SQL> ALTER DATABASE FLASHBACK ON;

Database altered.

SQL> ALTER DATABASE OPEN;

Database altered.

SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters and Automatic Storage Management options
[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$ srvctl start instance -d maa -i maa2
[oracle@rac11pri01 ~]$ srvctl status database -d maa
Instance maa1 is running on node rac11pri01
Instance maa2 is running on node rac11pri02
[oracle@rac11pri01 ~]$

Como disse, o pilar básico do DG são os archiveslogs, mas infelizmente muitas vezes temos tabelas em modo NOLOGGING. Acredito que você já percebeu que isso pode não ser ideal em um DG, mas temos uma forma de corrigir isso com o “FORCE LOGGING”. Habilitando o “FORCE LOGGING” fará o banco de dados a gerar sempre archivelogs mesmo que a sua tabela esteja em NOLOGGING.

Dependendo o modo como você configura o seu DG existe a possibilidade de não usar o “FORCE LOGGING”. Basicamente uma informação sobre a transação é escrita no redo mesmo a operação sendo NOLOGGING, somente o seu archive não é gerado. Não uso assim e não recomendo deixar sem force logging. Configurar o FORCE LOGGING não custa nada e você irá agradecer no futuro.

A configuração é simples, observe abaixo:

SQL> SELECT log_mode, flashback_on, force_logging FROM v$database;

LOG_MODE     FLASHBACK_ON       FOR
------------ ------------------ ---
ARCHIVELOG   YES                NO

SQL> ALTER DATABASE FORCE LOGGING;

Database altered.

SQL> SELECT log_mode, flashback_on, force_logging FROM v$database;

LOG_MODE     FLASHBACK_ON       FOR
------------ ------------------ ---
ARCHIVELOG   YES                YES

SQL>

PREPARANDO PFILE E SPFILE

Agora vamos começar a configurar o primary para o DG, deixando todos os parâmetros corretamente definidos (até para passos e artigos futuros). Como vamos trabalhar com os parâmetros eu recomendo começar com o um backup do spfile, nunca se sabe não é.

SQL> CREATE PFILE = '/tmp/pfile-primary-bkp.ora' FROM spfile;

File created.

SQL>

DB_NAME e DB_UNIQUE_NAME

Estes dois parâmetros são fundamentais em um ambiente DG. São eles que vão definir o nome da base de dados e das instâncias standby. O primeiro parâmetro é o db_name, responsável por dar nome ao banco de dados. O valor definido aqui será o mesmo utilizando tanto no primary quanto no standby.

SQL> SHOW PARAMETER db_name

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_name                              string      maa
SQL>

O próximo parâmetro db_unique_name é utilizado para identificar qual o banco que você está, primary ou standby. O valor deste parâmetro ficará diferente entre o primary e o standy (ao contrário do db_name). No primary nós não modificamos o seu valor, deixamos ele no valor default.

Além disso, a sua definição é utilizada em outros parâmetros e configurações do DG, como por exemplo no redo transportation. Em alguns casos (como no 10G) era possível ter o mesmo valor em ambos os lados, com a versão 11 se isso estiver ocorrendo primary e standby não se comunicam. Essas informações você pode ver neste documento (Oracle Data Guard Concepts and Administration).

Um detalhe importante, o valor do db_unique_name quando não está configurado (fixo no spfile) deriva do db_name. Assim, é fundamental garantir que ele esteja definido no spfile da primary. Veja abaixo:

SQL> SHOW PARAMETER db_unique_name

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_unique_name                       string      maa
SQL>
SQL>  ALTER SYSTEM SET db_unique_name='maa' SCOPE = spfile SID = '*';

System altered.

SQL>

LOG_ARCHIVE_CONFIG

Este parâmetro é utilizado para definir quem participa do DG, quais as bases que irão trocar os archives. Se você tiver mais de um standby você definirá todos eles aqui, se você adicionar mais um standby no futuro terá que modificar este parâmetro.

A configuração deste parâmetro é simples, basta definir como no exemplo abaixo onde temos os dois bancos. Os valores aceitos para este parâmetro são os definidos no parâmetro db_unique_name. Desta forma, observe que já definimos como ficará para o nome para o standby (maastb):

SQL> SHOW PARAMETER log_archive_config

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_config                   string
SQL>
SQL> ALTER SYSTEM SET log_archive_config='DG_CONFIG=(maa,maastb)' SCOPE = spfile SID = '*';

System altered.

SQL>

LOG_ARCHIVE_DEST_XX

Antes de alterarmos estes parâmetros precisamos entender algumas informações importantes do DG. Com as definições que podem ser especificadas nestes parâmetros definimos como o DG irá sincronizar os archives logs, quem será responsável por fazer isso e quando fazer isso.

A primeira definição importante a ser entendida é como os archives são sincronizados, a forma como redo é transportado (o que chamamos de redo transportation):

  • SYNC: No modo síncrono o redo transporation entre o primary e o standy acontece de forma síncrona, isso quer dizer que uma transação no primary somente retorna ao usuário se o standby recebeu ela. Consequentemente isso pode trazer alguns “problemas” se a sua rede não tiver o throughput necessário para conseguir transportar as informações. Imagine que a latência de sua rede será somada ao tempo de qualquer commit do usuário.
  • ASYNC: Neste modo o redo do primary não é transportado com sincronia, isso quer dizer que o commit do usuário não depende do envio da sua transação ao standby. Fica mais rápido, mas menos seguro.

Além da forma síncrona ou não do envio do redo também é necessário especificar uma “garantia” de recebimento por parte do standby. Assim temos duas opções:

  • AFFIRM: garante que o standby recebeu e escreveu o redo no seu grupo de redo (standby redo log – explicarei mais a frente).
  • NOAFFIRM: o primary não espera o ACK do standby sobre a escrita completa do redo enviado. Assim o standby responde o ACK antes de garantir a escrita em seu grupo de redo.

Depois de escolher a sincronia entre as bases é necessário delimitar para o que o log_archive_dest será válido. Esta definição é feita através do atributo VALID_FOR que é dividido em duas partes:

  • REDO_LOG_TYPE:
    • ONLINE_LOGFILE: com este parâmetro definido no VALID_FOR o LOG_ARCHIVE_DEST somente será utilizado quando estiver arquivando os redolog onlines.
    • STANDBY_LOGFILE: o destino somente será válido para standby redologs (explicarei eles mais a frente).
    • ALL_LOGFILES: o destino será utilizado independente do tipo de onlinelog. Como disse anteriormente, se utilizar um único local pode ficar mais simples a gerência.
  • DATABASE_ROLE:
      • PRIMARY_ROLE: o destino somente será utilizando quando o banco estiver atuando como primary.
      • STANDBY_ROLE: ativo somente quando estiver atuando como standby.
      • ALL_ROLES: para ambos os casos acima.

Com estas definições podemos montar o log_archive_dest corretamente, vou tomar como base o exemplo abaixo:

SQL> SHOW PARAMETER log_archive_dest_1

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_1                   string
...
...
SQL> ALTER SYSTEM SET log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=maa' SCOPE=spfile SID='*';

System altered.

SQL>

Vamos analisar em partes o que foi definido acima para deixar tudo claro:

  • LOCATION: definido que o destino dos archives será o que estiver definido no parâmetro DB_RECOVER_FILE_DEST.
  • ALL_LOGFILES: isso quer dizer que este destino será utilizado independente do tipo de onlinelog gerado.
  • ALL_ROLES: integrado com o parâmetro acima, o destino será utilizado independente da role do banco.

Com as definições acima temos que o LOG_ARCHIVE_DEST_1 será utilizado quando qualquer archive for gerado neste banco de dados, independe da role (primary ou standby) e do tipo de onlinelog (redo ou standby). Basicamente defini o armazenamento local. Claro que você pode definir configurações mais específicas, por exemplo, ter um local especifico para standby logs e redo logs. Você pode querer fazer isso para aliviar a carga sobre os discos por exemplo. Da forma como definido acima, tudo estará armazenando na flash_recovery_area.

Como você deve ter percebido, não foi definido nenhum local ou banco remoto para enviar os archives, somente definimos o que fazer localmente. Para especificar o que e como enviar para o standby adicionamos mais um destino, observe o exemplo abaixo:

SQL> ALTER SYSTEM SET log_archive_dest_2='SERVICE=maastb SYNC AFFIRM LGWR VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=maastb' SCOPE=spfile SID='*';

System altered.

SQL>

Novamente verificamos os detalhes:

  • SERVICE: define que o destino será um serviço TNS, o que estiver definido aqui tem que ser igual ao que está no tnsnames.ora. Como estamos em RAC, o TNS deve ser o mesmo para ambas as instâncias.
  • SYNC: aqui, o logwriter somente retornará a transação ao usuário se o standby a receber;
  • AFFIRM: além do logwriter esperar o standby receber, ele irá esperar até que o standby informar que escrever com sucesso em seu standby logs
  • LGWR: este parâmetro era utilizado para diferenciar quem era responsável por enviar os dados ao standby. Deixo aqui para uma garantia que será o logwriter.
  • ONLINE_LOGFILES: este destino será utilizado somente quando estiver arquivando os redolog, você não e não tem motivo para enviar os standby logs.
  • PRIMARY_ROLE: novamente, o destino somente será utilizado quando estiver atuando como primary.

Com a definição acima garantimos o envio síncrono dos dados entre o primary e o standby. Também garantido o recebimento e aplicação dos mesmos pelo standby.

Antes de prosseguirmos, eu acredito que seja importante desligar temporariamente (será ligado só no fim do processo) o log_archive_dest que aponta para o standby. Caso você tenha alguma instância reiniciada você não verá erro por erro de envio ao destino acima definido.

SQL> ALTER SYSTEM SET log_archive_dest_state_2=DEFER SCOPE=spfile SID='*';
System altered.

SQL

Se você quiser, defina um acrônimo para seus archives, quando usamos OFA, o seu nome pode ficar confuso para quem ainda não tem domínio:

SQL> ALTER SYSTEM SET log_archive_format='arch_%t_%s_%r.arc' SCOPE=spfile SID='*';

System altered.

SQL> 

DB_FILE_NAME_CONVERT, LOG_FILE_NAME_CONVERT e STANDBY_FILE_MANAGEMENT

Os dois primeiros parâmetros são importantes em ambientes primary e standby que diferem em sua estrutura de diretórios para datafiles/logfiles. Alguns passos acima você observou que intencionalmente o standby tem uma estrutura de diskgroups diferentes do primary. Esta diferença será corrigida aqui.

Ambos os parâmetros recebem conjunto (pares) de informações, basicamente você informa o caminho de origem e qual o caminho que o substituirá. Isso é importante, pois ao criarmos um novo datafile no primary ele será criado corretamente no standby. Na documentação da Oracle, existe a informação de que ele é considerado/avaliado em pares, o primeiro é substituído pelo segundo e assim sucessivamente (eles até comentam em expressões regulares para análise). Veja as definições abaixo:

SQL> ALTER SYSTEM SET db_file_name_convert='+DG01/maastb','+DATA/maa','+FRA/maastb','+FRA/maa' SCOPE=SPFILE SID='*';

System altered.

SQL>

Observe que aqui, caso o banco receba alguma informação quanto a criação de um datafile o caminho será substituído de ‘+DG01/maastb’ para ‘+DATA/maa’. Note que estamos definindo isso para a base atual que será a primary, mas já estamos preparando ela para caso ela vire standby os parâmetros já estejam corretos.

Fazemos a mesma coisa para os logfiles:

SQL> ALTER SYSTEM SET log_file_name_convert='+DG01/maastb','+DATA/maa','+FRA/maastb','+FRA/maa' SCOPE=spfile SID='*';

System altered.

SQL>

O parâmetro standby_file_management garante uma segurança maior no gerenciamento dos dados. Definido ele como AUTO garantimos que todo e qualquer arquivo criado ou deletado no primary será automaticamente replicado no standby. O detalhe é que ele vem desabilitado por padrão.

SQL> SHOW PARAMETER standby_file_management;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
standby_file_management              string      MANUAL
SQL> ALTER SYSTEM SET standby_file_management=AUTO SCOPE=SPFILE SID='*';

System altered.

SQL>

FAL_SERVER

Este parâmetro define onde que a instância irá buscar os archives caso ocorra algum gap de recebimento. Pense no seguinte caso, você precisa fazer uma manutenção no seu ambiente RAC standby e desliga ele por dois dias, na volta ele terá que buscar os archives em algum lugar (geralmente a primary), esse é o parâmetro que define isso. O valor deste parâmetro deve ser igual ao que está no TNS, em RAC garanta que exista no TNS de ambas as instâncias:

SQL> ALTER SYSTEM SET fal_server=maastb SCOPE=spfile SID='*';

System altered.

SQL>

Com isso, terminamos a preparação do spfile da primary, agora vamos preparar o spfile da base standby.

TNSNAMES

Antes de continuarmos temos que editar o TNSNAMES de todas as instâncias do RAC para criar entradas para o standby. Lembre de todos os parâmetros que definimos previamente e que apontam para o TNS, ele deve casar com os valores que definimos nos parâmetros anteriores. O TNS atual (de uma instância do primary):

[oracle@rac11pri01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

[oracle@rac11pri01 ~]$

Vamos editar ele e adicionar a entrada para o standby (observe que foi adicionado o MAASTB):

[oracle@rac11pri01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

[oracle@rac11pri01 ~]$
Vamos editar ele e adicionar a entrada para o standby (observe que foi adicionado o MAASTB):
[oracle@rac11pri01 ~]$ vi /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$ tnsping maastb

TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 30-MAR-2014 10:05:36

Copyright (c) 1997, 2011, Oracle.  All rights reserved.

Used parameter files:


Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb-scan.tjsc.jus.br)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = maastb)))
OK (10 msec)
[oracle@rac11pri01 ~]$

Como TNS foi editado em único nó para economizar tempo você copia ele (através do scp mesmo) entre todos os nós do primary e para todos os nós do standby:

[oracle@rac11pri01 ~]$ scp /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora rac11pri02:/u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
tnsnames.ora                                                                                                                                                                                               100%  534     0.5KB/s   00:00
[oracle@rac11pri01 ~]$ scp /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora rac11stb01:/u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
oracle@rac11stb01's password:
tnsnames.ora                                                                                                                                                                                               100%  534     0.5KB/s   00:00
[oracle@rac11pri01 ~]$ scp /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora rac11stb02:/u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
oracle@rac11stb02's password:
tnsnames.ora                                                                                                                                                                                               100%  534     0.5KB/s   00:00
[oracle@rac11pri01 ~]$

PREPARANDO STANDBY, SPFILE e DIRETÓRIOS

Depois do SPFILE da primary e do TNS configurado podemos começar os ajustes do spfile da stanby. Tomamos como base o spfile da primary fazendo uma cópia e enviando ela para o RAC standby:

SQL> CREATE PFILE = '/tmp/pfile-primary.ora' FROM spfile;

File created.

SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters and Automatic Storage Management options
[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$ scp /tmp/pfile-primary.ora oracle@rac11stb01:/tmp/pfile-primary-standby.ora
oracle@rac11stb01's password:
pfile-primary.ora                                                                                                                                                                                          100% 1854     1.8KB/s   00:00
[oracle@rac11pri01 ~]$ 

Depois de copiado vamos editar os parâmetros abaixo no spfile que foi copiado para o standby:

  • audit_file_dest: local novo, precisamos ajustar para o nome correto.
  • control_files: mesmo motivo do acima. Observe que foi alterado para +DG01 ao invés de +DATA
  • db_create_file_dest: voltamos ao mesmo ponto, a estrutura de diskgroups é diferente do primary.
  • db_file_name_convert: aqui invertemos as duplas definidas, lembre-se que estamos no standby
  • db_unique_name: lembre da definição de tópicos anteriores, no standby este parâmetro recebe um valor distinto do primary.
  • fal_server: o standby recorre ao primary.
  • log_archive_dest_1: uma simples mudança, o que estava “MAA” vira “MAASTB”
  • log_archive_dest_2: o contrário do anterior, o que era “MAASTB” vira “MAA”
  • log_file_name_convert: mesmo caso do db_file_name_convert, invertemos os valores.
  • remote_listener: ele deve apontar para o servidor que hospeda o standby.
  • maaX.*: todos os parâmetros que referenciavam instâncias específicas do primary foram substituídas para as equivalentes do standby (seguindo o definido pelo db_unique_name).

Observe como ficou o pfile editado:

[oracle@rac11stb01 ~]$ vi /tmp/pfile-primary-standby.ora
[oracle@rac11stb01 ~]$ 
[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora
*.audit_file_dest='/u01/app/oracle/admin/maastb/adump'
*.audit_trail='db'
*.cluster_database=true
*.compatible='11.2.0.0.0'
*.control_files='+DG01/maastb/controlfile/current.273.843488553','+FRA/maastb/controlfile/current.256.843488553'
*.db_block_size=8192
*.db_create_file_dest='+DG01'
*.db_domain=''
*.db_file_name_convert='+DATA/maa','+DG01/maastb','+FRA/maa','+FRA/maastb'
*.db_name='maa'
*.db_recovery_file_dest='+FRA'
*.db_recovery_file_dest_size=10737418240
*.db_unique_name='maastb'
*.diagnostic_dest='/u01/app/oracle'
*.fal_server='MAA'
maastb1.instance_number=1
maastb2.instance_number=2
*.log_archive_config='DG_CONFIG=(maa,maastb)'
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=maastb'
*.log_archive_dest_2='SERVICE=maa SYNC AFFIRM LGWR VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=maa'
*.log_archive_dest_state_2='DEFER'
*.log_archive_format='arch_%t_%s_%r.arc'
*.log_file_name_convert='+DATA/maa','+DG01/maastb','+FRA/maa','+FRA/maastb'
*.open_cursors=300
*.pga_aggregate_target=268435456
*.processes=150
*.remote_listener='rac11stb-scan.tjsc.jus.br:1521'
*.remote_login_passwordfile='exclusive'
*.sga_target=1073741824
*.standby_file_management='AUTO'
maastb2.thread=2
maastb1.thread=1
maastb1.undo_tablespace='UNDOTBS1'
maastb2.undo_tablespace='UNDOTBS2'
[oracle@rac11stb01 ~]$

Para terminar a configuração do standby precisamos ajustar dois detalhes: adump e pasword file. São dois passos simples, no primeiro são criados os diretórios no standby e no segundo o arquivo de senhas do primary é copiado para o standby (precisa ser o mesmo em todos os nós):

No standby
[oracle@rac11stb01 ~]$ mkdir -p /u01/app/oracle/admin/maastb/adump
[oracle@rac11stb01 ~]$
No primary
[oracle@rac11pri01 ~]$ cd $ORACLE_HOME/dbs
[oracle@rac11pri01 dbs]$ scp /u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaa1 oracle@rac11stb01:/u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaastb1
oracle@rac11stb01's password:
orapwmaa1                                                                                                                                                                                                  100% 1536     1.5KB/s   00:00
[oracle@rac11pri01 dbs]$ scp /u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaa1 oracle@rac11stb02:/u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaastb2
oracle@rac11stb02's password:
orapwmaa1                                                                                                                                                                                                  100% 1536     1.5KB/s   00:00
[oracle@rac11pri01 dbs]$

BACKUP, RESTORE E CLONE

Aqui vamos entrar em um ponto que necessita atenção e pode variar de caso a caso. Neste artigo tentarei cobrir 3 métodos de clone. O primeiro é através de backup e restore do banco de dados utilizando backup copiado (backupsets) do primary para o standby. O segundo modo é através de clone com ACTIVE DATABASE. O terceiro é um exemplo resumido de um clone com MML.

Clone com backup local

O primeiro exemplo de clone é criando o standby utilizando um backup do primary. Este backup é copiado ao standby para que seja possível acessá-lo localmente a partir do standby. Isso as vezes fica complicado devido ao tamanho da base de dados, uma base de 2TB necessita que você tenha este espaço disponível no filesystem do sistema operacional do standby. A título de exemplo, vamos seguir com este exemplo.

O primeiro passo é ir na primary e realizar um backup full da base de dados. Repare que não será feito backup do controlfile. O backup do controlfile tem uma função (e comandos específicos e eu prefiro fazer ele separado).

Observe abaixo os comandos executados (a saída foi reduzida para ficar menor e caber no artigo)

Comando executado:
    RUN {
        BACKUP FULL FORMAT '/tmp/bkpf-data-D-%d-DBID-%I-T-%T-NB-%s.bkp' DATABASE TAG 'BKP-FULL';
        SQL 'ALTER SYSTEM ARCHIVE LOG CURRENT';
        BACKUP FORMAT '/tmp/bkpf-arch-D-%d-DBID-%I-T-%T-NB-%s.bkp' ARCHIVELOG ALL TAG 'BKP-FULL-ARCH';
        BACKUP FORMAT '/tmp/bkp-spf-D-%d-DBID-%I-T-%T-NB-%s.bkp' SPFILE TAG 'BKP-FULL-SPFILE';
    }
    
[oracle@rac11pri01 ~]$ rman target /

Recovery Manager: Release 11.2.0.3.0 - Production on Sun Mar 30 13:09:17 2014

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

connected to target database: MAA (DBID=722024964)

RMAN>  RUN {
2>     BACKUP FULL FORMAT '/tmp/bkpf-data-D-%d-DBID-%I-T-%T-NB-%s.bkp' DATABASE TAG 'BKP-FULL';
3>     SQL 'ALTER SYSTEM ARCHIVE LOG CURRENT';
4>     BACKUP FORMAT '/tmp/bkpf-arch-D-%d-DBID-%I-T-%T-NB-%s.bkp' ARCHIVELOG ALL TAG 'BKP-FULL-ARCH';
5>     BACKUP FORMAT '/tmp/bkp-spf-D-%d-DBID-%I-T-%T-NB-%s.bkp' SPFILE TAG 'BKP-FULL-SPFILE';
6> }

Starting backup at 30-MAR-14
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=32 instance=maa1 device type=DISK
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=+DATA/maa/datafile/system.270.843488557
input datafile file number=00002 name=+DATA/maa/datafile/sysaux.269.843488563
...
...
...
channel ORA_DISK_1: starting piece 1 at 30-MAR-14
channel ORA_DISK_1: finished piece 1 at 30-MAR-14
piece handle=/tmp/bkp-spf-D-MAA-DBID-722024964-T-20140330-NB-4.bkp tag=BKP-FULL-SPFILE comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 30-MAR-14

RMAN>

Como disse e observado acima não temos backup do controlfile e ele é fundamental para a criação do standby. Observe que ele é específico para criar o standby, FOR STANDBY.

Eu prefiro fazer ele separado e para disco local. Se você estivesse usando MML, você poderia enviar seu backup para a fita e o controlfile ficaria local. É uma preferência minha, se você quiser enviar tudo para a MML ou executar tudo no passo anterior, sem problema.

RUN {
    BACKUP FORMAT '/tmp/bkp-ctf-D-%d-DBID-%I-T-%T-NB-%s.bkp' CURRENT CONTROLFILE FOR STANDBY TAG 'BKP-FULL-CONTROL';
}

RMAN> RUN {
    BACKUP FORMAT '/tmp/bkp-ctf-D-%d-DBID-%I-T-%T-NB-%s.bkp' CURRENT CONTROLFILE FOR STANDBY TAG 'BKP-FULL-CONTROL';
}2> 3>

Starting backup at 30/03/2014 13:14:12
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including standby control file in backup set
channel ORA_DISK_1: starting piece 1 at 30/03/2014 13:14:13
channel ORA_DISK_1: finished piece 1 at 30/03/2014 13:14:14
piece handle=/tmp/bkp-ctf-D-MAA-DBID-722024964-T-20140330-NB-6.bkp tag=BKP-FULL-CONTROL comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 30/03/2014 13:14:14

RMAN>

Com os backups em mão, vamos copiar eles para o standby.

[oracle@rac11pri01 ~]$ scp /tmp/bkp* oracle@rac11stb01:/tmp/
oracle@rac11stb01's password:
bkp-ctf-D-MAA-DBID-722024964-T-20140330-NB-6.bkp                                                                                                                                                           100%   18MB   8.8MB/s   00:02
bkpf-arch-D-MAA-DBID-722024964-T-20140330-NB-3.bkp                                                                                                                                                         100%  144MB  12.0MB/s   00:12
bkpf-data-D-MAA-DBID-722024964-T-20140330-NB-1.bkp                                                                                                                                                         100%  299MB  11.5MB/s   00:26
bkpf-data-D-MAA-DBID-722024964-T-20140330-NB-2.bkp                                                                                                                                                         100%   18MB   8.9MB/s   00:02
bkp-spf-D-MAA-DBID-722024964-T-20140330-NB-4.bkp                                                                                                                                                           100%   96KB  96.0KB/s   00:00
[oracle@rac11pri01 ~]$    

Com o backup copiado para o standby é possível iniciar o banco. Iniciamos o standby em modo nomount com o pfile que editamos previamente e iniciamos o clone. Subindo o banco em NOMOUNT com o pfile editado:

SQL> STARTUP PFILE='/tmp/pfile-primary-standby.ora' NOMOUNT;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size                  2235208 bytes
Variable Size             339739832 bytes
Database Buffers          721420288 bytes
Redo Buffers                5541888 bytes
SQL>

Como é a primeira vez que estamos iniciando a instância do standby é interessante observar o alertlog para ver se todos os parâmetros foram aceitos corretamente. Verifique os parâmetros que modificamos previamente neste PFILE:

[oracle@rac11stb01 ~]$ tail -1000f /u01/app/oracle/diag/rdbms/maastb/maastb1/trace/alert_maastb1.log
Sun Mar 30 13:19:03 2014
Starting ORACLE instance (normal)
...
...        
Using parameter settings in client-side pfile /tmp/pfile-primary-standby.ora on machine rac11stb01.tjsc.jus.br
System parameters with non-default values:
  processes                = 150
  sga_target               = 1G
  control_files            = "+DG01/maastb/controlfile/current.273.843488553"
  control_files            = "+FRA/maastb/controlfile/current.256.843488553"
  db_file_name_convert     = "+DATA/maa"
  db_file_name_convert     = "+DG01/maastb"
  db_file_name_convert     = "+FRA/maa"
  db_file_name_convert     = "+FRA/maastb"
  log_file_name_convert    = "+DATA/maa"
  log_file_name_convert    = "+DG01/maastb"
  log_file_name_convert    = "+FRA/maa"
  log_file_name_convert    = "+FRA/maastb"
  db_block_size            = 8192
  compatible               = "11.2.0.0.0"
  log_archive_dest_1       = "LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=maastb"
  log_archive_dest_2       = "SERVICE=maa SYNC AFFIRM LGWR VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=maa"
  log_archive_dest_state_2 = "DEFER"
  fal_server               = "MAA"
  log_archive_config       = "DG_CONFIG=(maa,maastb)"
  log_archive_format       = "arch_%t_%s_%r.arc"
  cluster_database         = TRUE
  db_create_file_dest      = "+DG01"
  db_recovery_file_dest    = "+FRA"
  db_recovery_file_dest_size= 10G
  standby_file_management  = "AUTO"
  thread                   = 1
  undo_tablespace          = "UNDOTBS1"
  instance_number          = 1
  remote_login_passwordfile= "EXCLUSIVE"
  db_domain                = ""
  remote_listener          = "rac11stb-scan.tjsc.jus.br:1521"
  audit_file_dest          = "/u01/app/oracle/admin/maastb/adump"
  audit_trail              = "DB"
  db_name                  = "maa"
  db_unique_name           = "maastb"
  open_cursors             = 300
  pga_aggregate_target     = 256M
  diagnostic_dest          = "/u01/app/oracle"
Cluster communication is configured to use the following interface(s) for this instance
  169.254.172.112
cluster interconnect IPC version:Oracle UDP/IP (generic)
...
...
List of instances:
 1 (myinst: 1)
 Global Resource Directory frozen
* allocate domain 0, invalid = TRUE
 Communication channels reestablished
...
...

Como tudo “subiu” com sucesso, vamos clonar o banco. Observe a forma de conexão ao RMAN e que os arquivos estão locais no nó desta instância.

Quanto a conexão um detalhe importante no RAC. Se você especificar no “auxiliary”, por exemplo “sys@maastb”, poderia ter um problema com o listener. O problema reside no fato de que não tem como especificar em que nó a conexão será feita, se tiver sorte será no mesmo nó que você está. Assim, você pode deixar vazio que a conexão será no nó local.

Após a conexão feita é possível clonar o banco para o standby a partir do backup que está armazenado localmente.

[oracle@rac11stb01 tmp]$ rman target sys@maa auxiliary sys

Recovery Manager: Release 11.2.0.3.0 - Production on Sun Mar 30 13:39:01 2014

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

target database Password:
connected to target database: MAA (DBID=722024964)
auxiliary database Password:
connected to auxiliary database: MAA (not mounted)

RMAN> RUN {
    ALLOCATE AUXILIARY CHANNEL d1 DEVICE TYPE DISK FORMAT = '/tmp/bkp-ctf-D-%d-DBID-%I-T-%T-NB-%s.bkp';
    DUPLICATE TARGET DATABASE FOR STANDBY NOFILENAMECHECK;
}2> 3> 4>

using target database control file instead of recovery catalog
allocated channel: d1
channel d1: SID=18 instance=maastb1 device type=DISK

Starting Duplicate Db at 30-MAR-14

contents of Memory Script:
{
   restore clone standby controlfile;
}
executing Memory Script

Starting restore at 30-MAR-14

channel d1: starting datafile backup set restore
channel d1: restoring control file
channel d1: reading from backup piece /tmp/bkp-ctf-D-MAA-DBID-722024964-T-20140330-NB-6.bkp
channel d1: piece handle=/tmp/bkp-ctf-D-MAA-DBID-722024964-T-20140330-NB-6.bkp tag=BKP-FULL-CONTROL
channel d1: restored backup piece 1
channel d1: restore complete, elapsed time: 00:00:06
output file name=+DG01/maastb/controlfile/current.265.843594121
output file name=+FRA/maastb/controlfile/current.260.843594123
Finished restore at 30-MAR-14

contents of Memory Script:
{
   sql clone 'alter database mount standby database';
}
executing Memory Script

sql statement: alter database mount standby database
RMAN-05529: WARNING: DB_FILE_NAME_CONVERT resulted in invalid ASM names; names changed to disk group only.

contents of Memory Script:
{
   set newname for tempfile  1 to
 "+dg01";
   switch clone tempfile all;
   set newname for datafile  1 to
 "+dg01";
   set newname for datafile  2 to
 "+dg01";
   set newname for datafile  3 to
 "+dg01";
   set newname for datafile  4 to
 "+dg01";
   set newname for datafile  5 to
 "+dg01";
   restore
   clone database
   ;
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to +dg01 in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting restore at 30-MAR-14

channel d1: starting datafile backup set restore
channel d1: specifying datafile(s) to restore from backup set
channel d1: restoring datafile 00001 to +dg01
channel d1: restoring datafile 00002 to +dg01
channel d1: restoring datafile 00003 to +dg01
channel d1: restoring datafile 00004 to +dg01
channel d1: restoring datafile 00005 to +dg01
channel d1: reading from backup piece /tmp/bkpf-data-D-MAA-DBID-722024964-T-20140330-NB-1.bkp
channel d1: piece handle=/tmp/bkpf-data-D-MAA-DBID-722024964-T-20140330-NB-1.bkp tag=BKP-FULL
channel d1: restored backup piece 1
channel d1: restore complete, elapsed time: 00:01:25
Finished restore at 30-MAR-14

contents of Memory Script:
{
   switch clone datafile all;
}
executing Memory Script

datafile 1 switched to datafile copy
input datafile copy RECID=6 STAMP=843572620 file name=+DG01/maastb/datafile/system.257.843594135
datafile 2 switched to datafile copy
input datafile copy RECID=7 STAMP=843572620 file name=+DG01/maastb/datafile/sysaux.256.843594135
datafile 3 switched to datafile copy
input datafile copy RECID=8 STAMP=843572620 file name=+DG01/maastb/datafile/undotbs1.262.843594137
datafile 4 switched to datafile copy
input datafile copy RECID=9 STAMP=843572620 file name=+DG01/maastb/datafile/undotbs2.263.843594137
datafile 5 switched to datafile copy
input datafile copy RECID=10 STAMP=843572620 file name=+DG01/maastb/datafile/users.264.843594137
Finished Duplicate Db at 30-MAR-14
released channel: d1

RMAN>

Acredito que a saída acima seja auto explicativa mas fazendo uma análise detalhada obervamos que os arquivos foram convertidos corretamente em seus destinos. +DATA do primary virou +DG01 no standby (ignore o warning que ele deu, o parâmetro está correto).

Se você for ao ASM do standby verá que tudo está no seu devido lugar:

[oracle@rac11stb01 tmp]$ export ORACLE_SID=+ASM1
[oracle@rac11stb01 tmp]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 tmp]$ asmcmd
ASMCMD> ls
DG01/
FRA/
SYS01/
ASMCMD> ls DG01
MAASTB/
ASMCMD> ls FRA
MAASTB/
ASMCMD> ls DG01/MAASTB/
CONTROLFILE/
DATAFILE/
ONLINELOG/
ASMCMD> ls FRA/MAASTB/
CONTROLFILE/
ONLINELOG/
ASMCMD>
ASMCMD> exit
[oracle@rac11stb01 ~]$

Clone com ACTIVE DATABASE

No clone realizado através do ACTIVE DATABASE você vai clonar o banco primary para o standby sem realizar qualquer backup. Você se conecta no banco primary e “manda” ele clonar um standby. Explicarei mais detalhes no decorrer dos próximos passos, o clone utilizando este método é mais complicado do que o anterior.

Diferentemente do método anterior, você precisa conectar no banco auxiliar utilizando tnsnames. Caso contrário, você verá o erro abaixo ao tentar clonar o banco:

[oracle@rac11stb01 ~]$ rman target sys@maa auxiliary sys

Recovery Manager: Release 11.2.0.3.0 - Production on Sun Mar 30 14:47:40 2014

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

target database Password:
connected to target database: MAA (DBID=722024964)
auxiliary database Password:
connected to auxiliary database: MAA (not mounted)

RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER NOFILENAMECHECK;

Starting Duplicate Db at 30/03/2014 14:48:15
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of Duplicate Db command at 03/30/2014 14:48:16
RMAN-05501: aborting duplication of target database
RMAN-06217: not connected to auxiliary database with a net service name

RMAN>

Assim, o primeiro passo é criar um método de conectar diretamente na instância. Como estamos em um ambiente RAC fica um pouco mais complicado, você pode ter problemas de conexão caso seja redirecionada para o nó errado. Basicamente registramos manualmente a instância.

Particularmente eu prefiro criar manualmente um listener em um único nó e direcionar as conexões do standby para ele. Este pode não ser o melhor método, mas me sinto confortável com ele.

Para isso temos que criar um listener específico no standby para o clone em uma outra porta (observe o numero da porta, o hostname, GLOBAL_DBNAME e SID_NAME):

[oracle@rac11stb01 ~]$ vi /u01/app/grid/11.2.0.3/network/admin/listener.ora
[oracle@rac11stb01 ~]$ cat /u01/app/grid/11.2.0.3/network/admin/listener.ora                           
LISTENER_CLONE =
       (DESCRIPTION_LIST =
          (DESCRIPTION =
             (ADDRESS_LIST =
                (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01-vip)(PORT = 1522)
                   (IP = FIRST)
                )
             )
             (ADDRESS_LIST =
                (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01)(PORT = 1522)
                   (IP = FIRST)
                )
             )
             (ADDRESS_LIST =
                (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
             )
          )
        )

    SID_LIST_LISTENER_CLONE =
     (SID_LIST =
       (SID_DESC =
         (GLOBAL_DBNAME = maastb)
         (ORACLE_HOME = /u01/app/oracle/product/11.2.0.3/db_1)
         (SID_NAME = maastb1)
       )
    )    

Além disso, vamos ajustar o TNS do nó standby em estamos conectados para apontar para o hostname e porta correta do listener. Neste caso, mudamos de 1521 para 1522 e para o rac11stb01.

[oracle@rac11stb01 ~]$ vi /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
[oracle@rac11stb01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01.tjsc.jus.br)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11stb01 ~]$

Depois de disso, podemos subir o novo listener e testar o tns (observe que a instância já fica registrada no listener – é isso que queremos):

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 ~]$ /u01/app/grid/11.2.0.3/bin/lsnrctl start LISTENER_CLONE

LSNRCTL for Linux: Version 11.2.0.3.0 - Production on 30-MAR-2014 16:24:46

Copyright (c) 1991, 2011, Oracle.  All rights reserved.

Starting /u01/app/grid/11.2.0.3/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 11.2.0.3.0 - Production
System parameter file is /u01/app/grid/11.2.0.3/network/admin/listener.ora
Log messages written to /u01/app/oracle/diag/tnslsnr/rac11stb01/listener_clone/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.17.42.52)(PORT=1522)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.17.42.48)(PORT=1522)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rac11stb01-vip)(PORT=1522)(IP=FIRST)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER_CLONE
Version                   TNSLSNR for Linux: Version 11.2.0.3.0 - Production
Start Date                30-MAR-2014 16:24:46
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/grid/11.2.0.3/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/rac11stb01/listener_clone/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.17.42.52)(PORT=1522)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.17.42.48)(PORT=1522)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
Services Summary...
Service "tjdgstb" has 1 instance(s).
  Instance "maastb1", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
[oracle@rac11stb01 ~]$
[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/oracle/product/11.2.0.3/db_1
[oracle@rac11stb01 ~]$ tnsping maastb

TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 30-MAR-2014 16:27:09

Copyright (c) 1997, 2011, Oracle.  All rights reserved.

Used parameter files:


Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01.tjsc.jus.br)(PORT = 1522)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = maastb)))
OK (0 msec)
[oracle@rac11stb01 ~]$

Como mudamos o listener e sua porta temporariamente precisamos que isso esteja refletido no pfile que iremos usar para subir a instância. Basta editar o pfile para apontar o parâmetro “remote_lister”para o endereço correto (observe como era e como ficou o parâmetro):

[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep remote_listener
*.remote_listener='rac11stb-scan.tjsc.jus.br:1521'
[oracle@rac11stb01 ~]$                     
[oracle@rac11stb01 ~]$ vi /tmp/pfile-primary-standby.ora
[oracle@rac11stb01 ~]$                             
[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep remote_listener
*.remote_listener='rac11stb01.tjsc.jus.br:1522'
[oracle@rac11stb01 ~]$

Devido a forma como o clone é feito, a origem dos dados (mesmo que você inicie o procedimento da standby) será do primary para o standby. Desta forma, o TNS do primary deve apontar para os endereços configurados nos passos acima para o standby. Faça isso somente em uma instância da primary (na que você vai chamar o RMAN), modifique a porta da entrada para a 1522.

Depois desta configuração inicial, basta iniciar a instância o standby em modo nomount para iniciar o clone. Além disso, podemos testar o PFILE criado e modificado previamente quanto a falhas.

SQL> STARTUP PFILE='/tmp/pfile-primary-standby.ora' NOMOUNT;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size                  2235208 bytes
Variable Size             343934136 bytes
Database Buffers          717225984 bytes
Redo Buffers                5541888 bytes
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters and Real Application Testing options
[oracle@rac11stb01 ~]$  

 Depois disso podemos conectar através do RMAN e realizar o clone do banco de dados. Observe na saída do comando que basicamente ele realiza um backup e um restore do banco de dados. Obviamente que isso tem uma carga considerável e pode demorar também.

Se você comparar com o método anterior a carga é a mesma, mas aqui (caso o seu banco seja grande) poderá acabar concorrendo com a sua carga de trabalho do dia a dia (você faz backup no meio do horário de pico?). Outro detalhe, a origem da conexão é da primary e não é especificada no comando do rman (observe a opção target).

[oracle@rac11pri01 ~]$ rman target sys auxiliary sys@maastb

Recovery Manager: Release 11.2.0.3.0 - Production on Sun Mar 30 17:17:00 2014

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

target database Password:
connected to target database: MAA (DBID=722024964)
auxiliary database Password:
connected to auxiliary database: MAA (not mounted)

RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER NOFILENAMECHECK;

Starting Duplicate Db at 30/03/2014 17:17:10
using target database control file instead of recovery catalog
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=19 instance=maastb1 device type=DISK

contents of Memory Script:
{
   backup as copy reuse
   targetfile  '/u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaa1' auxiliary format
 '/u01/app/oracle/product/11.2.0.3/db_1/dbs/orapwmaastb1'   ;
}
executing Memory Script

Starting backup at 30/03/2014 17:17:11
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=157 instance=maa1 device type=DISK
Finished backup at 30/03/2014 17:17:12

contents of Memory Script:
{
   backup as copy current controlfile for standby auxiliary format  '+DG01/maastb/controlfile/current.265.843606857';
   restore clone controlfile to  '+FRA/maastb/controlfile/current.260.843606857' from
 '+DG01/maastb/controlfile/current.265.843606857';
   sql clone "create spfile from memory";
   shutdown clone immediate;
   startup clone nomount;
   sql clone "alter system set  control_files =
  ''+DG01/maastb/controlfile/current.265.843606857'', ''+FRA/maastb/controlfile/current.260.843606857'' comment=
 ''Set by RMAN'' scope=spfile";
   shutdown clone immediate;
   startup clone nomount;
}
executing Memory Script

Starting backup at 30/03/2014 17:17:14
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
copying standby control file
output file name=/u01/app/oracle/product/11.2.0.3/db_1/dbs/snapcf_maa1.f tag=TAG20140330T171714 RECID=1 STAMP=843585435
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:07
Finished backup at 30/03/2014 17:17:21

Starting restore at 30/03/2014 17:17:22
using channel ORA_AUX_DISK_1

channel ORA_AUX_DISK_1: copied control file copy
Finished restore at 30/03/2014 17:17:26

sql statement: create spfile from memory

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area    1068937216 bytes

Fixed Size                     2235208 bytes
Variable Size                348128440 bytes
Database Buffers             713031680 bytes
Redo Buffers                   5541888 bytes

sql statement: alter system set  control_files =   ''+DG01/maastb/controlfile/current.265.843606857'', ''+FRA/maastb/controlfile/current.260.843606857'' comment= ''Set by RMAN'' scope=spfile

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area    1068937216 bytes

Fixed Size                     2235208 bytes
Variable Size                348128440 bytes
Database Buffers             713031680 bytes
Redo Buffers                   5541888 bytes

contents of Memory Script:
{
   sql clone 'alter database mount standby database';
}
executing Memory Script

sql statement: alter database mount standby database
RMAN-05529: WARNING: DB_FILE_NAME_CONVERT resulted in invalid ASM names; names changed to disk group only.

contents of Memory Script:
{
   set newname for tempfile  1 to
 "+dg01";
   switch clone tempfile all;
   set newname for datafile  1 to
 "+dg01";
   set newname for datafile  2 to
 "+dg01";
   set newname for datafile  3 to
 "+dg01";
   set newname for datafile  4 to
 "+dg01";
   set newname for datafile  5 to
 "+dg01";
   backup as copy reuse
   datafile  1 auxiliary format
 "+dg01"   datafile
 2 auxiliary format
 "+dg01"   datafile
 3 auxiliary format
 "+dg01"   datafile
 4 auxiliary format
 "+dg01"   datafile
 5 auxiliary format
 "+dg01"   ;
   sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to +dg01 in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 30/03/2014 17:18:11
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
input datafile file number=00001 name=+DATA/maa/datafile/system.270.843488557
output file name=+DG01/maastb/datafile/system.264.843606915 tag=TAG20140330T171811
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:05
channel ORA_DISK_1: starting datafile copy
input datafile file number=00002 name=+DATA/maa/datafile/sysaux.269.843488563
output file name=+DG01/maastb/datafile/sysaux.263.843606981 tag=TAG20140330T171811
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:55
channel ORA_DISK_1: starting datafile copy
input datafile file number=00003 name=+DATA/maa/datafile/undotbs1.268.843488567
output file name=+DG01/maastb/datafile/undotbs1.262.843607035 tag=TAG20140330T171811
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00004 name=+DATA/maa/datafile/undotbs2.265.843488579
output file name=+DG01/maastb/datafile/undotbs2.256.843607061 tag=TAG20140330T171811
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00005 name=+DATA/maa/datafile/users.258.843488581
output file name=+DG01/maastb/datafile/users.257.843607085 tag=TAG20140330T171811
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:03
Finished backup at 30/03/2014 17:21:05

sql statement: alter system archive log current

contents of Memory Script:
{
   backup as copy reuse
   archivelog like  "+FRA/maa/archivelog/2014_03_30/thread_2_seq_4.292.843592197" auxiliary format
 "+FRA"   archivelog like
 "+FRA/maa/archivelog/2014_03_30/thread_1_seq_18.537.843607269" auxiliary format
 "+FRA"   archivelog like
 "+FRA/maa/archivelog/2014_03_30/thread_2_seq_5.508.843607269" auxiliary format
 "+FRA"   ;
   catalog clone start with  "+FRA";
   switch clone datafile all;
}
executing Memory Script

Starting backup at 30/03/2014 17:21:11
using channel ORA_DISK_1
channel ORA_DISK_1: starting archived log copy
input archived log thread=2 sequence=4 RECID=8 STAMP=843592197
output file name=+FRA/maastb/archivelog/2014_03_30/thread_2_seq_4.571.843607095 RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:01
channel ORA_DISK_1: starting archived log copy
input archived log thread=1 sequence=18 RECID=9 STAMP=843607269
output file name=+FRA/maastb/archivelog/2014_03_30/thread_1_seq_18.574.843607095 RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:03
channel ORA_DISK_1: starting archived log copy
input archived log thread=2 sequence=5 RECID=10 STAMP=843607270
output file name=+FRA/maastb/archivelog/2014_03_30/thread_2_seq_5.257.843607099 RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:03
Finished backup at 30/03/2014 17:21:18

searching for all files that match the pattern +FRA

List of Files Unknown to the Database
=====================================
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_2_seq_4.571.843607095
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_1_seq_18.574.843607095
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_2_seq_5.257.843607099
cataloging files...
cataloging done

List of Cataloged Files
=======================
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_2_seq_4.571.843607095
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_1_seq_18.574.843607095
File Name: +fra/MAASTB/ARCHIVELOG/2014_03_30/thread_2_seq_5.257.843607099

datafile 1 switched to datafile copy
input datafile copy RECID=1 STAMP=843585503 file name=+DG01/maastb/datafile/system.264.843606915
datafile 2 switched to datafile copy
input datafile copy RECID=2 STAMP=843585503 file name=+DG01/maastb/datafile/sysaux.263.843606981
datafile 3 switched to datafile copy
input datafile copy RECID=3 STAMP=843585503 file name=+DG01/maastb/datafile/undotbs1.262.843607035
datafile 4 switched to datafile copy
input datafile copy RECID=4 STAMP=843585503 file name=+DG01/maastb/datafile/undotbs2.256.843607061
datafile 5 switched to datafile copy
input datafile copy RECID=5 STAMP=843585503 file name=+DG01/maastb/datafile/users.257.843607085

contents of Memory Script:
{
   set until scn  435603;
   recover
   standby
   clone database
    delete archivelog
   ;
}
executing Memory Script

executing command: SET until clause

Starting recover at 30/03/2014 17:21:21
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=145 instance=maastb1 device type=DISK

starting media recovery

archived log for thread 1 with sequence 18 is already on disk as file +FRA/maastb/archivelog/2014_03_30/thread_1_seq_18.574.843607095
archived log for thread 2 with sequence 5 is already on disk as file +FRA/maastb/archivelog/2014_03_30/thread_2_seq_5.257.843607099
archived log file name=+FRA/maastb/archivelog/2014_03_30/thread_1_seq_18.574.843607095 thread=1 sequence=18
archived log file name=+FRA/maastb/archivelog/2014_03_30/thread_2_seq_5.257.843607099 thread=2 sequence=5
media recovery complete, elapsed time: 00:00:01
Finished recover at 30/03/2014 17:21:25
Finished Duplicate Db at 30/03/2014 17:21:48

RMAN>

Vamos analisar a saída dos comandos acima, ele começa com um backup do password file do primary para o standby. Depois temos um script executado na standby com:

  • Backup do controlfile da primary (backup para standby).
  • Clone do spfile da standby.
  • Restart da instância (por isso o clone anterior).
  • Correção dos controlfiles na standby;
  • Novo restart da standby.
  • Por fim, clone da primary para a standby;

Durante o backup e restore o input é +DATA e o destino é +DG01. Isso quer dizer que ele seguiu como base o que foi definido no pfile que fez o startup da standby (você também pode verificar isso no alert da standby).

Observe a quantidade de vezes que ocorreu shutdown e startup na standby, para que isso ocorra com sucesso você precisa de um registro direto no listener. Está ai o motivo para criarmos o listener e registrarmos manualmente a instância nele.

Depois do clone concluir com sucesso é hora de colocar ordem na casa, corrigir os tnsnames e remover listener criado. No lado do primary (em ambos os nós) corrija os tns para apontar para o endereço correto (observe a definição “MAASTB”):

[oracle@rac11pri01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01.tjsc.jus.br)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11pri01 ~]$ vi /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
[oracle@rac11pri01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11pri01 ~]$

Arrume o parâmetro remote_listener do pfile da standby:

[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep remote_listener
*.remote_listener='rac11stb01.tjsc.jus.br:1522'
[oracle@rac11stb01 ~]$ vi /tmp/pfile-primary-standby.ora
[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep remote_listener
*.remote_listener='rac11stb-scan.tjsc.jus.br:1521'
[oracle@rac11stb01 ~]$

Removendo o listener utilizado no clone da standby:

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 ~]$ lsnrctl stop LISTENER_CLONE

LSNRCTL for Linux: Version 11.2.0.3.0 - Production on 30-MAR-2014 18:32:26

Copyright (c) 1991, 2011, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rac11stb01-vip)(PORT=1522)(IP=FIRST)))
The command completed successfully
[oracle@rac11stb01 ~]$
[oracle@rac11stb01 ~]$
[oracle@rac11stb01 ~]$ cat /u01/app/grid/11.2.0.3/network/admin/listener.ora
LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))))            # line added by Agent
LISTENER_SCAN3=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN3))))                # line added by Agent
LISTENER_SCAN2=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN2))))                # line added by Agent
LISTENER_SCAN1=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN1))))                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN1=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN2=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN3=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON              # line added by Agent


LISTENER_CLONE =
   (DESCRIPTION_LIST =
      (DESCRIPTION =
         (ADDRESS_LIST =
            (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01-vip)(PORT = 1522)
               (IP = FIRST)
            )
         )
         (ADDRESS_LIST =
            (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01)(PORT = 1522)
               (IP = FIRST)
            )
         )
         (ADDRESS_LIST =
            (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
         )
      )
    )

SID_LIST_LISTENER_CLONE =
 (SID_LIST =
   (SID_DESC =
     (GLOBAL_DBNAME = maastb)
     (ORACLE_HOME = /u01/app/oracle/product/11.2.0.3/db_1)
     (SID_NAME = maastb1)
   )
)
[oracle@rac11stb01 ~]$ vi /u01/app/grid/11.2.0.3/network/admin/listener.ora
[oracle@rac11stb01 ~]$ cat /u01/app/grid/11.2.0.3/network/admin/listener.ora
LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))))            # line added by Agent
LISTENER_SCAN3=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN3))))                # line added by Agent
LISTENER_SCAN2=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN2))))                # line added by Agent
LISTENER_SCAN1=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN1))))                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN1=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN2=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN3=ON                # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON              # line added by Agent


[oracle@rac11stb01 ~]$

E corrigindo o tns da standby

[oracle@rac11stb01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb01.tjsc.jus.br)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11stb01 ~]$ vi /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
[oracle@rac11stb01 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/network/admin/tnsnames.ora
MAA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11pri-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maa)
    )
  )

MAASTB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = rac11stb-scan.tjsc.jus.br)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = maastb)
    )
  )

[oracle@rac11stb01 ~]$

Pronto, depois destes passos você tem um standby criado através de um active database. O restart da instância fica para depois (já que ainda não terminamos o processo).

Clone através de MML

O procedimento é o mesmo do duplicate (sem active database), mas aqui especificando os canais para a fita. O detalhe é que você tem que ter habilitado o standby na sua MML. Peço que observe como os canais foram configurados, temos um canal que aponta para a fita e um segundo canal para disco específico para o controlfile.

Comando a ser executado:
    rman target sys/XXXXXXXX@oselocpd auxiliary sys/XXXXXX@oselo

    run {
    ALLOCATE AUXILIARY CHANNEL t1 DEVICE TYPE 'SBT_TAPE' PARMS 'ENV=(NSR_SERVER=mml-server,NSR_CLIENT=selodigital-st,NSR_DPRINTF=TRUE, NSR_DEBUG_FILE=/tmp/t1.log,NSR_DEBUG_LEVEL=2)';
    ALLOCATE AUXILIARY CHANNEL d1 DEVICE TYPE DISK FORMAT = '/tmp/bkp-ctf-D-%d-DBID-%I-T-%T-NB-%s.bkp';
    DUPLICATE TARGET DATABASE FOR STANDBY NOFILENAMECHECK;
    }    

-bash-3.00$ rman target sys/XXXXXXX@oselocpd auxiliary sys/XXXXXXX@oselo

Recovery Manager: Release 10.2.0.5.0 - Production on Wed Aug 7 17:10:32 2013

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

connected to target database: OSELO (DBID=2831035320)
connected to auxiliary database: OSELO (not mounted)

RMAN> run {
ALLOCATE AUXILIARY CHANNEL t1 DEVICE TYPE 'SBT_TAPE' PARMS 'ENV=(NSR_SERVER=mml-server,NSR_CLIENT=selodigital-st,NSR_DPRINTF=TRUE, NSR_DEBUG_FILE=/tmp/t1.log,NSR_DEBUG_LEVEL=2)';
2> 3> ALLOCATE AUXILIARY CHANNEL d1 DEVICE TYPE DISK FORMAT = '/tmp/bkp-ctf-D-%d-DBID-%I-T-%T-NB-%s.bkp';
DUPLICATE TARGET DATABASE FOR STANDBY NOFILENAMECHECK;
4> 5> }

using target database control file instead of recovery catalog
allocated channel: t1
channel t1: sid=155 devtype=SBT_TAPE
channel t1: NMO v5.0.0.0

allocated channel: d1
channel d1: sid=154 devtype=DISK

Starting Duplicate Db at 07-AUG-13

contents of Memory Script:
{
   restore clone standby controlfile;
   sql clone 'alter database mount standby database';
}
executing Memory Script

Starting restore at 07-AUG-13

channel d1: starting datafile backupset restore
channel d1: restoring control file
channel d1: reading from backup piece /tmp/bkp-ctf-D-OSELO-DBID-2831035320-T-20130807-NB-6297.bkp
channel d1: restored backup piece 1
piece handle=/tmp/bkp-ctf-D-OSELO-DBID-2831035320-T-20130807-NB-6297.bkp tag=BKP-FULL-CONTROL-STB
channel d1: restore complete, elapsed time: 00:00:11
output filename=+DATA/oselo/controlfile/current.280.822849075
output filename=+DATA/oselo/controlfile/current.279.822849075
Finished restore at 07-AUG-13

sql statement: alter database mount standby database
WARNING: DB_FILE_NAME_CONVERT resulted in invalid ASM names; names changed to diskgroup only.

contents of Memory Script:
{
   set newname for tempfile  1 to
 "+data";
   switch clone tempfile all;
   set newname for datafile  1 to
 "+data";
   set newname for datafile  2 to
 "+data";
   set newname for datafile  3 to
 "+data";
   set newname for datafile  4 to
 "+data";
   set newname for datafile  5 to
 "+data";
   set newname for datafile  6 to
 "+data";
   set newname for datafile  7 to
 "+data";
   set newname for datafile  8 to
 "+data";
   set newname for datafile  9 to
 "+data";
   restore
   check readonly
   clone database
   ;
}
executing Memory Script

executing command: SET NEWNAME

renamed temporary file 1 to +data in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting restore at 07-AUG-13

channel t1: starting datafile backupset restore
channel t1: specifying datafile(s) to restore from backup set
restoring datafile 00007 to +DATA
restoring datafile 00008 to +DATA
channel t1: reading from backup piece bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6288.bkp
channel t1: restored backup piece 1
piece handle=bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6288.bkp tag=BKP-INCR0-DB
channel t1: restore complete, elapsed time: 01:09:16
channel t1: starting datafile backupset restore
channel t1: specifying datafile(s) to restore from backup set
restoring datafile 00001 to +DATA
restoring datafile 00002 to +DATA
restoring datafile 00003 to +DATA
restoring datafile 00004 to +DATA
restoring datafile 00005 to +DATA
restoring datafile 00006 to +DATA
channel t1: reading from backup piece bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6289.bkp
channel t1: restored backup piece 1
piece handle=bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6289.bkp tag=BKP-INCR0-DB
channel t1: restore complete, elapsed time: 00:50:46
channel t1: starting datafile backupset restore
channel t1: specifying datafile(s) to restore from backup set
restoring datafile 00009 to +DATA
channel t1: reading from backup piece bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6290.bkp
channel t1: restored backup piece 1
piece handle=bkpi0-data-D-OSELO-DBID-2831035320-T-20130806-NB-6290.bkp tag=BKP-INCR0-DB
channel t1: restore complete, elapsed time: 00:04:45
Finished restore at 07-AUG-13

contents of Memory Script:
{
   switch clone datafile all;
}
executing Memory Script

datafile 1 switched to datafile copy
input datafile copy recid=220 stamp=822856580 filename=+DATA/oselo/datafile/system.273.822853265
datafile 2 switched to datafile copy
input datafile copy recid=221 stamp=822856580 filename=+DATA/oselo/datafile/undotbs1.274.822853263
datafile 3 switched to datafile copy
input datafile copy recid=222 stamp=822856580 filename=+DATA/oselo/datafile/sysaux.1172.822853265
datafile 4 switched to datafile copy
input datafile copy recid=223 stamp=822856580 filename=+DATA/oselo/datafile/users.263.822853265
datafile 5 switched to datafile copy
input datafile copy recid=224 stamp=822856581 filename=+DATA/oselo/datafile/tsselodigdat.276.822853251
datafile 6 switched to datafile copy
input datafile copy recid=225 stamp=822856581 filename=+DATA/oselo/datafile/tsselodigidx.275.822853259
datafile 7 switched to datafile copy
input datafile copy recid=226 stamp=822856581 filename=+DATA/oselo/datafile/tsselodigarqprotarqlob4k.278.822849095
datafile 8 switched to datafile copy
input datafile copy recid=227 stamp=822856582 filename=+DATA/oselo/datafile/tsselodigarqprotreclob4k.277.822849107
datafile 9 switched to datafile copy
input datafile copy recid=228 stamp=822856582 filename=+DATA/oselo/datafile/tsselodigarqprotarqlob2k.1011.822856297
Finished Duplicate Db at 07-AUG-13
released channel: t1
released channel: d1

RMAN>

MONTANDO A BASE DE DADOS

Depois de clonar o banco você pode montar o banco de dados. Eu recomento realizar um shutdown do standby e um startup com o pfile, principalmente pela necessidade de corrigir o parâmetro que aponta para os controlfiles. Existe a necessidade de correção, pois com OFA, no restore/clone novos nomes são gerados.

Para verificar, basta ir no ASM identificar eles e corrigir o pfile:

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 ~]$ export ORACLE_SID=+ASM1
[oracle@rac11stb01 ~]$ asmcmd
ASMCMD> ls +DG01/MAASTB/CONTROLFILE/
Current.265.843606857
ASMCMD> ls +FRA/MAASTB/CONTROLFILE/
Current.260.843606857
ASMCMD> exit
[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep control
*.control_files='+DG01/maastb/controlfile/current.273.843488553','+FRA/maastb/controlfile/current.256.843488553'
[oracle@rac11stb01 ~]$
[oracle@rac11stb01 ~]$ vi /tmp/pfile-primary-standby.ora
[oracle@rac11stb01 ~]$ cat /tmp/pfile-primary-standby.ora |grep control
*.control_files='+DG01/maastb/controlfile/current.265.843606857','+FRA/maastb/controlfile/current.260.843606857'
[oracle@rac11stb01 ~]$

Após a edição do pfile, a base standby pode ser montada (uma instância só até o momento).

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/oracle/product/11.2.0.3/db_1
[oracle@rac11stb01 ~]$ export ORACLE_SID=maastb1
[oracle@rac11stb01 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Sun Mar 30 19:01:38 2014

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

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management and Real Application Testing options

SQL> shutdown immediate;
ORA-01109: database not open


Database dismounted.
ORACLE instance shut down.
SQL> STARTUP PFILE='/tmp/pfile-primary-standby.ora' MOUNT;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size                  2235208 bytes
Variable Size             343934136 bytes
Database Buffers          717225984 bytes
Redo Buffers                5541888 bytes
Database mounted.
SQL>

Pronto, agora você tem uma instância standby criada e montada através de um clone da primary que já aponta para os controlfiles corretos.

STANDBY LOGS

Você até poderia habilitar o DG, mas não estaria como desejamos, você não conseguiria abrir ela com um grau de proteção ideal para MAA. Para que isso seja possível, temos que criar o os standby redo logs.

Standby redo logs são idênticos aos redo logs. Eles são utilizados como destino das informações (de redo) recebidas da primary. Quando ocorre um log switch na primary, existe um standby redo log switch na standby e este é arquivado através de um processo ARCn (você pode ler isso no documento Oracle Data Guard Concepts and Administration).

Na documentação fica claro a necessidade de criar um standby redo log a mais do que os redo log groups existentes na primary. Existe uma fórmula para calcular o número correto em um ambiente RAC:

  • ( (# de redo logs por instância) + 1 ) x ( # de instâncias ) (Referência existente neste documento)

Em um ambiente com duas instâncias que tem 2 grupos você teria que criar 6 standby redo logs. Sendo que estes seriam divididos em 3 grupos por instância. Vejamos no nosso caso:

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL>
SQL> SELECT group#, thread# FROM v$standby_log;

    GROUP#    THREAD#
---------- ----------
         5          1
         6          1
         7          1
         8          2
         9          2
        10          2

6 rows selected.

SQL>

Para verificar como ficamos poder executar o SQL abaixo. Observe a quantidade e standby logs grupous:

SQL> COL MEMBER FORMAT A60
SQL> SELECT group#, type, member FROM v$logfile;

    GROUP# TYPE    MEMBER
---------- ------- ------------------------------------------------------------
         1 ONLINE  +DATA/maa/onlinelog/group_1.272.843488553
         1 ONLINE  +FRA/maa/onlinelog/group_1.286.843488555
         2 ONLINE  +DATA/maa/onlinelog/group_2.271.843488555
         2 ONLINE  +FRA/maa/onlinelog/group_2.285.843488555
         3 ONLINE  +DATA/maa/onlinelog/group_3.257.843489101
         3 ONLINE  +FRA/maa/onlinelog/group_3.284.843489101
         4 ONLINE  +DATA/maa/onlinelog/group_4.262.843489103
         4 ONLINE  +FRA/maa/onlinelog/group_4.283.843489103
         5 STANDBY +DATA/maa/onlinelog/group_5.263.843615365
         5 STANDBY +FRA/maa/onlinelog/group_5.289.843615367
         6 STANDBY +DATA/maa/onlinelog/group_6.261.843615373

    GROUP# TYPE    MEMBER
---------- ------- ------------------------------------------------------------
         6 STANDBY +FRA/maa/onlinelog/group_6.670.843615373
         7 STANDBY +DATA/maa/onlinelog/group_7.260.843615379
         7 STANDBY +FRA/maa/onlinelog/group_7.263.843615379
         8 STANDBY +DATA/maa/onlinelog/group_8.259.843615383
         8 STANDBY +FRA/maa/onlinelog/group_8.703.843615385
         9 STANDBY +DATA/maa/onlinelog/group_9.256.843615389
         9 STANDBY +FRA/maa/onlinelog/group_9.504.843615389
        10 STANDBY +DATA/maa/onlinelog/group_10.274.843615393
        10 STANDBY +FRA/maa/onlinelog/group_10.496.843615393

20 rows selected.

SQL>

Estes grupos também precisam ser criados no standby, utilize a formula anterior, mas como temos o mesmo número de instâncias eles são criados em igual número.

[oracle@rac11stb01 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Sun Mar 30 19:39:19 2014

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management and Real Application Testing options

SQL> select instance_name FROM v$instance;

INSTANCE_NAME
----------------
maastb1

SQL> SELECT group#, thread#, bytes FROM v$log;

    GROUP#    THREAD#      BYTES
---------- ---------- ----------
         1          1   52428800
         2          1   52428800
         3          2   52428800
         4          2   52428800

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL> ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 SIZE 52428800;

Database altered.

SQL> SELECT group#, thread# FROM v$standby_log;

    GROUP#    THREAD#
---------- ----------
         5          1
         6          1
         7          1
         8          2
         9          2
        10          2

6 rows selected.

SQL> COL MEMBER FORMAT a50
SQL> SELECT group#, type, member FROM v$logfile;

    GROUP# TYPE    MEMBER
---------- ------- --------------------------------------------------
         1 ONLINE  +DG01/maastb/onlinelog/group_1.268.843607109
         1 ONLINE  +FRA/maastb/onlinelog/group_1.579.843607111
         2 ONLINE  +DG01/maastb/onlinelog/group_2.269.843607115
         2 ONLINE  +FRA/maastb/onlinelog/group_2.568.843607117
         3 ONLINE  +DG01/maastb/onlinelog/group_3.270.843607121
         3 ONLINE  +FRA/maastb/onlinelog/group_3.564.843607123
         4 ONLINE  +DG01/maastb/onlinelog/group_4.271.843607125
         4 ONLINE  +FRA/maastb/onlinelog/group_4.562.843607129
         5 STANDBY +DG01/maastb/onlinelog/group_5.267.843615577
         5 STANDBY +FRA/maastb/onlinelog/group_5.559.843615581
         6 STANDBY +DG01/maastb/onlinelog/group_6.266.843615585

    GROUP# TYPE    MEMBER
---------- ------- --------------------------------------------------
         6 STANDBY +FRA/maastb/onlinelog/group_6.553.843615589
         7 STANDBY +DG01/maastb/onlinelog/group_7.261.843615593
         7 STANDBY +FRA/maastb/onlinelog/group_7.604.843615595
         8 STANDBY +DG01/maastb/onlinelog/group_8.260.843615599
         8 STANDBY +FRA/maastb/onlinelog/group_8.600.843615601
         9 STANDBY +DG01/maastb/onlinelog/group_9.259.843615607
         9 STANDBY +FRA/maastb/onlinelog/group_9.611.843615611
        10 STANDBY +DG01/maastb/onlinelog/group_10.258.843615615
        10 STANDBY +FRA/maastb/onlinelog/group_10.591.843615617

20 rows selected.

SQL>

Assim, temos tanto o primary e standby configurados para permitir o envio correto de redo entre eles. Criamos os standby redo logs na primary para garantir que em uma eventual troca de roles já esteja tudo correto.

SPFILE/PFILE STANDBY

Independente da forma como você clona o standby tanto o spfile quanto o pfile estarão errados quanto ao seu destino, você terá que corrigir o caminho deles. Na base standby você vera que o spfile não existe:

SQL> SHOW PARAMETER spfile

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
spfile                               string
SQL>

A primeira coisa a ser feita é criar o SPFILE no local correto, neste caso estamos armazenando ele no ASM. A origem do SPFILE será o PFILE que editamos em passos anteriores e utilizamos para fazer o startup da standby:

SQL> CREATE spfile = '+DG01' FROM pfile = '/tmp/pfile-primary-standby.ora';

File created.

SQL>

Infelizmente nem tudo são flores e o SPFILE fica errado no ASM e precisa ser corrigido. O erro está no fato de que o alias que aponta para o parameterfile não ser criado. Observe:

[oracle@rac11stb01 ~]$ export ORACLE_SID=+ASM1
[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 ~]$ asmcmd
ASMCMD> cd +DG01
ASMCMD> cd maastb
ASMCMD> ls -l
Type  Redund  Striped  Time             Sys  Name
                                        Y    CONTROLFILE/
                                        Y    DATAFILE/
                                        Y    ONLINELOG/
                                        Y    PARAMETERFILE/
ASMCMD> ls -l PARAMETERFILE/
Type           Redund  Striped  Time             Sys  Name
PARAMETERFILE  UNPROT  COARSE   APR 10 01:00:00  Y    spfile.273.844479295
ASMCMD>
ASMCMD> mkalias +DG01/maastb/PARAMETERFILE/spfile.273.844479295 spfilemaastb.ora
ASMCMD> ls -l
Type           Redund  Striped  Time             Sys  Name
                                                 Y    CONTROLFILE/
                                                 Y    DATAFILE/
                                                 Y    ONLINELOG/
                                                 Y    PARAMETERFILE/
                                                 N    spfilemaastb.ora => +DG01/MAASTB/PARAMETERFILE/spfile.273.844479295
ASMCMD>

Depois disso, o seu caminho do SPFILE dentro do ASM está correto e apontando para o arquivo desejado. Agora basta corrigir a pasta “dbs” existente dentro do ORACLE_HOME da instância. Lá deve ser criado um pfile/init que aponta para o SPFILE do ASM.

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/oracle/product/11.2.0.3/db_1
[oracle@rac11stb01 ~]$ cd $ORACLE_HOME/dbs
[oracle@rac11stb01 dbs]$ ls -l
total 28
-rw-rw---- 1 oracle oinstall  1544 Apr  9 19:27 hc_maastb1.dat
-rw-r--r-- 1 oracle oinstall  2851 May 15  2009 init.ora
-rw-r----- 1 oracle oinstall  1536 Mar 30 17:14 orapwmaastb1
-rw-r----- 1 oracle oinstall 15872 Mar 30 17:15 spfilemaastb1.ora
[oracle@rac11stb01 dbs]$
[oracle@rac11stb01 dbs]$ rm spfilemaastb1.ora
[oracle@rac11stb01 dbs]$
[oracle@rac11stb01 dbs]$
[oracle@rac11stb01 dbs]$ vi initmaastb1.ora
[oracle@rac11stb01 dbs]$ cat initmaastb1.ora
SPFILE='+DG01/maastb/spfilemaastb.ora'
[oracle@rac11stb01 dbs]$ 

Se você observar, já existe um arquivo spfile da base standby, infelizmente em um ambiente RAC ele deve residir em um local compartilhado. Assim, removemos ele da pasta DBS. Além disso, precisamos corrigir a pasta “dbs” do outro nó do RAC. Copiamos o arquivo do nó 1 para este nó (observe o nome correto do arquivo de destino):

[oracle@rac11stb02 ~]$ cd $ORACLE_HOME/dbs
[oracle@rac11stb02 dbs]$ pwd
/u01/app/oracle/product/11.2.0.3/db_1/dbs
[oracle@rac11stb02 dbs]$ ls -l
total 12
-rw-rw---- 1 oracle oinstall 1544 Mar 30 15:39 hc_maastb2.dat
-rw-r--r-- 1 oracle oinstall 2851 Aug 18  2013 init.ora
[oracle@rac11stb02 dbs]$
[oracle@rac11stb02 dbs]$ scp oracle@rac11stb01:/u01/app/oracle/product/11.2.0.3/db_1/dbs/initmaastb1.ora initmaastb2.ora
initmaastb1.ora                                                                                                                                                                                            100%   39     0.0KB/s   00:00
[oracle@rac11stb02 dbs]$

Por fim, vamos testar o spfile da standby que está no local correto agora:

[oracle@rac11stb02 ~]$ cd $ORACLE_HOME/dbs
[oracle@rac11stb02 dbs]$ pwd
/u01/app/oracle/product/11.2.0.3/db_1/dbs
[oracle@rac11stb02 dbs]$ ls -l
total 12
-rw-rw---- 1 oracle oinstall 1544 Mar 30 15:39 hc_maastb2.dat
-rw-r--r-- 1 oracle oinstall 2851 Aug 18  2013 init.ora
[oracle@rac11stb02 dbs]$
[oracle@rac11stb02 dbs]$ scp oracle@rac11stb01:/u01/app/oracle/product/11.2.0.3/db_1/dbs/initmaastb1.ora initmaastb2.ora
initmaastb1.ora                                                                                                                                                                                            100%   39     0.0KB/s   00:00
[oracle@rac11stb02 dbs]$
Por fim, vamos testar o spfile da standby que está no local correto agora:
[oracle@rac11stb01 ~]$ export ORACLE_SID=maastb1
[oracle@rac11stb01 ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.3.0 Production on Wed Apr 9 19:48:46 2014

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management and Real Application Testing options

SQL> SHOW PARAMETER spfile

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
spfile                               string
SQL> SHUTDOWN IMMEDIATE;
ORA-01109: database not open


Database dismounted.
ORACLE instance shut down.
SQL>
SQL>
SQL>
SQL> STARTUP MOUNT;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size                  2235208 bytes
Variable Size             343934136 bytes
Database Buffers          717225984 bytes
Redo Buffers                5541888 bytes
Database mounted.
SQL>
SQL>
SQL> SHOW PARAMETER spfile;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
spfile                               string      +DG01/maastb/spfilemaastb.ora
SQL>

REINICIANDO A PRIMARY

Até o momento temos um ambiente onde existe um standby que foi clonado da primary e está configurado para receber os redologs enviados da primary. O banco primary foi configurado para enviar os dados para o standby, mas isso ainda não foi habilitado.

Se você revisar os passos até aqui irá perceber que somente configuramos os parâmetros da primary no spfile. Fizemos toda a configuração sem qualquer interrupção da primary, sem downtime. Precisamos agora reiniciar o banco do primary para que os parâmetros modificados passem a valer.

Eu recomendo fazer isso com a base parada em ambos os nós. Recomendo abrir uma segunda seção a instância que irá subir a base primary para acompanhar o seu alert.log. Observe os passos abaixo:

[oracle@rac11pri01 ~]$ srvctl stop database -d maa -o immediate
[oracle@rac11pri01 ~]$
[oracle@rac11pri01 ~]$ srvctl start instance -d maa -i maa1
[oracle@rac11pri01 ~]$

No alert (cropado para só mostrar pontos importantes):
    [root@rac11pri01 ~]# tail -f /u01/app/oracle/diag/rdbms/maa/maa1/trace/alert_maa1.log
    NOTE: force a map free for map id 3992
    Thu Apr 10 02:32:27 2014
    Stopping background process VKTM
    NOTE: force a map free for map id 3991
    Thu Apr 10 02:32:28 2014
    NOTE: Shutting down MARK background process
    Thu Apr 10 02:32:33 2014
    freeing rdom 0
    Thu Apr 10 02:32:36 2014
    Instance shutdown complete
    ...
    ...            
    Starting up:
    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
    ...
    ...
    Using parameter settings in server-side pfile /u01/app/oracle/product/11.2.0.3/db_1/dbs/initmaa1.ora
    System parameters with non-default values:
      processes                = 150
      spfile                   = "+DATA/maa/spfilemaa.ora"
      sga_target               = 1G
      control_files            = "+DATA/maa/controlfile/current.273.843488553"
      control_files            = "+FRA/maa/controlfile/current.256.843488553"
      db_file_name_convert     = "+DG01/maastb"
      db_file_name_convert     = "+DATA/maa"
      db_file_name_convert     = "+FRA/maastb"
      db_file_name_convert     = "+FRA/maa"
      log_file_name_convert    = "+DG01/maastb"
      log_file_name_convert    = "+DATA/maa"
      log_file_name_convert    = "+FRA/maastb"
      log_file_name_convert    = "+FRA/maa"
      db_block_size            = 8192
      compatible               = "11.2.0.0.0"
      log_archive_dest_1       = "LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=maa"
      log_archive_dest_2       = "SERVICE=maastb SYNC AFFIRM LGWR VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=maastb"
      log_archive_dest_state_2 = "DEFER"
      fal_server               = "MAASTB"
      log_archive_config       = "DG_CONFIG=(maa,maastb)"
      log_archive_format       = "arch_%t_%s_%r.arc"
      cluster_database         = TRUE
      db_create_file_dest      = "+DATA"
      db_recovery_file_dest    = "+FRA"
      db_recovery_file_dest_size= 10G
      standby_file_management  = "AUTO"
      thread                   = 1
      undo_tablespace          = "UNDOTBS1"
      instance_number          = 1
      remote_login_passwordfile= "EXCLUSIVE"
      db_domain                = ""
      remote_listener          = "rac11pri-scan.tjsc.jus.br:1521"
      audit_file_dest          = "/u01/app/oracle/admin/maa/adump"
      audit_trail              = "DB"
      db_name                  = "maa"
      db_unique_name           = "maa"
      open_cursors             = 300
      pga_aggregate_target     = 256M
      diagnostic_dest          = "/u01/app/oracle"
    ...
    ...
    Reconfiguration started (old inc 0, new inc 2)
    List of instances:
     1 (myinst: 1)
    ...
    ...            
    ALTER DATABASE OPEN /* db agent *//* {1:22542:638} */
    This instance was first to open
    ...
    ...
    ARC2: Becoming the 'no FAL' ARCH
    ARC2: Becoming the 'no SRL' ARCH
    ARC1: Becoming the heartbeat ARCH
    Thu Apr 10 02:36:35 2014
    ARC3 started with pid=36, OS id=16657
    ARC3: Archival started
    ARC0: STARTING ARCH PROCESSES COMPLETE
    ...
    ...
    Completed: ALTER DATABASE OPEN /* db agent *//* {1:22542:638} */
    Thread 1 advanced to log sequence 39 (LGWR switch)
      Current log# 1 seq# 39 mem# 0: +DATA/maa/onlinelog/group_1.272.843488553
      Current log# 1 seq# 39 mem# 1: +FRA/maa/onlinelog/group_1.286.843488555
    Starting background process SMCO
    ...
    ...

Observe que não tivemos qualquer problema em abrir a base. Peço que analise com atenção a saída que mostrada acima, principalmente nos parâmetros que fazem referência ao DG (destaquei eles em negrito). Depois, basta subir a instância nos outros nós.

PROTECTION

Agora chegamos a mais um ponto importante na definição do nosso ambiente, a definição do grau de proteção do nosso ambiente. Existem três modos que descreverei abaixo, cada um tem seu grau de proteção e você deve avaliar qual o melhor para o seu ambiente.

  • MAXIMUM PROTECTION: Neste modo ambas as bases primary e standby estão completamente sincronizadas, nenhuma transação é perdida ou deixa de ser enviada para o standby. Infelizmente isso tem um custo, caso o standby tenha alguma falha e fique indisponível, o primary também fica indisponível.
  • MAXIMUM AVAILABILITY: Este modo trabalha de forma semelhante ao anterior, mas permite que ocorra a indisponibilidade do standby sem que isso afete o primary. Assim, o primary continua disponível para os usuários e na volta do standby ele envia os archives para que a sincronia seja restabelecida. Um detalhe, caso o standby esteja fora e ocorra uma falha no primary (perda do Storage por exemplo), as transações que não foram enviadas foram perdidas e você terá “data loss”.
  • MAXIMUM PERFORMANCE: Aqui os archives são transferidos de maneira assíncrona entre o primary e o standby. Você deve estar ciente que está trabalhando com a possibilidade de perda de dados, caso ocorra uma falha com o primary você terá perdido informação.

A escolha do modo de proteção depende do projeto/ambiente que está montando, claro que a criticidade dos seus dados também influencia na escolha. Existe uma relação que as vezes não fica clara (principalmente a gestores) que quanto maior o grau de proteção, mais garantias você tem que ter sobre o seu ambiente. Não adianta montar um DG com MAXIMUM PROTECTION em um ambiente que não lhe dá as mesmas garantias do primary.

Aqui vamos utilizar e configurar o DG em MAXIMUM AVAILABILITY, você terá uma garantia de sincroniza entre primary e standby em tempo real. Isso sem deixar o seu ambiente indisponível caso seu standby resolva acordar de mau humor.

Para que possamos ter isso precisamos configurar o modo de proteção do primary, por padrão ele vem em MAXIMUM PROTECTION, precisamos aumentar isso. Observe os comandos abaixo:

SQL> SELECT protection_mode, protection_level FROM v$database;

PROTECTION_MODE      PROTECTION_LEVEL
-------------------- --------------------
MAXIMUM PERFORMANCE  MAXIMUM PERFORMANCE

SQL> ALTER DATABASE SET STANDBY TO MAXIMIZE AVAILABILITY;

Database altered.

SQL> SELECT protection_mode, protection_level FROM v$database;

PROTECTION_MODE      PROTECTION_LEVEL
-------------------- --------------------
MAXIMUM AVAILABILITY RESYNCHRONIZATION

SQL>

LIGANDO O STANDBY

Configurar modo de proteção não é tudo, você precisa fazer com que seu standy entenda que ele é um standby, explico. Até o momento você tem um clone do seu ambiente primary e só isso. Você não disse a ele que é um standby, as configurações que foram feitas no spfile não dizem nada.

Antes disso, precisamos ajustar um detalhe do seu banco standby. Quando você clonou seu banco para o standby o processo o deixou com o flashback desligado. Assim, recomendo ligar ele para evitar problemas futuros (em eventuais trocas de papeis entre primary e standby):

SQL> SELECT log_mode, flashback_on FROM v$database;

LOG_MODE     FLASHBACK_ON
------------ ------------------
ARCHIVELOG   NO

SQL> ALTER DATABASE FLASHBACK ON;

Database altered.

SQL> SELECT log_mode, flashback_on FROM v$database;

LOG_MODE     FLASHBACK_ON
------------ ------------------
ARCHIVELOG   YES

SQL>

Depois disso você pode dizer ao banco clonado que ele é um standby:

SQL> SELECT instance_name, status FROM v$instance;

INSTANCE_NAME    STATUS
---------------- ------------
maastb1          MOUNTED

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;

Database altered.

SQL>

Vamos entender o que aconteceu aqui. Primeiro, temos o seguinte comando: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT; Isso nos diz que o banco ficará em estado de recuperação para ser standby (RECOVER MANAGED STANDBY DATABASE) e utilizará o logfile para sincronia (USING CURRENT LOGFILE) e o comando retornará ao prompt ao fim da execução (DISCONNECT).

Indo um pouco além, você poderia não ter utilizado a opção USING CURRENT LOGFILE, mas desde o início foi dito que iríamos utilizar real-time apply. Mas o que é o real-time apply? Vou deixar a definição da documentação:

If the real-time apply feature is enabled, apply services can apply redo data as it is received, without waiting for the current standby redo log file to be archived. This results in faster switchover and failover times because the standby redo log files have been applied already to the standby database by the time the failover or switchover begins.

Acredito que a definição seja clara, mas resumindo, o que acontecer no redo da primary é enviado ao standby (aos standby red logs do banco standby) e já aplicado diretamente na base antes de esperar o swicthover de redo da primary. Isso é bem interessante, pois permite uma troca de papeis bem mais rápida para o standby.

Claro que isso tem algumas implicações, no DG você pode definir um tempo (delay) quando uma transação ocorre no primary e quando ela é aplicada no standby. Com real-time apply essa definição é ignorada. Além disso, para utilizar real-time apply é necessário operar em modo síncrono o envio de redo para o standby e utilizar standby redo logs.

A título de curiosidade, deixo o que apareceu no alert.log da instância standby no momento que executamos o comando acima:

[oracle@rac11stb01 ~]$ tail -f /u01/app/oracle/diag/rdbms/maastb/maastb1/trace/alert_maastb1.log
database for recovery-related files, and does not reflect the amount of
space available in the underlying filesystem or ASM diskgroup.
Sat Apr 12 08:51:08 2014
ALTER DATABASE FLASHBACK ON
Sat Apr 12 08:51:10 2014
RVWR started with pid=31, OS id=23476
Allocated 3981120 bytes in shared pool for flashback generation buffer
Sat Apr 12 08:51:20 2014
Flashback Database Enabled at SCN 435603
Completed: ALTER DATABASE FLASHBACK ON
Sat Apr 12 08:56:26 2014
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT
Attempt to start background Managed Standby Recovery process (maastb1)
Sat Apr 12 08:56:26 2014
MRP0 started with pid=36, OS id=23650
MRP0: Background Managed Standby Recovery process started (maastb1)
 started logmerger process
Sat Apr 12 08:56:31 2014
Managed Standby Recovery starting Real Time Apply
Parallel Media Recovery started with 2 slaves
Waiting for all non-current ORLs to be archived...
All non-current ORLs have been archived.
Sat Apr 12 08:56:33 2014
Media Recovery Waiting for thread 1 sequence 19
Completed: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT

SINCRONIZANDO

Até agora tudo está tranquilo e temos um banco primary configurado, esperando que o standby esteja preparado para operar em MAXIMUM AVAILABILITY. Para tal ele espera enviar os dados de forma síncrona ao standby. No lado do standby temos um banco configurado e já esperando receber as informações do primary.

Assim, chegou a hora de ligar a sincronia entre os lados. Se você observar os passos anteriores verá que o destino dos archives que aponta para o standby está desligado, nada foi transferido até o momento. Observe abaixo:

SQL> SELECT inst_id, name, value FROM gv$parameter WHERE name = 'log_archive_dest_2';

   INST_ID NAME                           VALUE
---------- ------------------------------ ------------------------------
         1 log_archive_dest_2             SERVICE=maastb SYNC AFFIRM LGW
                                          R VALID_FOR=(ONLINE_LOGFILES,P
                                          RIMARY_ROLE) DB_UNIQUE_NAME=ma
                                          astb

         2 log_archive_dest_2             SERVICE=maastb SYNC AFFIRM LGW
                                          R VALID_FOR=(ONLINE_LOGFILES,P
                                          RIMARY_ROLE) DB_UNIQUE_NAME=ma
                                          astb


SQL> SELECT inst_id, name, value FROM gv$parameter WHERE name = 'log_archive_dest_state_2';

   INST_ID NAME                           VALUE
---------- ------------------------------ ------------------------------
         1 log_archive_dest_state_2       DEFER
         2 log_archive_dest_state_2       DEFER

SQL>

Ambas as instâncias do primary estão com seu destino que aponta para o standby em modo DEFFER (desabilitado). Para habilitar basta executar o comando abaixo:

SQL> ALTER SYSTEM SET log_archive_dest_state_2 = enable SCOPE = BOTH SID = '*';

System altered.

SQL>

Observe o que aconteceu no alertlog de ambas as instâncias (das primary e da standby):

No final observe que o dest_2 está sincronizado.
No alert da primary (este alert não foi cropado e foi copiado de um único nó):
    [oracle@rac11pri01 ~]$ tail -f /u01/app/oracle/diag/rdbms/maa/maa1/trace/alert_maa1.log
    Sat Apr 12 14:32:39 2014
    Thread 1 cannot allocate new log, sequence 70
    Checkpoint not complete
      Current log# 1 seq# 69 mem# 0: +DATA/maa/onlinelog/group_1.272.843488553
      Current log# 1 seq# 69 mem# 1: +FRA/maa/onlinelog/group_1.286.843488555
    Thread 1 advanced to log sequence 70 (LGWR switch)
      Current log# 2 seq# 70 mem# 0: +DATA/maa/onlinelog/group_2.271.843488555
      Current log# 2 seq# 70 mem# 1: +FRA/maa/onlinelog/group_2.285.843488555
    Sat Apr 12 14:32:42 2014
    Archived Log entry 156 added for thread 1 sequence 69 ID 0x2b099804 dest 1:
    Sat Apr 12 14:33:12 2014
    ALTER SYSTEM SET log_archive_dest_state_2='ENABLE' SCOPE=BOTH SID='*';
    Sat Apr 12 14:33:14 2014
    ARC3: Standby redo logfile selected for thread 1 sequence 65 for destination LOG_ARCHIVE_DEST_2
    Sat Apr 12 14:33:15 2014
    Destination LOG_ARCHIVE_DEST_2 is UNSYNCHRONIZED
    ******************************************************************
    LGWR: Setting 'active' archival for destination LOG_ARCHIVE_DEST_2
    ******************************************************************
    LGWR: Standby redo logfile selected to archive thread 1 sequence 71
    LGWR: Standby redo logfile selected for thread 1 sequence 71 for destination LOG_ARCHIVE_DEST_2
    Thread 1 advanced to log sequence 71 (LGWR switch)
      Current log# 1 seq# 71 mem# 0: +DATA/maa/onlinelog/group_1.272.843488553
      Current log# 1 seq# 71 mem# 1: +FRA/maa/onlinelog/group_1.286.843488555
    Sat Apr 12 14:33:21 2014
    Archived Log entry 162 added for thread 1 sequence 70 ID 0x2b099804 dest 1:
    ARC3: Standby redo logfile selected for thread 1 sequence 70 for destination LOG_ARCHIVE_DEST_2
    Sat Apr 12 14:33:29 2014
    Destination LOG_ARCHIVE_DEST_2 is SYNCHRONIZED
    LGWR: Standby redo logfile selected to archive thread 1 sequence 72
    LGWR: Standby redo logfile selected for thread 1 sequence 72 for destination LOG_ARCHIVE_DEST_2
    Thread 1 advanced to log sequence 72 (LGWR switch)
      Current log# 2 seq# 72 mem# 0: +DATA/maa/onlinelog/group_2.271.843488555
      Current log# 2 seq# 72 mem# 1: +FRA/maa/onlinelog/group_2.285.843488555
    Sat Apr 12 14:33:32 2014
    Archived Log entry 174 added for thread 1 sequence 71 ID 0x2b099804 dest 1:


No alert da Primary (em outro nó):
    [oracle@rac11pri02 ~]$ tail -f /u01/app/oracle/diag/rdbms/maa/maa2/trace/alert_maa2.log
      Current log# 4 seq# 48 mem# 0: +DATA/maa/onlinelog/group_4.262.843489103
      Current log# 4 seq# 48 mem# 1: +FRA/maa/onlinelog/group_4.283.843489103
    Sat Apr 12 20:32:25 2014
    Archived Log entry 154 added for thread 2 sequence 47 ID 0x2b099804 dest 1:
    Sat Apr 12 20:32:39 2014
    Thread 2 advanced to log sequence 49 (LGWR switch)
      Current log# 3 seq# 49 mem# 0: +DATA/maa/onlinelog/group_3.257.843489101
      Current log# 3 seq# 49 mem# 1: +FRA/maa/onlinelog/group_3.284.843489101
    Sat Apr 12 20:32:40 2014
    Archived Log entry 155 added for thread 2 sequence 48 ID 0x2b099804 dest 1:
    Sat Apr 12 20:33:12 2014
    Using STANDBY_ARCHIVE_DEST parameter default value as USE_DB_RECOVERY_FILE_DEST
    Sat Apr 12 20:33:16 2014
    Destination LOG_ARCHIVE_DEST_2 is UNSYNCHRONIZED
    ******************************************************************
    LGWR: Setting 'active' archival for destination LOG_ARCHIVE_DEST_2
    ******************************************************************
    Sat Apr 12 20:33:16 2014
    NSS2 started with pid=48, OS id=17931
    LGWR: Standby redo logfile selected to archive thread 2 sequence 50
    LGWR: Standby redo logfile selected for thread 2 sequence 50 for destination LOG_ARCHIVE_DEST_2
    Thread 2 advanced to log sequence 50 (LGWR switch)
      Current log# 4 seq# 50 mem# 0: +DATA/maa/onlinelog/group_4.262.843489103
      Current log# 4 seq# 50 mem# 1: +FRA/maa/onlinelog/group_4.283.843489103
    Sat Apr 12 20:33:31 2014
    Destination LOG_ARCHIVE_DEST_2 is SYNCHRONIZED
    LGWR: Standby redo logfile selected to archive thread 2 sequence 51
    LGWR: Standby redo logfile selected for thread 2 sequence 51 for destination LOG_ARCHIVE_DEST_2
    Thread 2 advanced to log sequence 51 (LGWR switch)
      Current log# 3 seq# 51 mem# 0: +DATA/maa/onlinelog/group_3.257.843489101
      Current log# 3 seq# 51 mem# 1: +FRA/maa/onlinelog/group_3.284.843489101
    Sat Apr 12 20:33:32 2014
    Archived Log entry 175 added for thread 2 sequence 50 ID 0x2b099804 dest 1:
    Sat Apr 12 20:33:35 2014
    Starting background process SMCO
    Sat Apr 12 20:33:35 2014
    SMCO started with pid=49, OS id=17946


No alert da standby pode-se observar que os archives começaram a ser recebidos. Estes archives recebidos são aqueles com dados entre o momento que o duplicate foi feito e o que o dest_2 foi habilitado (o gap).
Estes arquivos foram recebidos e aplicados na base de dados para deixar ela sincronizada.
Observe que só depois de aplicar todos os archives é que o redo da Primary foi sincronizado (Recovery of Online Redo Log) para ambas as threads.
Alert da Standby:
    [oracle@rac11stb01 ~]$ tail -f /u01/app/oracle/diag/rdbms/maastb/maastb1/trace/alert_maastb1.log
    MRP0: Background Managed Standby Recovery process started (maastb1)
     started logmerger process
    Sat Apr 12 14:28:46 2014
    Managed Standby Recovery starting Real Time Apply
    Parallel Media Recovery started with 2 slaves
    Waiting for all non-current ORLs to be archived...
    All non-current ORLs have been archived.
    Sat Apr 12 14:28:48 2014
    Media Recovery Waiting for thread 2 sequence 43
    Completed: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT
    Sat Apr 12 14:30:07 2014
    Using STANDBY_ARCHIVE_DEST parameter default value as USE_DB_RECOVERY_FILE_DEST
    Sat Apr 12 14:30:08 2014
    RFS[1]: Assigned to RFS process 2456
    RFS[1]: Selected log 5 for thread 1 sequence 65 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:08 2014
    RFS[2]: Assigned to RFS process 2458
    RFS[2]: Opened log for thread 1 sequence 66 dbid 722024964 branch 843466948
    RFS[3]: Assigned to RFS process 2454
    RFS[3]: Opened log for thread 1 sequence 67 dbid 722024964 branch 843466948
    Archived Log entry 23 added for thread 1 sequence 66 rlc 843466948 ID 0x2b099804 dest 2:
    Archived Log entry 24 added for thread 1 sequence 67 rlc 843466948 ID 0x2b099804 dest 2:
    Sat Apr 12 14:30:09 2014
    Primary database is in MAXIMUM AVAILABILITY mode
    Standby controlfile consistent with primary
    RFS[1]: Opened log for thread 1 sequence 68 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:10 2014
    Archived Log entry 25 added for thread 1 sequence 65 ID 0x2b099804 dest 1:
    RFS[2]: Opened log for thread 1 sequence 69 dbid 722024964 branch 843466948
    Standby controlfile consistent with primary
    RFS[4]: Assigned to RFS process 2460
    RFS[4]: Selected log 5 for thread 1 sequence 71 dbid 722024964 branch 843466948
    Archived Log entry 26 added for thread 1 sequence 68 rlc 843466948 ID 0x2b099804 dest 2:
    Archived Log entry 27 added for thread 1 sequence 69 rlc 843466948 ID 0x2b099804 dest 2:
    Sat Apr 12 14:30:14 2014
    Primary database is in MAXIMUM AVAILABILITY mode
    Standby controlfile consistent with primary
    Standby controlfile consistent with primary
    RFS[5]: Assigned to RFS process 2467
    RFS[5]: Selected log 8 for thread 2 sequence 50 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:15 2014
    RFS[6]: Assigned to RFS process 2472
    RFS[6]: Selected log 6 for thread 1 sequence 70 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:16 2014
    RFS[7]: Assigned to RFS process 2474
    RFS[7]: Selected log 9 for thread 2 sequence 49 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:17 2014
    Archived Log entry 28 added for thread 1 sequence 70 ID 0x2b099804 dest 1:
    Archived Log entry 29 added for thread 2 sequence 49 ID 0x2b099804 dest 1:
    Sat Apr 12 14:30:18 2014
    Fetching gap sequence in thread 2, gap sequence 43-43
    RFS[7]: Opened log for thread 2 sequence 43 dbid 722024964 branch 843466948
    Archived Log entry 30 added for thread 2 sequence 43 rlc 843466948 ID 0x2b099804 dest 2:
    Sat Apr 12 14:30:18 2014
    RFS[8]: Assigned to RFS process 2478
    RFS[8]: Opened log for thread 2 sequence 44 dbid 722024964 branch 843466948
    Sat Apr 12 14:30:19 2014
    RFS[9]: Assigned to RFS process 2476
    ...
    ...
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_44.599.844720219
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_65.567.844720209
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_66.457.844720209
    Sat Apr 12 14:30:24 2014
    Changing standby controlfile to MAXIMUM AVAILABILITY level
    ...
    ...
    RFS[5]: Selected log 9 for thread 2 sequence 51 dbid 722024964 branch 843466948
    Archived Log entry 37 added for thread 2 sequence 50 ID 0x2b099804 dest 1:
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_45.425.844720219
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_46.420.844720219
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_68.498.844720209
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_47.609.844720219
    Sat Apr 12 14:30:28 2014
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_69.494.844720211
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_48.458.844720219
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_49.466.844720217
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_70.470.844720217
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_1_seq_71.583.844720225
    Media Recovery Log +FRA/maastb/archivelog/2014_04_12/thread_2_seq_50.257.844720225
    Media Recovery Waiting for thread 1 sequence 72 (in transit)
    Recovery of Online Redo Log: Thread 1 Group 6 Seq 72 Reading mem 0
      Mem# 0: +DG01/maastb/onlinelog/group_6.267.844716079
      Mem# 1: +FRA/maastb/onlinelog/group_6.604.844716081
    Media Recovery Waiting for thread 2 sequence 51 (in transit)
    Recovery of Online Redo Log: Thread 2 Group 9 Seq 51 Reading mem 0
      Mem# 0: +DG01/maastb/onlinelog/group_9.260.844716095
      Mem# 1: +FRA/maastb/onlinelog/group_9.591.844716097

Alguns detalhes destes alerts, observe que ambas as instâncias do banco primary estão enviando os seus archives para o standby. Se você observar, irá ver a sequência dos archives enviados do primary para o standby aplicar. Observe também que o standby detectou o GAP e requisitou eles ao primary.

É necessário habilitar o log_archive_dest_state_2 no standby também, pois em caso de uma mudança de papeis já está tudo preparado. Não se preocupe, pois nada será enviado, lembre que na definição ele só envia caso esteja atuando como role primary:

SQL> ALTER SYSTEM SET log_archive_dest_state_2 = enable SCOPE = BOTH SID = '*';

System altered.

SQL>

Podemos fazer alguns testes com a sincroniza para ver se tudo está em ordem. Os passos abaixo mostram como está a sincronia, observe que agora o banco está definido (PROTECTION_MODE) e operando (PROTECTION_LEVEL) em MAXIMUM AVAILABILITY.

SQL> SELECT instance_name FROM gv$instance;

INSTANCE_NAME
----------------
maa2
maa1

SQL> SELECT protection_mode, protection_level FROM v$database;

PROTECTION_MODE      PROTECTION_LEVEL
-------------------- --------------------
MAXIMUM AVAILABILITY MAXIMUM AVAILABILITY

SQL> col error format a10
SQL> col dest_name format a20
SQL> col destination format a20
SQL> SELECT inst_id, dest_name, destination, status, error FROM gv$archive_dest_status WHERE status != 'INACTIVE';

   INST_ID DEST_NAME            DESTINATION          STATUS    ERROR
---------- -------------------- -------------------- --------- ----------
         1 LOG_ARCHIVE_DEST_1                        VALID
         1 LOG_ARCHIVE_DEST_2   maastb               VALID
         2 LOG_ARCHIVE_DEST_1                        VALID
         2 LOG_ARCHIVE_DEST_2   maastb               VALID

SQL>

Forçando um arquivamento do primary você verá o seguinte no alert das instâncias:

No alert da Primary (nó 1)
    [oracle@rac11pri01 ~]$ tail -f /u01/app/oracle/diag/rdbms/maa/maa1/trace/alert_maa1.log
    Sat Apr 12 21:24:34 2014
    LGWR: Standby redo logfile selected to archive thread 1 sequence 74
    LGWR: Standby redo logfile selected for thread 1 sequence 74 for destination LOG_ARCHIVE_DEST_2
    Thread 1 advanced to log sequence 74 (LGWR switch)
      Current log# 2 seq# 74 mem# 0: +DATA/maa/onlinelog/group_2.271.843488555
      Current log# 2 seq# 74 mem# 1: +FRA/maa/onlinelog/group_2.285.843488555
    Sat Apr 12 21:24:35 2014
    Archived Log entry 183 added for thread 1 sequence 73 ID 0x2b099804 dest 1:

No alert da Primary (nó 2)
    [oracle@rac11pri02 ~]$ tail -f /u01/app/oracle/diag/rdbms/maa/maa2/trace/alert_maa2.log
    Sun Apr 13 03:20:01 2014
    Archived Log entry 179 added for thread 2 sequence 51 ID 0x2b099804 dest 1:
    Sun Apr 13 03:24:34 2014
    LGWR: Standby redo logfile selected to archive thread 2 sequence 53
    LGWR: Standby redo logfile selected for thread 2 sequence 53 for destination LOG_ARCHIVE_DEST_2
    Thread 2 advanced to log sequence 53 (LGWR switch)
      Current log# 3 seq# 53 mem# 0: +DATA/maa/onlinelog/group_3.257.843489101
      Current log# 3 seq# 53 mem# 1: +FRA/maa/onlinelog/group_3.284.843489101
    Sun Apr 13 03:24:35 2014
    Archived Log entry 182 added for thread 2 sequence 52 ID 0x2b099804 dest 1:

No alert da Standby:
    [oracle@rac11stb01 ~]$ tail -f /u01/app/oracle/diag/rdbms/maastb/maastb1/trace/alert_maastb1.log
    Sat Apr 12 21:21:27 2014
    Standby controlfile consistent with primary
    RFS[5]: Selected log 9 for thread 2 sequence 53 dbid 722024964 branch 843466948
    Sat Apr 12 21:21:28 2014
    Archived Log entry 40 added for thread 2 sequence 52 ID 0x2b099804 dest 1:
    Sat Apr 12 21:21:28 2014
    Standby controlfile consistent with primary
    RFS[4]: Selected log 6 for thread 1 sequence 74 dbid 722024964 branch 843466948
    Sat Apr 12 21:21:29 2014
    Archived Log entry 41 added for thread 1 sequence 73 ID 0x2b099804 dest 1:
    Sat Apr 12 21:21:29 2014
    Media Recovery Waiting for thread 2 sequence 53 (in transit)
    Recovery of Online Redo Log: Thread 2 Group 9 Seq 53 Reading mem 0
      Mem# 0: +DG01/maastb/onlinelog/group_9.260.844716095
      Mem# 1: +FRA/maastb/onlinelog/group_9.591.844716097
    Media Recovery Waiting for thread 1 sequence 74 (in transit)
    Recovery of Online Redo Log: Thread 1 Group 6 Seq 74 Reading mem 0
      Mem# 0: +DG01/maastb/onlinelog/group_6.267.844716079
      Mem# 1: +FRA/maastb/onlinelog/group_6.604.844716081

Observe no alert das instâncias primary que os archives foram gerados e que o standby arquiva eles e já fica esperando os próximos.

REGISTRANDO O RAC STANDBY

Lembre-se que estamos em um ambiente RAC o banco standby não foi criado através das vias normais, desta forma o CRS do RAC que atende o standby não sabe da existência deste banco. Isso é fácil de resolver, basta registrar o banco:

[oracle@rac11stb01 ~]$ export ORACLE_HOME=/u01/app/grid/11.2.0.3
[oracle@rac11stb01 ~]$ cd $ORACLE_HOME/bin
[oracle@rac11stb01 bin]$ srvctl add database -d maastb -o /u01/app/oracle/product/11.2.0.3/db_1 -c RAC -r PHYSICAL_STANDBY -s MOUNT -t IMMEDIATE -a DG01,FRA
[oracle@rac11stb01 bin]$

E registrar as instâncias:

[oracle@rac11stb01 bin]$ srvctl add instance -d maastb -i maastb1 -n rac11stb01
[oracle@rac11stb01 bin]$ srvctl add instance -d maastb -i maastb2 -n rac11stb02
[oracle@rac11stb01 bin]$ 

Observe que o banco foi registrado como PHYSICAL_STANDBY e para ser iniciado em modo MOUNT. Assim, garantimos que o standby, caso reinicie, volte corretamente.

OUTRAS INSTÂNCIAS

Se você quiser, poderá subir as outras instâncias do standby. Se você já estivesse com o broker, ela seria iniciada automaticamente por ele.

O procedimento é o mesmo, como a instância nunca foi iniciada, você deve criar o diretório “adump” como apontado no spfile. Todos os outros arquivos necessários (como init e password files) já foram copiados em passos anteriores.

Verificando o init da pasta dbs no segundo nó do standby.
    [oracle@rac11stb02 ~]$ cat /u01/app/oracle/product/11.2.0.3/db_1/dbs/initmaastb2.ora
    SPFILE='+DG01/maastb/spfilemaastb.ora'
    [oracle@rac11stb02 ~]$

Criando diretório de dump
    [oracle@rac11stb02 ~]$ mkdir -p /u01/app/oracle/admin/maastb/adump
    [oracle@rac11stb02 ~]$ 

Subindo a instância em modo mount
    [oracle@rac11stb02 ~]$ sqlplus / as sysdba

    SQL*Plus: Release 11.2.0.3.0 Production on Sat Apr 12 21:47:45 2014

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

    Connected to an idle instance.

    SQL> STARTUP NOMOUNT;
    ORACLE instance started.

    Total System Global Area 1068937216 bytes
    Fixed Size                  2235208 bytes
    Variable Size             343934136 bytes
    Database Buffers          717225984 bytes
    Redo Buffers                5541888 bytes
    SQL> ALTER DATABASE MOUNT;

    Database altered.

    SQL>

AMBIENTE FINAL

Chegando aqui, você tem um DG configurado em que ambos, primary e standby, são RAC. Além disso, seu DG está com o modo de proteção definido como MAXIMUM AVAILABIITY que garante sincronismo no envio do dados entre primary e standby, além de estar com real-time.

Mesmo assim, o seu ambiente não está 100%, o broker não está configurado e não existe a figura do “observador” definida. Caso seu primary fique offline, você precisará chavear manualmente para o standby. De qualquer forma, você já está protegido com DG.

Nos próximos artigos iremos ver como fazer algumas coisas com o DG, failover e switchover manuais. Iremos configurar broker e realizar failover e switchover através dele.

No fim, não esqueça de fazer um backup do seu ambiente primary e do spfile do seu standby.

3 thoughts on “Oracle e MAA – Artigo I

  1. Pingback: Oracle e MAA - Artigo II - Failover Manual | Have you hugged your backup today?

  2. Pingback: Oracle e MAA – Artigo X | Blog Fernando Simon

  3. Pingback: ORACLE e MAA - Parte III: Reinstate do Antigo Primary

Leave a Reply

Your email address will not be published. Required fields are marked *