به صورت پیش فرض common userها در محیط root container مجاز به مشاهده اطلاعات pdb containerها نیستند و حتی با داشتن مجوز select بر روی ویوهای _V$، GV$، CDB، نمی توانند اطلاعات containerهای دیگر را ببینید(البته common userهای ORACLE_MAINTAINED=N منظور است):
SQL> create user c##usef identified by a;
User created.
SQL> grant create session to c##usef;
Grant succeeded.
SQL> grant select on v_$session to c##usef;
Grant succeeded.
SQL> conn c##usef/a
Connected.
SQL> show con_name
CON_NAME
——————————
CDB$ROOT
SQL> select distinct con_id from v$session;
CON_ID
———-
1
0
برخلاف common userهای که ما ایجاد می کنیم، کاربرانی که توسط اوراکل ایجاد می شوند(نظیر کاربر sys وsystemء، ORACLE_MAINTAINED=Y) می توانند در محیط CDB$ROOT به اطلاعات همه containerها دسترسی داشته باشند:
SQL> show user
USER is “SYS”
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
———- —————————— ———- ———-
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
4 PDB2 READ WRITE NO
SQL> select distinct con_id from v$session;
CON_ID
———-
1
4
3
0
چرایی این مسئله به attributeای به نام CONTAINER_DATA برمی گردد. اگر این attribute برای objectای تنظیم شده باشد به آن object اصطلاحا container data object گفته می شود و common userها در root container نمی توانند به همه اطلات این دسته از objectها دسترسی داشته باشند(در حالت پیش فرض).
برای شناسایی container data objectها، ستونی با نام container_data به ویوی dba_views و dba_tables اضافه شده است که مشخص می کند خصیصه container_data برای آن ویو و یا جدول تنظیم شده است یا نه؟
SQL> select container_data from dba_views where view_name=’V_$SESSION’;
CONTAINER_DATA
————–
Y
برای آنکه کاربر c##usef بتواند همانند کاربران سیستمی sys و system، به ویوی v$session دسترسی کامل داشته باشد، می توان دستور زیر را اجرا کرد:
SQL> alter user C##USEF set container_data=all for sys.v_$session container=current;
User altered.
SQL> conn c##usef/a
Connected.
SQL> select distinct con_id from v$session;
CON_ID
———-
1
4
3
0
عبارت container_data=all در دستور alter user، سبب خواهد شد تا کاربر c##usef در صورت اتصال به root container، بتواند اطلاعات sessionهای همه containerهای دیگر(all) را ببینید. در صورتی که بخواهیم دسترسی را به یک یا چند container مشخص محدود کنیم، می توانیم دستور را به شکل زیر اصلاح کنیم:
SQL> alter user C##USEF set container_data = (cdb$root, pdb1) for sys.v_$session container=current;
User altered.
SQL> conn c##usef/a
Connected.
SQL> select distinct con_id from v$session;
CON_ID
———-
1
3
0
همچنین با اجرای دستور add container_data و remove container_data سطح دسترسی را تغییر داد:
SQL> alter user c##usef add container_data=(pdb2) for v_$session container=current;
User altered.
SQL> alter user c##usef remove container_data=(pdb2) for v_$session container=current;
User altered.
با کمک ویوی CDB_CONTAINER_DATA می توان مشاهده کرد که کدام کاربر و در چه سطحی به container data objectها دسترسی دارد. برای مثال، پرس و جوی زیر نشان می دهد که کاربر c##usef به چه container data objectای و در چه سطحی دسترسی خواهد داشت:
SQL> select username, owner, object_name, all_containers, container_name con_name from cdb_container_data where username=’C##USEF’;
USERNAME OWNER OBJECT_NAME ALL_CONTAINERS CON_NAME
——– —– ———– ————— ——–
C##USEF SYS V_$SESSION N CDB$ROOT
C##USEF SYS V_$SESSION N PDB1
به عنوان مثالی دیگر، پرس و جوی زیر کاربرانی که به همه container data object دسترسی دارند را لیست می کند:
select username from cdb_container_data where owner is null and all_containers=’Y’;
SYSTEM
DBSFWUSER
DBSNMP
SYS
SYSBACKUP
SYSDG
SYSRAC
اگر بخواهیم کاربر c##usef را هم به این لیست اضافه کنیم، می توانیم از دستور زیر استفاده کنیم:
SQL> alter user c##usef set container_data = all container = current;
User altered.
container_data = all همه containerها را شامل می شود. برای محدود کردن سطح دسترسی به pdb1 و pdb2 می توان از دستور زیر استفاده کرد:
SQL> alter user c##usef set container_data = (pdb1,cdb$root) container = current;
User altered.
همچنین اگر از این تصمیم منصرف شدیم(container_data = all) می توانیم container_data را به مقدار DEFAULT تنظیم کنیم:
SQL> alter user c##usef set container_data =default container = current;
User altered.