Trucos para crear un dataguard standby

Si consultamos la documentación de Oracle la creación de un datagurard es algo facilísimo, pero a la hora de la verdad, siempre hay pequeños flecos de configuración antes de la creación que es lo que nos puede traer de cabeza, vamos a ver en esta entrada algunos puntos que mirar antes de empezar para que todo funcione.

Suponemos que :

  • EL SID de la base de datos va a ser cdbtest
  • A la base de datos primaria la llamaremos primary , su nombre único será cdbtest
  • A la base de datos standby la llamaremos standby ,su nombre único será cdbtest_sdby

Pasos a llevar a cabo en primary

Se gun la documentación de Oracle, debería de bastar con:

, pero siempre hay cosas que podemos ir haciendo para que todo vaya a la primera

Activar el standby file management

Mediante esta opción los cambios que llevemos a cabo en la primary database se llevaran a cabo en la standby

alter system set STANDBY_FILE_MANAGEMENT=AUTO ;

Crear grupos de standby redo logs

Estos grupos serán necesarios en standby, si los tenemos creados en primary ademas solucionaremos antes de que ocurran los problemas en caso de switchover.

La sintaxis es igual que la de la creación de un grupo normal añadiendo standby

alter database add standby logfile group 4  '/u01/app/oracle/oradata/cdbtest/standby_redo04.log' size 52428800;

Hay que crear un grupo de standby redo log file mas que los grupos de redo logs normales.

Configurar el tnsnames del servidor

Este es uno de los puntos importantes, el servidor debe de ser capaz de acceder por oraclenet al standby.
Dado que los dos SID van a ser iguales, aconsejamos el poner una entrada clara en el listener.ora, en nuestro caso los llamaremos exactamente igual que el DB_UNIQU_NAME que es CDBTEST_STDBY

CDBTEST_STANDBY =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = cdbtest)
    )
  )

Además de esta entrada, deberá de haber una entrada para el LOCAL_LISTENER,la teoría indica que esto ya debería de estar configurado, pero la realidad a veces es distinta, por lo que nos aseguraremos que la variable LOCAL_LISTENER de nuestra base de datos este correctamente configurada y tenga su entrada en el nsnames.ora .


LISTENER_CDBTEST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = alone.pamplona.name)(PORT = 1521))

Configurar parametros en spfile

Antes de proseguir, es obligatorio el uso de spfile , la creación de la replica va a ser mediante RMAN, por lo que, en caso de usar file fallaría la creación del spfile en standby

Los parámetros que hemos de poner son:

DB_UNIQUE_NAME

Este parámetro no es obligatorio en el primary, pero es recomendable, por lo que lo pondremos

alter system set db_unique_name='cdbtest' scope=spfile sid='*';

LOG_ARCHIVE_CONFIG

LOG_ARCHIVE_CONFIG habilita o deshabita la recepcion/envio de los redo, pero lo que realmente nos interesa es que especifica para cada una de las bases de datos del Dataguard los nombres únicos de las mismas (DB_UNIQUE_NAME)

alter system LOG_ARCHIVE_CONFIG='DG_CONFIG=(cdbtest,cdbtest_stby)'

LOG_ARCHIVE_DEST_X

Otro de los valores que cambiaremos es la ubicación de los redo logs, aquí indicaremos donde va el primary y el standby, así como los casos.

ALTER SYSTEM SET LOG_ARCHIVE_DEST_1= 'LOCATION=/u01/app/oracle/oradata/cdbtest/archivelog
  VALID_FOR=(ALL_LOGFILES,ALL_ROLES)';
ALTER SYSTEM SET log_archive_dest_2='service=CDBTEST_STANDBY ASYNC NOAFFIRM delay=0 optional compression=disable max_failure=0 max_connections=1 reopen=300 net_timeout=30 DB_UNIQUE_NAME=cdbtest_sdby valid_for=(online_logfile,all_roles)' ;

Configuraciones en el servidor de Standby

Estas configuraciones son seguramente las que mas nos hagan fallar en el proceso, ya que en muchos documentos se dejan como algo que se asume ya está.
Las configuraciones son:

Configuraciones de tnsnames.ora

Este es posiblemente el fichero que vaya a marcar el éxito de nuestra acción a la primera, deberá de contar con las lineas:

  • LOCAL_LISTENER deberemos de tener una entrada distinta a la de producción que fijaremos en la BBDD standby
  • BBDD primaria debemos de tener una entrada que apunte a la BBDD primaria
  • BBDD standbydebemos de tener una entrada que apunte a la BBDD standby

LISTENER_CDBTEST_STANDBY =
(ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))

CDBTEST_PRIMARY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = alone.pamplona.name)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = cdbtest)
)
)

CDBTEST,CDBTEST_STANDBY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = cdbtest)
)
)

IMPORTANTE:Si miramos con atención el código que hemos puesto, veremos como el truco es que en el nodo standby la conexión a cdbtest será a si mismo, denotando el primario con otro nombre.

Configuraciones estática del listener

Además de la configuración standard del Listener, deberemos de definir una linea estática con la definición del standby.

# Configuracion estatica para el Dataguard
SID_LIST_LISTENER=
  (SID_LIST=
    (SID_DESC= (DB_UNIQUE_NAME=cdbtest_sandby) (ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome_1) 
(SID_NAME=cdbtest))

Si no tenemos esta opción, al intentar conectar con el rman obtendremos el error

RMAN-04006: error from auxiliary database: ORA-12528: TNS:listener: all appropriate instances are blocking new connections

Creación de las rutas físicas de la BBDD

En el caso como es el del ejemplo que haya rutas físicas para los datafiles, deberán de estar creadas en el servidor de standby con los permisos necesarios.

Copiado de fichero init.ora

Aunque hemos dicho que es necesario que la base de datos primaria necesitaba de un fichero sprite, para poder arrancar nuestra base de datos de dataguard , la base de datos standby necesitará un init.ora mínimo para arrancar.
Este init.ora va a ser cambiado por el spfile que recuperaremos de la primary,
Es importante que tengamos:

  • db_name
  • db_unique_name
  • local_listener

El resto como decimos lo eliminará substituirá el proceso.

*.audit_file_dest='/u01/app/oracle/admin/cdbtest/adump'
*.audit_trail='db'
*.compatible='12.1.0.2.0'
*.db_block_size=8192
*.db_domain=''
*.db_name='cdbtest'
*.db_unique_name='cdbtest_sdby'
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=cdbtestXDB)'
*.enable_pluggable_database=true
*.local_listener='LISTENER_CDBTEST_STANDBY'
*.log_archive_config='DG_CONFIG=(cdbtest,cdbtest_sdby)'
*.memory_target=4000m
*.open_cursors=300
*.processes=300
*.remote_login_passwordfile='EXCLUSIVE'
*.standby_file_management='AUTO'
*.undo_tablespace='UNDOTBS1'

Creación de fichero de duplicado

Llegamos al punto importante, el fichero de duplicado de aman.
Este proceso que era bastante costoso en las versiones 9 y 10 se ha facilitado muchísimo en la 11 y 12.

El fichero viene a ser algo así

connect target sys/XXX@cdbtest_primary
connect auxiliary sys/XXX@cdbtest
DUPLICATE TARGET DATABASE
  FOR STANDBY
  FROM ACTIVE DATABASE
  DORECOVER
NOFILENAMECHECK
  SPFILE
	SET db_unique_name="cdbtest_sdby"  comment "Base de datos sandby"
	SET LOCAL_LISTENER="LISTENER_CDBTEST_STANDBY"
	SET standby_file_management='AUTO'
	set log_file_name_convert='/u01/app/oracle/oradata/cdbtest/','/u01/app/oracle/oradata/cdbtest/'

Y los puntos importantes son:

  • NOFILENAMECHECK Esto nos dejará todos los ficheros exactamente como en la primary
  • Apartado set Aqui le decimos lo que va a cambiar del spfile respecto de la original, nosotros cambiamos:
    • db_unique_name. Indicamos el unique name de la standby
    • LOCAL_LISTENER Este es importante para que encuentre el listener de la maquina de la standby
    • log_file_name_convert La teoría indica que no deberíamos de tener que indicar este parámetro, pero en diversas pruebas he tenido problemas con los redo log files, mediante esta cláusula, indicándole el path de los redo log Files por duplicado (para que no cambie nada) los crea correctamente

Duplicacion

Con esto solamente nos queda el proceso de duplicación, que ya es algo tan sencillo como ejecutar en el servidor de standby

#!/bin/bash
SET ORACLE_SID=cdbtest 
sqlplus "/as sysdba" << EOF
startup nomount;
exit;
EOF
rman cmdfile comandos_rman.cmd 

Evento de espera enq: HW

Hoy vamos a ver un tipo de evento relaccionado habitualmente con las inserciones.

El HW High Water enqueue enq: HW se da cuando varios procesos compiten para aumentar el high water mark de una tabla .

Si disponemos del Enterprise manager console, podremos ver como aparece claramente un area marron de configuracion.

Esta carga se asocia claramente a una consulta de insert

Este caso puede ser comun en procesos de aplicacion con actualizaciones en paralelo sobre la misma tabla.

La manera de la resolución del mismo puede pasar por ampliar los freelists.

Mas informacion como siempre en soporte oracle

  • WAITEVENT: «enq: HW – contention» Reference Note (Doc ID 2098543.1)
  • Analyzing ‘enq: HW – contention’ Wait Event (Doc ID 740075.1)

errores ORA-16698: en la creación del data guard boker

Hoy vamos a ver un a entrada rápida y sencilla sobre un error bastante común en la creación de una configuración del dataguard broker.

Supongamos tenemos un dataguard funcionando y que queremos gestionar mediante el dataguard broker.

Nuestros primeros pasos serán intentar crear una configuración con

DGMGRL> create configuration cdbtest_DG as primary database is cdbtest connect identifier is cdbtest ;

Pero recibimos el siguiente error:

ORA-16698: LOG_ARCHIVE_DEST_n parameter set for object to be added

Si nuestro dataguard está funcionando correctamente , y esta aplicando los logs …¿A que es debido?

Si miramos en nuestra base de datos


SQL> show parameter LOG_ARCHIVE_DEST_2 

NAME			   TYPE	 VALUE
----------------------- ------------------------------
log_archive_dest_2	   string	 service=cdbtest_standby ASYNC
					 NOAFFIRM delay=0 optional comp
					 ression=disable max_failure=0
					 max_connections=1 reopen=300 n
					 et_timeout=30 DB_UNIQUE_NAME=c
					 dbtest_standby valid_for=(onli
					 ne_logfile,all_roles)
log_archive_dest_20		     string

Esto no debería de ser problema, pero la realidad es que si que lo es, y no por un bug, sino por indicación del propio Oracle.
Para poder crear la configuración este parámetro deberá de estar limpio , así pues si lo vaciamos y ejecutamos el comando tendremos que:

SQL> alter system set log_archive_dest_2='';
System altered.
SQL> quit

[oracle@alone creacion_dataguard]$ dgmgrl sys/XX
DGMGRL> create configuration cdbtest_DG as primary database is cdbtest connect identifier  is cdbtest ;
Configuration "cdbtest_dg" created with primary database "cdbtest"
DGMGRL> 

Más información en escenarios en la creación de dataguard

Trazando sqlnet en el servidor de Base de datos

Hoy veremos una entrada sobre diagnósticos de la base de datos.

Supongamos que tenemos algún tipo de error entre cliente y servidor en la capa OCI, la accion lógica en estos casos es activar una traza del sqlnet para detectar donde se encuentra el problema.
Si seguimos la nota de Oracle SQL*Net & Oracle Net Services – Tracing and Logging at a Glance (Doc ID 219968.1) veremos como , con las siguientes líneas deberíamos de tener en el directorio /home/oracle/trazas_problema_sqlnet una traza por cada uno de los procesos de conexion a la base de datos.

trace_level_server = 6
trace_file_server = svr
trace_directory_server = /home/oracle/trazas_problema_sqlnet
trace_unique_server = on
trace_timestamp_server = on
log_file_server = svr
log_directory_server = /home/oracle/trazas_problema_sqlnet

Sin embargo, cuando añadimos nuestros parámetros de traza vemos que en el directorio que hemos marcado para las trazas no aparece ningún fichero.
¿Que ocurre?

¿por que ocurre esto?

Si miramos la documentacion del sqlnet en https://docs.oracle.com/cd/B28359_01/network.111/b28317/sqlnet.htm#NETRF419

vemos como desde la version 11 en adelante tenemos los parámetros que funcionan con el ADDR-DIAG habilitado y los que funcionan cuando esta deshabilitado.
En nuestro caso, el problema es que al estar habilitado por defecto el diagnistico unificado de Oracle, no está haciendo caso a nuestras directrices.

¿Como lo solucionamos

La solución no puede ser mas sencilla, simplemente deberemos de decirle en el mismo sqlnet.ora que no use el diagnostico unificado de Oracle, esto lo haremos añadiendo la línea

DIAG_ADR_ENABLED = OFF

Con esto comenzará a trazar en la ubicación designada.

NOTA:
Debemos de recordar eliminar esta línea cuando acabemos de trazar ya que, ademas de poder llenar el filesystem por la traza, estamos indicando al servidor que no use el DIAG_ADR algo que no es conveniente .

Como siempre mas información en :

  • SQL*Net & Oracle Net Services – Tracing and Logging at a Glance (Doc ID 219968.1)
  • documentacion de Sqlnet

Conexiones JDBC Thin a una base de datos Oracle

Hoy vamos a ver una entrada rápida y útil sobre la manera de configurar los clientes JDBC para acceder a los motores de la base de datos. Tradicionalmente los desarrolladores e integradores Java son muy dados a configurar los pooles de conexión hardcodeando los datos de la conexión en el fichero de propiedades de la misma de la manera IP:puerto:SID
Esta codificación podía ser muy buena en los anales de la historia de Java, pero con la versión del jdbc del cliente 10.2.0.1 se introdujeron una serie de mejoras que, desgraciadamente no suelen ser aplicadas por los desarrolladores/integradores.

Veamos pues la maneras que hay de configurar el jdbc

Oracle JDBC Thin usando SID

Desgraciadamente es la mas utilizada de todos, en esta se fija en cada fichero de pool de conexión tanto la Ip como el puerto como el SID de base de datos, lo que además de hacer muy costoso el cambio de alguno de los tres elementos, imposibilita todas las funciones asociadas a los servicios de Oracle.
jdbc:oracle:thin:@//host:puerto:ORACLE_SID
Ejemplo :

 jdbc:oracle:thin:@//192.168.73.6:1521:TEST

Oracle JDBC Thin usando Service Name:

Esta opción es similar a la anterior, solamente que se cambia el ORACLE_SID por el SERVICE_NAME, dista mucho de ser buena, pero al menos nos permite utilizar servicios.
jdbc:oracle:thin:@ //host:puerto:SERVICE_NAME
Ejemplo :

jdbc:oracle:thin:@//192.168.73.6:1521/TEST

Oracle JDBC Thin usando a TNSName:

Este es el método que deberíamos de recomendar, puesto que mantiene centralizado en el TNSNAMES.ora la gestión de la notación de las bases de datos Oracle
jdbc:oracle:thin:@TNSName
Ejemplo :

jdbc:oracle:thin:@TEST 

Esta funcionalidad fue añadida en la versión 10.2.0.1(lleva disponible desde mediados del 2004) por lo que en un sistema bien mantenido no deberíamos de tener ningún problema la compatibilidad el driver jdbc de Oracle que usemos (al contrario debería de ser un problema si usamos un driver mas antiguo de una 10.2.0.1)

A la hora de utilizar el TNSNAMES, nos encontramos con que el servidor de aplicaciones deberá de conocer la ubicación de este fichero. Para ello usamos la variable de entorno del sistema operativo que referencia a este fichero, la variable TNS_ADMIN .unido a la variable de entorno del sistema, el servidor de aplicaciones debe de contar con una propiedad específica para encontrarla , esta propiedad es oracle.net.tns_admin que se le puede pasar en en arranque del java como como java -Doracle.net.tns_admin=$TNS_ADMIN

Mas información como siempre en las notas de soporte

  • Can JDBC Thin Driver Connect Using Tns Entry in tnsnames.ora File (Doc ID 333686.1)
  • JDBC/thin does not Currently Support the IFILE Clause Inside a TNSNAMES.ORA File (Doc ID 1270872.1)