اوراکل 23ai- قابلیت Automatic SQL Transpiler

همانطور که می دانید استفاده از تابع در یک دستور sqlای، context switch بین SQL engine و PL/SQL engine را در پی خواهد داشت و رخ دادن متعدد context switch می تواند اثرات منفی بر روی performance دیتابیس داشته باشد.

اوراکل در نسخه 21c برای افزایش سرعت اجرای این دسته از پرس و جوها، SQL Macros را معرفی کرده است که با استفاده از این قابلیت، متن پرس و جوی حاوی function به فرم ساده و بدون استفاده از function بازنویسی می شود.

در نسخه 23c هم اوراکل قابلیت Automatic SQL Transpiler را در این زمینه معرفی کرده است که در صورت تنظیم پارامتر sql_transpiler به مقدار ON، به صورت خودکار و بدون مداخله کاربر، تابع استفاده شده در متن دستور SQL «در صورت امکان» به SQL expression تبدیل خواهد شد تا از سربار ناشی از اجرای function در SQL کاسته شود.

(بیشتر…)

اوراکل 23ai – استفاده از Direct Join در دستورات Delete و Update

برای حذف و یا بروزرسانی رکوردهای یک جدول «در بسیاری از مواقع» نیاز به join آن جدول با جداول دیگر داریم تا تعیین کنیم کدام یک از رکوردها باید delete و یا update شوند تا قبل از اوراکل 23c در این شرایط به ناچار می بایست از دستور select هم همزمان استفاده می کردیم و امکان استفاده از Direct Join را نداشتیم اما در نسخه 23c، اوراکل این قابلیت را اضافه کرده است.

برای مثال دستور زیر با join بین دو جدول employees و departments مشخص می کند کدام رکوردهای جدول employees باید بروزرسانی شوند:

SQL> update employees e
  2     set e.salary = e.salary * 2
  3     from departments d
  4   where d.department_id = e.department_id
  5     and d.department_name = 'IT';
5 rows updated

از این قابلیت برای حذف رکوردها هم می توانیم استفاده کنیم:

SQL> delete employees e
  2     from departments d
  3   where d.department_id = e.department_id
  4     and d.department_name = 'IT'
  5     and e.employee_id!=d.manager_id;
4 rows deleted

 

اوراکل 23ai- قابلیت Traditional Auditing دیگر پشتیبانی نمی شود!

از اوراکل 23c قابلیت Traditional Auditing(یا همان Standard Auditing) دیگر پشتیبانی نمی شود! و قابلیت Unified Auditing در این نسخه از اوراکل به صورت پیش فرض فعال است:

SQL*Plus: Release 23.0.0.0.0 - Developer-Release on Wed Jun 14 18:26:42 2023
SQL> SELECT VALUE FROM V$OPTION WHERE PARAMETER = 'Unified Auditing';
VALUE
-------------
TRUE

البته پارامترها و جداول مربوط به Traditional Auditing کماکان وجود دارند:

SQL> select count(*) from dba_audit_trail;
  COUNT(*)
----------
         0
SQL> show parameter audit_trail
NAME         TYPE        VALUE
------------ ----------- --------
audit_trail  string      DB

همچنین امکان تغییر مقدار پارامتر audit_trail هم وجود دارد هر چند که در حالت عادی تغییر آن اثری ندارد:

SQL> alter system set audit_trail='db,extended' scope=spfile;
System altered.

(بیشتر…)

جلوگیری از Blocking Session در زمان اجرای دستور Update(قابلیت Lock-free reservation)

شرایطی را در نظر بگیرید که قرار است فیلدی به عنوان شمارنده، دائما توسط تعداد زیادی session بروزرسانی شود(با همزمانی بالا) به این شیوه که با هر بار انجام «اقدامی مشخص»، دستور updateای اجرا شده و یک عدد به این شمارنده اضافه کند.

در این حالت با توجه به زیاد بودن تعداد sessionهای همزمان، احتمال رخ دادن Blocking session هم بسیار افزایش می یابد چرا که در دیتابیس اوراکل اگر دو کاربر قصد ویرایش یک رکورد را داشته باشند و با فاصله زمانی کمی دستور Update را اجرا کنند، کاربری که دیرتر دستور update را صادر کرده Block خواهد شد و تا زمانی که کاربر اول(کاربری که زودتر رکورد را در اختیار گرفته) به تراکنش خاتمه ندهد، کاربر دوم در حالت Block باقی خواهد ماند.

--session 1:
SQL> select sid from v$mystat where rownum=1;
       SID
----------
      2190
SQL> update tbl_counter set counttt=counttt+1;
1 row updated
--session 2:
SQL> select sid from v$mystat where rownum=1;
       SID
----------
       944

SQL> update tbl_counter set counttt=counttt+1;
Executing…

بلاک شدن session دوم را می توانیم از طریق دستور زیر ببینیم:

SQL>  select SID,ID1,ID2,LMODE,block,request from v$lock where type='TX';
       SID        ID1        ID2      LMODE      BLOCK    REQUEST
---------- ---------- ---------- ---------- ---------- ----------
       944     458766       2511          0          0          6
      2190     458766       2511          6          1          0

بنابرین زمانی که کاربران زیادی قصد کار بر روی یک رکورد را دارند، مکانیزم locking امکان ویرایش رکورد را در هر لحظه به یک نفر از آنها خواهد داد و بقیه sessionها Block می شوند. پیدا کردن ترفندی برای جلوگیری از Block شدن sessionها می تواند در بعضی از این شرایط نظیر «شرایط ذکر شده در ابتدای متن» بسیار راهگشا باشد.

(بیشتر…)

اوراکل 23ai- تنظیم اولویت برای PDB

سوال: اگر CDBای بیش از یک PDB داشته باشد، چگونه می توان در مورد ترتیب open شدن این PDBها اعمال نظر کرد؟

تا قبل از اوراکل 23c راهکاری در این زمینه وجود نداشت و با اجرای دستور startup، تضمینی در مورد ترتیب باز شدن این PDBها وجود نداشت(معمولا بر اساس شماره container این PDBها باز می شدند). اما در نسخه 23c قابلیت جدیدی ارائه شد و بر اساس آن می توان برای هر PDB یک PRIORITY تنظیم کرد تا از طریق آن، ترتیب انجام عملیاتهایی نظیر open کردن PDBء، upgrade و یا restoration را کنترل کرد.

ساختار کلی دستور را در قسمت زیر می بینید:

ALTER PLUGGABLE DATABASE <PDB name> PRIORITY <value>

در این دستور، نام PDB الزامی است و PRIORITY می تواند مقداری بین 1 تا 4096 بگیرد که هر چه این عدد کمتر باشد، PDB اولویت بیشتری دارد به طور مثال، PDB با اولویت 1 نسبت به PDB با اولویت 2 زودتر open خواهد شد.

SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 TEHRANPDB                      READ WRITE NO
         4 BABOLPDB                       READ WRITE NO
         5 VARAMINPDB                     READ WRITE NO
         6 ABADANPDB                      READ WRITE NO
SQL> ALTER PLUGGABLE DATABASE babolpdb PRIORITY 1;
Pluggable database altered.
SQL> ALTER PLUGGABLE DATABASE ABADANPDB PRIORITY 2;
Pluggable database altered.
SQL> ALTER PLUGGABLE DATABASE VARAMINPDB PRIORITY 3;
Pluggable database altered.
SQL> ALTER PLUGGABLE DATABASE TEHRANPDB PRIORITY 4;
Pluggable database altered.

با restart کردن دیتابیس خواهیم دید که دیتابیسها با ترتیب اعلام شده باز شده اند:

SQL> startup force;
SQL> select OPEN_TIME,NAME,PRIORITY from v$pdbs order by 1;
OPEN_TIME                                NAME         PRIORITY
---------------------------------------- ---------- ----------
10-MAY-23 05.52.43.190 PM +04:30         PDB$SEED            1
10-MAY-23 05.52.43.812 PM +04:30         BABOLPDB            1
10-MAY-23 05.52.44.889 PM +04:30         ABADANPDB           2
10-MAY-23 05.52.45.929 PM +04:30         VARAMINPDB          3
10-MAY-23 05.52.47.102 PM +04:30         TEHRANPDB           4

ترتیب باز شدن PDB در ALERT LOG هم ثبت شده است:

PDB$SEED(2):Opening pdb with Resource Manager plan: DEFAULT_PLAN
BABOLPDB(4):SUPLOG: Initialize PDB SUPLOG SGA, old value 0x0, new value 0x18
2023-05-10T17:52:44.739491+04:30
ABADANPDB(6):SUPLOG: Initialize PDB SUPLOG SGA, old value 0x0, new value 0x18
2023-05-10T17:52:45.784421+04:30
VARAMINPDB(5):SUPLOG: Initialize PDB SUPLOG SGA, old value 0x0, new value 0x18
2023-05-10T17:52:46.828984+04:30
TEHRANPDB(3):SUPLOG: Initialize PDB SUPLOG SGA, old value 0x0, new value 0x18

*همراه با اوراکل 12cR2، اولویت PDBها در زمینه upgrade از طریق دستور زیر قابل تنظیم است:

SQL*Plus: Release 12.0.0.0.0 - Production on Wed May 10 16:56:59 2023
SQL> ALTER PLUGGABLE DATABASE babolpdb UPGRADE PRIORITY 5;
Pluggable database altered.

 

Schema Privilege در اوراکل 23ai

تا قبل از اوراکل23aiء، privilegeها به سه نوع object، system و administrative قابل تقسیم بودند و برای آنکه کاربری صرفا به اشیاء یک اسکیما دسترسی داشته باشد به ناچار می بایست از object privilegeها استفاده کرد که این محدودیت را قبلا در مستندی شرح داده ایم.

رجوع شود به : اهدای مجوز در سطح اسکیما در اوراکل و پستگرس

در نسخه 23ai قابلیت جدیدی در این زمینه ایجاد شد و اوراکل نوع دیگری از privilege به نام schema privilege را ارائه کرد که بر اساس آن می توان دسترسی به تمامی اشیاء{موجود و آینده} یک اسکیما را صرفا با اجرای یک دستور به یک کاربر(و یا role) اهدا کرد و یا به کاربر این امکان را داد تا برای اسکیما شی جدیدی بسازد.

schema privilege با کمک system privilegeها کار می کند مثلا می توانیم دسترسی select any table که یک system Privilege محسوب می شود را بر روی یک اسکیما به یک کاربر اهدا کنیم. بدیهی است که schema privilege به نسبت system privilege از دادن دسترسی های اضافه جلوگیری خواهد شد.

(بیشتر…)

اهدای مجوز به فانکشن، پکیج و پروسیجر

زمانی که یک program unit(فانکشن، پکیج، پروسیجر) به صورت invoker right ایجاد می شود، کاربر صدا زننده برنامه، با مجوز خودش این برنامه را اجرا خواهد کرد بنابرین اگر جدولی در برنامه موجود باشد که این کاربر به آن دسترسی نداشته باشد، کارش با خطا متوقف خواهد شد(بررسی Invoker’s Rights و Definer’s Rights). برای مثال، تابع زیر را در نظر بگیرید:

SQL> CREATE FUNCTION sys.Tabe(name_malek in varchar2,name_jadval in varchar2)
   RETURN VARCHAR2
   AUTHID CURRENT_USER
AS
V_bytes varchar2(1000);
BEGIN
  select bytes into V_bytes from dba_segments where owner=name_malek and segment_name=name_jadval;
   RETURN V_bytes;
END;
/
Function created.

این تابع که با یوزر sys ایجاد شده، قرار است نام segment را دریافت و حجم آن را بر اساس بایت برگرداند. عبارت AUTHID CURRENT_USER بیانگر invoker right است.

کاربری با نام vahid را با حداقل دسترسی ایجاد کرده و بررسی می کنیم که آیا این کاربر می تواند تابع فوق را اجرا کند؟

SQL> create user vahid  identified by a;
User created.
SQL> grant create session to vahid; 
Grant succeeded.

(بیشتر…)

ردیابی اهدای مجوزها در اوراکل از طریق ویوی ALL_TAB_PRIVS_MADE و USER_TAB_PRIVS_RECD

اگر کاربری مجوزی را به کاربر دیگر اهدا کند، این عملیات از طریق ویوی ALL_TAB_PRIVS_MADE قابل ردیابی است(البته با رعایت شرایطی!) و این ویو در کنار ویوی USER_TAB_PRIVS_RECD مشخص می کند که مجوز توسط کدام کاربر به کاربر دیگر اهدا شده است.

برای مثال در قسمت زیر، کاربر usef مجوز select on ali.tbl1 را به کاربر vahid اهدا می کند:

SQL> create user usef identified by a;
User created.
SQL> create user vahid identified by a;
User created.
SQL> grant create session to vahid,usef;
Grant succeeded.
SQL> grant select on ali.tbl1 to usef with grant option;
Grant succeeded.
SQL> conn usef/a
Connected.
SQL> show user
User is "USEF"
SQL> grant select on ali.tbl1 to vahid;
Grant succeeded.
SQL> conn ali/a
Connected.
SQL> select grantee, grantor,privilege, table_name from user_tab_privs_made where GRANTEE='VAHID';
GRANTEE     GRANTOR    PRIVILEGE  TABLE_NAME
----------- ---------- ---------- ----------
VAHID       USEF       SELECT     TBL1

همانطور که می بینید، با اجرای پرس و جوی فوق توسط کاربر ali، خواهیم دید که مجوز select on ali.tbl1 توسط کاربر usef به کاربر VAHID اختصاص داده شده است. البته با اجرای ویوی USER_TAB_PRIVS_RECD هم به این نتیجه خواهیم رسید:

SQL> conn vahid/a
Connected.
SQL> select owner,table_name,grantor,privilege,type from USER_TAB_PRIVS_RECD;
OWNER      TABLE_NAME GRANTOR    PRIVILEGE  TYPE
---------- ---------- ---------- ---------- ------------
ALI        TBL1       USEF       SELECT     TABLE

در این شرایط با حذف کاربر usef، دسترسی داده شده به کاربر vahid از بین خواهد رفت و به تبع آن، این دو ویو هم اطلاعاتی را در این زمینه بر نمی گردانند:

SQL> drop user usef;
User dropped.
SQL> conn ali/a
Connected.
SQL> select owner,table_name,grantor,privilege,type from USER_TAB_PRIVS_RECD;
no rows selected
SQL> select * from ALI.TBL1;
ORA-00942: table or view does not exist

با اندکی تغییر در سناریوی قبلی، نقش dba را به کاربر usef اختصاص می دهیم و بعد از ان کاربر usef، دسترسی select on ali.tbl1 را به کاربر vahid اهدا می کند، با این تغییر، دو ویوی فوق، کاربر ALI را به عنوان grantor معرفی خواهند کرد:

SQL> create user usef identified by a;
User created.
SQL> grant dba to usef;
Grant succeeded.
SQL>  conn usef/a
Connected.
SQL> grant select on ali.tbl1 to vahid;
Grant succeeded.
SQL> conn vahid/a
Connected.
SQL> select owner,table_name,grantor,privilege,type from USER_TAB_PRIVS_RECD;
OWNER      TABLE_NAME GRANTOR    PRIVILEGE  TYPE
---------- ---------- ---------- ---------- ------------------------
ALI        TBL1       ALI        SELECT     TABLE
SQL> conn ali/a
Connected.
SQL> select grantee, grantor, table_name from user_tab_privs_made where GRANTEE='VAHID';
GRANTEE     GRANTOR    TABLE_NAME
----------- ---------- ----------
VAHID       ALI        TBL1

 

نکته ای در مورد Role و Privilege در اوراکل

زمانی که مجوزی از نوع object privilege و یا system privilege به کاربری داده می شود(و یا از کاربر گرفته(revoke) می شود)، بلافاصله sessionهای ان user که به دیتابیس متصل هستند، از این مجوزها بهره مند خواهند شد:

–session 1:

SQL*Plus: Release 19.0.0.0.0 - Production on Thu Sep 16 19:48:16 2021
Version 19.11.0.0.0
SQL> show user
USER is "ALI"
SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION

–session 2:

SQL> show user
USER is "USEF"
SQL> grant select any table to ALI;
Grant succeeded.

–session 1:

SQL> select * from session_privs;
PRIVILEGE
----------------------------------------
CREATE SESSION
SELECT ANY TABLE

اما این مسئله برای role صادق نیست و در صورت grant یا revoke کردن یک roleء، sessionهای جاری متاثر نخواهند شد مگر آنکه از دستور SET ROLE استفاده کنند:

(بیشتر…)

اوراکل 21.7 – راه اندازی دیتاگارد در سطح PDB(قابلیت DGPDB)

DGPDB(یا همان Data Guard per Pluggable Database) قابلیت جدیدی است که در نسخه 21.7 اوراکل ارائه شده و قرار است با کمک این قابلیت، در سطح PDB، دیتاگارد راه اندازی کنیم.

 در معماری قدیمی(قبل از ارائه DGPDB)، یکی از CDBها(به انضمام همه PDBها) در نقش primary قرار داشت و CDB دیگر نقش standby را ایفا می کرد و راه اندازی دیتاگارد برای یک PDB منوط به راه اندازی دیتاگارد برای CDB$ROOT بود و دیتاگارد هم نمی توانست container اضافه ای را داشته باشد به عبارتی دیگر، Guard عینا مشابه primary و یا در صورت مستثنا کردن بعضی از PDBها(enabled_PDBs_on_standby)، دیتاگارد زیر مجموعه ای از primary بود.

اما DGPDB این محدودیتها را برداشت معماری این قابلیت که شباهتهایی هم با قابلیت PDB switchover دارد(قابلیت switchover  در نسخه 18c ارائه شده بود)، به این صورت است که:

1.هر دو CDB در نقش primary و در حالت read write قرار دارند و برخلاف معماری سنتی، CDB$ROOT بین این دو دیتابیس یکسان نیست و هر CDBء PDBهای مختص به خود را دارند.

2.نقش standby و primary در سطح PDB قابل تنظیم است مثلا برای PDB حاضر در CDB1 می توانیم در CDB2 گارد ایجاد کنیم و به همین شکل می توانیم در CDB1 برای PDBهای حاضر در CDB2 دیتاگارد راه اندازی کنیم.

3.تغییر چندانی در پروسه ارسال و دریافت redoها در طرفین ایجاد نشده و پروسه TTnn در معماری DGPDB نقش کلیدی را ایفا می کند.

(بیشتر…)