On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru








 

Как раздать пользователям приоритеты

Не секрет, что уже достаточно давно фирма Oracle испытывает в области средств моделирования данных нечто вроде кризиса жанра (впрочем, не выделяясь в этом среди своих конкурентов). Взять хотя бы ее искания в этом направлении в продолжении последних лет, а заодно и результаты этих исканий. Замечая на протяжении длительного времени лишь ближние рыночные ориентиры, фирма сама подвела себя к нелегкой ситуации - перспективы в этой области неясны... В области же эксплуатационной то же самое поведение Oracle оказалось не столь пагубным, и наверстывание многого из того, что можно было бы сделать давным-давно, пока возможно, и реально продолжается с каждой последней версией. Словом - здесь лучше поздно, чем никогда, хотя в других областях может статься лучше никогда, чем поздно.

Первое, например, касается очень простой задачи: как научиться выдавать пользователям, работающим с базой данных, приоритеты на процессорное время Oracle? Чтобы какой-нибудь из пользователей, запуская сложные запросы, не мешал работе остальных?

Кое-что по части администрирования использования ресурсов системы известно и применяется на практике давно. Имеются в виду профили, которые можно приписывать пользователям, и которые позволяют ограничивать процессорное время и обращения к диску в рамках отдельных запросов или всего сеанса. Ну а если мы не хотим вводить абсолютные ограничения, а хотим ввести приоритеты?

Такая возможность появилась в версии 8.1. Многие, наверное, обратили внимание на отсутствующие в более ранних версиях термины resource manager или consumer group, появившиеся формах OEM и в документации, но разобраться в них все было недосуг. Между тем, понять, о чем идет речь, вовсе нетрудно, что мы сейчас вместе и сделаем.

Постановка задачи

Допустим, мы хотим разбить пользователей на три группы:

  • администраторов, которым хотим гарантировать не менее 70% процессорного времени
  • прикладников, которым хотим гарантировать не менее 20% процессорного времени
  • всех остальных, которым достаточно будет иметь не менее 10% процессорного времени.
Из этого, конечно, не следует, что, к примеру, прикладники будут всегда довольствоваться только 20-ю процентами. Если кроме них на машине - никого, то все 100% своего времени Oracle отдаст им. (Более сложные ситуации оставим пока в покое).

Пусть, в свою очередь, прикладники делятся на

  • операционистов, которым нужно гарантировать не менее 90% от времени прикладников и
  • аналитиков, требующих не менее 10% времени, выделенного прикладникам, для выполнения-таки своих задач по подготовке отчетов.
То есть, аналитики будут запускать свои задания практически в фоновом режиме и мешать работе операционистов почти не будут; время для них - не столь уж критично.

Что для такой организации труда нужно сделать?

Диспетчер ресурсов

:Точнее было бы перевести 'диспетчер ресурса' (resource manager), а еще точнее - 'диспетчер ресурса процессорного времени', поскольку сейчас именно и только об этом ресурсе идет речь. В него входят:

  • два системных (встроенных, создаваемых автоматически при создании БД) пакета: DBMS_RESOURCE_MANAGER и DBMS_RESOURCE_MANAGER_PRIVS с определенными, с вовсе не очевидными правилами использования (см. дальше),
  • несколько новых ролей
  • серия новых виртуальных таблиц в словаре-справочнике (а также некоторые добавления в прежние таблицы).
Вот основные понятия, с которыми имеет дело диспетчер ресурсов.

Группа потребителей (consumer group) - группа пользователей Oracle, с которой связывается та или иная гарантированная доля процессорного времени

Ресурсный план (resource plan) - именованная схема распределения долей процессорного времени

Рабочая область (pending area) - временная область, в которой, по технологии диспетчера ресурсов, собирается и проверяется на корректность ресурсный план, прежде чем его можно будет употреблять.

Подготовительные действия

Поначалу нужно выбрать пользователя-администратора, который будет создавать группы потребителей и ресурсные планы в рабочей области, расположенной у себя. Если этот пользователь по вашему выбору - не SYS и не SYSTEM (а к такому решению могут располагать организационные моменты), ему нужно дать право:

EXEC DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE( -

'SCOTT', 'ADMINISTER_RESOURCE_MANAGER', FALSE);

EXEC DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE( -

Технология диспетчера организована так, что привилегия ADMINISTER RESOURCE MANAGER выдается и отбирается не обычными командами GRANT и REVOKE, а процедурно, на манер, как сделано выше.

Теперь администратор диспетчера ресурсов должен создать рабочую область, где будет создаваться и готовиться план (см. предложения ниже):

EXEC DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();

Создаем план

От имени администратора диспетчера выдаем:

BEGIN

DBMS_RESOURCE_MANAGER.CREATE_PLAN(

'DAILY',

'The plan for normal daily operations');

DBMS_RESOURCE_MANAGER.CREATE_PLAN(

'APPLICATIONS',

'The subplan for applications');

END;

/

Мы создали два плана: основной ('DAILY') и один подчиненный ('APPLICATIONS'). Подчиненных может быть и больше, а может и вовсе не быть.

Создаем потребительские группы

От имени администратора выдаем:

BEGIN

DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(

'Database support',

'Database administration group');

DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(

'Operators',

'Customer management department');

DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(

'Analytics',

'System analysis group');

END;

/

Тут созданы три потребительские группы; из кода полностью ясно, как.

Кроме указанных, системой автоматически создается группа OTHER_GROUPS, куда попадают все пользователи, не включенные в эти группы.

Привязываем потребительские группы к плану

Из созданной выше структуры для плана строим полноценный план, приписывая этой структуре потребительские группы:

BEGIN

DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(

'DAILY ',

'Database support',

'Resource allocation for DBA group',

cpu_p1 => 70);

DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(

'DAILY ',

'APPLICATIONS',

'Resource allocation for application users',

cpu_p1 => 20);

DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(

'DAILY ',

'OTHER_GROUPS',

'For users not included to any group.',

cpu_p1 => 10);

END;

/

То же самое продолжаем для подчиненного плана:

BEGIN

DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(

'APPLICATIONS',

'Operators',

'For general operators',

cpu_p1 => 90);

DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(

'APPLICATIONS',

'Analytics',

'For the report writers',

cpu_p1 => 10);

END;

/

Итак, мы сформировали полный план в виде дерева с двумя уровнями. 'Листья' дерева - потребительские группы, а промежуточное звено - подчиненный план.

Передаем план в распоряжение системы

Теперь мы готовы к тому, чтобы проверить сформированный план на правильность: может быть, в нем присутствуют циклы, отсутствующие группы или другие некорректности? Выдадим:

EXEC DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();

Если все в порядке (а в нашем случае должно быть так), план DAILY можно 'сдавать в эксплуатацию':

EXEC DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();

Включаем в потребительские группы пользователей Oracle

План готов к работе, но наши потребительские группы созданы только номинально: в них нет пользователей. По технологии, предлагаемой Oracle, пользователь системы может быть подключен к какой-нибудь группе только при наличии у него права SWITCH CONSUMER GROUP. Выдается оно также с помощью API, то есть одного из наших двух пакетов:

BEGIN

DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(

'SYSTEM', 'Database support', FALSE);

DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(

'SCOTT', 'Operators', FALSE);

DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(

'ADAMS', 'Analytics', FALSE);

END;

/

И только теперь пользователей (из списка выше, коль скоро у них появилось на то право) можно фактически включать в группы:

BEGIN

DBMS_RESOURCE_MANAGER.SET_INITIAL_CONSUMER_GROUP(

'SYSTEM', 'Database support');

DBMS_RESOURCE_MANAGER.SET_INITIAL_CONSUMER_GROUP(

'SCOTT', 'Operators');

DBMS_RESOURCE_MANAGER.SET_INITIAL_CONSUMER_GROUP(

'ADAMS', 'Analytics');

END;

/

План начинает действовать

Если теперь ADAMS запустит большой, но 'несмертельный' запрос (например, на удвоение безындексной таблицы из полмиллиона записей), никто больше с Oracle не работает, и мы от имени SCOTT попросим выдать EMP, то увидим, что в нашем распоряжении отнюдь не 90% ресурсов. Чтобы план DAILY заработал, требуется поставить последнюю точку:

ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = DAILY;

Думаю, что радость пользователя SCOTT от времени реакции системы после этого с лихвой окупит его страдания от набирания всех [PL/]SQL-операторов, указанных выше !

Точку можно поставить и по-другому. Указание RESOURCE_MANAGER_PLAN = DAILY можно включить в файл INIT.ORA, и тогда план будет автоматически включаться в действие при старте СУБД, а не быть активным только до первого останова.

Усовершенствования

Описанную выше схему организации приоритетного доступа к процессорному времени можно развивать дальше. Вот некоторое, что приходит в голову сразу:

  • Естественно, что дерево плана может быть более 'высоким', чем двухуровневое, или быть одноуровневым, или более широким. Есть, правда, ограничение на высоту: 7 уровней.
  • Вы можете подготовить второй план под название NIGHTLY, в котором поменять доли групп Operators и Analytics, например, на противоположные: 10 и 90%. В вечернее время и на ночь вы можете переключать систему на план NIGHTLY, подразумевая спад операционной активности со стороны приложения и рост аналитической (подготовка отчетов). С началом рабочего дня можно снова переводить систему на план DAILY.
  • Более того, вы можете обойтись без простановки RESOURCE_MANAGER_PLAN в файл INIT.ORA, а подготовить триггер на старт БД, который будет делать простую проверку текущего времени и включать дневной или ночной план; что-нибудь вроде:
CREATE OR REPLACE TRIGGER resource_plan_on_startup

AFTER STARTUP ON DATABASE

DECLARE

switch_to_daily varchar2(40) :=

'ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = DAILY';

switch_to_nightly varchar2(40) :=

'ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = NIGHTLY';

BEGIN

IF (SYSDATE > TRUNC(SYSDATE) + 9 / 24) AND

(SYSDATE < TRUNC(SYSDATE) + 18 / 24) THEN

EXECUTE IMMEDIATE switch_to_daily;

ELSE EXECUTE IMMEDIATE switch_to_nightly;

END IF;

END;

/

В этом случае, однако, вам придется позаботиться об автоматическом переключении плана при наступлении 9 утра и 6 вечера. Сделать это можно с помощью пакета DBMS_JOB.Чем это все хорошо

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

Это значит, что в ваши старые приложения вы можете 'вдохнуть новую жизнь', не переписывая ни одной строки кода. Приятное свойство!

Что делать дальше

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



Литература по Oracle