دیتابیس اوراکل

دیتابیس اوراکل
طبقه بندی موضوعی

Find and Delete Duplicate Records

SELECT session_user, db_unique_name, count(*)
  FROM p2.acl
 GROUP BY session_user, db_unique_name
HAVING count(*) > 1;

 

 

DELETE p2.acl
 WHERE db_unique_name = 'NIRVAN'
     AND rowid NOT IN (SELECT min (rowid)
                                    FROM p2.acl
                                  WHERE db_unique_name = 'NIRVAN'
                                  GROUP BY session_user, db_unique_name);

DISTINCT Option for LISTAGG Aggregate

 

Category : Application Development_SQL

Oracle DB version : 19.3.0.0.0

 

تابع LISTAGG از ورژن 11gR2 به اوراکل اضافه شده است، و در ورژن های 12cR2 و 19c تغییراتی داشته است.

همانطور که در مثال زیر مشاهده می کنید، در خروجی تابع LISTAGG، مقادیر تکراری هم نمایش داده می شوند:

SELECT deptno, LISTAGG (ename, ',') WITHIN GROUP (ORDER BY ename) AS employees

  FROM emp

GROUP BY deptno

ORDER BY deptno;

 

DEPTNO EMPLYEES
10 CLARK,KING,MILLER,MILLER,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

 

 

 

 

 

 

 

 

 

 

 

تا قبل از اوراکل 19c، برای حذف این مقادیر تکراری، راه حل های مختلفی وجود داشت که یکی از آنها استفاده از تابع ROW_NUMBER بود. ولی در اوراکل 19c، با اضافه شدن کلمه کلیدی DISTINCT به این تابع خیلی راحت میتوان مقادیر تکراری را از خروجی تابع LISTAGG حذف کرد.

 

SELECT deptno, LISTAGG (DISTINCT ename, ',') WITHIN GROUP (ORDER BY ename) AS employees

FROM   emp

GROUP BY deptno

ORDER BY deptno;

 
DEPTNO EMPLYEES
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

 

 

 

 

 

بدست آوردن تعداد Transactionها در ثانیه بین دو snapshot

در دیتابیس اوراکل، تعداد Transactionها در هر ثانیه را، هم میتوان از AWR Report بدست آورد، هم با استفاده از کوئری. 

 

AWR Report:

 

 

 

 

 

 

 

 

 

Query:

WITH
    hist_snaps
    AS
        (SELECT instance_number,
                snap_id,
                ROUND (begin_interval_time, 'MI') begin_snap_time,
                ROUND (end_interval_time, 'MI') end_snap_time,
                  (  begin_interval_time
                   + 0
                   - LAG (begin_interval_time + 0)
                         OVER (PARTITION BY dbid, instance_number
                               ORDER BY snap_id))
                * 86400                              diff_time
           FROM dba_hist_snapshot),
    hist_stats
    AS
        (SELECT dbid,
                instance_number,
                snap_id,
                stat_name,
                  VALUE
                - LAG (VALUE)
                      OVER (PARTITION BY dbid, instance_number, stat_name
                            ORDER BY snap_id)    delta_value
           FROM dba_hist_sysstat
          WHERE stat_name IN ('user commits', 'user rollbacks'))
  SELECT sn.begin_snap_time,
         sn.end_snap_time,
         sn.instance_number,
         ROUND (SUM (delta_value) / 3600)     "TRANSACTIONS/S"
    FROM hist_snaps sn, hist_stats st
   WHERE st.instance_number = sn.instance_number
     AND st.snap_id = sn.snap_id
     AND sn.diff_time IS NOT NULL
     AND sn.instance_number = 2
     AND TO_CHAR (sn.end_snap_time, 'yyyy-mm-dd') = to_char(sysdate, 'yyyy-mm-dd')
GROUP BY sn.begin_snap_time, sn.end_snap_time, sn.instance_number
ORDER BY 1;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Result Of above Query:

 

 

 

 

 

 

اکسپورت/ایمپورت جداول دارای پارتیشن

در مثال زیر از 2 پارتیشن جدول  TEST1.MESSAGE اکسپورت گرفته شده است.

 

expdp system tables=TEST1.MESSAGE:P201201,TEST1.MESSAGE:P201202 dumpfile=EXP_TEST1_MESSAGE_%U.dmp logfile=EXP_TEST1_MESSAGE.log directory=DATA_PUMP_DIR

 

در مرحله بعد، پارتیشن هایی را که در مرحله قبل از آنها اکسپورت گرفتیم، در یک اسیکمای جدید با نام TEST2 ایمپورت میکنیم.

 

impdp \'/ as sysdba\' remap_schema=TEST1:TEST2 dumpfile=EXP_TEST1_MESSAGE_%U.dmp logfile=IMP_TEST1_MESSAGE.log directory=DATA_PUMP_DIR transform=oid:n parallel=10 exclude=STATISTICS,INDEX,CONSTRAINT,GRANT remap_tablespace=TBS_TEST1:TBS_TEST2

 

اگر از قبل یک اکسپورت full از جدول وجود دارد و در حال حاضر فقط به پارتیشنهای خاصی از آن جدول نیاز دارید، میتوانید ایمپورت را به صورت زیر انجام دهید.

 

impdp \'/ as sysdba\'remap_schema=TEST1:TEST2 tables=TEST1.MESSAGE:P201201,TEST1.MESSAGE:P201202 dumpfile=EXP_FULL_TEST1_%U.dmp logfile=IMP_TEST1_MESSAGE.log directory=DATA_PUMP_DIR transform=oid:n parallel=10 exclude=STATISTICS,INDEX,CONSTRAINT,GRANT remap_tablespace=TBS_TEST1:TBS_TEST2

 

اگر میخواهید جدول را با یک نام جدید ایجادکنید، میتوانید ایمپورت را به صورت زیر انجام دهید.

 

impdp \'/ as sysdba\'remap_schema=TEST1:TEST2 tables=TEST1.MESSAGE:P201201,TEST1.MESSAGE:P201202 remap_table=TEST1.MESSAGE:MESSAGE_NEW dumpfile=EXP_FULL_TEST1_%U.dmp logfile=IMP_TEST1_MESSAGE.log  directory=DATA_PUMP_DIR transform=oid:n parallel=10 exclude=STATISTICS,INDEX,CONSTRAINT,GRANT remap_tablespace=TBS_TEST1:TBS_TEST2

 

 

SQL Quarantine

Category: Performance

Oracle DB Version: 19.3.0.0

 

با استفاده از Resource Manager، میتوانیم SQLها را از نظر مصرف منابع، محدود کنیم. مثلا به این صورت که SQLهایی که منابع بیشتری نسبت به thresholdهای ست شده استفاده کنند، توسط Resource Manger خاتمه یابند. تا قبل از نسخه 19c، وقتی یک SQL توسط Resource Manger متوقف میشد،  از اجرای مجدد آن ممانعت به عمل نمی آمد؛ فقط اگر مانند دفعه قبل، منابع بیشتری نسبت به thresholdهای ست شده استفاده میکرد، باز هم توسط Resource Manger متوقف میشد. که این موضوع باعث میشود که منابع سیستم هدر رود، چون آن دستور SQL مجددا اجرا شده و برای اجرا از منابع سیستم استفاده کرده است. ولی از اوراکل 19c ، میتوانیم با استفاده از  SQL Quarantine ، از اجرای مجدد SQLهایی که توسط Resource Manger خاتمه یافته اند، ممانعت به عمل آوریم.

به طور مثال فرض کنید در Resource Manger یک threshold ست شده است به این صورت که اگر زمان اجرای یک دستور SQL برای یک یوزر بیشتر از 3 ثانیه شد، آن SQL متوقف شود.

یک دستور SQL با نام SQL1 اجرا میشود. اگر SQL1 بیشتر از 3 ثانیه طول بکشد، توسط  Resource Manger خاتمه می یابد.

بعد از آن SQL Quarantine یک quarantine با نام Quarantine1 برای SQL1 ایجاد میکند و execution time مساوی 3 ثانیه را به عنوان threshold برای Quarantine1 ست میکند.

اگر SQL1 مجددا با همان  Execution Plan اجرا شود و threshold ست شده در Resource Manager نیز همچنان 3 ثانیه باشد، Quarantine1 اجازه نمیدهد که SQL1 اجرا شود، زیرا تشخیص داده است که SQL1 در نهایت توسط Resource Manager متوقف میشود.

اگر در Resource Manager، مقدار Execution Time به 2 ثانیه تغییر پیدا کند. وقتی SQL1 دوباره با همان execution plan اجرا شود، مجددا Quarantine1 اجازه اجرا به آن نمیدهد، زیرا تشخیص داده که SQL1 در نهایت توسط Resource Manager متوقف میشود، چون اجرای آن حداقل 3 ثانیه طول میکشد.

اگر در Resource Manager، مقدار Execution Time به 10 ثانیه تغییر پیدا کند. وقتی SQL1 دوباره با همان Execution Plan اجرا شود، Quarantine1 از اجرای آن ممانعتی به عمل نمی آورد، زیرا تشخیص داده است که SQL1 حداقل 3 ثانیه طول میکشد که اجرا شود، اما این احتمال وجود دارد که تا قبل از 10 ثانیه تمام شود.

 

مثالی از ایجاد شدن Quarantine براساس thresholdهای ست شده در Resource Manager

مثال زیر نشان میدهد که چگونه execution plan یک دستور SQL وقتی از thresholdهای ست شده در Resource Manger فراتر برود، قرنطینه میشود:

1. با استفاده از Resource Manager مشخص میکنیم که Execution Time برای SQLهایی که با استفاده از یوزر HR اجرا شوند 3 ثانیه باشد. برای انجام این کار مراحل زیر را طی کنید:

   1.1. ایجاد یک consumer group با نام TEST_RUNAWAY_GROUP

   1.2. اختصاص دادن یوزر HR به TEST_RUNAWAY_GROUP

   1.3. ایجاد یک resource plan با نام LIMIT_RESOURCE که حداکثر زمان اجرا را برای SQLهای اجرا شده 3 ثانیه در نظر بگیرد.

   1.4. تخصیص LIMIT_RESOURCE به TEST_RUNAWAY_GROUP

 

connect / as sysdba

 

begin

 

  -- Create a pending area

  dbms_resource_manager.create_pending_area();

 

  -- Create a consumer group 'TEST_RUNAWAY_GROUP'

  dbms_resource_manager.create_consumer_group (

    consumer_group => 'TEST_RUNAWAY_GROUP',

    comment        => 'This consumer group limits execution time for SQL statements'

  );

 

  -- Map the sessions of the user 'HR' to the consumer group 'TEST_RUNAWAY_GROUP'

  dbms_resource_manager.set_consumer_group_mapping(

    attribute      => DBMS_RESOURCE_MANAGER.ORACLE_USER,

    value          => 'HR',

    consumer_group => 'TEST_RUNAWAY_GROUP'

  );

 

  -- Create a resource plan 'LIMIT_RESOURCE'

  dbms_resource_manager.create_plan(

    plan    => 'LIMIT_RESOURCE',

    comment => 'Terminate SQL statements after exceeding total execution time'

  );

 

  -- Create a resource plan directive by assigning the 'LIMIT_RESOURCE' plan to

  -- the 'TEST_RUNAWAY_GROUP' consumer group

  -- Specify the execution time limit of 3 seconds for SQL statements belonging to

  -- the 'TEST_RUNAWAY_GROUP' group

  dbms_resource_manager.create_plan_directive(

    plan             => 'LIMIT_RESOURCE',

    group_or_subplan => 'TEST_RUNAWAY_GROUP',

    comment          => 'Terminate SQL statements when they exceed the' ||

                        'execution time of 3 seconds',

    switch_group     => 'CANCEL_SQL',

    switch_time      => 3,

    switch_estimate  => false

  );

 

  -- Allocate resources to the sessions not covered by the currently active plan

  -- according to the OTHER_GROUPS directive

  dbms_resource_Manager.create_plan_directive(

    plan              => 'LIMIT_RESOURCE',

    group_or_subplan  => 'OTHER_GROUPS',

    comment           => 'Ignore'

  );

 

  -- Validate and submit the pending area

  dbms_resource_manager.validate_pending_area();

  dbms_resource_manager.submit_pending_area();

 

  -- Grant switch privilege to the 'HR' user to switch to the 'TEST_RUNAWAY_GROUP'

  -- consumer group

  dbms_resource_manager_privs.grant_switch_consumer_group('HR',

                                                          'TEST_RUNAWAY_GROUP',

                                                          false);

 

  -- Set the initial consumer group of the 'HR' user to 'TEST_RUNAWAY_GROUP'

  dbms_resource_manager.set_initial_consumer_group('HR',

                                                   'TEST_RUNAWAY_GROUP');

 

end;

/

 

-- Set the 'LIMIT_RESOURCE' plan as the top plan for the Resource Manager

alter system set RESOURCE_MANAGER_PLAN = 'LIMIT_RESOURCE' scope = memory;

 

 

2. با یوزر HR به دیتابیس متصل شوید و دستور زیر را اجرا کنید. زمان اجرای این دستور بیشتر از 3 ثانیه است.

select count(*)

from employees emp1, employees emp2,

     employees emp3, employees emp4,

     employees emp5, employees emp6,

     employees emp7, employees emp8,

     employees emp9, employees emp10

where rownum <= 100000000;

 

این SQL توسط Resource Manger متوقف شده و خطای زیر به کاربر نمایش داده میشود:

 

ORA-00040: active time limit exceeded - call aborted

 

3. وقتی این SQL قرنطینه شد، اگر مجددا با همان plan اجرا شود، با خطای زیر مواجه میشوید:

 

ORA-56955: quarantined plan used

 

4. در viewهای زیر میتوانید آماری را در رابطه با SQLهای قرنطینه شده مشاهده کنید:

  • v$sql

select sql_text, plan_hash_value, avoided_executions, sql_quarantine

from v$sql

where sql_quarantine is not null;

 

خروجی کوئری بالا به شکل زیر است:

SQL_TEXT                           PLAN_HASH_VALUE        AVOIDED_EXECUTIONS          SQL_QUARANTINE

----------------------------       --------------------------          ------------------------------           ---------------------------------

select count(*)                  3719017987                      1                                                  SQL_QUARANTINE_3uuhv1u5day0yf6ed7f0c

from employees emp1,

     employees emp2, employees emp3,

     employees emp4, employees emp5,

     employees emp6, employees emp7,

     employees emp8, employees emp9,

     employees emp10

where rownum <= 100000000;

 

 

  • dba_sql_quarantine: این view اطلاعاتی درباره quarantine configurationهای ایجاد شده به ما میدهد:

 

select sql_text, name, plan_hash_value, last_executed, enabled

from dba_sql_quarantine;

 

خروجی کوئری بالا به شکل زیر است:

SQL_TEXT                          NAME                                                                         PLAN_HASH_VALUE     LAST_EXECUTE                                ENABLED

-------------------                   -----------------------------------                                     ---------------                    ----------------------------                      -------

select count(*)                  SQL_QUARANTINE_3uuhv1u5day0yf6ed7f0c    3719017987                  14-JAN-19 02.19.01.000000 AM   YES

from employees emp1,

     employees emp2,

    employees emp3,

     employees emp4,

     employees emp5,

     employees emp6,

     employees emp7,

     employees emp8,

     employees emp9,

     employees emp10

where rownum <= 100000000;

 
ایجاد Quarantine برای یک دستور SQL
با استفاده از پکیج DBMS_SQLQ میتوانیم برای execution plan یک دستور SQL یک Quarantine ایجاد کنیم و برای آن thresholdهایی مشابه thresholdهای Resource Manager ست کنیم.

در مثال زیر برای یکی از Execution planهای یک دستور SQL یک quarantine ایجاد شده است:

 

DECLARE

    quarantine_config   VARCHAR2 (40);

BEGIN

    quarantine_config :=

        DBMS_SQLQ.CREATE_QUARANTINE_BY_SQL_ID (

            SQL_ID            => '28bu8g33sbm4v',

            PLAN_HASH_VALUE   => '3347434651');

    DBMS_OUTPUT.put_line (quarantine_config);

END;

 

اگر execution plan را مشخص نکرده یا NULL ست کنیم، quarantine برای همه Execution Planهای آن SQL اعمال میشود، بجز آنهایی که به صورت جداگانه برایشان یک quarantine  تعریف شده باشد. در مثال زیر برای همه execution planهای یک SQL که SQL ID آن مساوی 28bu8g33sbm4v است، یک quarantine  ایجاد شده است.

 

DECLARE

    quarantine_config   VARCHAR2 (40);

BEGIN

    quarantine_config :=

        DBMS_SQLQ.CREATE_QUARANTINE_BY_SQL_ID (SQL_ID => '28bu8g33sbm4v');

END;

 

در مثال زیر هم برای همه execution planهای دستور 'select count(*) from emp' یک quarantine  ایجاد شده است.

DECLARE

    quarantine_config   VARCHAR2 (40);

BEGIN

    quarantine_config :=

        DBMS_SQLQ.CREATE_QUARANTINE_BY_SQL_TEXT (

            SQL_TEXT   => TO_CLOB ('select count(*) from emp'));

END;

 

نتیجه اجرای دستورات بالا نام Quarantine که ایجاد شده است، میباشد. که در مراحل بعدی موقع ست کردن threshold ، به آن نام نیاز میباشد.

Result:  SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b

 

مشخص کردن Threshold برای Quarantine ایجاد شده

بعد از ایجاد یکQuarantine  برای execution plan یک دستور SQL، میتوانیم با استفاده از پروسیجر DBMS_SQLQ.ALTER_QUARANTINE برای آن quarantine، threshold تعیین کنیم. وقتی هریک از thresholdهای ست شده در Resource Manager کوچکتر یا مساوی thresholdهای مشخص شده برای یک Quarantine باشند، به آن SQL اجازه اجرا داده نمیشود.

میتوانیم برای Resourceهای زیر در quarantine configuration ، threshold تعریف کنیم:

  • CPU time
  • Elapsed time
  • I/O in megabytes
  • Number of physical I/O requests
  • Number of logical I/O requests

در مثال زیر برای یک Quarantine که در مرحله قبل ایجاد کردیم ، thresholdهایی برای CPU time و Elapsed time ست می کنیم:

 

BEGIN

    DBMS_SQLQ.ALTER_QUARANTINE (

        QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

        PARAMETER_NAME    => 'CPU_TIME',

        PARAMETER_VALUE   => '5');

 

    DBMS_SQLQ.ALTER_QUARANTINE (

        QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

        PARAMETER_NAME    => 'ELAPSED_TIME',

        PARAMETER_VALUE   => '4');

END;

 

وقتی دستور SQL با همان plan مشخص شده در SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b اجرا شود. اگر thresholdهای ست شده در Resource Manager، برای CPU time ، 5 ثانیه یا کمتر و برای Elapse time، 4 ثانیه یا کمتر باشد،  از اجرای آن SQL ممانعت به عمل می آید.

 

بدست آوردن اطلاعات در مورد  Thresholdهای ست شده برای یک Quarantine

با استفاده از فانکشن DBMS_SQLQ.GET_PARAM_VALUE_QUARANTINE میتوانیم از یک Quarantine که قبلا ایجاد شده است، کوئری بگیریم.

با استفاده از مثال زیر میتوانیم متوجه شویم که مقدار threshold ست شده برای CPU time در SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b چقدر است:

 

DECLARE

    quarantine_config_setting_value   VARCHAR2 (30);

BEGIN

    quarantine_config_setting_value :=

        DBMS_SQLQ.GET_PARAM_VALUE_QUARANTINE (

            QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

            PARAMETER_NAME    => 'CPU_TIME');

    DBMS_OUTPUT.put_line (quarantine_config_setting_value);

END;

Result: 5

 

 پاک کردن thresholdهای ست شده برای یک Quarantine

در مثال زیر threshold ست شده برای CPU time، از SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b حذف شده است:

 

BEGIN

    DBMS_SQLQ.ALTER_QUARANTINE (

        QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

        PARAMETER_NAME    => 'CPU_TIME',

        PARAMETER_VALUE   => DBMS_SQLQ.DROP_THRESHOLD);

END;

 

 فعال یا غیرفعال کردن یک Quarantine

یک Quarantine به صورت پیش فرض وقتی ایجاد میشود enable است. در مثال زیر یک قرنطینه با نام      SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b که قبلا ایجاد شده بود، disable شده است:

BEGIN

    DBMS_SQLQ.ALTER_QUARANTINE (

        QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

        PARAMETER_NAME    => 'ENABLED',

        PARAMETER_VALUE   => 'NO');

END;

 

پاک کردن یک Quarantine

Quarantineهایی که مورد استفاده قرار نگرفته اند، به صورت اتومات بعد از 53 هفته پاک میشوند، که میتوانیم با استفاده از پروسیجر زیر این تنظیم اتومات را disable کنیم.

 

BEGIN

    DBMS_SQLQ.ALTER_QUARANTINE (

        QUARANTINE_NAME   => 'SQL_QUARANTINE_3u0anzbpmfkmdc785cc9b',

        PARAMETER_NAME    => 'AUTOPURGE',

        PARAMETER_VALUE   => 'NO');

END;

 

همچنین میتوانیم با استفاده از پروسیجر زیر یک Quarantine  را به صورت دستی پاک کنیم.

BEGIN

    DBMS_SQLQ.DROP_QUARANTINE ('SQL_QUARANTINE_3z0mwuq3aqsm8cfe7a0e4');

END;

 

انتقال یک Quarantine از یک دیتابیس به دیتابیس دیگر

با استفاده از پکیج DBMS_SQLQ میتوانیم یک Quarantine را از یک دیتابیس به دیتابیس دیگر انتقال دهیم. مثلا در یک دیتابیس تستی، یک Quarantine ایجاد و تستهای لازم انجام شده است. با توجه به اینکه عملکرد خوبی داشته است، میخواهیم آن را به دیتابیس اصلی منتقل کنیم. مثال زیر مراحل انجام این کار را نشان میدهد:

1. با استفاده از SQL*Plus با یک یوزر که دسترسی admin دارد، به دیتابیس مبدا متصل میشویم و با اجرای دستور زیر یک staging table ایجاد میکنیم:

BEGIN

    DBMS_SQLQ.CREATE_STGTAB_QUARANTINE (

        staging_table_name   => 'TBL_STG_QUARANTINE');

END;

 

2. کانفیگ های مربوط به SQL Quarantine را که میخواهیم به دیتابیس مقصد منتقل کنیم با استفاده از دستور زیر به جدولی که در مرحله قبل ساخته ایم منتقل میکنیم. در مثال زیر همه quarantine هایی که نام آنها با QUARANTINE_CONFIG شروع شده است به جدول TBL_STG_QUARANTINE که در مرحله قبل ایجاد شده است اضافه میشوند:

DECLARE

    quarantine_configs   NUMBER;

BEGIN

    quarantine_configs :=

        DBMS_SQLQ.PACK_STGTAB_QUARANTINE (

            staging_table_name   => 'TBL_STG_QUARANTINE',

            name                 => 'QUARANTINE_CONFIG_%');

END;

 

3. از جدول TBL_STG_QUARANTINE با استفاه از Data Pump اکسپورت بگیرید.

4. Dump File را از دیتابیس مبدا به مقصد انتقال دهید.

5. در دیتابیس مقصد dump file مربوطه را ایمپورت کنید.

6. با استفاده از SQL*Plus با یک یوزر که دسترسی admin دارد، به دیتابیس مقصد متصل شوید و با اجرای دستور زیر بر اساس staging table که ایمپورت کرده اید، یک quarantine  ایجاد کنید:

 

DECLARE

    quarantine_configs   NUMBER;

BEGIN

    quarantine_configs :=

        DBMS_SQLQ.UNPACK_STGTAB_QUARANTINE (

            staging_table_name   => 'TBL_STG_QUARANTINE');

    DBMS_OUTPUT.put_line (quarantine_configs);

END;

 

فانکشن DBMS_SQLQ.UNPACK_STGTAB_QUARANTINE به عنوان خروجی تعداد quarantine هایی که در دیتابیس مقصد ایجاد شده است را برمیگرداند.

 

 

 

DBMS_JOB in Oracle DB 19c

 

اوراکل از نسخه 12cR2 اعلام کرد که پکیج DBMS_JOB، منسوخ (deprecateشده است. و در نسخه 19c با تبدیل هر DBMS_JOB ایجاد شده به یک جاب DBMS_SCHEDULER، یک گام هم در جهت منسوخ کردن این پکیج جلوتر رفته است.

در زیر مثالی در رابطه با این موضوع آورده شده است:

SQL> conn raheleh

SQL> select job, what from user_jobs;

no rows selected

 

SQL> select job_name, job_action from user_scheduler_jobs;

no rows selected

 

 

SQL>

CREATE TABLE raheleh.tbl1

(

    id      NUMBER,

    name    VARCHAR2 (30)

);

 

 

SQL> INSERT INTO tbl1

(SELECT user_id, username FROM dba_users)

COMMIT;

 

 

SQL>

CREATE OR REPLACE PROCEDURE raheleh.prc_dbmsjob (username IN VARCHAR2)

IS

    userid   NUMBER;

BEGIN

    SELECT id

      INTO userid

      FROM raheleh.tbl1

     WHERE name = username;

END;

 

 

SQL>

DECLARE

    job1   PLS_INTEGER;

BEGIN

    DBMS_JOB.submit (job         => job1,

                                       what        => 'begin raheleh.prc_dbmsjob (''SYSTEM''); end;',

                                       next_date   => TRUNC (SYSDATE) + 1,

                                       interval    => 'trunc(sysdate)+1');

END;

COMMIT;

 

 

SQL> select job, what from user_jobs;

 

       JOB  WHAT

----------  ------------------------------

        22  begin raheleh.prc_dbmsjob ('SYSTEM'); end;

 

 

 

SQL> select job_name, job_action from user_scheduler_jobs;

 

JOB_NAME                       JOB_ACTION

------------------------------   ------------------------------

DBMS_JOB$_22               begin raheleh.prc_dbmsjob ('SYSTEM'); end;

 

 

همانطور که در مثال بالا مشاهده کردید، وقتی یک جاب با DBMS_JOB ایجاد کردیم، اوراکل به صورت اتومات، معادل همان جاب ، یک جاب هم با DBMS_SCHEDULER ایجاد کرد که نام آن با DBMS_JOB$_* شروع میشود.

 

 

َAutomatic Indexing در اوراکل دیتابیس 19c

Category: Big Data and Data Warehousing

Oracle DB Version: 19.3.0.0

Oracle DB Type: RAC

 

ایندکس یکی از ساختارهای مهم در بالا بردن کارایی دیتابیس است. ایندکس­ها هم برای محیط OLTP که SQLهای زیادی در روز اجرا می­کنند، هم برای محیط­ های OLAP که می­خواهند بخش کوچکی از دیتا را از یک جدول بزرگ انتخاب کنند ضروری هستند. اگر همزمان با تغییر در لود اپلیکیشن، ایندکس ها آپدیت نشوند، این موضوع می تواند باعث کاهش قابل توجه عملکرد دیتابیس شود. از featureهای جدید در اوراکل دیتابیس 19c، Automatic Indexing است که برای بهبود بخشیدن کارایی دیتابیس هنگام تغییر در لود اپلیکیشن، میتواند به صورت اتومات، ایندکس­های لازم را create، rebuild یا drop کند.

 

Automatic Indexing چگونه کار می­کند؟

فرآیند Automatic Indexing در background، هر 15 دقیقه اجرا و عملیات زیر را انجام می­دهد:

  1. انتخاب ایندکس­های کاندید بر اساس میزان استفاده ستون­های جداول در دستورات SQL.
  2. ایجاد ایندکس­های کاندید به صورت invisible.
  3. اگر performance مربوط به آن SQL که ایندکس برای آن ایجاد شده است بهبود پیدا کرد، وضعیت ایندکس به visible تغییر پیدا می­کند. و از این به بعد می­تواند در دستورات SQL مورد استفاده قرار بگیرید.
  4. ولی اگر performance بهبود پیدا نکرد، وضعیت ایندکس به unusable تغییر پیدا می­کند و در نهایت طی یک فرآیند اتومات کلا پاک میشود. و آن دستور SQL در balck list  قرار میگیرد. دستورات SQL که جزو black list قرار گرفته اند، در آینده در فرآیند automatic indexing مورد بررسی قرار نمی گیرند.

نکات مهم:

  • برای استفاده از auto indexing، باید statisticها آپدیت باشند. جداولی که statistic نداشته باشند یا statistic آنها stale باشد و real-time statistic هم برای آنها در دسترس نباشد در لیست بررسی automatic indexing قرار نمی ­گیرند.
  • Automatic Indexها میتوانند به صورت single-column یا multi-column باشند.
  • Auto Indexها برای SQLهایی که اولین بار در دیتابیس اجرا میشوند، مورد استفاده قرار نمی­ گیرند.
  • میتوان تنظیم کرد که جاب مربوط به Auto Indexing برای یک ساعاتی غیرفعال شود. یا اینکه تنظیم کنید این جاب کلا با ریسورس خیلی کمی اجرا شود.

 

کانفیگ کردن Automatic Indexing در Oracle DB

فعالسازی و غیر فعالسازی Automatic Indexing

برای فعالسازی Automatic Indexing، باید از پروسیجر CONFIGURE در پکیج DBMS_AUTO_INDEX استفاده کنید، که میتواند مقادیر زیر را بگیرد.

IMPLEMENT: فعال کردن Automatic Indexing

REPORT ONLY: ایندکس­های جدید ایجاد می­شوند ولی invisible باقی می­ مانند.

OFF: غیرفعال کردن Automatic Indexing

 

وقتی می­ خواهیم این ویژگی را فعال کنیم، خطای زیر را می گیریم:

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE','IMPLEMENT');

BEGIN DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE','IMPLEMENT'); END;

 

*

ERROR at line 1:

ORA-40216: feature not supported

ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79

ORA-06512: at "SYS.DBMS_AUTO_INDEX_INTERNAL", line 9180

ORA-06512: at "SYS.DBMS_AUTO_INDEX", line 283

ORA-06512: at line 1

 

EE-ES: Available on Exadata. Not available on Oracle Database Appliance.

 

 

 

 

 

 

 

 

 

 

 

 

 

دلیل آن هم این است که این feature در حال حاضر فقط در نسخه های Oracle Database Exadata Cloud Service و Oracle Database Enterprise Edition on Engineered Systems فعال می­ باشد.

Notes ExaCS DBCS EE-EP DBCS EE-HP DBCS EE DBCS SE EE-ES EE SE2

Feature /

Option /

Pack

EE-ES: Available on Exadata. Not available on Oracle Database Appliance. Y N N N N Y N N Automatic Indexing

 

 

 

 

 

 

برای اینکه این feature را تست کنیم می توانیم با استفاده از روش زیر برای نسخه Enterprise Edition آن را فعال کنیم.

SQL> alter system set "_exadata_feature_on"=true scope=spfile sid='*';

[oracle@test1-rac19c ~]$ srvctl stop database -d ORCL

[oracle@test1-rac19c ~]$ srvctl start database -d ORCL

 

 

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE','IMPLEMENT');

PL/SQL procedure successfully completed.

 

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config;

 

PARAMETER_NAME                      PARAMETER_VALUE
----------------------------------- --------------------
AUTO_INDEX_COMPRESSION              OFF
AUTO_INDEX_DEFAULT_TABLESPACE       
AUTO_INDEX_MODE                     IMPLEMENT
AUTO_INDEX_REPORT_RETENTION         31
AUTO_INDEX_RETENTION_FOR_AUTO       373
AUTO_INDEX_RETENTION_FOR_MANUAL
AUTO_INDEX_SCHEMA                   
AUTO_INDEX_SPACE_BUDGET             50

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

غیر فعالسازی Automatic Indexing برای یک یا چند اسکیما

وقتی Automatic Indexing را فعال می کنید به صورت پیش فرض همه اسکیماها میتوانند از این ویژگی استفاده کنند. با استفاده از دستور زیر می توانیم این ویژگی را برای یک یا چند اسکیما غیرفعال کنیم یا اصطلاحا آن اسکیما را در exclusion list قرار دهیم.

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', 'HR', allow => FALSE);

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_SCHEMA';

 

PARAMETER_NAME        PARAMETER_VALUE

-------------------- ----------------------------------------

AUTO_INDEX_SCHEMA     schema NOT IN (HR)

 

 

 

 

 

 

 

 

 

و با دستور زیر میتوان یک اسکیما را از exclusion list خارج کرد:

EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', 'HR', NULL);

 

 

دستور زیر همه اسکیماها را از exclusion list خارج می­کند، یعنی Auto Indexing مثل حالت پیش فرض برای همه اسکیماها فعال می­شود.

EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', NULL, allow => TRUE);

 

 

تغییر retention period برای unused auto index

به صورت پیش فرض auto indexهایی که ایجاد شده ولی استفاده نشده اند، بعد از 373 روز drop می­ شوند. به صورت زیر میتوان این پیش فرض را تغییر داد:

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_AUTO', '90');

PL/SQL procedure successfully completed.

 

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_RETENTION_FOR_AUTO';

 

PARAMETER_NAME                 PARAMETER_VALUE

------------------------------ --------------------

AUTO_INDEX_RETENTION_FOR_AUTO  90

 

 

 

 

 

 

 

 

 

 

 

و به صورت زیر میتوان آن را به مقدار پیش فرض برگرداند:

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_AUTO', NULL);

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_RETENTION_FOR_AUTO';

 

PARAMETER_NAME                 PARAMETER_VALUE

------------------------------ --------------------

AUTO_INDEX_RETENTION_FOR_AUTO  373

 

 

 

 

 

 

 

 

 

مشخص کردن retention period برای non-auto indexes

اگر می­خواهید برای ایندکس­ هایی که به صورت دستی هم ایجاد شده اند، یک retention تعیین کنید که بعد از n روز که unused بودند به صورت اتومات drop شوند، می­ توانید با استفاده از روش زیر این کار را انجام دهید. در غیر اینصورت ایندکس ­هایی که به صورت دستی ایجاد شده اند به صورت اتومات drop نمی ­شوند.

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_RETENTION_FOR_MANUAL';

 

PARAMETER_NAME                    PARAMETER_VALUE

--------------------------------- --------------------

AUTO_INDEX_RETENTION_FOR_MANUAL

 

 

 

 

 

 

 

 

به صورت زیر میتوان این پارامتر را تغییر داد:

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_MANUAL', '60');

PL/SQL procedure successfully completed.

 

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_RETENTION_FOR_MANUAL';

 

PARAMETER_NAME                  PARAMETER_VALUE

------------------------------  --------------------

AUTO_INDEX_RETENTION_FOR_MANUAL 60

 

 

 

 

 

 

 

 

 

 

 

و به صورت زیر هم میتوان آن را به مقدار پیش فرض برگرداند:

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_MANUAL', NULL);

PL/SQL procedure successfully completed.

 

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_RETENTION_FOR_MANUAL';

 

PARAMETER_NAME                  PARAMETER_VALUE

------------------------------  --------------------

AUTO_INDEX_RETENTION_FOR_MANUAL

 

 

 

 

 

 

 

 

 

 

 

تعیین یک tablespace مشخص برای auto indexها

می­توانیم برای ذخیره کردن Auto Indexها یک tablespace جداگانه تعریف کنیم. به این نکته توجه داشته باشید که نمیتوان از tablespaceهای پیش فرض اوراکل مثل sysaux برای این کار استفاده کرد.

SQL> EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_DEFAULT_TABLESPACE','TBS_AUTOIDX');

PL/SQL procedure successfully completed.

 

SQL> SELECT parameter_name, parameter_value

       FROM dba_auto_index_config

      WHERE parameter_name = 'AUTO_INDEX_DEFAULT_TABLESPACE';

 

PARAMETER_NAME                  PARAMETER_VALUE

------------------------------  --------------------

AUTO_INDEX_DEFAULT_TABLESPACE   TBS_AUTOIDX

 

 

 

 

 

 

 

 

 

 

 

ارائه یک مثال از کاربرد Auto Indexing

1. ابتدا یک جدول ایجاد می کنیم و تعداد زیادی رکورد در آن insert میکنیم.

SQL> CREATE TABLE test1.tab_test1_autoidx AS

( SELECT * FROM dba_objects );

 

SQL> INSERT INTO test1.tab_test1_autoidx

     ( SELECT * FROM test1.tab_test1_autoidx );

     COMMIT;

 

SQL> exec DBMS_STATS.GATHER_TABLE_STATS('TEST1','TAB_TEST1_AUTOIDX');

 

SQL> SELECT COUNT(*)

       FROM test1.tab_test1_autoidx;

     COUNT(*)

     ----------

     586248

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. روی جدول ایجاد شده یک select اجرا می­ کنیم و plan را برای آن دستور مشاهده می­ کنیم.

SQL> SELECT * FROM test1.tab_test1_autoidx WHERE owner='DBSNMP';

 

SQL> EXPLAIN PLAN FOR

SELECT * FROM test1.tab_test1_autoidx WHERE owner='DBSNMP';

 

SQL> select * from table(dbms_xplan.display());

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. اگر دستور بالا را به تعداد دفعات زیاد اجرا کنیم، بعد از طی یک زمان مشخص، مشاهده می­کنیم که یک ایندکس برای این جدول ایجاد شده است. مراحل ایجاد آن ایندکس را در view زیر می­توانیم ببینیم.

SQL> SELECT execution_name, index_name, index_owner, command, statement

      FROM dba_auto_index_ind_actions

     WHERE table_name = 'TAB_TEST1_AUTOIDX';

 

 

 

 

STATEMENT COMMAND INDEX_NAME INDEX_OWNER EXECUTION_NAME  
CREATE INDEX "TEST1"."SYS_AI_85xrrw9rhauv0"   ON "TEST1"."TAB_TEST1_AUTOIDX"("OWNER") TABLESPACE "TBS_AUTOIDX" UNUSABLE INVISIBLE AUTO  ONLINE CREATE INDEX SYS_AI_85xrrw9rhauv0 TEST1 SYS_AI_2020-12-01/10:40:22
ALTER INDEX "TEST1"."SYS_AI_85xrrw9rhauv0"   REBUILD  ONLINE REBUILD INDEX SYS_AI_85xrrw9rhauv0 TEST1 SYS_AI_2020-12-01/10:40:22
ALTER INDEX "TEST1"."SYS_AI_85xrrw9rhauv0"   VISIBLE   ALTER INDEX VISIBLE SYS_AI_85xrrw9rhauv0 TEST1 SYS_AI_2020-12-01/10:40:22

 

 

 

 

 

 

 

 

 

 

ستونی که تقریبا در تمام viewهای مرتبط با Auto Indexها مشترک است، execution_name است. بر این اساس میتوانیم بر اساس execution_name یا execution_nameهای مرتبط با یک ایندکس، اطلاعاتی از دیگر viewها راجع به آن بدست آوریم.

SQL> SELECT *

       FROM dba_auto_index_statistics

      WHERE execution_name = 'SYS_AI_2020-12-01/10:40:22';

 

 

 

 

 

 

 

 

 

 

 

 

 

لیست viewهای دیگر که میتوان از آنها در مورد Auto Indexها اطلاعات بدست آورد در زیر آمده است:

DBA_AUTO_INDEX_EXECUTIONS

DBA_AUTO_INDEX_SQL_ACTIONS

DBA_AUTO_INDEX_VERIFICATIONS

 

 

 

 

بعد از ایجاد ایندکس وقتی مجددا دستور قبل را اجرا کردم، plan آن به شکل زیر تغییر پیدا کرده بود:

SQL> EXPLAIN PLAN FOR

SELECT * FROM test1.tab_test1_autoidx WHERE owner='DBSNMP';

 

SQL> SELECT * FROM table(dbms_xplan.display());

 

 

 

 

 

 

 

 

 

 

 

 

 

 

از view زیر هم می­توانیم لیست تمام Auto Indexهای ایجاد شده در دیتابیس را مشاهده کنیم:

SELECT *

  FROM dba_indexes

 WHERE auto = 'YES';

 

 

 

 

تهیه ریپورتهای مختلف بر اساس یک بازه زمانی

میتوانیم با استفاده از یک سری پروسیجرها، گزارشهای مختلفی در رابطه با Automatic Indexها تهیه کنیم. نوع این ریپورت­ ها میتواند HTML، TEXT و XML باشد. اسامی این پروسیجرها به شرح زیر می­باشد:

DBMS_AUTO_INDEX.REPORT_ACTIVITY();

DBMS_AUTO_INDEX.REPORT_LAST_ACTIVITY();

 

 

 

یک نمونه از اجرای این ریپورت­ها در زیر آمده است:

SET SERVEROUTPUT ON

DECLARE

    report CLOB := NULL;

BEGIN

    report := dbms_auto_index.report_activity(

              activity_start => to_timestamp('2020-12-01','YYYY-MM-DD'),

              activity_end => to_timestamp('2020-12-02','YYYY-MM-DD'),

              type => 'HTML',

              section => 'ALL',

              level => 'ALL');

    dbms_output.put_line(report);

END;

 

 

 

 

 

 

 

 

 

 

 

 

 

خروجی ریپورت بالا به شکل زیر است:

 AutoIndex_Report.html

 

منابع

https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-indexes.html#GUID-FAE533D7-9C9E-48C9-9A61-EBC060BF3D70

https://webcache.googleusercontent.com/search?q=cache:NvWPTTaq_csJ:https://juliandontcheff.wordpress.com/2019/02/18/automatic-indexing-in-19c/+&cd=6&hl=en&ct=clnk&gl=ir

 

مشاهده مقدار bind_variable

SELECT *
  FROM gv$sql_bind_capture
WHERE inst_id = 1
    AND sql_id = '16h7r0vpcgvu2'
    AND child_address = '00000000ECCD5350';

 

SELECT *
  FROM DBA_HIST_SQLBIND
WHERE sql_id = '16h7r0vpcgvu2';

session_waits

کوئری زیر sessionهایی که در حال حاضر wait هستند را نمایش می دهد.

 

    SELECT s.inst_id,s.sid,s.serial#,s.username,s.status,s.osuser,s.program,s.machine,
                s.sql_id,s.sql_hash_value,s.sql_child_number,
                s.event,s.wait_class,s.p1,s.p2,s.p3,s.state,s.wait_time,s.seconds_in_wait
       FROM gv$session s
     WHERE s.inst_id = 1
         AND s.wait_class <> 'Idle'
         AND s.username NOT IN ('SYS','SYSTEM','DBSNMP','AUDSYS')
         AND s.state='WAITING'
ORDER BY seconds_in_wait DESC;

 

اگر میخواهید بدانید که P1,P2,P3 به ازای هر event چه مقداری را نمایش میدهند، کوئری زیر را اجرا کنید.

 SELECT name,parameter1,parameter2,parameter3
   FROM v$event_name
 WHERE name = 'gc current request';

 

PARAMETER3 PARAMETER2 PARAMETER1 NAME
id# block# file# gc current request

 

 

 

 

آماده سازی دیسک ها با EMC PowerPath و Oracle ASMLIB قبل از نصب Oracle Grid

Oracle Linux Server release = 7.5

EMC PowerPath version = DellEMCPower.LINUX-6.5.0.00.00-067.OL7.x86_64.rpm

 

انجام کارهای مربوط به PowerPath

 

  1. نصب پکیج DellEMCPower

[root@TEST ~]# yum localinstall DellEMCPower.LINUX-6.5.0.00.00-067.OL7.x86_64.rpm

 

  1. استارت کردن سرویس PowerPath در لینوکس

[root@TEST ~]# systemctl start PowerPath.service

[root@TEST ~]# systemctl enable PowerPath.service

[root@TEST ~]# systemctl status PowerPath.service

 

  1. رجیستر کردن EMC PowerPath

[root@TEST ~]# emcpreg -install

===========   Dell EMC PowerPath Registration ===========

Do you have a new registration key or keys to enter?[n] y

                  Enter the registration keys(s) for your product(s),

                  one per line, pressing Enter after each key.

                  After typing all keys, press Enter again.

 

Key (Enter if done): **emc-powerpath-license-key**

1 key(s) successfully added.

Key successfully installed.

 

[root@TEST ~]# powermt check_registration

**emc-powerpath-license-key**

  Product: PowerPath

  Capabilities: ALL

 

  1. برای اینکه مطمئن شویم تنظیمات PowerPath، بعد از ریستارت کردن host به همین شکل باقی می­ ماند، باید دستور زیر را اجرا کنیم.

[root@TEST]# powermt save

 

  1. با دستور زیر می­توانیم وضعیت hbaهای موجود را مشاهده کنیم. همانطور که در خروجی دستور مشخص است، دو hba به سرور ما متصل هستند و هر دو hba در وضعیت enable قرار دارند.

[root@TEST ~]# powermt display hba_mode

VNX logical device count=4

==============================================================================

----- Host Bus Adapters ---------  ------ I/O Paths -----  Stats

###  HW Path                       Summary   Total   Dead  Q-IOs Mode

==============================================================================

   0 qla2xxx                       optimal       0      0       0  Enabled

   4 qla2xxx                       optimal       0      0       0  Enabled

 

  1. برای اسکن کردن hbaها و کانفیگ کردن deviceهای جدید، دستور زیر را اجرا می­ کنیم.

[root@TEST ~]# /etc/opt/emcpower/emcplun_linux scan 0

WARNING: Dell EMC recommends that all I/O on the SCSI devices should be quiesced prior to attempting to rescan the SCSI bus.

Continue operation? [y,q->quit]: y

---------------------------------------------------------------------

Scanning qla SCSI host number: 0

---------------------------------------------------------------------

INFO: 'powermt config' is required to recognize the new LUN(s) under PowerPath

Continue operation? [y,n,q->quit]: y

---------------------------------------------------------------------

INFO: Executing 'powermt config', please wait ...

---------------------------------------------------------------------

INFO: Executing 'powermt save'

---------------------------------------------------------------------

INFO: Following new device(s) discovered

------------------------------------------------------------------------------------------------

Pseudo Dev      :Array ID       :Logical Dev    :Native Dev(s)=SCSI Address

------------------------------------------------------------------------------------------------

emcpowerb       :CKM00133604349 :P02Live_REDO01_LUN     :sdq=0:0:1:1     sdn=0:0:0:1

emcpowerc       :CKM00133604349 :P02Live_FRA01_LUN      :sdr=0:0:1:2     sdo=0:0:0:2

emcpowerd       :CKM00133604349 :P02LIVE_DATA_LUN02     :sds=0:0:1:3     sdp=0:0:0:3

دستور بالا را مجددا برای hba 4 هم اجرا می­کنیم:

[root@TEST ~]# /etc/opt/emcpower/emcplun_linux scan 4

 

  1. دستور زیر یکی از دستورهای کاربردی است که با استفاده از آن میتوان وضعیت تمامی logical deviceهای متصل به سرور را مشاهده کرد.

[root@TEST ~]# powermt display dev=all

Pseudo name=emcpowera

VNX ID=CKM00133604349 [P02LIVE_SG]

Logical device ID=60060160D3F035008B8C01E0F41CEB11 [P02LIVE_DATA_LUN01]

state=alive; policy=CLAROpt; queued-IOs=0

Owner: default=SP A, current=SP A       Array failover mode: 4

==============================================================================

--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---

###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs Errors

==============================================================================

   0 qla2xxx                sdb        SP A1     active   alive      0      0

   0 qla2xxx                sdc        SP B2     active   alive      0      0

   4 qla2xxx                sdg        SP A2     active   alive      0      0

   4 qla2xxx                sdh        SP B1     active   alive      0      0

 

Pseudo name=emcpowerb

VNX ID=CKM00133604349 [P02LIVE_SG]

Logical device ID=60060160D3F03500186C96B2ED1CEB11 [P02Live_REDO01_LUN]

state=alive; policy=CLAROpt; queued-IOs=0

Owner: default=SP B, current=SP B       Array failover mode: 4

==============================================================================

--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---

###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs

==============================================================================

  4 qla2xxx                sdw        SP B1     active   alive      0      0

   4 qla2xxx                sdt        SP A2     active   alive      0      0

   0 qla2xxx                sdq        SP B2     active   alive      0      0

   0 qla2xxx                sdn        SP A1     active   alive      0      0

 

Pseudo name=emcpowerc

VNX ID=CKM00133604349 [P02LIVE_SG]

Logical device ID=60060160D3F035006C904CABEB1CEB11 [P02Live_FRA01_LUN]

state=alive; policy=CLAROpt; queued-IOs=0

Owner: default=SP A, current=SP A       Array failover mode: 4

==============================================================================

--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---

###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs Errors

==============================================================================

   4 qla2xxx                sdx        SP B1     active   alive      0      0

   4 qla2xxx                sdu        SP A2     active   alive      0      0

   0 qla2xxx                sdr        SP B2     active   alive      0      0

   0 qla2xxx                sdo        SP A1     active   alive      0      0

 

Pseudo name=emcpowerd

VNX ID=CKM00133604349 [P02LIVE_SG]

Logical device ID=60060160D3F03500CE6361F0F41CEB11 [P02LIVE_DATA_LUN02]

state=alive; policy=CLAROpt; queued-IOs=0

Owner: default=SP B, current=SP B       Array failover mode: 4

==============================================================================

--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---

###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs Errors

==============================================================================

   4 qla2xxx                sdy        SP B1     active   alive      0      0

   4 qla2xxx                sdv        SP A2     active   alive      0      0

   0 qla2xxx                sds        SP B2     active   alive      0      0

   0 qla2xxx                sdp        SP A1     active   alive      0      0

 

انجام کارهای مربوط به Oracle ASMLIB

  1. نصب پکیج­های oracleasm

[root@TEST ~]# yum install -y oracleasm-support.x86_64

پکیج زیر در dvd مربوط به Oracle Linux 7.5 وجود نداشت و به صورت جداگانه دانلود شد.

[root@TEST ~]# yum localinstall oracleasmlib-2.0.12-1.el7.x86_64.rpm

[root@TEST ~]# rpm -qa |grep oracleasm

oracleasmlib-2.0.12-1.el7.x86_64

oracleasm-support-2.1.11-2.el7.x86_64

 

  1. کانفیگ کردن oracleasm

[root@TEST ~]# /usr/sbin/oracleasm configure -i

Configuring the Oracle ASM library driver.

This will configure the on-boot properties of the Oracle ASM library driver.  The following questions will determine whether the driver is loaded on boot and what permissions it will have.  The current values will be shown in brackets ('[]').  Hitting <ENTER> without typing an answer will keep that current value.  Ctrl-C will abort.

Default user to own the driver interface []: oracle

Default group to own the driver interface []: oinstall

Start Oracle ASM library driver on boot (y/n) [n]: y

Scan for Oracle ASM disks on boot (y/n) [y]: y

Writing Oracle ASM library driver configuration: done

 

[root@TEST ~]# /usr/sbin/oracleasm init

Creating /dev/oracleasm mount point: /dev/oracleasm

Loading module "oracleasm": oracleasm

Configuring "oracleasm" to use device physical block size

Mounting ASMlib driver filesystem: /dev/oracleasm

 

  1. برای پارتیشن کردن دیسک­ها مراحل زیر را انجام می­دهیم.

[root@TEST ~]# fdisk -l /dev/emcpowera

Disk /dev/emcpowera: 1099.5 GB, 1099511627776 bytes, 2147483648 sectors

Units = sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

 

همانطور که در بالا مشاهده می ­شود، برای این دیسک پارتیشنی وجود ندارد. برای پارتیشن کردن آن به تریتب دستورهای زیر را اجرا می­ کنیم.

­[root@TEST ~]# parted /dev/emcpowera mklabel msdos

[root@TEST ~]# fdisk -l /dev/emcpowera

Disk /dev/emcpowera: 1099.5 GB, 1099511627776 bytes, 2147483648 sectors

Units = sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk label type: dos

Disk identifier: 0x0003e25f

 

[root@TEST ~]# parted /dev/emcpowera mkpart p 0% 100%

[root@TEST ~]# fdisk -l /dev/emcpowera

Disk /dev/emcpowera: 1099.5 GB, 1099511627776 bytes, 2147483648 sectors

Units = sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk label type: dos

Disk identifier: 0x0003e25f

 

         Device Boot      Start         End      Blocks   Id  System

/dev/emcpowera1            2048  2147483647  1073740800   83  Linux

دستورات بالا را برای هریک از deviceهای emcpowerb، emcpowerc و emcpowerd هم اجرا می­ کنیم.

 

  1. زدن label روی دیسک­ها با استفاده از oracleasm

[root@TEST ~]# oracleasm createdisk P02LIVE_DATA_LUN01 /dev/emcpowera1

[root@TEST ~]# oracleasm createdisk P02LIVE_DATA_LUN01 /dev/emcpowerb1

[root@TEST ~]# oracleasm createdisk P02LIVE_DATA_LUN01 /dev/emcpowerc1

[root@TEST ~]# oracleasm createdisk P02LIVE_DATA_LUN01 /dev/emcpowerd1

 

  1. با استفاده از دستور زیر می­ توانیم لیست دیسک­های label زده شده توسط oracleasm را مشاهده کنیم.

[root@TEST ~]# oracleasm listdisks

P02LIVE_DATA_LUN01

P02LIVE_DATA_LUN02

P02LIVE_FRA01_LUN

P02LIVE_REDO01_LUN

 

[root@TEST ~]# oracleasm-discover

Using ASMLib from /opt/oracle/extapi/64/asm/orcl/1/libasm.so

[ASM Library - Generic Linux, version 2.0.12 (KABI_V2)]

Discovered disk: ORCL:P02LIVE_DATA_LUN01 [2147481600 blocks (1099510579200 bytes), maxio 1024, integrity none]

Discovered disk: ORCL:P02LIVE_DATA_LUN02 [2147481600 blocks (1099510579200 bytes), maxio 1024, integrity none]

Discovered disk: ORCL:P02LIVE_FRA01_LUN [1048573952 blocks (536869863424 bytes), maxio 1024, integrity none]

Discovered disk: ORCL:P02LIVE_REDO01_LUN [356513792 blocks (182535061504 bytes), maxio 1024, integrity none]

 

  1. برای اینکه ASMLIB هر بار موقع استارت شدن فقط سراغ دیسک­های powerpath برود و بقیه دیسک­ ها را scan نکند، باید در فایل  etc/sysconfig/oracleasm/  تغییرات زیر اعمال شود.

[root@TEST ~]# vim /etc/sysconfig/oracleasm

# ORACLEASM_ENABLED: 'true' means to load the driver on boot.

ORACLEASM_ENABLED=true

# ORACLEASM_UID: Default user owning the /dev/oracleasm mount point.

ORACLEASM_UID=oracle

# ORACLEASM_GID: Default group owning the /dev/oracleasm mount point.

ORACLEASM_GID=oinstall

# ORACLEASM_SCANBOOT: 'true' means scan for ASM disks on boot.

ORACLEASM_SCANBOOT=true

# ORACLEASM_SCANORDER: Matching patterns to order disk scanning

ORACLEASM_SCANORDER="emcpower"

# ORACLEASM_SCANEXCLUDE: Matching patterns to exclude disks from scan

ORACLEASM_SCANEXCLUDE="sd dm-"