Configurardataguard DatafilesToAsm
Configurardataguard DatafilesToAsm
Configurardataguard DatafilesToAsm
Índice
Introducción
Checklist
Consideraciones
Pasos del procedimiento
Procedimiento detallado
Crear estructura de directorios en standby como en primaria
Sacar pfile de origen y adaptarlo en destino
Asegurar conectividad entre nodos
Crear standby logs en primary (antes de duplicar)
Habilitar Forced Logging en Primary
Duplicar la base de datos
Configurar parámetros de instancia para ambas
Iniciar replicación
Configurar primary para poder funcionar como standby
Crear un servicio común
Configurar Broker (DGMGRL)
Forzar archivelog cada 30 minutos
Configurar backup y mantenimiento de archivelogs aplicados
Introducción
Procedimiento para configurar de cero un DataGuard y crear base de datos standby a una base de datos ya existente. Incluida la posibilidad de un
entorno heterogéneo Filesystem ASM.
Checklist
Antes:
Disponer de un nuevo servidor con mismas características que el de la base de datos actual.
Es necesario tener ya instalado un RDBMS en la misma versión y nivel de parcheo que el de la base de datos actual.
Comprobar que el almacenamiento es suficiente para alojar la nueva base de datos.
Después:
Consideraciones
Procedimiento detallado
Nos conectaremos por ssh al nuevo sistema que será el standby.
Para ello lanzamos en la base de datos primaria estas consultas y ejecutamos como oracle los resultados:
-- Extraer en primaria los directorios necesarios para la base de datos, en caso de que la standby sea ASM no
es necesario este paso
set pagesize 0
set feedback off
prompt DIRECTORIOS FICHEROS DE BD (no necesario para ASM)
select distinct 'mkdir -p '||SUBSTR(name, 0, INSTR(name,'/',-1)-1) from v$controlfile
union select distinct 'mkdir -p '||SUBSTR(member, 0, INSTR(member,'/',-1)-1) from v$logfile
union select distinct 'mkdir -p '||SUBSTR(name, 0, INSTR(name,'/',-1)-1) from v$datafile
union select distinct 'mkdir -p '||SUBSTR(name, 0, INSTR(name,'/',-1)-1) from v$tempfile order by 1;
NOTA: En caso de usar ASM no es necesario crear los directorios de "FICHEROS DE BD".
Ejemplo:
*.db_unique_name='AXPRECM4'
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=AXPRECM4'
3. Modificar el listener si procede, y en ese caso renombrar o crear dicho listener si no se va a usar el de por defecto 'LISTENER'. Ej:
*.local_listener='LISTENER_AXPRECM4'
4. En caso de usar distintas rutas o de ser un entorno heterogéneo Filesystem ASM, adaptar los siguientes parámetros. Ej:
*.db_recovery_file_dest='+DGRECO01'
*.db_create_file_dest='+DGDATA01'
5. Si el entorno es heterogéneo o las rutas no son iguales incluiremos además los parámentros "db_file_name_convert" y "log_file_name_convert"
para la conversión de rutas durante el restore de RMAN y futuras modificaciones de la estructura de la base de datos en el nodo primario, con el
siguiente formato:
*.db_file_name_convert='/<dir-origen-dbf>/','+<DG-dest>/<unique-name>/DATAFILE/', '/<dir-origen-dbf>
/','+<DG-dest>/<unique-name>/TEMPFILE/', '/<dir-origen-dbf>/','+<DG-dest>/<unique-name>/CONTROLFILE/', ...
*.log_file_name_convert='/<dir-origen>/','+<DG-dest>/<unique-name>/ONLINELOG/', ...
Para obtener los directorios de la base de datos origen nos valdremos de la ayuda de estas consultas:
TIPO DIR
------------ ------------------------------------------------------------
CONTROLFILE /oracle/oradata/axprecm2/sys/
/oracle/orasystem/axprecm2/
DATAFILE /oracle/oradata/axprecm2/sys/
/oracle/oradata/axprecm2/ucontrolm/
/oracle/oradata/axprecm2/uemuser/
TEMPFILE /oracle/oradata/axprecm2/sys/
6 rows selected.
TIPO DIR
------------ ------------------------------------------------------------
ONLINELOG /oracle/logs/axprecm2/
/oracle/orasystem/axprecm2/sys/
Hemos de asegurarnos que el fichero de passwords es el mismo en las dos bases de datos. Hacemos una copia y nos aseguramos que el parámetro
remote_login_passwordfile tiene el valor EXCLUSIVE.
Copiar en destino adaptando el SID si fuera necesario, o crearlo (con la misma clave de SYS) de la siguiente forma:
orapwd file=$ORACLE_HOME/dbs/orapw${ORACLE_SID}
AXPRECM4 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = axpreoracm4.central.inditex.grp)(PORT = 11521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = axprecm4.central.inditex.grp)
(UR = A)
)
)
LISTENER_AXPRECM4 =
(ADDRESS = (PROTOCOL = TCP)(HOST = axpreoracm4.central.inditex.grp)(PORT = 11521))
Nota: para evitar el siguiente error durante el restore de RMAN en nomount, añadir la opción: (UR = A).
RMAN-04006: error from auxiliary database: ORA-12528: TNS:listener: all appropriate instances are
blocking new connections
6 rows selected.
MB
----------
250
12 rows selected.
FORCE_LOGGING
---------------------------------------
NO
Database altered.
FORCE_LOGGING
---------------------------------------
YES <-----
File created.
SQL>
Verificar conectividad
TARGET (primary)
Servidor: axpreoracm2
SID: axprecm2
DB_UNIQUE_NAME: axprecm2
TNS: axprecm2
AUXILIARY (standby)
Servidor: axpreoracm4
SID: axprecm4
DB_UNIQUE_NAME: axprecm4
TNS: axprecm4
[oracle@axpreoracm2 ~]$ tnsping axprecm4
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = axpreoracm4.central.inditex.grp)(PORT =
11521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = axprecm4.central.inditex.grp)))
OK (40 msec)
-- Ejemplo:
rman auxiliary 'sys@axprecm4' target 'sys@axprecm2' @duplicate_from_active_script.rman
log=duplicate_from_active_script_$(date +%Y%m%d_%H:%M).log
Revisar log generado por si hubiera errores, si todo ha ido correctamente la instancia estará montada:
1 axprecm4
axpreoracm4.central.inditex.grp
12.1.0.2.0 10-AUG-21 MOUNTED NO 1 STARTED
ALLOWED NO ACTIVE PRIMARY_INSTANCE NORMAL NO 0
REGULAR EE
Asegurar que el UNDO, TEMP y demás sigan la distribución esperada:
Nota: RMAN no restaura datafiles de tablespaces de tipo temporary, por lo que cuando la instancia se convierta en PRIMARY y pase a OPEN
por primera vez se recreará el tempfile durante el arranque. Si no, será necesario recrearlo la primera vez.
ASMCMD> ls +DGDATA01/AXPRECM4/DATAFILE/temp01.dbf
ASMCMD-8002: entry 'temp01.dbf' does not exist in directory '+DGDATA01/AXPRECM4/DATAFILE/'
$ vi /etc/oratab
axprecm4:/opt/oracle/product/12c:Y
-- Ejemplo:
[oracle@axpreoracm4 ~]$ srvctl add database -db axprecm4 -instance axprecm4 -o /opt/oracle/product/12c -
diskgroup "DGDATA01,DGRECO01" -role PHYSICAL_STANDBY -startoption mount
En caso de que la release de Grid y RDBMS sean distintas ejecutar el comando 'srvctl' en el entorno del ORACLE_HOME de la base de datos.
LOG_MODE
------------
ARCHIVELOG
Obtener valores actuales de los parámetros que vamos a modificar:
log_archive_dest_2
log_archive_dest_state_2
enable
fal_client
fal_server
log_archive_config
standby_file_management
MANUAL
Configurar los siguientes parámetros de acuerdo a estos valores en ambas, para la que ahora es STBY configuramos los valores que debería tener
cuando se convierta en PRIMARY :
alter system set STANDBY_FILE_MANAGEMENT='AUTO' scope=BOTH; -- Replica las acciones sobre los datafiles en SO
(creación, modificación, borrado ...)
* Nota, para 12c y anteriores sustituir estas dos últimas lineas por:
Ejemplo:
-- Primary
alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(AXPRECM2,AXPRECM4)' scope=BOTH;
alter system set FAL_CLIENT=AXPRECM2 scope=BOTH;
alter system set FAL_SERVER=AXPRECM4 scope=BOTH;
alter system set STANDBY_FILE_MANAGEMENT='AUTO' scope=BOTH;
alter system set LOG_ARCHIVE_DEST_2='SERVICE=AXPRECM4 NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=AXPRECM4' scope=BOTH;
alter system set LOG_ARCHIVE_DEST_STATE_2='ENABLE' scope=BOTH;
-- Standby
alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(AXPRECM2,AXPRECM4)' scope=BOTH;
alter system set FAL_CLIENT=AXPRECM4 scope=BOTH;
alter system set FAL_SERVER=AXPRECM2 scope=BOTH;
alter system set STANDBY_FILE_MANAGEMENT='AUTO' scope=BOTH;
alter system set LOG_ARCHIVE_DEST_2='SERVICE=AXPRECM2 NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=AXPRECM2' scope=BOTH;
alter system set LOG_ARCHIVE_DEST_STATE_2='ENABLE' scope=BOTH;
Verificar:
log_archive_dest_2
SERVICE=AXPRECM4 NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQ
UE_NAME=AXPRECM4
log_archive_dest_state_2
ENABLE
fal_client
AXPRECM2
fal_server
AXPRECM4
log_archive_config
DG_CONFIG=(AXPRECM2,AXPRECM4)
standby_file_management
AUTO
Iniciar replicación
Arrancamos la replicación en la standby:
SQL> select database_role, switchover_status from v$database;
DATABASE_ROLE SWITCHOVER_STATUS
---------------- --------------------
PHYSICAL STANDBY RECOVERY NEEDED
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
Database altered.
DATABASE_ROLE SWITCHOVER_STATUS
---------------- --------------------
PHYSICAL STANDBY NOT ALLOWED
select al.thread#, al.last_rec "Last Recd", la.last_app "Last Applied", al.last_rec - la.last_app "Diff"
from
(select thread#, max(sequence#) last_rec
from v$archived_log
where resetlogs_id = (select max(resetlogs_id) from v$archived_log)
group by thread#) al,
(select thread#, max(sequence#) last_app
from v$archived_log
where resetlogs_id = (select max(resetlogs_id) from v$archived_log)
and applied='YES' and registrar in ('RFS','LGWR','ARCH')
group by thread#) la
where al.thread#=la.thread#
and al.thread# != 0
order by al.thread#;
prompt ** Comprobar que la diferencia entre recibido y aplicado es 0 ó 1
Ejemplo de resultado:
DATABASE_ROLE SWITCHOVER_STATUS OPEN_MODE
---------------- -------------------- --------------------
PRIMARY TO STANDBY READ WRITE
** Comprobar que esta lista para un posible switchover (TO STANDBY) y que el destino esta abierto (READ WRITE)
-- En la primary :
TIPO DIR
------------ ------------------------------------------------------------
CONTROLFILE /oracle/oradata/axprecm2/sys/
/oracle/orasystem/axprecm2/
DATAFILE /oracle/oradata/axprecm2/sys/
/oracle/oradata/axprecm2/ucontrolm/
/oracle/oradata/axprecm2/uemuser/
TEMPFILE /oracle/oradata/axprecm2/sys/
-- En la secondary :
TIPO DIR
------------ ------------------------------------------------------------
CONTROLFILE +DGDATA01/AXPRECM4/CONTROLFILE/
+DGRECO01/AXPRECM4/CONTROLFILE/
DATAFILE +DGDATA01/AXPRECM4/DATAFILE/
TEMPFILE +DGDATA01/AXPRECM4/DATAFILE/
-- En la primary:
TIPO DIR
------------ ------------------------------------------------------------
ONLINELOG /oracle/logs/axprecm2/
/oracle/orasystem/axprecm2/sys/
-- En la secondary:
TIPO DIR
------------ ------------------------------------------------------------
ONLINELOG +DGDATA01/AXPRECM4/ONLINELOG/
+DGRECO01/AXPRECM4/ONLINELOG/
Ejemplo:
-- Crear nuevo de nombre neutro con los siguientes parámertros en la base de datos PRIMARY
BEGIN
DBMS_SERVICE.CREATE_SERVICE(
service_name => 'axdscm.central.inditex.grp',
network_name => 'axdscm.central.inditex.grp',
aq_ha_notifications => TRUE,
failover_method => 'BASIC',
failover_type => 'SELECT',
failover_retries => 180,
failover_delay => 1
);
END;
/
Services Summary...
Service "axdscm.central.inditex.grp" has 1 instance(s).
Instance "axdscm2", status READY, has 1 handler(s) for this service...
Service "axdscm2.central.inditex.grp" has 1 instance(s).
Instance "axdscm2", status READY, has 1 handler(s) for this service...
Service "axdscm2XDB.central.inditex.grp" has 1 instance(s).
Instance "axdscm2", status READY, has 1 handler(s) for this service...
Service "axdscm2_DGB.central.inditex.grp" has 1 instance(s).
Instance "axdscm2", status READY, has 1 handler(s) for this service...
Crear trigger, en caso de que el servicio no sea gestionado por Grid, para poder levantar el servicio adecuado al rol de cada instancia.
Si la STANDBY se va a abrir además como READ ONLY crear un servicio adicional "xxx_ro" y descomentarlo dichas líneas en el trigger.
CREATE OR REPLACE TRIGGER SYS.START_SRVC_ROLE after startup on database
declare
role varchar2(30);
begin
select database_role into role from v$database;
IF role = 'PRIMARY' THEN
DBMS_SERVICE.START_SERVICE('axdscm.central.inditex.grp');
--DBMS_SERVICE.STOP_SERVICE('axdscm_ro.central.inditex.grp');
ELSE
DBMS_SERVICE.STOP_SERVICE('axdscm.central.inditex.grp');
--DBMS_SERVICE.START_SERVICE('axdscm_ro.central.inditex.grp');
END IF;
END;
/
AXDSCM =
(DESCRIPTION =
(ADDRESS_LIST =
(FAILOVER = ON)
(LOAD_BALANCE = OFF)
(ADDRESS=(PROTOCOL=TCP)(HOST=axdesoracm1.central.inditex.grp)(PORT=11521))
(ADDRESS=(PROTOCOL=TCP)(HOST=axdesoracm2.central.inditex.grp)(PORT=11521))
)
(CONNECT_DATA =
(SERVICE_NAME = axdscm.central.inditex.grp)
)
)
Para evitar el error "ORA-16698: LOG_ARCHIVE_DEST_n parámeter set for object to be added" durante la configuración es necesario poner a null el
LOG_ARCHIVE_DEST_2 previamente en ambos nodos de manera temporal:
##Ejemplo
DGMGRL> CREATE CONFIGURATION DGConfig AS PRIMARY DATABASE IS axprecm2 CONNECT IDENTIFIER IS axprecm2;
Configuration "dgconfig" created with primary database "axprecm2"
Configuration - dgconfig
Configuration Status:
SUCCESS (status updated 59 seconds ago)
Volver a configurar el parámetro LOG_ARCHIVE_DEST_2 con el valor inicial en ambos nodos si se ha reseteado.
Para evitar errores durante el switchover y que haya que levantar la nueva STBY a mano, revisar la configuración de la propiedad "staticconnectidentifier",
adaptando el servicio (tiene que ser uno GLOBAL)
Ejemplo de entrada en el listener.ora, GLOBAL_DBNAME es el nombre de servicio que tiene configurado DataGuard y SID_NAME la instancia local.
Editar el correspondiente en cada nodo:
SID_LIST_LISTENER_AXPRECM4 =
(SID_LIST=
(SID_DESC=
(GLOBAL_DBNAME=axprecm4_DGMGRL.central.inditex.grp)
(ORACLE_HOME=/opt/oracle/product/12c)
(SID_NAME=axprecm4)
)
)
CMD> dgmgrl /
System altered.
System altered.
System altered.
CMD> @ogi
CMD> asmcmd
CMD> @axprecm2
System altered.
CMD> dgmgrl /
En primary:
$ rman target /
CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY BACKED UP 1 TIMES TO 'SBT_TAPE';
En standby:
$ rman target /
CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;
ORACLE_SID=axprecm4
NB_ORA_CLIENT=axpreoracm4.central.inditex.grp
ORACLE_HOME=/opt/oracle/product/12c
$RMAN target $TARGET_CONNECT_STR catalog ******/******@****** msglog $RMAN_LOG_FILE append << EOF
Añadir script de limpieza de archivelogs ya aplicados 'delete_arc_applied_rman.sh' y programar en el crontab en ambos nodos (el script solo se
ejecutará en el que sea el standby). Revisar si es necesario en bases de datos 18c o superiores ya que se supone que los archives de la standby se
limpian automáticamente tras el backup y borrado de la primary.
Script 'delete_arc_applied_rman.sh':
#!/bin/bash
#---------------------------------------
# delete_arc_applied_rman.sh
# Limpiar de base de datos standby
# los archivelogs aplicados.
#---------------------------------------
# 12/08/2021 javierccha@ext.inditex.com
# v1.0 Inicial
# 21/10/2021 javierccha@ext.inditex.com
# v1.1 Comprobación STBY
#---------------------------------------
#--- Setup
RETENCION=12 # RETENCION en horas de archives aplicados a conservar
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=/opt/oracle/product/12.1.0
export ORACLE_SID=axdscm2
export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch:$PATH
#--- Ejecucion
(
echo
echo "===[$(date +"%d/%m/%Y %H:%M")]========================================================="
echo
DGR=$(timeout 60 sqlplus -s / as sysdba << EOF
SET FEEDBACK OFF
SET HEADING OFF
SELECT DATABASE_ROLE FROM V\$DATABASE;
EOF
)
if [ $? -eq 124 ]; then
echo " ERROR: TIMEOUT ejecutando SQL"
RC=100
else
if [ "$(echo $DGR|tr -d '\n')" != "PHYSICAL STANDBY" ]; then
echo " ERROR: La base de datos no está en modo STANDBY"
RC=200
else
echo " Borrando los archivelog aplicados en la STBY y mayores a $RETENCION horas:"
echo
${ORACLE_HOME}/bin/rman <<EOF
connect target /
delete noprompt archivelog all completed before 'sysdate-($RETENCION/24)' device type disk;
EOF
RC=$?
fi
fi
echo
if [ $RC -eq 0 ]; then
echo -e "===[$(date +"%d/%m/%Y %H:%M")]===============================================\e[92m[all OK]\e[0m=="
else
echo -e "===[$(date +"%d/%m/%Y %H:%M")]===========================================\e[91m[ERROR RC=$RC]\e[0m=="
fi
echo
exit $RC
) 2>&1|tee $LOG
exit ${PIPESTATUS[0]}