Thursday, October 11, 2018

Creating a Physical Standby database

So there are heaps of articles out there on how to do this, so this one is for my benefit because I've run through it a few times and I know it works. If it doesn't work using this, it means that there is an issue with the environment or infrastructure.

This is pretty much copy and paste.

Primary

copy+paste this into a sqlplus session as sysdba

ALTER DATABASE FORCE LOGGING;
alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(ORCL,ORCL_STDBY)';
alter system set log_archive_dest_2='SERVICE=ORCL_STDBY LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCL_STDBY';
alter system set LOG_ARCHIVE_DEST_STATE_2=DEFER;
alter system set fal_server=ORCL_STDBY;
alter system set fal_client=ORCL;
alter system set DB_FILE_NAME_CONVERT='ORCL_STDBY','ORCL' scope=spfile;
alter system set LOG_FILE_NAME_CONVERT='ORCL_STDBY','ORCL' scope=spfile;
alter system set STANDBY_FILE_MANAGEMENT=AUTO;

Find the size of the redo logs and create the same number and size for standby

SELECT GROUP#,BYTES FROM V$LOG;

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

Check to see if standby logs have been created

SELECT GROUP#,THREAD#,SEQUENCE#,ARCHIVED,STATUS FROM V$STANDBY_LOG;

If so, skip the next step.

If not, add them:
ALTER DATABASE ADD STANDBY LOGFILE GROUP 4 SIZE 50M;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 5 SIZE 50M;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 6 SIZE 50M;

create pfile='/home/oracle/initORCL_STDBY.ora' from spfile;

cat the created file and copy and paste it into the standby, then edit it.

Standby
edit the init.ora

*.control_files='+DATA','+RECO','+ARCH'
*.log_archive_dest_2='SERVICE=ORCL LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCL';
*.db_unique_name='ORCL_STDBY'
*.log_file_name_convert='ORCL','ORCL_STDBY'
*.db_file_name_convert='ORCL','ORCL_STDBY'
*.fal_client='ORCL_STDBY'
*.fal_server='ORCL'
*.log_archive_config='DG_CONFIG=(ORCL,ORCL_STDBY)'

standby listener (could be in GRID HOME, could be in ORACLE_HOME, could be defined by TNS_ADMIN)

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = ORCL_STDBY)
      (SID_NAME = ORCL)
      (ORACLE_HOME = /oracle/ORCL/121)
    )
  )

lsnrctl reload

Needs to be 'UNKNOWN', not 'BLOCKED'

tnsnames.ora on both hosts (could be in GRID HOME, could be in ORACLE_HOME, could be defined by TNS_ADMIN, may need .WORLD, may not)

ORCL.WORLD =
  (DESCRIPTION =
    (ADDRESS_LIST =
        (ADDRESS =
          (COMMUNITY = SAP.WORLD)
          (PROTOCOL = TCP)
          (HOST = oraorcl01)
          (PORT = 1521)
        )
    )
    (CONNECT_DATA =
       (SID = ORCL)
       (GLOBAL_NAME = ORCL.WORLD)
       (UR = A)
    )
  )

ORCL_STDBY.WORLD =
  (DESCRIPTION =
    (ADDRESS_LIST =
        (ADDRESS =
          (COMMUNITY = SAP.WORLD)
          (PROTOCOL = TCP)
          (HOST = oraorcl02)
          (PORT = 1521)
        )
    )
    (CONNECT_DATA =
       (SID = ORCL)
       (GLOBAL_NAME = ORCL.WORLD)
       (UR = A)
    )
  )


Check you can tnsping - if not, they probably haven't opened the ports.
TNS-12535: TNS:operation timed out = ports blocked

startup nomount pfile='initORCL_STDBY.ora'

rman script

DIR=/home/oracle/scripts
LOG=$DIR/duplicate.log
rman target sys@ORCL/xxxxx auxiliary sys@ORCL_STDBY/xxxxx << EOF > $LOG
RUN
{
        allocate channel dev1 type disk;
        allocate channel dev2 type disk;
        allocate channel dev3 type disk;
        allocate channel dev4 type disk;
        allocate channel dev5 type disk;
        ALLOCATE auxiliary CHANNEL CH01 TYPE DISK;
        ALLOCATE auxiliary CHANNEL CH02 TYPE DISK;
        ALLOCATE auxiliary CHANNEL CH03 TYPE DISK;
        ALLOCATE auxiliary CHANNEL CH04 TYPE DISK;
        ALLOCATE auxiliary CHANNEL CH05 TYPE DISK;
        DUPLICATE TARGET DATABASE
        FOR STANDBY
                FROM ACTIVE DATABASE;
}
EOF

check standby db_unique_name = ORCL_STDBY

shutdown immediate

sqlplus / as sysdba
create spfile='+DATA/ORCL_STDBY/spfileORCL.ora' from pfile;
exit

mv initORCL.ora initORCL.ora_old

vi initORCL.ora
spfile=('+DATA/ORCL_STDBY/spfileORCL.ora')

sqlplus / as sysdba
startup mount

On primary

alter system set log_archive_dest_state_2=enable;

On standby

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

tail the standby alert log

tail -f /oracle/ORCL/saptrace/diag/rdbms/ORCL_stdby/ORCL/trace/alert_ORCL.log

On the Primary

alter system switch logfile;
/
/

Logs should be applied to the standby.

Check the gap:

select al.thrd "Thread", almax "Last Seq Received", lhmax "Last Seq Applied"
from (select thread# thrd, max(sequence#) almax
      from v$archived_log
      where resetlogs_change#=(select resetlogs_change# from v$database)
      group by thread#) al,
     (select thread# thrd, max(sequence#) lhmax
      from v$log_history
      where first_time=(select max(first_time) from v$log_history)
      group by thread#) lh
where al.thrd = lh.thrd;

Numbers should match

    Thread Last Seq Received Last Seq Applied
---------- ----------------- ----------------
         1              7197             7197

There is a SAP process called BRARCHIVE which backs up and deletes logs, so you may have missing logs that have gone from the primary

If there is a gap in logs, restore them like this:

rman target = /
SET DECRYPTION IDENTIFIED BY 'xxxxx';
run {
allocate channel sbt_1 device type 'SBT_TAPE'
parms 'SBT_LIBRARY=/oracle/ORCL/121/lib/libosbws.so, ENV=(OSB_WS_PFILE=/oracle/ORCL/121/dbs/osbwsORCL.ora)';
restore archivelog from logseq=7187 until logseq=7194 ;
}


Setting up the broker

on both primary and standby - assuming it's a new configuration. If not, there is an Oracle note - Step By Step How to Recreate Dataguard Broker Configuration (Doc ID 808783.1)

alter system set dg_broker_start=true;
alter system set log_archive_dest_2='' scope=both;

show parameter broker

remove / move any broker config files

dg_broker_config_file1               string      /oracle/ORCL/121/dbs/dr1ORCL.dat
dg_broker_config_file2               string      /oracle/ORCL/121/dbs/dr2ORCL.dat

exit

dgmgrl /
create configuration 'ORCL_DG' as primary database is 'ORCL' connect identifier is 'ORCL';
ADD DATABASE 'ORCL_STDBY' AS CONNECT IDENTIFIER IS ORCL_STDBY MAINTAINED AS PHYSICAL;
enable configuration;

show configuration;

Should show "SUCCESS" at the bottom

Tail the standby alert log and switch some primary log files, check the gap.


Set up failover connections

exec DBMS_SERVICE.CREATE_SERVICE (service_name => 'ORCL_AUTO',network_name => 'ORCL_AUTO',failover_method => 'BASIC',failover_type => 'SELECT',failover_retries => 180,failover_delay => 1);

PL/SQL procedure successfully completed.

CREATE OR REPLACE TRIGGER manage_dgservice
after startup on database
DECLARE
role VARCHAR(30);
BEGIN
SELECT DATABASE_ROLE INTO role FROM V$DATABASE;
IF role = 'PRIMARY' THEN
DBMS_SERVICE.START_SERVICE('ORCL_AUTO');
END IF;
END;
/



client connection - give to the application
ORCL_AUTO=
(DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oraorcl01)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = oraorcl02)(PORT = 1521))
    (LOAD_BALANCE = yes)
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORCL_AUTO)
   )
)