Criação de serviço read-only em um Active Data Guard

Uma das vantagens obtidas quando temos um ambiente Active Data Guard, é a possibilidade de termos um standby físico que fica aberto em modo read-only enquanto o Redo Apply está sendo executado. Isso permite que os dados mais recentes inseridos no ambiente primário sejam replicados e tenhamos consultas sendo executadas no standby, que retornam os mesmos resultados que seriam retornados caso a query fosse executada no banco primário.

Para que isso seja possível, um serviço precisa ser configurado para o standby, para que as aplicações que tem um workload de leitura sejam apontadas para o ambiente read only.

Criação do serviço via SRVCTL no Active Data Guard

Caso o banco de dados esteja rodando em um ambiente que tenha o Oracle Restart ou o Oracle Clusterware, a criação deve ser feita através do utilitário SRVCTL, pois assim o serviço criado será gerenciado por esses softwares, e iniciado automaticamente, caso assim seja configurado.

Para a adição do serviço read-only, executamos, tanto no host primário quanto no standby:

# no host primário
[oracle@host_rw ~]$ srvctl add service -d mydb -pdb mypdb -service my_service_ro -role physical_standby

# no host standby
[oracle@host_ro ~]$ srvctl add service -d mydbsby -pdb mypdb -service my_service_ro -role physical_standby

A opção -role permite configurar o serviço para que seja iniciado somente quando o banco esteja na função de physical standby. A criação do serviço deve ser feita tanto no ambiente primário quanto no standby para que quando uma role transition (switchover ou failover) ocorrer, o serviço seja iniciado corretamente no standby, indepentende do host. Para ambientes RAC as opções available e preferred devem ser configuradas também, indicando os nós nos quais o serviço irá rodar.

Aqui porém, temos um ponto importante. Caso essa adição seja feita, e façamos o comando de start do serviço no standby, teremos o seguinte erro:

[oracle@host_ro ~]$ srvctl start service -d mydbsby -service my_service_ro
PRCD-1084 : Failed to start service my_service_ro
PRCR-1079 : Failed to start resource ora.mydbsby.my_service_ro.svc
CRS-5017: The resource action "ora.mydbsby.my_service_ro.svc start" encountered the following error:
ORA-16000: database or pluggable database open for read-only access
ORA-06512: at "SYS.DBMS_SERVICE", line 5
ORA-06512: at "SYS.DBMS_SERVICE", line 288
ORA-06512: at line 1
. For details refer to "(:CLSN00107:)" in "/u01/app/oracle/diag/crs/host_ro/crs/trace/ohasd_oraagent_oracle.trc".

CRS-2674: Start of 'ora.mydbsby.my_service_ro.svc' on 'host_ro' failed

Isso ocorre porque ao iniciar o serviço pela primeira vez, ele é registrado no banco de dados, e tenta realizar a escrita no dicionário de dados. Como o ambiente é read-only, essa operação falha.

Para resolver essa situação devemos iniciar o serviço manualmente no primário, para que as devidas modificações sejam feitas, e replicadas para o standby através do Redo Apply, para que seja possível iniciar o serviço corretamente no standby:

# no host primário
[oracle@host_rw ~]$ srvctl start service -d mydb -service my_service_ro
[oracle@host_rw ~]$ srvctl stop service -d mydb -service my_service_ro
[oracle@host_rw ~]$ srvctl enable service -d mydb -service my_service_ro

# no host standby
[oracle@host_ro ~]$ srvctl start service -d mydbsby -service my_service_ro
[oracle@host_ro ~]$ srvctl status service -d mydbsby -service my_service_ro
Service my_service_ro is running
[oracle@host_ro ~]$ srvctl enable service -d mydbsby -service my_service_ro

Com o serviço habilitado, quando o banco for iniciado na função de standby físico, o serviço será iniciado automaticamente pelo Oracle Restart ou Oracle Clusterware.

Criação do serviço via DBMS_SERVICE no Active Data Guard

Em ambientes onde nem o Oracle Restart ou o Oracle Clusterware estão presentes, podemos usar a package DBMS_SERVICE para realizar a criação do serviço.

Para realizar a criação do serviço com a package:

BEGIN DBMS_SERVICE.CREATE_SERVICE(
    service_name => 'my_service_ro',
    network_name => 'my_service_ro');
END;
/

Para controlar a inicialização automática do serviço, utilizamos uma trigger AFTER STARTUP, validando a role do banco e o modo de abertura:

CREATE OR REPLACE TRIGGER service_startup
  AFTER STARTUP ON DATABASE
DECLARE
  db_role VARCHAR2(16);
  db_mode VARCHAR2(20);
BEGIN
  SELECT DATABASE_ROLE, OPEN_MODE INTO db_role, db_mode FROM V$DATABASE;
  IF db_role = 'PHYSICAL STANDBY' AND db_mode LIKE 'READ ONLY%' THEN
    DBMS_SERVICE.start_service('servico_standby');
  END IF;
END;
/

Dessa forma, sempre que o banco assumir a role de standby físico, e for aberto em modo READ ONLY ou READ ONLY WITH APPLY, o serviço será iniciado.

Conclusão

A utilização do standby físico para execução de consultas em ambientes Active Data Guard traz uma melhor utilização da infraestrutura de banco de dados, distribuindo a carga entre o primário e o standby, reduzindo o impacto sobre o banco primário. Vale destacar que essa capacidade não afeta a funcionalidade de recuperação de desastres do standby, apenas utiliza melhor a infraestrutura que estaria subutilizada sem o Active Data Guard.

Publicar comentário