Broker y DGMGRL – Error al hacer Switchover

Estos días estoy haciendo pruebas con Dataguard y la forma de implementar la utilidad Broker para facilitar algunas tareas, concretamente el Switchover.

Todos los blogs, webs de autoayuda y las notas oficiales de Oracle te explican muy bien el procedimiento para habilitarlo. Pero en pocos lugares he visto un poco de «troubleshooting» con los errores más comunes, o qué puede pasar mientras lanzas comandos y no responden tan bien como las guías y tutoriales que estás siguiendo.

Será que soy muy curioso, y cada paso que doy me gusta comprobarlo, ver que hace, como se comporta… Además, tengo algo especial y es que me suelen pasar cosas que a nadie le pasan. O a lo mejor también les pasan, pero no las cuentan.

De eso va este rincón en la red, de contarte cada paso que de y cada chocazo que me pegue. Todo lo que consiga solucionar te lo voy a contar. Si alguna vez te pasa, aquí podrás encontrar la luz en tu oscuro camino.

Volviendo al tema principal, quiero implementar el uso de Broker en Dataguard. Estoy en un entorno de desarrollo, haciendo algunas pruebecillas y viendo como funciona la utilidad.

¿Qué es el broker?

El broker es una utilidad o herramienta que posee Oracle Database. Se utiliza para administrar, automatizar y centralizar la creación, mantenimiento y monitoreo de las configuraciones de un Dataguard.

Resalto configuraciones, porque creas, editas y mantienes configuraciones. Con el broker no puedes crear un Dataguard, ni realizar las tareas básicas de administración de una base de datos con Dataguard.

El interprete de comandos de esta utilidad es DGMGRL (Data Guard command-line interface).

La utilidad y su uso no precisa una licencia exclusiva o ampliación de los servicios que tengas contratados con Oracle. Ya viene incluida con la versión Enterprise de Oracle Database.

Por ejemplo, la funcionalidad «Active DataGuard» si que requiere de un licenciamiento especial, que en caso de no tener, no deberías usarla.

Habilitando el broker

Partimos de la base que ya tengo broker habilitado y «todo está bien configurado». Lo pongo entre comillas, porque de ser así, funcionaría todo de maravilla.

Fui siguiendo algunas guías junto con la documentación oficial de Oracle, y a priori, no me encontré con ningún obstáculo, por lo que supuse, que todo estaba correcto.

DGMGRL> create configuration dgbroker_config as primary database is dgbroker connect identifier is dgbroker;
Configuration "dgbroker_config" created with primary database "dgbroker"
DGMGRL> add database dgbroker_stby as connect identifier is dgbroker_stby;
Database "dgbroker_stby" added

DGMGRL> show configuration;

Configuration - dgbroker_config

  Protection Mode: MaxPerformance
  Members:
  dgbroker         - Primary database
    dgbroker_stby - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
DISABLED



DGMGRL> enable configuration;
Enabled.

DGMGRL> show configuration;

Configuration - dgbroker_config

  Protection Mode: MaxPerformance
  Members:
  dgbroker - Primary database
    dgbroker_stby    - Physical standby database 

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 32 seconds ago)

Aparentemente, todo bien como decía. Vamos ahora a probar la maquinaria.

Análisis del error

Broker habilitado y bases de datos agregadas a la configuración del broker. Todo está listo para la primera prueba.

Hacemos el primer switchover.

DGMGRL> switchover to dgbroker_stby;
Performing switchover NOW, please wait...
Operation requires a connection to database "dgbroker_stby"
Connecting ...
Connected to "dgbroker_stby"
Connected as SYSDBA.
New primary database "dgbroker_stby" is opening...
Operation requires start up of instance "dgbroker" on database "dgbroker"
Starting instance "dgbroker"...
Connected to an idle instance.
ORACLE instance started.
Connected to "dgbroker"
Database mounted.
Connected to "dgbroker"
Switchover succeeded, new primary is "dgbroker_stby"

TOMA YA!! 👏🏼🎉🙌🏼 A LA PRIMERA!

Ni yo mismo me lo creo. Qué fácil ha sido. Si esto funciona así de bien, qué fácil y qué sencillo es hacer un switchover con broker. Mucho mejor que el método de toda la vida haciendo 20 pasos de forma manual en cada instancia.

Venga, vamos a hacer otro switchover para dejar todo como estaba.

DGMGRL> switchover to dgbroker;
Performing switchover NOW, please wait...
Operation requires a connection to database "dgbroker"
Connecting ...
Connected to "dgbroker"
Connected as SYSDBA.
New primary database "dgbroker" is opening...
Operation requires start up of instance "dgbroker" on database "dgbroker_stby"
Starting instance "dgbroker"...
Unable to connect to database using (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))
ORA-12545: Connect failed because target host or object does not exist

Failed.
[W000 2024-11-22T10:55:09.300+01:00] Failed to attach to (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED))).

Please complete the following steps to finish switchover:
	start up and mount instance "dgbroker" of database "dgbroker_stby"

DGMGRL> 

Ooopssss!! Ya me extrañaba a mi… 🥲

Con la cantidad de problemas que me encuentro todos los días y que todo lo que puede pasar en el mundo, me pasa a mi, ya me parecía muy raro que esto fuera tan rodado.

Veamos el log del broker. (Sí, el broker también tiene su propio log).

El log del broker se llama drc<db_name>.log. En mi caso, que se llama dgbroker, pues el fichero se llama drcdgbroker.log.
Y donde lo encontramos? Por defecto en el mismo directorio donde tenemos el alert log de la base de datos.

Puedes encontrarlo con esta sencilla consulta:

select NAME,VALUE from v$diag_info where NAME='Diag Trace';

Consultamos el fichero de log, y encontramos las siguientes lineas:

2024-11-27T08:37:48.401+01:00     DMON: Registering 1 service/s with listener(s)
2024-11-27T08:37:48.401+01:00     DMON: Executing SQL [ALTER SYSTEM REGISTER]
2024-11-27T08:37:48.401+01:00     SQL [ALTER SYSTEM REGISTER] Executed successfully
2024-11-27T08:37:49.311+01:00     DMON: ERROR: Connect identifier "LISTENER_DGBROKER" could not be decomposed into name-value pairs; status=303, error=0
2024-11-27T08:37:49.312+01:00     DMON: SCI harvested (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))
2024-11-27T08:37:49.312+01:00     CLSR: clsr_crs_status CRS not configured, config = 2.
2024-11-27T08:37:49.312+01:00     DMON: Clusterware not configured; status -10

Más o menos nos viene a decir lo mismo que el mensaje anterior que veíamos en la consola DGMGRL.

No se puede conectar a la instancia dgbroker_stby por algún motivo que desconozco.

Antes de continuar, aplicamos lo que nos decía el error. Vamos a arrancar y dejar en estado MOUNT la instancia dgbroker_stby.

En este momento, el estado sería:

dgbroker ➡️ PRIMARY (open read write)
dgbroker_stby ➡️ STANDBY (mounted)

Causa del error

Vamos a realizar algunas pruebas de conectividad para ver si algo está fallando.

  • Revisión de tnsnames.ora y listener.ora ✅
  • lsnrctl status LISTENER_DGBROKER y LISTENER_DGBROKERSTBY ✅
  • TNSPING desde servidor1 a servidor2 ✅
  • TNSPING desde servidor2 a servidor1 ✅
  • Conexión con SQL*Plus desde dgbroker a dgbroker_stby ✅
  • Conexión con SQL*Plus desde dgbroker_stby a dgbroker ✅
  • Conexión con SQL*Plus a través del servicio dgbroker_DGMGRL de dgbroker desde los dos servidores ✅
  • Conexión con SQL*Plus a través del servicio dgbroker_stby_DGMGRL de dgbroker_stby desde los dos servidores ✅

Todas las pruebas que se me han ocurrido de conectividad entre las dos instancias y entre servidores, son satisfactorias.

Tras volver a revisar el error, veo un detalle en la cadena de conexión que había pasado por alto. Está intentando conectar por el puerto 1521, cuando yo todos los listener los tengo configurados en el puerto 1550.

Esto es muy raro. Yo en ningún momento he indicado ninguna cadena de conexión, ni el puerto. En mis tnsnames.ora y listener.ora, tampoco he indicado el host en las cadenas. ¿De donde ha cogido esta cadena de conexión? ¿Dónde está para poder cambiarla?

Reviso la configuración de cada base de datos.

DGMGRL> show database dgbroker;

Database - dgbroker

  Role:               PRIMARY
  Intended State:     TRANSPORT-ON
  Instance(s):
    dgbroker

Database Status:
SUCCESS



DGMGRL> show database dgbroker_stby

Database - dgbroker_stby

  Role:               PHYSICAL STANDBY
  Intended State:     APPLY-ON
  Transport Lag:      0 seconds (computed 1 second ago)
  Apply Lag:          0 seconds (computed 1 second ago)
  Average Apply Rate: 3.00 KByte/s
  Real Time Query:    OFF
  Instance(s):
    dgbroker

Database Status:
SUCCESS

Todo parece que está bien, nada extraño. Ni rastro tampoco de la cadena de conexión. Probamos otro comando para extraer más información de cada base de datos con verbose.

DGMGRL> show database verbose dgbroker_stby

Database - dgbroker_stby

  Role:               PHYSICAL STANDBY
  Intended State:     APPLY-ON
  Transport Lag:      0 seconds (computed 0 seconds ago)
  Apply Lag:          0 seconds (computed 0 seconds ago)
  Average Apply Rate: 83.00 KByte/s
  Active Apply Rate:  1.39 MByte/s
  Maximum Apply Rate: 80.86 MByte/s
  Real Time Query:    ON
  Instance(s):
    dgbroker

  Properties:
    DGConnectIdentifier             = 'dgbroker_stby'
    ObserverConnectIdentifier       = ''
    FastStartFailoverTarget         = ''
    PreferredObserverHosts          = ''
    LogShipping                     = 'ON'
    RedoRoutes                      = ''
    LogXptMode                      = 'ASYNC'
    DelayMins                       = '0'
    Binding                         = 'optional'
    MaxFailure                      = '0'
    ReopenSecs                      = '300'
    NetTimeout                      = '30'
    RedoCompression                 = 'DISABLE'
    PreferredApplyInstance          = ''
    ApplyInstanceTimeout            = '0'
    ApplyLagThreshold               = '30'
    TransportLagThreshold           = '30'
    TransportDisconnectedThreshold  = '30'
    ApplyParallel                   = 'AUTO'
    ApplyInstances                  = '0'
    StandbyFileManagement           = ''
    ArchiveLagTarget                = '0'
    LogArchiveMaxProcesses          = '0'
    LogArchiveMinSucceedDest        = '0'
    DataGuardSyncLatency            = '0'
    LogArchiveTrace                 = '0'
    LogArchiveFormat                = ''
    DbFileNameConvert               = ''
    LogFileNameConvert              = ''
    ArchiveLocation                 = ''
    AlternateLocation               = ''
    StandbyArchiveLocation          = ''
    StandbyAlternateLocation        = ''
    InconsistentProperties          = '(monitor)'
    InconsistentLogXptProps         = '(monitor)'
    LogXptStatus                    = '(monitor)'
    SendQEntries                    = '(monitor)'
    RecvQEntries                    = '(monitor)'
    HostName                        = 'servidor2'
    StaticConnectIdentifier         = '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))'
    TopWaitEvents                   = '(monitor)'
    SidName                         = '(monitor)'

  Log file locations:
    Alert log               : /oracle/dgbroker/admin/diag/rdbms/dgbroker_stby/dgbroker/trace/alert_dgbroker.log
    Data Guard Broker log   : /oracle/dgbroker/admin/diag/rdbms/dgbroker_stby/dgbroker/trace/drcdgbroker.log

Database Status:
SUCCESS

Aquí está!! 🤩🤩 Aquí está la cadena que está fallando y el puerto 1521 que nos daba el error de conexión. Detectado el problema, ahora vamos a buscarle solución.

Solución

Consultemos esta propiedad en las dos bases de datos:

DGMGRL> SHOW DATABASE 'dgbroker_stby' 'StaticConnectIdentifier';
  StaticConnectIdentifier = '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))'

DGMGRL> SHOW DATABASE 'dgbroker' 'StaticConnectIdentifier';
  StaticConnectIdentifier = '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=servidor1)(PORT=1550)))(CONNECT_DATA=(SERVICE_NAME=dgbroker_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))'

Se observa que en una está el puerto 1521 (Incorrecto) y en la otra el 1550 (Correcto).

Por este motivo, el switchover ha funcionado la primera vez, y no la segunda.

Toca corregir el problema. Editamos la propiedad en cuestión con la cadena correcta:

DGMGRL> EDIT DATABASE 'dgbroker_stby' SET PROPERTY StaticConnectIdentifier='(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=servidor2)(PORT=1550)))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))'
> ;
Property "staticconnectidentifier" updated

Comprobamos que el cambio se ha realizado:

DGMGRL> SHOW DATABASE 'dgbroker_stby' 'StaticConnectIdentifier';
  StaticConnectIdentifier = '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=servidor2)(PORT=1550))(CONNECT_DATA=(SERVICE_NAME=dgbroker_stby_DGMGRL)(INSTANCE_NAME=dgbroker)(SERVER=DEDICATED)))'

Solucionado esto, probamos de nuevo el switchover:

DGMGRL> switchover to dgbroker_stby;
Performing switchover NOW, please wait...
Operation requires a connection to database "dgbroker_stby"
Connecting ...
Connected to "dgbroker_stby"
Connected as SYSDBA.
New primary database "dgbroker_stby" is opening...
Operation requires start up of instance "dgbroker" on database "dgbroker"
Starting instance "dgbroker"...
Connected to an idle instance.
ORACLE instance started.
Connected to "dgbroker"
Database mounted.
Connected to "dgbroker"
Switchover succeeded, new primary is "dgbroker_stby"

DGMGRL> switchover to dgbroker;
Performing switchover NOW, please wait...
Operation requires a connection to database "dgbroker"
Connecting ...
Connected to "dgbroker"
Connected as SYSDBA.
New primary database "dgbroker" is opening...
Operation requires start up of instance "dgbroker" on database "dgbroker_stby"
Starting instance "dgbroker"...
Connected to an idle instance.
ORACLE instance started.
Connected to "dgbroker_stby"
Database mounted.
Connected to "dgbroker_stby"
Switchover succeeded, new primary is "dgbroker"

Funciona correctamente. El problema estaba ahí, en esa propiedad que había adoptado el puerto 1521 por defecto.

Como nota aclaratoria, me gustaría comentar que el switchover dejará las bases de datos en el estado original en el que se encontraban, cambiando el rol de PRIMARY por STANDBY y viceversa.

Digo esto, porque en una de las pruebas, tenía las dos instancias como OPEN, una OPEN READ WRITE y otra OPEN READ ONLY, como si estuviera usando ACTIVE DATAGUARD. Al hacer el switchover, las dos instancias quedaron como OPEN.

En caso de no tener la licencia de ACTIVE DATAGUARD y tener una instancia PRIMARY como OPEN READ WRITE y la STANDBY en estado MOUNTED mientras está recibiendo y aplicando archivelogs, cuando hagas el switchover, la infraestructura quedará tal y como estaba.

PRIMARY (open read write) ➡️ STANDBY (mounted)
STANDBY (mounted) ➡️PRIMARY (open read write)

Espero que sea de utilidad, y además del error, conozcas un poco más sobre Dataguard, Broker y DGMGRL. 😉

Error en conectividad SSH sin contraseña al instalar Grid Infrastructure 19c en RHEL8
Grid Infrastructure – Alto consumo de CPU por culpa de systemd-udevd

Deja un comentario