Использование Oracle 11,2Как ждать DBMS_SCHEDULER рабочих мест, чтобы закончить
Привет,
Вот что я хочу сделать: Я планирования заданий с использованием DBMS_SCHEDULER. Количество заданий для расписания не фиксировано, и одновременно должно выполняться максимум 4 задания. Процедура планирования заданий должна ждать завершения всех заданий. Если одно задание не выполняется, процедура «расписание» также должна завершиться неудачей, и все оставшиеся запланированные задания должны быть удалены из планировщика.
В настоящее время мне пришлось спать и опросить таблицу user_scheduler_jobs в цикле.
Я новичок в PL/SQL и достаточно неопытный поэтому, пожалуйста, не быть слишком жестким на меня;)
Вот мой код до сих пор.
Первый фрагмент кода для планирования работ:
BEGIN
FOR r IN (SELECT p_values FROM some_table WHERE flag = 0)
LOOP
-- count running jobs
SELECT count(*) INTO v_cnt
FROM user_scheduler_jobs
WHERE job_name LIKE 'something%';
/*
If max number of parallel jobs is reached, then wait before starting a new one.
*/
WHILE v_cnt >= l_max_parallel_jobs
LOOP
dbms_lock.sleep(10);
SELECT count(*) INTO v_cnt
FROM user_scheduler_jobs
WHERE job_name LIKE 'something%' AND state = 'RUNNING';
SELECT count(*) INTO v_cnt_failures
FROM user_scheduler_jobs
WHERE job_name LIKE 'something%' AND state = 'FAILED' OR state = 'BROKEN';
IF v_cnt_failures > 0 THEN RAISE some_exception; END IF;
END LOOP;
-- Start a new Job
v_job_name := 'something_someting_' || p_values;
v_job_action := 'begin user.some_procedure(''' || r.p_values || '''); end;';
dbms_scheduler.create_job(job_name => v_job_name,
job_type => 'PLSQL_BLOCK',
job_action => v_job_action,
comments => 'Some comment ' || v_job_name,
enabled => FALSE,
auto_drop => FALSE);
dbms_scheduler.set_attribute(NAME => v_job_name,
ATTRIBUTE => 'max_failures',
VALUE => '1');
dbms_scheduler.set_attribute(NAME => v_job_name,
ATTRIBUTE => 'max_runs',
VALUE => '1');
dbms_scheduler.enable(v_job_name);
v_job_count := v_job_count + 1;
-- array for all jobs
v_jobs_aat(v_job_count) := v_job_name;
END LOOP;
-- ... Wait till all jobs have finisched.
check_queue_completion(v_jobs_aat); -- see procedure below
END;
Процедура для ожидания до последних четырех рабочих мест finisched:
PROCEDURE check_queue_completion(p_jobs_aat IN OUT t_jobs_aat) AS
v_state user_scheduler_jobs.state%TYPE;
v_index PLS_INTEGER;
v_done BOOLEAN := TRUE;
-- Exceptions
e_job_failure EXCEPTION;
BEGIN
WHILE v_done
LOOP
v_done := FALSE;
FOR i IN p_jobs_aat.first..p_jobs_aat.last
LOOP
SELECT state INTO v_state FROM user_scheduler_jobs WHERE job_name = p_jobs_aat(i);
--dbms_output.put_line('Status: ' || v_state);
CASE
WHEN v_state = 'SUCCEEDED' OR v_state = 'COMPLETED' THEN
dbms_output.put_line(p_jobs_aat(i) || ' SUCCEEDED');
dbms_scheduler.drop_job(job_name => p_jobs_aat(i), force => TRUE);
p_jobs_aat.delete(i);
WHEN v_state = 'FAILED' OR v_state = 'BROKEN' THEN
--Exception auslösen
dbms_output.put_line(p_jobs_aat(i) || ' FAILED');
RAISE e_job_failure;
WHEN v_state = 'RUNNING' OR v_state = 'RETRY SCHEDULED' THEN
NULL;
dbms_output.put_line(p_jobs_aat(i) || ' RUNNING or RETRY SCHEDULED');
v_done := TRUE;
/*DISABLED, SCHEDULED, REMOTE, CHAIN_STALLED*/
ELSE
dbms_output.put_line(p_jobs_aat(i) || ' ELSE');
dbms_scheduler.drop_job(job_name => p_jobs_aat(i), force => TRUE);
p_jobs_aat.delete(i);
END CASE;
END LOOP;
hifa.gen_sleep(30);
END LOOP;
IF p_jobs_aat.count > 0 THEN delete_jobs_in_queue(p_jobs_aat); END IF;
EXCEPTION WHEN e_job_failure THEN
delete_jobs_in_queue(p_jobs_aat);
RAISE_APPLICATION_ERROR(-20500, 'some error message');
END check_queue_completion;
Это делает трюк, но это, кажется, как-то ужасный хак.
Не существует лучшего способа:
- Подождите, пока все рабочие не закончили.
- Просто запустите сразу четыре задания и запустите новый, как только закончится одно из рабочих заданий.
- Выбросить исключение, если одно задание не работает или не работает.
Я бы использовал существующие функции, доступные для dbms_scheduler. Для # 1, посмотрели ли вы на цепи (http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sched.htm#CHDCJFCI)? # 2 Вы посмотрели на изменение job_queue_processes? –
Что сказал Патрик - ознакомьтесь с механизмом цепей планировщика – thatjeffsmith
Спасибо за ваши комментарии. К сожалению, я не могу использовать job_queue_processes, потому что я на общей БД, и они не позволяли мне использовать «alter system .....». Мое понимание цепочки работы заключается в том, что она позволяет мне определить что-то вроде «делать первые 4 задания» -> «Следующие 4 задания» -> «Следующие 4 задания» и т. Д., Но не нравится «начать 4 задания и как только как один закончен, начните следующий ». Моя цель заключается в том, что в любой момент времени выполняются четыре задания. Я также подумал о том, чтобы использовать DBMS_ALERT для ожидания Джобса, что, по крайней мере, немного снизило бы накладные расходы на кодирование. –