Программирование >>  Oracle 

1 ... 389 390 391 [ 392 ] 393 394 395 ... 469


Пакет 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 часа ночи выполнять анализ всех таблиц в определенной схеме. Для этого можно использовать следующую хранимую процедуру:



1 ... 389 390 391 [ 392 ] 393 394 395 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика