div.main {margin-left: 20pt; margin-right: 20pt}
Как раздать пользователям
приоритеты
Не секрет, что уже достаточно давно фирма 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, простые внешне идеи при реализации обрастают
пугающим новичка изобилием технических подробностей, в которых отнюдь не просто
разобраться. (Объективно это или субъективно – для меня пока загадка.
|