29 июл. 2016 г.

RACChecker - check application for RAC compatible

Тема разработки и адаптации приложений под RAC очень обширна и многогранна и затрагивает практически все аспекты создания прикладного ПО для СУБД Oracle Database. Но, тем не менее, для того чтобы гарантировать что ваше приложение корректно будет работать в RAC, необходимо убедиться, что оно не использует технологии и механизмы которые в RAC в не работают, либо работают с особенностями. Подробно требования к приложению описаны в документе "Oracle RAC Database aware Applications - Developer’s Checklist". Вот перечень этих технологий:
  • каналы (пакет DBMS_PIPE) - не синхронизируются между узлами кластера;

  • объекты БД типа DIRECTORY (каталоги в файловой системе) должны располагаться на разделяемом сторадже и должны быть видны всем узам кластера;

  • вместо V$-представлений нужно использовать соответствующие GV$-представления;

  • задания управляемые через пакет DBMS_JOB - крайне не рекомендуется использовать в RAC, поскольку задания этого пакета не поддерживают сервисы.


    Методы борьбы с вышеперечисленными технологиями мы подробно рассматривали на культовом семинаре "RAC Deep Dive for Developers"

    Довольно часто приложение имеет большие объемы PL/SQL-кода (сотни тысяч и даже миллионы строк кода), и вспомнить о том, в каком месте используется тот же DBMS_PIPE крайне сложно: код давно отлажен и работает, а его автор уже давно не работает в компании.
    Для того, что облегчить анализ серверной части кода (хранимых процедур PL/SQL) мною была разработана утилита RACChecker. Эта утилита поможет быстро ответить на вопрос: готово ли, в минимальной степени, ваше приложение при переходе в RAC.
    RACChecker анализирует ваш исходный код и находит объекты и строки кода, где вы используете технологии, которые в RAC не работают.

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


Я думаю, что из списка параметров очевидно их назначение.
Следует обратить внимание лишь на следующие моменты:

  • пользователь в строке подключения (параметр USERID) должен иметь права на чтение словаря (dictionary);

  • утилита опционально может находить некэшируемые последовательности (с ними тоже возможны проблемы в RAC);

  • возможна выгрузка DDL-скриптов для плохих объектов с помощью параметра SAVE_SOURCE=Y;

  • для своей работы утилита требует установленной среды выполнения .NET Framework 4.5, а также ODP.NET Provider 12.1.0.2.4 - рекомендуется установить версию поставляемую с Instant Client - она небольшая по размеру.

Конечно, никакого волшебства в работе этой утилиты нет: она всего лишь анализирует соответствующие представления словаря.

Утилита может находить факт использования неработающих в RAC технологий (например: пакет DBMS_PIPE), даже если PL/SQL-код зашифрован (wrapped). Утилита на "лету" определяет что код зашифрован, и в этом случае анализирует не исходный код, а зависимости от пакетов dbms_pipe,dbms_job.
Утилита НЕ может обнаружить факт использования этих пакетов только в одном случае: если они используются через динамический PL/SQL (EXECUTE IMMEDIATE или DBMS_SQL) и код зашифрован.

Утилита определяет факт использования пакетов внутри однострочных коментариев. Это не приводит к ложному срабатыванию. Многострочные комментарии, к сожалению, не поддерживаются. При анализе последовательнойстей можно задать минимальный размер их кеша (параметр MIN_SEQ_CACHE). В этом случае будут выведены все последовательности, размер кэша которых меньше этого минимума.

За время своего существования утилита RACChecker постоянно развивалась, и помогла очень многим заказчикам перенести свои существующие приложения в среду Oracle Real Application Cluster.

C помощью RACChecker вы быстро определите проблемные места при переходе в RAC!

Ссылка для скачивания: RACChecker.

12 апр. 2016 г.

Real-Time Database Operation Monitoring в Oracle Database 12c

Технология мониторинга SQL-запросов в режиме реального времени (Real-Time SQL Monitoring ), которая появилась в Oracle Database 11g, позволяет администраторам и разработчикам взглянуть внутрь каждого долго выполняющего запроса.
Для каждого долго выполняющегося запроса можно увидеть его реальный план выполнения, количество обработанных строк, расхождение ожидаемой и фактической кардинальности (количество ожидаемых и количество фактических строк) на каждом шаге плана запроса. Также можно увидеть различные метрики SQL-запроса: CPU, I/O requests, throughput, PGA, temp space.
В том числе можно производить мониторинг статистики ввода-вывода для каждого шшага запроса.

В свое время технология Real-Time SQL Monitoring была большим шагом вперед для ответа на вопрос "Что реально происходит в базе данных?".

Рис 1. Мониторинг выполнения запроса с помощью Real-Time SQL Monitoring

Вместе с тем, вышеописанная технология позволяет производить мониторинг только на уровне отдельного запроса. Очень часто необходимо отслеживать выполнение на уровне отдельных бизнес-операций в приложении. Поскольку бизнес-операция, в приложении состоит из нескольких запросов, приходиться вручную сопоставлять выполняющиеся запросы к конкретной бизнес-операции, например: "Расчет зарплаты". Особенно актуальной эта задача становится при возникновении проблем с производительностью кричичных для бизнеса операций.

Рассмотрим такой типичный случай.
При возникновении проблемы с производительностью расчета зарплаты, конечный пользователь обращается к администратору СУБД. DBA должен среды сотен (возможно и тысяч!) выполняющихся запросов, выделить запросы относящиеся к расчету зарплаты, выяснить какие из них сейчас выполняются и, затем, наконец, разобраться в причинах медленной работы этой бизнес-операции.
Для идентификации запросов часто приходится обращаться к разработчикам приложения и анализировать его исходный код. Все это часто приводит к взаимным обвинениям администраторов и разработчиков.
Не правда-ли: знакомая картина?

СУБД Oracle Database 12c предлагает решение и этой проблемы, позволяя производить мониторинг на уровне составных бизнес-операций.
Эта технология получила название Real-Time Database Operation Monitoring, и позволяет осуществлять мониторинг в режиме реального времени в терминах бизнес-процессов (бизнес-операций) выполняющихся в данный момент в СУБД.
Очевидно, что СУБД ничего "не знает" про бизнес-процессы, и для этого приложению необходимо каким-либо образом сообщить об этом базе данных: сгруппировать обращения к СУБД в бизнес-операции.

Для того, чтобы выделить в потоке обращений к СУБД бизнес-операцию, предлагается специальный API (Application Program Interface), реализованный в виде PL/SQL-пакета DBMS_SQL_MONITOR.
Пакет DBMS_SQL_MONITOR стандартно поставляется в составе СУБД и устанавливается по умолчанию - то есть входит в состав стандартных системных пакетов Oracle Database 12с.
Для выделения начала бизнес-операции предназначена процедура BEGIN_OPERATION данного пакета, для окончания бизнес-операции - END_OPERATION.

Возвращаясь к вышеописанному примеру с расчетом заработной платы, ее мониторинг в исходном коде хранимой PL/SQL-процедуры может быть оформлен следующим образом:
 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;
Параметр forced_tracking процедуры BEGIN_OPERATION аналогичен хинту MONITOR в запросе: при его установке (forced_tracking => 'Y'), мониторинг бизнес-операции производится в любом случае. В противном случае - мониторинг производится только в случае, если бизнес-операции по продолжительности выполнения занимает 5 и более секунд ЦПУ или ввода-вывода. Запустим наш модифицированный бизнес-процесс расчета зарплаты и посмотрим, как он теперь отображается на экране SQL Monitoring консоли администрирования Enterprise Manager 12c. В списке выполняющихся запросов появился запрос c "говорящим" именем "Расчет зарплаты":

Рис 2. "Расчет зарплаты" в списке запросов на экране SQL Monitoring

Перейдя внутрь выполняющейся бизнес-операции - для этого нужно кликнуть мышью на SQL_ID операции (в нашем случае: "Расчет зарплаты"), можно увидеть страницу детальной информации: какие запросы из состава бизнес-операции уже выполнились, и какой запрос является текущим - выполняется в данный момент:

Рис 3. Детальная информация о выполнении бизнес-операции

"Провалившись" внутрь любого запроса в бизнес-операции, можно увидеть знакомый по предыдущим версиям экран SQL-мониторинга запросов.

После завершения бизнес-операции входящие в него запросы точно также доступы для анализа, как это и было раньше (в СУБД Oracle Database 11g) для уже завершившихся SQL-запросов.
Рис 4. Бизнес-операция "Расчет зарплаты" завершена

Для того, чтобы сгруппировать запросы в бизнес-операции из приложений Java и С++/C-приложений, соответствующий клиентский API доступа к БД (JDBC и OCI, соответственно) также был расширен.
Вот так, например, выглядит выделение бизнес-операции в Java-приложении:

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);
Если Вы разрабатываете приложение сразу для разных версий СУБД Oracle Database, то можете воспользоваться условной компиляцией PL/SQL, чтобы иметь один и тотже код в независимости от версии БД:
 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;
Объявление переменной v_xDBOpId нет смысла обрамлять в символ условной компиляции,поскольку при компиляции в СУБД Oracle Database 11g, PL/SQL-оптимизатор удалит её из исходного кода, поскольку она является "мертвой" - нигде не используется.

Продолжение следует ...