Для снижения конкуренции (событие ожидания "library cache: mutex X") за объекты в библиотечном кэше предназначена процедура MARKHOT системного пакета DBMS_SHARED_POOL. Данная процедура производит размножение (создает копии) указанного объекта (пакета, процедуры, курсора и т.д.) в библиотечном кэше, и тем самым снижает конкуренцию за мьютексы.
Недавно, общаясь с одним очень крупным заказчиком, высоконагруженные БД которого работают на больших Hi-End серверах, была затронута тема использования технологии Edition Base Redefinition для безостановочного обновления приложений. Этот заказчик очень активно использует процедуру MARKHOT в своих БД.
Основной вопрос, который волновал заказчика, заключался в поддержке процедурой MARKHOT технологии Edition Base Redefiniton: работает ли вышеописанное размножение объектов в кэше для разных версий (editions) объекта?
В явном виде в процедуре MARKHOT не фигурирует версия объекта (edition в которой он был определен).
Давайте разберемся в этом вопросе. Поскольку в данный момент заказчик использует Oracle Database 11.2.0.3, проверим именно на этой версии СУБД.
[oracle@localhost ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Wed Jun 18 10:58:48 2014
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options
rem Coздаем пользователя
SQL> CREATE USER test_markhot
2 IDENTIFIED BY oracle;
User created.
SQL> GRANT connect, resource TO test_markhot;
Grant succeeded.
rem Coздаем новую версию (edition), которая наследуется от ORA$BASE
SQL> CREATE EDITION version_2 AS CHILD OF ora$base;
Edition created.
rem Даем права пользователю на использование версии (edition)
SQL> GRANT USE ON EDITION version_2 TO test_markhot;
Grant succeeded.
rem Включаем для созданной схемы потенциальную версионируемость
SQL> ALTER USER test_markhot ENABLE EDITIONS;
User altered.
Далее подключимся к БД под вновь созданным пользователем test_markhot и создадим две версии одной и той же процедуры: в версиях ORA$BASE и version_2 соответственно.
SQL> conn test_markhot/oracle
Connected.
rem Проверяем версию, в которую мы вошли (должна быть по умолчанию - ORA$BASE)
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL>
SQL> create or replace procedure myproc is
k simple_integer := 0;
begin
k := 1;
end;
/
Procedure created.
rem Переключаемся в версию VERSION_2
SQL> ALTER SESSION SET EDITION=version_2;
Session altered.
SQL> show edition
EDITION
------------------------------
VERSION_2
rem Создадим новую версию нашей процедуры myproc
SQL> create or replace procedure myproc is
k simple_integer := 0;
begin
k := 2;
end;
/
Procedure created.
Далее, для удобства откроем отдельную сессию под пользователем SYS, и проверим наличие нашей процедуры MYPROC в библиотечном кэше помеченной как "горячий" объект, то есть для которой был выполнен вызов DBMS_SHARED_POOL.MARKHOT:
[oracle@localhost ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Wed Jun 18 12:25:50 2014
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options
SQL> SELECT
kglnaown,
kglnaobj,
kglhdnsp,
kglnahsh,
kglhdadr,
kglhdobj,
kglobprop,
decode(bitand(KGLHDFLG, 1024), 1024, 'ROOT',
decode(bitand(KGLHDFLG, 33554432), 33554432, 'COPY', null)) typhot
FROM
x$kglob
WHERE
(bitand(KGLHDFLG, 1024) = 1024 or bitand(KGLHDFLG, 33554432) = 33554432) and
kglnaobj='MYPROC';
no rows selected
SQL>
Все верно: поскольку мы еще не вызывали процедуру MARKHOT, - процедуры MYPROC в списке "горячих" нет.
Для удобства сохраним вышеприведенный запрос в файле hotlist.sqlНаходясь под пользователем SYS в версии ORA$BASE пометим нашу нашу процедуру как горячую:
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL> EXEC dbms_shared_pool.markhot('TEST_MARKHOT','MYPROC',1);
PL/SQL procedure successfully completed.
SQL @hotlist.sql
KGLNAOWN KGLNAOBJ KGLHDNSP KGLNAHSH KGLHDADR KGLHDOBJ KGLOBPROP TYPH
-------------- -------------------- ---------- ---------- ---------------- ---------------- ---------- ----
TEST_MARKHOT MYPROC 1 3513693258 0000000085E5F538 00 HOT ROOT
Как Вы видите, - наша процедура MYPROC была помечена как горячая. При этом вызов dbms_shared_pool.markhot создал handler на процедуру MYPROC в библиотечном кэше.Попробуем выполнить процедуру MYPROC в версии ORA$BASE (под владельцем - пользователем test_markhot):
SQL> ALTER SESSION SET edition=ora$base;
Session altered.
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL> EXEC myproc
PL/SQL procedure successfully completed.
SQL>
и проверим содержимое библиотечного кэша (в другой сессии конечно, - под пользователем SYS):
SQL> @hotlist
KGLNAOWN KGLNAOBJ KGLHDNSP KGLNAHSH KGLHDADR KGLHDOBJ KGLOBPROP TYPH
-------------- -------------------- ---------- ---------- ---------------- ---------------- ---------- ----
TEST_MARKHOT MYPROC 1 3513693258 0000000085E5F538 00 HOT ROOT
TEST_MARKHOT MYPROC 1 4205431051 0000000085E27C58 00000000853780B0 HOTCOPY1 COPY
Пока все работает штатно: в кэше были создана копия нашей процедуры.
Теперь собственно самая главная часть нашего эксперимента: пометим нашу процедуру как горячую в версии VERSION_2 и проверим содержимое library cache.
SQL> ALTER SESSION SET edition=version_2;
Session altered.
SQL> EXEC dbms_shared_pool.markhot('TEST_MARKHOT','MYPROC',1);
PL/SQL procedure successfully completed.
SQL> @hotlist
KGLNAOWN KGLNAOBJ KGLHDNSP KGLNAHSH KGLHDADR KGLHDOBJ KGLOBPROP TYPH
-------------- -------------------- ---------- ---------- ---------------- ---------------- ---------- ----
TEST_MARKHOT MYPROC 1 3513693258 0000000085E5F538 00 HOT ROOT
TEST_MARKHOT MYPROC 1 2382213173 0000000085E20EA0 00 HOT ROOT
TEST_MARKHOT MYPROC 1 4205431051 0000000085E27C58 00000000853780B0 HOTCOPY1 COPY
В кэше появился новый объект помеченный как "горячий"!
Вызовем нашу процедуру myproc в версии VERSION_2:
SQL> ALTER SESSION SET edition=version_2;
Session altered.
SQL> EXEC myproc;
PL/SQL procedure successfully completed.
и еще раз проверим содержимое library cache:
SQL> @hotlist
KGLNAOWN KGLNAOBJ KGLHDNSP KGLNAHSH KGLHDADR KGLHDOBJ KGLOBPROP TYPH
-------------- -------------------- ---------- ---------- ---------------- ---------------- ---------- ----
TEST_MARKHOT MYPROC 1 1543374076 0000000085E1FB68 00000000876D80B0 HOTCOPY1 COPY
TEST_MARKHOT MYPROC 1 3513693258 0000000085E5F538 00 HOT ROOT
TEST_MARKHOT MYPROC 1 2382213173 0000000085E20EA0 00 HOT ROOT
TEST_MARKHOT MYPROC 1 4205431051 0000000085E27C58 00000000853780B0 HOTCOPY1 COPY
Теперь в кэше началось размножение процедуры myproc новой версии!
Процедура dbms_shared_pool.markhot, которая предназначена для установки метки на горячие объекты в library cache, полностью учитывает версии объектов и ее можно совместно использовать с технологией обновления приложений на лету - Edition Base Redefinition!
Хочу выразить большую благодарность Сергею Томину за помощь в подготовке этого примера!
Игорь,
ОтветитьУдалитьМы активно используем EBR в своем приложении (не OeBS).
Не понятно, из каких представлений получить информацию о том, к какой редакции относится объект library cache.
Конкретно, в x$kglob и других я пока не нашел подходящих полей.
Вместе с тем, если сделать dump library cache, то там редакции видны:
ObjectName: Name=VERSION_2.TEST_MARKHOT.MYPROC
ObjectName: Name=TEST_MARKHOT.MYPROC
Не подскажите, из X$ как можно получить информацию о принадлежности объекта library cache к редакции?