|
Программирование >> Oracle
Пакет DBMS JOB 1599 Похоже, она выполняется примерно восемь десятых секунды, в лучшем случае. Для меня это слишком долго. Можно ускорить выполнение, точнее, создать видимость этого. Я использую задания для видимости ускорения работы и получаю при этом преимущества отправки сообщений в рамках транзакции. Начнем с создания таблицы для хранения сообщений и процедуры, которая сможет посылать находящиеся в ней сообщения. Эта процедура и будет выполняться как фоновое задание. Вопрос в том, зачем для хранения сообщений используется таблица? Почему просто не передать текст сообщения как параметр задания? Причина в использовании связываемых переменных и разделяемого пула. Поскольку все задания будут создаваться с параметром WHAT, a сервер будет просто выполнять эту строку, надо помнить, что значение параметра WHAT окажется в разделяемом пуле. Можно посылать задания и так: dbms job.submit(x, send mail(someone@there.com, someone0there.com , Привет!);); но в результате в разделяемом пуле окажутся сотни тысяч уникальных операторов, что отрицательно скажется на производительности сервера. Поскольку предполагается рассылка большого количества сообщений (больше одного - уже много, и использовать связываемые переменные при этом обязательно), надо иметь возможность посылать задания вида: dbms job.submit(x, background send mail(константа);); Оказывается, этого очень легко добиться. Достаточно создать таблицу с полями для каждого передаваемого параметра при отправке задания на выполнение (в данном случае, отправитель, адресат и само сообщение) и первичным ключом. Например: tkyte@TKYTE816> create table send mail data(id number primary key, 2 sender varchar2(2 55), 3 recipient varchar2(2 55), 4 message varchar2(40 00), 5 senton date default NULL) ; Table created. Я добавил в таблицу первичный ключ - столбец ID, и дату отправки сообщения в столбце senton. Мы будем использовать эту таблицу не только для организации очереди исходящих сообщений, но и как постоянный журнал, в котором будут регистрироваться все отправленные сообщения (пригодится, поверьте мне, когда кто-то скажет: А меня не предупреждали... ). Осталось только придумать, как генерировать значение ключа для таблицы и передавать его фоновому процессу в виде строковой константы. К счастью, пакет DBMS JOB содержит все необходимое для решения этой проблемы. При отправке задания на выполнение пакет автоматически создает для него уникальный идентификатор и возвращает его вызывающему. Поскольку блок кода, в который помещается переданное значение параметра WHAT, содержит идентификатор задания, мы можем его передавать. Процедура FAST SEND MAIL будет выглядеть так: tkyte@TKYTE816> create or replace 2 PROGEDURE fast send mail (p sender IN VARGHAR2, 3 p recipient IN VARGHAR2, 1600 Приложение А 10 11 12 13 14 p message IN VARCHAR2) l job number; begin dbms job.submit(l job, background send mail(JOB);); insert into send mail data (id, sender, recipient, message) values (l job, p sender, p recipient, p message); end; Procedure created. Эта процедура будет посглать на выполнение задание BACKGROUND SEND MAIL и передавать ему параметр JOB. Если обратиться к описанию параметра WHAT, вы увидите, что соответствующий блок кода включает три локальных переменных, к которым можно обращаться, - мы и передаем процедуре одну из них. Сразу после этого мы вставляем сообщение в таблицу очереди для последующей отправки. Итак, пакет DBMS JOB создает первичный ключ, а затем мы вставляем этот первичный ключ и соответствующие данные в таблицу. Вот и все. Теперь необходимо создать несложную процедуру BACKGROUND SEND MAIL: tkyte@TKYTE816> create or replace 10 11 12 13 procedure as background send mail(p job in number) begin l rec send mail data%rowtype; select * into l rec from send mail data where id = p job; send mail(l rec.sender, l rec.recipient, l rec.message); update send mail data set senton = sysdate where id = p job; end; Procedure created. Она читает сохраненные данные, вызывает медленно работающую процедуру SEND MAIL, а затем изменяет соответствующую запись, отражая в ней факт отправки сообщения по электронной почте. Теперь можно выполнить процедуру FAST SEND MAIL и определить, насколько быстро она выполняется: tkyte@TKYTE816> declare l start number dbms utility.get time; begin Привет!); fast send mai1(panda@panda.com, snake@snake.com, dbms output.put line (round((dbms utility.get time-l start)/100, seconds); end; Пакет DBMS JOB 1601 10 / .03 seconds PL/SQL procedure successfully completed. tkyte@TKYTE816> / .02 seconds PL/SQL procedure successfully completed. С точки зрения пользователя процедура FAST SEND MAIL работает в 26-40 раз быстрее, чем исходная. На самом же деле она работает не быстрее, но создает видимость быстрого выполнения (именно это и имеет значение). Фактическая отправка сообщения будет выполнена в фоновом режиме после фиксации транзакции. Об этом важно помнить. При выполнении этого примера не забудьте выполнить COMMIT, иначе сообщение никогда не будет послано. Задание не будет доступно в очереди для соответствующих процессов, пока транзакция не будет зафиксирована (в сеансе можно будет увидеть задание в представлении USER JOBS, но процессы обработки очередей его не увидят, пока не будет зафиксирована транзакция). Не считайте это ограничением. На самом деле это полезное свойство, с помощью которого мы только что включили отправку сообщений по электронной почте в транзакцию. Если откатить транзакцию, сообщение не будет послано. После фиксации транзакции оно будет отправлено. Текущие задания Еще одно стандартное применение пакета DBMS JOB - для организации периодического выполнения заданий в базе данных. Как уже упоминалось, многие пользователи пытаются применять для выполнения заданий в базе данных утилиты ОС cron или at, но сталкиваются при этом с проблемами защиты пароля и т.п. Я всегда предлагаю использовать очереди заданий. Они не только избавляют от необходимости хранения регистрационной информации, но и гарантируют выполнение заданий только в случае работоспособности и доступности сервера базы данных. В случае сбоя сервер будет повторно пытаться выполнить задание. Например, если при первой попытке выполнения задания удаленная база данных недоступна, задание возвращается в очередь и делается ,попытка выполнить его снова. Сервер делает это 16 раз, с каждым разом немного увеличивая время ожидания, прежде чем пометит задание как разрушенное . Подробнее об этом мы поговорим в подразделе Контроль заданий и поиск ошибок . Утилиты cron и at автоматически этого не сделают. Кроме того, поскольку задания выполняются в базе данных, с помощью запросов можно определить их статус: когда последний раз выполнялось задание и выполнялось ли вообще, и т.п. Вся информация находится в одном месте. Другие средства сервера Oracle, такие как репликация и материализованные представления, неявно используют очереди заданий при реализации своих функциональных возможностей. Изменения моментальных снимков и обновления материализованных представлений выполняются с помощью заданий, вызывающих соответствующие хранимые процедуры. Предположим, необходимо ежесуточно в 3 часа ночи выполнять анализ всех таблиц в определенной схеме. Для этого можно использовать следующую хранимую процедуру:
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |