Configuring Apply Lag Tolerance in an Active Data Guard environment

Em ambientes que possuam a opção de Active Data Guard habilitada, temos um recurso importante para controle de tolerância de Lag (de apply log), materializado em um parâmetro de sessão chamado STANDBY_MAX_DATA_DELAY. Neste artigo, vamos explorar em termos práticos esse item.

Validando ambiente que será utilizado para testes:

[oracle@fornix1 ~]$ sqlplus / as sysdba
 
SQL*Plus: Release 19.0.0.0.0 - Production on Tue Jun 1 06:14:22 2021
Version 19.3.0.0.0
 
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
 
SQL> SELECT NAME,OPEN_MODE,DATABASE_ROLE FROM V$DATABASE;
 
NAME      OPEN_MODE            DATABASE_ROLE
--------- -------------------- ----------------
CORTEX    READ WRITE           PRIMARY
[oracle@fornix2 trace]$ sqlplus / as sysdba
 
SQL*Plus: Release 19.0.0.0.0 - Production on Tue Jun 1 06:15:20 2021
Version 19.3.0.0.0
 
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
 
SQL> SELECT NAME,OPEN_MODE,DATABASE_ROLE FROM V$DATABASE;
 
NAME      OPEN_MODE            DATABASE_ROLE
--------- -------------------- ----------------
CORTEX    READ ONLY WITH APPLY PHYSICAL STANDBY

Através do teste abaixo, no banco Standby, constatamos que este parâmetro não é habilitado para usuários administrativos:

SQL> SHOW USER;
USER is "SYS"
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=30;
ERROR:
ORA-03174: STANDBY_MAX_DATA_DELAY does not apply to SYS users

O parâmetro em questão possui 3 valores possíveis, sendo que o seu valor padrão é NONE, que significa que a consulta será exibida no Standby independente se há delay ou não em relação ao Primary. Vamos realizar o teste abaixo, criando um tabela e populando-a no Primary:

SQL> SELECT NAME,OPEN_MODE,DATABASE_ROLE FROM V$DATABASE;
 
NAME      OPEN_MODE            DATABASE_ROLE
--------- -------------------- ----------------
CORTEX    READ WRITE           PRIMARY
 
SQL> CREATE TABLE SOE.TESTE1 (DESCRICAO VARCHAR2(20));
 
Table created.
 
SQL> INSERT INTO SOE.TESTE1 (DESCRICAO) VALUES ('ACTIVE DATA GUARD');
 
1 row created.
 
SQL> COMMIT;
 
Commit complete.

No standby, logado com um usuário não administrativo, vamos definir o valor do parâmetro para NONE e consultar a tabela recentemente criada:

SQL> conn SOE/soe
Connected.
SQL> SHOW USER;
USER is "SOE"
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=NONE;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD

Porém percebemos que não existe Lag no ambiente no momento:

SQL> conn / as sysdba
Connected.
SQL> SELECT value "Lag", datum_time "Received Time", Time_Computed "Time Computed " FROM V$DATAGUARD_STATS WHERE name like 'apply lag';
 
Lag
----------------------------------------------------------------
Received Time                  Time Computed
------------------------------ ------------------------------
+00 00:00:00
06/01/2021 06:24:32            06/01/2021 06:24:33

Vamos parar o processo de Redo Apply no Standby:

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
 
Database altered.

Inserindo mais um registro na tabela do Primary:

SQL> INSERT INTO SOE.TESTE1 (DESCRICAO) VALUES ('SEM REDO APPLY');
 
1 row created.
 
SQL> COMMIT;
 
Commit complete.

Realizando novamente a consulta no Standby, percebemos que só 1 registro é exibido:

SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD

Constatamos que com o valor NONE, as consultas no Standby continuarão a funcionar, mesmo se houver LAG entre o primary e standby (e mesmo que isso signifique diferença de dados):

SQL> conn / as sysdba
Connected.
SQL> SELECT value "Lag", datum_time "Received Time", Time_Computed "Time Computed " FROM V$DATAGUARD_STATS WHERE name like 'apply lag';
 
Lag
----------------------------------------------------------------
Received Time                  Time Computed
------------------------------ ------------------------------
+00 00:02:43
06/01/2021 06:28:02            06/01/2021 06:28:03

Outra possibilidade de nosso parâmetro seria um valor que representa a quantidade de segundos aceitáveis para o Lag. Para realizar este teste, vou habilitar novamente o Redo Apply, definir 180 segundos de Delay, e desligar o Redo Apply e acompanhar o desfecho:

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
 
Database altered.
 
SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD
SEM REDO APPLY

Parando Redo Apply:

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
 
Database altered.

Definindo valor do parâmetro em 180 segundos. Ou seja, conseguiremos consultar informações que possuam até esse limite:

SQL> conn SOE/soe
Connected.
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=180;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD
SEM REDO APPLY
 
SQL> conn / as sysdba
Connected.
SQL> SELECT value "Lag", datum_time "Received Time", Time_Computed "Time Computed " FROM V$DATAGUARD_STATS WHERE name like 'apply lag';
 
Lag
----------------------------------------------------------------
Received Time                  Time Computed
------------------------------ ------------------------------
+00 00:01:58
06/01/2021 06:33:51            06/01/2021 06:33:53

Em paralelo vou criar o terceiro registro no Primary:

SQL> INSERT INTO SOE.TESTE1 (DESCRICAO) VALUES ('BSS');
 
1 row created.
 
SQL> COMMIT;
 
Commit complete.

No standby, como o Redo Apply está desligado, só conseguimos ver 2 registros (pois o Lag ainda não atingiu 180 segundos):

SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD
SEM REDO APPLY

Porém, uma vez o limite excedido, a mensagem abaixo é reportada:

SQL> conn SOE/soe
Connected.
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=180;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
SELECT * FROM SOE.TESTE1
*
ERROR at line 1:
ORA-03172: STANDBY_MAX_DATA_DELAY of 180 seconds exceeded

O último valor possível de nosso parâmetro seria 0, onde o objetivo é garantir que a consulta no Standby esteja idêntica caso fosse executada no primary, a menos que haja algum Lag, o que causaria erro. No exemplo abaixo, como a tabela no primary possui 3 registros e no standby apenas 2 (por conta do Redo Apply estar parado), uma mensagem é reportada:

PRIMARY:
 
SQL> select * from SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD
SEM REDO APPLY
BSS
 
STANDBY:
 
SQL> SELECT value "Lag", datum_time "Received Time", Time_Computed "Time Computed " FROM V$DATAGUARD_STATS WHERE name like 'apply lag';
 
Lag
----------------------------------------------------------------
Received Time                  Time Computed
------------------------------ ------------------------------
+00 13:01:11
06/01/2021 19:33:10            06/01/2021 19:33:10
 
 
SQL> conn SOE/soe
Connected.
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=0;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
SELECT * FROM SOE.TESTE1
*
ERROR at line 1:
ORA-03172: STANDBY_MAX_DATA_DELAY of 0 seconds exceeded

Vamos habilitar o Redo Apply:

SQL> conn / as sysdba
Connected.
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
 
Database altered.

Realizando novamente a consulta no Standby. Mesmo assim o erro ainda é reportado, nos dando a impressão que ainda há algum lag (mesmo que nossa consulta de referência mostre que não):

SQL> SELECT value "Lag", datum_time "Received Time", Time_Computed "Time Computed " FROM V$DATAGUARD_STATS WHERE name like 'apply lag';
 
Lag
----------------------------------------------------------------
Received Time                  Time Computed
------------------------------ ------------------------------
+00 00:00:00
06/01/2021 19:45:30            06/01/2021 19:45:31
 
 
SQL> conn SOE/soe
Connected.
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=0;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
SELECT * FROM SOE.TESTE1
                  *
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-03172: STANDBY_MAX_DATA_DELAY of 0 seconds exceeded
 
 
SQL> alter session sync with primary;
ERROR:
ORA-03173: Standby may not be synced with primary

Logo percebemos que o “SYNC WITH PRIMARY” só é permitido quando o Transport Service está no modo SYNC, que não é o nosso caso:

log_archive_dest_2                   string      SERVICE=cortexDR ASYNC VALID_F
                                                 OR=(ONLINE_LOGFILES,PRIMARY_RO
                                                 LE) DB_UNIQUE_NAME=cortexDR

Vou parar o Redo Apply e alterar este parâmetro no primário:

STANDBY:
 
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
 
Database altered.
 
PRIMARY:
 
SQL> ALTER SYSTEM SET log_archive_dest_2='SERVICE=cortexDR SYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=cortexDR';
 
System altered.

Ao iniciar Redo Apply no Standby e fazer o teste novamente, o mesmo erro é reportado. Desse modo, alteramos o parâmetro “archive_lag_target” no banco Primary para o valor 0:

SQL> ALTER SYSTEM SET archive_lag_target=0;
 
System altered.
 
SQL> shu immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup;
ORACLE instance started.
 
Total System Global Area 2583690520 bytes
Fixed Size                  8899864 bytes
Variable Size             553648128 bytes
Database Buffers         2013265920 bytes
Redo Buffers                7876608 bytes
Database mounted.
Database opened.

Testando novamente no Standby:

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
 
Database altered.
 
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
 
Database altered.
 
SQL> conn SOE/soe
Connected.
SQL> ALTER SESSION SET STANDBY_MAX_DATA_DELAY=0;
 
Session altered.
 
SQL> SELECT * FROM SOE.TESTE1;
 
DESCRICAO
--------------------
ACTIVE DATA GUARD
SEM REDO APPLY
BSS

Obs: Este procedimento foi criado pelo senhor Ahmed Baraka (www.ahmedbaraka.com) e foi apenas reproduzido por mim em um laboratório pessoal para fins de aprendizado.

Leave a Comment

Your email address will not be published.