#oracle #oracle11gr2
#Oracle #oracle11gr2
Вопрос:
Недавно я научился использовать планировщик Oracle для асинхронного выполнения заданий.
Я пытаюсь создавать задания, которые выполняются только один раз, а затем автоматически удаляются.
Способ, которым я добился этого, — установить для атрибута MAX_RUNS задания значение 1, а для атрибута AUTO_DROP установить значение TRUE .
Все мои задания по умолчанию ОТКЛЮЧЕНЫ, поскольку я запускаю их только вручную.
Я заметил, что задания не удалялись, и в этом потоке Ask Tom объясняется, почему.
Таким образом, я должен сначала включить свои задания, прежде чем запускать их, если они должны быть удалены автоматически.
Однако, когда задание включено, оно немедленно планируется.
Мой вопрос:
Когда запланированное задание включено и, следовательно, немедленно запланировано, выполняется ли оно в отдельном сеансе?
Мне нужно, чтобы все задания планировались асинхронно, и поэтому я надеюсь добиться такого же поведения, как:
DBMS_SCHEDULER.RUN_JOB(V_JOB_NAME, FALSE);
FALSE указывает на асинхронное планирование задания в отдельном сеансе.
Я согласен с подходом включения задания и его немедленного планирования, если оно асинхронно в отдельном сеансе.
В качестве альтернативы, если бы был способ обеспечить, чтобы задание НЕ планировалось, когда оно включено, это тоже сработало бы.
В настоящее время я работаю с Oracle 11gR2
Ответ №1:
Если бы у меня была куча асинхронных одноразовых заданий, которые нужно было запускать, я бы серьезно подумал об использовании старого dbms_job
пакета для выполнения моего планирования, а не dbms_scheduler
. Тогда вы просто делаете что-то вроде этого
declare
l_jobno pls_integer;
begin
dbms_job.submit( l_jobno,
'<<what you want the job to do>>',
sysdate );
end;
/
Это приведет к открытию нового сеанса, как только вы зафиксируете submit
, который запускает любой указанный вами код. Оно будет запущено один раз, а затем удалено dba_jobs
.
В качестве альтернативы я бы попытался перестроить систему так, чтобы было фоновое задание «обработчик виджетов», которое выполняется каждые несколько минут, считывает таблицу, чтобы определить, какие виджеты необходимо обработать, и обрабатывает эти виджеты. Это, вероятно, имеет больше смысла, чем создавать отдельное задание для обработки каждого виджета.
dbms_scheduler
замечательно, когда вы хотите иметь более сложную обработку, когда одно задание зависит от другого, а задания запускаются на основе событий. Но старая школа dba_jobs
может быть действительно удобной, когда вам просто нужна очень легкая структура для очень простых заданий.
Комментарии:
1. Спасибо, Джастин, это имеет большой смысл. Мой вариант использования — это в первую очередь динамическое извлечение данных. Каждое запланированное задание просто вызывает программу с 2 аргументами, именем функции и идентификатором клиента. Задание выполняет функцию для извлечения данных и записывает данные в файл. Есть несколько других шагов, но это основная часть. Возможно, использование стандартных заданий — более простой подход. Я планирую усилить контроль над процессом, чтобы можно было перезапустить неудачные задания и т. Д. И я думаю, что это доступно только для запланированных заданий? Я действительно ценю вашу проницательность, еще раз спасибо!
2. @rcurrie — Я бы предпочел иметь таблицу с двумя столбцами, названными примерно так
customer_to_extract
, в которую ваш код записывает строку, а затем одно задание извлечения клиента, которое выполняется каждые n минут и обрабатывает все в этой таблице, чем запускать кучу автономных заданий. Это, как правило, значительно упрощает встроенное управление заданиями (т. Е. Попробуйте обработать строку дважды, если это не удается, запишите ее в отдельную таблицу проблемных извлечений, которые кто-то может отслеживать, легко написать отчет, который показывает извлечения, которые в данный момент находятся в очереди, И т. Д.)3. Это тоже отличный подход. Предыдущий процесс был полностью синхронным (более 240 выполнений функций на одного клиента), и я пытаюсь добиться лучшей производительности, запустив задания для клиента асинхронно. Каждая функция отвечает за один элемент данных, таким образом, если 5 клиентам требуется обработка, это будет 1200 выполняемых заданий. Если одно задание для клиента завершается неудачно, я хотел бы иметь возможность повторно запустить только это одно задание, а не все. Надеюсь, это имеет смысл.
4. @rcurrie — Я бы определенно не хотел, чтобы выполнялось 1200 отдельных заданий. Я бы предпочел иметь одно задание, которое выполняло извлечение данных (возможно, несколько из них, если вам нужно больше потоков для поддержания), которое знало, как пометить строку в
customer_to_extract
таблице как неудачную. Гораздо проще запросить это, исправить все, что не удается, а затем пометить строку, чтобы повторить попытку.5. Еще раз спасибо за понимание, я обязательно пересмотрю процесс. Мне трудно понять, как добиться более высокой пропускной способности при меньшем количестве выполняемых заданий. Если задания вызывают функции для выполнения запросов и записи данных, если за это отвечает только 1 задание, как можно одновременно выполнять множество вызовов функций?
Ответ №2:
Я обнаружил, что, установив START_DATE нового задания на будущую дату, а REPEAT_INTERVAL на что-то вроде ‘FREQ = YEARLY’, задание не будет выполняться сразу после его включения.
Хотя это и не идеально, это позволит удалить задание при запуске вручную с помощью команды DBMS_SCEHDULER.RUN_JOB(V_JOB_NAME, FALSE); .
Однако это означает, что выполнение задания запланировано на какой-то момент в будущем. Так что просто не забудьте запустить его вручную. В моем случае это нормально, поскольку все происходит за один вызов, но хорошо вызывать.