آشنایی و مدیریت JOBها

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

برای زمانبندی در سطح بانک اطلاعاتی، دو بسته با نامهای dbms_job و dbms_scheduler موجود می باشند که بسته dbms_job از نسخه های قدیمی اوراکل ارائه شده و در نسخه های جدید هم کماکان مورد استفاده قرار می گیرد و بسته dbms_scheduler که در نسخه جدیدتر اوراکل عرضه شد، توانست تا حدود زیادی جایگزین مناسبی برای بسته dbms_job باشد. در ادامه هر یک از این بسته ها به صورت جداگانه مورد بررسی قرار خواهد گرفت.

DBMS_JOB

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

{ORACLE_HOME}/rdbms/admin/dbmsjob.sql

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

پروسیجر Submit: این پروسیجر شامل چندین پارامتر می باشد که شرح هر یک به صورت مختصر در ادامه خواهد امد.

PROCEDURE submit (    

job       OUT BINARY_INTEGER,

what      IN  VARCHAR2,

next_date IN  DATE DEFAULT sysdate,

interval  IN  VARCHAR2 DEFAULT ‘null’,

no_parse  IN  BOOLEAN DEFAULT FALSE,

instance  IN  BINARY_INTEGER DEFAULT 0,

force     IN  BOOLEAN DEFAULT FALSE );

پارامتر Job: این پارامتر از نوع output می باشد که شماره job را برخواهد گرداند. برای اجرا و یا هرگونه تصرفی در job ایجاد شده، باید از این شماره استفاده کرد.

پارامتر  what: مقدار ورودی این پارامتر، دستوری است که باید اجرا شود برای مثال، ورودی این پارامتر می تواند اسم پروسیجر، فانکشن و … باشد.

مثال:

what  => ‘proc1;’

نکته: اگر دستور ورودی این پارامتر حاوی تک کوتیشن(‘) باشد، باید این کوتیشن تکرار شود. مثال:

what  => ‘myproc(”10-JAN-99”, next_date, broken);’

what  => usef.emp.give_raise(JI, 400);’

پارامتر  next_date: این پارامتر در هنگام ساخت job، زمان اولین اجرا را مشخص خواهد کرد و نیز بعد از اجرای اول جاب، اجرای دفعات بعدی هم توسط این پارامتر مشخص می شود. مقدار پیش فرض این پارامتر برابر با sysdate می باشد.

مثال:

next_date => to_date(’03-05-2017 14:58:18′, ‘dd-mm-yyyy hh24:mi:ss’)

پارامتر  interval: این پارامتر مشخص می کند که تناوب زمانی اجرای job در اینده چگونه باشد. مقدار پیش فرض آن برابر با null می باشد.

مثال:

interval => ‘sysdate+1’

نکته: در مورد نحوه تنظیم تاریخ، استفاده از نکات زیر می تواند مفید باشد:

‘SYSDATE + 7’ => هر هفت روز یکبار

‘SYSDATE + 1/48’=>هر نیم ساعت یکبار

‘NEXT_DAY(TRUNC(SYSDATE), ”MONDAY”) + 15/24’ =>هر دوشنبه ساعت 3 بعدازظهر

‘NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, ”Q”), 3), ”THURSDAY”)’=>اولین چهارشنبه هر ماه

مثال: نمونه ای از نحوه تعیین مقدار برای پارامتر interval:

variable x number;

execute bms_job.submit(:x,’pack.proc(”arg1”);’,sysdate,’sysdate+1′);

پارامتر  no_parse: زمانی که این پارامتر برابر با false تنظیم شده باشد، شی ای که نام ان در قسمت what امده است، یکبار پارس خواهد شد(در هنگام ساخت job) همچنین مقدار true برای این پارامتر، مانع از پارس شدن آن شی خواهد شد.

مثال 1:اگر این پارامتر برابر با TRUE باشد:

— no_parse=>true

declare

 job NUMBER ;

begin

dbms_job.submit(job => job, what => ‘obj_usef1;’,next_date => to_date(‘03-05-2017 14:58:18’, ‘dd-mm-yyyy hh24:mi:ss’),interval => ‘sysdate+1’,no_parse=>TRUE);

  commit;

end;

/

Done.

اگر این پارامتر برابر با false باشد:

— no_parse=>false

PLS-00201: identifier ‘OBJ_USEF1’ must be declared

ORA-06512: at “SYS.DBMS_JOB”, line 116

پارامتر  Instance: مقدار این پارامتر مشخص می کند که job مورد نظر در کدام یک از instanceها قابل اجرا و اصلاح می باشد. مقدار پیش فرض این پارامتر برابر با dbms_job.any_instance می باشد و می تواند در هر instanceای اجرا شود.

پارامتر force: پارامتر force در این پروسیجر مشخص می کند که شماره تعیین شده برای پارامتر instance باید معتبر باشد یا خیر؟! پس با کمک این پارامتر، اگر شماره instanceای که موجود نیست را به پارامتر instance نسبت دهیم، با خطایی مواجه نخواهیم شد(البته در صورتی که مقدار این پارامتر به true تنظیم شده باشد).

در نهایت مثالی را از نحوه ایجاد job از طریق این پروسیجر را مشاهده خواهید کرد.

مثال:

SQL> VARIABLE jobno number;

SQL>

SQL> BEGIN

  2     DBMS_JOB.SUBMIT(:jobno,

  3        ‘dbms_ddl.analyze_object(”TABLE”, ”USEF”, ”USEF_TBL”,  ”ESTIMATE”, NULL, 55);’ ,

  4        SYSDATE, ‘SYSDATE + 2’);

  5     COMMIT;

  6  END;

  7  /

در ادامه به دیگر پروسیجرهای این پکیج خواهیم پرداخت.

پروسیجر isubmit: با استفاده از پروسیجر isubmit می توان jobای با شماره دلخواه ایجاد کرد.

  PROCEDURE isubmit    ( job       IN  BINARY_INTEGER,

                         what      IN  VARCHAR2,

                         next_date IN  DATE,

                         interval  IN  VARCHAR2 DEFAULT ‘null’,

                         no_parse  IN  BOOLEAN DEFAULT FALSE);

مثال: در مثال زیر، jobای با شماره 99 ایجاد خواهد شد:

BEGIN

DBMS_JOB.isubmit (

job => 99,

what => ‘usef_proc1(1);’,

next_date => SYSDATE,

interval => ‘SYSDATE + 1/24 /* 1 Hour */’);

COMMIT;

END;

/

پروسیجر remove: برای حذف یک job باید شماره آن را به تنها ورودی این پروسیجر ارسال کرد البته برای حذف job در حال اجرا، باید ابتدا آن را متوقف نمود و سپس آن را حذف کرد.

PROCEDURE remove    ( job       IN  BINARY_INTEGER );

مثال:

execute dbms_job.remove(95);

commit;

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

declare

 job user_jobs.job%TYPE;

 CURSOR c IS  select job from user_jobs;

begin

    OPEN c;

    LOOP

        fetch c into job;

        exit when c%NOTFOUND;

        dbms_output.put_line(‘Removing job: ‘||job);

        dbms_job.remove(job);

    END LOOP;

    CLOSE c;

    commit;

end;

پروسیجر change: برای تغییر هر کدام از ویژگی های job، می توان از این پروسیجر استفاده کرد که پارامترهای این پروسیجر تقریبا مشابه با پارامترهای پروسیجر submit می باشند.

PROCEDURE change    (job       IN  BINARY_INTEGER,

                        what      IN  VARCHAR2,

                        next_date IN  DATE,

                        interval  IN  VARCHAR2,

                       instance  IN  BINARY_INTEGER DEFAULT NULL,

                       force     IN  BOOLEAN DEFAULT FALSE);

نکته: بعد از هر تغییری باید از commit استفاده کرد.

پروسیجر what: برای تغییر مقدار پارامتر what برای یک job به خصوص، از این پروسیجر استفاده می شود.

  PROCEDURE what( job       IN  BINARY_INTEGER,  what   IN  VARCHAR2 );

مثال:

BEGIN

DBMS_JOB.WHAT(99, ‘DBMS_DDL.ANALYZE_OBJECT(”TABLE”, ”USEF”, ”USEF_TBL2”,   ”ESTIMATE”, NULL, 50);’);

END;

پروسیجر next_date: با استفاده از این پروسیجر می توان تاریخ اجرای بعدی job را تغییر داد.

  PROCEDURE next_date ( job IN  BINARY_INTEGER,  next_date IN  DATE     );

پروسیجر interval: تناوب زمانی که یک job اجرا می شود را می توان با استفاده از این پروسیجر تغییر داد.

 PROCEDURE interval  ( job IN  BINARY_INTEGER, interval  IN  VARCHAR2 );

پروسیجر broken: استفاده از این پروسیجر سبب می شود تا job مربوطه هیچ گاه اجرا نشود. هر job بعد از 16  بار اجرای ناموفق به این حالت در خواهد امد(البته 16 بار اجرای ناموفق متوالی).

 PROCEDURE broken  ( job IN BINARY_INTEGER, broken IN BOOLEAN,next_date IN DATE DEFAULT SYSDATE );

مثال:

exec dbms_job.broken(job => 16,broken => true);

همچنین برای خروج از این حالت می توان زمان  بعدی اجرای آن job را مشخص کرد:

exec dbms_job.broken(job => 16,broken => false,next_date => NEXT_DAY(SYSDATE, ‘MONDAY’));

پروسیجرrun : برای اجرای job به صورت دستی می توان از این پروسیجر استفاده کرد.

PROCEDURE run       ( job IN  BINARY_INTEGER, force IN  BOOLEAN DEFAULT FALSE);

نکته: حتی اگر job در حالت بروکن هم قرار داشته باشد، از طریق این پروسیجر قابل اجرا می باشد.

مثال:

execute dbms_job.run(14144);

پروسیجر user_export: با استفاده از این پروسیجر، متن job از طریق شماره آن قابل مشاهده خواهد بود.

PROCEDURE user_export ( job IN BINARY_INTEGER, mycall IN OUT VARCHAR2);

مثال:

SQL> variable x varchar2;

SQL> exec dbms_job.user_export(3,:x);

dbms_job.isubmit(job=>3,what=>’proc1;’,next_date=>to_date(‘2017-05-04:14:15:36′,’YYYY-MM-DD:HH24:MI:SS’) ,interval=>’sysdate+1′, no_parse=>TRUE);

dbms_job و RAC

در محیط rac این قابلیت وجود دارد تا هر کدام از jobها را به یک instance خاص مقید کرد تا تنها به وسیله آن نود، job مورد نظر قابل اجرا و قابل تغییر باشد. همانطور که قبلا اورده شد، برای تنظیم شماره instance، می توان از پروسیجر submit و یا instance استفاده کرد:

DBMS_JOB.SUBMIT(job,what,interval,no_parse,instance,force);

DBMS_JOB.INSTANCE(JOB,instance,force);

پارامتر force در این دو پروسیجر مشخص می کند که شماره تعیین شده برای پارامتر instance باید معتبر باشد یا نه؟! در صورت تنظیم این پارامتر به مقدار false، شماره instance باید واقعی باشد(به بیانی دیگر، الزاما باید نودی با این شماره وجود داشته باشد) در غیر این صورت، ایجاد job و یا تغییر آن با خطا متوقف خواهد شد البته استفاده از مقدار true، از این خطا جلوگیری خواهد کرد و این پارامتر هر مقدار مثبتی را پذیرا خواهد بود:

–true

SQL> exec dbms_job.instance(job => 16,instance => 50,force => true);

PL/SQL procedure successfully completed

–false

SQL> exec dbms_job.instance(job => 16,instance => 50,force => false);

ORA-23428: job associated instance number 50 is not valid

ORA-06512: at “SYS.DBMS_SYS_ERROR”, line 86

در این صورت، اگر job شماره 16 به صورت دستی اجرا شود، با خطا متوقف خواهد شد:

SQL> exec dbms_job.run(job => 16);

ORA-23428: job associated instance number 50 is not valid

مگر  آن که از عبارت force استفاده شود که در این صورت این job بر روی نودهای دیگر اجرا خواهد شد:

SQL> exec dbms_job.run(job => 16,force => true);

PL/SQL procedure successfully completed

مقدار پیش فرض این پارامتر برابر با صفر می باشد که به معنی همه نودها خواهد بود و استفاده از مقادیر null و یا منفی برای پارامتر instance سبب بروز خطا خواهد شد.

نکته: بعد از هر تغییری باید از commit استفاده شود.

نکاتی در مورد dbms_job

نکته 1: تنها مالک job می تواند آن را اجرا، تغییر و یا حذف کند.

نکته 2: بعد از هر تغییری باید از commit استفاده شود.

نکته 3: شماره job از طریق sequenceای به نام JOBSEQ بدست می اید.

نکته 4: اجرای یک job از طریق job دیگر ممکن نیست.

نکته 5: در صورتی که مقدار پارامتر interval برابر با null تعیین شده باشد، job مورد نظر بعد از اولین اجرا، از لیست job queue خارج خواهد شد و با هر بار اجرای دستی ان، خطای زیر رخ خواهد داد:

ORA-23421: job number 88 is not a job in the job queue

ORA-06512: at “SYS.DBMS_SYS_ERROR”, line 86

ORA-06512: at “SYS.DBMS_IJOB”, line 781

ORA-06512: at “SYS.DBMS_JOB”, line 267

نکته 6: اطلاعات مربوط به dbms_jobs در جدول job$ ذخیره می شود و پروسس CJQ0 که مخفف coordinator job queue می باشد، مسئولیت دارد تا jobهای مربوطه را زیر نظر داشته باشد تا در صورت لزوم به کمک پروسس Jnnn ان job را اجرا کند. در صورتی که پارامتر job_queue_processes برابر با صفر تنظیم شده باشد، این پروسسها اجرا نخواهند شد. برای بررسی خطاها و هشدارهای مربوط به این پروسس، باید در بین فایلهای تریس، به دنبال فایلی با فرمت SID-cjq0_nnnn.trc گشت.

[root@usef ~]# locate *cjq0*.trc

[root@usef ~]# less /u01/oracle/diag/rdbms/usef11g/usef11g/trace/usef11g_cjq0_11511.trc

نکته 7: از ویوهای مهم مربوط به این نوع از jobها، می توان به dba_jobs و dba_jobs_running اشاره کرد. پرس و جوی زیر هم می تواند در این زمینه مفید باشد:

پرس و جوی 1:

SELECT SID, r.JOB, LOG_USER, r.THIS_DATE, r.THIS_SEC  FROM DBA_JOBS_RUNNING r, DBA_JOBS j  WHERE r.JOB = j.JOB;

پرس و جوی 2:

SELECT ‘Job:’|| job, WHAT, ‘Next:’|| to_char(NEXT_DATE,’dd-Mon-yyyy HH24:MI’), ‘ Last:’|| to_char(LAST_DATE,’dd-Mon-yyyy HH24:MI’), ‘ Broken:’|| BROKEN FROM dba_jobs;

نکته 8: در صورتی که فیلد LAST_DATE در ویوی DBA_JOBS برابر با null باشد و یا در صورتی که NEXT_DATE به صورت اتوماتیک در بازه زمانی تعیین شده تغییر نکند، نشانگر عدم اجرای این job به صورت خودکار می باشد.

نکته 9 به صورت خلاصه، برای جلوگیری از عدم اجرای به موقع یک job باید نکات زیر را در نظر داشت:

1.پارامتر JOB_QUEUE_PROCESSES برابر با صفر نباشد.

SQL> show parameter JOB_QUEUE_PROCESSES

job_queue_processes                  integer     4000

2. پارامتر _SYSTEM_TRIG_ENABLED به مقدار false تنظیم نشده باشد.

select a.ksppinm parameter,b.ksppstvl value from x$ksppi a,x$ksppcv b where a.indx=b.indx and ksppinm=’_system_trig_enabled’;

برای تنظیم مقدار این پارامتر به true باید:

alter system set “_system_trig_enabled”=TRUE scope=both;

3. بانک اطلاعاتی در حالت RESTRICTED SESSIONS راه اندازی نشده باشد. برای خروج از این حالت، از دستور زیر استفاده می شود:

select logins from v$instance ;

alter system disable restricted session;

4. بلافاصله بعد از اصلاح job از commit استفاده شود.

5. job مورد نظر در حالت broken قرار نگیرد.

select job,broken from dba_jobs where job=<job_number>;

6. ممکن است مقدار _job_queue_interval به مقداری غیر از مقدار پیش فرض که 5 ثانیه می باشد، تغییر کرده باشد.

select a.ksppinm parameter,b.ksppstvl value from x$ksppi a,x$ksppcv b where a.indx=b.indx and ksppinm=’_job_queue_interval’;

نکته 10: در زیر سه نمونه از معایب dbms_job آمده است:

1.توقف آن در عین ممکن بودن، مشکل می باشد.

2.تنها مالک آن job حق انجام عملیات را بر روی آن خواهد داشت.

3.بعد از 16 بار اجرا ناموفق، broken خواهند شد.

DBMS_SCHEDULER

این بسته همانند بسته dbms_job، قابلیت اجرای خودکار دستورات، توابع و پروسیجرها را دارا می باشد و علاوه بر آن ، امکان اجرای خودکار اسکریپت را نیز در سطح سیستم عامل فراهم می کند. به عبارت دقیق تر، این نوع از jobها، در سه سطح قابل ایجاد می باشند:

  1. STORED_PROCEDUR: توابع و پروسیجر به کمک این نوع job قابل اجرا می باشند.
  2. PL/SQL block: اجرای anonymous block از طریق این نوع از jobها قابل انجام می باشد.
  3. EXECUTABLE: برای اجرای اسکریپتی که بر روی سیستم عامل موجود است، می توان از این نوع job بهره گرفت.

بسته DBMS_SCHEDULER شامل پروسیجر و فانکشنهای متنوعی می باشد که در ادامه مهمترین آن ها را با محوریت job، program، schedule و window توضیح خواهیم داد.

Job

اینکه چه برنامه ای، در چه زمانی و با چه تناوب زمانی اجرا شود، توسط job تعیین خواهد شد برای ایجاد یک job، می توان از پروسیجر create_job استفاده کرد. در جدول زیر، اسامی پارامترهای این پروسیجر را اورده ایم.

پارامترها توضیحات
job_name نام job
job_type نوع job(STORED_PROCEDURE – PL/SQL block  –  EXECUTABLE)
job_action چه عملی باید توسط این job انجام شود.
number_of_arguments چه تعداد آرگومان  باید به پروسیجر تعیین شده در قسمت job_action پاس داده شوند.
start_date تعیین زمان اولین اجرای جاب(null به معنی اکنون می باشد).
repeat_interval تناوب زمانی اجرای job(bymonth, byweekno, byyearday, bymonthday, byday, byhour, byminute, bysecond)
end_date بعد از چه تاریخی این job دیگر اجرا نشود.
enabled فعال باشد و یا غیرفعال؟
auto_drop بعد از تاریخ end_date جاب حذف شود؟
comments توضیحات
job_priority اولویت از 1 تا 5 می باشد که یک بالاترین اولویت را دارد.

-در ادامه مثالهایی از نحوه ایجاد انواع مختلف job را با هم مرور خواهیم کرد.

مثال 1: ایجاد job از نوع PL/SQL block

begin

  sys.dbms_scheduler.create_job(job_name            => ‘SYS.JOBJOB’,

                                job_type            => ‘PLSQL_BLOCK’,

                                job_action          =>

‘declare

                                   a number:=0;

  begin

  for i in 1..100 loop

   a:=a+1;

                 dbms_lock.sleep(a);

  end loop;

  end;’,

                                start_date          => to_date(null),

                                repeat_interval     => ‘Freq=Minutely;Interval=5’,

                                end_date            => to_date(null),

                                job_class           => ‘DEFAULT_JOB_CLASS’,

                                enabled             => true,

                                auto_drop           => false,

                                comments            => ”);

end;

/

 

مثال 2: ایجاد job از نوع STORED_PROCEDUR :

BEGIN

  DBMS_SCHEDULER.CREATE_JOB (

   job_name           =>  ‘update_sales’,

   job_type           =>  ‘STORED_PROCEDURE’,

   job_action         =>  ‘OS.SALES_PKG.UPDATE_SALES_SUMMARY’,

   start_date         =>  ‘to_date(’24-05-2017 00:00:00’, ‘dd-mm-yyyy hh24:mi:ss’)’,

   repeat_interval    =>  ‘FREQ=DAILY;INTERVAL=2’,

   end_date           =>  to_date(null),

   auto_drop          =>   FALSE

);

END;

/

مثال 3: ایجاد job از نوع EXECUTABLE:

/u01/job.sh

#!/bin/sh

export ORACLE_BASE=/u01/oracle

export ORACLE_HOME=/u01/oracle/11g

export ORACLE_SID=humtesti

export  PATH=$ORACLE_HOME/bin:$PATH

/u01/oracle/11g/bin/rman  target / <<EOF

run

{

backup database format ‘/u01/oracle/back/yyy%U’;

}

EOF

ساخت جاب:

begin

  sys.dbms_scheduler.create_job(job_name            => ‘SYS.JB2’,

                                job_type            => ‘EXECUTABLE’,

                                job_action          => ‘/u01/job.sh’,

                                start_date          => to_date(’24-05-2017 00:00:00′, ‘dd-mm-yyyy hh24:mi:ss’),

                                repeat_interval     => ‘Freq=Weekly;Interval=1;ByDay=Fri’,

                                end_date            => to_date(null),

                                job_class           => ‘AUTO_TASKS_JOB_CLASS’,

                                enabled             => true,

                                auto_drop           => false,

                                comments            => ”);

end;

نکته: external job از طریق پروسس extjob اجرا می شود و برای اجرای external job توسط کاربر غیر sys، به دو روش زیر قابل تصور می باشد:

روش اول: تغییر کاربر و گروهی که می تواند external job را ایجاد کند.

$ORACLE_HOME/rdbms/admin/externaljob.ora

run_user=oracle

run_group=oinstall

روش دوم: ایجاد credential برای کاربر آن با تعیین پسورد کاربر اورکل:

exec dbms_scheduler.create_credential(credential_name => ‘EXTERNAL_JOBS’,username => ‘oracle’, password => ‘o’);

برای مشاهده لیست ویوهای مربوط به credentialها ویوی dba_scheduler_credentials قابل استفاده می باشد.همچنین می توان برای حذف این credential، از دستور زیر استفاده کرد:

exec dbms_scheduler.drop_credential(credential_name => ‘EXTERNAL_JOBS’);

 

تنظیم یک credential برای یک جاب:

   begin

  sys.dbms_scheduler.set_attribute(name =>’JB2′ ,attribute => ‘credential_name’,value=>’credential1′);

  end;

در ادامه به صورت خلاصه نکاتی را در مورد این نوع از jobها اورده شده است:استفاده از پارامتر use_current_session در پروسیجر run_job سبب می شود session جاری تا اتمام اجرای job به کاربر بر نگردد البته در صورتی که این پارامتر برابر با false باشد، job مورد نظر در پس زمینه اجرا خواهد شد و session به کاربر برخواهد گشت.اجرای جاب با کمک use_current_session تاثیری در مقدار پارامتر failure_count و یا run_count نخواهد داشت.-برای اجرای دستی jobها باید از پروسیجر run_job استفاده کرد:

exec dbms_scheduler.run_job(job_name => ‘JOB_USEF’);

-برای متوقف کردن job در حال اجرا، می توان از پروسیجر stop_job استفاده کرد:

exec dbms_scheduler.stop_job(job_name => ‘JOB_USEF’);

در این صورت وضیعت جاب job_usef برابر با STOPPED خواهدشد البته اگر قرار باشد این جاب تنها یکبار اجزا شود و درصورتی که معین شده باشد تا جاب مورد نظر بیش از یکبار شود، وضیعت جاب به حالت SCHEDULED در خواهد امد.

-برای حذف job، از پروسیجر drop_job استفاده می شود:

exec dbms_scheduler.drop_job(job_name => ‘JOB_USEF’);

-پروسیجرهای enable و disable برای فعال و غیرفعالسازی jobها قابل استفاده می باشند(البته وضیعت مولفه های دیگر از قبیل program، schedule و … نیز به وسیله این دو پروسیجر قابل تغییر خواهد بود):

exec dbms_scheduler.disable(name => ‘JOB_USEF’,force => TRUE);

exec dbms_scheduler.enable(name => ‘JOB_USEF’);

-با استفاده از پروسیجر copy_job می توان job موجود در بانک را با نام جدیدی کپی کرد که در این صورت، job جدید به صورت پیش فرض غیرفعال می باشد.

exec dbms_scheduler.copy_job(old_job => ‘JOB_USEF’,new_job => ‘JOB_USEF_OLD’ );

-برای تغییر خصوصیات فعلی jobها می توان از پروسیجر set_attribute استفاده کرد. مثال:

begin
dbms_scheduler.set_attribute (
name               =>  ‘run_load_sales’,
attribute          =>  ‘repeat_interval’,
value              =>  ‘freq=daily; byhour=3’);
end;
/

وضیعت jobها

وضیعت فعلی job، از طریق ویوی dba_scheduler_jobs و با کمک فیلد state قابل مشاهده خواهد بود. فیلد state می تواند مقادیر زیر را به خود بگیرد:

DISABLED : در وضیعت غیرفعال قرار دارد و به صورت خودکار اجرا نخواهد شد.

FAILED: اجرای job با خطا متوقف شده است و همچنین قرار نیست که دیگر این job به صورت خودکار اجرا شود.

SCHEDULED: قابلیت اجرای خودکار برای job وجود دارد و مانعی برای آن وجود ندارد.

RUNNING: در حال اجرا می باشد.

SUCCEEDED: به صورت کامل اجرا شده است و دیگر اجرا نخواهد شد.

BROKEN : یک job ممکن است به دلیل اجرای ناموفق، در وضیعت broken قرار بگیرد البته تعداد اجرای ناموفق آن باید از مقدار تعیین شده برای MAX_FAILURES بیشتر باشد.

Stopped: قبلا در حال اجرا بوده و متوقف شده است و قرار است تنها یکبار اجرا شود.

Schedule

زمان انجام و نیز تناوب زمانی اجرای jobها، از طریق schedule قابل تعیین خواهد بود در روش قبلی این کار از طریق پارامترهای start_date،repeat_interval ، end_date انجام می شد در صورتی که می توان به جای تعیین این پارامترها، از پارامتر دیگری به نام schedule_name استفاده کرد برای انجام این کار، باید ابتدا Scheduleای ایجاد کرد و سپس از ان schedule برای این پارامتر بهره گرفت. از مزیتهای schedule می توان به استفاده همزمان ان در چندین job مختلف اشاره کرد.

مثال: در این مثال نحوه ایجاد job با کمک schedule را مشاهده خواهید کرد:

begin

sys.dbms_scheduler.create_schedule(schedule_name   => ‘USEF.SCHEDULE1’,

start_date      => to_date(’22-06-2017 00:00:00′, ‘dd-mm-yyyy hh24:mi:ss’),

repeat_interval => ‘Freq=Minutely;Interval=10’,

end_date        => to_date(null),

comments        => ”);

end;

/

begin

  sys.dbms_scheduler.create_job(job_name            => ‘USEF.JOB1’,

                                job_type            => ‘PLSQL_BLOCK’,

                                job_action          => ‘pr1;’,

                                schedule_name       => ‘USEF.SCHEDULE1’,

                                job_class           => ‘AUTO_TASKS_JOB_CLASS’,

                                enabled             => true,

                                auto_drop           => false,

                                comments            => ”);

end;

/

-برای حذف Scheduleها باید از پروسیجر drop_schedule استفاده کرد:

BEGIN

  DBMS_SCHEDULER.drop_schedule(schedule_name =>‘USEF.SCHEDULE1’);

END;

/

-برای تغییر خصوصیات فعلی یک Schedule می توان از پروسیجر set_attribute استفاده کرد.-برای مشاهده اسامی scheduleها، می توان از ویوی dba_scheduler_schedules استفاده کرد.

 

Program

Jobای که ایجاد می شود، باید چه عملی را انجام دهد؟ در روش قبلی(در پروسیجر create_job)، پاسخ به این سوال با کمک پارامترهای job_type و job_action انجام می شد. program روش دیگری برای پاسخ دادن به این سوال می باشد که در این صورت، در هنگام ساخت job از پارامتر program_name به جای پارامترهای مذکور استفاده می شود. همانند schedule می توان از program هم استفاده چند باره داشت. برای ایجاد program، باید از پروسیجر create_program استفاده کرد.

 مثال: در این مثال نحوه ایجاد job با کمک program را مشاهده خواهید کرد:

begin

  sys.dbms_scheduler.create_program(program_name        => ‘USEF.PROGRAM1’,

                                    program_type        => ‘PLSQL_BLOCK’,

                                    program_action      => ‘pr1;’,

                                    number_of_arguments => 0,

                                    enabled             => true,

                                    comments            => ”);

end;

/

begin

  sys.dbms_scheduler.create_job(job_name            => ‘USEF.JOB1’,

                                program_name        => ‘USEF.PROGRAM1’,

                                start_date          => to_date(’22-06-2017 00:00:00′, ‘dd-mm-yyyy hh24:mi:ss’),

                                repeat_interval     => ‘Freq=Hourly;Interval=1’,

                                end_date            => to_date(null),

                                job_class           => ‘AUTO_TASKS_JOB_CLASS’,

                                enabled             => true,

                                auto_drop           => false,

                                comments            => ”);

end;

/

-برای تغییر خصوصیات فعلی یک program می توان از پروسیجر set_attribute استفاده کرد.

-برای مشاهده لیست programها، می توان از ویوی dba_scheduler_programs استفاده کرد.

-برای استفاده از یک program توسط یک کاربر، کاربر مورد نظر یا باید مالک ان program باشد و یا اینکه مجوز execute ان را دارا باشد.

آرگومان

فرض کنید از پروسیجری استفاده می کنیم که شامل پارامتر ورودی می باشد، برای استفاده از این پروسیجر در یک job می توان هر کدام از این پارامترهای ورودی را تحت یک ارگومان به این پروسیجر پاس داد.

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

مثال 1:  آرگومان در این مثال مربوط به پروسیجر می باشد.

 

begin 

DBMS_SCHEDULER.create_program (

    program_name        => ‘test_stored_procedure_prog’,

    program_type        => ‘STORED_PROCEDURE’,

    program_action      => ‘DBMS_STATS.gather_schema_stats’,

    number_of_arguments => 1,

    enabled             => FALSE

);

end;

/

begin 

  DBMS_SCHEDULER.define_program_argument (

    program_name      => ‘test_stored_procedure_prog’,

    argument_name     => ‘ownname’,

    argument_position => 1,

    argument_type     => ‘VARCHAR2’,

    default_value     => ‘USEF’);

  DBMS_SCHEDULER.enable (name => ‘test_stored_procedure_prog’);

END;

/

مثال 2: در این مثال، آرگومان مربوط به external job می باشد که در نتیجه اجرای آن، دستور(/bin/ls /u07) اجرا خواهد شد.

BEGIN

  DBMS_SCHEDULER.create_job(

    job_name             => ‘e5’,

    job_type             => ‘EXECUTABLE’,

    number_of_arguments  => 1,

    job_action           => ‘/bin/ls’,

    auto_drop            => FALSE,

    enabled              => FALSE);

  DBMS_SCHEDULER.set_job_argument_value(‘e5′,1,’/u07’);

  DBMS_SCHEDULER.enable(‘e5’);

END;

/

-برای مشاهده لیست آرگومان ها می توان از ویوی dba_scheduler_program_args استفاده کرد.

Job Class

با استفاده از job class می توان jobهای با خصوصیتهای مشابه و نزدیک به هم را در یک گروه مجزا قرار داد و در مورد آنها سیاستهایی را اعمال کرد از قبیل سطح لاگ گیری، تاریخچه نگهداری لاگها، تخصیص منابع، تعیین اولویتها و…. تعیین کلاس برای یک job باید در هنگام ایجاد آن(از طریق پروسیجرcreate_job) و با کمک پارامتر job_class انجام شود که در صورت عدم تعریف ان، jobها در کلاس DEFAULT_JOB_CLASS قرار می گیرند.

برای ساخت یک job_class جدید باید از پروسیجر create_job_class استفاده کرد که پارامترهای ان در ادامه خواهند امد:

job_class_name: این پارامتر، نام job class را مشخص خواهد کرد.

resource_consumer_group: جابهای موجود در این کلاس از کدام resource consumer group استفاده می کنند. لیست consumer groupها با دستور زیر تعیین می شود:

select consumer_group from dba_rsrc_consumer_groups;

در ادامه مثالی در مورد نحوه ایجاد یک resource plan اورده شده است:

exec dbms_resource_manager.create_pending_area();

exec dbms_resource_manager.create_plan(plan => ‘PLANU’, comment => ‘plan’);

exec dbms_resource_manager.create_consumer_group ( consumer_group => ‘GROUPU’ , comment =>’consumer_group’);

exec dbms_resource_manager.create_plan_directive ( plan => ‘PLANU’,group_or_subplan =>‘GROUPU’,comment => ‘Limit CPU resource’,parallel_degree_limit_p1 => 4 );

exec dbms_resource_manager.validate_pending_area();

exec dbms_resource_manager.create_plan_directive ( plan => ‘PLANU’,group_or_subplan =>‘OTHER_GROUPS’,comment => ‘Limit CPU resource’,parallel_degree_limit_p1 => 2);

exec dbms_resource_manager.validate_pending_area();

exec dbms_resource_manager.submit_pending_area();

exec dbms_resource_manager.create_pending_area();

exec dbms_resource_manager_privs.grant_switch_consumer_group(grantee_name=>‘USEF’ ,consumer_group=>‘GROUPU’,grant_option=>FALSE);

exec dbms_resource_manager.set_initial_consumer_group(user => ‘USEF’,consumer_group =>‘GROUPU’);

exec dbms_resource_manager.submit_pending_area();

Service: نام سرویس؛ که می تواند جاب مورد نظر را به instanceای به خصوص وصل کند.

logging_level: سطح لاگ گیری را مشخص می کند که می تواند مقادیر زیر را به خود بگیرد:

DBMS_SCHEDULER.LOGGING_OFF                     هیچ لاگی ثبت نمی شود

DBMS_SCHEDULER.LOGGING_RUNS                  تنها زمان استارت ثبت می شود

DBMS_SCHEDULER.LOGGING_FULL       ثبت همه اطلاعات

log_history: چند روز لاگها در سیستم باقی بمانند.

برای ساخت یک job class، تنها دو پارامتر اول اجباری می باشد. مثال:

BEGIN

  DBMS_SCHEDULER.create_job_class (job_class_name => ‘job_usef’,resource_consumer_group => ‘DSS_GROUP’);

END;

/

برای مشاهده لیست job classها و consumer group مربوط به انها می توان از پرس و جوی زیر استفاده کرد:

select job_class_name,resource_consumer_group from  dba_scheduler_job_classes;

برای حذف یک job class هم می توان از پروسیجر drop_job_class استفاده کرد. مثال:

BEGIN

DBMS_SCHEDULER.drop_job_class(job_class_name => ‘job_usef’,force => TRUE);

end;

/

Window

Window کاربردی شبیه به schedule دارد با این تفاوت که می تواند اجرای کارها را تنها به بازه زمانی معینی محدود کند تا پس از ان بازه زمانی معین، job مورد نظر متوقف شود حتی اگر به صورت کامل اجرا نشده باشد(البته بین window و schedule تفاوتهای بسیار مهم دیگری هم وجود دارد که در ادامه به ان اشاره خواهد شد). برای ایجاد window از پروسیجر CREATE_WINDOW استفاده می شود:

BEGIN

dbms_scheduler.create_window(

    window_name     => ‘EARLY_MORNING_WINDOW’,

    duration        =>  numtodsinterval(1, ‘hour’),

    resource_plan   => ‘DEFAULT_MAINTENANCE_PLAN’,

    repeat_interval => ‘FREQ=DAILY;BYHOUR=5;BYMINUTE=0;BYSECOND=0’);

END;

نکته: مقدار پارمتر duration به اشکال مختلف قابل تعیین می باشد که برای نمونه می توان به موارد زیر اشاره کرد:

-استفاده از تابع NUMTODSINTERVAL :

NUMTODSINTERVAL(150, ‘DAY’)

NUMTODSINTERVAL(1500, ‘HOUR’)

NUMTODSINTERVAL(15000, ‘MINUTE’)

NUMTODSINTERVAL(150000, ‘SECOND’)

*استفاده از عبارت interval:

interval ‘1’ second

interval ‘1’ minute

interval ‘1’ hour

interval ‘1’ day

البته می توان از پرس و جوی زیر هم کمک گرفت:

SQL> SELECT NUMTODSINTERVAL(1, ‘MINUTE’) FROM dual;

NUMTODSINTERVAL(1,’MINUTE’)

———————————————————————

+000000000 00:01:00.000000000

-ایجاد window با کمک schedule: 

BEGIN

DBMS_SCHEDULER.CREATE_WINDOW (

   window_name       => ‘WIN1’,

   schedule_name     => ‘USEF.SCHED1’,

   resource_plan     => ‘DEFAULT_PLAN’,

   duration          => interval ‘1’ minute,

   comments          => ‘WIN1’);

END;

/

-ایجاد job با کمک window:

begin

  sys.dbms_scheduler.create_job(job_name            => ‘USEF.WINJOB’,

                                program_name        => ‘USEF.PRG3’,

                                schedule_name       => ‘SYS.WIN1’,

                                job_class           => ‘AUTO_TASKS_JOB_CLASS’,

                                enabled             => false,

                                auto_drop           => false,

                                comments            => ”);

  sys.dbms_scheduler.enable(name => ‘USEF.WINJOB’);

end;

/

برای تغییر خصوصیات فعلی یک ویندو، باید از پروسیجر SET_ATTRIBUTE استفاده کرد برای مثال، بلاک زیر مدت زمان اجرای ویندو SATURDAY_WINDOW را به 4 ساعت تغییر میدهد البته قبل از اعمال این تغییر، باید این ویندو را غیرفعال کرد و بعد از اعمال تغییرات، این ویندو را به حالت فعال دراورد:

BEGIN

dbms_scheduler.disable(name  => ‘SATURDAY_WINDOW’);

dbms_scheduler.set_attribute(name      => ‘SATURDAY_WINDOW’,

    attribute => ‘DURATION’,

    value     => numtodsinterval(4, ‘hour’));

dbms_scheduler.enable(name => ‘SATURDAY_WINDOW’);

END;

-در هر زمان  تنها یک ویندو می تواند باز باشد همچنین زمانی که دو ویندو بخواهند با هم اجرا شوند، مقدار پارامتر window_priority بسیار موثر خواهد بود تا کدام یک از windowها با توجه به اولویتی که دارد، به اجرا در بیاید.

SELECT window_name, resource_plan, enabled, active FROM   dba_scheduler_windows;

در صورتی که دو ویندو اولویت یکسانی داشته باشند، ویندویی که درصد بیشتری از ان باقی مانده است، به اجرا در خواهد امد.همچنین اگر ویندویی در حال اجرا باشد و ویندوی جدیدی که اولویت بالاتری دارد، قصد اجرا شدن را داشته باشد، ویندوی در حال اجرا متوقف خواهد شد و جای خود را به ویندوی با اولویت بالاتر خواهد داد. -پنجره ها را می توان به صورت دستی باز کرد و یا بست. استفاده از عبارت force سبب می شود تا بدون ملاحضه اولویتها، ویندو مورد نظر باز شود همچنین می توان برای اجرای ویندوی مورد نظر، زمانی را تعیین کرد:

exec  DBMS_SCHEDULER.open_window ( window_name => ‘test2’,duration=> INTERVAL ‘1’ MINUTE, force=> TRUE);

exec  DBMS_SCHEDULER.close_window (window_name => ‘test2’);

-جزییات ویندوها را می توان در ویوهای DBA_SCHEDULER_WINDOW_LOG و DBA_SCHEDULER_WINDOWS مشاهده کرد.

مثال: در مثال زیر، اثر بسته شدن ویندو بر روی job روشن خواهد شد.برای این کار، ابتدا جدولی را ایجاد می کنیم:

create table usef_tbl(id number(32) primary key  ,sbt_date date);

create table usef_tbl2(id number(32) primary key  ,sbt_date date);

create sequence seq1;

در پروسیجر زیر، با دو وقفه، تاریخ جاری در جدول ثبت خواهد شد:

create or replace procedure usef_proc1(m number) is

begin

  dbms_lock.sleep(20);

  insert into usef_tbl values (seq1.nextval, sysdate);

  commit;

  dbms_lock.sleep(45);

  insert into usef_tbl2 values (seq1.nextval, sysdate);

  commit;

end;

در ادامه ویندویی ایجاد می کنیم که سه دقیقه یکبار اجرا شده و به مدت یک دقیقه به طول خواهد انجامید:

begin

  sys.dbms_scheduler.create_window(window_name     => ‘WM2’,

                                   resource_plan   => ‘DEFAULT_MAINTENANCE_PLAN’,

                                   start_date      => to_date(null),

                                   repeat_interval => ‘Freq=Minutely;Interval=3’,

                                   end_date        => to_date(null),

                                   duration        => ’00 00:01:00′,

                                   window_priority => ‘HIGH’,

                                   comments        => ”);

end;

/

حال با دستور زیر، جابی را ایجاد خواهیم کرد:

begin

  sys.dbms_scheduler.create_job(job_name            => ‘SYS.WMJJ’,

                                job_type            => ‘PLSQL_BLOCK’,

                                job_action          => ‘usef_proc1(9);’,

                                schedule_name       => ‘SYS.WM2’,

                                job_class           => ‘DEFAULT_JOB_CLASS’,

                                enabled             => true,

                                auto_drop           => false,

                                comments            => ”);

end;

/

به صورت پیش فرض، جاب مورد نظر بعد از بسته شدن ویندو، به کار خودش ادامه خواهد داد(چون زمان اجرای این جاب از زمان اجرای ویندو بیشتر می باشد) برای متوقف کردن جاب بعد از بسته شدن ویندو، باید خصیصه stop_on_window_close را برابر با true قرار دهیم:

BEGIN

  DBMS_SCHEDULER.SET_ATTRIBUTE(‘WMJJ’, ‘stop_on_window_close’,true );

END;

/

-هنگام باز شدن یک ویندو، resource plan ان نیز در صورت لزوم تغییر خواهد کرد:

Fri Jul 14 22:37:54 2017

Closing scheduler window

Closing Resource Manager plan via scheduler window

Clearing Resource Manager plan via parameter

Setting Resource Manager plan SCHEDULER[0x22B0]:DEFAULT_MAINTENANCE_PLAN via scheduler window

Setting Resource Manager plan DEFAULT_MAINTENANCE_PLAN via parameter

Fri Jul 14 22:37:54 2017

Starting background process VKRM

Fri Jul 14 22:37:54 2017

VKRM started with pid=34, OS id=28785

Closing scheduler window

Closing Resource Manager plan via scheduler window

Clearing Resource Manager plan via parameter

Setting Resource Manager plan SCHEDULER[0x5D10C]:PLANU via scheduler window

Setting Resource Manager plan PLANU via parameter

برای ممانعت از تغییر resource plan در زمان اجرای جاب، می توانیم از دو حربه زیر استفاده کنیم:

یک: تنظیم جبری پارامتر RESOURCE_MANAGER_PLAN به مقداری مشخص:

ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = ‘FORCE:mydb_plan’;

دوم:تنظیم صفت RESOURCE_PLAN به مقدار null:

execute dbms_scheduler.set_attribute(‘WEEKNIGHT_WINDOW’,’RESOURCE_PLAN’,”);

برای بدست اوردن شکل ddl یک job، باید از پرس و جوی زیر استفاده کرد:

SELECT to_char(DBMS_METADATA.get_ddl(‘PROCOBJ’,’JOB_NAME’, ‘USEF’)) AS job_def FROM dual;

-ویوی زیر اطلاعاتی از قبیل متوسط و حداکثر را در مورد windowهای اجرا شده در بانک را به ما خواهد داد:

select c.client_name,c.status,w.window_group_name,w.next_start_date as next_start_date,extract(hour from c.mean_job_duration) * 60 + extract(minute from c.mean_job_duration) as mean_job_duration,extract(hour from c.max_duration_last_7_days) * 60 + extract(minute from c.max_duration_last_7_days) as mdl7  from dba_autotask_client c ,dba_scheduler_window_groups w  where w.window_group_name = c.window_group  order by 1 ;

همچنین وضیعت جاری ویندوی مورد نظر از طریق پرس و جوی زیر بدست می اید:

select l.active  from dba_scheduler_windows l where l.window_name=’W1′;

 

window group

همانطور که مشخص شد، هر job در هر لحظه تنها می تواند از یک window استفاده کند که در این صورت محدودیتها و قوانین ان ویندو برای ان جاب اعمال خواهد شد حال در صورتی که بخواهیم یک job در هر اجرا، در یک ویندو به خصوص قرار بگیرد، می توانیم از window group استفاده کنیم که در این صورت مجموعه ای از چند window  تحت یک نام در یک گروه قرار می گیرند و job موجود در این گروه، در زمانهای تعیین شده در هر یک از این ویندوها، به اجرا در خواهد امد(البته با رعایت اولویتها و محدودیتها). همچنین باید تکرار شود که در هر لحظه تنها یک ویندو اجازه باز شدن را دارد.

برای مشاهده لیست window groupها به همراه اعضای هر یک از انها، می توان از ویوی dba_scheduler_wingroup_members استفاده کرد.

Automated Maintenance Task

همانطور که می دانید، اوراکل چند مورد از وظایف dba را به صورت خودکار و معمولا در زمانی خارج از پیک کاری سیستم انجام می دهد و در صورت لزوم خروجی ای را ارائه می کند تا dba بتواند از ان خروجی بهرمند شود. از بین این کارها Automatic Segment Advisor و Automatic SQL Tuning Advisor ممکن است توصیه هایی را به dba ارائه بدهند و Automatic Optimizer Statistics Collection هم وظیفه دارد تا امارهای مربوط به اشیاها را در صورت فقدان و یا stale بودنشان، بروز کند.

نکته ای که سبب شد تا این مبحث را در این قسمت مورد بررسی قرار دهیم، ارتباط automated maintenance task با maintenance window می باشد که در ادامه چگونگی ارتباط بین انها خواهد امد.

زمانی که maintenance window به حالت open در می اید، به صورت خودکار برای هر maintenance task جابی ایجاد می شود که نام ان در زمان اجرا و با پیشوند ORA$AT مشخص می شود برای صورت مثال،  در بانک ما ORA$AT_OS_OPT_SY_8 برای Optimizer Statistics و ORA$AT_SA_SPC_SY_11 برای Segment Advisor ساخته شده است. جاب ایجاد شده، بلافاصله بعد از اجرا، به صورت کامل از لیست جابها پاک خواهد شد و تنها در logها ردپایی از ان باقی خواهد ماند(ویوی dba_scheduler_job_log).

-در صورتی که maintenance window خیلی طولانی شود، به جز Automatic SQL Tuning Advisor دو task دیگر هر چهار ساعت یکبار تکرار می شود.

-برای فعال و غیرفعال کردن هر یک از این taskها، می توان از پکیج DBMS_AUTO_TASK_ADMIN استفاده کرد.

exec   dbms_auto_task_admin.disable(client_name => ‘sql tuning advisor’,operation   => NULL,window_name => NULL);

همچنین می توان برای یک window خاص این task را غیر فعال کرد:

exec dbms_auto_task_admin.disable(client_name => ‘sql tuning advisor’, operation   => NULL, window_name => ‘MONDAY_WINDOW’);

برای مشاهده وضیعت فعلی  هر کدام از این taskها، می توان از پرس و جوی زیر استفاده کرد:

select client_name, status from dba_autotask_client;

-برای تغییر زمان اجرای maintenance windowها می توان از دستورات زیر کمک گرفت:

تنظیم زمان مناسب برای WEEKNIGHT_WINDOW:

exec DBMS_SCHEDULER.disable(name=>'”SYS”.”WEEKNIGHT_WINDOW”‘);

exec dbms_scheduler.set_attribute(‘WEEKNIGHT_WINDOW’,’REPEAT_INTERVAL’,’freq=daily;byday=SUN,SAT,MON,TUE,WED,THU;byhour=20;byminute=0;bysecond=0′);

exec dbms_scheduler.set_attribute(‘WEEKNIGHT_WINDOW’,’DURATION’,’+000 08:00:00′);

exec DBMS_SCHEDULER.ENABLE(name=>'”SYS”.”WEEKNIGHT_WINDOW”‘);

تنظیم زمان مناسب برای WEEKEND_WINDOW:

exec DBMS_SCHEDULER.disable(name=>'”SYS”.”WEEKEND_WINDOW”‘);

exec dbms_scheduler.set_attribute(‘WEEKEND_WINDOW’,’REPEAT_INTERVAL’,’freq=daily;byday=FRI;byhour=02;byminute=0;bysecond=0′);

exec dbms_scheduler.set_attribute(‘WEEKEND_WINDOW’,’DURATION’,’+000 23:00:00′);

exec DBMS_SCHEDULER.ENABLE(name=>'”SYS”.”WEEKEND_WINDOW”‘);

برای مشاهده وضیعت فعلی maintenance windowها می توان از پرس و جوی زیر استفاده کرد:

select window_name, repeat_interval, duration,l.enabled,active from dba_scheduler_windows l;

نکاتی در مورد SCHEDULER:

نکته 1: اطلاعات scheduler در جدول SCHEDULER$_JOB ذخیره می شود.

نکته 2: زمانی که job به طور مستقیم توسط کاربر اجرا می شود، در لیست jobهای در حال اجرا قابل مشاهده نیست(یعنی نمی توان آن را در dba_scheduler_running_jobs مشاهده کرد)

نکته 3: به صورت پیش فرض، لاگها به مدت سی روز حفظ می شوند و پس از آن پاک خواهند شد این مقدار از طریق ویوی dba_scheduler_global_attribute قابل مشاهده می باشد و می توان این مقدار را به صورت زیر تغییر داد:

begin

DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(‘log_history’,’111′);

end;

البته حذف لاگها به صورت دستی هم امکان  پذیر می باشد:

begin DBMS_SCHEDULER.PURGE_LOG(); end;

همچنین می توان لاگها را به صورت بازه ای حذف کرد:

begin DBMS_SCHEDULER.PURGE_LOG(log_history => 3, which_log => ‘JOB_LOG’); end;

نکته 4: تعیین اولویت هم برای jobها ممکن می باشد که در این صورت می توان به یک job، اولویتی بین عدد یک تا پنج داده شود که عدد یک، بالاترین اولویت را دارد:

BEGIN

DBMS_SCHEDULER.SET_ATTRIBUTE (

   name           =>   ‘J1’,

   attribute      =>   ‘job_priority’,

   value          =>   1);

END;

/

نکته 5: تعیین و تغییر timezone پیش فرض برای dbms_scheduler:

SELECT SYSTIMESTAMP  FROM dual;
SELECT dbms_scheduler.stime FROM dual ;

select current_date, sysdate,dbtimezone,sessiontimezone from dual;

exec dbms_scheduler.set_scheduler_attribute (‘DEFAULT_TIMEZONE’, ‘Asia/Calcutta’);

مقدار جاری timezone را می توان در ویوی dba_scheduler_global_attribute مشاهده کرد.

نکته 6: در نسخه 10gR1 برای ایجاد external job، تنها داشتن مجوز create job کافی بود ولی در نسخه 11g، باید مجوز دیگری به نام CREATE EXTERNAL JOB را هم در اختیار داشت.همچنین با مجوز create any job و رول SCHEDULER_ADMIN هم می توان ایجاد و مدیریت جابها را انجام داد.جدول زیر به صورت دقیق تر در مورد مجوزها اطلاعاتی را ارائه می کند.

Task Privilege Needed
Create a job CREATE JOB or CREATE ANY JOB
Alter a job ALTER or CREATE ANY JOB or be the owner
Run a job ALTER or CREATE ANY JOB or be the owner
Copy a job ALTER or CREATE ANY JOB or be the owner
Drop a job ALTER or CREATE ANY JOB or be the owner
Stop a job ALTER or CREATE ANY JOB or be the owner
Disable a job ALTER or CREATE ANY JOB or be the owner
Enable a job ALTER or CREATE ANY JOB or be the owner
Create a program CREATE JOB or CREATE ANY JOB
Create a schedule CREATE JOB or CREATE ANY JOB
Create a job class MANAGE SCHEDULER
Create a window MANAGE SCHEDULER
Privilege Needed MANAGE SCHEDULER

از لحاط امنیتی توصیه می شود تا مجوز create any job به هر کسی داده نشود چون به واسطه این مجوز، کاربر می تواند برای کاربران دیگر جاب تعریف کند.

نکته 7: در صورتی که پارامتر JOB_QUEUE_PROCESSES برابر با صفر باشد، هر دو نوع از jobها غیرفعال خواهند شد(dbms_job و dbms_schedular). البته تنظیم این پارامتر به مقدار صفر، سبب توقف jobی که در حال اجرا می باشد نخواهد شد.

نکته8: در صورتی که خصوصیت MAX_JOB_SLAVE_PROCESSES به عدد مشخصی تنظیم شده باشد، بیش از ان تعداد، امکان اجرای job همزمان وجود نخواهد داشت(از طریق dbms_scheduler). مقدار پیش فرض این صفت، برابر با null می باشد که محدودیتی را ایجاد نخواهد کرد:

select value from dba_scheduler_global_attribute where attribute_name = ‘MAX_JOB_SLAVE_PROCESSES’;

برای تغییر مقدار این صفت به null باید:

SQL> exec dbms_scheduler.set_scheduler_attribute(‘max_job_slave_processes’,null);

نکته 9: در صورتی که خصیصه SCHEDULER_DISABLED در ویوی dba_scheduler_global_attribute برابر با true باشد، در این صورت جابهای تعریف شده توسط dbms_scheduler ، قابل اجرا نخواهند بود. برای برگرداندن ابن مقدار باید:

exec dbms_scheduler.set_scheduler_attribute(‘scheduler_disabled’,’false’);

نکته 10: یکی از دلایل عدم اجرای dbms_scheduler می تواند بخاطر عدم استارت سرویسی که در job_class به آن اشاره شده است، برگردد. در این صورت باید سرویس مربوطه را با استفاده از دستور dbms_service.start_service و یا srvctl به حالت اجرا دراورد.

نکته 11: از دیگر دلایل احتمالی عدم اجرای dbms_scheduler، می توان به محدودیت منابع تعریف شده در resource plan اشاره کرد.

نکته 12: در صورتی که در فیلد next_run_date مربوط به ویوی dba_scheduler_jobs، به timezone به صورت عددی(+04:30) اشاره شود(به جای نمایش نام timezone مثل US/PACIFIC)، ممکن است daylight saving در نظر گرفته نشود و جاب مورد نظر با یک ساعت عقب و یا جلو اجرا شود.

نکته 13: برای راه اندازی مجدد scheduler می توان دستورات زیر را اجرا کرد:

exec dbms_scheduler.set_scheduler_attribute(‘SCHEDULER_DISABLED’, ‘TRUE’);

alter system set job_queue_processes=0;

exec dbms_ijob.set_enabled(FALSE);

alter system flush shared_pool;

alter system flush shared_pool;

exec dbms_ijob.set_enabled(TRUE);

alter system set job_queue_processes=99;

exec dbms_scheduler.set_scheduler_attribute(‘SCHEDULER_DISABLED’, ‘FALSE’);

در این صورت، پروسس CJQ0 راه اندازی مجدد خواهد شد:

2017-07-02T16:09:52.058254+04:30

Stopping background process CJQ0

2017-07-02T16:09:52.073575+04:30

ALTER SYSTEM SET job_queue_processes=0 SCOPE=BOTH;

2017-07-02T16:09:53.769322+04:30

Starting background process CJQ0

2017-07-02T16:09:53.827848+04:30

ALTER SYSTEM SET job_queue_processes=99 SCOPE=BOTH;

2017-07-02T16:09:53.830816+04:30

CJQ0 started with pid=109, OS id=26481

2017-07-02T16:10:01.822576+04:30

Setting Resource Manager plan SCHEDULER[0x3009]:DEFAULT_MAINTENANCE_PLAN via scheduler window

Setting Resource Manager plan DEFAULT_MAINTENANCE_PLAN via parameter

نکته 14: با کمک پرس و جوی زیر، می توان اسکریپت لازم را برای تبدیل جابهای از نوع dbms_job به حالت scheduler را بدست اورد:

select ‘dbms_scheduler.create_job( ‘ || chr(13)|| ‘  job_name=>”’ || substr(upper(translate(what,’.(),;’,’_’)),1,26) ||’_JOB’ || ”’, ‘ || chr(13)|| ‘  job_type => ”PLSQL_BLOCK”,’ || chr(13)|| ‘  job_action=> ”begin ‘ || chr(13) || what  || chr(13) || ‘end; ”, ‘ || chr(13)|| ‘  start_date => to_timestamp(”’     || to_char(next_date,’mm/dd/yyyy hh24:mi:ss’)   || ”’, ”mm/dd/yyyy hh24:mi:ss”), ‘ || chr(13)|| DECODE (interval,’null’,NULL,  ‘  repeat_interval => ”’ || interval || ”’, ‘ || chr(13) )|| ‘  enabled => true, auto_drop=> false, ‘ || chr(13)|| ‘  comments => ”Converted from job ‘ || job || ”” || chr(13)|| ‘);’ || chr(13)  from user_jobs where broken = ‘N’;

نکته 15: مقدار پارامتر repeat_interval  به طریقهای مختلفی قابل تعیین می باشد که در جدول زیر، مثالهای در این مورد اورده شده است.

تناوب زمانی توضیحات
‘sysdate + 1/24”systimestamp + 1/24”sysdate + interval ”1” hour”systimestamp + interval ”1” hour’freq=hourly  

هر ساعت یکبار

‘trunc(sysdate, ”HH24”) + 1/24”trunc(systimestamp, ”HH24”) + 1/24”trunc(sysdate, ”HH24”) + interval ”1” hour”trunc(systimestamp, ”HH24”) + interval ”1” hour’ ‘freq=hourly; byminute=0; bysecond=0;’   

 

هر ساعت یکبار(سر ساعت)

freq=daily; byhour=2 هر روز ساعت دو صبح
freq=daily; byhour=9,21 هر روز ساعت 9 صبح و بعد ازظهر
freq=monthly; bymonthday=1 روز اول هر ماه
freq=monthly; bymonthday=-1 روز اخر هر ماه
‘trunc(sysdate) + 1 + 6/24”trunc(systimestamp) + 1 + 6/24”trunc(sysdate) + interval ”1 6” day to hour ”trunc(systimestamp) + interval ”1 6” day to hour’  

هر روز ساعت 6

‘sysdate + 1/24/60”systimestamp + 1/24/60’ ‘sysdate + interval ”1” minute”systimestamp + interval ”1” minute’ ‘freq=minutely;’  

هر دقیقه یکبار

freq=yearly; bymonth=sep; bymonthday=20; بیستم سپتامبر هر سال
‘trunc(sysdate, ”MI”) + 1/24/60’

‘trunc(systimestamp, ”MI”) + 1/24/60”trunc(sysdate, ”MI”) + interval ”1” minute”trunc(systimestamp, ”MI”) + interval ”1” minute’ ‘freq=minutely; bysecond=0;’

 

 

هر دقیقه یکبار(در شروع دقیقه)

‘freq=weekly; byday=mon; byhour=9; byminute=0; bysecond=0;’ ‘trunc(next_day(sysdate, ”MONDAY”)) + 9/24”trunc(next_day(systimestamp, ”MONDAY”)) + 9/24”trunc(next_day(sysdate, ”MONDAY”)) + interval ”9” hour”trunc(next_day(systimestamp, ”MONDAY”)) + interval ”9”hour’  

 

 

هر دوشنبه ساعت 9

Crontab

برای زمانبندی در سطح لینوکس می توان از سرویسهایی چون atd، crontab و یا در صورت لزوم از anacron استفاده کرد که در اینجا سرویس crontab را به دلیل کاربرد زیادی که برای یک مدیر بانک اطلاعاتی دارد، مورد بررسی قرار خواهیم داد.

برای کار با این سرویس، از دستور crontab استفاده می شود که پروسس crond مسئولیت اجرای وظایف این دستور را بر عهده دارد که به صورت خودکار راه اندازی می شود و با اطلاعاتی که در فایلهایی چون /var/spool/crond/* ذخیره شده است(در این مسیر فایلهایی به اسم کاربران وجود دارد که job هر کدام در ان تنظیم شده است)، وظایفش را انجام می دهد. این پروسس که معمولا تحت نظر init اجرا می شود در هر دقیقه یکبار وظیفه دارد تا عملیات محوله را مورد بررسی و در صورت لزوم انجام دهد.

دستور crontab سوییچهای مختلفی دارد که از پرکاربردترین انها می توان به موارد زیر اشاره کرد:

crontab –e    ویرایش

crontab -l      نمایش محتویات

crontab –u oracle  –e    ویرایش برای کاربر اوراکل

crontab –r             حذف کامل محتویات کرونتب

در فایل crontab خطوط به صورت مستقل و جدا از هم معنی پیدا می کنند و هر خط می تواند بیانگر یک job باشد که برای تنظیم ان، باید در ابتدا با ساختار ان اشنا بود که در این قسمت امده است.

# ┌───────────── min (0 – 59)

 # │ ┌────────────── hour (0 – 23)

 # │ │ ┌─────────────── day of month (1 – 31)

 # │ │ │ ┌──────────────── month (1 – 12)

 # │ │ │ │ ┌───────────────── day of week (0 – 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)

 # │ │ │ │ │

 # │ │ │ │ │

 # * * * * *  command to execute

در ادامه مثالهایی را در این مورد مشاهده خواهید کرد.

مثال 1: در خط زیر ابتدا به کاربر اوراکل سوییچ می شود و سپس در ساعت 19:50 دقیقه، فایل level1 اجرا خواهد شد:

50 19  * * *  su – oracle  /home/oracle/level1 

مثال 2: فایل level1 هر نیم ساعت یکبار اجرا می شود:

00,30 * * * *   /home/oracle/level1 

مثال 3: فایل level1 در ساعتهای 9، 10 و 11 اجرا می شود:

00  09,10,11 * * *   /root/level1 

مثال 4: دوشنبه و چهارشنبه ساعت دو بعدازظهر فایل level1 اجرا خواهد شد:

* 2 * * 1,3  /root/level1  

البته برای تنظیم زمان به صورت بازه ای می توان از خط تیره(-) استفاده کرد(دوشنبه تا چهارشنبه):

* 2 * * 1-3  /root/level1

مثال 5: فایل a هر سه دقیقه یکبار اجرا می شود:

*/3  *  *  * * /u01/a

مثال 6: فایل a هر چهار روز یکبار اجرا می شود:

*  *  */4  * * /u01/a

مثال 7: اجرای چند اسکریپت با هم:

* * * * * /scripts/script.sh; /scripts/scrit2.sh

-به سه طریق زیر می توان بررسی کرد که ایا پروسس crond در حال اجرا می باشد یا نه؟

ps -eaf|grep crond

service crond status

ll /var/run/crond.pid

-برای مانیتوینگ سرویس crontab می توان از دستور زیر استفاده کرد:

tail -f  /var/log/cron

– همانطور که در ابتدا بیان شد، در صورتی که کاربری jobای را تعریف کرده باشد، اطلاعات ان در مسیر /var/spool/cron قرار خواهد گرفت و همچنین برای تنظیم جاب، می توان از فایل/etc/crontab و یا فایلهای موجود در پوشه های زیر هم استفاده کرد.

/etc/cron.hourly/,

/etc/cron.daily/,

/etc/cron.weekly/,

/etc/cron.monthly/

همچنین پروسس crond، فایلهای موجود در زیر پوشه /etc/cron.d/ را هم مورد بررسی قرار می دهد و در صورت لزوم، انها را اجرا خواهد کرد.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد.