18 июн. 2014 г.

Markhot и Edition Base Redefinition

Для снижения конкуренции (событие ожидания "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, проверим именно на этой версии СУБД.

Создадим отдельного пользователя и новую версию (edition), выдав права на использование этой версии и включив потенциальную версионируемость в вновь созданной схеме:
[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!

Хочу выразить большую благодарность Сергею Томину за помощь в подготовке этого примера!

1 комментарий:

  1. Игорь,

    Мы активно используем EBR в своем приложении (не OeBS).

    Не понятно, из каких представлений получить информацию о том, к какой редакции относится объект library cache.
    Конкретно, в x$kglob и других я пока не нашел подходящих полей.
    Вместе с тем, если сделать dump library cache, то там редакции видны:
    ObjectName: Name=VERSION_2.TEST_MARKHOT.MYPROC
    ObjectName: Name=TEST_MARKHOT.MYPROC

    Не подскажите, из X$ как можно получить информацию о принадлежности объекта library cache к редакции?

    ОтветитьУдалить