Using Resource Manager with CDB and PDBs

O Resource Manager nos permite gerenciar recursos de hardware alocados para o nosso database, e assim como já era implementado em ambientes non-CDB’s, também temos essa opção para a arquitetura Multitenant. Com ele, podemos controlar, por exemplo, recursos de CPU Time, Degree de Paralelismo, Limite de Sessões em Idle, etc. Nesse artigo, vamos explorar a criação de 2 planos de Resource Manager, com “Shares Directives” distintos, para vermos o reflexo disso entre 2 PDBs. A tabela abaixo ilustra o cenário de teste:

Resource Manager PlanPDBShares Directive
BALANCEADOHIPOFISE11
BALANCEADO HIPOFISE21
DESBALANCEADO HIPOFISE1 3
DESBALANCEADO HIPOFISE2 1

Validando nossos PDB’s:

[oracle@quiasma admin]$ sqlplus / as sysdba
 
SQL*Plus: Release 18.0.0.0.0 - Production on Thu Jun 10 05:36:56 2021
Version 18.13.0.0.0
 
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.13.0.0.0
 
SQL> SHOW PDBS;
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 HIPOFISE2                      READ WRITE NO
         4 HIPOFISE1                      READ WRITE NO

Agora vamos conectar em cada PDB, e criar o objeto PL/SQL abaixo, que realiza operações aritméticas, consumindo assim o recurso de CPU, que será gerenciado pelos planos de Resource Manager:

CREATE OR REPLACE PROCEDURE SYSTEM.HIT_CPU ( P_LOOP NUMBER ) 
IS 
    V_BEGIN DATE; 
    V NUMBER; 
 BEGIN 
  V_BEGIN := SYSDATE; 
  FOR I IN 1..P_LOOP*10000 LOOP 
   V := SQRT(I); 
  END LOOP; 
  DBMS_OUTPUT.PUT_LINE('ELAPSED TIME: ' || ROUND((SYSDATE-V_BEGIN)*24*60*60,2 )|| ' seconds'); 
  END HIT_CPU; 
/

PDB HIPOFISE1:

[oracle@quiasma admin]$ sqlplus system/oracle@HIPOFISE1
 
SQL*Plus: Release 18.0.0.0.0 - Production on Thu Jun 10 05:38:26 2021
Version 18.13.0.0.0
 
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
 
Last Successful login time: Thu Jun 10 2021 05:36:48 -03:00
 
Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.13.0.0.0
 
SQL> CREATE OR REPLACE PROCEDURE SYSTEM.HIT_CPU ( P_LOOP NUMBER )
IS
        V_BEGIN DATE;
        V NUMBER;
 BEGIN
  V_BEGIN := SYSDATE;
  FOR I IN 1..P_LOOP*10000 LOOP
   V := SQRT(I);
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('ELAPSED TIME: ' || ROUND((SYSDATE-V_BEGIN)*24*60*60,2 )|| ' seconds');
  END HIT_CPU;
/  2    3    4    5    6    7    8    9   10   11   12
 
Procedure created.

PDB HIPOFISE2:

[oracle@quiasma admin]$ sqlplus system/oracle@HIPOFISE2
 
SQL*Plus: Release 18.0.0.0.0 - Production on Thu Jun 10 05:41:05 2021
Version 18.13.0.0.0
 
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
 
Last Successful login time: Thu Jun 10 2021 05:38:26 -03:00
 
Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.13.0.0.0
 
SQL> CREATE OR REPLACE PROCEDURE SYSTEM.HIT_CPU ( P_LOOP NUMBER )
IS
        V_BEGIN DATE;
        V NUMBER;
 BEGIN
  V_BEGIN := SYSDATE;
  FOR I IN 1..P_LOOP*10000 LOOP
   V := SQRT(I);
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('ELAPSED TIME: ' || ROUND((SYSDATE-V_BEGIN)*24*60*60,2 )|| ' seconds');
  END HIT_CPU;
/  2    3    4    5    6    7    8    9   10   11   12
 
Procedure created.

Agora, conectado no CDB$ROOT, vamos criar o primeiro plano, onde a prioridade de CPU Time resource é igualmente distribuída entre os 2 PDBs:

[oracle@quiasma admin]$ sqlplus / as sysdba
 
SQL*Plus: Release 18.0.0.0.0 - Production on Thu Jun 10 05:42:27 2021
Version 18.13.0.0.0
 
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - Production
Version 18.13.0.0.0
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA();
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN('BALANCEADO', 'One share to HIPOFISE1 and HIPOFISE2');
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('BALANCEADO', 'HIPOFISE1', shares => 1);
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('BALANCEADO', 'HIPOFISE2', shares => 1);
 
PL/SQL procedure successfully completed.

Criando o segundo plano, onde o PDB HIPOFISE1 tem prioridade 3 vezes maior que o PDB HIPOFISE2:

SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN('DESBALANCEADO', 'HIPOFISE1 tem prioridade');
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('DESBALANCEADO', 'HIPOFISE1', shares => 3);
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('DESBALANCEADO', 'HIPOFISE2', shares => 1);
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
 
PL/SQL procedure successfully completed.
 
SQL> EXEC DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
 
PL/SQL procedure successfully completed.

Confirmando a existência dos 2 planos:

SQL> col plan format a20
SQL> SELECT Plan from CDB_CDB_Rsrc_Plans WHERE CON_ID = 1 AND PLAN IN ('BALANCEADO','DESBALANCEADO') ORDER BY 1;
 
PLAN
--------------------
BALANCEADO
DESBALANCEADO
 
SQL> col pluggable_database format a30
SQL> SELECT PLAN, PLUGGABLE_DATABASE, SHARES FROM CDB_CDB_RSRC_PLAN_DIRECTIVES WHERE CON_ID = 1 AND PLAN IN ('BALANCEADO','DESBALANCEADO') ORDER BY 1, 2;
 
PLAN                 PLUGGABLE_DATABASE                 SHARES
-------------------- ------------------------------ ----------
BALANCEADO           HIPOFISE1                               1
BALANCEADO           HIPOFISE2                               1
BALANCEADO           ORA$AUTOTASK
BALANCEADO           ORA$DEFAULT_PDB_DIRECTIVE               1
DESBALANCEADO        HIPOFISE1                               3
DESBALANCEADO        HIPOFISE2                               1
DESBALANCEADO        ORA$AUTOTASK
DESBALANCEADO        ORA$DEFAULT_PDB_DIRECTIVE               1
 
8 rows selected.

Habilitando o primeiro plano:

SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = BALANCEADO;
 
System altered.
 
SQL> col name format a20
SQL> SELECT NAME FROM V$RSRC_PLAN WHERE CON_ID = 1;
 
NAME
--------------------
BALANCEADO

Agora, vou abrir 2 sessões de Putty, logando como system no PDB HIPOFISE1, e mais 2 sessões conectando como system no PDB HIPOFISE2:

Com o “SET SERVEROUTPUT ON”, vou disparar a execução do comando “EXEC HIT_CPU(10000)” nas 4 sessões, o mais rápido possível, para rodarem em paralelo:

Podemos perceber que os tempos ficaram muito próximos (120,121,117 e 118 segundos), o que nos mostra que a distribuição de recurso de CPU Time foi uniforme aos 2 PDBs:

Alterando o plano do Resource Manager, para que passe a utilizar o que dá mais prioridade ao PDB HIPOFISE1:

SQL> conn / as sysdba
Connected.
SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = DESBALANCEADO;
 
System altered.
 
SQL> SELECT NAME FROM V$RSRC_PLAN WHERE CON_ID = 1;
 
NAME
--------------------------------
DESBALANCEADO

Disparando o mesmo teste, de forma simultânea, percebemos que as sessões do HIPOFISE1 tiveram prioridade (78 e 79 segundos), se comparadas com as sessões do HIPOFISE2 (116 e 117 segundos). Percebemos também que a diferença de tempo não é de 3 vezes, porém devemos considerar que uma vez finalizada o processamento necessário no HIPOFISE1, o Resource Manager pode engajar mais recursos para o processamento do HIPOFISE2. A priorização só acontece quando existe a concorrência de um contra o outro.

Alterando o CDB$ROOT para não utilizar nenhum plano customizado por nós:

SQL> conn / as sysdba
Connected.
SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = '';
 
System altered.
 
SQL> col name format a30
SQL> SELECT NAME FROM V$RSRC_PLAN WHERE CON_ID = 1;
 
NAME
------------------------------
ORA$INTERNAL_CDB_PLAN

Deletando os 2 planos usados neste artigo:

SQL> begin
DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA();
DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
DBMS_RESOURCE_MANAGER.DELETE_CDB_PLAN('BALANCEADO');
DBMS_RESOURCE_MANAGER.DELETE_CDB_PLAN('DESBALANCEADO');
DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
end;
/  2    3    4    5    6    7    8    9
 
PL/SQL procedure successfully completed.

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.

2 thoughts on “Using Resource Manager with CDB and PDBs”

  1. Obrigado pelo post Bruno, top! Queria entender o que que eh* ‘shares’.

    * desculpa nao instalei teclado pt-br no laptop do trabalho

    Cheers from the UK

    1. Obrigado por prestigiar o post, Antony!
      Esse conceito dos Shares é meio confuso, mas vou tentar explicar de um modo simples:
      Imagina que este é um número de proporção usado pelo Resource Manager, para distribuir os recursos do ambiente. Imaginemos que temos um PDB com valor share de 3, outro PDB com valor share de 3, e um último PDB com valor share de 1. Quanto maior este valor, mais prioridade o PDB terá. Neste exemplo, se você soma todos os Shares, temos o número 7 (3 +3 +1). Ou seja, o Oracle vai dividir os recursos do ambiente em 7, e distribuir estes recursos de acordo com o valor de cada PDB. Ou seja, o PDB 1 receberá 3/7 de recurso, o PDB 2 receberá 3/7 de recurso e o último PDB, que tem o menor número, receberá a menor proporção: 1/7.
      Abraços e desculpe a demora em retornar!!
      Bruno

Leave a Comment

Your email address will not be published.