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 Plan | PDB | Shares Directive |
BALANCEADO | HIPOFISE1 | 1 |
BALANCEADO | HIPOFISE2 | 1 |
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.
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
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