Quando fui pensar em reproduzir este artigo, confesso que criei muita confusão com o recurso que tentarei demonstrar, e precisei assistir minhas aulas umas duas ou três vezes (do curso do Ahmed Baraka, link AQUI) , recorrer à documentação oficial da Oracle (link AQUI)e aos artigos do Tim Hall (link AQUI). Mas o bom disso é tentarmos aprender algo novo sempre, e é isso que faz do nosso trabalho algo desafiador e estimulante.
Quando criamos um common user em nosso ambiente Multitenant, nós usamos o parâmetro CONTAINER=ALL, que significa que aquele usuário está sendo criado em todos os containers (e naqueles que serão criados posteriormente). O mesmo conceito se refere ao conceder privilégios. Quando este valor é declarado, o privilégio é concedido em todos os containers. Caso precise de exemplo, demonstrei NESTE artigo. Até aqui, tudo bem. Observemos nosso usuário abaixo:
[oracle@quiasma ~]$ sqlplus / as sysdba
SQL*Plus: Release 18.0.0.0.0 - Production on Tue Apr 13 20:25: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> CREATE USER C##BRUNO2 IDENTIFIED BY oracle CONTAINER=ALL;
User created.
SQL> GRANT CREATE SESSION TO C##BRUNO2 CONTAINER=ALL;
Grant succeeded.
SQL> col username format a30
SQL> SELECT DISTINCT USERNAME,COMMON FROM CDB_USERS WHERE COMMON='YES' AND USERNAME LIKE '%BRUNO2%';
USERNAME COM
------------------------------ ---
C##BRUNO2 YES
Concedendo privilégio na view v$datafile para todos os containers:
SQL> GRANT SELECT ON SYS.V_$DATAFILE TO C##BRUNO2 CONTAINER=ALL;
Grant succeeded.
Logado no root container com o usuário criado, percebemos que a consulta retornará apenas os datafiles do root container (que é o current), e não de todos os PDBs:
SQL> CONN C##BRUNO2/oracle
Connected.
SQL> SHOW USER;
USER is "C##BRUNO2"
SQL> SELECT name from v$datafile;
NAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/oracle/dados/TALAMO/datafile/o1_mf_system_j3w17w26_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_sysaux_j3w1bkdm_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_undotbs1_j3w1cyoh_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_users_j3w1czy4_.dbf
Se quisermos ver os datafiles de algum outro PDB, precisaremos conectar no mesmo:
SQL> CONN C##BRUNO2/oracle@HIPOFISE1
Connected.
SQL> SHOW USER;
USER is "C##BRUNO2"
SQL> SELECT name from v$datafile;
NAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_system_j781yvm6_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_sysaux_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_undotbs1_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_users_j7824z91_.dbf
O cerne deste recurso está aqui: poder alterar nosso usuário para que possa consultar os dados de todos os containers caso queira, ou apenas algu container em específico, utilizando o parâmetro CONTAINER_DATA. Abaixo farei uma alteração em nossos usuário e definirei o valor deste parâmetro para ALL, que significa que todos os containers (inclusive os criados posteriormente) serão contemplados:
SQL> conn / as sysdba
Connected.
SQL> SHOW CON_ID CON_NAME
CON_ID
------------------------------
1
CON_NAME
------------------------------
CDB$ROOT
SQL> ALTER USER C##BRUNO2 SET CONTAINER_DATA=ALL FOR V_$DATAFILE CONTAINER=CURRENT;
User altered.
Realizando teste:
SQL> conn C##BRUNO2/oracle@TALAMO
Connected.
SQL> SHOW USER;
USER is "C##BRUNO2"
SQL> SELECT name from v$datafile;
NAME
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/oracle/dados/TALAMO/datafile/o1_mf_system_j3w17w26_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_sysaux_j3w1bkdm_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_undotbs1_j3w1cyoh_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_system_j3w1q776_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_sysaux_j3w1q76z_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_users_j3w1czy4_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_undotbs1_j3w1q779_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_system_j781yvm6_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_sysaux_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_undotbs1_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_users_j7824z91_.dbf
/oracle/dados/TALAMO/BFE3BC783DEA324EE0536A00A8C0486E/datafile/o1_mf_system_j7d9759c_.dbf
/oracle/dados/TALAMO/BFE3BC783DEA324EE0536A00A8C0486E/datafile/o1_mf_sysaux_j7d9759j_.dbf
/oracle/dados/TALAMO/BFE3BC783DEA324EE0536A00A8C0486E/datafile/o1_mf_undotbs1_j7d9759k_.dbf
14 rows selected.
Agora imaginemos que temos um common user que por algum motivo, não pode ter acesso à um PDB em específico. Com este recurso, podemos configurar o acesso aos outros PDBs, exceto aquele que não desejamos. Vejamos os PDBs que possuo em meu laboratório:
SQL> conn / as sysdba
Connected.
SQL> COL NAME FOR A40
SQL> SELECT NAME,OPEN_MODE,GUID FROM V$PDBS;
NAME OPEN_MODE GUID
---------------------------------------- ---------- --------------------------------
PDB$SEED READ ONLY BC8B772AA6A82204E0536B00A8C0CF6B
HIPOFISE1 READ WRITE BFC37CDFCB3A0CF9E0536A00A8C0C9C5
HIPOFISE2 READ WRITE BFE3BC783DEA324EE0536A00A8C0486E
Vamos simular que não queremos que nosso common user tenha acesso à v$datafile do PDB HIPOFISE2. Podemos realizar a seguinte alteração:
SQL> ALTER USER C##BRUNO2 SET CONTAINER_DATA=(CDB$ROOT, HIPOFISE1) FOR V_$DATAFILE CONTAINER=CURRENT;
User altered.
Percebemos que o usuário não consegue retornar as informações do PDB HIPOFISE2:
SQL> CONN C##BRUNO2/oracle@TALAMO
Connected.
SQL> COL NAME FOR A100
SQL> SELECT NAME FROM V$DATAFILE;
NAME
----------------------------------------------------------------------------------------------------
/oracle/dados/TALAMO/datafile/o1_mf_system_j3w17w26_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_sysaux_j3w1bkdm_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_undotbs1_j3w1cyoh_.dbf
/oracle/dados/TALAMO/datafile/o1_mf_users_j3w1czy4_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_system_j781yvm6_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_sysaux_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_undotbs1_j781yvmc_.dbf
/oracle/dados/TALAMO/BFC37CDFCB3A0CF9E0536A00A8C0C9C5/datafile/o1_mf_users_j7824z91_.dbf
8 rows selected.
Para finalizar, caso precisemos consultar as configurações a nível de CONTAINER_DATA, podemos usar a query abaixo:
column username format a10
column default_attr format a7
column owner format a6
column object_name format a11
column all_containers format a3
column container_name format a10
column con_id format 999
set pages 100
set line 200
SELECT USERNAME, DEFAULT_ATTR, OWNER, OBJECT_NAME, ALL_CONTAINERS, CONTAINER_NAME, CON_ID
FROM CDB_CONTAINER_DATA WHERE username NOT IN ('GSMADMIN_INTERNAL', 'APPQOSSYS', 'DBSNMP') ORDER BY USERNAME;
SQL> CONN / AS SYSDBA
Connected.
SQL> column username format a10
column default_attr format a7
column owner format a6
column object_name format a11
column all_containers format a3
column container_name format a10
column con_id format 999
set pages 100
set line 200
SELECT USERNAME, DEFAULT_ATTR, OWNER, OBJECT_NAME, ALL_CONTAINERS, CONTAINER_NAME, CON_ID
FROM CDB_CONTAINER_DATA WHERE username NOT IN ('GSMADMIN_INTERNAL', 'APPQOSSYS', 'DBSNMP') ORDER BY USERNAME;SQL> SQL> SQL> SQL> SQL> SQL> SQL> SQL> SQL> 2
USERNAME DEFAULT OWNER OBJECT_NAME ALL CONTAINER_ CON_ID
---------- ------- ------ ----------- --- ---------- ------
C##BRUNO2 N SYS V_$DATAFILE N CDB$ROOT 1
C##BRUNO2 N SYS V_$DATAFILE N HIPOFISE1 1
C##BRUNO2 Y Y 1
DBSFWUSER Y Y 1
SYS Y Y 1
SYSBACKUP Y Y 1
SYSDG Y Y 1
SYSRAC Y Y 1
SYSTEM Y Y 1
9 rows selected.
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.