Skip to content
Keep Learning Keep Living
Keep Learning Keep Living
Keep Learning Keep Living

CONTAINER_DATA for Common Users

Mustafa, 2022-01-062022-01-06

Hello Everyone (if anyone reading this 🙂 ),

it has been a long year and I am glad it is over. As always, we hope the for “a time of period” like new year, birthday etc etc but hope is the only thing that we can hold on. I hope whole world get rid of this illness called corona, racism, wars (and again etc etc, list goes on)… Wish everyone a healthy, peaceful year.

In my personal blog, I mentioned vary of things and I realized that I didn’t mention about container database structure at all. Main reason for this is I was lazy on multi-tenant architecture and didn’t work on it, yeah, pretty much this was the reason 🙂

I wanted to start with common user’s container_data attribute (or property I am not sure). As you know, in multi-tenant architecture there two types of users COMMON and LOCAL. Common users are defined in the CDB (not in a pluggable database) and they are known by every current and future pdb. Local users are defined in a pluggable database and can access to only pluggable database they are defined. By saying “defined”, I mean “created”. So, local users don’t aware of other pluggable databases or container database (cdb) but common users are aware that they are in a CDB and can connect to PDBs on that CDB if they have privileges.

By default, newly created common users doesn’t see whole data in container data views or tables. what is “container data views”? As you noticed (even if you use non-cdb database 12c and above) there are some new columns on data dictionary and v$ views like CON_ID. in a multi-tenant database when a privileged user like SYS queried V$SESSION, user can see whole sessions in all containers (cdb$root and pdbs). Let’s see:

I will be running those queries on a 21.3 version. I have 3 PDBs on my CDB:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
select con_id, name from v$containers;
 
    CON_ID NAME
---------- ------------
         1 CDB$ROOT
         2 PDB$SEED
         3 PDB1
         4 PDB2
         5 PROXY_PDB

these are just dummy PDBs that I use for testing purpose on VM. Now Lets connect as SYS and query some views:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
sqlplus sys/oracle@192.168.56.102/cdb.localdomain as sysdba
 
Connected to:
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
----------------------------------------------------------------------------
 
show con_name
 
CON_NAME
------------------------------
CDB$ROOT
 
 
select con_id, count(*) number_of_sessions
from   v$session
group by con_id;
 
    CON_ID NUMBER_OF_SESSIONS
---------- ------------------
         1                  5
         0                 80
         3                  1
         5                  1
 
---------------------------------------------------------------------------
 
select con_id, count(*) number_of_data_files
from v$datafile
group by con_id;
 
    CON_ID NUMBER_OF_DATA_FILES
---------- --------------------
         1                    4
         2                    3
         5                    4
         3                    3
         4                    3

I connected as SYS and I am in the cdb$root container. I queried V$SESSION and V$DATAFILE views by grouping con_id column. I am able to see sessions on different PDBs, in my example, con_id 3 and 5 has 1 session each. V$DATAFILE query shows count of all data files per PDBs.

Now, let’s create a common user and give necessary privileges and query with that user:

Oracle PL/SQL
1
2
3
create user c##my_admin identified by oracle ;
 
grant dba to c##my_admin container=All;

I created C##MY_ADMIN user and grant DBA for all containers. So, this user can connect to any pdb and query any data dictionary view. for example, c##my_admin can connect to pdb1, pdb2 etc and query v$session in all of them and is able to see whole session for current pdb that user in it but problem is when c##my_admin connected to root (cdb$root), he/she won’t be able to see whole sessions in CDB (including PDB sessions). just the ones in cdb$root:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
conn c##my_admin/oracle@192.168.56.102/cdb.localdomain
Connected.
 
SQL> show user
USER is "C##MY_ADMIN"
SQL> show con_name
 
CON_NAME
------------------------------
CDB$ROOT
 
 
select con_id, count(*) number_of_sessions
  2  from   v$session
  3  group by con_id;
 
    CON_ID NUMBER_OF_SESSIONS
---------- ------------------
         1                  5
         0                 80
 
select con_id, count(*) number_of_data_files
from v$datafile
group by con_id;
 
    CON_ID NUMBER_OF_DATA_FILES
---------- --------------------
         1                    4

as you see, only sessions in con_id 1 which is cdb$root are listed. By the way, con_id 0 is CDB itself and only background processes are in there and they are listed in v$session all the time.

again, v$datafile lists only files in current container which is cdb$root. Please consider that c##my_admin is a DBA in CDB so it can connect to any PDB and query their data. it has necessary privileges for that. It has just don’t have “privilege” to query PDBs’ data in the CDB$ROOT container.

That is what CONTAINER_DATA does. it allows a common user to query some or all pdbs data in cdb$root. you must add necessary pdbs to common user’s container_data property:

Oracle PL/SQL
1
2
3
4
conn sys/oracle@192.168.56.102/cdb.localdomain as sysdba
 
alter user c##my_admin set container_data=(pdb1,pdb2, cdb$root) container=current;
User altered.

this alter must be done by a privileged user in cdb$root container. Here, I set container_data of c##my_admin user as PDB1, PDB2 (con_ids are 3 and 4) and CDB$ROOT.

there are few important keys here:

  1. this command must be run in cdb$root.
  2. CDB$ROOT must be in container_data list because it is the root and common user will query data in it so, it must be able to see it
  3. CONTAINER=CURRENT is mandatory because by default it is ALL and this command can be run only in cdb$root which is “current”

so, c##my_admin will be able to see whole sessions in v$session for cdb$root, pdb1 and pdb2 (not PROXY_PDB which its con_id is 5). Let’s see:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
conn c##my_admin/oracle@192.168.56.102/cdb.localdomain
Connected.
 
 
select con_id, count(*) number_of_sessions
from   v$session
group by con_id;
 
    CON_ID NUMBER_OF_SESSIONS
---------- ------------------
         1                  5
         0                 80
         3                  1
 
-------------------------------------------------------------------------
 
select con_id, count(*) number_of_data_files
from v$datafile
group by con_id;
 
    CON_ID NUMBER_OF_DATA_FILES
---------- --------------------
         1                    4
         3                    3
         4                    3

so, c##my_admin is able to query other pdbs data in cdb$root. There is no session in pdb2 by the way, that is why no session for con_id 4 in v$session.

instead of giving all container data view access you can specified necessary view as this:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
conn sys/oracle@192.168.56.102/cdb.localdomain as sysdba
Connected.
 
alter user c##my_admin set container_data=default container=current;
 
User altered.
 
alter user c##my_admin set container_data=(pdb1, pdb2, cdb$root) for v_$session container=current;
 
User altered.

by setting container_data to default it will reset everything. now, I just add container_data info just for V_$session view (which is based view for v$session, you can not grant on v$session) and query v$session and datafile again with c##my_admin:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
conn c##my_admin/oracle@192.168.56.102/cdb.localdomain
Connected.
 
select con_id, count(*) number_of_sessions
from   v$session
group by con_id;
 
    CON_ID NUMBER_OF_SESSIONS
---------- ------------------
         1                  5
         0                 80
         3                  1
 
--------------------------------------------------------------
 
select con_id, count(*) number_of_data_files
from v$datafile
group by con_id;
 
    CON_ID NUMBER_OF_DATA_FILES
---------- --------------------
         1                    4

here it is. we can see session rows for other pdbs in v$session but not for v$datafile.

if you want to set all pdbs at once:

Oracle PL/SQL
1
alter user c##my_admin set container_data=all for v_$session container=current;

you can use ALL clause for pdb list. remember when you use SET as “ALTER USER … SET CONTAINER_DATA” it will overwrite previous container_data property. if you want to add a new PDB into container_data list then you can use ADD instead of SET:

Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
--reset all
alter user c##my_admin set container_data=default container=current;
 
--assign container_data list
alter user c##my_admin set container_data=(pdb1, pdb2, cdb$root) for v_$session container=current;
 
--add a new pdb into previous list
alter user c##my_admin add container_data=(proxy_pdb) for v_$session container=current;
 
--remove a pdb from list
alter user c##my_admin remove container_data=(proxy_pdb) for v_$session container=current;

You can query who has access to what using CDB_CONTAINER_DATA data dictionary view.

Oracle PL/SQL
1
2
3
4
5
6
7
select * from CDB_CONTAINER_DATA where username = 'C##MY_ADMIN';
 
USERNAME      DEFAULT_ATTR OWNER  OBJECT_NAME  ALL_CONTAINERS CONTAINER_NAME  CON_ID
------------- -            ------ ------------ -------------- --------------- -------
C##MY_ADMIN   N            SYS    V_$SESSION   N              CDB$ROOT        1
C##MY_ADMIN   N            SYS    V_$SESSION   N              PDB1            1
C##MY_ADMIN   N            SYS    V_$SESSION   N              PDB2            1

I hope this will helpful, any comments is appreciated.

Thanks for reading, wish you healthy days.

12c 18c 19c 21c cdbcommon usercommon user privilegecontainer databasecontainer_datadata dictionarymulti-tenantmultitenantpdbs

Post navigation

Previous post
Next post

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • How to call HTTPS Url Without SSL Wallet in 19c
  • Is Table Unnecessary for Pipelined Function
  • Password Rollover Time in Seconds
  • PDB Syncronization Issue
  • How to limit DB Link Connection Timeout
  • Cloud Base Database Service
  • 29th of February and interval
  • How to Copy Local Files to Oracle Object Storage

Recent Comments

  • Mustafa on How to call HTTPS Url Without SSL Wallet in 19c
  • Накрутка авито on How to call HTTPS Url Without SSL Wallet in 19c
  • Mustafa on Cloud Base Database Service
  • Raja on Cloud Base Database Service
  • Mustafa on Refreshable PDB and ORA-17627: ORA-12578: TNS:wallet open failed

Categories

  • 11g
  • 12c
  • 18c
  • 19c
  • 21c
  • 23ai
  • Administration
  • Cloud
  • Compression
  • Development
  • Materialized View
  • Multi-tenant
  • Performance
  • Security
  • SQL / PLSQL
  • Uncategorized
  • Undocumented
  • Useful Scripts

Archives

  • April 2025
  • November 2024
  • July 2024
  • April 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • October 2021
  • September 2021
  • August 2021
  • April 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • July 2019
  • June 2019
  • May 2019
  • March 2019
  • February 2019
  • June 2018

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

RSS Follow This Blog

  • How to call HTTPS Url Without SSL Wallet in 19c
  • Is Table Unnecessary for Pipelined Function
  • Password Rollover Time in Seconds
  • PDB Syncronization Issue
  • How to limit DB Link Connection Timeout
  • Cloud Base Database Service
  • 29th of February and interval
  • How to Copy Local Files to Oracle Object Storage
  • Guid vs Sequences
  • Refreshable PDB and ORA-17627: ORA-12578: TNS:wallet open failed

Archives

  • April 2025
  • November 2024
  • July 2024
  • April 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • October 2021
  • September 2021
  • August 2021
  • April 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • July 2019
  • June 2019
  • May 2019
  • March 2019
  • February 2019
  • June 2018

RSS Follow This Blog

  • How to call HTTPS Url Without SSL Wallet in 19c
  • Is Table Unnecessary for Pipelined Function
  • Password Rollover Time in Seconds
  • PDB Syncronization Issue
  • How to limit DB Link Connection Timeout
  • Cloud Base Database Service
  • 29th of February and interval
  • How to Copy Local Files to Oracle Object Storage
  • Guid vs Sequences
  • Refreshable PDB and ORA-17627: ORA-12578: TNS:wallet open failed
RSS Error: A feed could not be found at `http://www.mywebsite.com/feed/`; the status code is `200` and content-type is `text/html; charset=UTF-8`
©2025 Keep Learning Keep Living | WordPress Theme by SuperbThemes