על dbms_scheduler - תיזמונים במסד נתונים אורקל - ilDBA Portal

על dbms_scheduler – תיזמונים במסד נתונים אורקל

08/05/2012 | פורסם על ידי

הרבה DBA- ים נרתעים מלהשתמש בכלי DBMS_SCHEDULER בגלל שהוא נראה מורכב יותר מ- DBMS_JOB: יש יותר הגדרות, יש הרבה תלויות, יותר Data Dictionary Views.
אך ה- DBMS_SCHEDULER יכול להיות פשוט באותה המידה כמו DBMS_JOB על אף שיש לו יכולות יותר מתקדמות.
חשוב להבהיר במאמר זה האובייקט JOB מתייחס ל- DBMS_SCHEDULER, אין להתבלבל בינו לבין ה- DBMS_JOB.
ב- DBMS_SCHEDULER האובייקט המרכזי נקרא JOB, ה- JOB הכי פשוט מורכב משני פרמטרים:

  1. מה להריץ ? (כגון סקריפט PLSQL, פרוצדורה קיימת או אפילו קובץ הרצה שיושב על המערכת הפעלה)
  2. מתי להריץ ? (כגון מתי להתחיל, באיזה תדירות ויעד אחרון אם נדרש )

נתחיל בדוגמא פשוטה אנחנו נבצע יצירה של JOB בעזרת פקודה אחת בלבד:

begin
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'UPDATE_ALL_SALARIES',
job_type => 'STORED_PROCEDURE',
job_action => 'SOME_UPDATE_PROCEDURE',
number_of_arguments => 0,
start_date => to_date('07-JAN-12 08:30','DD-MON-YY HH24:MI'),
repeat_interval => 'freq=daily; byminute=0; bysecond=0;',
end_date => null,
enabled => TRUE,
comments => 'Hello World! This is my first scheduler job');
END;
/

ה- JOB בדוגמה הנ"ל בשם UPDATE_ALL_SALARIES מוכן לעבודה, JOB זה מורכב מפרמטרים המציינים מה להריץ והם job_type , job_action number_of_arguments וגם מכיל פרמטרים המציינים מתי להריץ והם start_date, repeat_interval, end_date.
לפי פרמטרים אלה ה- Job מריץ פרוצדורה שהכנתי מראש בשם SOME_UPDATE_PROCEDURE, והוא מריץ אותה מדי יום החל משעה 8:30.
לצפייה בהגדרות של ה- JOB:

select JOB_NAME,JOB_TYPE,JOB_ACTION,START_DATE,REPEAT_INTERVAL,NEXT_RUN_DATE
from dba_scheduler_jobs
where JOB_NAME='UPDATE_ALL_SALARIES';

במצבים יותר מורכבים, בהם יש לי תשתית של ג'ובים רבים בעלי תלויות וחלקם מעמיסים יותר או פחות אני ארצה תשתית יותר מתוחכמת.
כאן נכנסים אובייקטים נוספים:
Program – קטע הקוד שמורץ
Schedule – מתי הוא מורץ
כל JOB יכול להכיל את שתי ההגדרות האלה אצלו:

או להכיל הפניה לאובייקטים Program ו Scheduler נפרדים.

הצורך ב- PROGRAM:
מה קורה במצב שבו הפרוצדורה SOME_UPDATE_PROCEDURE אותה ציינתי בדוגמה הקודמת צריכה לשמש אותי ב- JOB נוסף.
לדוגמה מצב שבו יש לי את ה- JOB UPDATE_ALL_SALARIES אשר רץ קבוע וגם יצרתי JOB נוסף הנקרא MANUAL_UPDATE_ALL_SALARIES_BY_DAVID אשר מורץ ידנית על ידי משתמש.
בשני ה- JOB- ים אני ארצה שתרוץ אותה הפרוצדורה SOME_UPDATE_PROCEDURE,
לכן אצל שניהם בפרמטר job_action מופיעה שם הפרוצדורה SOME_UPDATE_PROCEDURE.
לעומת זאת אם למשל אני ארצה להחליף בפרוצדורה אחרת אני אצטרך לגשת לכל אחד מה- JOB- ים ולשנות אצלם את הפרמטר job_action לשם של הפרוצדורה החדשה.
לחלופין יש לי אפשרות ליצור אובייקט חדש מסוג PROGRAM אשר נקרא לו UPDATE_SALARIES_PROGRAM, הוא מכיל את כל ההגדרות של הפרוצדורה SOME_UPDATE_PROCEDURE ושני ה- JOB- ים מכילים פרמטר המשמש בתור קישור ל- UPDATE_SALARIES_PROGRAM במקום ישירות לפרוצדורה עצמה,
וכך במקרה ואני ארצה לעשות את השינוי הנ"ל כל מה שאני צריך לעשות זה לשנות את הפרמטר בתוך האובייקט SOME_UPDATE_PROCEDURE מסוג PROGRAM ושני ה- JOB- ים שמקושרים ל- PROGRAM הנ"ל יפעילו את הפרוצדורה שמופיעה ב- PROGRAM.
אז איך מגדירים Program:
קודם כל צריך ליצור אובייקט חדש מסוג Program:

begin
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'UPDATE_SALARIES_PROGRAM',
program_type => 'STORED_PROCEDURE',
program_action => 'SOME_UPDATE_PROCEDURE',
enabled => TRUE,
comments => 'program for SOME_UPDATE_PROCEDURE procedure');
END;
/
ומתוך התזמון המקורי נדרש להוציא את הפרמטרים job_type , job_action ו- number_of_arguments , במקומם נציין את הפרמטר program_nameאשר מתייחס ל- Program החדש.

BEGIN
DBMS_SCHEDULER.drop_job(
 job_name => 'UPDATE_ALL_SALARIES');
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'UPDATE_ALL_SALARIES',
 program_name => 'UPDATE_SALARIES_PROGRAM',
 start_date => to_date('07-JAN-12 08:30','DD-MON-YY HH24:MI'),
 repeat_interval => 'freq=daily; byminute=0; bysecond=0;', end_date => null,
 enabled => TRUE,
 comments => 'Hello World!');
 END;
/

או לחלופין נשנה את ההגדרות הנדרשות בלבד:

BEGIN DBMS_SCHEDULER.DISABLE
( name => 'UPDATE_ALL_SALARIES'); 

DBMS_SCHEDULER.SET_ATTRIBUTE_NULL
( name => 'UPDATE_ALL_SALARIES',
attribute => 'job_action'); 

DBMS_SCHEDULER.SET_ATTRIBUTE_NULL
( name => 'UPDATE_ALL_SALARIES',
attribute => 'job_type' ); 

DBMS_SCHEDULER.SET_ATTRIBUTE_NULL
( name => 'UPDATE_ALL_SALARIES',
attribute => 'NUMBER_OF_ARGUMENTS'); 

DBMS_SCHEDULER.SET_ATTRIBUTE
 ( name => 'UPDATE_ALL_SALARIES',
 attribute => 'program_name', value => 'UPDATE_SALARIES_PROGRAM');

 DBMS_SCHEDULER.ENABLE
( name => 'UPDATE_ALL_SALARIES');

 END;
/

הצורך ב- SCHEDULER:
מה קורה במצב בו נרצה ליצור הגדרה של זמן ריצה שיהיה אחיד למספר JOB- ים שונים, לדוגמה נסתכל על אותו ה- JOB בשם UPDATE_ALL_SALARIES אשר רץ מדי יום החל משעה 8:30 בבוקר.
בנוסף אליו אני ארצה ליצור JOB נוסף בשם DELETE_OLD_WORKERS אשר מריץ פרוצדורה אחרת אבל אני ארצה שהוא ירוץ בזמנים זהים לשעות ריצה של ה- JOB הראשון לפי מה שמוגדר בפרמטר start_date אצל כל אחד מה- JOB- ים.
במקרה ויום מסוים אני אחליט שאני רוצה ששני ה- JOB- ים הנ"ל יתחילו לרוץ בשעה 9:00 בבוקר מדי יום במקום 8:30 אני אצטרך לשנות פרטנית את הפרמטר start_date אצל כל אחד מה- JOB- ים.
לחלופין יש לי את האפשרות ליצור אובייקט חדש מסוג SCHEDULER אשר נקרא לו UPDATE_ALL_SALARIES_SCHED, הוא יכיל בו את ההגדרות הנוגעות לזמני תזמון ה- JOB.
שני ה- JOB- ים יכילו קישור ל- SCHEDULE החדש תחת הפרמטר schedule_name, ככה ששינוי ב- UPDATE_ALL_SALARIES_SCHED ישפיע באופן גורף על כל ה- JOB- ים שיש בהם קישור אליו.
יצירת אובייקט מסוג Scheduler מתבצע כך:

BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'UPDATE_ALL_SALARIES_SCHED',
start_date => to_date('07-JAN-12 08:30','DD-MON-YY HH24:MI'),
repeat_interval => 'freq=daily; byminute=0; bysecond=0;',
end_date => null,
comments => 'Schedule for running SOME_UPDATE_PROCEDURE procedure' );
END;
/
מתוך הג'וב המקורי נדרש להוציא את הפרמטרים start_date, repeat_interval, end_date ובמקום לציין את שם ה- scheduler תחת פרמטר schedule_name:

BEGIN
DBMS_SCHEDULER.DROP_JOB(
job_name => 'UPDATE_ALL_SALARIES');
END;
/

BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'UPDATE_SALARIES_PROGRAM',
program_name => 'SOME_UPDATE_PROCEDURE',
schedule_name => 'UPDATE_ALL_SALARIES_SCHED',
enabled => TRUE,
comments => 'Hello World!');
END;
/

או לחלופין נשנה את ההגדרות הנדרשות בלבד:

BEGIN
DBMS_SCHEDULER.DISABLE (
name => 'UPDATE_ALL_SALARIES');
DBMS_SCHEDULER.SET_ATTRIBUTE_NULL (
name => 'UPDATE_ALL_SALARIES',
attribute => 'start_date');
DBMS_SCHEDULER.SET_ATTRIBUTE_NULL (
name => 'UPDATE_ALL_SALARIES',
attribute => 'repeat_interval' );
DBMS_SCHEDULER.SET_ATTRIBUTE_NULL (
name => 'UPDATE_ALL_SALARIES',
attribute => 'end_date');
DBMS_SCHEDULER.SET_ATTRIBUTE (
name => 'UPDATE_ALL_SALARIES',
attribute => 'schedule_name',
value => 'UPDATE_ALL_SALARIES_SCHED');
DBMS_SCHEDULER.ENABLE (
name => 'UPDATE_ALL_SALARIES');
END;
/
לצפייה בהגדרות של התזמון המעודכן:

select JOB_NAME,PROGRAM_NAME,SCHEDULE_NAME
from DBA_SCHEDULER_JOBS
where JOB_NAME='UPDATE_ALL_SALARIES';
JOB_NAME PROGRAM_NAME SCHEDULE_NAME
-------------------- ------------------------------ ------------------------------
UPDATE_ALL_SALARIES UPDATE_SALARIES_PROGRAM UPDATE_ALL_SALARIES_SCHED
לצפייה בהגדרות של ה- Program:

select PROGRAM_TYPE,PROGRAM_ACTION
from DBA_SCHEDULER_PROGRAMS
where PROGRAM_NAME='UPDATE_SALARIES_PROGRAM';
PROGRAM_TYPE PROGRAM_ACTION
------------------------- -------------------------
STORED_PROCEDURE SOME_UPDATE_PROCEDURE
לצפייה בהגדרות של ה- Scheduler:

select START_DATE,REPEAT_INTERVAL
from DBA_SCHEDULER_SCHEDULES
where SCHEDULE_NAME='UPDATE_ALL_SALARIES_SCHED';
START_DATE REPEAT_INTERVAL
--------------- -----------------------------------
07-JAN-12 08:30 freq=daily; byminute=0; bysecond=0;

סיכום:
בחלק זה :

  1. סקרנו כיצד מתחילים לעבוד עם ה- DBMS_SCHEDULER.
  2. ראינו שהוא יכול להיות פשוט באותה המידה כמו DBMS_JOB.
  3. ראינו כיצד שימוש באובייקטים PROGRAM ו- SCHEDULER יכולים להקל על עבודה עם ריבוי JOB- ים.

בחלק 2 נסקור את האובייקטים:

JOB Class
Job Chaining

קישורים:

  1. Oracle Documentation- DBMS_SCHEDULER
  2. Calendaring Syntax (השפה לפיה מגדירים את זמני הריצה)
  3. פרמטרים של DBMS_SCHEDULER.CREATE_JOB
  4. פרמטרים של DBMS_SCHEDULER.CREATE_PROGRAM
  5. פרמטרים של DBMS_SCHEDULER.CREATE_SCHEDULE

בהצלחה ונתראה בחלק 2 🙂

תודה,

דימיטרי אברוטין,
OCP (Oracle Certified Professional)

The following two tabs change content below.

דימיטרי אברוטין

Latest posts by דימיטרי אברוטין (see all)

3 תגובות ל- “על dbms_scheduler – תיזמונים במסד נתונים אורקל”

commenter

דימיטרי יא תותח!
אתה לא מבין איך זה עזר לי.
יישר כוח.

commenter

יפה מאוד! הסברים תמציתיים וברורים והדוגמאות מפורטות להפליא.

[…] בפרק הקודם סקרנו את ה- DBMS_SCHEDULER, כיצד יוצרים ג’וב, כיצד משייכים אליו Program ו- Scheduler. תזכורת לחלק הראשון : על dbms_scheduler – תיזמונים במסד נתונים אורקל […]

השאר תגובה:

שם (חובה):
אימייל (לא יפורסם) (חובה):
תגובה (חובה):

*



מאמרים קשורים

Baruch Osoveskiy

תיקון מהיר לדיסק איטי

  רציתי לשתף אתכם בתקלה שהיתה לי ובפיתרון שלה. לפעמים אני רוצה לבדוק גירסה חדשה או יכולת שלא מתועדת מספיק בספרות, ואז אני מסתפק בהקמה של סביבה ווירטואלית בדרך כלל על חומרה זולה (לפעמים זולה [...]
OS

OS Background operations

אורי לרנר בטיפ קצר ושימושי על העברת פעולות לרקע במערכת [...]
רשימת

רשימת הפיצ'רים החדשים של אורקל 12.1

אורקל פרסמו את הספרות הרשמית לגרסה 12.1 שיצאה לאחרונה וזמינה להורדה. בין שאר הספרים (החשובים כל אחד שלעצמו), פורסם הספר המסקרן ביותר בעיני – Oracle Database 12c Release 1 (12.1) New Features. זהו ספר שראוי שכל DBA [...]
גרסת

גרסת אורקל 12c זמינה להורדה

בשעה טובה ולאחר המתנה סופר ארוכה, גרסת אורקל 12c (גרסה 12.1) זמינה סוף סוף להורדה רשמית מהאתר של אורקל. הגרסה החדשה מנסה לתת פתרונות לעולם ה"ענן" – ומוסיפה פיצ'רים חדשים שבאים לתת מענה בדיוק [...]
Website Security Test