tag:blogger.com,1999:blog-52804123118126665022024-03-05T01:38:19.460-08:00 Life in OracleLife in OracleIgor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.comBlogger82125tag:blogger.com,1999:blog-5280412311812666502.post-36559294310007072032020-12-27T08:08:00.007-08:002020-12-27T08:20:25.365-08:00RACChecker 21.1 Released!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcjYJqTM_yp2qniHB_jEzO7a-pop9qgyhNetKSSvBRD2EwiPQdBvFd0xbEjz7VyzjP9qP78Gve40pUEWXCM_osQ89eEngcMVnOQ7bLuraNT3-3OqG4CLdjraagBZ6nofavemLH1AePN3tY/s1600/racchecker.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcjYJqTM_yp2qniHB_jEzO7a-pop9qgyhNetKSSvBRD2EwiPQdBvFd0xbEjz7VyzjP9qP78Gve40pUEWXCM_osQ89eEngcMVnOQ7bLuraNT3-3OqG4CLdjraagBZ6nofavemLH1AePN3tY/s320/racchecker.jpg" width="320" height="306" /></a></div>
Спешу сообщить, что выпущена новая версия утилиты RACChecker, которая предназначена для проверки готовности приложения к миграции в среду Oracle Real Application Cluster.<br>
Появилось ряд новых возможностей, которые я добавил по просьбе трех крупных заказчиков:
<ul>
<li>для работы утилиты теперь необходим ODP.Net 19c, который входит в состав <a href="https://www.oracle.com/database/technologies/oracle19c-windows-downloads.html#license-lightbox">Oracle Client 19c for Windows</a>;<br><br>
<li>новый параметр CHECK_JOB_NO_CLASS, включает проверку на наличие заданий DBMS_SCHEDULER, которые не привязаны к сервису, то есть не привязаны ни к какому JOB CLASS; <br><br>
<li>при включенном параметре CHECK_V$VIEWS (проверка на использование V$-представлений в PL/SQL-коде приложения), теперь выводится не просто имя PL/SQL-процедуры и номер строки, но и имя используемого V$-представления, например:
<pre> Checking v$-views issue
found in procedure TEST_RACCHECKER_VDOLLAR - line 9 ("V$SESSION")
found in procedure TEST_RACCHECKER_VDOLLAR_WRAP - (wrapped!) - ("V$INSTANCE")
Finish check this issue
</pre>
обратите, кстати, внимание, что в втором случае - номера строки нет, потому-что исходная процедура зашифрована (wrapped) - утилита обнаружила факт использования представления V$INSTANCE через зависимости! ;<br><br>
<li> новый недокументированный параметр _SKIP_INVALID_OBJECTS позволяет пропустить проверку объектов, которые находятся в состоянии INVALID;<br>
Да,да - RACChecker имеет недокументированные параметры! Посмотреть их можно, указав ключ "_HELP=Y" при запуске утилиты;<br><br>
<li> новый параметр CREATE_SAMPLE_CONFIG позволяет сгененировать простой файл конфигурации sample_config.cfg, - для дальнейшей его модификации;<br><br>
<li> теперь утилита поддерживает более 1000-пакетов (packages)- в предыдущих версиях происходило "падение" утилиты по ошибке переполнения, если в БД в одной смехе присутствовало более 1000 пакетов; <br><br>
<li> проверка на использование директорий (Oracle directory) включена по умолчанию (CHECK_DIRS=Y). <br>
</ul>
Подробно требования к приложению описаны в свежем документе <a href="https://www.oracle.com/technetwork/database/options/clustering/overview/racappdevbp-3124851.pdf">"Application Development Best Practices for Oracle Real Application Clusters (RAC) - Developer’s Checklist"</a>.
<br><br>
<b>Ссылка для скачивания: </b><a href="https://drive.google.com/uc?confirm=no_antivirus&id=1IZFczdB2HAqY4tOkzeKci2lT-BH7hiMX">RACChecker</a>.
<br><br><br>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-3288006470488478232017-02-17T05:08:00.001-08:002017-02-17T05:13:47.028-08:00Oracle Database 12.2 New Features content<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHBIxWwnFcEi_ItQv9OwIqU5ZVvYYMJqfjhnBS7vVc31QKhmfjrx021-obhXqbiFtEGv0D0r29gsEPkZMIc7rXfIKFy_cJxYPAnf2GN-cxAbTkAYY1Y8JWLMMufPfk7NUljjy-78-eQA7A/s1600/IMG-20161130-WA0000.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHBIxWwnFcEi_ItQv9OwIqU5ZVvYYMJqfjhnBS7vVc31QKhmfjrx021-obhXqbiFtEGv0D0r29gsEPkZMIc7rXfIKFy_cJxYPAnf2GN-cxAbTkAYY1Y8JWLMMufPfk7NUljjy-78-eQA7A/s320/IMG-20161130-WA0000.jpg" width="320" height="240" /></a></div>
Материалы нашего семинара по новым возможностям Oracle Database 12c Release 2 можно скачать по следующей ссылке:
<a href="http://www.oracle.com/us/dm/se0100586871-emea-ru-ip-ipi1-ie2-ru-3398030-ru.html">Oracle Database 12c Release 2</a>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-20249086358940984022016-07-29T03:09:00.001-07:002020-12-27T08:11:03.575-08:00RACChecker - check application for RAC compatible<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcjYJqTM_yp2qniHB_jEzO7a-pop9qgyhNetKSSvBRD2EwiPQdBvFd0xbEjz7VyzjP9qP78Gve40pUEWXCM_osQ89eEngcMVnOQ7bLuraNT3-3OqG4CLdjraagBZ6nofavemLH1AePN3tY/s1600/racchecker.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcjYJqTM_yp2qniHB_jEzO7a-pop9qgyhNetKSSvBRD2EwiPQdBvFd0xbEjz7VyzjP9qP78Gve40pUEWXCM_osQ89eEngcMVnOQ7bLuraNT3-3OqG4CLdjraagBZ6nofavemLH1AePN3tY/s320/racchecker.jpg" width="320" height="306" /></a></div>
Тема разработки и адаптации приложений под RAC очень обширна и многогранна и затрагивает практически все аспекты создания прикладного ПО для СУБД Oracle Database.
Но, тем не менее, для того чтобы гарантировать что ваше приложение корректно будет работать в RAC, необходимо убедиться, что оно не использует технологии и механизмы которые в RAC в не работают, либо работают с особенностями.
Подробно требования к приложению описаны в документе <a href="http://www.oracle.com/technetwork/database/availability/racdbawareapplications-1933522.pdf
">"Oracle RAC Database aware Applications - Developer’s Checklist"</a>.
Вот перечень этих технологий: <ul><li>каналы (пакет DBMS_PIPE) - не синхронизируются между узлами кластера;<br /><br /></li>
<li>объекты БД типа DIRECTORY (каталоги в файловой системе) должны располагаться на разделяемом сторадже и должны быть видны всем узам кластера;<br /><br /></li>
<li>вместо V$-представлений нужно использовать соответствующие GV$-представления;<br /><br /></li>
<li>задания управляемые через пакет DBMS_JOB - крайне не рекомендуется использовать в RAC, поскольку задания этого пакета не поддерживают сервисы.<br /><br /><br />Методы борьбы с вышеперечисленными технологиями мы подробно рассматривали на культовом семинаре "RAC Deep Dive for Developers"<br /><br />Довольно часто приложение имеет большие объемы PL/SQL-кода (сотни тысяч и даже миллионы строк кода), и вспомнить о том, в каком месте используется тот же DBMS_PIPE крайне сложно: код давно отлажен и работает, а его автор уже давно не работает в компании.<br />Для того, что облегчить анализ серверной части кода (хранимых процедур PL/SQL) мною была разработана утилита <a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XSEd4MmIxRTRKa2s">RACChecker</a>. Эта утилита поможет быстро ответить на вопрос: готово ли, в минимальной степени, ваше приложение при переходе в RAC.<br />RACChecker анализирует ваш исходный код и находит объекты и строки кода, где вы используете технологии, которые в RAC не работают.<br /><br /></li></ul>
<pre>
C:\RAC\Utils\RACChecker>RACChecker.exe help=y
RAC Checker: Release 12.2.0.1.0 - Production on 15.04.2015 11:07:13
Utility for check support Oracle DB for RAC and Exadata
Copyright (c) 2016 Igor Melnikov. All rights reserved.
You can control how RACChecker runs by entering the RACChecker command followed
by various arguments. To specify parameters, you use keywords:
Format: RACChecker parameter=value TYPE=value
Example: RACChecker USERID=scott/tiger@orcl TYPE=PIPE
RACChecker USERID=demo/demo@demo TYPE=ALL
Keyword Description (Default)
--------------------------------------------------
SCHEMAS schemas in which check ALL-for all schemas (ALL)
HELP print this message: Y/N (N)
TYPE object type: PIPE,JOB,ALL (ALL)
REPORT_FILE file name for output report
PARFILE parameter file name
SEQUENCES Show NON-cached sequences (Y)
MIN_SEQ_CACHE Check for sequences on minimum cache size (20)
SEQ_ORDERED Check for sequences which are ordered (N)
SAVE_SOURCE Save sources for "bad" objects (N)
DIR_SOURCE Directory where sources will be save
SEQ_DDL_OPT Generate sequence ddl-optimization for RAC: CACHE,ORDER,BOTH,NONE (NONE)
CHECK_DIRS Check directory objects (for shared dir issue) (N)
CHECK_V$VIEWS Check v$-views usage (Y)
USERID Oracle connection string
</pre>
<br /><p><br />Я думаю, что из списка параметров очевидно их назначение.<br />
Следует обратить внимание лишь на следующие моменты: </p><ul>
<li>пользователь в строке подключения (параметр USERID) должен иметь права на чтение словаря (dictionary);<br /><br /></li>
<li>утилита опционально может находить некэшируемые последовательности (с ними тоже возможны проблемы в RAC);<br /><br /></li>
<li>возможна выгрузка DDL-скриптов для плохих объектов с помощью параметра SAVE_SOURCE=Y;<br /><br /></li>
<li>для своей работы утилита требует установленной среды выполнения .NET Framework 4.5, а также <a href="http://download.oracle.com/otn/other/ole-oo4o/ODAC121024Xcopy_x64.zip">ODP.NET Provider 12.1.0.2.4</a> - рекомендуется установить версию поставляемую с Instant Client - она небольшая по размеру.<br /></li></ul><p></p>
<p>
Конечно, никакого волшебства в работе этой утилиты нет: она всего лишь анализирует соответствующие представления словаря.<br />
</p>
<p>
Утилита может находить факт использования неработающих в RAC технологий (например: пакет DBMS_PIPE), даже если PL/SQL-код зашифрован (wrapped). Утилита на "лету" определяет что код зашифрован, и в этом случае анализирует не исходный код, а зависимости от пакетов dbms_pipe,dbms_job. <br />
Утилита НЕ может обнаружить факт использования этих пакетов только в одном случае: если они используются через динамический PL/SQL (EXECUTE IMMEDIATE или DBMS_SQL) и код зашифрован.
</p>
Утилита определяет факт использования пакетов внутри однострочных коментариев. Это не приводит к ложному срабатыванию. Многострочные комментарии, к сожалению, не поддерживаются.
При анализе последовательнойстей можно задать минимальный размер их кеша (параметр MIN_SEQ_CACHE). В этом случае будут выведены все последовательности, размер кэша которых меньше этого минимума.
<p>
За время своего существования утилита RACChecker постоянно развивалась, и помогла очень многим заказчикам перенести свои существующие приложения в среду Oracle Real Application Cluster.
</p>
<p>
C помощью RACChecker вы быстро определите проблемные места при переходе в RAC!<br /><br />
</p>
Ссылка для скачивания: <a href="https://drive.google.com/uc?confirm=no_antivirus&id=1IZFczdB2HAqY4tOkzeKci2lT-BH7hiMX">RACChecker</a>.<br /><br />
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-71719608494391226192016-04-12T05:15:00.002-07:002016-04-12T05:15:53.400-07:00Real-Time Database Operation Monitoring в Oracle Database 12c<p>
Технология мониторинга SQL-запросов в режиме реального времени (<a href="http://www.oracle.com/technetwork/database/manageability/sqlmonitor-084401.html">Real-Time SQL Monitoring </a>), которая появилась в Oracle Database 11g, позволяет администраторам и разработчикам взглянуть внутрь каждого долго выполняющего запроса. <br>
Для каждого долго выполняющегося запроса можно увидеть его реальный план выполнения, количество обработанных строк, расхождение ожидаемой и фактической кардинальности (количество ожидаемых и количество фактических строк) на каждом шаге плана запроса.
Также можно увидеть различные метрики SQL-запроса: CPU, I/O requests, throughput, PGA, temp space. <br>
В том числе можно производить мониторинг статистики ввода-вывода для каждого шшага запроса.<br>
</p>
В свое время технология <i>Real-Time SQL Monitoring</i> была большим шагом вперед для ответа на вопрос "Что реально происходит в базе данных?".<br>
<p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM570bL9x55FzilqKKfZE2x8GCKlVNqeDbQ641P5syjHiCuOGlremaZYu5g3EroNQDFX6dBBolDbCtl8CwTmrMIFohpeRDDKCwXFvl071N9_Vs8DM1dtlEZUTREo8TaBJQdKkWS3xTq6o7/s1600/112589.jpg" imageanchor="1" style="clear: left; float: center; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM570bL9x55FzilqKKfZE2x8GCKlVNqeDbQ641P5syjHiCuOGlremaZYu5g3EroNQDFX6dBBolDbCtl8CwTmrMIFohpeRDDKCwXFvl071N9_Vs8DM1dtlEZUTREo8TaBJQdKkWS3xTq6o7/s320/112589.jpg" /></a></div>
<center><i>Рис 1. Мониторинг выполнения запроса с помощью Real-Time SQL Monitoring</i></center>
</p>
Вместе с тем, вышеописанная технология позволяет производить мониторинг только на уровне отдельного запроса.
Очень часто необходимо отслеживать выполнение на уровне отдельных бизнес-операций в приложении.
Поскольку бизнес-операция, в приложении состоит из нескольких запросов, приходиться вручную сопоставлять выполняющиеся запросы к конкретной бизнес-операции, например: "Расчет зарплаты".
Особенно актуальной эта задача становится при возникновении проблем с производительностью кричичных для бизнеса операций.<br>
<p>
Рассмотрим такой типичный случай.<br>
При возникновении проблемы с производительностью расчета зарплаты, конечный пользователь обращается к администратору СУБД. DBA должен среды сотен (возможно и тысяч!) выполняющихся запросов, выделить запросы относящиеся к расчету зарплаты, выяснить какие из них сейчас выполняются и, затем, наконец, разобраться в причинах медленной работы этой бизнес-операции.<br>
Для идентификации запросов часто приходится обращаться к разработчикам приложения и анализировать его исходный код. Все это часто приводит к взаимным обвинениям администраторов и разработчиков.<br>
Не правда-ли: знакомая картина?
</p>
СУБД Oracle Database 12c предлагает решение и этой проблемы, позволяя производить мониторинг на уровне составных бизнес-операций.<br>
Эта технология получила название <a href="https://docs.oracle.com/database/121/TGSQL/tgsql_monit.htm#TGSQL94586">Real-Time Database Operation Monitoring</a>, и позволяет осуществлять мониторинг в режиме реального времени в терминах бизнес-процессов (бизнес-операций) выполняющихся в данный момент в СУБД.<br>
Очевидно, что СУБД ничего "не знает" про бизнес-процессы, и для этого приложению необходимо каким-либо образом сообщить об этом базе данных: сгруппировать обращения к СУБД в бизнес-операции.
<br><br>
Для того, чтобы выделить в потоке обращений к СУБД бизнес-операцию, предлагается специальный API (Application Program Interface), реализованный в виде PL/SQL-пакета <a href="http://docs.oracle.com/database/121/ARPLS/d_sql_monitor.htm#ARPLS74779">DBMS_SQL_MONITOR</a>.<br>
Пакет DBMS_SQL_MONITOR стандартно поставляется в составе СУБД и устанавливается по умолчанию - то есть входит в состав стандартных системных пакетов Oracle Database 12с.<br>
Для выделения начала бизнес-операции предназначена процедура <i>BEGIN_OPERATION</i> данного пакета, для окончания бизнес-операции - <i>END_OPERATION</i>.
<br></br>
Возвращаясь к вышеописанному примеру с расчетом заработной платы, ее мониторинг в исходном коде хранимой PL/SQL-процедуры может быть оформлен следующим образом:
<code><pre>
CREATE PROCEDURE calc_salary(v_pDep IN NUMBER) IS
v_xDBOpId NUMBER;
BEGIN
v_xDBOpId := dbms_sql_monitor.begin_operation('Расчет зарплаты',
forced_tracking => 'Y');
prepare_calc();
main_calc();
finish_calc();
dbms_sql_monitor.end_operation('Расчет зарплаты', v_xDBOpId);
END;
</pre></code>
Параметр <i>forced_tracking</i> процедуры <i>BEGIN_OPERATION</i> аналогичен хинту <i>MONITOR</i> в запросе: при его установке (forced_tracking => 'Y'), мониторинг бизнес-операции производится в любом случае. В противном случае - мониторинг производится только в случае, если бизнес-операции по продолжительности выполнения занимает 5 и более секунд ЦПУ или ввода-вывода.
Запустим наш модифицированный бизнес-процесс расчета зарплаты и посмотрим, как он теперь отображается на экране SQL Monitoring консоли администрирования Enterprise Manager 12c.
В списке выполняющихся запросов появился запрос c "говорящим" именем "Расчет зарплаты":<br><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6PuEcoZrlfq8i0ocd2kmlVFe2anahuWUxevgTLHoCyoeX1trU_cVad7CHuMgFdYX3kpEmRz2C10HtLLDIN8A34heEP7guFdVo-GGXeoBuXCFz-MyuKm-0z3MUcXsTFa7UoCE7HMkX4S_6/s1600/em12c.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6PuEcoZrlfq8i0ocd2kmlVFe2anahuWUxevgTLHoCyoeX1trU_cVad7CHuMgFdYX3kpEmRz2C10HtLLDIN8A34heEP7guFdVo-GGXeoBuXCFz-MyuKm-0z3MUcXsTFa7UoCE7HMkX4S_6/s320/em12c.jpg" /></a></div>
<center><i>Рис 2. "Расчет зарплаты" в списке запросов на экране SQL Monitoring</i></center>
<br>
Перейдя внутрь выполняющейся бизнес-операции - для этого нужно кликнуть мышью на SQL_ID операции (в нашем случае: "Расчет зарплаты"), можно увидеть страницу детальной информации: какие запросы из состава бизнес-операции уже выполнились, и какой запрос является текущим - выполняется в данный момент:<br><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifKlKcLjfrGll7zPQoq2su_U7-V5V6Z3g-T615Viek0L2r2_roj6x6M1UyzycrRPYnkVRd0oC1-EZogYI-0Zo187n12Lzcwnvk-q0jM6_GbF1gqJZbuS03njd_9x8ABueSNu6rTXSKxKPm/s1600/em_op1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifKlKcLjfrGll7zPQoq2su_U7-V5V6Z3g-T615Viek0L2r2_roj6x6M1UyzycrRPYnkVRd0oC1-EZogYI-0Zo187n12Lzcwnvk-q0jM6_GbF1gqJZbuS03njd_9x8ABueSNu6rTXSKxKPm/s320/em_op1.jpg" /></a></div>
<center><i>Рис 3. Детальная информация о выполнении бизнес-операции</i></center>
<br>
"Провалившись" внутрь любого запроса в бизнес-операции, можно увидеть знакомый по предыдущим версиям экран SQL-мониторинга запросов.
<br>
<br>
После завершения бизнес-операции входящие в него запросы точно также доступы для анализа, как это и было раньше (в СУБД Oracle Database 11g) для уже завершившихся SQL-запросов.
<br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzN-xvIdbCLMEA_a9mng6Ktu99EFJ7MX-j-JQGgu6SKEdkgQOVCBpQMcqAJ0NAycLEUAZAvM1x8mueqbNl7EWwYv8WgThrcgQL0LRerN2OD0QgQozhhVZ5XjhjFrOrjAYy7PbWyk0lH9c-/s1600/op_finish.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzN-xvIdbCLMEA_a9mng6Ktu99EFJ7MX-j-JQGgu6SKEdkgQOVCBpQMcqAJ0NAycLEUAZAvM1x8mueqbNl7EWwYv8WgThrcgQL0LRerN2OD0QgQozhhVZ5XjhjFrOrjAYy7PbWyk0lH9c-/s320/op_finish.jpg" /></a></div>
<center><i>Рис 4. Бизнес-операция "Расчет зарплаты" завершена</i></center>
<p>
Для того, чтобы сгруппировать запросы в бизнес-операции из приложений Java и С++/C-приложений, соответствующий клиентский API доступа к БД (<a href="http://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#JJDBC29008">JDBC</a> и <a href="http://docs.oracle.com/database/121/LNOCI/oci16rel001.htm#LNOCI17123">OCI</a>, соответственно) также был расширен.<br>
Вот так, например, выглядит выделение бизнес-операции в Java-приложении:
</p>
<code><pre>
Connection conn = DriverManager.getConnection(myUrl, myUsername, myPassword);
conn.setClientInfo("E2E_CONTEXT.DBOP", “Расчет зарплаты");
Statement stmt = conn.createStatement();
stmt.execute(v_xSQLQuery1);
... ... ... ...
... ... ... ...
conn.setClientInfo("E2E_CONTEXT.DBOP", null);
</pre></code>
Если Вы разрабатываете приложение сразу для разных версий СУБД Oracle Database, то можете воспользоваться условной компиляцией PL/SQL, чтобы иметь один и тотже код в независимости от версии БД:
<code><pre>
create procedure calc_salary(v_pDepartmentId in number) is
v_xDBOpId NUMBER;
begin
$if dbms_db_version.ver_le_11_2 $then
$else
v_xDBOpId := dbms_sql_monitor.begin_operation('Расчет зарплаты',
forced_tracking => 'Y');
$end
v_gCurrentDepartmentId := v_pDepartmentId;
prepare_calc();
main_calc();
finish_calc();
$if dbms_db_version.ver_le_11_2 $then
$else
dbms_sql_monitor.end_operation('Расчет зарплаты', v_xDBOpId);
$end
end;
</pre></code>
Объявление переменной v_xDBOpId нет смысла обрамлять в символ условной компиляции,поскольку при компиляции в СУБД Oracle Database 11g, PL/SQL-оптимизатор удалит её из исходного кода, поскольку она является "мертвой" - нигде не используется.
<br><br>
<i>Продолжение следует ...</i>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com2tag:blogger.com,1999:blog-5280412311812666502.post-56982927834201647162015-05-02T14:23:00.001-07:002015-05-02T14:23:42.739-07:00Новые возможности в динамическом SQL в Oracle 12c (передача переменных PL/SQL типов)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZIqoMRDbn5XYh-opdFJh-r4V2gSAup-kKA3rND5BqdoKAG6y1zqWqAALTNuuQxBF7TzyDMLwjUOzPABv17jiHe9BufQ_kj5BOMcMZit0eWGkPyPvlmjIix4KfUyL5sAgBpbH-9BIe44Uv/s1600/rROUxpvvDXQ.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZIqoMRDbn5XYh-opdFJh-r4V2gSAup-kKA3rND5BqdoKAG6y1zqWqAALTNuuQxBF7TzyDMLwjUOzPABv17jiHe9BufQ_kj5BOMcMZit0eWGkPyPvlmjIix4KfUyL5sAgBpbH-9BIe44Uv/s320/rROUxpvvDXQ.jpg" /></a></div>
И, наконец, последняя новая возможность в динамическом SQL, которая появилась в Oracle Database 12c.<br>
<p>
Последняя, не по значимости, а по порядку изложения! <br>
Стоит отметить, что она имеет очень большую практическую ценность, - и, по большому счету, ее очень не хватало.
</p>
Существенным ограничением до Oracle Database 12c являлась невозможность передачи в динамический код переменных, которые имеют PL/SQL-типы.<br>
Если рассмотреть нижеприведенный анонимный блок, выполненный в среде Oracle Database 11g (11.2.0.4):
<code><pre>
[oracle@localhost]$ <b>sqlplus rscott/rtiger</b>
SQL*Plus: Release 11.2.0.4.0 Production on Sun May 3 00:07:27 2015
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> <b>DECLARE
b BOOLEAN;
BEGIN
EXECUTE IMMEDIATE
'begin :x := true; end;'
USING
OUT b;
END;
/</b>
OUT b;
*
ERROR at line 7:
ORA-06550: line 7, column 9:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored
SQL>
</pre></code>
можно увидеть, что ошибка при передаче в динамический блок кода возникает даже когда переменная типа BOOLEAN передается именно в PL/SQL-блок.
<p>Очевидно, что исполняющая среда PL/SQL предполагает, что исполняться будет именно SQL-выражение. </p>
<p>
Для того, чтобы обойти это ограничение, приходилось применять вот примерно такой дорогостоящий workaround, связанный с преобразованиями значения из PL/SQL-типа в SQL-тип, и затем обратно:
</p>
<code><pre>SQL><b> create function CharToBoolean(v_pValue in char) return boolean is
begin
if v_pValue = 'Y' then
return true;
end if;
return false;
end;
/
</b>
Function created.
SQL><b> create function BooleanToChar(v_pValue in boolean) return char is
begin
if v_pValue then
return 'Y';
end if;
return 'N';
end;
/</b>
Function created.
SQL><b> DECLARE
b BOOLEAN;
s char(1);
BEGIN
EXECUTE IMMEDIATE
'begin :x := BooleanToChar(true); end;'
USING
OUT s;
b := CharToBoolean(s);
END;
/</b>
PL/SQL procedure successfully completed.
SQL>
</pre></code>
Конечно-же, это усложняло понимание кода и дальнейшее его сопровождение.
<p>Наконец-то, это ограничение снято в Oracle Database 12c, и приведеный выше первоначальный код теперь выполняется без ошибок:<p>
<code><pre>[oracle@localhost Desktop]$ <b>sqlplus / as sysdba</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sun May 3 00:10:28 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL><b> DECLARE
b BOOLEAN;
BEGIN
EXECUTE IMMEDIATE
'begin :x := true; end;'
USING
OUT b;
END;
/</b>
PL/SQL procedure successfully completed.
SQL>
</pre></code>
Причем теперь, стало возможным передавать в динамический блок кода не только переменные типа BOOLEAN, но также PL/SQL-записи и PL/SQL-массивы:
<code><pre>SQL> <b>create or replace package Account_service is
type
TArrayOfVarchar2 is table of Varchar2(32) index by pls_integer;
end;
/</b>
Package created.
<b>set serveroutput on
DECLARE
v_xArray Account_service.TArrayOfVarchar2;
BEGIN
v_xArray(1) := 'First'; v_xArray(2) := 'Second';
EXECUTE IMMEDIATE
'begin
for v_xIndex in 1..:v_xCount
loop
dbms_output.put_line(:v_pArray(v_xIndex));
end loop;
end;'
USING
IN v_xArray.Count,v_xArray;
END;
/</b>
First
Second
PL/SQL procedure successfully completed.
SQL></pre></code>
Также поддерживается ситуация, когда передача параметра, имеющего PL/SQL, производится в SQL-выражение:
<code><pre>
SQL><b> create or replace function printArray(v_pArray in Account_service.TArrayOfVarchar2) return number is
begin
for v_xIndex in 1..v_pArray.count
loop
dbms_output.put_line(v_pArray(v_xIndex));
end loop;
return 1;
end;
/</b>
Function created.
SQL><b>DECLARE
v_xArray Account_service.TArrayOfVarchar2;
n number;
BEGIN
v_xArray(1) := 'First'; v_xArray(2) := 'Second';
EXECUTE IMMEDIATE
'SELECT printArray(:v_pArray) FROM dual'
INTO
n
USING
IN v_xArray;
END;
/</b>
First
Second
PL/SQL procedure successfully completed.
SQL>
</pre></code>
К сожалению, хэш-массивы (PL/SQL-массивы c INDEX BY VARCHAR2) пока не поддерживаются.<br>
<br>
И необходимо помнить, что динамический блок кода не является замыканием (closure), то есть используемый тип должен быть определен на уровне всей схемы - в спецификации пакета.
</br>
<p>
Поддержка передачи (и возвращения тоже!) в динамический SQL переменных имеющих PL/SQL-типы - это новая впечатляющая возможность Oracle Database 12c,
которая позволяет упростить Ваш код, тем самым сделать его более читабельным и легким в сопровождении.
</p>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com3tag:blogger.com,1999:blog-5280412311812666502.post-83264942860328304412015-01-24T12:22:00.001-08:002015-01-24T12:27:56.066-08:00Новые возможности в динамическом SQL в Oracle 12c (возврат "неявного" курсора)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjJxeUNBm6MOMb3EpeTY-5vvGoFDJmfzwT9UXJL_9EZKe8wOnT_iBkL7bIqLMCj8v8dazj3_5Fw5P50G47e_G6kx7EmVM3yhyphenhyphenIzpgOl0Y373hUi38kkx0MHsgurfobbcdMZFecL7KwWAT/s1600/migs.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjJxeUNBm6MOMb3EpeTY-5vvGoFDJmfzwT9UXJL_9EZKe8wOnT_iBkL7bIqLMCj8v8dazj3_5Fw5P50G47e_G6kx7EmVM3yhyphenhyphenIzpgOl0Y373hUi38kkx0MHsgurfobbcdMZFecL7KwWAT/s320/migs.JPG" /></a></div>В некоторых СУБД есть возможность вернуть из хранимой функции непосредственно набор данных. Например, в СУБД MS SQL Server возможен такой код хранимой процедуры на T-SQL:
<code><pre>
CREATE PROCEDURE my_proc1
AS
BEGIN
SELECT * FROM accounts_amounts WHERE Amount >= 20000
END
</pre></code>
Далее, клиентские библиотеки, на стороне приложения, могут такой "неявный" курсор прочитать.<br><br>
Как вы хорошо знаете, такой возможности в СУБД Oracle Database нет: хранимая процедура не может вернуть просто запрос.
Необходим возврат ссылки на курсор (<i>ref cursor</i>): через OUT-переменную, либо как результат возвращаемый хранимой функцией.<br><br>
Например:<code><pre>
CREATE OR REPLACE PACKAGE my_types IS
TYPE
Taccounts_amounts_cur is ref cursor;
END;
/
CREATE PROCEDURE my_proc1(v_xRes in out my_types.Taccounts_amounts_cur) IS
BEGIN
OPEN v_xRes FOR
SELECT * FROM accounts_amounts WHERE Amount >= 20000;
END;
/
</pre></code>
<p>
В общем-то, отсутствие в СУБД Oracle Database возможности вернуть из хранимой процедуры просто курсор, никак не мешала разработчикам приложений.<br>
Тем не менее, это значительно усложняло процедуру миграции приложений на СУБД Oracle Database, с тех СУБД, где такая возможность присутствовала.<br><br>
</p>
<p>
В СУБД Oracle Database 12c такая возможность появилась!<br>
Это, конечно, потребовало адаптации клиентских библиотек доступа в Oracle Client. Начиная с Oracle Database Client 12c приложения, которые используют любой интерфейс доступа к СУБД (Oracle Call Interface, ODP.Net, JDBC), могут получать из СУБД такие "неявные" курсоры.
Собственно на стороне СУБД, чтобы вернуть такой курсор, необходимо использовать новую процедуру <i>RETURN_RESULT</i> из пакета DBMS_SQL.
</p>
Эта процедура перегружена, и присутствует в двух вариантах:
<ul>
<li> для возврата слаботипизированной ссылки на курсор - <br>
<i>PROCEDURE RETURN_RESULT(rc IN OUT SYS_REFCURSOR, to_client IN BOOLEAN DEFAULT TRUE);</i>
<li> для возврата курсора отрытого с помощью динамического SQL в пакете DBMS_SQL - <br>
<i>PROCEDURE RETURN_RESULT(rc IN OUT INTEGER, to_client IN BOOLEAN DEFAULT TRUE);</i>
</ul>
Параметр <i>to_client</i> определяет возможность возвращения курсора непосредственно сразу клиентcкому приложению, либо в другую хранимую процедуру PL/SQL.
Хранимая процедура может вернуть таким образом не один курсор, а несколько - может вызвать процедуру <i>RETURN_RESULT</i> несколько раз.
Определим хранимую процедуру, которая возвращает курсор подобным образом в клиентское приложение:
<code><pre>
SQL> <b>create or replace procedure test_dyn3 is
v_xCursor integer;
v_xRowCount integer;
begin
v_xCursor := dbms_sql.open_cursor;
dbms_sql.parse(c => v_xCursor,
statement => 'select * from dual',
language_flag => DBMS_SQL.NATIVE);
v_xRowCount := dbms_sql.execute(c => v_xCursor);
dbms_sql.return_result(v_xCursor,<font color="red">true</font>);
end;
/</b>
Procedure created.
</pre></code>
Попробуем вызвать нашу процедуру в среде утилиты <i>SQL*Plus</i>:
<code><pre>
SQL><b> exec test_dyn3;</b>
PL/SQL procedure successfully completed.
ResultSet #1
D
-
X
SQL>
</pre></code>
Как Вы можете убедиться: утилита SQL*Plus версии 12с "понимает" такой вид курсора, и просто выводит его содержимое на свою консоль.<br>
Эта возможность появилась в версии 12с этой утилиты.
Если курсор возвращается таким образом из динамического SQL, то чтобы его получить внутри вызываемого блока PL/SQL, предназначена еще одна новая процедура пакета DBMS_SQL - GET_NEXT_RESULT. Эта процедура также перегружена и имеет два варианта:
<ul>
<li> для получения слаботипизированной ссылки на курсор - <br>
<i>PROCEDURE GET_NEXT_RESULT (c IN INTEGER, rc OUT SYS_REFCURSOR);</i>
<li> для получения курсора отрытого с помощью динамического SQL в пакете DBMS_SQL - <br>
<i>PROCEDURE GET_NEXT_RESULT (c IN INTEGER, rc OUT INTEGER);;</i>
</ul>
Для того чтобы, иметь возможность получения таких "неявных" курсоров, вызов процедуры OPEN_CURSOR должен быть выполнен с новым параметром <i>treat_as_client_for_results</i> равным значению TRUE, по умолчанию значение этого параметра равно FALSE.
Немного перепишем нашу процедуру test_dyn3 указав в функции возврата курсора значение параметра <i>to_client</i> равным FALSE:
<code><pre>
SQL> <b>create or replace procedure test_dyn3 is
v_xCursor integer;
v_xRowCount integer;
begin
v_xCursor := dbms_sql.open_cursor;
dbms_sql.parse(c => v_xCursor,
statement => 'select * from dual',
language_flag => DBMS_SQL.NATIVE);
v_xRowCount := dbms_sql.execute(c => v_xCursor);
dbms_sql.return_result(v_xCursor,<font color="red">false</font>);
end;
/</b>
Procedure created.
</pre></code>
Теперь вызовем нашу процедуру через динамический SQL, и попробуем получить и вывести на экран содержимое курсора:
<code><pre>
SQL> <b>DECLARE
v_xCursor integer;
v_xRowCount integer;
v_xReturnCursor integer;
v_xResult dual.dummy%type;
v_xReturnRefCursor sys_refcursor;
BEGIN
v_xCursor := dbms_sql.open_cursor(treat_as_client_for_results => <font color="color">true</font>);
dbms_sql.parse(v_xCursor, 'BEGIN test_dyn3(); END;', dbms_sql.native);
v_xRowCount := DBMS_SQL.EXECUTE(v_xCursor);
dbms_sql.get_next_result(v_xCursor, v_xReturnCursor);
--Для удобства превращаем полученный курсор в ссылку на курсор (sys_refcursor)
v_xReturnRefCursor := dbms_sql.to_refcursor(v_xReturnCursor);
FETCH v_xReturnRefCursor
INTO v_xResult;
dbms_output.put_line('Result: ' || v_xResult);
dbms_sql.close_cursor(v_xCursor);
END;
/</b>
Result: X
PL/SQL procedure successfully completed.
SQL>
</pre></code>
Мы рассмотрели еще одну новую возможность Oracle Database 12c в области динамического SQL - возможность непосредственного возврата курсоров из хранимых процедур.<br>
На мой взгляд, эта новая возможность в основном востребована при миграции приложений с других СУБД, которые уже поддерживают эту технологию, на СУБД Oracle Database. Поскольку в этом случае значительно снижается объем работ по адаптации кода приложения под СУБД Oracle.
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-64426060831286515172015-01-09T06:10:00.000-08:002015-01-09T06:10:03.702-08:00Новые возможности в динамическом SQL в Oracle 12c (определение схемы по умолчанию)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqAe2WP8EDUHXV_0pxJwrPkM4MC-xZS3DkOAzKU7HoY7H16R9WsHWJxdF-vgaNNcT5bftCmYkj4h3BXioQCun0NT4kbM2T_Q4jgFZchrshUpLqfLFjInJjI59sqUFv83-UESMaWoj17f3/s1600/blog21.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqAe2WP8EDUHXV_0pxJwrPkM4MC-xZS3DkOAzKU7HoY7H16R9WsHWJxdF-vgaNNcT5bftCmYkj4h3BXioQCun0NT4kbM2T_Q4jgFZchrshUpLqfLFjInJjI59sqUFv83-UESMaWoj17f3/s320/blog21.jpg" /></a></div>Следующая новая возможность в динамическом SQL тоже связана с процедурой <i>PARSE</i> пакета <i>DBMS_SQL</i>.<br>
До Oracle Database 12c, если в тексте запроса или анонимного PL/SQL-блока в имени объекта не была явна указана схема, то будет использована текущая схема.<br>
Для программных единиц PL/SQL (пакетов, процедур, функций и т.д.) созданных с правами создателя, это будет схема в которой происходила компиляция, для созданных с правами вызывающего - схема пользователя, под которым происходит вызов динамического SQL.<br></br>
Начиная с Oracle Database 12c, можно четко контролировать схему в имени объекта, для которых она была не указана в динамическом SQL:
<pre><code>[oracle@rac1 ~]$ <b>sqlplus rscott/rtiger</b>
SQL*Plus: Release 12.1.0.2.0 Production on Fri Jan 9 16:24:34 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management options
SQL> <b>create or replace package body account_service as
procedure deleteAccount(v_pId in number) is
v_xCursor integer;
v_xRowCount integer;
v_xPLSQL_Str varchar2(1600);
begin
v_xPLSQL_Str := 'delete from accounts where id = :v_pId';
v_xCursor := dbms_sql.open_cursor;
dbms_sql.parse(c => v_xCursor,
statement => v_xPLSQL_Str,
language_flag => DBMS_SQL.NATIVE,
<font color="red">schema => 'DATA_OWNER'</font>);
dbms_sql.bind_variable(v_xCursor, ':v_pId', v_pId);
v_xRowCount := dbms_sql.execute(c => v_xCursor);
dbms_sql.close_cursor(c => v_xCursor);
end;
end;
/</b>
Package body created.
</code></pre>
Важно отметить, что параметр <i>SCHEMA</i> в процедуре <i>PARSE</i> отвечает лишь за имя схемы, в которой происходит поиск объекта при парсинге. Выполнение динамического SQL происходит с правами той программной единицы PL/SQL, в которой происходит вызов пакета DBMS_SQL - с правами создателя, либо с правами вызывающего.
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-9007506587468701422015-01-02T13:26:00.000-08:002015-01-08T11:45:13.880-08:00Новые возможности в динамическом SQL в Oracle 12c (выполнение кода в PDB)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS5Ko20Dg5vADStF6IsK7mWeeHCTohzxrsCUO1idMOEO9CHQV7ntxP8OqATcRWt3-xaHuIcnmNfL3hQh9pR5ovXNAkZe-cV-fP3p99kcH5_Pyz_Pv25jJLJTLUYEKeDWqNGm-zVhfPPC9j/s1600/Y54uZGJTl9s.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS5Ko20Dg5vADStF6IsK7mWeeHCTohzxrsCUO1idMOEO9CHQV7ntxP8OqATcRWt3-xaHuIcnmNfL3hQh9pR5ovXNAkZe-cV-fP3p99kcH5_Pyz_Pv25jJLJTLUYEKeDWqNGm-zVhfPPC9j/s320/Y54uZGJTl9s.jpg" /></a></div>
Говоря о новых возможностях Oracle Database 12c, нельзя не упомянуть динамический SQL. <br>
В этой области тоже появилось много новых и интересных возможностей.<br><br>
<b><font size="3"> 1. Выполнение кода в контексте произвольной PDB-базы </font></b><br>
Безусловно, самой главной новой технологией, которая пришла вместе с Oracle 12c, являются <a href="http://www.oracle.com/technetwork/articles/database/multitenant-part1-pdbs-2193987.html"> мультиарендная архитектура баз данных (Multitenant database)</a>.<br>
Поддержка контейнерной архитектуры не могла пройти мимо динамического SQL: в пакете DBMS_SQL появилась возможность выполнить произвольный код в контексте указанной подключаемой базы данных (PDB).
В процедуре <i>PARSE</i> появился новый параметр <i>CONTAINER</i>, который указывает PDB-базу, в которой нужно выполнить соответствующий динамический SQL или PL/SQL-код:
<code><pre>
dbms_sql.parse(c => v_xCursor,
statement => v_xPLSQL_Str,
language_flag => DBMS_SQL.NATIVE,
container => 'CRM');
</pre></code>
В вышеприведенном примере, код содержащийся в переменной <i>v_xPLSQL_Str</i> будет выполнен в PDB-базе <i>CRM</i>.<br>
Важно отметить следующее: такой динамический код может быть выполнен только когда текущая сессия находится в БД-контейнере (CDB$ROOT), и пользователь должен иметь права на доступ к соответствующей PDB, то есть должен быть common-пользователем.<br><br>
Создадим common-пользователя и дадим ему доступ к всем PDB в контейнере:
<code><pre>[oracle@dbim cdb1]$ sqlplus / as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Sat Jan 2 07:04:01 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> <b>CREATE USER global$rscott1
IDENTIFIED BY rtiger container=all;</b>
User created.
SQL> <b>grant connect, resource to global$rscott container=all;</b>
Grant succeeded.
</pre></code>
Для имени common-пользователя был использован нестандартный префикс (GLOBAL$, а не C##), поскольку параметр common_user_prefix был переопределен:
<code><pre>
SQL> show parameter common
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
common_user_prefix string global$
</pre></code>
Возможность переопределения префикса в именах common-пользователей появилась в патчсете 12.1.0.2.<br>
<br>
Предположим, что в контейнере находятся три PDB-базы: ERM, CRM и DW. В каждой из этих БД есть процедура создания учетной записи клиента определенная в пакете account_service:<code><pre>
create or replace package account_service as
v_gLastAuditMessage varchar2(128);
procedure newAccount(v_pName in varchar2,
v_pDescription in varchar2);
end;
</pre></code>
И после создание учетной записи клиента происходит сохранение информации аудита в глобальной переменной v_gLastAuditMessage:
<code><pre>create or replace package body account_service as
procedure newAccount(v_pName in varchar2,
v_pDescription in varchar2) is
begin
--код специфичный для каждой PDB
... ... ... ... ... ...
v_gLastAuditMessage := 'Account "' || v_pName || '" created in pdb ' || sys_context('USERENV', 'CON_NAME');
end;
end;
</pre></code>
В root-контейнере мы можем создать процедуру создания учетных записей клиентов сразу в нескольких PDB, при этом реально в каждой PDB-базе будет выполняться именно свой прикладной код.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Jd5O2jTfgoDT8aguD6aKdWjpr7htF3fveVZqc27YQBXR0wViD5g_uATFml4JC2fgUnYsgzs99lKQ0Gw7hHY4sT-90hVqCr9iLMTIIIo0erUQ1ffvZDfJ7y_u60a0RXo1-DANwNX0Txuw/s1600/pdbs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Jd5O2jTfgoDT8aguD6aKdWjpr7htF3fveVZqc27YQBXR0wViD5g_uATFml4JC2fgUnYsgzs99lKQ0Gw7hHY4sT-90hVqCr9iLMTIIIo0erUQ1ffvZDfJ7y_u60a0RXo1-DANwNX0Txuw/s400/pdbs.png" /></a></div>
<center><i>Рис.1 Инкапсуляция прикладной логики в cdb$root c помощью динамического SQL </i></center>
<br>
Исходный код, иллюстрирующий вышеописанный подход, может выглядеть следующим образом:
<code><pre>
[oracle@dbim cdb1]$ <b>sqlplus / as sysdba</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sat Jan 2 07:45:16 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL><b>conn global$rscott/rtiger</b>
Connected.
SQL> --in Root container:
SQL> <b>create or replace type TArrayOfString as table of varchar(32);</b>
/
Type created.
SQL><b> create or replace package account_service as
procedure newAccount(v_pName in varchar2,
v_pDescription in varchar2,
v_pContainers in TArrayOfString);
end;
/
</b>
Package created.
--Бизнес-логика выполняется в каждой PDB:
SQL><b> create or replace package body account_service as
procedure newAccount(v_pName in varchar2,
v_pDescription in varchar2,
v_pContainers in TArrayOfString) is
v_xCursor integer;
v_xRowCount integer;
v_xPLSQL_Str varchar2(1600);
begin
v_xPLSQL_Str := 'begin account_service.newAccount(:v_pName, :v_pDescription); end;';
v_xCursor := dbms_sql.open_cursor;
for v_xContainerIndex in 1..v_pContainers.count
loop
dbms_sql.parse(c => v_xCursor,
statement => v_xPLSQL_Str,
language_flag => DBMS_SQL.NATIVE,
<u>container => v_pContainers(v_xContainerIndex)</u>);
dbms_sql.bind_variable(v_xCursor, ':v_pName', v_pName);
dbms_sql.bind_variable(v_xCursor, ':v_pDescription', v_pDescription);
v_xRowCount := dbms_sql.execute(c => v_xCursor);
end loop;
dbms_sql.close_cursor(c => v_xCursor);
end;
end;
/</b>
Package body created.
</pre></code>
Попробуем создать учетные записи клиентов сразу в трех подключаемых БД в контейнере:
<code><pre>
SQL><b> exec account_service.newAccount('Scott Tiger','Scott Tiger demo',new TArrayOfString('ERP','CRM','DW'));</b>
PL/SQL procedure successfully completed.
</pre></code>
Теперь переключимся в конкретную PDB-бд и проверим контекст сессии (состояние переменной v_gLastAuditMessage):
<code><pre>
SQL><b> alter session set container=ERP;</b>
Session altered.
SQL> <b> set serveroutput on</b>
SQL> <b> exec dbms_output.put_line(account_service.v_gLastAuditMessage);</b>
Account "Scott Tiger" created in pdb ERP
PL/SQL procedure successfully completed.
SQL> alter session set container=CRM;
Session altered.
SQL> <b> set serveroutput on</b>
Account "Scott Tiger" created in pdb CRM
PL/SQL procedure successfully completed.
</pre></code>
Как видите, в каждой PDB-бд поддерживается свой контекст сессии - значение глобальной переменной v_gLastAuditMessage имеет свое значение для каждой PDB.
Вообще говоря, это три разные переменные, поскольку каждая PDB-бд имеет собственную реализацию пакета управления учетными записями клиентов - account_service.<br>
<br>
В Oracle 12c динамический SQL позволяет на уровне контейнера CDB$Root проводить своеобразную "оркестровку" вашего прикладного кода реализованного внутри PDB-баз данных.
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-22791951615546286462014-11-16T10:17:00.000-08:002014-11-16T10:17:39.201-08:00Oracle Database 12c: функции с правами вызывающего в представлениях<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyd_tFQ1hDRKo0EvXmaZjOWOvx7ehlQ76Sh50yH9T_Zm4d2seB1xODZXv87WKeMbyqxUFAECTur1rA-rwJYLKuo3Jn4453grjD501XnU1jAsVe9GHgs43wSd9b69648imIUwQ_7V3ALPV5/s1600/GhmzL3PI8Ng.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyd_tFQ1hDRKo0EvXmaZjOWOvx7ehlQ76Sh50yH9T_Zm4d2seB1xODZXv87WKeMbyqxUFAECTur1rA-rwJYLKuo3Jn4453grjD501XnU1jAsVe9GHgs43wSd9b69648imIUwQ_7V3ALPV5/s320/GhmzL3PI8Ng.jpg" /></a></div>
До Oracle Database 12c, если мы вызываем функцию внутри представления (неважно каким способом: в предикате фразы WHERE, либо в вычисляемом столбце), этот вызов всегда происходит с правами создателя (DEFINER RIGHTS), независимо от того как была определена функция. <br>
Рассмотрим следующий пример.<br>
Предположим, что у нас в Oracle Database 11g есть функция определенная с правами вызывающего:
<pre><code>
[oracle@rac1 ~]$ <b>sqlplus rscott/rtiger</b>
SQL*Plus: Release 11.2.0.4.0 Production on Sat Nov 10 13:09:00 2014
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP
and Data Mining options
SQL> <b>CREATE OR REPLACE FUNCTION getClosedAccounts(v_pBranchId IN NUMBER) RETURN VARCHAR2
<font color="red">AUTHID CURRENT_USER</font> IS
v_xRes NUMBER(9);
BEGIN
SELECT
count(a.rowid)
INTO
v_xRes
FROM
accounts a
WHERE
a.branch_id = v_pBranchId and
a.Status = 'CLOSED';
RETURN v_xRes;
END;
/</b>
Function created.
SQL> </code></pre>
Вызов этой функции под другим пользователем, как и положено, будет сделан с правами вызывающего:
<pre><code>
SQL> <b>grant execute on getClosedAccounts to hr;</b>
Grant succeeded.
SQL> <b>connect hr/hr</b>
Connected.
SQL> <b>select rscott.getClosedAccounts(123) from dual;</b>
select rscott.getClosedAccounts(123) from dual
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "RSCOTT.GETCLOSEDACCOUNTS", line 5
SQL>
</code></pre>
Все правильно: вызов произошел с правами вызывающего, а пользователь HR не имеет прав не чтение таблицы <i>accounts</i>.
А теперь попробуем вызвать эту же функцию под пользователем HR, но уже внутри представления:
<pre><code>
SQL> <b>conn rscott/rtiger</b>
Connected.
SQL><b>CREATE OR REPLACE VIEW v$Branches_Closed_Accounts AS
SELECT
b.Id,
getClosedAccounts(b.Id) as Closed_Count
FROM
branches b;</b>
View created.
SQL> <b>GRANT SELECT ON v$Branches_Closed_Accounts TO hr;</b>
Grant succeeded.
SQL> <b>conn hr/hr</b>
Connected.
SQL> <b>SELECT * FROM rscott.v$Branches_Closed_Accounts;</b>
ID CLOSED_COUNT
--- ---------------------------------------------------------------------
1 0
</code></pre>
Функция внутри представления была вызвана без всякой ошибки!
До Oracle Database 12c вызов функции внутри представления всегда происходит с правами создателя, даже если функция была определена как с правами вызывающего.
<br><br>
В Oracle Database 12c, в определении представления, указывается фраза BEQUEATH, которая определяет, как будут вызывать PL/SQL-функции используемые в запросе: DEFINER или CURRENT_USER.<br><br>
Переключимся на Oracle Database 12c и перепишем наше представление по другому, указав что наша функция должна быть вызвана с правами вызывающего:
<pre><code>
[oracle@localhost]$<b> sqlplus rscott/rtiger</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sun Nov 16 20:57:49 2014
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Last Successful login time: Sun Nov 16 2014 20:56:22 +03:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> <b>CREATE OR REPLACE VIEW v$Branches_Closed_Accounts
<font color="red">BEQUEATH CURRENT_USER</font> AS
SELECT
b.Id,
getClosedAccounts(b.Id) as Closed_Count
FROM
branches b;</b>
View created.
SQL> <b>conn hr/hr</b>
Connected.
SQL> <b>SELECT * FROM rscott.v$Branches_Closed_Accounts;</b>
SELECT * FROM rscott.v$Branches_Closed_Accounts
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "RSCOTT.GETCLOSEDACCOUNTS", line 5
SQL>
</code></pre>
Теперь функция в представлении вызывается с правами вызывающего!<br>
<br>
По умолчанию, в Oracle Database 12 представление будет создаваться с неявной фразой BEQUEATH DEFINER, то есть поведение будет как в предыдущих версиях - функции в представлениях будут вызываться с правами создателя.<br>
<br>
Важно отметить, что если в определении функции был указан режим вызова с правами создателя, то фраза <i>BEQUEATH CURRENT_USER</i> в представлении игнорируется:
<pre><code>
SQL> <b>conn rscott/rtiger</b>
Connected.
SQL> <b>CREATE OR REPLACE FUNCTION getClosedAccounts(v_pBranchId IN NUMBER) RETURN VARCHAR2
AUTHID DEFINER IS
v_xRes NUMBER(9);
BEGIN
SELECT
count(a.rowid)
INTO
v_xRes
FROM
accounts a
WHERE
a.branch_id = v_pBranchId and
a.Status = 'CLOSED';
RETURN v_xRes;
END;</b>
/
Function created.
SQL> <b>conn hr/hr</b>
Connected.
SQL> <b>SELECT * FROM rscott.v$Branches_Closed_Accounts;</b>
ID CLOSED_COUNT
--- ---------------------------------------------------------------------
1 0
</code></pre>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-34756710197698456342014-11-04T09:45:00.001-08:002014-11-04T22:55:14.002-08:00Oracle JavaVM Component 12.1.0.2.1 Database PSU<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0jkScpExytDjr4lrzkdz0eCSdg9PePnPTjA0mXBDyq9R66UINB6sGo0JiKhr2INVGXSJRpM2ULnL4zkafK99RpXo-oL_f7ZPbtesj1_oTO1mth35dc0oJJ4E-BwUB25bTT3Kz2K564m6t/s1600/im07t1-java-se-support-2-1526624.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0jkScpExytDjr4lrzkdz0eCSdg9PePnPTjA0mXBDyq9R66UINB6sGo0JiKhr2INVGXSJRpM2ULnL4zkafK99RpXo-oL_f7ZPbtesj1_oTO1mth35dc0oJJ4E-BwUB25bTT3Kz2K564m6t/s320/im07t1-java-se-support-2-1526624.png" /></a></div>
Продолжается стабилизация релиза Oracle 12c R1 (12.1.0.2). В октябре, как и положено, вышел первый PatchSet Update (PSU 1).<br>
Вместе с знакомыми нам патчами: для БД (DB PSU) и для Grid Infrastructure (GI PSU) появился новый вид PSU - Oracle JVM Component Database PSU. Этот пакет исправлений содержит исправления ошибок для виртуальной Java-машины работающей внутри БД. <br>
Следует заметить, что перед установкой Oracle JVM Database PSU, на базе данных предварительно уже <u>должен</u> стоять соответствующий Database PSU, в данном случае - Database PSU1.
<p>
Таким образом, теперь процедура установки патчей PSU на базу данных выглядит следующим образом:
<ul>
<li> обновляем утилиту OPatch до последней версии - здесь ничего необычного: всегда рекомендовалось скачать ее свежую версию (Patch 6880880);</li><br>
<li> устанавливаем DB PSU - здесь тоже все по старому: в каталоге распакованного архива с патчем запускаем утилиту <i>opatch</i> c параметром <i>apply</i> (это знает любой школьник! :-));
<center><br><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6PFajpvH9STpVvQH5VVUWJ6JNfyR-HO3G8BPOqqOJy6_pMj2wIove1iBlUgI2VelJkq0lUpiYzTPL4udnHhAXxW923CvA2mKJYsuEv0g6xYc5FUk9bmm8p17a-8yEwT_j7cg3XzaTOsqN/s1600/Screenshot-oracle@localhost%5E%25-tmp-19303936.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6PFajpvH9STpVvQH5VVUWJ6JNfyR-HO3G8BPOqqOJy6_pMj2wIove1iBlUgI2VelJkq0lUpiYzTPL4udnHhAXxW923CvA2mKJYsuEv0g6xYc5FUk9bmm8p17a-8yEwT_j7cg3XzaTOsqN/s320/Screenshot-oracle@localhost%5E%25-tmp-19303936.png" /></a></div>
</center>
<center><i>Рис.1 Установка патча Oracle Database 12.1.0.2 PSU 1 </i></center>
</ul>
</p>
<li> затем необходимо обновить словарь, - теперь это делается с помощью утилиты datapatch (никаких <i>catcpu.sql</i>!), эта утилита выполняет все SQL-скрипты, необходимые для корректной установки патча;
<center><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM4xiU7xJNUDz_moiWQqkVzvv5vlbWcTPaplxiUgG3hljJ1Inpkp7dHCWECCIgBDwfGIENOZR-2rcalAkmZT9833vEzcZhnncHsSXSYBvGoJskx54k0VVSI6EV134eWFLguK0zM2BclUQb/s1600/Screenshot-oracle@localhost%5E%25-u01-app-oracle-product-12.1.0-dbhome_1-OPatch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM4xiU7xJNUDz_moiWQqkVzvv5vlbWcTPaplxiUgG3hljJ1Inpkp7dHCWECCIgBDwfGIENOZR-2rcalAkmZT9833vEzcZhnncHsSXSYBvGoJskx54k0VVSI6EV134eWFLguK0zM2BclUQb/s320/Screenshot-oracle@localhost%5E%25-u01-app-oracle-product-12.1.0-dbhome_1-OPatch.png" /></a></div>
</center>
<center><i>Рис.2 Обновление словаря для DB 12.1.0.2 PSU 1 с помощью команды $O_H/OPatch/datapatch -verbose </i></center>
<br><br>
<li> устанавливаем DB OJVM PSU, - точно также выполняем: <i>opatch apply</i>;
<center><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM3RHcd1TiTgVaJzK93QDWUHl4olePyiRzqQvOVqT2QYjt6n_4fAHi7z3Vilcng3ECdSYUxn6tSWXoMDL52sEHSWbGjNnOL6iK-SxMxDKiC92KlIG1HUHcA9_QPzkEFSBvCV0dvPh5qkot/s1600/Screenshot-oracle@localhost%5E%25-tmp-19282028.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM3RHcd1TiTgVaJzK93QDWUHl4olePyiRzqQvOVqT2QYjt6n_4fAHi7z3Vilcng3ECdSYUxn6tSWXoMDL52sEHSWbGjNnOL6iK-SxMxDKiC92KlIG1HUHcA9_QPzkEFSBvCV0dvPh5qkot/s320/Screenshot-oracle@localhost%5E%25-tmp-19282028.png" /></a></div>
</center>
<center><i>Рис.3 Установка патча Oracle Database 12.1.0.2 OJVM PSU 1</i></center>
<br><br>
<li> наконец, обновляем словарь для DB OJVM PSU, - точно также выполняем: <i>datapatch -verbose</i>;
<center><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8buvxUCezJ19K6qRp_qAhHvkExJ1cT0ihvD96F_T2ohKHS_QS4jCfonM5OPRTe0HNBWS008NlhNJHbTrbvMhF4WUNLrh4edtW3e-S7o2ZuggcPD3gIiz6ddy7V_ErEkSClY7q9hI3p14j/s1600/Screenshot-oracle@localhost%5E%25-u01-app-oracle-product-12.1.0-dbhome_1-OPatch-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8buvxUCezJ19K6qRp_qAhHvkExJ1cT0ihvD96F_T2ohKHS_QS4jCfonM5OPRTe0HNBWS008NlhNJHbTrbvMhF4WUNLrh4edtW3e-S7o2ZuggcPD3gIiz6ddy7V_ErEkSClY7q9hI3p14j/s320/Screenshot-oracle@localhost%5E%25-u01-app-oracle-product-12.1.0-dbhome_1-OPatch-1.png" /></a></div>
</center>
<center><i>Рис.4 Обновление словаря для DB 12.1.0.2 OJVM PSU 1</i></center>
<p>
Процедура установки патчей на СУБД Oracle Database 12c претерпела изменения: теперь нам не нужно вручную запускать post-install SQL-скрипты, также следует не забывать об установке нового вида PSU - Database PSU JVM Component.
</p>
P.S. Выпущенный в сентябре большой MLR-патч для Oracle In-Memory (patch 19615705), к сожалению, конфликтует с DB PSU 12.1.0.2.1.
В ближайшее время будет выпущен такой же MLR, но для 12.1.0.2.1 (on Top 12.1.0.2.1).
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com1tag:blogger.com,1999:blog-5280412311812666502.post-35839695204780956112014-10-17T12:00:00.001-07:002014-10-17T12:04:33.048-07:00Oracle 12c: grant roles to PL/SQL units<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdvI3Zcyypb72P30wuv9N86dF3CuZ0ddZMU79qoSSQ_5D672dNE2dRUoLzOUjwcOyrUy3DBcrlUlmAdXdPkpEsokObH8B5pgpw63P4nc3aUb04jUQYqJGSM54EqGh1J3VQcKbPi91Y2Yt1/s1600/plsql.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdvI3Zcyypb72P30wuv9N86dF3CuZ0ddZMU79qoSSQ_5D672dNE2dRUoLzOUjwcOyrUy3DBcrlUlmAdXdPkpEsokObH8B5pgpw63P4nc3aUb04jUQYqJGSM54EqGh1J3VQcKbPi91Y2Yt1/s320/plsql.jpg" /></a></div>
В Oracle Database 12c появилась интересная новая возможность: назначать роли непосредственно PL/SQL-объектам.<br>
Для чего это нужно?
Это дает возможность давать доступ к таблицам (вообще к любым объектам БД) только через вызовы PL/SQL-объектов созданных с правами вызывающего.<br>
Предположим, у нас есть очень секретная таблица с остатками по счетам:
<code><pre>
[oracle@rac1 ~]$ <b>sqlplus rscott/rtiger</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sat Oct 18 05:57:08 2014
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Last Successful login time: Thu Oct 16 2014 08:26:35 +04:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options
SQL> <b>CREATE TABLE acc_amounts
(
Acc_Id NUMBER(9),
Acc_Date DATE,
Amount NUMBER(22,2)
);</b>
Table created.
SQL> <b>INSERT INTO acc_amounts VALUES(1,trunc(sysdate),100);</b>
1 row created.
SQL> <b>INSERT INTO acc_amounts VALUES(2,trunc(sysdate),200);</b>
1 row created.
SQL> <b>COMMIT;</b>
</pre></code>
И есть функция, которая возвращает остаток по счету на определенную дату. Для того, чтобы не давать делать вызов с потенциально более высокими правами создателя (definer right) - владельца объектов БД, функция создана с правами вызывающего (invoker rights):
<code><pre>
SQL> <b>CREATE OR REPLACE FUNCTION getAccAmount(v_pAccId IN NUMBER,
2 v_pAccDate IN DATE) RETURN NUMBER
3 AUTHID CURRENT_USER IS
4 v_xRes acc_amounts.Amount%type;
5 BEGIN
6 SELECT
7 Amount
8 INTO
9 v_xRes
10 FROM
11 rscott.acc_amounts
12 WHERE
13 Acc_Date = trunc(v_pAccDate);
14
15 RETURN v_xRes;
16 END;
17 /</b>
Function created.
SQL></pre></code>
Для того, чтобы прикладной пользователь мог вызывать эту функцию, необходимо дать ему права на чтение этой таблицы, иначе возникает ошибка:
<code><pre>
SQL> <b>GRANT EXECUTE ON getAccAmount TO user1;</b>
Grant succeeded.
SQL> <b>conn user1/oracle</b>
Connected.
SQL> <b>SELECT rscott.getAccAmount(1,sysdate) FROM dual;</b>
select rscott.getAccAmount(1,sysdate) from dual
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "RSCOTT.GETACCAMOUNT", line 6
SQL></pre></code>
Казалось бы нет проблем: нужно дать права пользователю на чтение этой таблицы. После этого все будет работать:
<code><pre>
SQL> <b>conn rscott/rtiger</b>
Connected.
SQL> <b>GRANT SELECT ON acc_amounts TO user1;</b>
Grant succeeded.
SQL> <b>conn user1/oracle</b>
Connected.
SQL> <b>SELECT rscott.getAccAmount(1,sysdate) FROM dual;</b>
RSCOTT.GETACCAMOUNT(1,SYSDATE)
------------------------------
100
SQL></pre></code>
Но теперь пользователь имеет полный доступ к таблице, и может посмотреть остаток по любому счету!
<code><pre>
SQL> <b>SELECT * FROM rscott.acc_amounts;</b>
ACC_ID ACC_DATE AMOUNT
---------- --------- ----------
1 17-OCT-14 100
2 17-OCT-14 200
SQL></pre></code>
В Oracle Database 12c мы можем дать права на чтение таблицы непосредственно самой функции. Теперь пользователь не будет иметь непосредственного доступа к таблице:
<code><pre>
SQL> <b>conn rscott/rtiger</b>
Connected.
SQL> <b>REVOKE SELECT ON acc_amounts FROM user1;</b>
Revoke succeeded.
SQL> <b>GRANT SELECT ON acc_amounts TO FUNCTION getaccamount;</b>
GRANT SELECT ON acc_amounts TO FUNCTION getaccamount
*
ERROR at line 1:
ORA-28700: Only roles can be attached to or detached from program units.
REM <b><font color="red">Дать права PL/SQL-объекту можно только через роль!</font></b>
SQL> <b>CREATE ROLE getAccAmount_role;</b>
Role created.
SQL> <b>GRANT SELECT ON acc_amounts TO getAccAmount_role;</b>
Grant succeeded.
SQL> <b>GRANT getAccAmount_role TO FUNCTION getaccamount;</b>
Grant succeeded.
SQL></pre></code>
После этого пользователь успешно может вызывать функцию получения остатка, доступ к которому мы регламентируем через параметры (передавая в вызов функции на стороне приложения текущий идентификатор пользователя). При этом пользователь не имеет прямого доступа к таблице и вынужден использовать наш PL/SQL API:
<code><pre>
SQL> <b>conn user1/oracle</b>
Connected.
SQL> <b>SELECT * FROM rscott.acc_amounts;</b>
SELECT * FROM rscott.acc_amounts
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> <b>SELECT rscott.getAccAmount(1,sysdate) FROM dual;</b>
RSCOTT.GETACCAMOUNT(1,SYSDATE)
------------------------------
100
SQL>
</pre></code>
Выдача прав на объекты непосредственно PL/SQL-объектам позволяет повысить защищенность вашего приложения от несанкционированного доступа к конфиденциальным данным. Прекрасно сочетаясь с другой возможностью Oracle 12c - <a href="http://www.igormelnikov.com/2013/12/oracle-database-12c-r1-accessible-by.html">ограничением места вызова PL/SQL-объектов</a>, эта технология позволяет четко регламентировать доступ к данным через прикладной программный интерфейс вашего приложения!
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com1tag:blogger.com,1999:blog-5280412311812666502.post-14760707404922812732014-10-05T12:23:00.002-07:002014-10-06T00:24:57.345-07:00Oracle ILM 12 and custom business rules<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyujYfuPwbLnUAWTOLuldSULjRvaYM0rv4OSf3suanvV0LNDw_EwC21voXW-Q9ftHhUH5jpn-Tc5B8jIRE62-bzN5183S8deP1ADCpxf-UbpGVKX7i9WqG9LV7Ox_mjtuy296rr9IsELpN/s1600/ILM.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyujYfuPwbLnUAWTOLuldSULjRvaYM0rv4OSf3suanvV0LNDw_EwC21voXW-Q9ftHhUH5jpn-Tc5B8jIRE62-bzN5183S8deP1ADCpxf-UbpGVKX7i9WqG9LV7Ox_mjtuy296rr9IsELpN/s320/ILM.jpg" /></a></div>
<p>В Oracle Database 12c появилась новая и очень мощная технология автоматизации жизненного цикла информации - <a href="http://www.oracle.com/technetwork/database/enterprise-edition/automatic-data-optimization-wp-12c-1896120.pdf">Automatic Data Optimization</a>. С помощью политик ILM (атрибуты сегмента, задаваемые через команду ALTER TABLE ADD ILM POLICY), мы устанавливаем политики для сжатия и перемещения данных между разными уровнями системы хранения, например: c SSD-дисков на SAS-накопители, и далее на SATA-диски.</p>
Вообще, базовые технологии для реализации такого автоматического ILM, уже давно были в СУБД Oracle еще до версии 12с: Partitioning, сжатие Advanced Compression и Hybrid Columnar Compression. Не было самого механизма отслеживания и автоматического выполнения политик ILM - приходилось их реализовывать в коде приложения, и в виде собственных скриптов и заданий (job-ов СУБД).<br>
Наконец, в Oracle Database 12c появилась технология Automatic Data Optimization.
<p>Уже пара заказчиков задали мне вопрос: а чем, собственно, это отличается от того, что уже давно есть внутри систем хранения?</p>
Действительно: подобная функциональность уже давно есть в многих массивах. Система хранения, отслеживая статистику обращения к данным, может производить автоматическое их перемещение между разными типами дисковых полок.<br>
Например, в массивах EMC Symmetrix V-Max есть технология <a href="http://www.emc.com/collateral/hardware/technical-documentation/h6234-tiered-storage-oracle-ilm-enabled-symmetrix-v-max-reference-architecture.pdf"> Virtual LUN</a>. Отдельного обсуждения заслуживает тема негибкости и сложности такой реализации ILM: поскольку массив ничего не "знает" про таблицы БД, миграция данных происходит на основе виртуальных разделов, - на каждый такой раздел нужно создавать свою ASM-группу.
<br><br>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5w4CdmiLOk_RHsPLTTGADgSuGA8xH5jlN4BzFGI3FIM_xJndX-V9oTa6VX3w4iNeK8GyvPMNyuvQ9Xl7xGnSnQfCNx31CPclnL7oTrrX4JnQiDpPTlNfGQ3ARCs-L3-kIwNmo2k-rxxm0/s1600/vlun.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5w4CdmiLOk_RHsPLTTGADgSuGA8xH5jlN4BzFGI3FIM_xJndX-V9oTa6VX3w4iNeK8GyvPMNyuvQ9Xl7xGnSnQfCNx31CPclnL7oTrrX4JnQiDpPTlNfGQ3ARCs-L3-kIwNmo2k-rxxm0/s320/vlun.jpg" /></a></div>
<center><i>Рис 1. Перещение виртуальных разделов на массивах EMC Symmetrix V-Max</i></center>
<br>
Есть два важных отличия технологии Automatic Data Optimization от реализации ILM на системе хранения.<br>
Первое: подобная функциональность есть как правило только в СХД Hi-End класса, и стоит отдельных, довольно значительных денег.<br>
Второе, и самое важное отличие: в случае автоматизации ILM средствами системы хранения, отсутствует связь с бизнес-правилами, что может привести к ложному срабатыванию политик на СХД.
<p>
Рассмотрим следующий простой случай.<br>
Мы определили на уровне системы хранения, что для таблицы с заказами, если к данным не было обращения на запись более 5 дней (то есть заказ оплачен, доставлен и закрыт), то к нему не нужен быстрый доступ - нужно переносить их с SSD-полки на другой уровень системы хранения на основе SATA-дисков.<br>
Все замечательно будет работать до тех пор, пока не появятся заказы, по которым на срок более 5-ти дней была задержана оплата или поставка. Система хранения честно переместит эти данные на SATA-диски. Когда же потребуется произвести изменение заказов при поступлении оплаты, мы получим большое время доступа, поскольку данные уже лежат на медленных дисках!
</p>
<p>
В случае использовании технологии Automatic Data Optimization мы можем задать не просто временные рамки, но собственную логику контроля перемещения данных, которая основывается на бизнес-логике приложения. Подобное, никакая система хранения, конечно сделать не сможет.
</p>
Рассмотрим пример.<br>
Пусть у нас есть таблица заказов, секционированная по годам:<pre><code>[oracle@localhost Desktop]$ <b>sqlplus rscott/rtiger</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sun Oct 5 21:45:32 2014
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> <b>create table orders
(
Id number(9) generated as identity,
Customer_id number(9),
pay_date date,
amount number,
status varchar2(15) invisible default on null 'ACTIVE'
)
partition by range (pay_date)
(
partition year_old values less than (to_date('01.01.2001','dd.mm.yyyy')) nocompress,
partition year_2001 values less than (to_date('01.01.2002','dd.mm.yyyy')) nocompress,
partition year_2002 values less than (to_date('01.01.2003','dd.mm.yyyy')) nocompress,
partition year_current values less than (maxvalue) nocompress
)
tablespace rscott_data;
</b>
Table created.
</code></pre>
Заполним секцию за 2001 год - вставим 1млн записей:<pre><code>SQL> <b>begin
for i in 1..1000000
loop
insert into orders(Customer_id,pay_date,amount)
values(1,to_date('02.01.2001','dd.mm.yyyy'),100);
end loop;
commit;
end;</b>
/
PL/SQL procedure successfully completed.
</code></pre>
Секция за 2001 год занимает 40 мегабайт и расположена в табличном пространстве RSCOTT_DATA, которое находится на SAS-дисках:<pre><code><b>SQL> SELECT bytes,tablespace_name FROM user_segments WHERE PARTITION_NAME ='YEAR_2001';</b>
BYTES TABLESPACE_NAME
---------- ------------------------------
41943040 RSCOTT_DATA
</code></pre>
Мы хотим определить правило, согласно которому, если в секции все заказы проплачены (поле status = 'PAID'): включать для нее сжатие на уровне строк (OLTP compression). Поскольку мы знаем, что после этого данные в заказе не будут часто меняться.<br>
После того как все заказы в секции будут закрыты (поле status = 'CLOSED'): переносить секцию в другое табличное пространства RSCOTT_ARCHIVE, расположенное на дисковых полках с SATA-дисками.<br>
<p>
Функция, которую мы будем использовать для проверки ILM-политики, должна иметь строго определенную сигнатуру: входной параметр <i>object_number</i>-номер объекта для которого нужно проверить правило, возвращаемое значение - типа <i>boolean</i>.
</p>
Определим две вспомогательные функции:<pre><code>SQL> /**
* Функция возвращает TRUE, если ВСЕ заказы в секции находятся в определенном состоянии
*
* @param v_pPartitionName - название секции
* @param v_pStatus - состояние заказа
* @return TRUE, если ВСЕ заказы в секции находятся в состоянии определенном в переменной v_pStatus
*/
create or replace function getOrdersStatusInPart(v_pPartitionName in varchar2,
v_pStatus in varchar2) return boolean is
v_xCount number(9);
begin
execute immediate
'select count(rowid) from orders partition (' || v_pPartitionName || ') where status != :v_pStatus'
into v_xCount
using
in v_pStatus;
return (v_xCount=0);
end;
/
Function created.
SQL> /**
* Функция возвращает название секции таблицы orders по Object_Id этой секции
*
* @param v_pPartitionObjectId - Object Id секции
* @return название секции
*/
create or replace function getPartitionNameById(v_pPartitionObjectId in number) return varchar2 is
v_xResult user_tab_partitions.partition_name%type;
begin
select
subobject_name
into
v_xResult
from
user_objects
where
object_id = v_pPartitionObjectId;
return v_xResult;
end;
/
Function created.
</code></pre>
Определяем функцию для проверки ILM-политики, которая возвращает TRUE, если все заказы в секции проплачены:<pre><code>SQL> create or replace function orders_is_paid(object_number in number) return boolean is
begin
return getOrdersStatusInPart(getPartitionNameById(object_number),'PAID');
end;
/
Function created.
</code></pre>
И, наконец, определим функцию для проверки ILM-политики, которая возвращает TRUE, если все заказы в секции закрыты:<pre><code>SQL> create or replace function orders_is_closed(object_number in number) return boolean is
begin
return getOrdersStatusInPart(getPartitionNameById(object_number),'CLOSED');
end;
/
Function created.
</code></pre>
Определяем ILM-политику для сжатия строк, когда все заказы в секции оплачены. За проверку срабатывания ILM-правила отвечает наша функция orders_is_paid:
<pre><code>SQL> <font color="red"><b>ALTER TABLE orders ILM ADD POLICY
ROW STORE COMPRESS ADVANCED
SEGMENT
ON orders_is_paid;</b></font>
Table altered.
</code></pre>
Имитируем ситуацию оплаты всех заказов в секции за 2001 год:
<pre><code>SQL>update orders partition(year_2001) set status='PAID';
1000000 rows updated.
SQL> commit;
Commit complete.</code></pre>
Автоматическое задание для выполнения ILM-политик выполняется в окне сопровождения (MAINTANCE_WINDOW).<br>
Для проверки, вызовем его вручную:<pre><code>SQL> declare
v_xExecId number;
begin
dbms_ilm.execute_ilm (ilm_scope => dbms_ilm.scope_schema,
execution_mode => dbms_ilm.ilm_execution_offline,
task_id => v_xExecId);
end;
/
PL/SQL procedure successfully completed.</code></pre>
Проверим атрибут сжатия у секций таблицы orders:<pre><code>SQL> select compression,compress_for,partition_name,tablespace_name from user_tab_partitions where TABLE_NAME ='ORDERS';
COMPRESS COMPRESS_FOR PARTITION_NAME TABLESPACE_NAME
-------- ------------ -------------- ---------------
DISABLED YEAR_OLD RSCOTT_DATA
ENABLED ADVANCED YEAR_2001 RSCOTT_DATA
DISABLED YEAR_2002 RSCOTT_DATA
DISABLED YEAR_CURRENT RSCOTT_DATA</code></pre>
Как видите, наша ILM-политика отработала и для секции заказов за 2001 год включилось OLTP-сжатие!
Определяем ILM-политику для переноса секции в табличное пространство расположенное RSCOTT_ARCHIVE на медленном носителе (SATA-диски), если все заказы в секции закрыты. За проверку срабатывания ILM-правила отвечает наша функция orders_is_closed:
<pre><code>SQL> <font color="red"><b>ALTER TABLE orders ILM ADD POLICY
TIER TO rscott_archive ON orders_is_closed;</b></font>
Table altered.
</code></pre>
Имитируем ситуацию закрытия всех заказов в секции за 2001 год:<pre><code>SQL> update orders partition(year_2001) set status='CLOSED';
1000000 rows updated.
SQL> commit;
Commit complete.</code></pre>
Для проверки, снова запускаем задание по выполнению ILM-политик вручную:<pre><code>SQL> declare
v_xExecId number;
begin
dbms_ilm.execute_ilm (ilm_scope => dbms_ilm.scope_schema,
execution_mode => dbms_ilm.ilm_execution_offline,
task_id => v_xExecId);
end;</code></pre>
Выясним размер секции за 2001 год и табличное пространство в котором оно расположено:<pre><code>SQL> SELECT bytes,tablespace_name FROM user_segments WHERE PARTITION_NAME ='YEAR_2001';
BYTES TABLESPACE_NAME
---------- ------------------------------
16777216 RSCOTT_ARCHIVE</code></pre>
Размер секции уменьшился в два с половиной раза (c 40 мегабайт до 16), и теперь она расположена в табличном пространстве RSCOTT_ARCHIVE!
<p>Технология Automatic Data Optimization, которая появилась в Oracle Database 12c, позволяет не просто автоматизировать политики ILM, а интегрировать правила их выполнения c бизнес-логикой приложения.<br>
Это выгодно отличает эту технологию от реализации ILM-политик на уровне системы хранения.
</p>Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com2tag:blogger.com,1999:blog-5280412311812666502.post-66385798378413575922014-10-02T22:01:00.001-07:002014-10-02T22:01:28.344-07:00Как Ларри Элиссон искал Путина. Записки in-memory скептика<div dir="ltr" style="text-align: left;" trbidi="on">
На OOW очень много говорят об опции database in-memory option. Игорь про нее рассказывал. Она ускоряет работу аналитических приложений без их переписывания. Ускорение достигается за счет многих механизмов - одновременное построчное и поколоночное хранение табличек в памяти, использование векторных команд процессора, новые алгоритмы построения агрегирующих отчетов, прунинг (storage index), преобразование join в набор операций фильтрации колонок, bloom filters и т д. <br> На всех выступлениях говорят про ускорение аналитических запросов в 100 раз, а потом показывают слайды, где приложения ускоряются в 1000, 2000, 3000 раз. Как такое может быть? Конечно механизмы понятные и работу Select ускоряют, ну в 2-3 раза, ну в 5-10 раз, но как может быть тысяча, непонятно. Я даже подумал, что это достигается за счет неявного result cache - сначала запрос считался час, а потом результат взяли за секунду - вот и тысячи. Но оказалось все не так <br> <br>
Прослушал несколько докладов не от Oracle, ребята детально потестировали опцию в разных режимах и вот что получилось <br> <br>
Взяли таблицы с миллионами записей и написали простой запрос - соединение, условие на выбор диапазона значений и сумма по колонкам <br>
Тестировали на Exadata. Вначале честно отключили все механизмы ячеек (offload) и In-memory. Были только обычные индексы. Запрос работал 4,5 мин. Потом заставили делать чтение вперед и full buffering, стало работать быстрее, но все равно основное время шло на ввод-вывод <br>
Потом включили механизмы Exadata - стал работать 2 секунды <br>
А потом включили еще и In-memory - все выполняется за 0,1 сек. Т е с 4.5 мин до 0.1 сек и без трюков и фокусов (хотя in-memory cache конечно разогрели)
Результаты впечатляют <br><br>
Теперь про Путина. Ларри демонстрировал как быстро работает запрос с In-memory. Закачали в БД кучу данных об упоминании разных людей в прессе. Миллионы записей. И сделали поисковую системку. Вводишь имя и на экране появляется график кол упоминаний в час для каждого дня года. <br> На экране было 2 области - в верхней показывали результат, полученный с in-memory, а в нижней - тот же запрос работал без нее. Результат поиска всегда был одинаков. В верхнем окне график появлялся мгновенно, в нижнем медленно и лениво полз от даты к дате. <br> Вначале Ларри поискал инфо по упоминанию Федерера. In-memory отработал мгновенно, потом поискал еще кого-то, результат тот-же. А потом сказал, для тех кто не верит давайте поищем инфо еще о ком-то. И тут из зала ему сказали Путин. Ларри набрал в поисковой строке putin и результат с in-memory опять появился мгновенно, а на нижнем графике он полз, полз, и в конце концов начали искать еще кого-то
<br><br>
Т е In-memory option действительно работает и действительно драматически ускоряет работу существующих аналитических приложений
<br /></div>mrivkinhttp://www.blogger.com/profile/14103136053439376952noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-4602051156200008022014-09-28T22:31:00.001-07:002014-09-28T22:31:16.150-07:00Oracle Open World 2014. Что сказал Ларри<div dir="ltr" style="text-align: left;" trbidi="on">
Начался новый OOW, как всегда много народа, будет куча презентаций и демонстраций (выбрать сложно)
<br>
Открыл OOW как всегда Ларри (после коротких выступлений маркетинга, Сафры и тетки из Intel)и сказал следующее: <br>
Сначала долго говорил про наши апсы в публичном облаке Oracle, их там уже сотни и прибавляются все новые, мы переди планеты всей, в день заходят более 40 млн пользователей, все построено на единой облачной платформе, включающей СУБД, WebLogic + Social, Mobility, IDM. Т к Бд содержит Multitennant, In-Memory, надежность, безопасность и т д, то и все приложения это имеют в облаке. Кроме, того, в отличие от конкурентов эти приложения можно развивать используя возможности платформы. Простор для ISV. Короче все потихоньку идет в облако <br><br>
Наконец сделали в публ облаке нормальный DBaaS и Web Logic. Я подозреваю, что это вирт машины с СУБД или WL, но во всяком случае это не схема в БД, как раньше, а полноценная БД и сервер приложений. Пользователь может их сам администрировать (будут тулзы) или отдать администрирование в Oracle. При заказе БД можно выбрать разные наборы опций, с стендбаем или без, с RAC (будет позже) Т е есть набор стандартных сервисов с разной ценой <br>
Ларри много раз повторил, что теперь одной кнопкой можно перенести БД или приложение Java или любое приложение в облако или из облака в свой ЦОД. Где та кнопка я не знаю, может сделают инструмент. Переносить БД и Java можно т к теперь в облаке та же полноценная СУБД и WL что и в ЦОД, а под переносом любых других приложений он понимает IaaS (называется compute service) Т е заказываем вирт машину из шаблона, а в нее ставим что хотим<br>
<br>
Анонсы Ларри оставил на закуску<br><br>
Запускается ZDLRA - Zero data loss and recovery appliance - устройство для бэкапирования и восст БД. В отличие от других средств он не файлы бэкапит, а знает структуру БД.На самом деле используется тот же механизм, что и для Standby - передаются только Redo entry и копятся на этом appliance в ячейках Exadata. В любой момент можно попросить бэкап на любой момент времени в прошлом и Appliance его реконструирует из копии Бд и этих redo. Один appliance для бэкапирования всех БД организации. Трафик минимальный, восстановления на произвольный момент (а не на прошлый бэкап как сейчас)
<br><br>
В Exalitics поставили БД 12С с inmemory
<br><br>
Главное - в след году выйдут процы М7 с встроенными в железо (силикон) командами БД Соответств енно производительность БД опять взлетит. 12с будет поддерживать.
В М7 зашиты команды для ускорения работы СУБД (какие не ясно, но как минимум работа по сканированию колонок in-memory), декомпресия сжатых данных, безопасность
Впервые в мире на уровне железа будут проверять доступ к областям памяти. Если это не память этого приложения, то туда не пустят, не дадут испортить данные или их считать
Ларри показал select count(*) с несколькими условиями и сказал, что он весь будет выполняться на процессоре
<br><br>
Да, еще запускают какую то стойку SAN с SSD дисками. Называется FS1 Дешевле и быстрее, чем EMC
<br><br>
Ну вот, то что вспомнил, остальное см прессрелизы (еще BI для Hadoop будет, BI в облаке, улучшения в RAT, In-memory adviser и т д и т п)
<br /></div>mrivkinhttp://www.blogger.com/profile/14103136053439376952noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-61898484947611874572014-09-28T08:44:00.001-07:002014-09-28T09:13:55.642-07:00The same code for Oracle 11g and 12c<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH9D6yixAYGkzvM5tsDwAVCiUO5tO2T5sNjQuNOtlYjtLRE9UjDwipQRKo-m4ECJW_DEu4iMxrqykOq80uFepZiHaWEbCdAh5EMeknUdNqohtKXRj31WjJDuP5BDpZuHadxNlqUD_5-Ow9/s1600/oracle-12c-logo-370x290.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH9D6yixAYGkzvM5tsDwAVCiUO5tO2T5sNjQuNOtlYjtLRE9UjDwipQRKo-m4ECJW_DEu4iMxrqykOq80uFepZiHaWEbCdAh5EMeknUdNqohtKXRj31WjJDuP5BDpZuHadxNlqUD_5-Ow9/s320/oracle-12c-logo-370x290.jpg" /></a></div>
В настоящий момент некоторые компании-разработчики объявили о поддержке Oracle Database 12c в своих приложениях.<br>
Мне довелось принять участие в конференции, посвященной этой грядущей поддержке в решениях компании ЦФТ: <a href="http://www.cft.ru/press-center/Pages/16-09-2014.aspx">Миграция банковских комплексов ЦФТ на СУБД Oracle 12с</a>.<br><br>
В ходе последующего общения с разработчиками ЦФТ возник вопрос о сложности сопровождения кода в промежуточный период: когда будет необходимо поддерживать одновременно и Oracle 11g и Oracle 12c.<br><br>
В решении этой задачи, на мой взгляд, может помочь условная компиляция PL/SQL. C помощью определенных в стандартном встроенном PL/SQL-пакете DBMS_DB_VERSION символов условной компиляции (логических констант), мы можем указывать части кода которые будут работоспособны только в Oracle 12c.<br>
В этом пакете есть логическая константа VER_LE_11_2, истинное значение которой указывает на то, что компиляция кода производится в версии не более чем Oracle 11g Release 2.<br><br>
Рассмотрим в качестве примера одну из новых технологий Oracle 12c - возможность определять <a href="http://www.igormelnikov.com/2014/02/oracle-database-12c-plsql-inside-sql.html">UDF-функции</a>, и тем самым значительно снижать затраты на переключение контекста в SQL-запросах.<br>
Идея очень проста: директиву компиляции UDF мы обрамляем в символ условной компиляции.
<code><pre>
CREATE OR REPLACE FUNCTION inc_amount(v_pValue in number) RETURN number is
<font color=red> $if not dbms_db_version.ver_le_11_2 $then</font>
PRAGMA UDF;
<font color=red> $end</font>
v_xValue number(9);
BEGIN
v_xValue := v_pValue;
return v_xValue+10;
END;
</pre></code>
Далее, в момент компиляции этого кода, исходный текст будет препроцессирован. Если текущая версия БД - Oracle 12c, в код, который в итоге будет скомпилирован, попадет UDF-прагма PL/SQL-компилятора. Если БД имеет версии ниже, чем Oracle 12c - перед компиляцией, из исходного текста будет удалена строка с определением прагмы.<br><br>
Важно отметить, что нам не нужно обрабатывать версию СУБД на уровне патчера нашего приложения и проводить собственный препроцессинг: компиляция этого кода на обеих версиях БД проходит без ошибок. <br>
Компилируем код в Oracle 11.2:
<code><pre>
-bash-4.1$ <b>sqlplus scott/tiger</b>
SQL*Plus: Release 11.2.0.4.0 Production on Sun Sep 28 20:06:36 2014
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning and Real Application Testing options
SQL> <b>CREATE OR REPLACE FUNCTION inc_amount(v_pValue in number) RETURN number is
$if not dbms_db_version.ver_le_11_2 $then
PRAGMA UDF;
$end
v_xValue number(9);
BEGIN
v_xValue := v_pValue;
return v_xValue+10;
END;
/</b>
Function created.
SQL>
</pre></code>
Теперь тот же самый код компилируем в Oracle 12c R1:
<code><pre>
[oracle@localhost Desktop]$ <b>sqlplus scott/tiger</b>
SQL*Plus: Release 12.1.0.2.0 Production on Sun Sep 28 20:10:13 2014
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Last Successful login time: Sun Sep 28 2014 19:35:23 +04:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> <b>CREATE OR REPLACE FUNCTION inc_amount(v_pValue in number) RETURN number is
$if not dbms_db_version.ver_le_11_2 $then
PRAGMA UDF;
$end
v_xValue number(9);
BEGIN
v_xValue := v_pValue;
return v_xValue+10;
END;
/
</b>
Function created.
SQL>
</pre></code>
Таким образом, мы имеем единую версию исходных текстов нашего приложения, который работоспособен сразу в нескольких версиях СУБД, получая преимущества от использования новых версий!
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-12449257511113889912014-09-26T12:36:00.001-07:002014-09-26T12:36:14.048-07:00Oracle Database 12.1.0.2 for Windows released!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyqX0-vqyYXofAtyr_Ix7JhVncuIriA5FT5OlrQdVneUWGqEwI3__2BL694p21Gy1_nE-kOtsFokFekSHAGrB-soW7D1-IXBG-qjZaPc9vG0DaEnQipAfjG26qYg5ts_rHdZxv7QHyyxOx/s1600/images.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyqX0-vqyYXofAtyr_Ix7JhVncuIriA5FT5OlrQdVneUWGqEwI3__2BL694p21Gy1_nE-kOtsFokFekSHAGrB-soW7D1-IXBG-qjZaPc9vG0DaEnQipAfjG26qYg5ts_rHdZxv7QHyyxOx/s320/images.jpg" /></a></div>
Ссылка для скачивания: <a href="http://www.oracle.com/technetwork/database/enterprise-edition/downloads/database12c-win64-download-2297732.html">Oracle Database 12c Release 1 (12.1.0.2.0) for Microsoft Windows (x64)</a>Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-33225740085664697692014-09-18T06:44:00.000-07:002014-09-18T06:46:19.821-07:00Материалы семинара "Новые возможности Oracle Database 12с для обеспечения высокой доступности"<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPaKY0lenrA0l61_a-2uFsSikr5CGJmjrW04q4JnRIXt1o3B9IkO_qIyNPkgDJ5t1-Jpxqa-MGv7mts141-BpgVTk-YXhvv68YJfF6ehhZTjAyN7aX4aE_bWRyb_W_SP9rk1wh4vJQtBtc/s1600/IMG_0439.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPaKY0lenrA0l61_a-2uFsSikr5CGJmjrW04q4JnRIXt1o3B9IkO_qIyNPkgDJ5t1-Jpxqa-MGv7mts141-BpgVTk-YXhvv68YJfF6ehhZTjAyN7aX4aE_bWRyb_W_SP9rk1wh4vJQtBtc/s320/IMG_0439.JPG" /></a></div>
Материалы семинара <a href="http://www.igormelnikov.com/2014/09/oracle-database-12-18-2014.html">"Новые возможности Oracle Database 12с для обеспечения высокой доступности"</a>, который прошел сегодня 18 сентября 2014 года в Санкт-Петербурге можно скачать по этой <a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XeDdrZkpnZ01UOTQ"><font color="red">ссылке </font></a>(архив zip, 5Mb).<br><br>
Архив включает в себя все презентации и описание демонстрации технологии Application Continuity, включая исходный код демонстрационного приложения.
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com1tag:blogger.com,1999:blog-5280412311812666502.post-83470795089489515932014-09-11T11:45:00.001-07:002014-09-11T11:46:23.973-07:00"Новые возможности Oracle Database 12с для обеспечения высокой доступности: - Санкт-Петербург 18 сентября 2014 года<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu8dp3EEo4Hg51dPiU1b1qR9LDYqYc3kHGcbcN9zezNXgQZX4fU6y_npHq1CsfsVnrdal0NFzSsQJDROoQzVmHhCDMNjwTzGuzhD2iwlbdabAq5xd6YW0ezt4_BY8jMW9gzgz_dsqyi5N-/s1600/vXfmzQllqL4.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu8dp3EEo4Hg51dPiU1b1qR9LDYqYc3kHGcbcN9zezNXgQZX4fU6y_npHq1CsfsVnrdal0NFzSsQJDROoQzVmHhCDMNjwTzGuzhD2iwlbdabAq5xd6YW0ezt4_BY8jMW9gzgz_dsqyi5N-/s320/vXfmzQllqL4.jpg" /></a></div>
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:DoNotShowComments/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>RU</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";
mso-ansi-language:EN-US;
mso-fareast-language:EN-US;}
table.MsoTableGrid
{mso-style-name:"Table Grid";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-priority:59;
mso-style-unhide:no;
border:solid windowtext 1.0pt;
mso-border-alt:solid windowtext .5pt;
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-border-insideh:.5pt solid windowtext;
mso-border-insidev:.5pt solid windowtext;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Calibri","sans-serif";
mso-bidi-font-family:"Times New Roman";
mso-ansi-language:EN-US;
mso-fareast-language:EN-US;}
</style>
<![endif]--><span lang="EN-US"><a href="http://goo.gl/maps/ceKu7"><span lang="RU" style="mso-ansi-language: RU; mso-bidi-font-weight: bold;"></span></a></span><b><span style="color: black; mso-ansi-language: RU;"></span></b><br />
<table border="0" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-insideh: none; mso-border-insidev: none; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 1184;"><tbody>
<tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0; mso-yfti-lastrow: yes;"><td style="padding: 0cm 5.4pt 0cm 5.4pt; width: 339.95pt;" valign="top" width="567"><br /></td><td style="padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="210"><br /></td></tr>
</tbody></table>
<div class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; text-align: justify;">
<span style="color: black; mso-ansi-language: RU; mso-bidi-font-weight: bold;">
Компания Oracle совместно со своим партнером компанией COMPAREX приглашают Вас посетить БЕСПЛАТНУЮ конференцию: «Новые возможности Oracle Database 12с для обеспечения высокой доступности».Вы узнаете о последних достижениях компании Oracle в области СУБД Oracle 12c. Презентации будут сопровождаться демонстрациями технологий Oracle.<br><br>
Мероприятие пройдет 18 сентября 2014 года, г. Санкт-Петербург, с 10:00 до 15:30<br>
Мероприятие будет интересно: администраторам баз данных, техническим специалистам.</span></div><br>
<br />
<br />
<br style="mso-special-character: line-break;" />
<div class="MsoListParagraph" style="mso-list: l0 level1 lfo2; mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; text-indent: -18.0pt;">
<span lang="EN-US" style="mso-bidi-font-weight: bold; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: NL;">
<br style="mso-special-character: line-break;" />
</span><span lang="EN-US" style="mso-bidi-font-weight: bold;"></span></div>
<div class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto;">
<b><span style="mso-ansi-language: RU; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: NL;">Программа семинара:</span></b></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .75pt solid windowtext; mso-border-insidev: .75pt solid windowtext; mso-padding-alt: 0cm 0cm 0cm 0cm; width: 803px;">
<tbody>
<tr style="height: 20.25pt; mso-yfti-firstrow: yes; mso-yfti-irow: 0;">
<td style="background: #969696; border: solid windowtext 1.0pt; height: 20.25pt; mso-border-bottom-alt: .75pt; mso-border-color-alt: windowtext; mso-border-left-alt: .5pt; mso-border-right-alt: .75pt; mso-border-style-alt: solid; mso-border-top-alt: .5pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">Время</span></b><b><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;"></span></b></div>
</td>
<td style="background: #969696; border-left: none; border: solid windowtext 1.0pt; height: 20.25pt; mso-border-bottom-alt: .75pt; mso-border-color-alt: windowtext; mso-border-left-alt: .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: .5pt; mso-border-style-alt: solid; mso-border-top-alt: .5pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">Тема выступления</span></b><b><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;"></span></b></div>
</td>
</tr>
<tr style="height: 2.5pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .5pt; mso-border-right-alt: .75pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">10:00 – 10:30</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: .5pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoNormal">
<i style="mso-bidi-font-style: normal;"><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;"><span style="mso-spacerun: yes;"> </span>Регистрация,
приветственный кофе</span></i></div>
</td>
</tr>
<tr style="height: 11.05pt; mso-yfti-irow: 2;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 11.05pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">10:30 – 11:15</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 11.05pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoListParagraph" style="mso-list: l1 level1 lfo1; text-indent: -18.0pt;">
<span lang="EN-US" style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt "Times New Roman";">
</span></span></span><span lang="EN-US">Увеличие производительности и масштабируемости системы благодаря технология Flex RAC для построения кластера. Новая архитектура Oracle RAC 12c: Flex Cluster, Flex ASM.</span></div>
</td>
</tr>
<tr style="height: 2.5pt; mso-yfti-irow: 3;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 2.5pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span lang="EN-US" style="mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">11:15 – 12:00</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 2.5pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoListParagraph" style="mso-list: l1 level1 lfo1; text-indent: -18.0pt;">
<span lang="EN-US" style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-bidi-font-weight: bold; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt "Times New Roman";">
</span></span></span><span lang="EN-US">Решение проблем сбоя БД во время транзакции при помощи Transaction Guard и Application Continuity<span style="mso-bidi-font-weight: bold;"></span></span></div>
</td>
</tr>
<tr style="height: 8.25pt; mso-yfti-irow: 4;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 8.25pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">12:00 – 13:00</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 8.25pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoNormalCxSpMiddle">
<i style="mso-bidi-font-style: normal;"><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;"><span style="mso-spacerun: yes;">
</span>Ланч</span></i><span style="mso-ansi-language: RU;"></span></div>
</td>
</tr>
<tr style="height: 2.8pt; mso-yfti-irow: 5;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 2.8pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">13:00 – 1</span><span lang="EN-US" style="mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">3</span><span style="mso-ansi-language: RU; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">:45</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 2.8pt; mso-border-alt: solid windowtext .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoListParagraph" style="mso-list: l1 level1 lfo1; text-indent: -18.0pt;">
<span lang="EN-US" style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt "Times New Roman";">
</span></span></span><span lang="EN-US">Global Data Services. Технология «Данные как сервис» в новой версии СУБД.</span><span style="mso-ansi-language: RU;"></span></div>
</td>
</tr>
<tr style="height: 2.5pt; mso-yfti-irow: 6; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .5pt; mso-border-right-alt: .75pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span lang="EN-US" style="mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">13:45 – 14:30</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: .5pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoListParagraph" style="mso-list: l1 level1 lfo1; text-indent: -18.0pt;">
<span lang="EN-US" style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt "Times New Roman";">
</span></span></span><span lang="EN-US">Обзор технологии Active Data Guard 12с для разгрузки первого сервера от работы с отчетами.</span></div>
</td>
</tr>
<tr style="height: 2.5pt; mso-yfti-irow: 6; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .5pt; mso-border-right-alt: .75pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 14.84%;" valign="top" width="14%"><div align="center" class="MsoNormal" style="text-align: center;">
<span lang="EN-US" style="mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-font-weight: bold; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: "Arial Unicode MS"; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin;">14:30 – 15:30</span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 2.5pt; mso-border-bottom-alt: .5pt; mso-border-color-alt: windowtext; mso-border-left-alt: .75pt; mso-border-left-alt: solid windowtext .75pt; mso-border-right-alt: .5pt; mso-border-style-alt: solid; mso-border-top-alt: .75pt; mso-border-top-alt: solid windowtext .75pt; padding: .75pt .75pt 0cm .75pt; width: 85.16%;" valign="top" width="85%"><div class="MsoListParagraph" style="mso-list: l1 level1 lfo1; text-indent: -18.0pt;">
<span lang="EN-US" style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt "Times New Roman";">
</span></span></span><span lang="EN-US">Сессия вопросов и ответов. Кулуарное общение. </span></div>
</td>
</tr>
</tbody></table>
<table border="0" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-insideh: none; mso-border-insidev: none; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 1184;">
<tbody>
<tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0; mso-yfti-lastrow: yes;">
<td style="padding: 0cm 5.4pt 0cm 5.4pt; width: 339.95pt;" valign="top" width="567"><div class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto;">
<br /></div>
<div class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto;">
<b style="mso-bidi-font-weight: normal;"><span style="mso-ansi-language: RU;">Участие
в семинаре бесплатное.<br />
Регистрация на мероприятие является обязательной!<br />
<span style="color: black;">Количество<span style="mso-bidi-font-weight: bold;">
мест ограничено!</span></span></span></b></div>
</td>
<td style="padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="210"><div align="center" class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; text-align: center;">
<br /></div>
<div align="center" class="MsoNormal" style="mso-margin-bottom-alt: auto; mso-margin-top-alt: auto; text-align: center;">
<a href="http://www.comparex-group.com/web/ru/ru/events/seminars/SeminarSamara/Main.htm"><span lang="EN-US"><b style="mso-bidi-font-weight: normal;"><span lang="RU" style="font-size: 14.0pt; mso-ansi-language: RU;">РЕГИСТРАЦИЯ</span></b></span></a><b><span style="color: black; font-size: 14.0pt; mso-ansi-language: RU;"></span></b></div>
</td>
</tr>
</tbody></table>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-76250005363305463802014-08-27T12:37:00.000-07:002014-08-28T07:48:13.628-07:00Материалы семинара "Особенности обновления СУБД на Oracle Database 12c"Материалы семинара "Особенности обновления СУБД на Oracle Database 12c".<br><br>
Общий архив с всеми презентациями: <a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XN1pkd0YzV0tqTUE">ссылка</a> (zip-архив, 15Mb).<br>
<br>
<b>Презентации по отдельности:</b><br><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XcGpkXzdWczl4R00">Подготовка к переходу на Oracle Database 12c и обновление</a><br>
Игорь Мельников, Ведущий консультант, Oracle
<br> <br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XQkRDeDJQa0h5MjQ">Переход на Oracle Database 12c с помощью Full Transportable Database и другие способы обновления. Переход в контейнерную архитектуру Oracle Database 12c</a><br>
Борис Пищик, Старший консультант, Oracle
<br> <br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2Xc0FYT2xLVTNLRTA">Образовательные программы от Oracle University</a><br>
Анна Гуляева,Менеджер по продажам обучения, Oracle
<br><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XVjBzMmR6aW1SNEE">Особенности Oracle Database 12c: новые процессы, параметры, утилиты и т.д.</a><br>
Андрей Забелин, Ведущий консультант, Oracle
<br><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XcFVyV1JfLWRuNTA">Настройка производительности в Oracle Database 12c: управление планами SQL-запросов, изменения в оптимизаторе и т.д.</a><br>
Борис Пищик, Старший консультант, Oracle
<br> <br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XZG1XWWx2TGlWRVU">Лучшие практики по переходу на Oracle Database 12c</a><br>
Андрей Забелин, Ведущий консультант, Oracle
<br><br>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-86472559911490010402014-08-23T12:26:00.002-07:002014-08-23T12:29:28.035-07:00Cеминар "Особенности обновления СУБД на Oracle Database 12c" - 28 августа <div class="separator" style="clear: both; text-align: center;"><a href="http://eventreg.oracle.com/profile/web/index.cfm?PKWebId=0x113241b0e5&source=EV-IE1" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdJcJLRyieYDMIMpG7OOx_elN71S-aSx-OjLV1StFerDwlEyG7ltj2e8HurMhz9IMqu2UCfWX1xQSYtv9PxCR2PBJKuWPKkUl5qRCY2iM1mk3gYQjK0xSq7udbMA1t5z7QpIgbe6SJ5WSA/s320/seminar.jpg" /></a></div>
Поскольку в ближайший год у заказчиков <a href="http://www.igormelnikov.com/2014/08/oracle-database-112-premier-support-end.html">встанет задача</a> обновления БД до версии Oracle Database 12c, мы решили провести семинар посвященный этой теме.<br>
Это мероприятие состоится 28 августа 2014 года в офисе Oracle.
<p>
В ходе семинара будут рассмотрены теоретические и практические вопросы перевода баз данных на новую версию СУБД. Также особое внимание будет уделено изменениям в процедурах обновления, которые произошли в Oracle Database 12c, - этих изменений очень много.<br>
Также отдельно будут рассмотрены вопросы связанные в переходом в контейнерную архитектуру Pluggable Database.
</p>
<a href="http://eventreg.oracle.com/profile/web/index.cfm?PKWebId=0x113241b0e5&source=EV-IE1"><font color="red">Ссылка на регистрацию</font></a>
<br><br>
Программа семинара:<br>
<code><pre>
10:00 - 11:00 Регистрация участников, утренний кофе
11:00 - 11:45 Подготовка к переходу на Oracle Database 12c
Игорь Мельников, Ведущий консультант, Oracle
11:45 - 12:30 Обновление с помощью Oracle Database Upgrade Assistant
Игорь Мельников, Ведущий консультант, Oracle
12:30 - 12:45 Перерыв
12:45 - 13:30 Переход на Oracle Database 12c с помощью Full Transportable Database и другие способы обновления
Борис Пищик, Старший консультант, Oracle
13:30 - 14:10 Обед
14:10 - 14:20 Образовательные программы от Oracle University
Анна Гуляева,Менеджер по продажам обучения, Oracle
14:20 - 15:10 Особенности Oracle Database 12c: новые процессы, параметры, утилиты и т.д.
Борис Пищик, Старший консультант, Oracle
15:10 - 15:45 Настройка производительности в Oracle Database 12c: управление планами SQL-запросов, изменения в оптимизаторе и т.д.
Андрей Забелин, Ведущий консультант, Oracle
15:45 - 16:00 Перерыв
16:00 - 17:15 Лучшие практики по переходу на Oracle Database 12c
Андрей Забелин, Ведущий консультант, Oracle
</pre></code>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-68706529851518424822014-08-23T12:02:00.000-07:002014-08-23T12:02:21.032-07:00Oracle Database 11.2 - Premier Support end after 5 month!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyh5W37GZ83toSWzkqkONPyDN69BiyGsSXowY3smr4iXMgiUUf2vUMtoRfzZMtu3vi2dOJW5N4d243mboJK9q4NDCIawAkzg8w5icwZjrYIkBD64zCwzxdy4t6xG1mprx-s5Zs3VJMdxab/s1600/lsp.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyh5W37GZ83toSWzkqkONPyDN69BiyGsSXowY3smr4iXMgiUUf2vUMtoRfzZMtu3vi2dOJW5N4d243mboJK9q4NDCIawAkzg8w5icwZjrYIkBD64zCwzxdy4t6xG1mprx-s5Zs3VJMdxab/s320/lsp.jpg" /></a></div>
Да-да: через 5 месяцев (в январе следующего года <a href="http://www.oracle.com/us/support/library/lifetime-support-technology-069183.pdf">заканчивается Premier Support </a> СУБД Oracle Database 11g Release 2!<br>
Для заказчиков использующих Oracle Database 11.2.0.4, первый год Extended-поддержки не потребует дополнительных затрат, - то есть ее стоимость не возрастет как обычно на 20%.<br><br>
Более подробную информацию об этом, и почему не стоит ждать выходе второго релиза Oracle Database 12с (12.2) - в <a href="https://blogs.oracle.com/UPGRADE/entry/why_i_we_ll_wait">блоге Майка Дитриха</a>.<br><br>
Как Вы знаете, месяц назад вышел первый патчсет к Oracle Database 12c R1 - 12.1.0.2, который помимо устранения ошибок и недочетов, также привносит много <a href="http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT003">новых возможностей</a>, прежде всего технологию <a href="http://docs.oracle.com/database/121/ADMIN/memory.htm#ADMIN14257">Oracle Database In-Memory</a>. Об этой технологии мы подробно недавно рассказывали на нашем семинаре <a href="http://www.igormelnikov.com/2014/08/oracle-database-in-memory.html">"Oracle Database In-memory" - новая технология обработки в памяти</a>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com1tag:blogger.com,1999:blog-5280412311812666502.post-35446170154824536982014-08-14T12:35:00.002-07:002014-08-14T12:36:35.727-07:00Материалы семинара "Oracle Database In-Memory"Материалы семинара <a href="http://www.igormelnikov.com/2014/08/oracle-database-in-memory-14.html">"Oracle Database In-Memory Detail"</a>, который состоялся 14 августа 2014 года в офисе Oracle, можно скачать по следующим ссылкам:<br>
<p>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XbURkbDhXRU1reU0">Oracle Database In-Memory 12.1.0.2 <br>
Игорь Мельников, Ведущий консультант, Oracle СНГ</a>
</p>
<p>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XcHFEZU9EaUNKVms">Мониторинг использования In-Memory Option с помощью Oracle Enterprise Manager Cloud Control 12c</br>
Андрей Забелин, Ведущий консультант, Oracle СНГ</a>
</p>
<p>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XbXFUR1hMNHhyRmM">Образовательные программы компании Oracle<br>
Анна Гуляева, Oracle</a>
</p>
<p>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XMEQzUkdNb0t0djQ">Новые технологии управления буферным КЭШем: Automatic Big Table Cache и Full Database Cache Mode<br>
Борис Пищик, Старший консультант, Oracle СНГ</a>
</p>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com2tag:blogger.com,1999:blog-5280412311812666502.post-65222802973433426382014-08-10T08:29:00.001-07:002014-08-10T08:30:57.349-07:00Семинар "Oracle Database In-memory" - новая технология обработки в памяти (14 августа)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVhWq21boseiyBVrma_mYPjGZJQUOOW8dAwdOyf-n-FW8EnCB8QQWbkLv0w-X03T2YS4Okp_CMKrFYp0Ih__TMIqP43zl0Hi7YjmcXbEy9QiVsOGqKLFA4-vwAjdGz_pxU8iSFZ20CNTb-/s1600/inmemory.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVhWq21boseiyBVrma_mYPjGZJQUOOW8dAwdOyf-n-FW8EnCB8QQWbkLv0w-X03T2YS4Okp_CMKrFYp0Ih__TMIqP43zl0Hi7YjmcXbEy9QiVsOGqKLFA4-vwAjdGz_pxU8iSFZ20CNTb-/s400/inmemory.jpg" /></a></div>
ORACLE SUMMER TECH DAYS: НОВАЯ ТЕХНОЛОГИЯ ОБРАБОТКИ ДАННЫХ В ПАМЯТИ СУБД ORACLE DATABASE
<p>
В настоящий момент резкое увеличение объема оперативной (Random Access Memory - RAM) памяти у аппаратных серверов стало реальностью. Развитие аппаратного обеспечения привело к тому, что даже сервер начального уровня может иметь на борту 1 Тб и более RAM.<br>
Вместе с тем, традиционная архитектура промышленного ПО (прежде всего СУБД), в плане принципов работы с памятью, остались прежними – память используется только для кэширования. Основной проблемой традиционных СУБД является увеличение накладных расходов на сопровождение буферного КЭШа больших объемов.<br>
</p>
<p>
Ответом на эти вызовы явилась технология вычислений в памяти – In-Memory Computing. Технология In-Memory Computing рассматривает память не просто как область для КЭШа, а включает в себя специализированные алгоритмы обработки данных в памяти.
</p>
<p>
Oracle Database In-Memory является опцией базы данных Oracle и позволяет увеличить в десятки и сотни раз производительность аналитических запросов в приложениях бизнес-анализа и в приложениях смешанного типа. За счет отказа от индексов, которые ранее были необходимы для аналитических запросов, также возрастает скорость выполнения транзакций в приложениях смешанного типа (mixed applications).
</p>
<p>
В ходе семинара подробно будут рассмотрены новые технологии, используемые в Oracle Database In-Memory, включая механизмы тонкого тюнинга объектов БД для достижения максимальной производительности приложений. Дополнительно будут рассмотрены новые технологии для работы с традиционным буферным кэшем СУБД, которые появились в патчсете 12.1.0.2.
</p>
Участие в семинаре – бесплатное при условии предварительной регистрации и получения подтверждения от организаторов.
<br><br>
<a href="http://eventreg.oracle.com/profile/web/index.cfm?PKWebId=0x105622894c&source=EV-IE1"><font color="red">Ссылка на регистрацию</font></a>
<br><br>
Программа:
<code><pre>
14 августа 2014 года<br>
10:00 – 11:00 Регистрация участников, утренний кофе
11:00 – 11:30 Введение в In-Memory Option
Игорь Мельников, Ведущий консультант, Oracle СНГ
11:30 – 12:00 Особенности использования In-Memory Option
Игорь Мельников, Ведущий консультант, Oracle СНГ
12:00 – 12:30 Демонстрация
Игорь Мельников, Ведущий консультант, Oracle СНГ
12:30 – 13:00 Мониторинг использования In-Memory Option с помощью Oracle Enterprise Manager Cloud Control 12c
Андрей Забелин, Ведущий консультант, Oracle СНГ
13:00 – 13:40 Обед
13:40 – 15:10 Новые технологии управления буферным КЭШем: Automatic Big Table Cache и Full Database Cache Mode
Борис Пищик, Старший консультант, Oracle СНГ
15:10 – 15:25 Демонстрация
Борис Пищик, Старший консультант, Oracle СНГ
</pre></code>Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-91723034395967686652014-06-27T11:48:00.001-07:002014-06-27T11:56:11.929-07:00Материалы семинара "Oracle Multitenant Option"<div class="separator" style="clear: both; text-align: center;"><a href="http://docs.oracle.com/cd/E16655_01/server.121/e17636/cdb_intro.htm#ADMIN13507" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMNs4REisjHa2eSCBLyIhBsisa9R4x_WyAj_dPS8P5XR46CvCBAw94QsGdnRH8P1vWrzTDfb27oR3yBNRDqwjP56xQ6y1XQw8FFG9-lI9wqRqA32SaTPzsQ5QROcMNfW1Vvg-8p3aVF68t/s320/admin094.jpg" /></a></div>
По нижеприведенным ссылкам Вы можете скачать материалы семинара <a href="http://www.igormelnikov.com/2014_05_01_archive.html">"Oracle Multitenant Option"</a> который был посвящен практическим аспектам консолидации БД с помощью этой технологии. <br>
Данный семинар проходил в офисе Oracle 29 мая и 26 июня 2014 года.<br><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XYmJZRE83WVJKTTQ">Практические аспекты консолидации БД с использованием Multitenant Option</a><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XRmRJVk1xOTltNm8">Особенности работы технологий СУБД Oracle в Multitenant-среде</a><br>
<a href="https://drive.google.com/uc?confirm=no_antivirus&id=0B3O0_0wGAA2XUTFmX1ptVTVENG8">Oracle Dataguard & Мultitenant</a><br>
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com0tag:blogger.com,1999:blog-5280412311812666502.post-50879413706896712062014-06-18T04:00:00.001-07:002014-06-18T07:18:40.550-07:00Markhot и Edition Base Redefinition<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJdtJwXTeUq9R134UzPyBvQ36dTTjXtmh1hlBqdkwBYUv191PcmxR4STH1hdvNthsP9GEevU610l1GGvZC9rlT93tpJ7Zjr7wrJ07LK7ahkkb29jkGUD2Drs3Maw2pEx36UIH9kn9Kie0u/s1600/bd.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJdtJwXTeUq9R134UzPyBvQ36dTTjXtmh1hlBqdkwBYUv191PcmxR4STH1hdvNthsP9GEevU610l1GGvZC9rlT93tpJ7Zjr7wrJ07LK7ahkkb29jkGUD2Drs3Maw2pEx36UIH9kn9Kie0u/s320/bd.jpg" /></a></div>
<p>Для снижения конкуренции (событие ожидания "library cache: mutex X") за объекты в библиотечном кэше предназначена процедура <a href="http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_shared_pool.htm#ARPLS73476">MARKHOT</a> системного пакета DBMS_SHARED_POOL. Данная процедура производит размножение (создает копии) указанного объекта (пакета, процедуры, курсора и т.д.) в библиотечном кэше, и тем самым снижает конкуренцию за мьютексы.</p>
<p>
Недавно, общаясь с одним очень крупным заказчиком, высоконагруженные БД которого работают на больших Hi-End серверах, была затронута тема использования технологии <a href="http://www.igormelnikov.com/2013/11/oracle-database-12c-r1-edition-base.html">Edition Base Redefinition</a> для безостановочного обновления приложений. Этот заказчик очень активно использует процедуру MARKHOT в своих БД.<br>
Основной вопрос, который волновал заказчика, заключался в поддержке процедурой MARKHOT технологии Edition Base Redefiniton: работает ли вышеописанное размножение объектов в кэше для разных версий (editions) объекта?<br> В явном виде в процедуре MARKHOT не фигурирует версия объекта (edition в которой он был определен).
Давайте разберемся в этом вопросе. Поскольку в данный момент заказчик использует Oracle Database 11.2.0.3, проверим именно на этой версии СУБД.
</p>
Создадим отдельного пользователя и новую версию (edition), выдав права на использование этой версии и включив потенциальную версионируемость в вновь созданной схеме:
<code><pre>
[oracle@localhost ~]$ <b>sqlplus / as sysdba</b>
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> <b>CREATE USER test_markhot
2 IDENTIFIED BY oracle;</b>
User created.
SQL> <b>GRANT connect, resource TO test_markhot;</b>
Grant succeeded.
rem Coздаем новую версию (edition), которая наследуется от ORA$BASE
SQL> <b>CREATE EDITION version_2 AS CHILD OF ora$base;</b>
Edition created.
rem Даем права пользователю на использование версии (edition)
SQL> <b>GRANT USE ON EDITION version_2 TO test_markhot;</b>
Grant succeeded.
rem Включаем для созданной схемы потенциальную версионируемость
SQL> <b>ALTER USER test_markhot ENABLE EDITIONS;</b>
User altered.
</pre></code>
Далее подключимся к БД под вновь созданным пользователем <i>test_markhot</i> и создадим две версии одной и той же процедуры: в версиях <i>ORA$BASE</i> и <i>version_2</i> соответственно.
<code><pre>
SQL> <b>conn test_markhot/oracle</b>
Connected.
rem Проверяем версию, в которую мы вошли (должна быть по умолчанию - ORA$BASE)
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL>
SQL> <b>create or replace procedure myproc is
k simple_integer := 0;
begin
k := 1;
end;</b>
/
Procedure created.
rem Переключаемся в версию VERSION_2
SQL> <b>ALTER SESSION SET EDITION=version_2;</b>
Session altered.
SQL> <b>show edition</b>
EDITION
------------------------------
VERSION_2
rem Создадим новую версию нашей процедуры myproc
SQL> <b>create or replace procedure myproc is
k simple_integer := 0;
begin
k := <font color="red">2;</font>
end;</b>
/
Procedure created.
</pre></code>
Далее, для удобства откроем отдельную сессию под пользователем SYS, и проверим наличие нашей процедуры MYPROC в библиотечном кэше помеченной как "горячий" объект, то есть для которой был выполнен вызов DBMS_SHARED_POOL.MARKHOT:
<code><pre>
[oracle@localhost ~]$ <b>sqlplus / as sysdba</b>
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> <b>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';</b>
no rows selected
SQL>
</pre></code>
Все верно: поскольку мы еще не вызывали процедуру MARKHOT, - процедуры MYPROC в списке "горячих" нет.
Для удобства сохраним вышеприведенный запрос в файле <i>hotlist.sql</i><br>
Находясь под пользователем SYS в версии ORA$BASE пометим нашу нашу процедуру как горячую:
<code><pre>
SQL> <b>show edition</b>
EDITION
------------------------------
ORA$BASE
SQL> <b>EXEC dbms_shared_pool.markhot('TEST_MARKHOT','MYPROC',1);</b>
PL/SQL procedure successfully completed.
SQL <b>@hotlist.sql</b>
KGLNAOWN KGLNAOBJ KGLHDNSP KGLNAHSH KGLHDADR KGLHDOBJ KGLOBPROP TYPH
-------------- -------------------- ---------- ---------- ---------------- ---------------- ---------- ----
TEST_MARKHOT MYPROC 1 3513693258 0000000085E5F538 00 HOT ROOT
</pre></code>
Как Вы видите, - наша процедура MYPROC была помечена как горячая. При этом вызов dbms_shared_pool.markhot создал handler на процедуру MYPROC в библиотечном кэше.<br>
Попробуем выполнить процедуру MYPROC в версии ORA$BASE (под владельцем - пользователем <i>test_markhot</i>):
<code><pre>
SQL> <b>ALTER SESSION SET edition=ora$base;</b>
Session altered.
SQL> <b>show edition</b>
EDITION
------------------------------
ORA$BASE
SQL> <b>EXEC myproc</b>
PL/SQL procedure successfully completed.
SQL> </pre></code>
и проверим содержимое библиотечного кэша (в другой сессии конечно, - под пользователем SYS):
<code><pre>
SQL> <b>@hotlist</b>
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
</pre></code>
Пока все работает штатно: в кэше были создана копия нашей процедуры.
Теперь собственно самая главная часть нашего эксперимента: пометим нашу процедуру как горячую в версии VERSION_2 и проверим содержимое library cache.
<code><pre>
SQL> <b>ALTER SESSION SET edition=version_2;</b>
Session altered.
SQL> <b>EXEC dbms_shared_pool.markhot('TEST_MARKHOT','MYPROC',1);</b>
PL/SQL procedure successfully completed.
SQL> <b>@hotlist</b>
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
</pre></code>
В кэше появился новый объект помеченный как "горячий"!
Вызовем нашу процедуру myproc в версии <i>VERSION_2</i>:
<code><pre>
SQL> <b>ALTER SESSION SET edition=version_2;</b>
Session altered.
SQL> <b>EXEC myproc;</b>
PL/SQL procedure successfully completed.
</pre></code>
и еще раз проверим содержимое library cache:
<code><pre>
SQL> <b>@hotlist</b>
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
</pre></code>
Теперь в кэше началось размножение процедуры myproc новой версии!
<p>
Процедура <i>dbms_shared_pool.markhot</i>, которая предназначена для установки метки на горячие объекты в library cache, полностью учитывает версии объектов и ее можно совместно использовать с технологией обновления приложений на лету - Edition Base Redefinition!
</p>
Хочу выразить большую благодарность Сергею Томину за помощь в подготовке этого примера!
Igor Melnikovhttp://www.blogger.com/profile/14474629761582968538noreply@blogger.com1