Модель еТОМ состоит (см. рис.1) из трех областей: “Стратегия, Инфраструктура, Продукт”, “Операционные (производственные) процессы” и “Управление предприятием”, каждая из которых имеет многоуровневую иерархическую структуру декомпозиции бизнес-процессов от концептуального (нулевого) до достаточно детализированного (третьего) уровня. На этом заканчивается стандартная часть еТОМ. Дальнейшая декомпозиция бизнес-процессов потребует уже данных о структуре, возможностях и особенностях конкретного предприятия Телекома, что можно и следует делать уже на предприятии, желающим разобраться со своими бизнес-процессами, в рамках консалтинг-проекта. А именно: упорядочить, модернизировать бизнес-процессы, привести их в соответствие с общепризнанными рекомендациями, которые и воплотились в стандарте еТОМ.
См. .
Приведем в качестве примера в нашем переводе фрагменты описания трех процессов, находящихся на 2-м и 3-м уровне еТОМ :
2-й уровень области “Операционные Процессы” слой “Сетевая эксплуатация и управление ресурсами”: "Resource Performance Management" ("Управление производительностью ресурсов")
Код процесса OPS 3-4.
"Resource Performance Management processes encompass monitoring, analyzing, controlling and reporting on the performance of resources. They work with basic information received from the Resource Data Collection & Processing processes. If the analysis identifies a resource quality problem, information will be passed to Resource Trouble Management and/or Service Quality Management."
[ “Процессы "Управления производительностью ресурсов" проводят мониторинг, анализ, управление и составляют отчеты о производительности ресурсов. Они работают с исходной информацией, получаемой из процессов "Накопления и обработки данных о ресурсах". Если анализ выявляет проблему качества ресурса, то информация будет передана в процесс "Управление проблемами ресурсов" и/или в "Управление качеством услуги" и т.д. ]
“eTOM Overview”, TeleMagement Forum, http://www.tmforum.org/browse.asp?catID=1648 ITU-T. TELECOMMUNICATION STANDARDIZATION SECTOR. (06/2004). Telecommunications management network. Enhanced Telecom Operations Map® (eTOM) – The business process framework. M3050.1 @ ITU 2004
[3]Е.Нагаев “еТОМ: структурная модель бизнес-процессов для операторов связи”, М:, 2Мобильные системы”, 5, 2005. “Enhanced Telecom Operations Map (eTOM) The Business Process Framework” Addendum D: Process Decompositions and Descriptions (For The Information and Communications Services Industry), www.tmforum.com, GB921D_v4-0-1_040318.pdf Mike Kelly (TeleManagement Forum) “NGOSS and eTOM”, November 2002, Free Download. Telecargar Document. Formato. Talla. Colocado. Free Download. http://www.itu.int/itudoc/itu-t/com2/infodocs/019_pp7.ppt Steve Cox (Sr. Director NAS Applications Business Unit, Oracle Corporation) “Leveraging the ETOM To Facilitate Your Business”, Telemamagment World, Nice, May 19-22, 2003, http://www.tmforum.com/browse.asp?articleID=23012 Martin Huddleston (Principal Engineer, QinetiQ) “From ITIL to eTOM: Gluing Together the eProcess Value Chain In Mixed Civil/Military Environments”, 2002, TMFC1132 OSSBIZ4 Martin Huddleston and Nigel Phillips ver2.ppt, http://www.tmforum.org/browse.asp? catID=1207&sNode=1207&Exp=Y&linkID=25663&docID=1132
Хорошо известно, что информатизация управления не приносит заявляемых и ожидаемых результатов в условиях слабой или отсутствия конкуренции, при наличии дешевых или практически бесплатных ресурсов. Как анекдот, известно высказывание руководителя одной Большой компании, что он с лихвой покроет все будущие денежные результаты от информатизации, продав сегодня пару дополнительных составов природного сырья, и что это ему почти ничего стоит. Истинная информатизация управления связана с новыми вложениями в вычислительную технику и программное обеспечение, с привлечением высококвалифицированных и, следовательно, дорогих специалистов, с переобучением своих сотрудников и ломкой сложившихся стереотипов поведения, деятельности и т.д. А результат всей этой деятельности может проявиться и не скоро, и неизвестно, будет ли он таким, каким сегодня мыслится инициаторам.
Но делать что-то надо. Старый лозунг “АСУ – веление времени” - не просто лозунг, а, действительно, веление времени. Как только действенность хотя бы одного фактора (слабая конкуренция и/или дешевизна ресурсов) существенно падает, так падает и поток доходов. Оказывается, что модель экстенсивного развития более не работает, имеющаяся система управления, хотя численно разбухла, но уже не обеспечивает скорость, качество и цели управления и начинает расходовать на свое содержание больше ресурсов, чем производит производство. Единственный выход – переход на модель интенсивного развития, которая предполагает, в том числе, исследование и модернизацию бизнес-процессов управления предприятием.
Одной из наиболее известных современных многоуровневых моделей бизнес-процессов управления производством – это eTOM (Enhanced Telecom Operations Map – расширенная модель деятельности Телекома), разработанная международной некоммерческой организацией TeleManagement Forum (TMF) . С апреля 2004г. eTOM 4.0 становится стандартом – так принял Комитет по телекоммуникационным стандартам (Telecommunication Standardization Sector (ITU-T)) Международный Союз Связи (ITU - International Telecommunication Union) .
На представлен первый уровень иерархии (всего их четыре: 0 – 3) декомпозиции бизнес-процессов [1, 3].
По нашему представлению, еТОМ (на любом, даже самом детализированном уровне декомпозиции бизнес-процессов) представляет собой логически-имитационную модель деятельности предприятия. Для того, чтобы она заработала в режиме АСУ, ее надо воплотить в программно-информационную структуру. Это можно сделать разными путями, например, разработав схему базы данных, построив требуемые приложения и т.п. Но можно воспользоваться готовыми приложениями, оценив только, насколько они отвечают выполненному проекту, и настроить имеющиеся и разработать только недостающие приложения. Такой путь предлагает полнофункциональный комплекс приложений уровня предприятия Oracle E-Business-Suite, в котором имеются необходимые программные компоненты для реализации модели еТОМ на предприятии Телекома .
Предложение и привязка компонентов Oracle E-Business-Suite к уровням и процессам модели еТОМ:
Основные программные системы Oracle E-Business-Suite для индустрии коммуникаций Отображение модели еТОМ на решения Oracle для промышленности
В промышленности связи, в сфере телекоммуникаций за последние несколько десятков лет наблюдалось настолько бурное развитие, что, можно сказать, отрасль претерпела ряд действительно революционные изменения, поскольку направление электронных коммуникаций поднялось почти от нуля. Естественно, это было связано с общественным, с бизнес-спросом на увеличение объемов передаваемой информации, на повышение скорости и качества ее переработки.
Но немалую роль сыграла и специфика ориентированной на высокотехнологичные услуги телекоммуникационной отрасли. Для нее характерна относительно малая материало- и повышенная науко- емкость. В ней широко применяется высококвалифицированный (дорогой) и сравнительно мало – низкоквалифицированный (дешевый) труд. Нематериальный характер конечной продукции позволяет избежать больших капитальных вложений в производство, что обуславливает достаточно высокий уровень и быстроту возврата инвестиций, прибыльность и прочие позитивные макроэкономические показатели. “Платой” за такие уникальные условия стало требование быстрой модернизации в ответ на все возрастающие потребности общества и бизнеса в информации, скорости и объемах ее получения. Новейшие способы совершенствования сетей, интеграция технологий и различного телекоммуникационного оборудования, создание мультисервисных сетей следующего поколения, беспроводные способы передачи данных и многое другое – без этого трудно выжить на рынке.
Жесткая конкуренция, высокая изменчивость, многоплановость и многообразие, быстрота предоставления услуг,… - неизбежно отражаются на системе управления предприятия Телекома, на (это - решающий фактор (!)) скорости, правильности, полноте принятия решений, на необходимом прогнозе конкуренции, партнерства, развития потребностей пользователей и рынка и т.п.
Это - общие для всех Телеком-предприятий задачи, которые воплощены в повседневные бизнес-процессы управления. Отметим, что многие бизнес-процессы характерны и существуют для многих-многих других отраслей бизнеса. Но Телеком в лице TeleManagement Forum (TMF), объединяющего около 400 компаний по всему миру, в том числе, и операторов связи, в данном случае оказался одним из первых, возведя в ранг международного стандарта модель еТОМ.
Использование еТОМ дает: экономию времени и затрат на разработку структуры бизнес-процессов предприятия решение типичных задач анализа и оптимизации бизнес-процессов
выявление и устранение дублирующих процессов, имеющих одинаковую функциональность ускорение разработки новых процессов основу для управления набором ИТ-приложений, исходя из потребностей бизнеса возможность создания четких и качественных моделей потоков бизнес-процессов. дальнейшее применение знаний в области бизнес-процессов.
Применение технологии еТОМ на многих предприятиях Телекома дает возможность интегрировать между собой многие бизнес-процессы нескольких предприятиях, являющихся поставщиками-партнерами друг друга или объединенных другими связями. На показано, как взаимодействуют между собой бизнес-процессы разных Телеком-предприятий, применяющих модель еТОМ, причем эти взаимодействия можно автоматизировать, доведя их в идеале до уровня баз данных.
Положительный эффект от использования еТОМ ощутим не только для Телеком-компаний, но также и для софтвер-компаний, разработчиков систем класса OSS/BSS, системных интеграторов и др. еТОМ используют Oracle, Amdocs, Agilent Technologies. Примером реализации еТОМ может служить разработка глобальной ИТ-архитектуры Vodafone, в основу которой была положена структура еТОМ, адаптированная и отражающая специфику компании.
По мере развития сферы телекоммуникаций в России проблема комплексного анализа и оптимизации бизнес-процессов, операторов связи становится все более актуальной. Соответственно возрастает ценность и значимость как всей программы по развитию структуры NGOSS, так и ее бизнес-составляющей eTOM. В России в настоящее время модель структуры бизнес-процессов еТОМ в реализации Casewise Corporate Modeler поставляет только “ФОРС –Центр Разработки”.
Пирамида управления предприятием Телекома, представленная в левом верхнем углу (сверху вниз – управление бизнесом, услугами, сетью и элементами сети) воплощается в модель производственных (операционных) процессов ТОМ (Telecom Operations Map), которая расширяется до еТОМ - бизнес-модели процессов управления Телеком-предприятия в целом, которую TMForum собирается воплотить в проект NGOSS (New Generation Operations Systems & Software), который позиционируется как обобщенная и интегрированная структура для создания эффективного комплекса систем класса BSS/OSS и другого программного обеспечения .
Структура NGOSS представляет собой четыре различные, взаимосвязанные между собою компоненты, а именно:
Анализ бизнес-процессов Анализ и проектирование систем Анализ и проектирование решений Анализ на соответствие
Тем самым, миссия NGOSS - интеграция в единую архитектуру технических и бизнес-аспектов деятельности Телеком-компаний, устранение разрозненности и "лоскутности" автоматизации, построение общей информационной инфраструктуры. Структура NGOSS используется в деятельности таких крупнейших провайдеров как Vodafone, Verizon, Telstra, Telecom Italia, TeliaSonera, China Telecom и др. Главным компонентом NGOSS является механизм анализа бизнес-процессов, а именно eTOM.
А.В.Бачин
Источник:
Чтобы победить,
надо знать себя и противника.
Карл фон Клаузевиц
(и, наверное, не только он)
Приведу пример использования нескольких функций, их декларацию можно посмотреть в спецификации пакета DBMS_STANDARD.
Листинг 3
SCOTT@O102>alter session set nls_time_format='HH24:MI:SSXFF'; Session altered. SCOTT@O102>alter session set nls_time_tz_format='HH24:MI:SSXFF TZH:TZM'; Session altered. SCOTT@O102>col tm for a40 SCOTT@O102> --CURRENT_TIME - текущее время с временной зоной SCOTT@O102>select current_time tm from dual; TM ---------------------------------------- 02:22:34 +06:00 SCOTT@O102> --LOCALTIME - локальное время SCOTT@O102>select localtime tm from dual; TM ---------------------------------------- 02:23:29 SCOTT@O102>
--TO_TIME - преобразование строки к типу TIME, опциональный второй аргумент - NLS-format SCOTT@O102>select to_time('01.02.03','hh24.mi.ss') tm from dual; TM ---------------------------------------- 01:02:03.000000000 SCOTT@O102> --TO_TIME_TZ - аналогичен TO_TIME, но возвращает TIME WITH TIME ZON SCOTT@O102>select to_time_tz('01.02.03','hh24.mi.ss') tm from dual; TM ---------------------------------------- 01:02:03.000000000 +06:00 SCOTT@O102> --EXTRACT - действие, как и для прочих DATETIME типов данных SCOTT@O102>col hour for 9999 SCOTT@O102>col min for 999 SCOTT@O102>col sec for 90.999999999 SCOTT@O102>with t as (select to_time('01.02.03.123456789','hh24.mi.ssxff') tm 2 from dual) 3 select extract (hour from tm) hour, 4 extract (minute from tm) min, 5 extract (second from tm) sec 6 from t 7 / HOUR MIN SEC ----- ---- ------------- 1 2 3.123456789 SCOTT@O102> --TO_CHAR - аналогична TO_CHAR (datetime) SCOTT@O102>col tm for a20 SCOTT@O102>select to_char(current_time,'hh-mi AM "TZ" TZH:TZM') tm from dual; TM -------------------- 09-06 PM TZ +06:00
В заключении, приведем таблицу операций, которые мне удалось обнаружить над типом данных TIME.
Листинг 4
TIME | - | TIME | DSINTERVAL |
TIME | + | DSINTERVAL | TIME |
TIME | - | DSINTERVAL | TIME |
Включение использования типа данных TIME можно добиться установкой события 10407 на уровне сессии. Без включения данного события тип данных TIME остается заблокированным, и все обращения к нему или к зависимым функциям будут заканчиваться различными ошибками. Ниже приведен листинг включения данного события и создания таблицы с единственным полем типа данных TIME(0).
Листинг 1
SCOTT@O102>exec dbms_output.put_line (sqlerrm(-10407)); ORA-10407: enable datetime TIME datatype creation PL/SQL procedure successfully completed. SCOTT@O102> --Create table with time datatype SCOTT@O102>create table t (tm time); create table t (tm time) * ERROR at line 1: ORA-00902: invalid datatype SCOTT@O102> --Set event 10407 and try again SCOTT@O102>alter session set events '10407 trace name context forever, level 1';
Session altered. SCOTT@O102>create table t (tm time); Table created. SCOTT@O102>desc t Name Null? Type ----------------------------------------- -------- ------------------------- TM TIME(0) SCOTT@O102>insert into t select to_time('01.02.'level*5) from dual connect by level<=5; 5 rows created. SCOTT@O102>select * from t; TM --------------------------------------------------------------------------- 01.02.05 AM 01.02.10 AM 01.02.15 AM 01.02.20 AM 01.02.25 AM
В паре к типу данных TIME, существует тип данных TIME WITH TIME ZONE, который дополнительно хранит еще часы и минуты временной зоны. Если обратить внимание, то на самом деле мы в предыдущем примере создали таблицу типа данных TIME (0) – в текущей реализации тип данных TIME может хранить и доли, меньшие секунды. То есть TIME (n) служит для хранения: часов, минут, секунд и 10n
долей секунды (где n – целое от 0 до 9).
NLS-параметры, связанные с типом данных TIME, подчиняются абсолютно тем же правилам, что и прочие NLS-параметры (типов DATE, TIMESTAMP и т.д.). Как мне известно, есть всего два таких NLS-параметра: первый для TIME, второй для TIME WITH TIME ZONE. Рассмотрим небольшой пример.
Листинг 2
SCOTT@O102>col parameter for a30 SCOTT@O102>col value for a30 SCOTT@O102>select * from nls_session_parameters where parameter like '%TIME\_%' escape '\'; PARAMETER VALUE ------------------------------ ------------------------------ NLS_TIME_FORMAT HH.MI.SSXFF AM NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR SCOTT@O102>desc t1 Name Null? Type ----------------------------------------- -------- ------------------------- TM TIME(6) SCOTT@O102>select * from t1; TM --------------------------------------------------------------------------- 01.02.03.456789 AM SCOTT@O102>alter session set nls_time_format='HH24:MI:SSXFF'; Session altered. SCOTT@O102>select * from t1; TM --------------------------------------------------------------------------- 01:02:03.456789
М.Великих
инженер ЦТП Oracle
компания "АйТи"
г.Новосибирск
Ограничения: В данном примере описывается создание простой конфигурации (basic level of availability).
Вначале добавим сущность в cluster.oracle.ini, в которой пропишем узлы, на которых будет запущена репликация, и директорию для CRS-скриптов (check, start, stop) для определенной репликации). … [ha_ds] MasterHosts=rac1,rac2 ScriptInstallDir=/u01/app/oracle/product/11.2.1/TimesTen/tt1/info/crs_scripts …
Теперь нужно повторить настройки cluster.oracle.ini и sys.odbc.ini на втором узле (rac2).
Далее регистрируем TimesTen кластер в OCR.
[root@rac1 ~]$ cd /u01/app/oracle/product/11.2.1/TimesTen/tt1/bin/
[root@rac1 bin]$ ./ttCWAdmin -ocrconfig
Oracle Clusterware home = /u01/app/oracle/product/11.1.0/crs
Далее запускаем агенты кластера TimesTen на обоих узлах. [root@rac1 bin]$ ./ttCWAdmin -init
Oracle Clusterware home = /u01/app/oracle/product/11.2.1/crs, hosts = rac1,rac2 =============================================================== Registering agent resources:... Registration complete. =============================================================== =============================================================== Registering daemon resources:... Registration complete. ===============================================================
После этого в CRS должны появиться четыре новых сервиса.
[oracle@rac1 ~]$ crs_stat -t
Name Type Target State Host ------------------------------------------------------------ TT_A...le_RAC1 application ONLINE ONLINE rac1
TT_A...le_RAC2 application ONLINE ONLINE rac2
TT_D...le_RAC1 application ONLINE ONLINE rac1
TT_D...le_RAC2 application ONLINE ONLINE rac2
ora.rac1.gsd application ONLINE ONLINE rac1 ora.rac1.ons application ONLINE ONLINE rac1 ora.rac1.vip application ONLINE ONLINE rac1 ora.rac2.gsd application ONLINE ONLINE rac2 ora.rac2.ons application ONLINE ONLINE rac2 ora.rac2.vip application ONLINE ONLINE rac2 [oracle@rac1 ~]$
[oracle@rac1 ~]$ crs_stat
… NAME=TT_Agent_tt1_oracle_RAC1 TYPE=application TARGET=ONLINE STATE=ONLINE on rac1 NAME=TT_Agent_tt1_oracle_RAC2 TYPE=application TARGET=ONLINE STATE=ONLINE on rac2 NAME=TT_Daemon_tt1_oracle_RAC1 TYPE=application TARGET=ONLINE STATE=ONLINE on rac1 NAME=TT_Daemon_tt1_oracle_RAC2 TYPE=application TARGET=ONLINE STATE=ONLINE on rac2 …
Oracle® TimesTen In-Memory Database Documentation Media Library 11g (11.2.1) Using Openfiler iSCSI with an Oracle RAC database on Linux (Doc ID 371434.1)
Посмотрим на текущее состояние конфигурации. [root@rac1 bin]# ./ttCWAdmin -status
TimesTen Cluster status report as of Fri Sep 3 15:54:23 2010 ==================================================================== TimesTen daemon monitors: Host:RAC1 Status: online Host:RAC2 Status: online ==================================================================== ==================================================================== TimesTen Cluster agents Host:RAC1 Status: online Host:RAC2 Status: online ==================================================================== Status of Cluster related to DSN HA_DS: ==================================================================== 1. Status of Cluster monitoring components: Monitor Process for Master Datastore 1 on Host rac1: RUNNING Monitor Process for Master Datastore 2 on Host rac2: RUNNING Monitor Process for Active datastore:RUNNING on Host rac1 Monitor Process for Standby datastore:NOT RUNNING 2.Status of Datastores comprising the cluster Master Datastore 1: Host:rac1 Status:AVAILABLE State:ACTIVE Master Datastore 2: Host:rac2 Status:AVAILABLE State:STANDBY ==================================================================== The cluster containing the replicated DSN is offline
Подсоединимся к узлу, имеющему состояние active, и вставим ряд записей в таблицу plans.
[oracle@rac1 ~]$ ttisql "DSN=ha_ds;UID=app;PWD=app"
Copyright (c) 1996-2009, Oracle. All rights reserved. Type ? or "help" for help, type "exit" to quit ttIsql. connect "DSN=ha_ds;UID=app;PWD=app"; Connection successful: DSN=ha_ds;UID=app;DataStore=/u01/app/oracle/datastore/ha_ds;DatabaseCharacterSet=AL32UTF8;ConnectionCharacterSet=US7ASCII;DRIVER=/u01/app/oracle/product/11.2.1/TimesTen/tt1/lib/libtten.so;PermSize=40;TempSize=32;TypeMode=0; (Default setting AutoCommit=1) Command> call ttRepStateGet();
< ACTIVE >
1 row found. Command> select count(*) from plans;
< 0 > 1 row found. Command> declare
На данном этапе создадим базу данных, которую будем реплицировать. Для этого создадим на обоих узлах следующие директории:
/u01/app/datastore - для хранения всех баз данных Oracle TimesTen /u01/app/datastore/ha_ds – для базы данных «ha_ds», которую будем реплицировать.
[root@rac1 ~]$ mkdir /u01/app/datastore
[root@rac1 ~]$ chown oracle:oinstall /u01/app/datastore
[root@rac1 ~]$ mkdir /u01/app/datastore/ha_ds
[root@rac1 ~]$ chown oracle:oinstall /u01/app/datastore/ha_ds
Далее выбираем один из узлов кластера для создания базы данных. В данном случае - это узел rac1. Создадим сущность в файле sys.odbc.ini.
… [ha_ds]
Driver=/u01/app/oracle/product/11.2.1/TimesTen/tt1/lib/libtten.so DataStore=/u01/app/datastore/ha_ds PermSize=40 TempSize=32 PLSQL=1 DatabaseCharacterSet=AL32UTF8 …
Далее соединяемся с базой данных «ha_ds» как администратор экземпляра Oracle TimesTen (в данном примере это oracle - он устанавливал экземпляр Oracle TimesTen) и создадим в ней необходимых пользователей:
adm – администратор базы данных и репликации (для этого данному пользователю
необходима привилегия ADMIN).
app – пользователь имеющий минимальный набор привилегий, владелец объектов.
[oracle@rac1 ~]$ ttisql ha_ds
Copyright (c) 1996-2009, Oracle. All rights reserved. Type ? or "help" for help, type "exit" to quit ttIsql. connect "DSN=ha_ds"; Connection successful: DSN=ha_ds;UID=oracle;DataStore=/u01/app/datastore/ha_ds;DatabaseCharacterSet=AL32UTF8;ConnectionCharacterSet=US7ASCII;DRIVER=/u01/app/oracle/product/11.2.1/TimesTen/tt1/lib/libtten.so;PermSize=40;TempSize=32;TypeMode=0; (Default setting AutoCommit=1) Command> create user adm identified by adm;
User created. Command> grant ADMIN to adm;
Command> create user app identified by app;
User created. Command> grant create session, create table to app;
Command> exit; Disconnecting... Done. [oracle@rac1 ~]$
После этого соединяемся с базой данных под пользователем app и создаем таблицу plans.
[oracle@rac1 ~]$ ttisql "DSN=ha_ds;UID=app;PWD=app"
Copyright (c) 1996-2009, Oracle. All rights reserved. Type ? or "help" for help, type "exit" to quit ttIsql. connect "DSN=ha_ds;UID=app;PWD=app"; Connection successful: DSN=ha_ds;UID=app;DataStore=/u01/app/datastore/ha_ds;DatabaseCharacterSet=AL32UTF8;ConnectionCharacterSet=US7ASCII;DRIVER=/u01/app/oracle/product/11.2.1/TimesTen/tt1/lib/libtten.so;PermSize=40;TempSize=32;TypeMode=0; (Default setting AutoCommit=1) Command> create table plans ( Id number(12),
> Name varchar(32 char),
> PricePerMin binary_double,
> Status char(3 char),
> primary key (Id) );
Command> exit; Disconnecting... Done. [oracle@rac1 ~]$
Вначале установим Oracle Clusterware.
На момент написания статьи, интеграция Oracle TimesTen и Oracle Clusterware возможна только на платформах Linux x86 и Linux x86-64, и только с версией Oracle Clusterware 11.1.0.7., поэтому после установки 11.1.0.6. необходимо установить патчсет 11.1.0.7.
Процессу установки Oracle Clusterware посвящено достаточно много статей. Поэтому я не буду детально описывать этот процесс, отмечу только, что все машины должны использовать Network Time Protocol (NTP) или похожую систему для устранения расхождения во времени между машинами на интервал более чем 250 миллисекунд.
Данное ограничение связано с функционированием active-standby pair репликации в Oracle TimesTen.
В данном примере я создал 2-ух узловой кластер (установлено только Oracle Clusterware) из виртуальных машин на базе Oracle VM-сервера 2.2.0 (x86 64 bit). В качестве гостевой операционной системы использовался Oracle Enterprise Linux 5.3 (x86). В качестве разделяемой системы хранения использовался Openfiler.
Характеристики кластера:
OS username / password:
root/oracle oracle/oracle
Hostname raс1:
public IP 192.168.2.131 virtual IP 192.168.2.31 private IP 10.10.10.131 IP for openfiler 172.16.2.131
Hostname rac2:
public IP 192.168.2.132 virtual IP 192.168.2.32 private IP 10.10.10.132 IP for openfiler 172.16.2.132
Openfiler:
Public IP 172.16.2.1
Oracle Clusterware:
CRS_HOME=/u01/app/oracle/product/11.1.0/crs
Убедимся, что программное обеспечение Oracle Clusterware установлено и нормально функционирует. [oracle@rac1 ~]$ crs_stat –t
Name Type Target State Host ------------------------------------------------------------ ora.rac1.gsd application ONLINE ONLINE rac1 ora.rac1.ons application ONLINE ONLINE rac1 ora.rac1.vip application ONLINE ONLINE rac1 ora.rac2.gsd application ONLINE ONLINE rac2 ora.rac2.ons application ONLINE ONLINE rac2 ora.rac2.vip application ONLINE ONLINE rac2
Также убедимся, что установлена соответствующая версия Oracle Clusterware (11.1.0.7). [oracle@rac1 ~]$ crsctl query crs activeversion
Oracle Clusterware active version on the cluster is [11.1.0.7.0]
После установки Oracle Clusterware инсталлируем Oracle TimesTen 11.2. Его надо установить на те же машины, на которых функционирует Oracle Clusterware, в данном случае на узлах rac1 и rac2. Вначале выполним данную операцию на узле rac1.
Я инсталлирую Oracle TimesTen 11.2.1.4 (дистрибутив можно скачать с ). Перед этим я настоятельно рекомендую ознакомиться с документацией (Oracle® TimesTen In-Memory Database Installation Guide) и выполнить шаги, описанные в разделе "Installation prerequisites" (для Linux, например, необходимо сконфигурировать huge pages, shared memory и т.д.).
Установка производится пользователем oracle (в дальнейшем, этот пользователь будет администратором экземпляра Oracle TimesTen).
Сначала создадим необходимые директории:
- /etc/TimesTen - необходима для инсталляции.
- /u01/app/oracle/product/11.2.1- здесь будет размещено программное обеспечение Oracle TimesTen.
[root@rac1 ~]$ mkdir /etc/TimesTen
[root@rac1 ~]$ chown oracle:oinstall /etc/TimesTen
[root@rac1 ~]$ mkdir /u01/app/oracle/product/11.2.1
[root@rac1 ~]$ chown oracle:oinstall /u01/app/oracle/product/11.2.1
Далее разархивируем дистрибутив. [oracle@rac1 ~]$ pwd
/home/oracle [oracle@rac1 ~]$ ls
timesten112140.linux86.tar.gz [oracle@rac1 ~]$ gunzip timesten112140.linux86.tar.gz
[oracle@rac1 ~]$ tar -xf timesten112140.linux86.tar
Далее переходим в директорию linux86 и запускаем установку.
[oracle@rac1 ~]$ cd linux86
[oracle@rac1 linux86]$ ./setup.sh
NOTE: Each TimesTen installation is identified by a unique instance name.The instance name must be a non-null alphanumeric string, not longer than 255 characters.
Вначале, предлагается ввести имя экземпляра Oracle TimesTen (или согласиться с именем по умолчанию). В данном примере имя экземпляра tt1.
Please choose an instance name for this installation? [ tt1121 ] tt1
Instance name will be 'tt1'. Is this correct? [ yes ]
Далее, предлагается выбрать компоненты для установки. В данном примере я устанавливаю все компоненты ("Client/Server and Data Manager").
Возьмем стандартный демонстрационный пример из любой поставки Oracle: таблицу сотрудников EMP в схеме пользователя SCOTT. Предположим, что организация, в которой работают сотрудники, устроена таким образом, что каждый пользователь Oracle, обратившись к этой таблице, может видеть в ней только перечень сотрудников из своего отдела, то есть SCOTT – только сотрудников отдела 20, ALLEN – отдела 30 и так далее.
Это, конечно, простая постановка задачи, но для иллюстрации идеи она годится. От нее рукой подать до такой организации данных, при которой каждый врач, обратившись к одной и той же таблице, видит только своих пациентов и до более сложных постановок.
В соответствие с известной дихотомией «правильный метод»/ «наш метод» рассмотрим два решения: одно более правильное, а другое – более эффективное.
В пакете DBMS_RLS предусмотрены и другие возможности, следующего порядка значимости. О них можно самостоятельно справиться в документации. Например, сформированную «политику доступа» можно включать и выключать, обновлять и так далее.
Описанный способ разграничения доступа к отдельным строкам таблицы фирма Oracle называет Fine Grained Access Control (FGAC). В документации по СУБД Oracle вы можете встретить еще одно название для разграничения доступа к строкам: Label Security. В Label Security разработчики Oracle воспользовались FGAC как основой для построения логически иной модели доступа. В рамках терминологии этой статьи и предыдущей, эту последнюю модель можно назвать «решением № 3». Ей будет посвящена отдельная статья.
Наша цель – разрешить разным пользователям Oracle работать (SELECT, INSERT, UPDATE, DELETE) только с сотрудниками из таблицы EMP определенных отделов.
Для этого создадим в SQL*Plus регламентирующую таблицу, которую назовем UDPERMISSIONS:
CONNECT / AS SYSDBA
CREATE TABLE udpermissions (username VARCHAR2(14), deptno NUMBER (2));
INSERT INTO udpermissions VALUES ('SCOTT', 10);
INSERT INTO udpermissions VALUES ('SCOTT', 30);
INSERT INTO udpermissions VALUES ('ADAM', 10);
(Полагаем, что пользователь SCOTT будет работать с сотрудниками 10 и 30 отделов, а пользователь ADAM – с сотрудниками только 10).
Тут же создадим предикат, формулирующий условие доступа, отталкиваясь от содержимого только что созданной таблицы UDPERMISSIONS:
CREATE OR REPLACE FUNCTION deptsallowed ( obj_schema IN VARCHAR2 ,obj_name IN VARCHAR2 ) RETURN VARCHAR2 IS BEGIN RETURN 'deptno IN (SELECT deptno FROM udpermissions ' 'WHERE username = USER)'; END; /
Замечание. У функции DEPTSALLOWED два неиспользуемых в теле параметра. Не использовали мы их для простоты, а при желании могли бы и использовать для передачи имен схемы и таблицы, задав функцией более сложную логику. С другой стороны опыт показал, что для безошибочной работы параметры должны быть объявлены.
Тут же создадим под именем EPOLICY «политику доступа» к таблице SCOTT.EMP на основе созданного только что предиката:
BEGIN DBMS_RLS.ADD_POLICY
( POLICY_NAME => 'epolicy'
,OBJECT_SCHEMA => 'scott'
,OBJECT_NAME => 'emp'
,FUNCTION_SCHEMA => 'sys'
,POLICY_FUNCTION => 'deptsallowed'
); END; /
Перечень имеющихся «политик» можно посмотреть в таблицах DBA(USER)_POLICIES.
Так как функция DEPTSALLOWED принадлежит SYSTEM, а связываться в нашем случае она будет с таблицей SCOTT.EMP, не забудем дать пользователю SCOTT право к этой функции обращаться (неявно, через созданную политику):
GRANT EXECUTE ON deptsallowed TO scott;
С каждым сеансом работы пользователя в Oracle может быть связан так называемый контекст. Он представляет собой набор пар «параметр/значение», совсем как это сделано в таблице UDPERMISSIONS выше. Там, однако, в качестве «параметров» выступали имена пользователей, а в контексте это имена отвлеченных «параметров», каких захотим. Создается контекст SQL-предложением CREATE CONTEXT …, связывается с сеансом процедурой DBMS_SESSION.SET_CONTEXT, а вот узнается почему-то обращением к стандартной процедуре SYS_CONTEXT.
Связывать контекст с сеансом можно и вручную, явной выдачей команды, но хорошая практика – поручить это триггерной процедуре, срабатывающей при подключении прикладной программы к СУБД.
Oracle рекомендует пользоваться контекстом для формулирования предиката доступа, но смысл контекста представляется не совсем уж очевидным. Хотя он и дает некоторую дополнительную свободу по сравнению с регламентирующей таблицей из примера выше (нет жесткой связи с именем пользователя), ясно, что подправив одновременно и нашу регламентирующую таблицу, и предикат, мы всегда сможем реализовать точно такую же свободу. Возможно, что рациональное зерно здесь в эффективности, так как от нас не требуется создавать специальную хранимую таблицу и обращаться к ней каждый раз, и в защищенности данных. Но достигается это за счет усложнения и очередного уклонения от реляционного подхода.
Предикат условия доступа Oracle рекомендует оформлять в виде не отдельной функции, а пакетированной. Определенный резон в этом есть. Так, у вас может иметься несколько предикатов для разных таблиц, и объединить их в специальный пакет естественно и удобно для разработки. В тот же пакет разумно включить процедуру DBMS_SESSION.SET_CONTEXT установки контекста для сеанса, так как у нее есть странноватая особенность: она не вызывается напрямую (попробуйте !), а только из состава какого-нибудь пакета.
Оговорюсь сразу: «таблица» в заголовке – не обязательно базовая, а может быть и выводимая, то есть view, а с версии 10 – так же и синоним таблицы. Способ, описываемый ниже, позволяет ограничить доступ к определенным строкам таблицы (базовой ли, выводимой – не важно) разным пользователям по-разному: в зависимости от условия, которое мы сами сконструируем. Способ основан на использовании системного пакета DBMS_RLS и доступен он только в Oracle, то есть для переносимости на другие СУБД это решение – не лучший вариант, хотя и не 100%-безнадежный.
Основные элементы этого специфичного Oracle-решения таковы:
Создадим на PL/SQL функцию-предикат P, задающую условие на строки таблицы TAB. С помощью подпрограммы из пакета DBMS_RLS создадим так называемую «политику доступа», связывающую таблицу TAB с этим предикатом. Начиная с этого момента всякое обращение пользователей к таблице TAB будет автоматически заменяться СУБД на SELECT * FROM tab WHERE p, словно бы TAB была выводимой таблицей с указанной формулировкой.
Теперь дело техники – придумать определение для P так, чтобы эта функция отбирала для каждого пользователя только положенные ему строки. Тут тоже есть разные решения.
У процедуры DBMS_RLS.ADD_POLICY есть еще один параметр, опущеный в примере выше в виду позволительного для него умолчания. Это параметр STATEMENT_TYPES, помощью которого имеется возможность уточнить, на какие виды действий с таблицей будет распространяться конкретный предикат. Пример использования этого параметра: STATEMENT_TYPES => 'select, update, delete'.
С учетом сказанного можно предложить более «правильный» (с точки зрения разработчиков Oracle) способ решения проблемы разграничения доступа к строкам:
CONNECT / AS SYSDBA
CREATE OR REPLACE CONTEXT dept_permissions USING permissions_package;
CREATE OR REPLACE PACKAGE permissions_package IS PROCEDURE set_location_context(loc IN VARCHAR2);
FUNCTION deptsallowed (obj_schema IN VARCHAR2, obj_name IN VARCHAR2)
RETURN VARCHAR2;
END permissions_package;
/
CREATE OR REPLACE PACKAGE BODY permissions_package IS
PROCEDURE set_location_context(loc IN VARCHAR2) IS
BEGIN
DBMS_SESSION.SET_CONTEXT('dept_permissions', 'location', loc);
END;
FUNCTION deptsallowed (obj_schema IN VARCHAR2, obj_name IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN RETURN
'deptno in
(SELECT deptno
FROM scott.dept
WHERE loc = sys_context(''dept_permissions'', ''location''))';
END;
END permissions_package;
/
GRANT EXECUTE ON permissions_package TO scott;
EXECUTE DBMS_RLS.ADD_POLICY - ('scott','emp','epolicy','sys', - 'permissions_package.deptsallowed','select,update')
Проверка:
SQL> CONNECT scott/tiger
Connected.
SQL> EXECUTE -
> system.permissions_package.set_location_context('DALLAS')
SQL> SELECT SYS_CONTEXT('dept_permissions', 'location') FROM DUAL;
SYS_CONTEXT('DEPT_PERMISSIONS','LOCATION')
------------------------------------------
DALLAS
SQL> SELECT ename, loc FROM emp, dept WHERE emp.deptno = dept.deptno;
ENAME LOC ---------- ------------- SMITH DALLAS
JONES DALLAS
SCOTT DALLAS
ADAMS DALLAS
FORD DALLAS
5 rows selected.
Выглядит не самым простым образом, верно. Но зато возможностей при таком решении больше, чем при работе с непакетированной функцией-предикатом или же при использовании решения № 1. Так, меняя контекст сеанса мы приобретаем возможность регулировать объем выборки из одной и той же таблицы, не выполняя дополнительных подключений к БД.
Теперь можно посмотреть, как это работает:
SQL> CONNECT scott/tiger
Connected.
SQL> SELECT ename, loc FROM emp, dept WHERE emp.deptno = dept.deptno;
ENAME LOC ---------- ------------- CLARK NEW YORK
KING NEW YORK
MILLER NEW YORK
ALLEN CHICAGO
WARD CHICAGO
MARTIN CHICAGO
BLAKE CHICAGO
TURNER CHICAGO
JAMES CHICAGO
9 rows selected.
Действительно, мы видим сотрудников только двух отделов.
Если у вас получились ошибки в последнем предложении SELECT, причину можно уточнить в трассировочном файле в каталоге udump (обычно это $ORACLE_HOME/admin//udump).
В качестве упражнения создайте пользователя ADAM, дайте ему права на выборку из SCOTT.EMP и убедитесь, что политика доступа работает и для него.
Выше изложена суть организации «политики доступа» к строкам таблицы в ее очень простом исполнении. Однако разработчики Oracle предлагают и целый ряд дополнительных возможностей, призваных, по их мнению, сделать аппарат «политики» более востребованным. Насколько им удалось этого достичь – судите сами.
Возможности бесконечны- например, один из файлов определения средств называется oraclec.fdf и позволяет отслеживать действия в буферном кэше. После трассировки этих действий можно, с точностью до микросекунды, определить, какие блоки были загружены в кэш, в каком порядке, и какие блоки пришлось вытеснить из кэша, чтобы можно было их загрузить. (Я подозреваю, что дополнительные расходы далеко не всегда позволят использовать этот метод.)
Еще одна возможность трассировки, которая многим пригодиться, представлена файлом connect.fdf. Он перехватывает подключения и отключения сеансов, во многом аналогично тому, как работает команда audit session. Однако в трассировочном файле накапливается еще полдюжины дополнительных статистических показателей (таких как записи повторного выполнения), которые в таблицу aud$ не попадают; и в процессе накопления запись в базу данных не выполняется.
Можно добраться и до отдельного пользователя: можно нацелить oracle_trace на трассировку действий одного пользователя. Можно даже написать SQL-оператор, читающий результирующие таблицы и генерирующий файл, аналогичный создаваемому sql_trace. При этом можно будет также отслеживать момент регистрации, перехода с одного разделяемого сервера на другой и, наконец, выхода.
oracle_trace - это компонент сервера, собирающий информацию о событиях, используя сравнительно небольшие ресурсы.
Среди этих событий - ожидания, подключения, отключения, анализ и выполнение запросов, выборка строк, и некоторые другие.
Можно собирать информацию для всего экземпляра или только для определенных пользователей, событий или процессов; причем трассировку можно включать и отключать в любой момент.
Но одна из наиболее впечатляющих возможностей oracle_trace состоит в том, что можно организовать буферизацию собранной информации и сброс ее на диск большими блоками, вместо построчной выдачи. Более того, можно потребовать, чтобы файл с собранной инфрмацией был фиксированного размера и использовался повторно.
Есчтественно, сгенерировав файл с информацией, необходимо ее анализировать. Это можно сделать двумя способами - запустить программу, строящую по данным файла ряд текстовых отчетов, или запустить программу, читающую данные файла и сбрасывающую их в набор таблиц Oracle, по которым можно будет строить собственные отчеты.
Ну, и как oracle_trace поможет ответить на исходный вопрос?
Просто: один из классов событий, которые можно трассировать, - ожидания. Надо проверить, что сервер запущен в режиме, позволяющем включить трассировку, а затем потребовать от него (либо с помощью PL/SQL, либо из командной строки) начать трассировать ожидания (waits). При этом мы ограничиваем набор событий одижания только событием 92 (это buffer busy waits в Oracle 9i, но проверьте, на всякийц случай, значения столбцов event# и name из представления v$event_name в вашей системе). Затем остается сидеть и ждать примерно час в период, когда проблема ощущается острее всего. Когда получим достаточно большой файл трассировки, прекращаем трассировку, помещаем данные из файла трассировки в базу и выполняем SQL-оператор, запрашивающий, скажем, следующее:
Для каких объектов возникали события buffer busy waits, сколько приходилось ждать, как часто возникали ожидания и кто более всего пострадал?
Если смириться с дополнительными затратами ресурсов, можно при трассировке собирать даже ожидающие SQL-операторы, что позволит узнать, какие SQL-операторы больше всего пострадали от ожиданий.
Как найти объект, являющийся источником всех событий buffer busy waits, которые можно увидеть в представлении v$waitstat?
Все мы читали руководства по настройке производительности: "Если вы видите ... может потребоваться увеличить количество списков свободных мест (freelists) для проблемной таблицы". Но там не сказано, как найти эту самую проблемную таблицу.
Вариант 1: выполнять непрерывный поток запросов к представлению v$session_wait и проверять значения столбцов p1, p2, p3 при возникновении этого события. Статистически, рано или поздно вы получите таким образом обоснованное представление о том, какой объект или объекты являются причиной проблемы. Этот вариант - достаточно болезненный, и результат его отчасти зависит от везения.
Вариант 2: включить событие 10046 на уровне 8 и получить поток информации об ожиданиях в трассировочных файлах. Весьма серьезно нагружает систему и тоже требует некоторого везения.
Вариант 3: есть событие (10240), которое должно порождать в трассировочном файле список адресов блоков, которые мы ожидаем (ура!), но мне еще не удавалось заставить это событие работать. Если вы знаете, как это сделать, сообщите мне, поскольку данное решение, безусловно, является оптимальным.
Итак, не хотите ли вы получить список именно тех блоков, которых приходится ждать, с идентфикаторами ожидающих сеансов, причиной и продолжительностью ожидания, и все это- с минимальными затратами ресурсов? Именно это, помимо прочего, и позволяет получить oracle_trace.
Итак, что же мы сделали:
Создали файл конфигурации Начали сбор данных
Выполнили определенные действия в базе данных
Остановили сбор данных
Сформатировали набор данных
И что теперь?
Предположим, мы использовали файл конфигурации, представленный на рис. 2. Подключившись от имени учетной записи otrace, мы обнаружим строки в таблицах connection, disconnect и wait. Строки в таблице wait расскажут на все о событиях buffer busy waits, произошедших за время трассировки.
Например, мы могли выполнить SQL-оператор, представленный на рис. 4:
select p1 file_id, p2 block_id, p3 reason_code, count(*) ct, sum(time_waited)/100 secs
from wait group by p1, p2, p3 order by sum(time_waited) desc ; |
Рисунок 4: Пример запроса, позволяющий выявить наиболее продолжительные ожидания занятых блоков
Если необходимо большая точность, можно выдать все ожидания с временными отметками, и столбцом, (довольно оптимистично) названным timestamp_nano.
Если необходимо выяснить, каким пользователям пришлось ждать дольше всего, измените запрос, и суммируйте по столбцам session_index (SID) и session_serial (serial#). Для получения по значениям (session_index, session_serial) имени пользователя, имени машины, времени регистрации и т.п. можно использовать таблицу (синоним) connection.
Конечно, ничего (кроме снижения производительности) не мешает соединять эту таблицу с представлением dba_extents для преобразования идентификаторов файла и блока в типы и имена объектов.
А если необходимо выявить конкретные SQL-операторы, при выполнении которых пришлось ждать, всегда, хотя и ценой затраты еще больших ресурсов, можно перейти на использование файла sql_waits.fdf, который приводит к заполнению трассировочной информацией еще нескольких таблиц, которые затем можно соединять по столбцам session_index, session_serial, timestamp и timestamp_nano.
Наконец, если вы думаете, что затраты на загрузку данных в таблицы и построение отчетов отрицательно скажутся на системе, всегда можно перенести файлы cdf и dat на другую машину и обрабатывать их в другой базе данных. Мне удалось даже, с небольшими исправлениями, сгенерировать набор данных на экземпляре версии 9i, а затем обработать их на экземпляре версии 8i, просто чтобы доказать эту возможность. Это, конечно, затруднит возможность по номерам блоков определять объекты.
Джонатан Льюис,
Перевод
В сервер Oracle встроено множество диагностического кода. Часть его, например, sql_trace, хорошо описана в документации, а часть, например, представление x$trace, не документирована вовсе. Я люблю периодически посвящать некоторое время повторному анализу такого кода, чтобы узнать, насколько расширены его возможности, получили ли они официальное признание и описаны ли в документации. Недавно, работая с сервером Oracle 9i, я с удивлением обнаружил существенное расширение возможностей oracle_trace, которое произошло за последних пару релизов. Эта статья представляет собой краткое введение в oracle_trace и описание его возомжностей.
Есть много отличий, обычно связанных только с именами, между реализациями oracle_trace в версиях Oracle 8i и Oracle 9i. Эта статья написана исключительно на базе Oracle 9i.
Сначала надо установить ряд параметров инициализации, чтобы на сервере можно было включить трассировку, но не включать ее сразу. Список этих параметров представлен на рис. 1.
Обязательные oracle_trace_enable = true oracle_trace_collection_name = **
Стандартные значения oracle_trace_collection_size = 5242880 oracle_trace_collection_path = |
Рисунок 1: Параметры инициализации, связанные с oracle_trace
Параметру oracle_trace_collection_name нужно явно задать пустое значение "", ибо его стандартное значение - "oracle", а если имя набора указано и трассировка включена, сервер Oracle выполняет трассироку на уровне экземпляра с момента запуска (ого!).
Параметр oracle_trace_collection_path задает каталог, в котором будут размещаться файлы. В каталоге oracle_trace_facility_path размещаются списки событий, которые можно трассировать (facility definition files - файлы определения средств, предоставляемые Oracle Corporation). Параметр oracle_trace_facility_name задает список событий, которые нас интересуют. Наконец, можно ограничить размер (в байтах) файла с трассировочной информацией, задав значение параметра oracle_trace_collection_size.
После запуска сервера можно начинать сбор трассировочной информации.
В этой статье я буду использовать только средства командной строки, хотя есть и альтернативный PL/SQL-интерфейс (пакет dbms_oracle_trace_agent - прим. переводчика), и даже графический интерфейс, если купить соответствующий модуль для Oracle Enterprise Manager. Мы будем использовать команду следующего вида:
otrccol start 1 otrace.cfg
Команда otrccol - основной интерфейс для oracle_trace. Есть и другие команды, но большинство их возможностей были добавлены в otrccol. Очевидно, что параметр start требует начать трассировку (а параметр stop - ее остановить). Значение "1" - произвольно выбранный идентификатор задания, а otrace.cfg - файл конфигурации. Пример файла конфигурации представлен на рис. 2.
Используется для сбора данных col_name = jpl cdf_file = jpl dat_file = jpl fdf_file = waits.fdf max_cdf = -10485760 buffer_size = 1048576 regid = 1 192216243 7 92 5 d901 Используется для форматирования username = otrace password = otrace service = d901 full_format = 1 |
create user otrace identified by otrace default tablespace users -- если не используется 9i: -- temporary tablespace temp quota 100m on users; grant create session to otrace; grant create table to otrace; grant create sequence to otrace; grant create synonym to otrace; |
--
Эта статья первоначально была опубликована на сайте , сетевом портале, посвященном проблемам различных СУБД и их решениям.
Джонатан Льюис () - независимый консультант с более чем 15-летним опытом работы с СУБД Oracle. Он специализируется на физическом проектировании баз данных и стратегиях использования возможностей СУБД Oracle, является автором книги "Practical Oracle 8I - Designing Efficient Databases", опубликованной издательсвом Addison-Wesley, а также одним из наиболее широко известных лекторов по Oracle в Великобритании. Подробнее об опубликованных им статьях, презентациях и семинарах можно узнать на сайте , где также поддерживается список ЧаВО The Co-operative Oracle Users' FAQ
по дискуссионным группам Usenet, связанным с СУБД Oracle.
Вот тут, вероятно, и наступает решающий момент для систем оперативной обработки транзакций (ООТ - OLTP). Их ждет двойной удар - сначала в подчиненной таблице, а потом и в главной.
Возьмите таблицу из и вставьте в нее еще 9 одинаковых строк, чтобы всего их стало 10. Затем выполните следующие тесты и проверьте объем логического ввода/вывода и т.п.:
update t2 set id_gp = id_gp;
10 rows updated.
alter table t1 add constraint t1_pk primary key (id_gp);
alter table t2 add constraint t2_fk_p1 foreign key (id_gp) references t1;
update t2 set id_gp = id_gp; 10 rows updated
Вы обнаружите, что количество прочитанных блоков db block gets (current mode gets) увеличится на 10 после добавления ограничения целостности. Почему? Потому что при каждом обновлении сервер Oracle проверяет ограничение внешнего ключа, и делает это путем просмотра индекса по первичному ключу в главной таблице с помощью current mode gets. Если главная таблица будет достаточно большой, может потребоваться три current mode gets для каждого избыточного обновления столбца в подчиненной таблице.
Теперь перейдем к проблемам главной таблицы. Достаточно только попытаться выполнить обновление "без изменения" строки главной таблицы, если нет индекса по внешнему ключу, и вы обнаружите печально известную блокировку TM/4. Индексы по внешним ключам не обязательны, если значения первичного ключа не изменяются и не удаляются, но если вы сталкиваетесь со случайными "зависаниями" и сообщениях о взаимных блокировках, то, вероятно, вы столкнулись с классической проблемой, - вы сами первичные ключи не обновляете, а вот генератор приложений за кадром это делает.
Некоторые эксперименты с индексами должны быть более продуманными, поскольку для оценки всех затрат может иметь смысл учитывать логический ввод/вывод, а для этого - построить достаточно большую таблицу, чтобы индекс по ней был многоуровневым. Однако для некоторых тестов достаточно будет проверять объем данных отмены и повторного выполнения, и учитывать блокировки, оставляя в стороне такой тонкий момент, как объем логического ввода/вывода.
Итак, что же происходит при выполнении обновления без фактического изменения значения для столбца, входящего в простой индекс на основе B-дерева? Ничего. Сервер Oracle определяет, что проиндексированное значение не изменилось, и даже не обращается к индексу, не говоря уже про блокирование записи. Это верно и для простых индексов на основе битовых карт.
Вы можете усомниться, а не произойдет ли что-то ужасное при переходе на индексы по функции - не будет ли вызываться функция "на всякий случай", правильно ли отслеживает сервер Oracle зависимости между функциями и используемыми в них столбцами? Ответ: все работает правильно, никаких лишних вычислений функции или проходов по индексу не будет. В качестве теста можно создать такую же таблицу, как в , а затем выполнить следующие SQL-операторы:
create or replace function my_fun ( i1 in number, i2 in number ) return number deterministic as begin dbms_output.put_line('Testing function'); return i1 + i2; end; /
create index t2_idx on t2(my_fun(id_gp,id_p));
update t2 set id_gp = id_gp where rowid = '&m_rid';
update t2 set id_gp = id_gp + 1 where rowid = '&m_rid';
Вы увидите, что функция вызывается один раз (поскольку в таблице только одна строка), при создании индекса, но она не вызывается при обновлении без изменения значения. Кстати, при выполнении второго оператора update функция будет вызываться дважды- один раз для поиска исходного местонахождения в индексе, а второй - для вычисления нового. Вы можете обнаружить, что функция вызывается еще два раза при выполнении отката - я уверен, что сталкивался с этим в прежних версиях, когда индексы по функции только появились, но сейчас это больше не происходит.
Вы могли уже решить, что пора переписывать массу кода. Но, написание кода, генерирующего идеальный SQL-оператор каждый раз, повышает вероятность ошибок. Компромисс между повышенным риском ошибки (а также временем на кодирование, тестирование и отладку) и производительностью всегда будет, так что, если сервер далек до полной загрузки, вполне допустимо и обоснованно будет игнорировать все описанные выше проблемы. По крайней мере, в краткосрочной перспективе.
Есть и еще один, более тонкий компромисс. Если приложение генерирует идеальный SQL-оператор для каждого обновления, которое оно потенциально может сгенерировать конечное приложение, то существенно возрастает количество различных SQL-операторов в системе.
Теоретически, если в таблице есть N столбцов, тогда разных операторов update может быть power(2,N) - 1, и это если ограничиться только однострочными обновлениями по rowid. Если не увеличить соответственно разделяемый пул и не настроить несколько параметров, вроде session_cached_cursors, может оказаться, что экономия в одном месте оборачивается дополнительными проблемами (такими как конфликты доступа к библиотечному кэшу) в другом.
Было время, когда в SQL*Forms (так его тогда называли) было принято использовать единственный SQL-оператор обновления для блока. Этот оператор update обновлял (по значению rowid) каждый столбец таблицы, упоминающийся в блоке. Это казалось неплохой идеей, поскольку упрощало код и делало его более эффективным на клиенте: не нужно было решать вычислительно сложную задачу определения действиетльно измененных полей и динамически формировать SQL-оператор для обновления только соответствующих столбцов в базе данных.
Потом, в районе версии Forms 4.5 (я могу ошибаться с версией - жду поправок), корпорация Oracle добавила флаг, который можно устанавливать для выбора либо одного оператора, "обновляющего все", либо динамически генерируемого оператора "обновлять только минимальный набор столбцов". Какая из этих опций лучше?
Дополнительный объем данных отмены и повторного выполнения - это еще не обязательно самая большая проблема - в конечном итоге, дополнительно генерируемые и буферизуемые данные зачастую не так уж велики по сравнению с базовыми накладными расходами. Более того, поскольку архитектура сервера Oracle такова, что записи на диск, по возможности, выполняются фоновыми "асинхронными" процессами, конечный пользователь не часто ощущает замедление из-за записи на диск. Но есть еще ряд нюансов, непосредственно влияющих на производительность системы с точки зрения конечных пользователей.
Как вы думаете, что делает сервер при обновлении столбца без реального изменения со следующими объектами:
Срабатывают ли строчные триггеры типа 'update of {список_столбцов}'?
before row
after row
instead of Изменяются ли индексы, включающие такой столбец?
Что, если это индексы на основе B*-дерева?
А как насчет индексов на основе битовых карт?
Что будет с индексами по функции (function-based indexes)?
Как сервер будет обеспечивать целостность ссылок?
Если этот столбец - подчиненный?
Если этот столбец - главный?
В частности, нас будет интересовать, сколько стоит обновление столбца, если его значение не меняется. Если бы сервер мог выявить, что при обновлении реально ничего не меняется, то дополнительные расходы ресурсов на лишнее обновление были бы минимальны. К сожалению, сервер и не пытается выявлять "лишние" обновления. В конечном итоге, логично предполагать, что при обновлении данные должны меняться. Было бы контрпродуктивно добавлять проверку условия, которое почти всегда будет истинным, просто чтобы немного сэкономить в тем "весьма редких и странных" случаях, когда при обновлении изменения не происходят.
Итак, что же может произойти при обновлении одного столбца в таблице в отдельной транзакции? Понятно, что строку надо заблокировать и данные изменить, а для этого - получить запись списка заинтересованных транзакций (Interested Transaction List - ITL) в блоке. Необходимо захватить слот таблицы транзакций (transaction table slot) в заголовке сегмента отмены (undo segment header) для использования в качестве глобально видимой "ссылки" на транзакцию, а также внести запись отмены в блок отмены, описывающую, как отменить изменения, только что выполненные в блоке данных. Изменения во всех трех блоках необходимо записать в журнал повторного выполнения (первоначально - в буфер журнала), и в этом простом случае потребуется только одна запись повторного выполнения (redo record).
Затем, при фиксации транзакции в слоте таблицы транзакций записывается соответствующее значение номера системного изменения (commit SCN) и он помечается как свободный, а адрес использованного блока отмены тоже можно записать в пул свободных блоков в блоке заголовка сегмента отмены. Эти изменения в блоке заголовка сегмента отмены записываются в журнал повторного выполнения (в буфер), а для сброса буфера журнала на диск вызывается процесс записи журнала (log writer process - lgwr), после чего пользовательский процесс уведомляют, что транзакция успешно зафиксирована. (Oracle может, а в этом случае, скорее всего, и будет также очищать измененный блок данных, но не будет записывать выполненные при очистке изменения в журнал повторного выполнения).
Джонатан Льюис,
Перевод
На рынке есть несколько генераторов приложений, поддерживающих базовый подход к разработке "чем проще, тем лучше". Простой код легче генерировать и проще сопровождать, даже если он кажется несколько менее эффективным. Но если генератор форм всегда генерирует код для обновления каждого столбца в таблице, даже если пользователь меняет всего лишь одно поле в форме, насколько при этом растет нагрузка на сервер базы данных?
Создадим простую таблицу с триггером и выполним действия, представленные ниже в листинге 1:
Листинг 1
create table t2 ( id_gp number(4), id_p number(4), n2 number(4) ); insert into t2 values (1,1,1); commit;
create or replace trigger t2_bru before update of id_gp on t2 for each row -- when ( -- new.id_gp != old.id_gp --or new.id_gp is null and old.id_gp is not null --or old.id_gp is null and new.id_gp is not null -- ) begin dbms_output.put_line('Updating'); end; /
column rid new_value m_rid
select rowid rid from t2 where rownum = 1;
update t2 set id_gp = id_gp where rowid = '&m_rid';
Триггер срабатывает. То же самое происходит и с триггером after-row update. Подтверждение моего предположения, что сработает и триггер instead of оставляю читателю в качестве упражнения.
Фактически, строчный триггер before генерирует одну дополнительную запись отмены и одну дополнительную запись повторного выполнения, даже если ничего при этом не делает из-за добавления достаточно сложной конструкции when, которая в примере закомментирована. Так что, если есть выбор, немного эффективнее будет использовать строчные триггеры after.