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_SIZEEx)
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 toFALSE
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 theSGA_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 theSGA_TARGET
value at the PDB level.If the
SGA_TARGET
initialization parameter is not set, but theDB_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 theDB_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) | 80G | 12G |
Standby (CDBSTB) | 16G | 12G |
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...