Когда включено запланированное задание Oracle, выполняется ли оно в отдельном сеансе?

#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); .

Однако это означает, что выполнение задания запланировано на какой-то момент в будущем. Так что просто не забудьте запустить его вручную. В моем случае это нормально, поскольку все происходит за один вызов, но хорошо вызывать.