Parámetros de Base de datos a nivel PDB en Standby

Photo by Andrew Neel on Unsplash

Parámetros de Base de datos a nivel PDB en Standby

Recientemente se me ha planteado un escenario donde hay una diferencia de rendimiento notable entre una réplica de una CDB con una PDB en una Standby y la primaria.

Dicha réplica consiste en una Snapshot Standby de una BBDD con una PDB que se sincroniza diariamente a efectos de ser explotada por desarrollo disponiendo de la información más actual posible.

Los recursos de dicha réplica son menores que los de producción, pero tampoco es similar la carga, siendo mucho menos en el entorno replicado, por lo que no sería un inconveniente.

Saltan las alertas comparando una misma consulta, mismo plan en ambas, donde veo que la primera ejecución en ambas "se demora" (carga los datos en la buffer caché) y en consecutivas ejecuciones de la misma en producción es instantanea, mientras que en la Standby el tiempo requerido para la misma en la primera ejecución en similar, pero las consecutivas son x4 comparando con una ejecución buena en la primaria.

La diferencia entre ambos tiempos son los bloques leídos a nivel de buffer cache (logical reads), donde en la Standby acusa de más physical reads. Conclusión, es necesario revisar la SGA.

Veo en el alert que al abrir la PDB obtenemos el siguiente aviso:

Reducing shared_pool size across all PDBs because the sum (3072MB) is too large a percentage of CDB's SGA_TARGET

Bien, vamos a entender por qué. Detallo documentación.

In Database Reference 12.2 and later mentioned that the sum of below parameters on PDBs are managed considering the configuration of CDB.

- SGA_TARGET
- SGA_MIN_SIZE
- SHARED_POOL_SIZE
- DB_CACHE_SIZE

Ex)

Oracle Database Database Reference 12c Release 2 (12.2) E85634-06

Note:

This parameter is optional for pluggable databases (PDBs). When this parameter is set for a PDB, it indicates a possible minimum value for the PDB usage of the memory pool.

To be able to use Resource Manager in a CDB to control the amount of memory each PDB can use:

  • The NONCDB_COMPATIBLE initialization parameter must be set to FALSE at the CDB level (in the root of the CDB).

  • The MEMORY_TARGET initialization parameter must not be set at the CDB level.

  • If the SGA_TARGET initialization parameter is set at the CDB level, then the following requirement must be met:

    • The value of DB_CACHE_SIZE set in a PDB must be less than or equal to 50% of the SGA_TARGET value at the CDB level.
  • If the SGA_TARGET initialization parameter is set at the PDB level, then the following requirement must be met:

    • The value of DB_CACHE_SIZE set in a PDB must be less than or equal to 50% of the SGA_TARGET value at the PDB level.
  • If the SGA_TARGET initialization parameter is not set, but the DB_CACHE_SIZE initialization parameter is set at the CDB level, then the following requirement must be met:

    • The value of DB_CACHE_SIZE set in a PDB must be less than or equal to 50% of the DB_CACHE_SIZE value at the CDB level.

When you set DB_CACHE_SIZE in a PDB to a value that does not meet these requirements, you receive an error.

Como comenté anteriormente el nivel de recursos es más limitado en la Standby, por lo que la parametrización de SGA_TARGET y SGA_MAX_SIZE es menor (se configuró a la hora de desplegarla para ajustar a la memoria del servidor destino).

El valor db_cache_size está definido a nivel de PDB en la primaria que como sabemos es el valor mínimo reservado. Los parámetros definidos a nivel de PDB no podemos alterarlos a nivel de spfile ya que se almacenan en el diccionario de datos. De ahí que cada vez que se sincroniza con la primaria el valor viaja a la PDB de la Standby e incumplimos los requisitos de reserva de memoria a nivel de PDB.

Al viajar éste no cumple el cálculo a nivel de CDB. Muestro los valores para entenderlo:

BBDD (DB_UNIQUE_NAME)SGA_TARGET (CDB)DB_CACHE_SIZE(PDB)
Primaria (CDBPRIM)80G12G
Standby (CDBSTB)16G12G

Como vemos, centrando en db_cache_size que tiene definido valor, en producción se cumple que es menor del 50% en la CDB, mientras que en la Standby no.

Ya conocemos el problema, y a donde quiero llegar es a no tener el valor establecido a nivel de PDB en la Standby y dejarlo en ésta a nivel de CDB. De ésta manera me saltaré esa limitación y tendremos 12G que son necesarios para el correcto funcionamiento en dicha aplicación en el entorno de Standby.

¿Cómo hacemos esto? Existe un parámetro no documentado que podemos aplicar en la modificación de parámetros en BBDD donde indicamos el cb_unique_name al que aplica.

Starting with 12.1.0.2 there is a syntax enhancement to execute an ALTER SYSTEM SET statement with a DB_UNIQUE_NAME clause.

This clause provides a way to modify the system parameter with SCOPE=SPFILE inside the PDB on the primary database, but specify the db_unique_name of the standby database where the parameter value should really take effect.

Comencé siendo conservadora y planteando realizar un reset en la primaria para el db_unique_name de la Standby, queriendo ver si al sincronizar la Standby aplica el mismo principio que estableciendo un valor en concreto.

Valor previo a nivel de PDB del parámetro db_cache_size:

DB_UNIQ_NA    PDB_UID PDB_NAME   NAME                                               VALUE$
---------- ---------- ---------- -------------------------------------------------- ------------------------------
*          1834373939 PDBAP      db_cache_size                                      12884901888

Importante recalcar que el scope debe ser spfile, en caso contrario nos encontraremos con el siguiente error:

ERROR en línea 1:
ORA-65147: Se ha especificado DB_UNIQUE_NAME sin el ámbito SPFILE

Aunque es scope sea spfile la actualización a nivel de diccionario es inmediata.

SYS@cdbprim1> show con_name;

CON_NAME
------------------------------
PDBAP

alter system reset db_cache_size scope=spfile db_unique_name='CDBSTB' sid='*';

Al comprobar a nivel de PDB el valor del parámetro no hay cambio evidente

DB_UNIQ_NA    PDB_UID PDB_NAME   NAME                                               VALUE$
---------- ---------- ---------- -------------------------------------------------- ------------------------------
*          1834373939 PDBAP      db_cache_size                                      12884901888

Confirmo cuando se sincroniza la Standby que no ha habido cambio, era esperable. Sigue estableciendo 12Gb de Buffer caché.

Opto por la opción que personalmente pienso es más eficiente. Si tenemos un escenario donde tenemos parámetros a nivel de PDB y ésta se replica o se va a replicar con Standby definirlos para que apliquen en la primaria en primera instancia.

Si se decide a futuro replicarla revisarlos y parametrizar cada uno que aplique para la Standby.


SYS@cdbprim1> show con_name;

CON_NAME
------------------------------
PDBAP

alter system set db_cache_size=12G scope=spfile db_unique_name='cdbprim' sid='*';

-- Entrada en el alertlog

2023-10-10T15:17:38.339668+02:00
PDBAP(3):ALTER SYSTEM RESET db_cache_size SCOPE=SPFILE SID='*' PDB='PDBAP';

-- Compruebo parámetros a nivel de PDB

DB_UNIQ_NA    PDB_UID PDB_NAME   NAME                                               VALUE$
---------- ---------- ---------- -------------------------------------------------- ------------------------------
*          1834373939 PDBAP      db_cache_size                                      12884901888
cdbprim    1834373939 PDBAP      db_cache_size                                      12884901888

Como vemos sigue aplicando para todos los db_unique_name, a mayores del unique name de la primaria.

Espero siguiente sincronización y confirmo que el valor que sigue obteniendo la PDB son los 12Gb de la primaria.

Intento un reset del parámetro para ver si queda únicamente el valor que me interesa, que es aquel que solo aplica a la primaria. Resto de unique names cogería por defecto valor 0.

SYS@cdbprim1> show con_name;

CON_NAME
------------------------------
PDBAP

alter system reset db_cache_size scope=spfile  sid='*'; 
alter system set db_cache_size=12G scope=spfile db_unique_name='cdbprim' sid='*';

-- Compruebo parámetros a nivel de PDB
DB_UNIQ_NA    PDB_UID PDB_NAME   NAME                                               VALUE$
---------- ---------- ---------- -------------------------------------------------- ------------------------------
*          1834373939 PDBAP      db_cache_size                                      12884901888
cdbprim    1834373939 PDBAP      db_cache_size                                      12884901888

Llegados a este punto veo que es necesario reiniciar la BBDD primaria para que libere el valor para todos los db_unique_name y conserve únicamente el que hemos definido, quedando de la siguiente manera:

DB_UNIQ_NA    PDB_UID PDB_NAME   NAME                                               VALUE$
---------- ---------- ---------- -------------------------------------------------- ------------------------------
cdbprim    1834373939 PDBAP      db_cache_size                                      12884901888

Una vez dicho valor está únicamente para la primaria, cuando sincronice la Standby el valor que cogerá de db_cache_size será el que ya haya dejado yo preparado a nivel de CDB en la Standby: 12Gb. Y problema de rendimiento general resuelto.

Hay que recordar que es un parámetro no documentado, así que con cautela...