با ارائه ویژگی multitenant در اوراکل 12c، نوع دیگری از کاربر به نام common user ارائه شد که در محیط cdb قابل ایجاد می باشد و در pdbهای مختلف تکثیر خواهد شد.
توجه! اگر در زمان ساخت این نوع از کاربر، pdbای در حالت open read write قرار نداشته باشد، ساخت کاربر در این pdb، به زمان باز شدن آن به صورت read write موکول خواهد شد.
این نوع از کاربر، در صورت دارا بودن مجوز لازمه، به pdbهای مختلف، امکان دسترسی خواهد داشت. کاربرد عمده این نوع از کاربر، در انجام عملیات مدیریتی می باشد.
نکته: علاوه بر common user، نوع دیگری از کاربر هم در محیط multitenant وجود دارد که تنها در محیط pdb قابل ایجاد می باشد این نوع از کاربرها، به local user معروف هستند و خصوصیتهای مشابه ای را با کاربران حاضر در محیط non-cdb دارند.
به طور کلی دو نوع از common user در بانک موجود یا قابل ایجاد می باشند نوع اول انها همانند sys، system و … توسط اوراکل و در زمان ایجاد بانک ساخته شده(ORACLE_MAINTAINED=Y) و نوع دوم هم بعد از ساخت بانک قابل ایجاد می باشند(ORACLE_MAINTAINED=N).
در این متن، به طور مختصر، به تعدادی از مسائل و چالشهای مربوط به نوع دوم از common userها خواهیم پرداخت.
برای تفکیک اسامی common user(نوع دوم) از local user، اسامی آنها با پیشوند ##c شروع می شوند(به طور پیش فرض):
SQL> create user c##usef identified by usef;
User created.
که این پیشوند از طریق پارامتر COMMON_USER_PREFIX تعیین می شود:
SQL> show parameter COMMON_USER_PREFIX
NAME VALUE
————————— ———-
common_user_prefix C##
همچنین امکان تغییر این پیشوند از طریق تغییر مقدار پارامتر common_user_prefix وجود دارد. برای مثال، در دستور زیر، مقدار این پارامتر را به _common تغییر می دهیم:
SQL> alter system set common_user_prefix=common_ scope=spfile;
System altered.
بعد از این تغییر، common userها باید با پیشوند common_ ایجاد شوند:
SQL> create user common_usef identified by usef;
User created.
همچنین حذف کامل پیشوند برای این نوع از کاربران امکان پذیر می باشد:
SQL> alter system set common_user_prefix=” scope=spfile;
System altered.
در این صورت می توان اسامی common userها را بدون پیشوندی مشخص، مشابه با local user ایجاد کرد:
SQL> create user usef identified by a;
User created.
با دستور زیر، نام کاربر usef در لیست common userها قابل مشاهده می باشد:
SQL> select USERNAME,COMMON,CON_ID,ORACLE_MAINTAINED from cdb_users where USERNAME=’USEF’;
USERNAME COM CON_ID O
———- — ———- –
USEF YES 1 N
البته انجام این کار، باید با ملاحضاتی هم همراه باشد برای مثال در صورت وجود کاربر usef در یک pdb، نباید کاربری با این نام در محیط cdb ایجاد کرد. این کار باعث بروز خطا در محیط pdb خواهد شد. مثال زیر را ببینید.
مثال) برای شبیه سازی این مسئله، در ابتدا کاربری را با نام usef در محیط pdb ایجاد می کنیم:
SQL> alter session set container=pdb18c;
Session altered.
SQL> create user usef identified by a;
User created.
در صورتی که pdb مورد نظر، در حالت read write قرار داشته باشد، ایجاد کاربر عمومی usef، با خطا مواجه خواهد شد(در اوراکل 18c):
SQL> alter session set container=cdb$root;
Session altered.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
———- —————————— ———- ———-
2 PDB$SEED READ ONLY NO
5 PDB18C READ WRITE NO
SQL> create user usef identified by a container=all;
ORA-01920: user name ‘USEF’ conflicts with another user or role name
SQL> create user usef identified by a;
ORA-01920: user name ‘USEF’ conflicts with another user or role name
با بستن pdb18c، این خطا برطرف خواهد شد:
SQL> alter pluggable database PDB18C close;
Pluggable database altered.
SQL> create user usef identified by a container=all;
User created.
با اجرای این دستور، دو کاربر عمومی و محلی با نام مشترک usef در بانک موجود خواهند بود که مشکلاتی را در سطح pdb ایجاد خواهند کرد. برای مثال، باز شدن مجدد pdb همراه با خطا و به صورت RESTRICTED خواهد بود:
SQL> alter pluggable database PDB18C open;
Warning: PDB altered with errors.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
———- —————————— ———- ———-
2 PDB$SEED READ ONLY NO
5 PDB18C READ WRITE YES
همچنین pdb18c کاربر usef را به عنوان local user خواهد شناخت:
SQL> alter session set container=PDB18C;
Session altered.
SQL> select USERNAME,COMMON,CON_ID,ORACLE_MAINTAINED from cdb_users where USERNAME=’USEF’;
USERNAME COM CON_ID O
———- — ———- –
USEF NO 5 N
برای حل محدودیت ایجاد شده، می توان کاربر عمومی usef را حذف کرد:
SQL> alter session set container=cdb$root;
Session altered.
SQL> drop user usef;
User dropped.
SQL> alter pluggable database PDB18C close;
Pluggable database altered.
SQL> alter pluggable database PDB18C open;
Pluggable database altered.
SQL> show pdbs CON_ID
CON_NAME OPEN MODE RESTRICTED
———- —————————— ———- ———-
2 PDB$SEED READ ONLY NO
5 PDB18C READ WRITE NO
*ایجاد common user از نوع اول(که در ابتدا متن، مطالبی در مورد آن اورده شد: Oracle-supplied administrative)، با کمک پارامتر oracle_script_ و بدون تعیین پیشوندی خاص قابل انجام می باشد:
SQL> show parameter common
common_user_prefix string c##
SQL> alter session set “_ORACLE_SCRIPT”=true;
Session altered.
SQL> create user esfandiar identified by a;
User created.
SQL> alter session set “_ORACLE_SCRIPT”=false;
Session altered.
کاربر عمومی اسفندیار مانند کاربرانی که توسط اوراکل ایجاد و نگهداری می شوند، به حساب خواهد امد همانند کاربر sys، system و … به همین دلیل، فیلد ORACLE_MAINTAINED در ویوی cdb_users برای این کاربر برابر با yes می باشد:
SQL> select USERNAME,COMMON,CON_ID,ORACLE_MAINTAINED from cdb_users where USERNAME=’ESFANDIAR’;
USERNAME COM CON_ID O
———- — ———- –
ESFANDIAR YES 1 Y
همچنین امکان حذف این کاربر، بدون کمک پارامتر oracle_script_ میسور نخواهد بود:
SQL> drop user esfandiar;
ORA-28014: cannot drop administrative users
SQL> alter session set “_ORACLE_SCRIPT”=true;
Session altered.
SQL> drop user esfandiar;
User dropped.
SQL> alter session set “_ORACLE_SCRIPT”=false;
Session altered.
common user و مجوزها
common userها می توانند در هر pdb، مجوز متفاوتی داشته باشند:
SQL> create user c##usef identified by a;
User created.
SQL> alter session set container=PDB18C;
Session altered.
SQL> grant create session to c##usef;
Grant succeeded.
SQL> alter session set container=PDBCLONE;
Session altered.
SQL> revoke create session from c##usef;
ORA-01952: system privileges not granted to ‘C##USEF’
همچنین می توان با کمک عبارت container در زمان اهدای مجوز به این نوع از کاربران(در سطح cdb)، مجوز مورد نظر را به این کاربر در سطح تمامی pdbها اعمال نمود.
مثال: اهدای مجوز dba به c##usef در همه pdbها:
SQL> alter session set container=cdb$root;
Session altered.
SQL> grant dba to c##usef container=all;
Grant succeeded.
با اهدای این مجوز، امکان revoke کردن آن در سطح یک pdb وجود نخواهد داشت:
SQL> alter session set container=PDB18C;
Session altered.
SQL> revoke create session from c##usef;
ORA-65092: system privilege granted with a different scope to ‘C##USEF’
سوییچ بین containerها با مجوز set container
کاربر c##usef با دارا بودن مجوز create session، امکان استفاده از دستور set container را دارد؟
پاسخ این سوال را در ادامه ببینید:
SQL> grant create session to c##usef container=all;
Grant succeeded.
SQL> conn c##usef/a@pdb18c
Connected.
SQL> alter session set container=cdb$root;
ORA-01031: insufficient privileges
همانطور که ملاحضه شد، کاربر c##usef، دسترسی لازم را برای اجرای دستور set container ندارد و برای انجام این کار توسط کاربر c##usef، باید مجوز set container را به ان اهدا کرد:
SQL> conn sys as sysdba
SQL> grant set container to c##usef;
Grant succeeded.
SQL> conn c##usef/a@pdb18c
Connected.
SQL> alter session set container=cdb$root;
Session altered.
وضیعت common user بعد از unplug
در ادامه خواهید دید که وضیعت common userها بعد از unplug شدن یک pdb، به چه صورتی در خواهد امد(در cdb جدید).
قبل از عملیات unplugه، common userای را در cdb1 ایجاد می کنیم:
–cdb1
SQL> create user c##usef identified by a container=all;
User created.
SQL> grant dba to c##usef container=all;
Grant succeeded.
SQL> alter session set container=PDB18C;
Session altered.
SQL> create table c##usef.tbl as select name from v$datafile;
Table created.
با در نظر گرفتن این مسئله، pdb مورد نظر را unplug می کنیم:
–cdb1:
SQL> alter pluggable database PDB18C close immediate;
Pluggable database altered.
SQL> alter pluggable database pdb18c unplug into ‘/18c/unplug.xml’;
Pluggable database altered.
SQL> drop pluggable database pdb18c;
Pluggable database dropped.
بعد از انجام مراحل unplug، عملیات plug این pdb را در cdb2 مجددا انجام می دهیم:
–cdb2
SQL> create pluggable database pdb18c using ‘/18c/unplug.xml’ nocopy tempfile reuse;
Pluggable database created.
SQL> alter pluggable database PDB18C open;
Pluggable database altered.
بعد از انجام عملیات plug، خواهیم دید که کاربر c##usef در وضیعت lock قرار خواهد داشت البته امکان دسترسی به اطلاعات جداول موجود در این کاربر در محیط pdb18c، امکان پذیر خواهد بود:
QL> select con_id,username,common from cdb_users where username like ‘C##USEF%’;
CON_ID USERNAME COM
———- ———- —
4 C##USEF YES
SQL> conn C##USEF/a@pdb18c
ORA-28000: The account is locked.
SQL> alter user C##USEF account unlock;
ORA-65146: account cannot be unlocked in a PDB while it is locked in the root
SQL> select USERNAME,ACCOUNT_STATUS from dba_users where username like ‘C##USEF%’;
USERNAME ACCOUNT_STATUS
———- ——————————–
C##USEF LOCKED
SQL> alter session set container=PDB18C;
Session altered.
SQL> select count(*) from C##USEF.tbl;
COUNT(*)
———-
4
برای حل مشکل قفل بودن این کاربر، می توان مراحل زیر را طی نمود:
SQL> alter pluggable database PDB18C close;
Pluggable database altered.
SQL> create user c##usef identified by a;
User created.
SQL> grant dba to c##usef container=all;
Grant succeeded.
SQL> alter pluggable database PDB18C open;
Pluggable database altered.
SQL> conn C##USEF/a@pdb18c
Connected.