Русский
Русский
English
Статистика
Реклама

Oracle

Логирование событий в Oracle PLSQL

31.03.2021 16:16:13 | Автор: admin
рис. Старый "дедовский" debug кодарис. Старый "дедовский" debug кода

Добрый день! Работая разработчиком Oracle PL/SQL, часто ли вам приходилось видеть в коде dbms_output.put_line в качестве средства debug-а? Стоит признать, что к сожалению, большинство (по моему личному мнению и опыту) разработчиков Oracle PL/SQL не уделяет должного внимания логированию как к спасательному кругу в случае возникновения ошибок. Более того, большая часть разработчиков не совсем понимает зачем нужно логировать информацию об ошибках и самое главное, не совсем понимают что делать и как использовать эту информацию в будущем.

Предисловие

Данным постом хотел бы начать цикл статей посвященных Логированию ошибок в Oracle PL/SQL. В первую очередь донести мысль до многих разработчиков, о том как можно построить функционал фиксации, хранения логов в БД. На своем опыте продемонстрировать поэтапный процесс создания полноценного логирования в БД. Рассказать как нам удалось создать логирование ошибок, разработать единую нумерацию событий для их дальнейшей идентификации, как поверх логирования натянуть мониторинг событий, создать функционал позволяющий увидеть все текущие ошибки в БД в виде таблиц (с указанием частоты возникновения ошибок и кол-ва и т.д.), графиков (отразить динамику роста кол-ва ошибок) и правильно распределить ресурсы для устранения тех или иных ошибок.

Оговорюсь сразу, что на рынке возможно уже есть успешные существующие коммерческие продукты осуществляющие логирование гораздо лучше и качественнее хотя бы, потому что у них есть многолетний опыт внедрения и сопровождения своего продукта в различных компаниях. Я же хочу показать один из множества примеров реализации функционала логирования, которые вполне можно осуществить силами своих разработчиков.

Введение

В этой и следующих статьях будет показано как реализованный функционал логирования позволяет фиксировать факт возникновения не только ошибок (сообщение с типом Error), но и сообщений с предупреждением (тип Warning), информативных сообщений (с типом Info) и т.д., поэтому, в рамках данных статей введём термин - Модель логирования событий (далее по тексту - "модель") или коротко Логирование событий, где под "событием" подразумевается некоторое ожидаемое действие, возникшее в ходе штатной/внештатной работы алгоритма.

Модель логирования позволяет реализовать:

  1. Единый подход в обработке и хранении событий

  2. Собственную нумерацию и идентификацию событий происходящих в БД

  3. Единый мониторинг событий

  4. Анализ событий происходящих в БД

Описанные выше характеристики указаны в порядке нумерации и каждый следующий пункт (шаг) есть улучшение и усложнение существующей модели. Описание этой модели будет сложно выполнить в рамках одной статьи, поэтому опишем их последовательно. Начнём с первого пункта.

Единый подход в обработке и хранении событий

Основной идеей "Единого подхода в обработке и хранении событий" заключается в создании одного одновременно простого и в тоже время очень сложного правила: "Все объекты базы данных (функции, процедуры) в обязательном порядке должны завершаться блоком обработки исключений с последующим логированием события". Простота заключается в том, что легко, в команде разработчиков, на словах договориться об исполнении данного правила. Сложность же заключается в том, что данное правило должно быть установлено на ранних этапах создания вашей БД и выполняться обязательно на протяжении всего жизненного цикла. Внедрить функционал логирования в уже существующие и действующие БД очень сложно (практически не возможно).

Все объекты базы данных (функции, процедуры) в обязательном порядке должны завершаться блоком обработки исключений с последующим логированием события

Наверное сейчас кто-то из читателей может возразить: "Зачем в обязательном порядке?". А всё очень просто, если вы разработчик PL/SQL и вы не согласны с этим правилом, то вот вам пример. Посмотрите на свой текущий проект более внимательно. Скорее всего вы найдете какое-нибудь логирование событий реализованное кем-то, когда-то. Вспомните сколько раз вы обращались к этому логированию при решении багов. Именно в таких ситуациях, когда есть срочность по времени в исправлении бага, вы или ваши коллеги начинают использовать dbms_output.put_line в качестве экспресс-дебага (быстрый способ получения значений переменных используемых в коде). Согласитесь, что для исправления бага мало знать в какой процедуре, в каком запросе и на какой строке возникла ошибка, необходимо знать параметры запроса на которых возникает ошибка. И вот тут нам на помощь приходит "Логирование событий", потому что помимо места возникновения ошибки мы узнаем параметры вызова процедуры, в которой возникает ошибка и это очень упрощает исправление бага.

Первая статья посвящена базовому функционалу Логирования событий. В простейшей реализации это одна общая таблица и пакет процедур для работы с ней. Для создания и демонстрации логирования, нам необходимо реализовать следующие объекты БД (весь список объектов с их исходными кодами представлен в Git):

  1. Таблица messagelog - единая таблица логов. Именно в данной таблице будет храниться информация о дате и времени события, об объекте где происходит событие, типе события с указанием кода, текста и параметров. В нашем примере, столбец backtrace вынесен в отдельную таблицу messagelog_backtrace для удобства.

    Примечание. Представленное ниже описание таблицы является демонстрационным с минимальным набором столбцов для создания простейшего функционала логирования. Наличие дополнительных столбцов и их тип данных может меняться в зависимости от целей и задач логирования.

    Структура таблицы

    Название столбца

    Тип данных

    Комментарий

    id

    number primary key

    Первичный ключ таблицы

    objname

    varchar2(60)

    Содержит наименование объекта из которого было инициировано событие. Чаще всего это комбинация имя_пакета.имя_процедуры

    msgtype

    varchar2(3)

    Тип события, например: ERR - сообщение от ошибке; INF - информационное сообщение; WRN - сообщение с предупреждением и т.д.

    insertdate

    date

    Дата и время создания записи о событии

    msgcode

    varchar2(10)

    Код ошибки, чаще всего это SQLCODE, либо код ошибки из справочника ошибок (об этом будет отдельная статья)

    msgtext

    varchar2(500)

    Текст ошибки, чаще всего это SQLERRM, либо текст ошибки из справочника ошибок

    paramvalue

    varchar2(500)

    Наименования параметров процедуры/функции и их значения. При анализе ошибок удобно видеть с каким параметрами была запущена та или иная процедура, выполнить повторный запуск этой процедуры с указанными параметрами и воспроизвести ошибку

    backtrace

    varchar2(4000)

    Записывается результат функции dbms_utility.format_error_backtrace, либо иная дополнительная информация

    Исходный код таблицы
    create table messagelog(id         number(38)      not null,                        msgtype    varchar2(3)     not null,                        objname    varchar2(60)    default null,                        insertdate date            default sysdate,                        msgcode    varchar2(10)    default null,                        msgtext    varchar2(4000)  default null,                        paramvalue varchar2(4000)  default null,                        constraint pk_messagelog_id primary key (id))partition by range (insertdate)  interval (numtoyminterval(3, 'MONTH'))    (partition p1 values less than (to_date('01.01.2020', 'DD.MM.YYYY'))); 
    

    *Исходный код других используемых объектов смотрите в Git

    В данной статье не будем подробно описывать способы индексирования и партицирования таблицы, всё зависит от целей и задач логирования. Самый предпочтительный вид хранения таблицы это партицирование по столбцу insertdate с интервалом 3 месяца.

    Отдельно стоит упомянуть про столбцы msgtext, paramvalue и backtrace. По своему опыту скажу, что указанные столбцы в 60% - 70% случаев будут пустыми и это очень сильно не нравится архитекторам и/или руководителям отделов разработки. Поэтому иногда есть смысл вынести указанные столбцы в отдельную таблицу с привязкой по id записи. В нашем примере столбец backtrace вынесен в отдельную таблицу messagelog_backtrace (см. исходный код в git).

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

    Исходный код процедур пакета
    -- процедура логирования ошибокprocedure p_log_err(p_objname    in varchar2,                    p_msgcode    in varchar2,                    p_msgtext    in varchar2 default null,                    p_paramvalue in varchar2 default null,                    p_backtrace  in varchar2 default null)  is  begin    p_insert_log(p_msgtype_    => 'ERR',                 p_objname_    => p_objname,                 p_insertdate_ => sysdate,                 p_msgcode_    => p_msgcode,                 p_msgtext_    => p_msgtext,                 p_paramvalue_ => p_paramvalue,                 p_backtrace_  => p_backtrace);  end p_log_err;    -- корневая процедура логирования  procedure p_insert_log(p_msgtype_    in varchar2,                         p_objname_    in varchar2,                         p_insertdate_ in date,                         p_msgcode_    in varchar2,                         p_msgtext_    in varchar2 default null,                         p_paramvalue_ in varchar2 default null,                         p_backtrace_  in varchar2 default null)  is    v_id   messagelog.id%type;    pragma autonomous_transaction;  begin    insert into messagelog(msgtype,                           objname,                           insertdate,                           msgcode,                           msgtext,                           paramvalue,                           backtrace)        values(p_msgtype_,               p_objname_,               p_insertdate_,               p_msgcode_,               p_msgtext_,               p_paramvalue_,               p_backtrace_)    return id      into v_id;    if trim(p_backtrace_) is not null then      insert into messagelog_backtrace(id,                                       backtrace)      values(v_id,             trim(p_backtrace_));    end if;    commit;  end p_insert_log;
    

    *Исходный код других используемых объектов смотрите в Git

  3. Тестовый пакет pkg_clients - пакет с демонстрационными процедурами поиска и создания пользователей. Обратите внимание, что процедура p_insert_user выполняет функции аудита события - "создание нового пользователя".

    Исходный код процедур поиска и создания пользователей
    create or replace package body pkg_clients as  procedure p_insert_user(p_login_     in varchar2,                          p_firstname_ in varchar2,                          p_lastname_  in varchar2,                          p_id_        out number)  is    v_id clients.id%type;  begin    insert into clients(login,                        firstname,                        lastname)        values(upper(p_login_),               p_firstname_,               p_lastname_)    return id      into v_id;    if v_id > 0 then      -- аудит события - создание нового пользователя      pkg_msglog.p_log_wrn(p_objname    => 'pkg_clients.p_insert_user',                           p_msgcode    => '101',                           p_msgtext    => 'Создан новый пользователь с id = '||v_id,                           p_paramvalue => 'p_login = '||p_login_                                             ||', p_firstname = '||p_firstname_                                             ||', p_lastname = '||p_lastname_);    end if;    commit;  exception    when others then      pkg_msglog.p_log_err(p_objname    => 'pkg_clients.p_insert_user',                           p_msgcode    => SQLCODE,                           p_msgtext    => SQLERRM,                           p_paramvalue => 'p_login_ = '||p_login_                                             ||', p_firstname_ = '||p_firstname_                                             ||', p_lastname_ = '||p_lastname_,                           p_backtrace  => dbms_utility.format_error_backtrace);      rollback;  end p_insert_user;    procedure p_create_user(p_login     in varchar2,                          p_firstname in varchar2,                          p_lastname  in varchar2,                          p_id        out number)  is    v_id clients.id%type;  begin    begin      select id        into v_id        from clients       where login = upper(p_login);    exception      when no_data_found then        p_insert_user(p_login_     => p_login,                      p_firstname_ => p_firstname,                      p_lastname_  => p_lastname,                      p_id_        => v_id);    end;       p_id := v_id;  exception    when others then      pkg_msglog.p_log_err(p_objname    => 'pkg_clients.p_create_user',                           p_msgcode    => SQLCODE,                           p_msgtext    => SQLERRM,                           p_paramvalue => 'p_login = '||p_login                                             ||', p_firstname = '||p_firstname                                             ||', p_lastname = '||p_lastname,                           p_backtrace  => dbms_utility.format_error_backtrace);  end p_create_user;end pkg_clients;
    

    *Исходный код других используемых объектов смотрите в Git

Демонстрация логирования событий

Для демонстрации работы выполним три стандартных кейса с помощью созданного ранее пакета pkg_clients.

  1. (Ошибочная ситуация) Создание пользователя с длиной имени превышающей допустимое значение в таблице

    Пример 1
    рис. пример запуска процедурырис. пример запуска процедуры

    Результат

    рис. описание ошибкирис. описание ошибки
  2. (Ошибочная ситуация) Создание пользователя с пустым значением имени или фамилии (предположим, что есть такое требование)

    Пример 2
    рис. пример запуска процедурырис. пример запуска процедуры

    Результат

    рис. описание ошибкирис. описание ошибки
  3. (Успешная ситуация) Создание нового пользователя с аудитом события

    Пример 3
    рис. пример запуска процедурырис. пример запуска процедуры

    Результат

    рис. описание ошибкирис. описание ошибки

    Обратите внимание, что все демонстрационные процедуры завершаются блоком exception when others then с дальнейшим вызовом процедуры логирования события вне зависимости от "важности" процедуры.

Заключение

В заключении я повторюсь, что гораздо проще и правильнее добавлять логирование событий в обработку исключений при первом написании процедуры (функции) т.к. это не занимает много времени. Гораздо сложнее в будущем, внести правки в большое количество объектов БД и это займет гораздо больше времени на написание кода, тестирование и т.д.

По своему опыту отмечу, что пакет pkg_msglog (со всеми дополнительными объектами логирования) должен быть создан самым первым в проектируемой БД и в дальнейшем другие объекты создаются с логированием событий. Также, часто в командах появляются разработчики, которые говорят: "Зачем логировать все процедуры (функции)? Давайте вести логирование только важных и нужных процедур (функций)!". Вот здесь скрывается самая главная и распространенная ошибка. У всех нас разное понимание что есть "важная и нужная" процедура (функция). По сути, вы создаете логирование ошибок, которое "как бы и есть, но как бы его нет" т.е. все в команде знают, что в БД есть лог ошибок, но в нужный момент (например, при возникновении "блокера" на продакшн) вы обнаружите что в логах нет никакой информации об ошибке. Именно в такие моменты и возникает ошибочное мнение, что логировать события бесполезно и бессмысленно, а ведь это не так.

В следующей статье я расскажу как доработать "Логирование событий", чтобы мы могли идентифицировать события (установить принадлежность события к конкретному бизнес-процессу), установить приоритет события и максимально быстро реагировать на факт появления таких событий.

Спасибо за внимание.

Подробнее..

Настройка CICD скриптов миграции БД с нуля с использованием GitLab и Liquibase

17.05.2021 14:19:21 | Автор: admin

Пролог

Добрый день, уважаемые читатели. Совсем недавно мне пришлось осваивать новую для себя область CI/CD, настраивая с нуля доставку скриптов миграции базы данных в одном из проектов. При этом было тяжело преодолеть самый первый этап "глаза боятся", когда задача вроде бы ясна, а с чего начать, не знаешь. Однако вопрос оказался на поверку значительно проще, чем казалось изначально, давая при этом неоспоримые преимущества ценой нескольких часов работы и не требуя никаких дополнительных средств, кроме обозначенных в заголовке.

Полученным опытом я решил поделиться в данной статье, чтобы помочь тем, кто хочет автоматизировать свои рабочие процессы, но не знает, с чего начать.

Оглавление

Введение

Об авторе

Меня зовут Копытов Дмитрий, я являюсь главным разработчиком и архитектором проектов. Специализируюсь на C#/.NET, Vue.js и Postgres.

К теме CI/CD пришел после получения "в наследство" проекта с уже существующим CI/CD, который пришлось перерабатывать.

О статье

В первую очередь статья предназначена для разработчиков, которые хотят внедрить в свои проекты CI/CD, но не знают, с чего начать, а также для тех, кому в наследство достались проекты с уже внедренным CI/CD, суть работы которого им не понятна.

Целью статьи является подробное описание технических аспектов настройки связки GitLab + Liquibase на конкретном примере, а также основы теории, чтобы у читателя отложилась не только сама инструкция, но и понимание процесса. Многие моменты и возможности GitLab CI/CD & Liquibase будут сознательно опущены во избежание перегрузки информацией.

Уже после написания большей части статьи, осознал насколько она оказалась большая, но разбить ее на несколько частей не вижу возможности без потери целостности. Приготовьтесь, будет многобукофф.

Перед самой публикацией во время выбора хабов обнаружил схожую статью по автоматизации деплоя Liquibase. Это досадная случайность без злого умысла, не более.

Кулинарный рецепт

Для приготовления блюда нужны следующие ингредиенты:

  • GitLab Community Edition хранилище Git

  • GitLab Runner рабочая лошадка CI/CD

  • Liquibase, на момент написания статьи версия 4.3.4

  • Драйвер Liquibase для целевой БД

  • Выделенный сервер с установленными Liquibase и GitLab Runner и доступом к целевой БД для наката скриптов и к GitLab для получения исходников. Необязательно.

  • 3 чашки чая или кофе. Обязательно.


Основы

Используемые технологии

Все технологии, используемые в статье, являются открытыми, вы можете использовать их совершенно бесплатно без необходимости закупки Premium-фич.

Примеры из статьи (скрипты и конфиги) опубликованы на гитхабе: https://github.com/Doomer3D/Gliquibase.

GitLab CI/CD

CI/CD у всех на слуху, поэтому не буду вдаваться в детали, отмечу только, что в контексте статьи будет рассмотрен процесс автоматического (при мерже/коммите) или ручного (по команде) наката скриптов миграции базы данных на целевую среду, будь то дев или прод. В качестве конвейера будут использоваться GitLab pipelines, а непосредственным исполнителем будет GitLab Runner, поэтому если вы не используете GitLab в качестве хранилища, статья вам будет по большому счета бесполезна.

Все примеры будут рассмотрены в контексте используемого в нашей компании GitLab Community Edition13.x.

Liquibase

Liquibase (ликви) платформа c открытым кодом, которая позволяет управлять миграциями вашей базы. Если кратко, то Liquibase позволяет описывать скрипты наката и отката базы в виде файлов чейнжсетов (changeset). Сами скрипты при этом могут быть как обычными SQL-командами, так и БД-независимыми описаниями изменений, которые будут преобразованы в скрипт конкретно для вашей базы. Список поддерживаемых БД можно найти здесь: https://www.liquibase.org/get-started/databases.

Liquibase написан на Java, поэтому может быть запущен на любой машине с JVM.

В статье будет рассмотрен Oracle 19 в качестве целевой базы, потому что именно для него настраивал деплой на рабочем проекте. Но, как писал выше, тип базы не имеет принципиального значения.

Схема работы

В данном разделе я сначала хотел нарисовать схему, но быстро понял, что давно не рисовал диаграммы процессов, поэтому постараюсь объяснить на пальцах.

Когда разработчик делает коммит или мерж реквест, запускается конвейер CI/CD, называемый пайплайном (pipeline), который включает в себя этапы (stage), состоящие из джобов (job).

В нашем примере будет один этап деплой (deploy), т.е. применение скриптов наката. При этом будет столько джобов, сколько стендов мы имеем. Предположим, что у нас всего два стенда дев и прод. Соответственно, будет два джоба деплой на дев (deploy-dev) и деплой на прод (deploy-prod), которые будут отличаться целевой БД. Кроме того, деплой на прод мы хотим запускать только вручную, по команде, а не в момент мержа или коммита.

Джобы обрабатываются раннером (GitLab Runner) специальной программой, которая скачивает себе исходники проекта и выполняет скрипты на сервере деплоя, при этом раннеру передаются различные параметры в виде переменных окружения. Это может быть пользовательская информация, хранимая в настройках проекта, такая как адрес и логин/пароль сервера БД, а также информация о самом процессе CI/CD, например, название ветки, автор, текст коммита и т.п.

Важно! Раннер сам обращается к GitLab по http, а не наоборот, поэтому машина с раннером должна иметь доступ к GitLab, в то время как разработчик и сервер GitLab могут ничего не знать о машине, где находится раннер.

Если оба стенда дев и прод, доступны с одной машины, достаточно будет одного раннера, однако обычно прод находится в другой сети, тогда в ней должен быть отдельный раннер с доступом к БД прода.

В нашем случае раннер будет вызывать Liquibase через командную строку. В параметрах к Liquibase будет передана информация о целевой базе и используемом драйвере, а сами скрипты наката Liquibase сформирует из описаний миграций из файлов вашего проекта.

В случае успеха, если скрипты отработали без ошибок, пайплайн считается успешным, а мерж реквест вливается в ветку. Картина будет примерно такой:

В противном случае пайплайн будет в состоянии failed:

Мы сможем провалиться в джоб и посмотреть логи, чтобы найти ошибку или перезапустить пайплайн, если проблема была в сетевом доступе. В моей практике была ситуация, что поднятый VPN на машине деплоя в какой-то момент стал блокировать доступ к GitLab по доменному имени, при этом пайплайн оказывался в состоянии pending, т.е. ожидал, что раннер подхватит джоб, но этого не происходило. Правка hosts и перезапуск пайплайна разрешили проблему.

Итак, подытожим, как выглядит схема работы:

  1. Разработчик делает мерж реквест или коммит в ветку.

  2. Запускается пайплайн, который исполняет ассоциированный с этой веткой джоб.

  3. Джоб инициирует раннер, находящийся на удаленной машине.

  4. Раннер скачивает исходники и выполняет скрипт, вызывающий Liquibase.

  5. Liquibase генерирует и исполняет скрипты наката/отката.

  6. ...

  7. Profit!

А теперь обо всем по порядку.


Liquibase

Этот раздел посвящен Liquibase. Здесь не будет полного изложения документации, потому что эта тема для отдельной статьи или даже для цикла статей, но я постараюсь осветить основы Liquibase.

Ссылка на официальную документацию по Liquibase: https://docs.liquibase.com/concepts/basic/home.html

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

Liquibase это платформа управления и наката миграций БД. В основе лежит понятие чейнжсета (changeset) атомарного изменения базы. Чейнжсетом, например, может быть создание таблицы в базе, добавление колонки/триггера, или наполнение таблицы данными. Чейнжсеты объединяются в чейнжлоги (changelog), которые выстраиваются в цепочку, которая применяется на целевой БД последовательно, таким образом обновляя базу до актуального состояния.

changelog

Начнем рассмотрение Liquibase с понятия чейнжлога. Чейнжлог это отдельный файл, содержащий в себе чейнжсеты или ссылки на другие чейнжлоги. Порядок включения чейнжлогов/чейнжсетов определяет порядок их наката. Как и чейнжсеты, чейнжлоги могут быть описаны в одном из четырех форматов: SQL, XML, JSON и YAML. В статье будут рассмотрены форматы SQL и XML как наиболее популярные и удобочитаемые.

Один из чейнжлогов является корневым, т.е. именно от него идет раскручивание всей цепочки. Назовем его мастером и дадим имя master.xml. Этот чейнжлог несет в себе функцию аккумуляции ссылок на другие чейнжлоги. Изначально у нас в проекте был один такой аккумулятор, в который последовательно дописывались ссылки на другие файлы, которые складировались в той же папке. Это приводило к двум проблемам:

  • Папка со временем разрослась до гигантских размеров, и ориентироваться в ней стало невозможно.

  • Когда с файлом стали работать два разработчика, изменение файла неизбежно приводило к конфликтам, которые приходилось решать.

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

Структура проектаСтруктура проекта

Файлы Liquibase хранятся в папке db/changelog, в корне лежит мастер-файл master.xml

В отдельных папках, соответствующих релизам 156 и 157, складируются чейнжлоги. В общем случае один таск = один чейнжлог. Также отдельно выделена папка common для служебных целей, там лежит скрипт пре-миграции, который выполняется при каждом накате скриптов. Аналогичным образом можно было бы добавить скрипт пост-миграции, если это нужно.

Разберем файл master.xml:

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog"                   xmlns:pro="http://personeltest.ru/away/www.liquibase.org/xml/ns/pro"                   xmlns:xsi="http://personeltest.ru/away/www.w3.org/2001/XMLSchema-instance"                   xsi:schemaLocation="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.2.xsd     http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.2.xsd ">  <preConditions>    <dbms type="oracle" />  </preConditions>  <!-- предварительные скрипты -->  <include file="/common/pre_migration.xml" />  <!-- релизы -->  <includeAll path="/v156" relativeToChangelogFile="true" />  <includeAll path="/v157" relativeToChangelogFile="true" /></databaseChangeLog>

XML-файл выглядит несколько перегруженным неймспейсами, пусть это вас сильно не волнует. Это стандартная обертка для любого XML-файла Liquibase.

Раздел preConditions определяет различные параметры запуска, конкретно здесь мы указываем, что используем oracle, но также можно указать имя пользователя, от которого будет происходить запуск скриптов. Более плотно preConditions используются в чейнжсетах.

Далее идет включение скриптов в нужной последовательности. Для этого существуют команды include (включение отдельного файла) и includeAll (включение папки).

Использование includeAll позволяет избежать проблем с конфликтами при правке файла-аккумулятора внутри релиза, но тогда нужно выработать стратегию именования файлов, т.к. их включение будет происходить в алфавитном порядке. В примере выше я использую дату + номер таска, но этого будет недостаточно в реальном проекте, если изменения по таску с меньшим номером нужно применить после таска с большим номером, и при этом они будут в один день.

Как альтернативу includeAll вы можете внутри папки релиза создать свой мастер-файл (аккумулятор скриптов релиза), в который включать ссылки на отдельные скрипты, что в целом менее удобно.

changeset

Чейнжсеты описываются внутри файлов чейнжлогов в виде отдельных блоков. Рассмотрим на примере файла 2021-05-01 TASK-001 CREATE TEST TABLE.xml:

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog"                   xmlns:pro="http://personeltest.ru/away/www.liquibase.org/xml/ns/pro"                   xmlns:xsi="http://personeltest.ru/away/www.w3.org/2001/XMLSchema-instance"                   xsi:schemaLocation="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.2.xsd     http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.2.xsd ">  <changeSet author="Doomer" id="20210501-01">    <preConditions onFail="MARK_RAN">      <not>        <tableExists tableName="TEST"/>      </not>    </preConditions>    <createTable tableName="TEST" remarks="Тестовый справочник">      <column name="ID" type="NUMBER(28,0)" remarks="Идентификатор">        <constraints nullable="false" primaryKey="true" primaryKeyName="TEST_PK" />      </column>      <column name="CODE" type="VARCHAR2(64)" remarks="Код">        <constraints nullable="false" />      </column>      <column name="NAME" type="VARCHAR2(256)" remarks="Наименование">        <constraints nullable="false" />      </column>    </createTable>    <rollback>      <dropTable tableName="TEST" />    </rollback>  </changeSet></databaseChangeLog>

В файле описан чейнжсет, который создает таблицу TEST с тремя колонками. При этом описание происходит в виртуальных сущностях, которые транслируются в скрипты для конкретной БД.

Элемент preConditions указывает, что чейнжсет нужно применять только в случае, если таблица не существует в базе.

Элемент rollback указывает, как нужно откатывать скрипт, если такой механизм планируется использовать. Откаты в нашей стране, конечно, популярны, но выходят за рамки данной статьи.

Рассмотрим основные атрибуты чейнжсетов.

Атрибут

Описание

id

Идентификатор, обязательный атрибут, использование см. ниже.

author

Автор, обязательный атрибут, использование см. ниже.

dbms

Фильтр баз данных, для которых применяется чейнжсет.

contexts

Контексты, для которых применяется чейнжсет. Например, мы можем указать, что чейнжсет применяется только на проде или везде, кроме прода.

Подробнее по ссылке.

runAlways

Булево. Указывает, что чейнжсет применяется при каждом запуске. Полезно для скриптов установки контекста окружения, см. ниже.

runOnChange

Булево. Указывает, что чейнжсет применяется при изменении содержимого. Полезно для скриптов создания recreatable-объектов, таких как процедуры, вьюхи, триггеры и т.п.

Подробную документацию по чейнжсетам можно почитать по ссылке.

DATABASECHANGELOG

Чейнжсеты, которые были применены к базе, сохраняются в специальную таблицу DATABASECHANGELOG, в паре с которой идет таблица DATABASECHANGELOGLOCK, обеспечивающая параллельную работу нескольких экземпляров Liquibase.

В таблице нет физических ключей, но у самих чейнжсетов есть уникальный ключ это комбинация идентификатора, автора и имени файла. Политика именования чейнжсетов у всех может быть своя, у нас исторически сложился формат <дата>-<номер><ФИ автора>, например 20210501-01KD. Отмечу, что это мой первый проект с использованием Liquibase, поэтому не буду давать советов, как лучше именовать чейнжсеты.

Также у каждого чейнжсета вычисляется MD5-сумма на основе его тела, поэтому нельзя просто так менять файл чейнжсета, если он уже был применен к базе. Это может иметь значение при разработке, особенно при освоении Liquibase. Поначалу вы будете часто ошибаться с тем, как правильно составить чейнжсет, в итоге в базе окажется сохраненный чейнжсет с MD-5 суммой и неверно выполненный скрипт. В этом случае нужно будет вручную откатить его изменения, а также удалить соответствующие записи из DATABASECHANGELOG.

runAlways

База данных предоставляет инструменты для настройки контекста окружения, что может быть полезно, например, в сценарии аудита таблиц, когда записи, измененные скриптами, выполненных через Liquibase, нужно как-то помечать. Мы это решаем через установку переменной сессии USER_ID.

Для этой цели в описании мастер-чейнжлога включается скрипт пре-миграции, который занимается настройкой окружения. Приведу его текст:

<?xml version="1.0" encoding="UTF-8"?><databaseChangeLog xmlns="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog"                   xmlns:pro="http://personeltest.ru/away/www.liquibase.org/xml/ns/pro"                   xmlns:xsi="http://personeltest.ru/away/www.w3.org/2001/XMLSchema-instance"                   xsi:schemaLocation="http://personeltest.ru/away/www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.2.xsd     http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.2.xsd ">  <changeSet author="SYSTEM" id="PRE_MIGRATION" runAlways="true">    <sql splitStatements="true" stripComments="true">      -- устанавливаем в контекст сессии пользователя liquibase      CALL DBMS_SESSION.SET_CONTEXT('CLIENTCONTEXT','USER_ID', 13);    </sql>  </changeSet></databaseChangeLog>

Здесь в качестве тела используется SQL-скрипт, который записывает в переменную сессии USER_ID значение 13 наш внутренний идентификатор пользователя Liquibase. Этот скрипт будет влиять на все последующие скрипты, поэтому помечен флагом runAlways и включен перед скриптами релизов.

SQL-чейнжсет

Чейнжсеты можно оформлять и в формате SQL, что особенно полезно при написании сложных запросов. Рассмотрим файл 2021-05-01 TASK-002 TEST.sql, который выполняется сразу после создания таблицы TEST:

--liquibase formatted sql--changeset Doomer:20210501-02--preconditions onFail:MARK_RAN--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM ALL_TABLES WHERE TABLE_NAME = 'TEST' AND OWNER = 'STROY';--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM TEST WHERE ID = 1;insert into TEST (ID, CODE, NAME)values (1, 'TEST', 'Какое-то значение');--rollback not required--changeset Doomer:20210501-03--preconditions onFail:MARK_RAN--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM ALL_TABLES WHERE TABLE_NAME = 'TEST' AND OWNER = 'STROY';--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM TEST WHERE ID = 1;update TEST   set NAME = 'CONTEXT USER_ID=' || nvl(SYS_CONTEXT('CLIENTCONTEXT', 'USER_ID'), 'NULL') where ID = 1;--rollback not required

Это файл с двумя чейнжсетами в составе.

Первый добавляет новую запись в таблицу TEST, проверяя существование таблицы и отсутствие элемента с ID = 1. Если одно из условий не выполнится, чейнжсет не будет применен, но будет помечен в DATABASECHANGELOG как выполненный (MARK_RAN). Подробнее можно почитать в документации по preConditions.

Второй чейнжсет обновляет созданную запись значением из переменной сессии USER_ID.

После наката скриптов мы предсказуемо увидим следующую картину в таблице TEST:

К сожалению, формат статьи и ее и без того обширная тема не позволяет описать чейнжсеты Liquibase более подробно, но тут можно только сказать классическое RTFM.

Командная строка Liquibase

Liquibase является консольным приложением, поэтому нужно понимать, как его вызывать. Вообще, это тема больше относится к области GitLab Runner'а, но чтобы не смешивать обе темы, рассмотрим вызов Liquibase в этом разделе.

Документация по командам Liquibase: https://docs.liquibase.com/commands/community/home.html

Нас в первую очередь интересуют команды:

  • update применение изменений

  • updateSQL получение SQL-скриптов для анализа, полезно для обучения

Обе команды имеют схожий набор параметров, поэтому рассмотрим основные из них на нашем тестовом примере:

Параметр

Описание

Пример значения

changeLogFile

Путь к мастер-файлу чейнжлога, обязательный параметр

master.xml

url

Адрес БД, обязательный параметр

jdbc:oracle:thin:1.2.3.4:1521:orastb

username

Логин пользователя БД, обязательный параметр

vasya

password

Пароль пользователя БД, обязательный параметр

pupkin

defaultSchemaName

Имя схемы по умолчанию

DATA

contexts

Контекст БД для фильтров чейнжсетов по контексту

dev / prod

driver

Тип драйвера БД

oracle.jdbc.OracleDriver

classpath

Путь до драйвера

/usr/share/liquibase/4.3.4/drivers/ojdbc10.jar

outputFile

Путь до файла, куда выводить результат для команды updateSQL. Если не указано, вывод будет в консоль.

Для обучения можно создать батник, который будет запускать Liquibase c вашим скриптом до его добавления в гите. Разумеется, надо помнить о необходимости отката изменений (см. выше). Рядом помещаете папку с Liquibase и драйвером, об установке которых рассказывается в следующем разделе, а также файл скрипта.

Пример батника для Windows:

call "C:\Temp\liqui\liquibase-4.3.1\liquibase.bat" ^--defaultSchemaName=STROY ^--driver=oracle.jdbc.OracleDriver ^--classpath="C:\Temp\liqui\ojdbc5.jar" ^--url=jdbc:oracle:thin:@1.2.3.4:1521:dev ^--username=xxx ^--password=yyy ^--changeLogFile=.\master.xml ^--contexts="dev"--logLevel=info ^updateSQL

Настройка сервера деплоя

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

В нашей компании используются виртуальные машины на основе Centos 7, поэтому все примеры команд буду приводить именно для него. Также я исхожу из предположения, что вы знакомы с основами работы в консоли Linux.

Установка Java

Liquibase рекомендует использовать Java 11+, давайте установим его. Я использую OpenJRE 11:

sudo yum install java-11-openjdkjava --version

Установка Liquibase

Официальная документация: https://www.liquibase.org/get-started/quickstart

Liquibase не требует установки, потому что является программой на Java. Заходим на сайт и скачиваем архив с программой. Архив распаковываем в папку по вашему усмотрению, но для себя я решил использовать путь /usr/share/liquibase/<version>, например /usr/share/liquibase/4.3.4

Там же, в папке с установленным Liquibase, создаем папку drivers и копируем в нее нужный драйвер для вашей БД. В моем случае это был ojdbc10.jar

Проверяем, что Liquibase работает:

cd /usr/share/liquibase/4.3.4liquibase --version

Установка Git

Git является зависимостью GitLab Runner и ставится автоматически, но нужно отметить одну неприятную особенность, характерную для Centos 7 и, возможно, для других версий пингвинообразных. Если вы просто установите GitLab Runner на голую ось, он потянет за собой git в виде зависимости, который в стандартном репозитории имеет версию 1.8. Эта версия откровенно баганая, что в связке с GitLab приводит к тому, что в какой-то момент, причем не сразу, CI/CD перестает работать с выдачей совершенно непонятной ошибки.

Чтобы избежать неприятных сюрпризов, необходимо установить более свежую версию git до установки GitLab Runner:

# проверяем текущую версию гитаgit --version# удаляем гит, если он версии 1.8sudo yum remove git*# устанавливаем последнюю версию гита на момент написания статьи (2.30)sudo yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpmsudo yum install git

Установка GitLab Runner

Официальная документация: https://docs.gitlab.com/runner/install/linux-manually.html

# добавляем репуcurl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash# устанавливаемexport GITLAB_RUNNER_DISABLE_SKEL=true; sudo -E yum install gitlab-runner

Настройка GitLab Runner

В этом разделе будет рассказано о том, как создать и настроить свой экземпляр GitLab Runner, который будет вызывать Liquibase.

Ссылка на официальную документацию по GitLab Runner: https://docs.gitlab.com/runner/configuration/

Для начала, нужно узнать, куда был установлен раннер, и дать ему права на исполнение:

# определяем место установкиwhich gitlab-runner # /usr/bin/gitlab-runner# выдаем права на исполнениеsudo chmod +x /usr/bin/gitlab-runner

Далее, нужно создать пользователя для сервиса раннера и установить демона. Вполне возможно, что эти шаги уже были выполнены при установке.

# создаем пользователяsudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash# запускаем демонаsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner

Управлять сервисом раннера можно по аналогии с systemctl:

# статус сервисаsudo gitlab-runner status# запуск сервисаsudo gitlab-runner start# останов сервисаsudo gitlab-runner stop# получения списка зарегистрированных раннеровsudo gitlab-runner list

После завершения настройки сервиса GitLab Runner нужно создать экземпляр раннера для запуска Liquibase. Для этого воспользуемся командой register, но перед этим нам нужно получить токен для нашего проекта в GitLab.

Переходим в интерфейсе GitLab в раздел Settings CI/CD Runners. Здесь мы видим список доступных нам раннеров, которые либо привязаны к группе проектов, либо к конкретному проекту. У меня этот список выглядит примерно так (немного законспирировал имена):

Нас интересуют два пункта:

  1. Адрес вашего GitLab. Раннер будет обращаться к нему для получения исходников и команд на запуск джобов.

  2. Токен для регистрации раннера. По нему раннер будет связан с нашим проектом или группой, если происходит настройка раннера для группы в целом.

Также у каждого раннера вы можете видеть теги, выделенные синим цветом. Это своего рода метки, по которым определяется, будет ли использовать раннер для конкретного джоба, об этом подробнее будет рассказано ниже. Пока достаточно знать, что раннер будет запущен, если его теги содержат теги джоба.

Регистрация раннера

Для создания раннера нужно выполнить команду sudo gitlab-runner register

Вас попросят ввести следующие параметры:

  1. Enter the GitLab instance URL

    Вводим адрес вашего GitLab

  2. Enter the registration token

    Вводим токен

  3. Enter a description for the runner

    Вводим имя раннера, например, my-awesome-runner

  4. Enter tags for the runner

    Вводим теги раннера через запятую. Пример: liquibase,dev

    Выбор можно позже изменить через интерфейс GitLab CI/CD

  5. Enter an executor

    Выбираем механизм исполнения раннера. Подробнее по ссылке.

    Вводим shell

shell это простейший механизм исполнения команд оболочки целевой ОС. Мы будем использовать скрипты на bash.

После регистрации раннера можно проверить его наличие через команду sudo gitlab-runner list или через интерфейс GitLab CI/CD:

my-awesome-runnermy-awesome-runner

Настройка CI/CD

Информация о том, что делать в процессе CI/CD хранится в файлах проекта. Главным является файл .gitlab-ci.yml в корне. Остальные файлы, в нашем случае скрипты на bash, размещаются на усмотрение разработчика, например, в папке /ci.

Все тонкости конфигурации тянут на отдельную статью, да и опыта в данной области у меня маловато, но то, что использовано в тестовом проекте, будет разложено по полочкам.

Для начала отмечу, что есть встроенный линтер для файла .gitlab-ci.yml, доступный по относительному пути ci/lint в проекте, например: https://gitlab.example.com/gitlab-org/my-project/-/ci/lint. Рекомендую воспользоваться им перед пушем конфига. Также предполагается, что вы знакомы с форматом YAML.

Полный листинг конфига в тестовом проекте:

variables:    LIQUIBASE_VERSION: "4.3.4"stages:    - deploydeploy-dev:    stage: deploy    tags:        - liquibase        - dev    script:        - 'bash ./ci/deploy-db.sh $DEV_DB $DEV_DB_USER $DEV_DB_PASS'    environment:        name: dev    only:        - devdeploy-prod:    stage: deploy    tags:        - liquibase        - prod    script:        - 'bash ./ci/deploy-db.sh $DEV_DB $DEV_DB_USER $DEV_DB_PASS'    environment:        name: prod    when: manual    only:        - prod

Переменные

Документация: https://docs.gitlab.com/ee/ci/variables/README.html

variables:    LIQUIBASE_VERSION: "4.3.4"

В этом блоке описаны переменные окружения, которые в дальнейшем можно использовать в скриптах. Переменная LIQUIBASE_VERSION указывает на версию Liquibase, которая будет применяться для наката скриптов миграции. Если мы захотим сменить версию, просто установим новую версию Liquibase и поменяем значение этой переменной.

На самом деле, лучше описать эту переменную в настройках проекта, о чем мы поговорим далее, но это просто пример того, как можно использовать переменные в конфиге.

Переменные проекта можно настроить в разделе Settings CI/CD Variables.

Пример того, как выглядят переменные в интерфейсе:

CI/CD VariablesCI/CD Variables

Помимо переменных, описанных в непосредственно и конфиге и в настройках проекта, существует целый ряд предопределенных переменных, относящихся к процессу CI/CD, таких как имя коммита, ветки или имя пользователя, совершившего коммит. Они могут быть полезны для настройки обратной связи, например, для автоматических уведомлений по результатам деплоя.

Этапы (stages)

stages:    - deploy

В этом блоке перечисляются этапы деплоя, о которых рассказано в разделе описания схемы работы.

Джобы (jobs)

Рассмотрим на примере джоба деплоя на дев:

deploy-dev:    stage: deploy    tags:        - liquibase        - dev    script:        - 'bash ./ci/deploy-db.sh $DEV_DB $DEV_DB_USER $DEV_DB_PASS'    environment:        name: dev    only:        - dev

Строка stage: deploy указывает на этап, к которому относится данный джоб.

Теги перечислены массивом, т.е. это liquibase и dev. Наш ранее созданный раннер отреагирует на эти теги и запустит скрипты в разделе script. Важно отметить, что в джобе прода указан тег prod, поэтому раннер для него должен быть отдельный, исходя из соображений, что он, вероятно, находится в другой сети. А вообще, один и тот же раннер может обслуживать несколько проектов, если это требуется.

Блок environment указывает на окружение, которое можно настроить в отдельном разделе по пути Operations Environments. Это своего рода дашборд ваших стендов (дев, предпрод, прод и т.п.), где можно увидеть их статус и выполнить, например, ручной деплой. Также можно настроить переменные, привязанные к окружению, но это премиум-фича, которую мне попробовать не удалось.

Пример страницы окружений:

EnvironmentsEnvironments

Блок only указывает, для каких веток нужно применять данный джоб. Его братом является блок except, который указывает для каких веток джоб применять не нужно. Помимо веток можно настроить более сложные условия: https://docs.gitlab.com/ee/ci/jobs/job_control.html.

Для прода мы также указали when: manual. Это означает, что запуск деплоя для прода будет в ручном режиме при нажатии на кнопку в пайплайне, а не в момент коммита. Это позволит нам собрать чемодан до того, как что-то пойдет не так выполнить деплой в запланированное время.

Мерж в прод, ручной запускМерж в прод, ручной запуск

Скрипт наката

В блоке script мы указываем список скриптов, которые будут выполнены раннером. Так как у нас shell-исполнитель на линуксе, будем использовать bash. Все переменные автоматически передаются в скрипт в виде переменных окружения, но т.к. реквизиты базы отличаются для разных стендов, передаем их непосредственно при вызове скрипта.

Разберем непосредственно скрипт вызова Liquibase:

#!/bin/bashecho "Environment: $CI_ENVIRONMENT_NAME"cd db/changelog/usr/share/liquibase/$LIQUIBASE_VERSION/liquibase \    --classpath=/usr/share/liquibase/$LIQUIBASE_VERSION/drivers/ojdbc10.jar \    --driver=oracle.jdbc.OracleDriver \    --changeLogFile=master.xml \    --contexts="$CI_ENVIRONMENT_NAME" \    --defaultSchemaName=STROY \    --url=jdbc:oracle:thin:@$1 \    --username=$2 \    --password=$3 \    --logLevel=info \    update

Подробно параметры вызова Liquibase описаны в соответствующем разделе.

Переменные DEV_DB, DEV_DB_USER, DEV_DB_PASS приходят в скрипт в виде $1, $2 и $3 соответственно. Помимо них мы используем указанное в джобе имя окружения, которое приходит в предопределенной переменной $CI_ENVIRONMENT_NAME, что можно использовать, чтобы какие-то скрипты накатывались только на определенном стенде, а не на всех.

Если все настроено правильно, то после коммита конфига и скриптов в гит, заработает деплой.

Успешный лог пайплайна для Liquibase выглядит примерно так:

Отклонение мержей с ошибками

Если процесс деплоя пойдет с ошибками, можно не допустить соответствующий мерж. Особенно это полезно, если в CI/CD встроены тесты как отдельный этап. В нашем примере тестов нет, но Liquibase тоже может сломаться, если, например, указаны неверные пути до файлов.

Для запрета ошибочных мержей нужно установить галочку в разделе General Merge requests.

Важно! Галочку нужно устанавливать после настройки CI/CD, иначе перестанут проходить любые мержи.


Заключение

Статья оказалась большой, но это не должно вас пугать. На самом деле мне удалось с нуля и без каких-либо предварительных знаний разобраться и настроить проект с деплоем примерно за 5 часов времени в пятницу вечером. Очень надеюсь, что данная статья поможет вам освоить деплой быстрее, а кого-то направит на путь CI/CD.

Если какие-то моменты остались за кадром, и есть желание узнать о них подробнее, пишите в комментариях. Буду иметь в виду, но обещать ничего не стану, т.к. эта статья, например, отняла у меня более 20 часов времени в течение трех недель, что в два-три раза больше среднего времени на написание статьи.

Как обычно, если понравилась статья, посмотрите другие:

Подробнее..

Актуальность инициативы BAAG BattleAgainstAnyGuess

31.05.2021 06:09:55 | Автор: admin

14 лет назад, в июне 2007го, Алекс Горбачев, в то время еще CTO Pythian, основал BAAG Party - Battle Against Any Guess - инициативу против любых гаданий при решении технических проблем. Уже тогда это становилось большой проблемой: все чаще на форумах и публичных мейл-листах на вопросы о специфических проблемах, вместо запроса необходимых технических деталей, приходили ответы в духе "а попробуйте то, если не поможет - попробуйте это", "я когда-то видел похожее, мне помогло XXX", "а мне ХХХ не помогло, зато помогло YYY". Рождались различные мифы и порождали еще большее новых, оттуда и всякое "шаманство" и "танцы с бубном"(частично и "работает - не трожь"). Все это вполне объяснимо: сложность ПО и железа экспоненциально увеличивается; количество недостоверной информации а-ля "for dummies" в сети растет как снежный ком; IT отрасли нужно все больше и больше работников на "конвейеры" - "бери больше, кидай дальше". Появление #BAAG тогда было абсолютно закономерным и неотвратимым, но насколько она актуальна сейчас? Почему после ее расцвета и популярности в течение нескольких лет, она в забвении? Что и когда должно появиться ей на замену на данный период развития IT?

Для начала я хотел бы процитировать отрывок из интервью Алекса:

Whats wrong with making an educated guess? We have limited data, limited knowledge, limited experience, limited tools, and limited time. Can we ever really know?

Yes we can! At least, we should strive to know....
Most real life problems can be solved with the knowledge that is available in the public domain, using data that is possible to extract by applying the right experience and tools and taking enough time to do the job properly.
It is the purpose of the Battle to promote the importance of knowledge fighting ignorance, selecting the right tools for the job, popularizing the appropriate troubleshooting techniques, gaining experience, and learning to take time to diagnose the issue before applying the solution. One might think that the BAAG motto is a bit extreme but thats a political decision to emphasize the importance of the goal.
...
When I established the Battle Against Any Guess Party, a number of people argued that guesswork is the cruel reality with Oracle databases because sometimes we do hit the wall of the unknown. The argument is that at such point, there is nothing else left but to employ guesswork. Several times people have thrown out the refined term educated guess. However, I would argue that even in these cases, or especially in these cases, we should be applying scientific techniques. Two good techniques are deduction and induction.

Мой вольный перевод:

А что не так с обоснованными предположениями? Что если мы ограничены в данных, знаниях, опыте, средствах и времени? Можем ли мы действительно что-то точно узнать?

Да, мы можем! По крайней мере, мы должны пытаться. Большинство реальных проблем могут быть решены с помощью публично-доступных знаний и данных, которые можно получить, применяя правильные средства, опыт и достаточное время, чтобы сделать свою работу как следует. В этом и есть цель BAAG - продвижение важности знаний выбора правильных средств, популяризация соответствующих методов траблшутинга, получение опыта и обучение диагностике. Кто-то может сказать, что девиз BAAG чересчур категоричный, но это было сделаано нарочно, чтобы подчеркнуть важность цели. Когда я основал BAAG, множество людей утверждало, что гадания - это жестокая реальность при работе Oracle, т.к. иногда мы бьемся о стену неизвестности, т.е. в определенный момент не остается ничего, кроме как гадать. Несколько раз люди бросались термином "обоснованное предположение". Тем не менее, я считаю, что даже в таких случаях, или особенно в таких случаях, мы должны придерживаться научных подходов, например: дедукции и индукции.

Времена меняются: так же как и когда-то прошло время энциклопедистов, придет время и в IT, когда объем необходимых знаний даже для траблшутинга от верхнеуровневых процедур до сисколлов ядра превысит критическую точку. Все еще осложняется тем, что количество качественной достоверной информации относительно низкосортной писанины неуклонно уменьшается. Типичная ситуация сейчас: человека встречает проблему, гуглит ее, приходит на какой-нибудь стековерфлоу и берет решение из ответа, помеченного как правильный. Ладно еще, если это помогло, а если не помогло, то начинается перебор - вторая ссылка, третья ссылка, и тд, или создается новый вопрос и тогда перебор по ответам... Какова же вероятность выбора оптимального решения в таких случаях? Или даже проще: являются ли люди из топа по ответам экспертами в областях, в которых они отвечают? Не будет ли порожден очередной миф? Причем, я одобряю и полностью поддерживаю терпение, широту знаний и любознательность таких энтузиастов! IT уже давно не удел только энтузиастов, теперь полно людей, которые не любят свою работу, и их палкой не заставить что-то прочитать, или сотрудников загоняют настолько, что у них просто не остается ни времени, ни сил на самообразование.

В сложившейся ситуации, очевидно, что от гаданий и метода проб и ошибок уже никуда не деться. Так может уже уйти от категоричного Battle Against Any Guess, к чему-то более терпимому? Например, Battle Against Any Non-educated Guess или на худой конец Guess Carefully? Или уже смириться с этим и просто надеяться на светлое будущее? Ведь в целом, несмотря на всю печальность ситуации и страшные (но уже набившие оскомину) аналогии с врачами, все не так страшно: проблемы так или иначе решаются, а в сложных критичных областях все намного серьезнее и уже так не гадают...

Подробнее..

Как селф-сервис BI убивает кровавый энтерпрайз

15.02.2021 10:17:19 | Автор: admin

Привет, меня зовут Владимир Шилов, я руководитель направления в департаменте анализа данных Ростелекома. В мае 2019 года я пришёл в команду Business Intelligence (BI) и одной из первых задач была реализация отчётности по анализу посещаемости отчетов во всех BI-инструментах, установленных в компании.

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

Какие BI системы наиболее востребованы в реалиях крупной компании;
Какие критерии влияют на внутреннюю популярность решения;
Какие современные тенденции пользовательского поведения можно наблюдать внутри компании и какие вопросы будут стоять перед ИТ-подразделениями в ближайшее время.

С чего всё началось: реализация решения по анализу используемости BI систем

Начну с общего описания ситуации и подходов к сбору информации. У нас в компании целевыми BI-системами являются:

1. Oracle BI
2. Microsoft analysis services
3. Microsoft Power BI
4. Qlik Sense
5. Форсайт

Кроме перечисленных инструментов, у нас на разных уровнях также используются более узкоспециализированные и экзотические решения. Но для целей нашей статьи мы опустим эти нюансы, и далее речь пойдет именно о целевых BI-системах (за исключением Форсайта), так как именно они используются в масштабах всей компании, и на наш взгляд их обзор будет более интересен читателям.

Для сбора информации об использовании инструментов было разработано специализированное решение, подход к реализации которого можно представить в виде последовательности шагов:

1. Провести анализ логов BI-систем по запуску отчётов;
2. Спроектировать модель витрины данных;
3. Разработать ETL;
4. Реализовать отчет в Power BI;

Решение получилось примерно следующим:

Числа в зелёных стикерах обозначают общее количество инсталляций, в синих количество self-service инсталляций.Числа в зелёных стикерах обозначают общее количество инсталляций, в синих количество self-service инсталляций.

Очевидно, что любая разработка в крупной компании с некоторой бюрократией превращается в нечто большее, чем просто Возьми и сделай! Ты же мужик! и выполнение простого алгоритма из четырёх шагов. Я довольно сильно погряз в разработку архитектурного решения и согласования его с архитекторами, а также предоставления доступов к логам и ETL. В этой статье описывать свои трудности я детально не буду и сконцентрируюсь на конечном результате.

Для начала предлагаю рассмотреть каждый BI-инструмент в отдельности.

Oracle BI

На Oracle BI реализовано подавляющее большинство отчётности в виду того, что Oracle BI является самым старым инструментом и у него почти не было альтернативы очень долгое время. Ниже представлены графики динамик по следующим показателям:
Количество используемых уникальных отчётов за период;
Количество уникальных пользователей.

На основе второго графика динамики уникальных пользователей можно сделать вывод, что аудитория BI-системы стабилизировалась и сильного роста в 2020 году не наблюдается. Этому есть ряд причин:
Доступ к отчётности требует согласования, а прозрачность процесса предоставления доступа очень низкая;
Новые предметные области появляются очень редко;
Нет возможности создавать дашборды с аналитикой.

Analysis services

Microsoft Analysis services в компании это тоже достаточно распространённый инструмент, что во многом обусловлено удобной для пользователей работой в Excel. Именно этот инструмент получил наибольшее распространение в компании: он даже более популярен в МРФ (макрорегиональных филиалах), чем в корпоративном центре. Это можно увидеть на следующей диаграмме по уникальным пользователям в разрезе территорий за последние 12 месяцев:

Ниже представлены графики динамик по следующим показателям:
Количество используемых уникальных OLAP-кубов за период;
Количество уникальных пользователей.

Рост количества используемых OLAP-кубов за последний год не наблюдается, а рост аудитории в BI-системе нестабильный со значительными всплесками. У такой статистики несколько причин:
OLAP-кубы в основном дорабатываются, а новые кубы появляются очень редко;
BI-система больше предназначена для аналитиков, умеющих работать с данными, и она сложно продается широкой аудитории;
Доступ к отчётности требует согласования с владельцем OLAP-куба.

Power BI

BI-система Power BI от Microsoft появилась самой последней в стеке инструментов компании, но именно к этой системе сейчас приковано самое большое внимание со стороны бизнеса по следующим причинам:
Базовый набор визуализаций имеет хороший дизайн;
Лицензирование осуществляется по ядрам на сервере, отсутствует лицензирование по пользователям;
Скорость разработки отчётов довольно высокая, но стоит отметить, что на полный цикл разработки это не сильно влияет.

Ниже представлены динамики показателей аудитории и количество отчётов, которые она использует:

Стоит отметить, что при относительно низком росте количества используемой отчётности аудитория продолжает расти. Это связанно в большей степени с тем, что доступ к отчётам предоставляется без выделения лицензий на каждого пользователя и изначально нет никаких ограничений по доступу, то есть оформлять заявку не нужно. Уже сейчас наблюдается тенденция перевода отчетов с Qlik sense на Power BI именно потому, что новые пользователи подключаются бесплатно.

Qlik sense

Qlik sense была первой корпоративной BI-системой с возможностью реализации полноценных дашбордов. Именно с Qlik sense связан переход от предоставления табличных данных к графическим визуализациям в компании.
Ниже представлены графики динамик по следующим показателям:
Количество используемых уникальных отчётов за период;
Количество уникальных пользователей.

Казалось бы, перед нами современный BI-инструмент с высоким спросом, в котором можно создавать красивые решения, но сильного роста отчётности по сравнению с Oracle BI и Analysis services мы не наблюдаем. Тут есть несколько причин, влияющие на аудиторию и количество новых отчётов:
Лицензия на одного пользователя стоит существенных денег, и поэтому бизнес отказывается заказывать отчетность в Qlik sense;
Длительный период реализации отчётов от подготовки данных до реализации не позволяет быстро перенести все бизнес-процессы на новый инструмент.

Теперь поговорим про инструменты Self-service.

Self-service инструменты

Qlik sense self-service

В ноябре 2019 для бизнеса мы развернули self-service и предложили бизнесу реализовывать свои отчеты на своих источниках самостоятельно. С точки зрения лицензирования было одно изменение разработчики лицензируются отдельно. С лицензиями пользователей изменений не было по причине того, что сервера были объединены в один кластер и лицензии, соответственно, тоже.
Графики динамик количества запускаемых отчётов и уникальных пользователей в недельной динамике представлены ниже:

По графикам можно сделать вывод, что первоначальный рост аудитории и количества отчётов остановился в первом квартале 2020 года, а дальше наблюдается стагнация числа уникальных пользователей. Но стоит отметить, что с появлением новых отчётов в сентябре используемость отчётности вернулась на свой максимум, хотя роста аудитории не наблюдается. Основной причиной является высокая стоимость лицензий пользователей системы, что не позволяет делать отчёты для большой аудитории.

Power BI self-service

Вот мы и дошли к самому интересному. Power BI self-service появился примерно в то же самое время, что и Qlik Sense self-service, но у данных систем есть одно существенное отличие в лицензировании. Для подключения команды разработчиков от бизнеса в Power BI self-service надо разово заплатить за лицензию на 2 ядра, что примерно равняется 35 лицензиям пользователей в Qlik sense, но лимита на пользователей в Power BI нет.

То есть бизнес-подразделение разово платит за одну лицензию и получает существенные возможности по реализации отчётности для большой аудитории. Разумеется это позитивно повляло на показатели используемости данной системы, стоит отметить, что цена вхождения BI-разработчика в разработку базовых отчетов очень низкая.
Ниже представлены динамики показателей аудитории и количество отчётов, которые она использует:

Ещё более наглядно всё выглядит если показать все рассматриваемые системы вместе:

Какие критерии влияют на развитие отчетности?

В части развития отчетности в BI-системах стоит выделить следующие особенности, которые описаны в таблице:

Свойство\BI-система

Power BI

Power BI self-service

Qlik sense

Qlik sense self-service

Analysis services

Oracle BI

Лицензирование

Бесплатно для бизнеса

Лицензия на 2 ядра на одну команду разработки. Для пользователей бесплатно.

Лицензия на каждого пользователя

Лицензия на каждого пользователя и разработчика

Бесплатно для бизнеса

Бесплатно для бизнеса

Вид визуализации

Дашборды

Дашборды

Дашборды

Дашборды

Excel таблицы

Табличные отчеты без аналитики

Требования к квалификации BI-разработчика

Низкие

Низкие

Средние

Средние

Средние

Выше среднего

Качество дизайна базовых визуализаций

Высокое

Высокое

Среднее

Среднее

Отсутствует

Низкое

Процесс подготовки данных

Централизованное хранилище

Собственные источники

Централизованное хранилище

Собственные источники

Централизованное хранилище

Централизованное хранилище

Предоставление доступа

Все отчеты публичные

Все отчеты публичные

По согласованию владельца лицензий

По согласованию владельца лицензий

По согласованию владельца куба

По согласованию владельца области предметной области

Исходя из результатов нашего анализа именно критерии, описанные в таблице, оказали самое большое влияние как на скорость создания новой отчетности, так и на востребованность отчетности пользователями компании. А ключевым фактором успеха Power BI self-service стала политика лицензирования и его условная бесплатность для разработчиков на стороне бизнеса.

Заключение

Из выше сказанного можно сделать вывод, что ключевыми факторами по использованию отчётности в различных BI-системах являются (расположены по мере уменьшения значимости):
Стоимость подключения новых пользователей, особенно на большую аудиторию;
Длительность полного цикла реализации отчёта от подготовки данных до публикации;
Простота реализации отчётов в BI-системе.

Если бизнесу предоставить возможность самостоятельно заниматься подготовкой данных или предоставить доступ к уже подготовленным данным и дать простой и дешевый инструмент для анализа, то бизнес очень быстро начнёт самостоятельно удовлетворять свои потребности в аналитике данных. При таком подходе остаётся много открытых вопросов: Кто будет сопровождать отчёты и данные в них?, Каким отчётам можно доверять?, Как сделать единую систему отчётности с общей навигацией в едином стиле?.

Несмотря на то, что у ИТ сейчас нет однозначных ответов на эти вопросы, очевидно, что бизнес уже сделал свой выбор в пользу Self-service инструментов, и на эти вопросы нам придется отвечать. Будем рады присоединиться к обсуждению в комментариях. О том, какие решения мы нашли для self-service контура Ростелекома мы расскажем вам в наших будущих статьях.

Статья подготовлена командой управления данными Ростелекома

Подробнее..

JPoint 2021 тенденции и тренды мира Java

19.04.2021 00:19:54 | Автор: admin
В третьем онлайн-сезоне конференций, проводимых JUG Ru Group, с 13 по 17 апреля 2021 года успешно прошла Java-конференция JPoint 2021.



Что было интересного на конференции? Какой тематики были доклады? Кто из спикеров и про что рассказывал? Что изменилось в организации конференции и долго ли ждать возвращение офлайн-формата? Можно ли что-то ещё придумать оригинальное при написании обзора о конференции?

Основным инструментом, который поможет делать рассказ о конференции и её докладах в этом обзоре, будет облако тегов (англ. tag cloud). Облако тегов визуальное представление текстовых данных, в котором слова, используемые с большей частотой, выделяются размером шрифта или цветом. Облака тегов помогут

  • показать общие тенденции, тренды, направленность прошедшей конференции;
  • проиллюстрировать каждый из представленных в обзоре докладов;
  • поиграть в игру, где будут и облака тегов, и доклады, и спикеры.

Картинка в начале статьи с облаком тегов в форме логотипа JPoint была сформирована с использованием названий и описаний абсолютно всех докладов конференции. Посмотреть файл в оригинальном размере можно по следующей ссылке. Из 1685 слов в топ-3 с заметным отрывом попали: Spring (50 повторений), Java (49 повторений) и data (21 повторение). Из прочих фаворитов, но с меньшей частотой использования, можно также отметить слова session, JDK, cloud, code, Kubernetes, GraphQL и threads. Данная информация помогает понять, куда движется Java-платформа и названия каких сущностей, технологий и продуктов являются самыми актуальными сегодня.

Открытие


Долгожданное открытие конференции выполнили Алексей Фёдоров, Глеб Смирнов, Андрей Когунь и Иван Углянский. Ими были представлены спикеры, эксперты и программный комитет все те, без которых проведение конференции было бы невозможным.



Редкий случай, когда можно было видеть одновременно трёх лидеров Java-сообществ: JUG.ru (Алексей Фёдоров), JUG.MSK (Андрей Когунь) и JUGNsk (Иван Углянский).



Основные события конференции были трёх типов:

  • доклады;
  • мини-доклады партнёров;
  • воркшопы.

Доклады


Приятной неожиданностью для русскоязычных участников конференции стало то, что Себастьян Дашнер свой доклад Качественный код в тестах не просто приятный бонус делал на русском языке. Себастьян принимает участие в качестве спикера в конференциях JUG Ru Group c 2017 года, причём, не только в Java-конференциях. Текущий доклад был посвящён интеграционному тестированию, поэтому в нём присутствовали и Java, и тесты на JUnit, и Docker. В качестве приглашённого эксперта рассказ успешно дополнил Андрей Солнцев. Отличное знание русского языка и неизменно интересный доклад от Себастьяна Дашнера.





В докладе Building scalable microservices for Java using Helidon and Coherence CE от Дмитрия Александрова и Aleksandar Seovic было продемонстрировано совместное использование двух продуктов компании Oracle Helidon (в его разработке участвует Дмитрий) и Oracle Coherence (Aleks является архитектором продукта). Митя ранее делал доклады про MicroProfile (первый доклад и второй) и написал хорошую статью на Хабре про Helidon, поэтому было любопытно посмотреть дальнейшее развитие темы. Повествование сопровождалось демонстрацией кода и запуском приложения, код которого доступен на GitHub. Докладчики, каждый из которых лучше знаком со своим продуктом, отлично дополняли друг друга. Посмотреть оказалось увлекательно и полезно.





Анна Козлова работает над созданием нашего любимого инструмента IntelliJ IDEA, внеся по количеству коммитов самый большой вклад среди всех конрибьютеров в репозиторий IntelliJ IDEA Community Edition, что вызывает огромное уважение.

В своём докладе Многоступенчатые рефакторинги в IntelliJ IDEA Анна очень доходчиво и убедительно показала, как сложные типы рефакторингов могут быть получены комбинацией более простых уже существующих рефакторингов. В препарировании рефакторингов ей ассистировал коллега по компании JetBrains Тагир Валеев. Исключительно полезен как сам доклад (определённо, стоит его пересмотреть), так и озвученная Анной и Тагиром статистика применения разного типа рефакторингов пользователями.





Type inference: Friend or foe? от Venkat Subramaniam. Венкат фантастически харизматичный спикер, которого каждый раз хочется смотреть при присутствии его докладов на конференции. Мне кажется, ценность его докладов в том числе в том, что он заставляет увидеть другую сторону каких-то вещей, ранее казавшимися простыми и очевидными. В этот раз подобной темой было выведение типов (type inference). Кроме интересной информации в очень экспрессивном исполнении наконец-то узнал, в чём Венкат показывает презентации и запускает код (ломал голову над этим при просмотре его предыдущих докладов) это редактор vi.





Доклад Антона Кекса про то, Что такое Работающий Продукт и как его делать своеобразное продолжение его выступления The world needs full-stack craftsmen двухлетней давности. Если в прошлом докладе Антон говорил о недопустимости узкой специализации разработчика, то в этот раз сфокусировал своё внимание и внимание слушателей на том, почему важно и как можно сделать качественный работающий программный продукт. Докладчик подкреплял приведённые теоретические тезисы практическими примерами, поэтому просмотр стал весьма захватывающим зрелищем.





Под доклад Spring Data Рostроитель (Spark it!) в исполнении Евгения Борисова предусмотрительно был отведён отдельный пятый день конференции. Планировалось, что демонстрация написания поддержки Spark для Spring Data займёт 6 часов (в итоге вышло почти 7). Положительным моментом онлайн-конференции является то, что в случае длинных докладов можно комфортно прерывать и продолжать просмотр позднее. Много кода, новой информации и подробных пояснений. Традиционно получилось качественно, основательно и увлекательно.



Мини-доклады партнёров


+10 к безопасности кода на Java за 10 минут стал первым из 15-минутных докладов партнёров, увиденных на конференции. Алексей Бабенко сконцентрировал в небольшом времени, отведённом на доклад, внимание на вопросах безопасности при написании кода на языке Java. Формат мини-докладов, которые показываются в перерывах между большими докладами, оказался достаточно удачным и востребованным.





Ещё один мини-доклад, 1000 и 1 способ сесть на мель в Spring WebFlux при написании высоконагруженного сервиса от Анатолия Тараканова, может пригодиться в том случае, если используете Spring WebFlux и возникли какие-либо проблемы в разработке и эксплуатации приложения. Краткое перечисление проблем и способов их решений может чем-то помочь.





В кратком докладе R2DBC. Стоит ли игра свеч? от Антона Котова даётся оценка практической применимости спецификации R2DBC в текущий момент. После ранее прослушанного вот этого доклада Олега Докуки было интересно узнать сегодняшнее положение вещей. Антон в конце доклада даёт однозначный ответ на вопрос Стоит ли игра свеч?. Через некоторое время ответ должен, вероятно, измениться.





Доклад Секретный ингредиент: Как увеличить базу пользователей в 3 раза за год в исполнении Александра Белокрылова и Алисы Дрожжиновой представил следующие новости от компании BellSoft, наиболее известной своим продуктом Liberica JDK:

  • клиентская база компании увеличилась в 3 раза за последний год;
  • появился новый инструмент Liberica Administration Center (LAC) для централизованного обновления Java на компьютерах пользователей;
  • стала доступна утилита Liberica Native Image Kit на базе GraalVM CE;
  • компания ведёт работы в области серверов приложений (на сайте доступен продукт LiberCat на основе Apache Tomcat).





Кирилл Скрыган докладом Code With Me новая платформа для удаленной коллаборативной разработки представил новую возможность продуктов компании JetBrains для парного программирования и коллективной разработки в среде разработки. Была показана базовая функциональность сервиса и перечислены получаемые преимущества.



Воркшопы


На конференции было два воркшопа: Парное программирование вместе с Андреем Солнцевым и Антоном Кексом и Строим Бомбермена с RSocket вместе с Сергеем Целовальниковым и Олегом Докукой. Для просмотра во время конференции выбор пал на воркшоп Строим Бомбермена с RSocket. Олег и Сергей убедительно продемонстрировали на примере игры взаимодействие составных частей приложения по протоколу RSocket. Код приложения доступен на GitHub для изучения и повторения действий, выполненных во время воркшопа.



Конференции, Java-митапы и игра


На сайте jugspeakers.info по-прежнему доступно приложение, состоящее из двух частей:

  • поиск и просмотр информации о конференциях и Java-митапах, организуемых JUG Ru Group, JUG.MSK и JUGNsk (спикеры, доклады, презентации, видео, статистика);
  • игра Угадай спикера.

К новому сезону конференций в приложение были сделаны ряд доработок и новшеств, первое из которых позволит более эффективно использовать программу во время конференций:

  1. Начальная страница отображает теперь ближайшую или идущую в данный момент конференцию (картинка слева ниже сделана во время работы JPoint 2021). Установка значений всех фильтров поиска по умолчанию на текущую конференцию также должна помочь сделать программу максимально полезной во время идущей сейчас конференции.
  2. Приложение дополнено фильтрами по организатору конференций и митапов (средняя картинка).
  3. Добавлена информация о видео всех докладов, сделанных публично доступными (в том числе видео докладов с Joker 2020).
  4. Появились данные о конференции SnowOne, второй год проводящейся новосибирским Java-сообществом JUGNsk (см. картинку внизу справа).
  5. Стало возможным видеть учётные записи Хабра у спикеров.



Во второй части приложения (в игре Угадай спикера) появилось 2 новых режима: угадывание облака тегов по спикеру и спикера по облаку тегов. Облака тегов формируются на лету, при выборе пользователем конференций или митапов. Источником для создания облаков тегов по спикерам являются наименования и описания их докладов. Для каждого спикера создаётся одно (по тексту на английском языке) или два облака тегов (второе облако возможно, если у докладов есть описание и на русском языке). Переключением языка интерфейса можно посмотреть оба облака тегов.

Хорошее знание тематики, на которую спикеры предпочитают делать свои доклады, поможет Вам правильно выбрать из нескольких вариантов либо облако тегов, либо спикера.



Чем больше конференций выбрано в игре для данных режимов (угадывание облака тегов по спикеру и спикера по облаку тегов), тем больше информации для формирования облака тегов и результат будет более точный. Java-разработчикам для игры можно порекомендовать следующие варианты в порядке усложнения:

  1. Выбрать только одну конференцию JPoint 2021 (Тип события JPoint, Событие JPoint 2021)
  2. Выбрать все конференции JPoint (Тип события JPoint, Событие конференции за все годы)
  3. Выбрать все Java-события (Тип события Joker, JPoint, SnowOne, JBreak, JUG.MSK, JUG.ru и JUGNsk)

Код приложения находится на GitHub, репозиторию можно ставить звёздочки.

Закрытие


Алексей Фёдоров, Глеб Смирнов и Андрей Когунь закрыли конференцию, подведя итоги и поделившись каждый своими впечатлениями от пятидневного конференционного марафона.



Несмотря на вынужденное ограничение онлайн-форматом, конференция продолжает держать высокую планку: удобная платформа для просмотра докладов и взаимодействия с другими участниками, множество докладов по Java-технологиям, горячая информация о новых продуктах (Space и Code With Me), любимые спикеры с отлично дополняющими их приглашёнными экспертами.

В весенне-летнем сезоне онлайн-конференций JUG Ru Group ещё будут конференции HolyJS, DotNext (20-23 апреля 2021 года) и Hydra (15-18 июня 2021 года). Можно посетить любую из конференций отдельно или купить единый билет на все шесть конференций сезона (три уже прошедших и три оставшихся), видео докладов становятся доступными сразу же после завершения конференций.
Подробнее..

Получаем бесплатные сервера в Oracle Cloud Free Tier

09.02.2021 02:22:17 | Автор: admin

Сразу предупреждаю, что бесплатно выдаются машинки достаточно слабенькие (одноядерные, на каждой RAM 1Gb, суммарное дисковое пространство обоих машин до 100Gb, подключение к сети 480Mbit), но для экспериментов этого более чем достаточно. Впрочем на них вполне можно развернуть почтовый сервер для небольшой организации, собственную систему управления умным домом или какой-нибудь FreePBX.

Я не буду здесь полностью описывать процедуру регистрации в Oracle Cloud, она достаточно хорошо представлена на официальном сайте, ссылка есть в конце статьи. Просто скажу, что для этого вам понадобится действующий адрес электронной почты, действующий (российский) телефон с возможностью приема SMS и банковская карта, на которой имеется хотя бы 1EUR или соответствующий рублевой эквивалент. Электронная почта и телефон используются в процессе регистрации, на них отправляются коды, которые необходимо будет затем подтвердить. На последнем шаге привязывается банковская карта (я использовал цифровую дебетовую от банка ВТБ), на ней в процессе регистрации блокируется сумма порядка 1EUR для проверки валидности карты. В дальнейшем она возвращается и больше карта никак не используется, если только вы не захотите сделать апгрейд с Free Tier на какой-либо платный тариф. Замечу, что сразу после завершения регистрации вам предоставляется бонус в размере 250EUR на 30 дней. Т.е. в течении месяца вы можете абсолютно бесплатно попробовать и другие сервисы, которые не входят в программу Free Tier.

В процессе регистрации вас попросят выбрать домашний регион. По умолчанию все ресурсы будут создаваться именно в нем, для создания ресурсов в других регионах надо будет сделать на них подписку. Однако в лимитах после создания учетной записи (той, что нам требуется для Free Tier) разрешена подписка только на один (домашний) регион. Возможно при обращении в техническую поддержку это ограничение и снимается, я не проверял. Но лучше сразу выбирайте в качестве домашнего регион, с которым у вас наилучшая пропускная способность каналов связи или минимальная задержка сигнала. Ссылка на сервис, который поможет вам определить параметры доступа до всех регионов, есть в конце статьи.

Описанную ниже последовательность действий можно сильно упростить, если впоследствии вы не планируете подключать облачную инфраструктуру к своей локальной или офисной сети штатными средствами. В этом случае можно не создавать виртуальную сеть вручную, а сразу перейти к созданию виртуальных машин. Однако если хотите разобраться во взаимосвязи всех облачных элементов, лучше делайте все пошагово, не используя возможностей wizard.

В Oracle Cloud облачная приватная сеть (VCN), имеющая подключение к Интернет, в общем случае выглядит следующим образом:

Service Gateway, так же как и NAT Gateway, нам пока не нужны. Мы хотим получить виртуальную машину, полностью доступную из внешнего мира. Правда (и, видимо, это особенность большинства сервис-провайдеров) внешний адрес IP будет назначен не непосредственно виртуальной машине, а посредством технологии NAT 1:1 (на рисунке выше она фактически реализуется в объекте Internet Gateway).

Итак начнем с создания собственной сети (VCN) в датацентре домашнего региона. Для этого в меню (левый верхний угол страницы) выбираем пункт Networking.

Выбираем в меню "Networking"=>"Virtual Cloud Networks" и нажимаем на кнопку "Create VCN". Придумываем и вводим в поле "Name" идентификатор нашей VCN, а в поле "CIDR Blocks" добавляем минимум одну сеть. Пусть это будет сеть 172.31.254.0/26, в адресном пространстве которой будут адреса создаваемых нами виртуальных машин и всякие служебные туннели для связи виртуальной сети с нашей локальной или офисной сетью. Галочку в пункте "USE DNS HOSTNAMES IN THIS VCN" оставляем отмеченной, чтобы впоследствии можно было бы привязать внутренний DNS к этой VCN.

После создания VCN система также создаст нам следующие объекты по умолчанию: CIDR Blocks (1 шт), Route Tables (1 шт), Security Lists (1 шт) и DHCP Options (1 шт).

Теперь мы должны будем создать внутри VCN подсеть IP-адресов. Для этого нажимаем кнопку "Create Subnet". В поле "Name" вводим имя подсети (сейчас создаем подсеть, в которой будут располагаться виртуальные машины, поэтому назовем ее "Virtual Machines"). Subnet type выбираем "Regional", в поле "CIDR Block" запишем значение 172.31.254.0/28 (хватит нам для начала 13 адресов на 2 бесплатные виртуальные машины?). В "SUBNET ACCESS" выбираем "PUBLIC SUBNET" (чтобы на виртуальные машины нам потом выделили внешние IP-адреса), остальные поля заполняем единственно доступными для выбора на данном этапе значениями.

После создания VCN мы можем создать в ней Internet Gateways. Здесь вообще все просто: в поле "Name" вводим имя создаваемого Internet Gateway и нажимаем кнопку "Create Internet Gateway"

Остался предпоследний шаг, который обеспечит нам возможность выходить из нашей VCN в сеть Интернет (а также входить из Интернета в нашу VCN, используя NAT 1:1). Сначала в меню идем по пунктам "Networking"=>"Virtual Cloud Networks", затем в списке выбираем созданную ранее VCN Zurich, внутри нее в блоке "Resources" выбираем "Route Tables", в появившемся списке выбираем таблицу "Default Route Table for VCN Zurich" (она была создана ранее автоматически), и нажимаем кнопку "Add Route Rule". В поле "Target type" выбираем "Internet Gateway", в поле "DESTINATION CIDR BLOCK" пишем маршрут по умолчанию 0.0.0.0/0, в поле "Target Internet Gateway" выбираем элемент, созданный нами на предыдущем шаге (впрочем он пока вообще будет единственным в списке выбора).

А теперь стоит разрешить ICMP Echo запросы из внешнего мира к нашей внутренней инфраструктуре (по умолчанию они запрещены). Для этого снова выбираем наш VCN Zurich, в его ресурсах выбираем Security Lists. Там будет единственный элемент, созданный автоматически при создании VCN.

Выбираем его в списке, нажимаем кнопку "Add Ingress Rules" и добавляем правило, разрешающее ICMP Echo Requests с любых адресов.

Отлично, мы создали себе сетевую инфраструктуру с требуемым диапазоном внутренних адресов и с подключением к сети Интернет. Теперь можно перейти непосредственно к созданию виртуальных машин.

В меню выбираем пункты "Compute"=>"Instances" и нажимаем кнопку "Create Instance". В поле "Name" указываем имя создаваемой машины, выбираем требуемую нам ОС, в Shape указываем тип VM.Standard.E2.1.Micro (это бесплатная виртуальная машина), в блоке "Configure networking " устанавливаем значение "Assign a public IPv4 address: Yes" (чтобы нашей виртуальной машине выделили внешний адрес в сети Интернет). Ну и убеждаемся, что сеть VCN и подсеть внутри нее выбраны правильно (т.е. те, которые мы создавали на предыдущих шагах). При необходимости можно загрузить уже существующий открытый ключ SSH или создать новый.

Возвращаемся в пункт "Instances" чтобы узнать внешний IP-адрес вновь созданной виртуальной машины.

Примечание: на картинке выше в списке отображаются две виртуальные машины: одна только что созданная и одна с именем "eu-zurich-1-ad-1.vedga.com". Эту машину я создавал ранее, а потом удалил. Но она все равно еще сутки будет отображаться в этом списке в состоянии "Terminated". Беспокоиться нечего: удаленные машины ресурсы не потребляют и не помешают вам создавать новые виртуальные машины (в пределах бесплатного лимита).

Для проверки делаем ping на внешний адрес, и если сеть на предыдущих шагах была настроена правильно, то мы получим ответ от нашей виртуальной машины. Теперь на нее можно зайти по SSH. Замечу, что при создании виртуальной машины из образа Ubuntu, первый вход надо делать не с именем root, а с именем ubuntu и заданным при создании машины SSH-ключем. Впрочем если попробуете зайти под root сразу он вас хотя и не пустит, но укажет, что надо сделать. Для перехода в режим root введите команду sudo /bin/bash, скопируйте содержимое /home/ubuntu/.ssh/* в /root/.ssh и поменяйте владельца файла /root/.ssh/authorized_keys на root:root. Теперь можно будет зайти на машину сразу под root-пользователем, используя ключ SSH.

Теперь у вас есть одна (или две) виртуальных машины, защищенных облачным firewall, и доступ них из внешнего мира. Кому-то этого будет достаточно, кто-то быстро поставить на них OpenVPN и свяжет их со своей сетью. А мы будем строить VPN штатными средствами Oracle Cloud (IPSec со статической или динамической BGP маршрутизацией и Mikrotik или Linux на другом конце туннеля), но это уже тема отдельной статьи. Итак, продолжение следует...

Полезные ресурсы

Подробнее..

Cli-IDE для Oracle СУБД. Ну. Почти IDE

25.01.2021 18:10:11 | Автор: admin

Добрый день.

Первый вопрос: зачем, есть же Toad/SQL-developer/PLSQL-developer и т.п. графические ide-среды.

Ну. Да. Есть. Однако не всем именно они нужны, как средство работы с объектами oracle-субд.

Т.е. я тут, в этой статье - не именно для oracle-разработчиков буду рассказывать что то. Скорее для dba, т.е. людей у которых работа с объектами субд - значительно более специфичная, им не нужен такой ide-комбайн как Toad/SQL-developer/PLSQL-developer;

Второй момент: сейчас: удалёнка, везде и всюду. В этой связи доступ на работу - организовывается удалённый.

Либо: через что то типа VDI/RDP. Либо: выдаётся рабочий ноутбук и от на нём, с него - работай.

В первом случае - ну, часто подразумевается графический интерфейс удалённого рабочего стола и: виндовый и с ограничением по ресурсам.

Во втором случае: ну, организации часто пытаются и тут сэкономить - выдадут что нибудь с 8Гб оперативы и - как хочешь, так на этом и работай. Т.е.: файрфокс/хром, с N>>10 кол-вом вкладок, какой нибудь Toad/SQL-developer/PLSQL-developer, скайп/зум, ещё что то.

В обоих случаях: возникает вопрос - а как то бы тут сэкономить, на ресурсах, например - на IDE для oracle-субд.

Ну и, как мне кажется, находится, под этот запрос, интересный проект: VoraX

Проект, на настоящее время, абандонед, увы.

Вот хочу, по ряду причин, обратить внимание сообщества на этот проект. С одной стороны - чтобы больше народу посмотрело, с разных сторон и что то, какие то за/против увидели/оценили.

С другой стороны - уже появились, у меня, к этому проекту хотелки, но, не понятно как к ним подступится - нет ни времени, ни ресурса этим заниматься. Может быть тоже - кто то подскажет. А то и: свой форк запилит: штука то - весьма интересная.

В русскояз-м сегменте интернета практически нет упоминаний об этом проекте, есть упоминание воракса, в хабр-комменте, одного из контрбьютеров воракс-проекта.

В функционально-пользовательском смысле про возможности/свойства воракс-а отлично рассказывает автор проекта, здесь.

В инженерно-техническом смысле это - vim-плагин. Часть кода плагина: собственно дополнительные vim-функции, обеспечивающие работу в пользовательском инт-се. Часть - это руби-скрипты, которым выполняется, например, запуск-взаимодействие с sqlplus, работа с репозиторем подключений.

Т.е. воракс - это честная скл-сессия в субд, со всеми отсюда вытекающими последствиями: возможность выполнять транзакции из нескольких команд, например. Во всяких dbext, vim-dadbod, Emacs в скл-моде: такого не получится - они, при выполнении каждой конкретной скл-команды: запускают скл-плюс, подключаются в бд, выполняют команду, получают результат, закрывают соединение в бд.

Ещё часть, релевантного к воракс-у, руби-кода распространяется в виде gem-пакета с именем "vorax", который надо доставлять в руби отдельно. В этом гем-е проверяются и, если надо, предварительно ставятся зависимости, в частности racc gem. Ему, этому gem-пакету, нужен ruby-dev ОС-пакет, его надо ставить в систему.

Соответственно: требуется, установленными на машине: ruby, vim с поддержкой ruby, oracle-клиент (можно инстант-клиент).

На LinuxMint - всё это ставится без проблем, я делал так:

apt install gawk bison libffi-dev libgdbm-dev libncurses-dev libsqlite3-dev libyaml-dev zlib1g-dev -y apt install sqlite3 libgmp-dev libreadline-dev checkinstall libxml2-dev libxslt-dev -y apt install build-essential ruby-dev pkg-config -yruby -vgem install voraxgem list | sort

Потом сборка vim-а, с поддрежкой ruby:

mkdir ~/Vim4VoraX; cd ~/Vim4VoraXgit clone https://github.com/vim/vim.gitcd ./vim/src/#make distclean./configure --enable-rubyinterp --with-features=hugemake./vim --version | grep ruby; pwdsudo apt remove vimsudo checkinstall --pkgname vim4vorax4 --pkgversion 8.2.0 --install#dpkg -r vim4vorax4#in vim:#:ruby puts RUBY_VERSION

Затем патоген-ом доставил собственно vorax-плагин в vim, использовал более современный форк, уважаемого kish4ever:

cd ~/.vim/bundle && git clone https://github.com/kakash1hatake/vorax4.git

При установке кода вим-плагина руками, так как это описывает автор, плагин полностью работоспособным не становился. Не знаю может тут что то с кривизной моих рук. Патоген-менеджер vim-плагинов - мне помог.

Ну. Пара-тройка скринов, мы все - любим скрины:

Дока есть вот тут и в файле /vorax4/doc/vorax.txt - здесь и далее: путь относительный, от директории куда ставился vim-плагин.

Из некоторых вкусностей, которые успел заметить за те два дня что разглядываю этот плагин:

  1. Профили подключения: шифруются, хранятся в виде xml-файла profiles.xml, в, по умолчанию, домашнем каталоге. Профиль-менеджер, технически, это скрипт: /vorax4/vorax/ruby/lib/vorax/profiles_manager.rb

  2. Есть некий функционал, задающий режим отображения выхлопа селект-команд, в окне (точнее: буфере, если в vim-терминах) вывода. Бегло: поддерживается аппенд-мода вывода, поддерживается лимитирование строк в выборке (дописывается WHERE ROWNUM <= :limit), подерживается задание режима в котором не усекаются имена полей, если они длинее ширины столбца, есть Топ-режим отображения. Есть ещё несколько функций. Конечно можно выполнять set-команды и прочие команды склплюс-а и задавая какое то своё форматирование. Однако, в остальном - это всё тот же склплюс, со своими плюсами и минусами, касательно вывода. Об этом - несколько ещё поговорю, ниже. В правом нижнем углу окна вывода - подсказывается текущая мода отображения.

  3. Вот про выполнение команд и всякое форматирование: есть режим <Leader>E: т.н.: sanbdox-мода. В ней можно выполнить какой то скл-скрипт, который может выполнять свои склплюс-команды настройки скл-сессии. При этом, настройки скл-сессии самого воракс-а, из которого был, в такой моде выполнения, вызван некий скл-скрипт - будут запомнены, а после выполнения скрипта - восстановлены. Also: поддерживается обработка sigint сигналов 2,9 при выполнении команд - они посылаются склплюс-у. Also: поддерживается выполнение конкретной команды, на которой стоит курcор (или то что выделено, в visual-моде ), в верхнем vim-окне.

  4. plsql-подпрограммы, их определение, можно получить из объектного вьювера, в отдельный буфер (в терминах vim-а), просто встав на элемент в тривью и жмакнув "Enter". Что тут интересно - конкретно вот этот буфер, его содержимое, при попытке изменить-скомпилировать ддл-код процедурного объекта, воракс будет отправлять в субд as is, цитирую:

The default key mapping for compiling is c. "C" stands, obviously, for "C"ompile. For convenience, you may also use @. Two things happen when a PLSQL object is compiled:

* the buffer content is sent as it is to the server.

* as soon as the buffer content is executed, Vorax will check the ALL_ERRORS view to see if any relevant errors exist. If such errors are found, they are loaded into a Vim quickfix window, along with the error line, error column and the message itself.

Note: Pay attention that during the compilation of an PLSQL object, the substitution variables feature is disabled.

Проблемки (ну. с моей т.з.):

Спулинг выборок из воракс-а в файл. Формально - работает. Однако выясняется что воракс, обменивается с склплюс-ом (читает/пишет на/с стдоут/стдин) данными особенным образом - он обрамляет пользовательский текст в свои текстовые брекеты. Взаимодействие с склплюс - делается скриптом: /vorax4/vorax/ruby/lib/vorax/sqlplus.rb, там это выглядит, например, таким образом (пара скринов):

В итоге, в спул-файл, выписывается, кроме самой выборки - ещё куча служебных строк, от обмена данными между воракс-ом и склплюс-ом. Всё это - обходится конечно, но надо сделать дополнительные усилия, для обхода.

Второй момент.

Разглядывая склплюсовое форматирование выборок, в окне вывода, в воракс-е, вспомнил про SQLcl: какой он весь из себя модный-молодёжный, как там всё здорово с форматированием выборок. Ну и: тут же пришла в голову мысль о костыле рационализаторско-конструкторском усовершенствовании - а пуркуа бы и не па вписать в /vorax4/vorax/ruby/lib/vorax/sqlplus.rb вместо вызова бинаря sqlplus, вызов sql;

Да, виновен/мне стыдно: на тот момент ещё не знал что SQLcl - вызывается шельником <SQLcl-хоум>/sqlcl/bin/sql, который запускает ява-процесс, к которым и взаимодействует пользователь.

Поэтому, конечно, тут ничего не получилось: воракс - честно запускал шельник /sqlcl/bin/sql и потом выдавал ошибку - ой что то оно не отвечает.

Плюс, не известно - как бы ещё SQLcl реагировал, на эти текстовые брекеты воракс-а, типа #set blockterm, которыми он окружает текст пользовательских команд, получаемых от пользователя.

Пробовалось вписать, в вызов явы, в функции run в шелнике <SQLcl-хоум>/sqlcl/bin/sql ехес-команду баш-а, т.е., вот так:

function run { if  [  "m$SQLCL_DEBUG" != "m" ]; then   echo "JAVA=$JAVA"   echo "JAVA_OPTS=${APP_VM_OPTS[@]}"   echo "DEBUG=$DEBUG"   echo "CPLIST=$CPLIST"   echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"   echo "exec $JAVA  $CUSTOM_JDBC $CYGWIN "${APP_VM_OPTS[@]}" -client $SQLCL_DEBUG -cp "$CPLIST" oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli " fiexec $JAVA  $CUSTOM_JDBC $CYGWIN "${APP_VM_OPTS[@]}" -client $SQLCL_DEBUG -cp "$CPLIST" oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli "$@"}

Не выгорело, так же - сбоит.

Отдельно оговорюсь: в руби/яве - не понимаю ничего.

Собственно, зачем обращаю внимание собщества на этот проектик.

Интересны отзывы о этой штуке, может быть кто пользовался/пользуется, может рассказать плюсы/минусы которые с опытом работы становятся видны.

Ещё любопытно, как бы скрестить воракс-а с SQLcl, может быть есть, какие то, у кого то идеи об этом?

Так же, вопрос, какие ещё есть/знаете варианты работы с oracle-субд через cli-приложения, сопоставимые, или более продвинутые чем воракс, т.е.: коннекшен-менеджмент, обжект-браузер, и вот это вот всё.

Спасибо за внимание, ваше время.

Подробнее..
Категории: Ruby , Oracle , Vorax , Sqlplus

Решение проблемы безопасности данных интегрированными средствами Oracle

14.05.2021 10:12:48 | Автор: admin

С началом работы программ лояльности, появилась возможность накапливать скидки, предоставляемых продавцами в виде бонусов. и оплачивать ими покупки. Сотрудники, обрабатывающие данные программ лояльности, оказываются перед соблазном использовать свои права доступа для неправомерных действий. Дмитрий Юдин, директор по развитию бизнеса Oracle СНГ, и Сергей Петраков, начальник службы информационной безопасности АО ТПК, специализированного оператора по процессингу пластиковых карт на корпоративном и розничном топливном рынке, рассказывают, почему тем, перед кем стоит задача защиты данных, стоит сосредоточиться не на поиске мошенников в своей команде и устранении последствий мошенничества, а на превентивных мерах защиты данных в информационных системах. О том, как с помощью встроенных в базы данных инструментов, можно исключить возможность мошенничества до того, как оно произошло.

Почему данные программ лояльности стали объектом интереса мошенников

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

Цифровизация топливного ритейла охватывает, в числе прочего, программы лояльности для физических лиц - комментирует Сергей Петраков, - а также корпоративные топливные программы, участниками которых являются юридические лица, заключившие контракты на поставку, продажу нефтепродуктов. В обеих программах конечный пользователь проводит расчеты на АЗС, используя соответствующие пластиковые карты или иные, замещающие карты цифровые сущности (QR-код, штрих-код, токен и др.) Объем средств, проходящий через корпоративную топливную программу существенно больше по отдельной покупке, но число участников программ лояльности при этом значительно выше. Случаи мошенничества встречаются во всех программах, но программы лояльности становятся особенно привлекательными для злоумышленников за счет растущего объема передвигающихся средств, высоким уровнем использования современных цифровых технологий, возможностью применения, так называемых, технологий социальной инженерии на участниках программы. Для корпоративных программ возможности злоумышленника ограничены контрактной сущностью взаимодействия юридических лиц и реальной целью мошенника может стать задача по обналичиванию средств на АЗС или воздействие на данные в информационной системе, которое позволит, например, подставному юридическому лицу незаконно получить по картам топливо.

Борьбу с мошенничеством можно разделить на два больших направления борьба с мошенничеством на уровне конечного пользователя и противодействие мошенничеству на уровне информационных систем. Если первое направление это, как правило, совместная работа служб безопасности всех участников программ, включая и конечного пользователя, то второе направление это забота, в первую очередь, оператора, владельца информационной системы. Обеспечить безопасность данных в информационной системе - именно так представляют себе основную задачу безопасности в Топливной Процессинговой Компании, осуществляющей услуги процессинга по топливным программам и программам лояльности своих партнеров операторов сетей АЗС.

На каких этапах обработки данных по программам возможны неправомерные действия

Разрабатывая комплексную защиту данных программы лояльности, в ТПК проводят анализ и систематизацию потенциальных точек мошенничества в своих информационных системах. Неправомерные изменения могут происходить со стороны клиента, приложений, работающих с системой процессинга, а также может осуществляться непосредственное воздействие на базы данных, являющихся ядром работы процессинговых систем.

Новые технологии на стороне клиента появляются постоянно, - объясняет Сергей Петраков, - К примеру, это мобильные приложения, виртуальные карты и другие инструменты, которые используются при покупке в качестве инструментов программы лояльности. С интеграцией каждого нового инструмента появляются новые уязвимости. Мошенники стремятся их обнаружить и создать механизмы, с помощью которых можно эти уязвимости использовать. Однако все эти способы мошенничества находятся на стороне клиента, за границей периметра наших систем, в которых хранятся данные. Поэтому мы можем бороться с потенциальными злоупотреблениями на стороне клиента только в определенных пределах. Используются для этого системы антифрода, специальных ограничений в правилах программы, обеспечивающих безопасность со стороны клиента. Это важно, но это не поможет, если мошенником окажется инсайдер, имеющий доступ к данным в базах на нашей стороне.

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

Выработка принципиального решения

В ТПК пришли к выводу, что наиболее эффективным способом противостоять неправомерным действиям инсайдеров можно, ограничивая права привилегированных пользователей и лишая их возможности получить доступ к данным, в которые необходимо внести изменения, чтобы провести неправомерную операцию. Делать это удобнее всего непосредственно внутри баз данных, с помощью инструментов, контролирующих и ограничивающих действия привилегированных пользователей и делающих часть данных невидимыми.

Эти подходы позволяют решать проблемы безопасности данных наиболее кардинально. Не наделяя привилегированных пользователей достаточным объемом прав для внесения важных изменений и фиксируя каждое их действие для дальнейшего анализа, компания, осуществляющая процессинг карт, привязанных к какой-либо программе, создает сдерживающий фактор, препятствующий вмешательствам.

Выбор средств, ограничивающих действия инсайдеров

Выработав принципиальное решение, в ТПК приступили к формированию комплекса средств, необходимых для контроля доступа и действий администраторов.

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

Помимо ключевых составляющих в комплекс должны были войти и другие средства, например, для фиксирования всех операций. Такие средства расширяют функционал системы безопасности, не работая непосредственно с данными в базах.

Когда основной набор инструментов был определен, перед ТПК возникла необходимость выбора используемых средств. При этом использование преимущественно именно встроенных средств дает серьезные гарантии сохранения производительности и надежности работы самой базы данных в высоконагруженных процессинговых системах. Используя в качестве ядра процессинговой системы базу данных Oracle, в ТПК, в первую очередь, ориентировались на комплекс средств безопасности, имеющихся для данного продукта в виде встроенных опций, позволяющих ограничивать доступ к данным, разделять полномочия распределения доступов между администраторами и сотрудниками безопасности, решать задачи контроля действий привилегированных пользователей. Рассматривались также варианты средств сторонних вендоров, работающие с базами данных этого производителя и доступные на рынке.

Выбор между интегрированными средствами и внешними решениями

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

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

При небольшом объеме транзакций мы пользовались бы большей свободой действий и могли позволить себе тестировать различные решения, не особенно заботясь об отказоустойчивости и сохранении производительности, - комментирует Сергей Петраков, - Но поскольку для нас именно стабильность важнее всего, мы предпочли ориентироваться на те средства, которые максимально оптимизированы и сбалансированы для работы именно в той базе, которой мы пользуемся. Важнейшую роль в выборе сыграла возможность получить техническую поддержку, не останавливая работу.

Использование баз данных Oracle на практике уже само по себе представляет комплексную задачу. В решение входит программное обеспечение, созданное Oracle, и оборудование, предоставленное партнером. Добавлять к этому дополнительные решения от стороннего разработчика значит делать этот комплекс еще более сложным. Когда стоимость минуты простоя очень высока, служба поддержки должна быть не просто доступна. Она должна быть доступна через единую точку обращения в случае возникновения проблем с программной и аппаратной частью. Поддержка Oracle обеспечивает возможность единого доступа в случае возникновения проблем любого характера.

Еще один важный аспект возможность решить проблему, не останавливая обработку данных. Анализ причин сбоя требует моделирования ситуации, которая привела к возникновению ошибки. Сотрудник поддержки производителя может отследить или воссоздать ситуацию, не останавливая процессы. В случае возникновения проблемы по вине внешнего решения обработку данных придется останавливать, чтобы воссоздать условия, при которых возникла ошибка.

При необходимости обеспечить стопроцентную отказоустойчивость, угроза простоя оказывается более весомой для принятия решения, чем любые преимущества маркетингового характера, предложенные третьим производителем. С учетом этого в ТПК сделали выбор в пользу интегрированных решений Oracle.

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

Какие интегрированные решения Oracle используют в ТПК

В качестве средства для шифрования данных клиентов программ лояльности в ТПК используют Oracle Advanced Security Transparent Data Encryption (TDE). Это решение обеспечивает возможность управления ключами шифрования и прозрачность шифрования конфиденциальных данных. В TDE задействован механизм шифрования на основе команд DDL. Он полностью исключает необходимость в изменении приложений и создании дополнительных программных средств для управления ключами шифрования, триггеров и представлений в базах данных. Шифрование дает возможность реализовать многоуровневую глубокую защиту. Данные защищены как при передаче, так и при хранении.

Для контроля и анализа доступа привилегированных пользователей в ТПК выбрали решение Oracle Database Vault. Это решение повышает безопасность существующих приложений и обеспечивает соответствие нормативным политикам, предписывающим разделение обязанностей и минимальные привилегии для пользователей любого уровня. Оба эти решения используют превентивный подход и профилактическую защиту данных приложений от доступа привилегированных пользователей, вне зависимости от того, санкционированные эти действия или неправомерные.

Наибольшую опасность представляет персонал с высоким уровнем доступа, - комментирует Сергей Петраков, - Принимая на работу администраторов, мы проводим многоступенчатые проверки. Однако, даже в этом случае, сотрудник, пользующийся расширенным доступом к данным, продолжает быть слабым звеном. Средства шифрования и ограничения доступа позволяют технологически лишить его возможности вносить изменения вручную. К примеру, мы можем закрыть часть данных таким образом, что пользователю они будут не видны. При необходимости внести изменения в весь объем данных необходимо ставить в известность службу безопасности и проходить двухуровневую идентификацию с помощью доступа администратора и с помощью доступа сотрудника безопасности. Таким образом, для внесения изменений необходимы согласованные действия, и этот принцип сам по себе позволяет уменьшить количество слабых звеньев.

Результаты

Использование средств Oracle и распределение ролей между командами безопасности и администраторами предоставило возможность ТПК не заниматься расследованием случаев несанкционированных изменений в тот момент, когда предполагаемое мошенничество уже произошло, а предотвращать саму возможность таких случаев. При этом, средства безопасности не являются надстройкой над базами данных Oracle и представляют собой неотъемлемую часть программного комплекса. Эта особенность дает возможность сохранить максимальную отказоустойчивость и исключить простои при возникновении проблем.

Подробнее..

DataGrip 2021.1 Редактирование прав, контекстные шаблоны, предсказуемая навигация и не только

01.04.2021 20:04:02 | Автор: admin

Привет!

Сегодня мы выпустили DataGrip 2021.1: наш самый мощный релиз за последние годы. И это не шутка!

Самое важное:

  • Интерфейс для работы с правами доступа

  • Контекстные шаблоны Live Templates

  • Упрощенная навигация

  • Легкое копирование источников данных

  • Улучшенная сортировка

  • Редактирование данных в MongoDB

  • Поддержка Azure MFA

Редактирование прав

В окне редактирования объекта теперь можно изменять права на объект.

Также права можно добавлять и изменять в окне редактирования пользователя или роли. Напомним, что вызываются окна редактирования нажатием Cmd/Ctrl+F6.

Это работает в PostgreSQL, Redshift, Greenplum, MySQL, MariaDB, DB2, SQL Server и Sybase.

Контекстные шаблоны

Нас давно просили сделать как у других: чтобы для таблицы в проводнике можно было быстро сгенерировать простой запрос, например SELECT TOP 100 FROM %tableName%.

Мы всегда отвечали, что как только вы научитесь пользоваться шаблонами кода Live Templates, ваша жизнь изменится навсегда, и не надо будет тыкать мышкой во вложенные меню.

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

В итоге мы сделали новый вид шаблонов кода контекстные шаблоны. Работают они так:

Посмотрим шаблон Select first N rows from a table. Найдите его в настройках:

Он выглядит, как обычный шаблон, и его можно использовать в таком качестве. Но у переменной $table$ есть специальное выражение dbObjectName(). Вы увидите это, нажав на Edit Variables. Так вот, именно это выражение делает шаблон контекстным, то есть значение в эту переменную можно подставить автоматически кликнув на любой объект в проводнике базы данных.

Важно отметить, что синтаксис этого шаблона работает не во всех базах, в нижней части окна перечислены диалекты, для которых такой код можно сгенерировать.

В настройках можно выбрать, будет ли запрос генерироваться в новую консоль или в активную.

Редактор данных

Редактирование данных в MongoDB

Этого нам не хватало для полноценной поддержки Монги, но теперь все на месте: вы можете редактировать данные а апдейт-запрос просматривать до того, как данные отправятся в базу.

<img src="http://personeltest.ru/aways/habrastorage.org/webt/1t/ux/8y/1tux8yvfyrs2eiha3byoj0ss2tu.png" />

Еще можно менять тип ячейки: из контекстного меню или панели инструментов при просмотре больших значений.

Сортировка

Сортировка стала более удобной:

  • Мы добавили поле ORDER BY, а <Filter> переименовали в WHERE. Впишите в ORDER BY условия сортировки, чтобы получился работающий запрос.

  • По умолчанию сортировка не накапливается: каждый клик по новой колонке сбрасывает сортировку по другим колонкам. Если хочется сортировать по нескольким колонкам сразу, используйте клик с зажатой клавишей Alt.

Если хотите отсортировать данные на стороне DataGrip, отключите Sort via ORDER BY. Конечно, в этом случае, сортируются данные только на текущей странице.

Теперь вы можете по умолчанию открывать таблицы отсортированными по числовому первичному ключу.

Панель инструментов

Мы немного обновили панель инструментов в редакторе данных: добавили кнопки Revert Changes и Find. Кнопки Rollback и Commit в режиме автоматического подтверждения транзакций скрываются.

Транспонирование однострочных результатов

Если в полученном результате одна строка, его удобно сразу смотреть в транспонированном виде. Мы сделали для этого настройку:

Навигация

Предсказуемые действия

Мы удалили эти настройки:

Если вы никогда не меняли их значения по умолчанию, то главное изменение в новой версии для вас такое: действие Go to declaration (Ctrl/Cmd+B) теперь открывает DDL этого объекта. Раньше оно подсвечивало объект в проводнике базы данных.

Для перемещения к объекту в проводнике мы представили новое сочетание клавиш: Alt+Shift+B для Windows/Linux и Opt+Shift+B для macOS.

Теперь нет сложной логики, и каждое нажатие горячих клавиш ведет в туда, куда вы ожидаете попасть:

  • Ctrl/Cmd+B открывает DDL.

  • F4 открывает данные.

  • Alt/Opt+Shift+B подсвечивает объект в проводнике.

Удаление настроек всегда ломает привычки некоторому количеству людей. Мы постарались учесть это. Вот наши советы таким пользователям:

  • Все сочетания клавиш можно менять. Если, например, вы не хотите отвыкать от того, что Ctrl/Cmd+B подсвечивает объект в проводнике, назначьте это сочетание клавиш действию Select in database tree.

  • В то же время, если вам нравится, что внутри скрипта Ctrl/Cmd+B и Ctrl/Cmd+Click открывает определение CREATE, не убирайте эти сочетания с действия Go to declaration, если вы последовали предыдущему совету.

  • Если вам нравилось, что при отключенной настройке Preview data editor over DDL editor двойной клик по таблице открывал DDL, это можно вернуть через ключ в реестре. Он называется database.legacy.navigate.to.code.from.tree. Но мы не советуем менять значения в реестре и надеемся, что те полпроцента людей, у которых эта галочка была снята, быстро привыкнут к новому поведению :)

Если мы про что-то забыли, пишите, пожалуйста, в комментах.

Вкладка Database

Тут мы ничего особо не сделали просто переименовали вкладку Tables в Database. Этим мы напоминаем, что по сочетанию клавиш Cmd+O/Ctrl+N можно искать не только таблицы, но и процедуры, функции, схемы.

Соединение

Поддержка Azure MFA

Мы поддержали интерактивную аутентификацию через Azure Active Directory. Если она включена, при соединении у вас автоматически откроется браузер, где вы сможете завершить аутентификацию.

Версия 2.x драйвера для Redshift

Этот драйвер можно скачать в DataGrip, начиная с версии 2021.1. Главное изменение состоит в том, что теперь запросы можно останавливать.

Полная поддержка Google Big Query

Подсветку языка мы поддержали в предыдущей версии, а в этой добавили интроспекцию. То есть, информацию об объектах IDE берет не из драйвера, а выкачивает ее сама при помощи специальных запросов.

Поддержка диалекта CockroachDB

Теперь DataGrip правильно подсвечивает запросы и показывает ошибки в скриптах для CockroachDB. Соответствующую интроспекцию мы сделаем в одном из следующих релизов.

Улучшения в окне соединения

Сделали это окно чуть более дружелюбным:

  • Источники данных и драйверы разделены на две вкладки.

  • На странице каждого драйвера появилась кнопка Create data source.

  • Кнопка Test Connection переехала вниз теперь ее видно из всех вкладок, а не только из General и SSH/SSL.

  • Для источников данных на основе файлов (так называемых DDL Data Sources) теперь можно явно задать диалект.

  • Поле JDBC URL расширяется, потому что адреса для подключения бывают очень длинными.

Проводник базы данных

Легкое копирование источников данных

Возможность копировать и вставлять источники данных мы сделали давно. Но с этого релиза вы можете использовать самые знаменитые сочетания клавиш в мире Ctrl/Cmd+C/V/X.

  • Напоминаем, что когда вы копируете источник данных, в буфер обмена сохраняется XML. Его можно послать коллеге в мессенджере, а он вставит его в свою IDE все сработает.

  • Если копирование и вставка происходит в одном проекте, вам не понадобится заново вводить пароль.

  • Источник данных можно не только копировать, но и вырезать. Вырезание отменяется при помощи Ctrl/Cmd+Z.

Новый интерфейс

Объекты второстепенной важности (роли, пространства имен, внешние источники и др.) мы поместили в папки Server Objects и Database Objects.

Если хотите чтобы было, как раньше, включите настройку Group Database and Schemas.

[Oracle] Скрытие сгенерированных объектов

Если отключить Show generated objects, то из проводника пропадут:

  • Таблицы материализованных представлений

  • Логи материализованных представлений

  • Вторичные таблицы

[SQLite] Новые типы объектов

В SQLite теперь отображаются функции, модули и виртуальные столбцы.

Улучшения для неподдерживаемых баз

Шаблоны для источников данных

Начиная с этой версии стало легче создавать источники данных для баз, которые мы не поддерживаем. Вам не придется самим качать драйвер мы предложим сделать это за вас. Драйверы мы кладем к себе на сервер и обновляем, когда нужно. При создании источников данных ищите шаблоны в секции Other.

Еще раз напомним, что поддержка для таких источников данных базовая. Скрипты подсвечиваются на основе стандарта SQL:2016, а информация об объектах берется из драйвера.

Написание запросов

Инспекция про избыточные имена в CTE

Если запрос не запустится из-за избыточных имен в общем табличном выражении, DataGrip сообщит об этом.

[SQL Server] Системные функции можно использовать без имени схемы

Использовать системные функции без имени схемы можно было и раньше, но DataGrip считал это ошибкой :) Теперь они и подсвечиваются правильно, и для них работает навигация с автодополнение.

Поддержка JSON Lines

Формат JSON Lines используется для хранения данных и логов. И новая версия правильно подсвечивает файлы этого формата.

Толщина шрифта

Теперь вы можете настраивать толщину шрифта.

Импорт / Экспорт

Незагруженные данные

Если бинарные данные не были загружены полностью, вы увидите такое сообщение:

Настройка, которая определяет, какое количество данных DataGrip загружает по умолчанию, находится здесь: Settings/Preferences | Database | Data Views | Maximum number of bytes loaded per value.

Запрос в файле Excel

Когда вы экспортируете данные в Excel, на отдельном листе сохраняется изначальный запрос.

First row is header в контекстном меню импорта

Раньше было неудобно находить эту настройку, поэтому мы добавили ее в контекстное меню заголовков.

Интерфейс

Прикрепление папки при помощи drag-n-drop

Прикрепить папку, то есть открыть ее в панели Files, теперь можно, перетащив её.

Открытие вкладок в режиме разделенного редактора

Если редактор разделен вертикально на несколько вкладок, вы можете расширить окно редактора для любой из вкладок, кликнув по ней дважды. Чтобы вернуться в прежнее состояние, снова кликните дважды по окну.

Длинные названия вкладок

В одной из предыдущих версий мы укоротили названия вкладок. Это не всем понравилось, поэтому мы сделали настройку:

На этом все!

Скачать триал на месяц

Фидбек принимаем в комментариях к посту и здесь:

Трекер (это если точно нашли проблему)

Телеграм-канал

Твиттер

Почта

Команда DataGrip

Подробнее..

Мониторинг популярных баз данных из единого интерфейса Quest Foglight анонс вебинара

05.04.2021 10:08:01 | Автор: admin
Foglight for Databases удобный инструмент для DBA, который поддерживает мониторинг SQL Server, Oracle, MySQL, PostgreSQL, DB2, SAP ASE, MongoDB и Cassandra. И всё это в одном интерфейсе.

Кроме этого, инструмент позволяет сравнивать производительности БД в разные периоды времени (например, до релиза и после него), а также выполнять сравнение производительности различных экземпляров.

image

Приглашаем вас зарегистрироваться на вебинар, который состоится 7 апреля в 11 часов по московскому времени. Вы узнаете о возможностях решения, кейсах использования, лицензировании и сможете задать интересующие вопросы. Если вы не сможете присутствовать на вебинаре, в любом случае оставьте ваши контактные данные, мы вышлем вам запись после мероприятия. Под катом описание функционала решения и несколько скриншотов.

Ключевая особенность мониторинга SQL Server в Foglight for Databases наличие инструмента Performance Investigator, который выполняет многомерный анализ производительности БД в разрезах по базам данных, долгим запросам, сессиям, пользователям, исполнимым скриптам, рабочим станциям и приложениям. На скриншоте ниже ниже в древовидном меню можно рассматривать производительность БД в нескольких разрезах. Кроме этого, Foglight фиксирует изменения к конфигурации БД, Execution Plan и других компонентах.

image

В одной из предыдущих статей мы рассказывали о примере выполнения диагностики в Foglight следующих проблем:

  • Поиск источника блокировки;
  • Сравнение настроек БД было-стало с привязкой к метрикам производительности;
  • Поиск изменений в структуре БД, из-за которых снизилась производительность.

Аналогичных кейсов с диагностикой в решении есть с избытком.

Чтобы узнать больше о Foglight for Databases вы также можете прочитать другие наши статьи:

Как не превратиться в стрекозу, если у вас много разных баз данных

Интерфейсы для мониторинга производительности популярных БД в Foglight for Databases

Подписывайтесь на нашу группу в Facebook и канал в Youtube.
Подробнее..

Эволюция моих SQL запросов

26.01.2021 00:16:12 | Автор: admin

Всем привет! Я тимлид и Senior Oracle Developer, 12 лет работаю с OeBS и в основном пишу SQL запросы. Хотел бы рассказать, как за это время менялся мой подход в написании SQL запросов.

Вначале было слово, а точнее запрос. Скажем

select name from user where id = 1

Написать такой запрос как-то не так практически невозможно. Он одинаково хорошо работает во всех известных мне базах данных. А знаю я только oracle :З Но подозреваю что и в других реляционных тоже всё будет ок.

Так что же произошло? Проблемы начались, когда таблиц стало две:

select name from user u, rest r where u.id = 1 and u.id = r.user_id

Этот код вызывал у меня больше вопросов. Например, как должны быть соединены эти таблицы? Казалось бы что проще id = user_id, но мне что-то не нравилось. В блоке where мне не хватало четкого разделения между условиями фильтрации и соединениями таблицам. Когда запрос содержал 2 таблицы всё ещё было норм, но когда кол-во таблиц доходило до 5 - всё рассыпалось. Взглянув на запрос, я не мог сразу понять как соединены таблицы и не пропущена ли какая-то связка. И с этим все прекрасно жили, но я не мог. Однажды мне, молодому джуну, на глаза попался ANSI синтаксис.

select name from user inner join rest on u.id = r.user_id where u.id = 1

букв стало немного больше, но я намного лучше стал понимать, как связаны таблицы в моих SQL выражениях. Мир запросов расцвёл для меня новыми красками, и я больше не писал запросы как-то иначе. А ещё распространял эту весть среди других джунов. Это был мой первый шаг в эволюции SQL. Я вырвался от привычных шаблонов легаси кода и сделал что-то своё. Но была одна проблема. Когда используется скажем левостороннее соединение ANSI синтаксис заставляет переносить в связки, и все прочие ограничения для таблицы.

select u.name, r.resp_name from user u left join resp r on u.id = r.user_id  and r.end_date > sysdate where id = 1

Это меня жутко бесило, так как опять связи и параметры сливались в одну кучу. Помимо этого, наступал момент, когда запрос разрастался до гигантских размеров и становился практически не читаемым. К тому времени я уже дорос до мидла и хотел рассказывать истории своими селектами. И это подтолкнуло меня на второй шаг эволюции. И имя ему with.

select resp_q as (  select resp_name, userid   from resp where r.end_date > sysdate) ,main_q as (   select u.name, r.respname   from user u    left join resp_q r on u.id = r.userid   where id = 1) select * from main_q

Кода стало опять большое, но запросы в with позволили мне разбить монолитный запрос и группировать разные кусочки запроса по историям, а потом сплетать их вместе. Я мог рассказать про свой запрос так: Получаем список пользователей. Список ролей. Объединяем их в одну выборку и отсекаем тех кто нам не нравится. С оставшимися идём дальше, взявшись за руки. И за каждый шаг отвечала свой небольшой именованный запрос. Это также помогло мне бороться с моим злейшим врагом WET, т.к. одни и те же истории я мог использовать в разных частях своего запроса, не дублируя код. Ко всему прочему, упростилась отладка. Знай в блок from подставляй разные именованные запросы и отлаживай их по отдельности. А ещё, как выяснилось позже, с помощью with можно оптимизировать запросы, используя hint MATERIALIZE. Он материализует именованный подзапрос и данные при запросе из него берутся из темпового пространства. До этого я использовал обычные темповые таблицы. Это было более грубое решение, т.к. создавались лишние объекты БД + надо было помнить про очистку. Как итог, теперь, если запрос сложнее 10 строк, я почти всегда использую with.

Но чего-то не хватало. По своей природе я люблю кодить, но, когда приходит время тестировать, весь мой энтузиазм куда-то пропадает. Как итог, я часто отдавал не до конца протестированный код. Мне регулярно приходилось слышать про unit тесты, автотесты и прочее. Но сложно было это применить к БД. Сегодня сумма за период равна 100р, а завтра 120р. И как ты тут напишешь тест? Так и жил Но, уже став тимлидом, мне попалась задача, в которой надо было найти отмененные документы. Условие отмены было достаточно сложным и собиралось из множества нюансов (спрятал под функцию).

select * from document where xxstorno(id) = 'Y'

У меня было порядка 10 примеров документов. И завершая условие для одного документа, что-то ломалось в другом. А так как тестировал руками и глазами, времени уходило просто море. Я уже думал этому не будет конца. Пока не понял, что вокруг моего запроса можно написать обертку, которая будет за меня проверять все мои кейсы и говорить какие документы прошли проверку, а какие нет. Потратив на обертку несколько минут, я сократил время тестирования с 5-7 минут, до нескольких секунд.

with test_case as (  select 10 id, 'Y' storno from dual   union all   select 5 id, 'N' storno from dual)  , run_test as (    select tc.id, decode(xxstorno(d.id), tc.storno, 'OK', 'Error') result    from test_case tc    left join documentd on d.id = tc.id) select * from run_test

После правки функции, я просто запускал тест-запрос и смотрел сколько документов прошло тестирование, а сколько нет. В процессе тестирования я накидывал туда ещё кейсов, при том что про старые тесты тоже не забывались. И тогда я понял, как же это здорово! Как можно легко тестировать свой запрос, повышать надёжность и при этом не нужно ничего делать руками. Это может показаться элементарным, но до этого мне не встречались подобные конструкции. Обычно я видел конструкции типа and id = 5--6 7 10 135 1345 в которой просто перебором подставлялись разные значения и руками смотрелось что и как оно должно возвращать. С того дня я написал несколько разработок, и к каждой из них я уже готовил свой тестовый скрипт. Данный стиль мне очень понравился и теперь я пытаюсь привить его и своим разработчикам. Чтобы им не пришлось проделать путь в 12 лет, чтобы писать красивые SQL запросы.

По итогу в мире SQL не происходит почти ничего нового уже много лет, тем не менее всегда приятно найти возможность улучшить свои запросы.

Подробнее..
Категории: Sql , Oracle , Developer , Pl/sql

Oracle разница между deterministic и result_cache

06.02.2021 14:21:21 | Автор: admin

От переводчика: свой путь на Habr я решил начать не с попытки написать какой-то уникальный текст с нуля, а с перевода относительно свежей (от 17.08.2020) статьи классика PL/SQL-разработки Стивена Фойерштайна, в которой он достаточно подробно рассматривает разницу между двумя основными вариантами кэша результатов выполнения PL/SQL функций. Надеюсь, что этот перевод будет полезен для многих разработчиков, начинающих работу с технологиями Oracle.

Введение

Рано или поздно к любому опытному разработчику Oracle обращаются с вопросом наподобие:

Я не понимаю, в чем именно разница между deterministic и result_cache. Они имеют разные сценарии использования? Я использую deterministic во многих функциях, получающих данные из справочных таблиц. Необходимо ли мне использовать ключевое слово result_cache вместо deterministic?

Я подумал, что стоит написать про различия этих двух возможностей. Прежде всего, давайте убедимся, что мы все одинаково понимаем, в каких случаях функция является детерминированной (deterministic).

В Википедии дается следующее определение детерминированного алгоритма:

Детерминированный алгоритм - это алгоритм, который возвращает один и тот же набор выходных значений для одного и того же набора входных значений, при этом осуществляя одну и ту же последовательность действий.

Иначе говоря, детерминированная подпрограмма (процедура или функция) не имеет побочных эффектов. Передавая определенный набор значений в качестве входных параметров, на выходе вы всегда получите один и тот же результат, причем вне зависимости от того, когда, где или как часто вы будете вызывать эту подпрограмму.

Резонный вопрос - что же может считаться побочным эффектом для функции на PL/SQL? Как минимум (список не является исчерпывающим):

  • любой (то есть совсем любой) DML-оператор

  • Использование переменной, объявленной вне этой функции (то есть глобальной, out-of-scope aka "global")

  • вызов любой не-детерминированной подпрограммы

Далее мы кратко рассмотрим, как использовать deterministic и result_cache при разработке, после чего рассмотрим отличия этих двух возможностей и сценарии их использования. В данной статье мы будем рассматривать функции. Процедуры тоже могут быть детерминированными (но не result_cache), хотя такие процедуры, насколько мне известно, используются достаточно редко.

Создаем детерминированную функцию

FUNCTION betwnstr (   string_in   IN   VARCHAR2 , start_in    IN   INTEGER , end_in      IN   INTEGER)   RETURN VARCHAR2 DETERMINISTIC ISBEGIN   RETURN (SUBSTR (string_in, start_in, end_in - start_in + 1));END;

Эта функция - простейшая обертка над substr, позволяющая указывать начальную и конечную позицию возвращаемой подстроки, вместо начальной позиции и длины. Я думаю, что все согласны, что эта функция является детерминированной.

Для того, чтобы движок Oracle Database считал ее таковой, необходимо просто добавить ключевое слово DETERMINISTIC к объявлению этой функции (или процедуры).

Что это даст?

  • Это позволяет использовать эту функцию для создания индекса, основанного на функции

  • Это может (но не обязано) улучшить производительность за счет кэширования и переиспользования результата выполнения этой функции

Давайте посмотрим, как кэширование влияет на детерминированную функцию:

CREATE OR REPLACE FUNCTION pass_number (i NUMBER)   RETURN NUMBER   DETERMINISTICISBEGIN   DBMS_OUTPUT.put_line ('pass_number executed');   RETURN 0;END;/DECLARE   n   NUMBER := 0;BEGIN   FOR rec IN (SELECT pass_number (1)                 FROM all_objects                WHERE ROWNUM < 6)   LOOP      n := n + 1;   END LOOP;   DBMS_OUTPUT.put_line (n + 1);END;/pass_number executed6

Обратите внимание, что, хотя функция была вызвана 5 раз, она была исполнена только один раз. Oracle Database создала короткоживущий кэш, действительный только для этой функции и только в этом вызове (блоке PL/SQL или SQL-запросе, из которого мы обратились к функции).

Намного более детальный разбор поведения и производительности детерминированных функций можно найти у Роба ван Вейка.

Создаем функцию, использующую result_cache

Давайте изменим уже знакомую нам функцию betwnstr, чтобы она превратилась в использующую result_cache:

FUNCTION betwnstr (   string_in   IN   VARCHAR2 , start_in    IN   INTEGER , end_in      IN   INTEGER)   RETURN VARCHAR2    RESULT_CACHEISBEGIN   RETURN (SUBSTR (string_in, start_in, end_in - start_in + 1));END;

Все очень просто - я просто добавил ключевое слово RESULT_CACHE. Обратите внимание, что я убрал DETERMINISTIC, но это было сделано исключительно для читаемости. Функция может быть одновременно и детерминированной, и использующей result_cache.

Что же дает использование result_cache? Данное ключевое слово:

  • указывает Oracle Database, что необходимо использовать память в SGA (Shared Global Area) для кэширования входных и выходных результатов этой функции

  • таким образом, при вызове функции она будет исполнена лишь в том случае, если отсутствует кэшированный результат для данных входных параметров

  • иначе (при "попадании" в кэш этого набора входных значений) результат будет просто получен из кэша и возвращен в вызывающий контекст

  • если функция зависит от (в терминах Oracle - ссылается на, references) любых таблиц базы данных, то при любом commit в эти таблицы закэшированные значения функции будут автоматически удаляться

Необходимо отметить, что это лишь верхушка айсберга. RESULT_CACHE - это опция заметно "круче" DETERMINISTIC и может оказать заметно большее воздействие (как положительное, так и отрицательное) на производительность системы в целом. Если вы хотите использовать RESULT_CACHE , то начать следует с подробной официальной документации. Пару примеров использования RESULT_CACHE можно найти на Oracle Live SQL.

Давайте посмотрим, как выглядит кэширование для функций, использующих RESULT_CACHE:

CREATE OR REPLACE FUNCTION pass_number (i NUMBER)   RETURN NUMBER   RESULT_CACHEISBEGIN   DBMS_OUTPUT.put_line ('pass_number executed for ' || i);   RETURN 0;END;/DECLARE   n   NUMBER := 0;BEGIN   FOR rec IN (SELECT pass_number (100)                 FROM all_objects                WHERE ROWNUM &lt; 6)   LOOP      n := n + 1;   END LOOP;   DBMS_OUTPUT.put_line ('All done ' || TO_CHAR (n + 1));END;/pass_number executed for 100All done 6BEGIN   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (100));   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (200));   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (300));   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (100));   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (200));   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (300));END;/Returned 0pass_number executed for 200Returned 0pass_number executed for 300Returned 0Returned 0Returned 0Returned 0

Хотя я вызвал эту функцию трижды со входным значением 100 (один раз в первом блоке и дважды во втором), она исполнилась лишь однажды, при самом первом вызове, хотя сами вызовы относились к разным блокам исполняемого кода.

Аналогично и со входными значениями 200 и 300 - функция была выполнена лишь однажды для каждого из них, хотя я вызывал ее дважды.

Более того! Если я создам новую сессию (без перекомпиляции функции) и затем повторно вызову эти же два блока PL/SQL кода, в выводе я увижу только:

All done 6Returned 0Returned 0Returned 0Returned 0Returned 0Returned 0

Кэш для функций, объявленных с использованием ключевого слова RESULT_CACHE сохраняется для различных блоков, сессий, даже для различных пользователей. Как следствие, использование этой функции может повлечь за собой цепную реакцию - положительную или отрицательную - во всей вашей системе.

Нужно помнить: если неосторожно использовать функции, использующие result_cache, то можно получить ворох непредусмотренных проблем, некоторые из которых описаны в этой статье.

Что объединяет deterministic и result_cache?

Использование ключевых слов DETERMINISTIC и RESULT_CACHE может улучшить производительность за счет исключения исполнения функции.

Чем они отличаются?

Кэш, создаваемый при вызове функции, объявленной с использованием ключевого слова DETERMINISTIC, имеет узкую область видимости (только одна сессия) и небольшое время жизни (кэш существует только во время исполнения SQL-запроса, вызвавшего функцию). Общее влияние на производительность, вероятно, будет незначительным.

Наоборот, результаты исполнения, добавленные в кэш для функций, объявленных с использованием RESULT_CACHE, доступны для всех пользователей экземпляра (instance) и существуют до тех пор, пока не инвалидированы (изменением таблицы, от которой зависит функция) или не удалены вручную. Такой вариант кэширования может намного сильнее улучшить производительность в целом, но также вынуждает мириться с риском отрицательных последствий.

Когда использовать детерминированные функции?

Можно вывести простое правило: следует добавлять ключевое слово DETERMINISTIC в объявление любой функции, которая действительно является детерминированной.

Этим вы даете понять движкам PL/SQL и SQL, как они могут оптимизировать выполнение функции, а также делаете ее доступной для использования в некоторых специфических случаях (например, для построения основанного на функции индекса).

Даже если это не даст немедленного положительного эффекта, он может проявиться в будущем. Соответственно, было бы неплохо добавить это ключевое слово в объявление функции, если бы не одно НО.

Ни в коем случае нельзя использовать ключевое слово DETERMINISTIC в функциях, которые не являются детерминированными. Иногда Oracle поймет, что мы его обманываем, но зачастую это приведет к проблемам во всей вашей системе.

Когда использовать функции, объявленные с использованием result_cache?

Ответить на этот вопрос сложнее. Добавление ключевого слова RESULT_CACHE породит цепную реакцию в рамках всего экземпляра СУБД и повлияет на производительность в целом. Необходимо предметно проработать с DBA, что экземпляры разработки, тестирования и эксплуатации корректно настроены. Прежде всего, что объем SGA достаточен для всех кэшей и сделать все, чтобы избежать конфликта защелок (latch contention).

Необходимо крайне осмотрительно выбирать функции, которые будут использовать result_cache. Можно использовать следующие основные критерии для их определения:

  • эта функция часто вызывается с одними и теми же входными значениями?

  • если функция зависит от таблицы, неизменны ли данные в этой таблице? Если да, то это хороший кандидат

  • если функция зависит от таблицы, верно ли, что данные читаются заметно чаще, чем изменяются? Нужно помнить, что кэш будет очищен при изменении значений в таблице, от которой зависит функция

  • зависит ли функция от каких-либо специфических для сессии параметров, например NLS? Если да, то кэшированное значение может оказаться неверным, как, например, при использовании функции TO_CHARбез явно указанной маски формата. Решением в подобных случаях может стать вынос всех определяемых в сессии зависимостей в список входных параметров

Главное помнить: любая детерминированная функция является хорошим кандидатом для использования ключевого слова RESULT_CACHE, но не всякая функция, использующая это ключевое слово, является детерминированной.

Подробнее..
Категории: Sql , Oracle , Pl/sql , Deterministic , Result_cache

Oracle Deterministic functions, result_cache and operators

10.02.2021 18:20:17 | Автор: admin

После перевода статьи Oracle: разница между deterministic и result_cache от Steven Feuerstein, хотелось бы дополнить ее действительно важными деталями их устройства. У меня есть серия статей на эти темы, но тут я хотел бы просто все резюмировать и оставить самое важное.

1. Запросы в PL/SQL функциях не консистентны самому запросу, их вызывающему

Дело в том, что запросы внутри функции "видят" данные (согласованы/консистентны) на момент их запуска, а не запроса их вызывающего. И не важно, как определена сама функция, даже функция продекларированная в WITH clause запроса, точно так же будет получать несогласованные данные. То есть, если данные успели измениться за промежуток между стартом основного запроса и запроса внутри функции, то функция будет возвращать другие данные. Примеры тут и тут.

Из этого, очевидно, что либо функции не должны содержать запросов внутри, либо надо создать SQL оператор для нее, пример: оператор f1_op для функции f1:

CREATE OPERATOR f1_op   BINDING (INT)    RETURN INT   USING F1;

Кроме того, в Oracle 21 официально появляются SQL Macros: они пока весьма глючны, но в будущем они позволят во многих случаях отказаться от функций, что даст как прирост производительности за счет уменьшения переключений контекста, так и избавит от проблем с консистентностью данных.

2. Количество вызовов функций может быть больше из-за трансформации запроса

Рассмотрим такой простой запрос:

select *from (     select xf(t10.id) a     from t10      )where a*a >= 25;-- таблица t10:/*SQL> select id from t10;         ID----------         1         2         3         4         5         6         7         8         9        10 10 rows selected.*/

Как вы думаете сколько раз выполнится функция xf?

Ответ зависит от того, как отработает оптимизатор: будет ли выполнен merge подзапроса или нет и произойдет ли filter pushdown: примеры планов:

---------------------------------------------------- Plan 1:Plan hash value: 2919944937--------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes |--------------------------------------------------|   0 | SELECT STATEMENT  |      |     1 |     3 ||*  1 |  TABLE ACCESS FULL| T10  |     1 |     3 |--------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("XF"("T10"."ID")*"XF"("T10"."ID")>=25)---------------------------------------------------- Plan 2:Plan hash value: 2027387203---------------------------------------------------| Id  | Operation          | Name | Rows  | Bytes |---------------------------------------------------|   0 | SELECT STATEMENT   |      |     1 |    13 ||   1 |  VIEW              |      |     1 |    13 ||*  2 |   TABLE ACCESS FULL| T10  |     1 |     3 |---------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   2 - filter("XF"("T10"."ID")*"XF"("T10"."ID")>=25)----------------------------------------------------- Plan 3:---------------------------------------------------| Id  | Operation          | Name | Rows  | Bytes |---------------------------------------------------|   0 | SELECT STATEMENT   |      |     1 |    13 ||*  1 |  VIEW              |      |     1 |    13 ||   2 |   TABLE ACCESS FULL| T10  |     1 |     3 |---------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   3 - filter("A"*"A">=25)Column Projection Information ------------------------------    1 - "A"[NUMBER,22]   2 - "A"[NUMBER,22]

Подробнее: http://orasql.org/2013/06/10/too-many-function-executions/

3. Кэширование deterministic функций в SQL

3.1 Кэширование deterministic функций использует hash-таблицы и функции так же как и scalar subquery caching

И Scalar Subquery Caching(далее SSC) и Deterministic Functions Caching хэшируют входящие аргументы для хранения результатов, соответственно, возможны hash-коллизии.

3.2 Кэш результатов хранится только в течение одного fetch-call'a

Это значит, что эффективность кэширования зависит от fetch size (arraysize в sql*plus) и при каждом Fetch call кэш сбрасывается. Есть лишь одно исключение: когда аргумент функции это константы-литералы. У SSC такого ограничения нет. Кроме того, у SSC есть еще одна приятная особенность: он хранит кэш последнего результата даже в случае hash-коллизии.

3.3 Размер кэша и частота хэш-коллизий зависят от параметра "_query_execution_cache_max_size"

От этого же параметра зависит и SSC.

3.4 Кэширование отключается после определенного кол-ва неудачных попыток

Это зависит от параметра "_plsql_minimum_cache_hit_percent". У SSC есть и тут приятная особенность: даже в случае превышения кол-ва неудачных попыток, хотя кэширование новых значений отключается, уже сохраненные старые результаты он все равно будет возвращать.

Подробнее тут:
http://orasql.org/2013/02/10/deterministic-function-vs-scalar-subquery-caching-part-1/
http://orasql.org/2013/02/11/deterministic-function-vs-scalar-subquery-caching-part-2/
http://orasql.org/2013/02/11/deterministic-function-vs-scalar-subquery-caching-part-3/

Особенности совместного deterministic + result cache, operator + deterministic + result cache: http://orasql.org/2014/03/31/deterministic-functions-result_cache-and-operators/

4. Кэширование deterministic функций в PL/SQL

Вызов deterministic функций может быть вынесен из тела цикла при следующих условиях:

  1. PLSQL_OPTIMIZE_LEVEL >= 2

  2. Аргументы функции не должны меняться в теле цикла

  3. Не должно быть неявных конвертаций аргументов (implicit conversions)

  4. Не должно быть вызово не-"детерминированных" функций (кроме некоторых стандартных таких как to_date, to_char, nvl) и процедур

Пример: http://orasql.org/2013/03/13/optimization-of-loops-in-plsql-part-1/

5. Result cache

В отличие от SSC and Deterministic functions caching, которые хранят результаты в CGA, Result cache - это shared cache для всех сессий внутри инстанса (в shared pool), со всеми вытекающими отсюда плюсами и минусами. Отслеживание зависимостей происходит с помощью механизма Fine-grained dependency tracking c определенными нюансами (раз, два и три), защищено защелками (RC latches). Зависимости можно отследить с помощью v$result_cache_objects (type=dependency) и v$result_cache_dependency. Минимальной "гранулой" является сегмент (таблицы или секции), соответственно любое изменение или даже select for update c коммитом приведут к инвалидации результатов. Поэтому имеет смысл его использовать только на редко изменяемых таблицах. Использование же на часто изменяемых таблицах может поставить базу "колом".

Резюме резюме

Так как механизм Result Cache сам по себе достаточно тяжелый и гораздо медленнее, чем кэширование скалярных подзапросов или deterministic функций, желательно все такие функции объявлять и как deterministic, чтобы при многократном вызове с одинаковыми аргументами не было лишних достаточно тяжелых обращений к RC, а при потенциальной несогласованности данных лучше использовать собственные операторы. В целом же, надеемся на допиливание SQL Macro лет через 5-10 :)

Подробнее..
Категории: Sql , Oracle , Pl/sql , Result_cache , Deterministic functions

Troubleshooting в Oracle

08.05.2021 18:17:24 | Автор: admin

Этот пост навеян статьями Часть 1. Логирование событий в Oracle PL/SQL и Часть 2. Идентификация событий происходящих в Oracle PL/SQL. В первую очередь, как специалисту по performance tuning и troubleshooting, хотелось бы прокомментировать некоторые нюансы.

1. Уровни детализации логгирования

В показанной системе не хватает гибкости настройки логгирования: как уровня детализации, так и места, куда их выводить. Можно было позаимствовать функциональность из широко известных систем логгирования а-ля java.util.logging (SLF4j, log4j и его вариации для других языков/систем, и тд), гибкую настройку для какого кода с какого уровня сообщений и куда их сохранять. Например, в том же log4plsql можно настроить вывод и в alert.log, и в trace file (с помощью `dbms_system.ksdwrt()`)

2. Пользовательские ошибки и сообщения

Из самой внутренней системы ошибок Оракл можно было позаимствовать использование UTL_LMS.FORMAT_MESSAGE. Кстати, сами ошибки(и events) можно посмотреть с помощью sys.standard.sqlerrm(N):

SQL> select sys.standard.sqlerrm(-1476) errmsg from dual;ERRMSG-------------------------------------ORA-01476: divisor is equal to zero

Примеры: err_by_code.sql, trace_events.sql

Кроме того, я, конечно, понимаю, что не все ошибки можно предусмотреть, но все-таки считаю, что их надо добавлять в exception handler после того как они уже были отловлены. Это будет полезно как минимум при последующих изменениях логики и будет проще видеть нестандартные или непредусмотренные ранее ситуации.

3. Что же делать в случае незалоггированных ошибок

Естественно, может случиться так, что существующая система логгирования не регистрирует какие-то неординарные ошибки, или даже ее совсем нет в базе. Тут могут быть полезны триггеры `after servererror on database/schema`. Простой минимальный пример: https://github.com/xtender/xt_scripts/blob/master/error_logging/on_database.sql

К сожалению, для полноценного и срочного решения неординарных проблем, ни системы логгирования, ни таких триггеров, может быть недостаточно, и тут на помощь приходит вся мощь самой встроенной системы событий Oracle.

Например, недавно Nenad Noveljic расследовал проблему c "TNS-12599: TNS:cryptographic checksum mismatch" для чего ему нужно было получить callstack:

К счастью, помимо использованного у него в статье "ERRORSTACK", есть еще большой список "ACTIONS", включающий в себя и "CALLSTACK":

В этой команде 12599 - это номер события(event), callstack - инструктирует сделать дамп call стека, level 2 - указывает вывести еще и аргументы функций, lifetime 1 - только один раз.

Более подробно об этом у Tanel Poder с примерами:
- http://tech.e2sn.com/oracle/troubleshooting/oradebug-doc
- https://tanelpoder.com/2010/06/23/the-full-power-of-oracles-diagnostic-events-part-2-oradebug-doc-and-11g-improvements/

Мало того, как сам Танел и посоветовал, можно еще воспользоваться и "trace()" для форматированного вывода shortstack():

Так что этим же мы можем воспользоваться этим для вывода callstack:

alter system set events '12599 trace("stack is: %\n", shortstack())';

Или в более новом формате:

alter system set events 'kg_event[12599]{occurence: start_after 1, end_after 1} trace("stack is: %\n", shortstack())';

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

Покажу на примере "ORA-01476: divisor is equal to zero":

alter system set events 'kg_event[1476]{occurence: start_after 1, end_after 1} trace("stack is: %\n", shortstack())';

Здесь kg_event - это Kernel Generic event, 1476 - ORA-1476. После этого запускаем в своей сессии:

SQL> alter session set events 'kg_event[1476]{occurence: start_after 1, end_after 1} trace("stack is: %\n", shortstack())';Session altered.SQL> select 1/0 x from dual;select 1/0 x from dual        *ERROR at line 1:ORA-01476: divisor is equal to zeroSQL> select 1/0 x from dual;select 1/0 x from dual        *ERROR at line 1:ORA-01476: divisor is equal to zeroSQL> select 1/0 x from dual;select 1/0 x from dual        *ERROR at line 1:ORA-01476: divisor is equal to zero

И в трейсфайле получаем:

# cat ORA19_ora_12981.trcTrace file /opt/oracle/diag/rdbms/ora19/ORA19/trace/ORA19_ora_12981.trcOracle Database 19c Enterprise Edition Release 19.0.0.0.0 - ProductionVersion 19.9.0.0.0Build label:    RDBMS_19.9.0.0.0DBRU_LINUX.X64_200930ORACLE_HOME:    /opt/oracle/product/19c/dbhome_1System name:    LinuxNode name:      b7c493c7f9b0Release:        3.10.0-1062.12.1.el7.x86_64Version:        #1 SMP Tue Feb 4 23:02:59 UTC 2020Machine:        x86_64Instance name: ORA19Redo thread mounted by this instance: 1Oracle process number: 66Unix process pid: 12981, image: oracle@b7c493c7f9b0*** 2021-05-08T14:12:27.000816+00:00 (PDB1(3))*** SESSION ID:(251.9249) 2021-05-08T14:12:27.000846+00:00*** CLIENT ID:() 2021-05-08T14:12:27.000851+00:00*** SERVICE NAME:(pdb1) 2021-05-08T14:12:27.000855+00:00*** MODULE NAME:(sqlplus.exe) 2021-05-08T14:12:27.000859+00:00*** ACTION NAME:() 2021-05-08T14:12:27.000862+00:00*** CLIENT DRIVER:(SQL*PLUS) 2021-05-08T14:12:27.000865+00:00*** CONTAINER ID:(3) 2021-05-08T14:12:27.000868+00:00stack is: dbgePostErrorKGE<-dbkePostKGE_kgsf<-kgeade<-kgeselv<-kgesecl0<-evadiv<-kpofcr<-qerfiFetch<-opifch2<-kpoal8<-opiodr<-ttcpip<-opitsk<-opiino<-opiodr<-opidrv<-sou2o<-opimai_real<-ssthrdmain<-main<-__libc_start_main

Или, например, недавно я посоветовал использовать alter system set events 'trace[sql_mon.*] [SQL: ...] disk=high,memory=high,get_time=highres'; для выяснения причин, почему конкретный запрос не мониторится/сохраняется real-time SQL монитором (RTSM - Real Time SQL Monitor).

Получилось несколько сумбурно, в связи с недостатком времени, но на этом, пожалуй, закончу. Будут рад вопросам - задавайте, и я постараюсь их раскрыть отдельно.

Подробнее..
Категории: Sql , Oracle , Logging , Performance , Troubleshooting

Oracle diagnostic events Cheat sheet

20.05.2021 02:20:23 | Автор: admin

Oracle diagnostic events - это очень мощное средство, но, к сожалению, слабо документированное, поэтому я решил перечислить и свести воедино несколько неизвестных или малоизвестных способов его использования.

Единственная его документация - это очень краткая встроенная документация, доступная по команде oradebug doc в SQL*Plus, и она отсутствует в официальной документации. Вы можете встретить только отрывки из нее в разных блогах, что не очень удобно, поэтому я скомпилировал ее полностью: http://orasql.org/files/events/

Современный синтаксис и несколько простых примеров приведены в oradebug doc event. Я их здесь приводить не буду и начну сразу с примеров.

alter system set events    'kg_event[1476]        {occurence: start_after 1, end_after 3}            trace("stack is: %\n", shortstack())            errorstack(2)    ';
  1. kg_event[errno] - это Kernel Generic event из библиотеки Generic, инструктирующее сработать на ошибку с номером errno;

  2. {occurence: start_after X, end_after Y} - это один из фильтров , инструктирующий пропустить X срабатываний данного event и выполниться Y раз;

  3. trace(format, str1, str2, ..., str15) - это функция из ACTIONS для вывода в трейс-файл своих сообщений;

  4. shortstack() - это функция из ACTIONS , возвращающая call stack в кратком виде;

  5. errorstack(level) - это функция из ACTIONS, выводящая в трейс-файл расширенную информацию (level: 0 - только errorstack, 1 - errorstack + call stack, 2 - как level=1 + processtate, 3 - как level=2 + context area). Еще более расширенную информацию можно получить с помощью PROCESSSTATE или SYSTEMSTATE. Если нужен только call stack можно воспользоваться CALLSTACK(level) - при level>1 запишет и аргументы.

alter system set events     'trace[SQL_Compiler.* | SQL_Execution.*]        [SQL: ...]            {process: ospid = ...}            {occurence:end_after 3}                controlc_signal()';
  1. trace[component] - это основной диагностический event, позволяющий указать компоненты, внутри которых надо срабатывать. В данном случае, я указал срабатывать внутри всех дочерних функций в SQL_Compiler и SQL_Execution. Например, RDBMS.SQL_Compiler.SQL_Optimizer.SQL_Transform.* указало бы срабатывать только в функциях трансформации запросов.

  2. SQL[SQL: sqlid ] - это единственный SCOPE в библиотеке RDBMS, позволяющий отфильтровать все события, связанные с указанными запросами, включая события его рекурсивных запросов(например, если это sql_id PL/SQL вызова, то будут оттрассированы все запросы внутри него, или для запроса - все его внутренние запросы во время парсинга и оптимизации, внутренних запросов PL/SQL функций и тд.);

  3. {process: ...} - это фильтр, позволяющий указать процессы для которых данный event будет включен.

  4. controlc_signal - это ACTION, вызывающий ошибку "ORA-01013: user requested cancel of current operation", т.е. сессия запустившая этот запрос получит эту ошибку, как будто она сама прервала выполнение запроса.

    Конкретно, данным примером я воспользовался, когда в ходе нагрузочного тестирования большого веб-приложения на hibernate, были обнаружены очень плохие фактически ненужные запросы и нужно было помочь разработчикам быстро найти откуда в их коде они выполняются.

alter system set events     'sql_trace {process: ospid = ...}      trace("sqlid(%): %\n", sqlid(), evfunc())     ';

sql_trace - это старый добрый event 10046, а целиком команда предписывает при каждом событии инструментированным этим event 10046, вывести функцию, его вызвавшую(evfunc) и sqlid запроса (ACTION sqlid).

Пример:

включаем eventвключаем eventсначала выполняем запрос с настройками по умолчанию, а затем с _rowsource_statistics_sampfreq=1сначала выполняем запрос с настройками по умолчанию, а затем с _rowsource_statistics_sampfreq=1Разница в трейсе заметнаРазница в трейсе заметна

Как видите, при "_rowsource_statistics_sampfreq" =1 инструментировано намного больше событий: 26 против 12! Подробнее тут.

alter system set events     'wait_event["enq: TM - contention"]        {wait: minwait=1000}             errorstack(1)            trace("event=[%] sqlid=%, ela=% p1=% p2=% p3=%\n",                    evargs(5), sqlid(), evargn(1), evargn(2), evargn(3), evargn(4))    ';
  1. wait_event[name] - event, срабатывающий по имени событий ожидания (wait events), имена и их параметры вы можете посмотреть в v$event_name:
    select wait_class,name,parameter1,parameter2,parameter3 ,display_name from v$event_name

  2. {wait: ... } - фильтр позволяющий отфильтровать как по долготе ожидания(в мс), так и по параметрам P1, P2, P3. Например, для указанного ожидания "TM-contention", P2 - это object #, и можно указать {wait: minwait=1000; p2=12345}, т.е. только ожидания табличной блокировки на таблице с object_id=12345 и длившиеся дольше 1 сек.

  3. evargX() - это функции из ACTION, возвращающие аргументы event-check события, где 1-й аргумент это elapsed time(ms), 2-4 - p1-p3, 5-й - имя ожидания. Соответствующие функции имеет и kg_event: errargX.

Или еще пример, когда вам надо узнать какие сессионные переменные были изменены. Допустим, кто-то забыл указать nls-параметры в to_number, on conversion error не указан, и какие-то сессии периодически получают ORA-01722: invalid number:

-- допустим, изначально должны стоять следующие параметры:SQL> alter session set nls_numeric_characters='.,';Session altered.-- и все работает нормальноSQL> select to_number('1,200.3','999g999d999') + 10 from dual;TO_NUMBER('1,200.3','999G999D999')+10-------------------------------------                               1210.3-- до тех пор, пока в какой-то момент они не меняются:SQL> alter session set nls_numeric_characters=q'[.']';'Session altered.-- соответственно вылетает ошибка:SQL> select to_number('1,200.3','999g999d999') + 10 from dual;select to_number('1,200.3','999g999d999') + 10 from dual                 *ERROR at line 1:ORA-01722: invalid number

Хотя нет никакой вьюхи для получения параметров чужой сессии, не входящих в v$ses_optimizer_env, мы можем легко их получить с помощью MODIFIED_PARAMETERS():

alter system set events     'kg_event[1722]         {process: ospid=27556}        {occurence:end_after 1}            MODIFIED_PARAMETERS()';

И благодаря тому, что сейчас есть удобные v$diag_alert_ext - для доступа к alert.log, v$diag_trace_file_contents - для доступа к трейс-файлам, мы можем все получить простым запросом:

select c.payloadfrom v$diag_trace_file_contents cwhere 1=1  and c.session_id   = ... -- sid сессии  and c.serial#      = ... -- serial#  and c.section_name = 'Error Stack' -- параметры будут в секции Error Stack--  and c.payload like '%nls_numeric%' -- можно отфильтровать именно  and c.timestamp>systimestamp-interval'15'minute;-- результат:DYNAMICALLY MODIFIED PARAMETERS:  nls_language             = "AMERICAN"  nls_territory            = "AMERICA"  nls_sort                 = "BINARY"  nls_date_language        = "AMERICAN"  nls_date_format          = "yyyy-mm-dd hh24:mi:ss"  nls_currency             = "$"  nls_numeric_characters   = ".'"  nls_iso_currency         = "AMERICA"  nls_calendar             = "GREGORIAN"  nls_time_format          = "hh24:mi:ssxff"  nls_timestamp_format     = "yyyy-mm-dd hh24:mi:ssxff"  nls_time_tz_format       = "hh24:mi:ssxff TZR"  nls_timestamp_tz_format  = "yyyy-mm-dd hh24:mi:ssxff TZR"  nls_dual_currency        = "$"  nls_comp                 = "BINARY"  local_listener           = ""

PS. Дополнительные детали вы можете узнать в статьях Tanel Poder:
1. The full power of Oracles diagnostic events, part 1: Syntax for KSD debug event handling
2. The full power of Oracles diagnostic events, part 2: ORADEBUG DOC and 11g improvements
3. What Caused This Wait Event: Using Oracle's wait_event[] tracing
4. http://tech.e2sn.com/oracle/troubleshooting/oradebug-doc

О внутренних функциях у Frits Hoogland: http://orafun.info/

Полная внутренняя документация по oradebug/diagnostic events: http://orasql.org/files/events

Подробнее..

Войны лоббистов и развитие BIM.Часть 5 BlackRock хозяин всех технологий. Как корпорации контролируют Open source

11.04.2021 10:22:11 | Автор: admin

Технологические гиганты при помощи денег инвестиционных фондов контролируют всё большую часть новых разработчиков и продуктов, перекрывая тем самым путь для новых программ и новых технологий в строительной отрасли.

Сегодняшние лидеры САПР-индустрии: Autodesk, Hexagon, Nemetschek, Bentley, Trimble - хорошо готовятся к будущим угрозам: стандартной тактикой больших корпораций стал агрессивный захват новых рынков и поглощение возможных конкурентов на ранних стадиях развития.

В результате вся САПР-индустрия стала похожа на олигополию, в которой доминирует группа из нескольких компаний. И их положение на вершине становится всё более непоколебимым.

Содержание:

  1. BlackRock - хозяин всех технологий

  2. Олигополия на рынке САПР

  3. Autodesk идёт по стопам Oracle

  4. Почему программы не развиваются

  5. Борьба корпораций с open source

  6. Autodesk и формат данных IFC

  7. Проблема Autodesk - организация открытых стандартов - ODA

  8. В заключение

Олигополия в САПРОлигополия в САПР

В этой статье мы рассмотрим:

  • кто сегодня руководит развитием новых технологий в строительстве

  • как происходит синхронизация политики между САПР-вендорами

  • почему компании не развивают программы, написанные в 90-е

  • как большие корпорации контролируют open source разработчиков

  • почему IFC и Dynamo - это непрозрачный open source

  • как благодаря Autodesk появился альянс ODA

  • как велась борьба за формат DWG между ODA и Autodesk

  • как сегодня развивается борьба за открытость форматов RVT и RFA

  • как BlackRock и Vangaurd создали плановую экономику на мировом уровне

BlackRock - хозяин всех технологий

Основа олигополистической структуры в строительном проектировании - это большая пятёрка САПР-вендоров: Autodesk, Hexagon, Trimble, Bentley, Nemetschek.

Эти компании выходили с середины 90-х на IPO (initial public offering), распродав большую часть своих акций среди крупнейших инвестиционных фондов Соединённых Штатов и распределив тем самым ответственность за будущее компаний среди держателей акций.

Данные о держателях долей в уставном капитале (только материнские компании, за исключением владения фондами небольших дочерних компаний)Данные о держателях долей в уставном капитале (только материнские компании, за исключением владения фондами небольших дочерних компаний)

Главными бенефициарами (и держателями акций) от выхода САПР-компаний на биржу стали три американских инвестиционных фонда: The Capital Group, Vanguard и BlackRock, которые на протяжении последних 30 лет скупали акции технологических компаний напрямую или через свои банковские филиалы.

Акционеры крупнейших CAD-компанийАкционеры крупнейших CAD-компаний

Мало кто слышал о BlackRock, но эта фирма является крупнейшей инвестиционной компанией, под управлением которой находятся активы стоимостью в $8,7 трлн в 2021 году (в 2015 году - $4,6 трлн). На 2021 год BlackRock, штаб-квартира которой расположена на Манхэттене, имеет отделения в 100 странах, и она тесно связана с крупнейшими финансовыми регуляторами, такими как министерство финансов США, Федеральная резервная система (ФРС) США и Европейский центральный банк (ЕЦБ).

Как только какой-либо крупный экономический субъект попадает в поле зрения таких фондов, как Vanguard и BlackRock, они предлагают ему возможности выгодных инвестиций. Пользуясь своей надёжной репутацией, связями и огромными средствами, Vanguard и BlackRock скупают активы субъекта и начинают заниматься его управлением.

Например, только в Германии в 2014 году BlackRock принадлежало 4% акций BMW, 5,2% акций Adidas,7% акций Siemens, 6% акций Daimler. В целом BlackRock является акционером (почти всегда самым крупным) всех предприятий, входящих в индекс DAX (важнейший фондовый индекс Германии).Гигантская платформа Aladdin, созданная BlackRock для управления активами, ежесекундно отслеживает стоимость акций, облигаций и других активов, находящихся под управлением компании, а также рассчитывает, как влияют на их котировки различные события, такие как рост цен на нефть или алюминий.

BlackRock является мажоритарным акционером почти во всех технологических компаниях мира. Какое отношение к строительству и проектированию имеют инвестиционные корпорации BlackRock и Vanguard (Vanguard/Windsor)?

BlackRock и Vanguard принадлежат почти все САПР-компании и технологии в мире строительного проектирования и BIM решений.

Доля владения акциями BlackRock и Vanguard в компаниях САПРДоля владения акциями BlackRock и Vanguard в компаниях САПР

На графике владения акциями заметно, что особым смыслом здесь обладает цифры - 7-10%. До таких цифр инвестфонды доводят долю владения любой компанией, чего хватает, чтобы полностью контролировать целые корпорации.

На следующем графике видно похожее распределение владения акциями крупнейших компаний мира - Big 5.

Доля владения акциями BlackRock и Vanguard в компаниях Big 5Доля владения акциями BlackRock и Vanguard в компаниях Big 5

Из-за того, что 70% акций компании после выхода на биржу распределены между тысячами инвесторов, контрольный пакет составляет всего 720% акций, что даёт держателю небольшого пакета полномочия по принятию всех решений в компании.

Степень контроля (X - сила голоса) в компании в зависимости от вечеличины пакета акций (Y - процент капитала)Степень контроля (X - сила голоса) в компании в зависимости от вечеличины пакета акций (Y - процент капитала)

Таким образом, если у вас есть 7-20% акций нескольких основных компаний-монополистов, то вы почти полностью влияете на развитие всей отрасли.

При таком многократном перекрестном владении и при наличии долей практически во всех крупных корпорациях - как этим инвестиционным фондам удаётся следить за темой BIM или, например, развитием AR в строительстве, да и вообще за всеми технологиями мира одновременно?

Олигополия на рынке САПР

Олигополия в первую очередь означает скоординированность и взаимосвязь в действиях на рынке, что осуществляется Vanguard и BlackRock через глав компаний, утверждаемых на собрании акционеров.

Доля доли BlackRock в компаниях САПРДоля доли BlackRock в компаниях САПР

С выходом на биржу большие САПР-компании фактически убили конкуренцию на рынке САПР тем, что основные стратегические решения теперь принимаются не агрессивными руководителями компаний, которые борются за выживание и место на рынке, а пролоббированным советом директоров, который контролируется извне финансовыми специалистами, интересующимися отраслью строительства только как цифрой в годовом отчёте Annual Revenue.

Политолог Jan Fichtner из Амстердамского университета, исследуя этих основных финансовых игроков, утверждает: Влияние в основном осуществляется через фоновые дискуссии. Вы ведете себя на поводу у BlackRock и Vanguard, потому что знаете, что однажды вам может понадобиться их благосклонность. Для руководства компаний и корпораций рационально действовать в интересах основных держателей акций.

"Там, где есть договор, есть перочинный нож."

Шарль-Морис де Талейран-Перигор

Все, кто работает в развитии технологий строительной отрасли, постепенно попадают в жернова этой плановой экономики, созданной акулами капитализма при поддержке богатых династий запада, пенсионных фондов и печатного станка ФРС.

BlackRock управляет активами централизованно и строго следит за соблюдением всех формальных предписаний. Но сверх этого BlackRock и Vanguard практически ничего не делают. А между тем для функционирования рыночной экономики чрезвычайно важно, чтобы акционеры постоянно держали руку на пульсе событий в своих предприятиях и критически оценивали политику менеджмента.

В итоге сегодня все мировые САПР (и вообще все технологические) компании принадлежат инвестиционным фондам, которые на бумаге занимаются управлением стратегией компании, а де-факто - только соблюдением формальных предписаний для отчётов, которые позже попадают в красивый PDF документ для ежегодного собрания совета директоров.

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

Бегство от свободы, Эрих Фромм

Как сегодня Trimble будет соперничать с Autodesk или Hexagon на одном рынке, если CEO этих компаний отчитываются ежеквартально перед одними и теми же инвестиционными фондами с WallStreet, которые, в свою очередь, не заинтересованы в резких изменениях на тех рынках, от которых зависят их годовые отчёты и, как следствие, их личные бонусы.

Нет здоровой конкуренции - не будет и новых технологий. Отчасти поэтому все крупные корпорации в мире строительного проектирования фактически не имели отношения к разработке новых продуктов в последние 20 лет.

Если ещё десять лет назад такие крупные компании, как Autodesk, Nemetschek, Trimble имели репутацию уже не новаторов, а скорее имитаторов, когда было достаточно просто скопировать новый популярный продукт и выпустить свой клон, то сегодня необходимость в клонировании продуктов отпала. Сегодня стартапы и целые компании скупаются за любые деньги, которые предоставляют своим подопечным BlackRock и Vanguard.

Чтобы не конкурировать друг с другом на одном рынке, каждая компания из big5 САПР выбирает для себя отдельные технологические ниши и скупает постепенно программы и любые технологии в этом направлении.

Основные стартапы, приобретенные за последние 20 летОсновные стартапы, приобретенные за последние 20 лет

Для примера John Walker (будущий CEO Autodesk) предлагал Mike Riddle купить Autocad в 1982 году всего за $15 тыс. (изначально за $8 тыс.), но Mike настоял на условиях продажи Autocad за 1$ и 10% c продаж продукта. В 2020 году Revit стал самым продаваемым продуктом Автодеск, который она купила в 2002 году за 133 млн долларов. А уже в 2018 году Autodesk заплатил за Plangrid (стартап-приложение для планшета) почти миллиард долларов ($875 млн), где одним членом из совета директоров, за несколько лет до покупки, стала бывшая CEO Autodesk - Carol Ann Bartz.

Таким образом, на данный момент весь мир проектирования и вообще все технологии мира разделились на тех, кто принадлежит Blackrock и Vanguard, и тех, кого эти фонды через свои САПР-филиалы ещё купить не успели. Ни одна организация с высокими денежными показателями не имеет возможности избежать встречи с такими финансовыми гигантами, в какой бы стране она ни находилась.

Сегодня уже невозможно построить новый Autodesk или Trimble в нашем мире, где с такими ресурсами, которыми располагают сегодня инвестфонды, можно купить целые страны, не говоря уже о талантливых командах разработчиков.

Мы убрали с рынка всех конкурентов, но почему мы не движемся вперед?Мы убрали с рынка всех конкурентов, но почему мы не движемся вперед?

!Нельзя ни в коем случае демонизировать структуры, которые были построены BlackRock и Vanguard: любая организация и скорее всего каждый человек на земле, имея такие бесплатные ресурсы и доступ к печатному станку, воспользовались бы этим и поступили бы на месте Blackrock точно так же, скупая всё на своём пути.

В противовес монополиям, только мир open source решений мог бы сегодня составить конкуренцию таким олигопольным конгломератам. Посмотрим дальше на то, как большие корпорации пытаются контролировать open source движение.

Для чего мировым вендорам САПР нужны тысячи специалистов по базам данных, oб open source решениях, а также о решениях, над которыми работают основные вендоры САПР, поговорим в седьмой части.

Чтобы к седьмой части немного лучше понимать нового игрока на рынке САПР - Oracle, базы данных и open source, а также из-за схожести поведения двух компаний - сравним историю Oracle с историей развития Autodesk и посмотрим на то, как эти две корпорации боролись с open source движениями на своём рынке.

Autodesk идёт по стопам Oracle

История Autodesk, одного из лидеров САПР-мира, начинает всё больше походить на историю такого лидера своего времени, как Oracle. Так же, как Autodesk с Autocad была последние 30 лет мировым лидером 2D-проектирования, Oracle, в это же время, была мировым лидером баз данных - DBMS систем (database management system).

Прибыль Oracle от бизнеса, построенного на хранении данных, примерно в 10 раз больше, чем продажи лидеров САПР-отрасли: годовой оборот Oracle сегодня - $20 mlrd., а у Autodesk - всего $1,7 mlrd.. Как и во всех технологических компаниях мира, ведущими акционерами Oracle (как и Autodesk, Trimble, Apple, Microsoft и почти всех компаний на земле) являются две крупнейшие в мире инвестиционные компании - Vanguard и BlackRock.

Во многих статьях говорится, что Oracle была основана в конце 1970-х и что Oracle продает линейку программных продуктов, которые помогают крупным и средним компаниям управлять своей деятельностью. Но везде каким-то образом игнорируется тот факт, что Oracle всегда была значительным игроком в индустрии национальной безопасности. И что его основатель не заработал бы свои миллиарды, если бы не помогал создавать инструменты современной государственной и мировой слежки.

Как многие основные компании, выросшие после холодной войны, обязаны своим развитием федеральным и оборонным контрактам, так и Oracle на самом деле берет свое название от кодового названия проекта ЦРУ 1977 года. И именно ЦРУ было первым заказчиком Oracle.

C середины 2000-х Oracle начинает активно интересоваться строительной отраслью. Примечательно, что Oracle стал стратегическим партнёром buildingSMART в 2019 году, за один год до того, как главный САПР-производитель Autodesk присоединился к buildingSMART в 2020 году.У Oracle есть все шансы, чтобы стать лидером BIM-технологий. Об этом и почему BIM - это базы данных, поговорим подробнее в седьмой части.

В какой-то момент большие технологические компании выросли в большие структуры, которые, как и все крупные и сложные структуры, однажды перестали активно заниматься разработкой новых технологий.

Как в открытых письмах лучших архитекторов мира, адресованных Autodesk, (подробнее об этом в Часть 4: Борьба CAD и BIM. Монополии и лоббисты в строительной отрасли), так и в подкасте с Еленой Слеповой - мы все отмечаем, что Autodesk почти не развивает основной продукт Revit, а занимается только дизайном и украшательством интерфейса, попутно покупая новые стартапы (Navisworks, Assemble, Vault, Civil 3D) и технологии.

Открытое письмо архитектурных бюро мира Autodesk о том что продукт Revit не развиваетсяОткрытое письмо архитектурных бюро мира Autodesk о том что продукт Revit не развивается

Раздражение проектировщиков продуктами Autodesk растёт от версии к версии, но большие корпорации: Autodesk, Nemetschek и другие крупные покупатели стартапов - не могут привнести в код купленных программ значительных изменений.

Почему программы не развиваются

Любой большой программный продукт, разрабатываемый больше пяти лет, напоминает длинный "спагетти-код". При этом только несколько главных разработчиков в компании знают, как работает (максимум) 70% кода в такой программе, как Oracle Database, Autocad, Revit или Archicad.Новые инструменты от Autodesk, Nemetschek или Oracle сегодня являются лишь попыткой скрыть накопленные проблемы от разработчиков, потому что справиться с ними стало невозможно.

Затухание активного роста в техническом плане начинается с ухода разработчиков на более высокие должности или, что происходит чаще, с Exit основных разработчиков, которые забирают деньги (после продажи стартапа или выхода компании на IPO) и сами становятся венчурными инвесторами.

После Exit главных разработчиков большое количество костылей, из которых состоят эти программы, в последующих проектах создают трудно выявляемые баги, которые заваливают всю дальнейшую разработку продукта. Такой продукт, или, точнее, код, из которого он состоит, обозначают как legacy code.

Legacy code (от Legacy (англ.) наследство) устойчивое выражение, обозначающее старый код без каких-либо пояснений; главным его признаком является отсутствие возможности в нём разобраться.

Legacy code не проблема - если тебе не нужно поменять егоLegacy code не проблема - если тебе не нужно поменять его

На примере Oracle можно представить, в чём же состоит сложность Legacy кода и почему программы из 90-х почти не развиваются в последнее время.

Объем кодовой базы Oracle Database в период разработки версии 12.2 в 2017 году составлял 25 миллионов строк на языке C и стоит вам изменить лишь одну из этих строк, как ломаются тысячи написанных ранее тестов. За прошедшие годы над кодом Oracle Database успело потрудиться несколько поколений программистов, которых регулярно преследуют жесткие дедлайны, благодаря чему код превратился в настоящий кошмар.

Интерфейс - Геометрическое ядро. Мы не знаем как это работает, но если удалить это приложение рухнетИнтерфейс - Геометрическое ядро. Мы не знаем как это работает, но если удалить это приложение рухнет

Сегодня код любой программы из 90-х состоит из сложных кусков кода, отвечающих за логику, управление памятью, переключение контекстов и многое другое; они связаны друг с другом при помощи тысяч различных костылей. В итоге, у разработчика может уйти день или два только на то, чтобы разобраться, чем же в действительности занимается та или иная строка кода.

Возникает вопрос: каким же образом при всем этом Oracle Database (или Revit, Archicad) до сих пор удается держаться на ногах? Секрет в миллионах тестов. Их полное выполнение может занимать от 20 до 30 часов (при этом выполняются они распределенно на тестовом кластере из 100-200 серверов), поэтому сегодня процесс исправления одного единственного бага в Oracle Database занимает от нескольких недель до нескольких месяцев.

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

Autodesk разрабатывает Revit проще: разработчики просто не занимаются темой производительности, а от версии к версии создают только такие инструменты, которые работают поверх основного функционала.

Так как основной код был написан в конце 90-х, в Revit используется (исключая визуализацию) только одно ядро процессора, что сдерживает производительность проектирования. Например, у программы Revit уже нет возможности работать в многопоточном режиме, используя все ядра в hardware. И даже если у вас через 10 лет будет тысяча ядер в процессоре - прироста производительности в программе Revit вы не получите.

Геометрическое ядроГеометрическое ядро

Благодаря постоянной текучке кадров в дополнение к проблеме закрытой разработки кода, вокруг нас полно старых Legacy продуктов, которые написаны ужасно плохо, но при этом невероятно сложно и дорого поддерживаются сегодня на плаву. Причём переписать их уже никогда не получится, потому что они взаимодействуют с таким же ужасным кодом у пользователей продукта, и поэтому необходимо соблюдать совместимость с багами и не документированными особенностями. По этой причине многие продукты стали заложниками обратной совместимости. В том числе Windows, Microsoft Office и основные программы на рынке САПР.

У таких программ, как Revit, ArchiCAD, Microstation уже нет будущего, и возможно, сами вендоры это понимают. Поэтому все силы корпораций сегодня тратятся не на увеличение производительности геометрического ядра, а на поиск нового успешного продукта или новых уникальных разработчиков, как Leonid Raiz (Revit), Mike Riddle (AutoCAD) или Gabor Bojar (ArchiCAD).

Из-за отсутствия новых успешных продуктов, основные усилия таких больших корпораций начинают концентрироваться на навязывании своих продуктов, агрессивном маркетинге и на том, чтобы поддерживать текущее ресурсоёмкое жизнеобеспечение сложной и забюрократизированной структуры.

Исследование Campaign for Clear Licensing, показало, что аудиты, проводимые такими поставщиками программного обеспечения, как Oracle и Autodesk (Microsoft, SAP, IBM) блокируют конкуренцию и препятствуют инновациям в ИТ-отделах компаний, где эти аудиты проводились.

Кто наименее полезный поставщик с точки зрения аудита? Oracle был признан худшим поставщиком в процессе аудита, за ним следуют IBM и Autodesk.Кто наименее полезный поставщик с точки зрения аудита? Oracle был признан худшим поставщиком в процессе аудита, за ним следуют IBM и Autodesk.

К началу 2000-х основные корпорации заняли свои ниши в отрасли и каждый год спокойно распределяли прибыли среди акционеров. Но с началом эры open source на горизонте появляется новый конкурент - разработчики открытых и прозрачных продуктов, совсем не похожие на специалистов по контракту, переехавших в Калифорнию или Бостон из Азии или Европы.

Основной головной болью руководителей больших корпораций Oracle, Microsoft, SAP, Autodesk, IBM к середине 2000-х становится не миллион строк спагетти кода, а новые open source продукты, стремительно набирающие популярность: Linux, GitHub, Spark, Mozilla, Gimp, PHP, WordPress, Android, Blender и тысячи других.

В случае с Oracle таким конкурентом стал молодой open source стартап из Швеции - MySQL.

Борьба корпораций с open source

Обычно любые стартапы, стоящие на пути корпораций, уже к началу 2000-х можно было купить при поддержке BlackRock, но как купить Оpen source-идею, за которой стоят сотни разработчиков со всего мира?

MySQL - open source проект, который одновременно разрабатывали сотни специалистов со всего мира. При этом код полностью бесплатен и прозрачен для дальнейшей разработки (или написания инструментов для него), благодаря чему MySQL быстро завоевал популярность на рынке баз данных.

Популярность баз данных по годам с 2013 годаПопулярность баз данных по годам с 2013 года

В борьбе за рынок Oracle начала снижать цены и предоставлять большие скидки тем компаниям, которые уже использовали или ещё только собирались использовать MySQL. Одновременно с этим Oracle, осознавая угрозу своему бизнесу, всеми способами пытался купить это быстрое, бесплатное и прозрачное DBMS решение.

В течение всего 2006 года Ларри Эллисон (глава Oracle с одесскими корнями) неоднократно предлагал выкупить MySQL, но трое друзей-шведов, основателей MySQL, постоянно отвергали предложение от империи зла Oracle, взлёт которой произошёл благодаря сотрудничеству с ЦРУ.

Стабильный Oracle c 1997 годаСтабильный Oracle c 1997 года

В итоге акционеры MySQL продали свой продукт компании Sun (отцы-основатели МySQL получили от сделки по $10 mln.) и уже в 2009 году Oracle сумел опередить IBM и заключил соглашение о покупке компании Sun (вместе с продуктом MySQL) за $7.4 миллиардов.

В 2009 MySQL ждало большое обновление: в версии MySQL 5.4 появилась поддержка 16-процессорных серверов x86, и, по некоторым тестам, производительность MySQL должна была вырасти в десятки раз. Выход MySQL 5.4 был запланирован на 21 апреля, но, по случайности, за день до того произошла сделка с Oracle.

Уже после покупки, чтобы не давать развития своему непокорному приёмному open source сыну, с 2009 г., Oracle (которая теперь являлась владельцем прав на MySQL) пыталась изнутри расшатать и замедлить открытую модель разработки знаменитой СУБД.

Таким образом, Oracle, при помощи BlackRock, расчистил рынок своему основному закрытому спагетти продукту Oracle Database на следующие 10 лет, а акционеры инвестиционных фондов теперь могли ожидать выплаты дивидендов на ожидаемом уровне в ближайшие годы.

Но open source MySQL-идею убить уже невозможно, и разработчики из комьюнити MySQL начали перетекать в другие open source проекты. В итоге все основные разработчики MySQL махнули рукой на Oracle и перешли на более быстрые и современные open source базы данных - MariaDB (форк копия MySQL), PostgreSQL и SQL-lite.

Подобные покупки постоянно происходят и на рынке САПР-решений. Все те же тренды ждут любых разработчиков САПР и BIM-решений, а сама история с MySQL похожа на историю с IFC, изначально открытым форматом.

Oracle, по сути, сделал c MySQL то же самое, что сделал Autodesk c IFC в середине 90-х, но гораздо быстрее и проще.

Autodesk и формат данных IFC

Идея открытого формата IFC родилась у визионера строительных технологий Leonard Obermeyer, который перед олимпиадой в Мюнхене во время строительства мюнхенского аэропорта взаимодействовал с поставщиками и фирмами со всего мира. Во время проектирования олимпийских проектов Leonard Obermeyer понял, что нужен один общий язык, на котором будут общаться строители и производители строительных элементов со всего мира.

Так как сам Leonard Obermeyer не был программистом, эту идею он передал своему родному факультету мюнхенского университета, где дальнейшей разработкой нового открытого формата занимались Richard Junge и Thomas Liebich с командой студентов.

Идеей создателей IFC-формата было создать всемирный и свободный язык обмена данными в строительстве (несмотря на военные корни формата IFC-STEP, протокола Application Protocol 225), но в начале 90-х ещё мало было известно об open source.

Благодаря другу Leonard Obermeyer - Patrick MacLeamy (CEO of HOK) - Autodesk активно включается в развитие всемирной идеи IFC. Проходит всего несколько лет, и регистрацию и разработку IFC берёт полностью под свой контроль Autodesk.

Об этом подробнее в Часть 3: Отцы BIM технологий. Кто стоит за успехом Autodesk и openBIM?

Но к концу 90-х, не имея нормальных 3D-продуктов, сам Autodesk не смог применять нормально этот продукт в своих программах - и идея мирового 3D формата уходит под контроль картельной организации IAI (которая позже переименовывается в buildingSMART).

Для контроля над развитием IFC у руля buildingSMART остаётся Patrick MacLeamy, партнёр корпорации Autodesk по совместным проектам с компанией HOK (где McLeamy был CEO). К слову, в некоторых странах ещё сегодня представителями Autodesk и представителями buildingSMART являются зачастую одни и те же специалисты.

Исходя из этих фактов, можно предположить, что американская организация buildingSMART держит Autodesk в курсе возможных вариантов развития, для того чтобы Autodesk смог вовремя перехватить инициативу в мире форматов обмена данными и заниматься новыми технологиями без оглядки на конкурентов.

Подобным образом Autodesk выпустил на рынок open source решение Dynamo, которое используется в Revit и Civil 3D для расширения функционала. Dynamo изначально представлялся как open source продукт, который внезапно возник в 2011 году в недрах Autodesk (или точнее был разработан по заказу Autodesk). Так же, как и buildingSMART, к рождению которого приложила руку корпорация Autodesk, - код Dynamo тоже не отличается прозрачностью. Многие разработчики указывают на то, что пакеты, завернутые в библиотеки DLL, часто запрещают доступ к коду, что не позволяет пользователям исследовать ни код, ни то, как отдельные куски кода обрабатываются или анализируются в инструменте Dynamo. Что также не позволяет использовать Dynamo в продуктах, по-настоящему открытых, таких как BlenderBIM (для визуального программирования в Blender сегодня используется Sverchok).

Типы open source: совершенно свободный, с явным контролем, неявно контролируемыйТипы open source: совершенно свободный, с явным контролем, неявно контролируемый

Таким образом, Autodesk в контроле над открытыми проектами IFC и Dynamo создала конструкцию, похожую на ту, что Oracle создал с MySql. Только в мире баз данных - Oracle открыто, через Sun, купила open source - MySql, а Autodesk на расстоянии контролирует движение проектов Dynamo и buildingSMART (который, в свою очередь, старается на расстоянии общаться с европейскими вендорами openBIM движения - Nemetschek).

И если сегодня образуется по-настоящему новый open source формат или у Revit появится достойный open source конкурент, - то Autodesk пойдёт проверенным путём Oracle и, возможно, попытается выкупить права на любой продукт на самых ранних стадиях, что, скорее всего, опять продлит жизнь продуктам Autodesk ещё на одно десятилетие.

Как узнать кто уже мёртв, а кто ещё нет? Мы маленькая строительная компания.Как узнать кто уже мёртв, а кто ещё нет? Мы маленькая строительная компания.

Сегодня buildingSMART неспешно пытается устанавливать правила на рынке САПР, при этом интересы buildingSMART в основном диктуются потребностями основных игроков в этой нише - Autodesk, Bentley Systems (с 2019 Oracle).

Единственной более-менее свободной от лоббирования организацией остаётся альянс ODA (Open Design Alliance).

Проблема Autodesk - организация открытых стандартов - ODA

ODA круто изменил ситуацию для пользователей CAD во всём мире, когда позволил разработчикам CAD-приложений существенно сократить затраты на поддержку формата DWG, ставшего де-факто отраслевым стандартом для обмена CAD-данными.

ODA создала продукты (основным из которых является Teigha) с возможностью для более чем 2000 организаций-членов работать без всякой оглядки на Autodesk, чем фактически убрал искусственные барьеры, которые сдерживали развитие всей отрасли САПР.

Альянс по Открытому Проектированию (Open Design Alliance) является некоммерческим консорциумом, нацеленным на распространение открытых форматов для обмена данными САПР. Технологическая платформа ODA обеспечивает пользователей средствами для создания широкого спектра приложений, включая средства визуализации и даже полномасштабные САПР. Платформа поддерживает файлы DWG, DGN, RFA, IFC, RVT с возможностями редактирования, импорта и экспорта в другие файловые форматы.

История ODA началась с попытки Autodesk купить компанию SoftDesk, которая в середине 90-х разрабатывала свою САПР-платформу с целью полностью заменить AutoCAD. После антимонопольного расследования суд запретил Autodesk покупать SoftDesk, который позже (после передачи прав VISIO) был выкуплен компанией Microsoft.

На основе технологий компании Softdesk и InteliCADD (позже InteliCAD) в 1998 году образуется новый альянс OpenDWG. Альянс ODA (OpenDWG Alliance) поставил своей целью уравнивать шансы всех производителей САПР-решений, вне зависимости от того, в каких отношениях с компанией Autodesk находятся эти разработчики.

Эквалайзер - урванитель САПР разработкиЭквалайзер - урванитель САПР разработки

Первый конфликт между ODA и Autodesk возник в начале 2000-х вокруг формата DWG.

В 1998 году ODA предоставила новые инструменты миллионам пользователей программного обеспечения с возможностью продолжать использовать формат файла DWG без привязки к единственному поставщику продуктов - Autodesk.

Примечательно, что сам формат файла DWG и программа Autocad были разработаны Mike Riddle и что DWG использовался в конце 1970-х в его InteractCAD, и только в 1982 году John Walker выкупает полностью продукт Autocad вместе с форматом DWG, основывая таким образом фирму Autodesk для массовой продажи DWG продукта.

Сам Autodesk после покупки программы Autocad (20 лет) не предоставлял API для доступа к файлам DWG, поэтому и ответом на такую закрытость стало появление на рынке САПР первой открытой инициативы: GNU LibreDWG, который мог читать формат DWG. Но, к сожалению, LibreDWG не мог редактировать информацию в DWG файле.

Этот барьер по изменению файла DWG смог преодолеть альянс ODA с продуктом Teigha, который позволял работать с форматом DWG в любой САПР-программе. Этот продукт уравнял шансы всех САПР-разработчиков, и именно ему обязаны своим успехом такие ныне известные компании, как бельгийская Bricsys, немецкая Graebert, французская DraftSight, китайская ZWSoft, российская NanoSoft и ряд других.

В ответ на открытые разработки Autodesk создал для сторонних разработчиков САПР инструмент - RealDWG (настоящий истинный DWG) в виде модулей экспорта и импорта, что позволяло сторонним разработчикам САПР-программ наконец встраивать в свой функционал экспорт и импорт чертежей в формате DWG.

С 2006 года на ODA посыпались судебные иски от Autodesk, которая пыталась защитить купленный ими в 1982 году продукт DWG. И с момента противостояния с ODA, чтобы усложнить жизнь конкурентам и искусственно ограничить конкуренцию, Autodesk создавала каждые несколько лет новую версию самого правильного DWG формата (при этом вставляя в формат водяные знаки Autodesk).

Иск компании Autodesk к альянсу ODA через Американский окружной суд (US District Court)Иск компании Autodesk к альянсу ODA через Американский окружной суд (US District Court)

В 2006 году компания Autodesk внедрила в обновленный формат DWG 2007 технологию TrustedDWG, которая позволяла определить, создан ли файл формата DWG в одной из программ Autodesk или в программе, использующей RealDWG. В случае, если файл DWG 2007 создан в нелицензированной программе, AutoCAD показывал сообщение, предупреждающее пользователя о возможных проблемах совместимости. Компания мотивировала своё решение заботой о пользователях.

Из-за резкого интереса конкурентов к инструментам ODA, спустя 25 лет после создания DWG, Autodesk в 2006 году решила зарегистрировать DWG как свою торговую марку. Захватив рынок CAD, Autodesk утверждала, что самый правильный DWG файл могут делать только продукты Autodesk.

Autodesk выиграл суды, и на первый взгляд показалось, что Autodesk отстоял свои права на формат DWG, но судебные запреты не стали концом света для альянса ODA.

В 2007 году иск был окончательно отозван. Стороны заключили мировое соглашение. ODA исключил код TrustedDWG из библиотек DirectDWG, а Autodesk изменил предупреждающие сообщение в AutoCAD 2008. В итоге в решениях суда речь шла только о торговой марке "DWG", при этом формат файла DWG остался общедоступным.

Информация о проигрыше в суде на официальном сайте ODAИнформация о проигрыше в суде на официальном сайте ODA

Возможно, уже сегодня подобная борьба разворачивается за форматы RVT и RFA.

Revit (и похожий продукт форк PTC - Solidworkds) и форматы RFA и RVT были разработаны Леонидом Райцем (и его учителем по PTC - Самуилом Гайзбергом) в 90-е. После покупки при помощи патентов и регистрации прав на торговые марки Autodesk пытался закрепить своё право над 3D САПР-программой Revit и её форматом.

В мае 2020 года, на пике интереса к продукту Revit и его BIM решениям (а не на закате популярности, как это было с Autocad), ODA официально выходит на рынок со своим продуктом BimRv SDK. BimRv SDK от ODA предлагает работать с данными Revit без зависимости от приложения Revit. Инструмент позволяет, например, создавать семейства (геометрию типов), не используя Revit.

За несколько лет до публикации релиза BimRv ODA становится первым вендором, который позволяет не просто читать информацию из IFС, а дает возможность создавать IFC геометрию, чего ещё ни одна САПР-компания сделать не смогла. Полный открытый IFC-набор инструментов от ODA будет представлять собой доступ к данным и к созданию объектов, интегрированный с высокоскоростной визуализацией и возможностями конвертирования IFC-данных в другие форматы, такие как .dwg.

Логично, что если инструмент, редактирующий Revit или IFC файлы от ODA, получит реальное распространение, то прибыли, которые Autodesk сегодня делает на своих продуктах, могут резко упасть.

На опыте борьбы с Softdesk и после судебных тяжб с ODA по продукту Teigha-DWG Autodesk понимает, что ODA c BimRv SDK уже продвинулась на порядок дальше в своих возможностях, и теперь ODA уже не допустит ошибок, которые были допущены в борьбе за открытость формата DWG.

Поэтому сегодня Autodesk остаётся массово скупать новые технологии на рынке стартапов или пробовать "усложнить" работу альянса ODA, который пытается незаконно (по мнению Autodesk) распространять форматы RVT и DWG и, по пути, стать тем самым возрождённым SoftDesk, который Autodesk не получилось до конца убить в самом начале развития.

Самый простой и верный способ обмануть человека это прикинуться другом.

Публий Овидий Назон

Наблюдая за успехами ODA со стороны, через несколько месяцев после того, как ODA опубликовал BimRV, Autodesk вынес волевое решение присоединиться к альянсу ODA, чтобы, возможно ближе понять все возможности альянса, который ещё не удалось купить. Autodesk указал причину присоединения к ODA: интерес к набору инструментов IFC от ODA (который обеспечивает полную и гибкую совместимость с IFC для любого настольного или веб-приложения). При этом в саму организацию buildingSMART, которая занимается не только инструментами IFC, но и разработкой непосредственно формата IFC, Autodesk вступил на один месяц позже, в октябре 2020 года.

ODA показывает BimRV SDK - Autodesk вступает в ODA - Autodesk вступает в buildingSMARTODA показывает BimRV SDK - Autodesk вступает в ODA - Autodesk вступает в buildingSMART

Из-за активности альянса ODA по раскрытию форматов RVT, RFA, начиная с 2020 года Autodesk стал активно возвращаться к управлению своим брошенным приемным сыном - форматом IFC, встраивая с версии Revit-2020 все те возможности экспорта в IFC формат, которые до этого (видимо, искусственно) тормозились или просто не развивались.

Возможно, Autodesk понимает, что закрытые форматы сегодня больше не смогут быть драйвером той бизнес-модели, которая успешно работала в 90-е годы, и поэтому сегодня Autodesk ставит для себя целью отказаться от форматов и продавать главным образом облачные решения. Одновременно с этим Autodesk спешит возглавить разработку открытых технологий в САПР-мире вслед за своими друзьями: IBM, Microsoft, Oracle, SAP, которые также заявили свои права на лидерство в open source-разработках (об этом подробнее в следующей части).

Но открытость open source плохо сочетается с той политикой, которую фирмы силиконовой долины проводили последние 30 лет.

В заключение

Времена настоящей конкуренции благодаря финансовым фондам уходят в историю. Отсутствие конкуренции сказывается на развитии технологий в нашей, и без того отсталой, отрасли строительства.

Старые корпорации, такие как Autodesk, Hexagon, Nemetschek Group, Trimble, построившие отличную инфраструктуру в 90-е, пытаются подстраиваться под быстрые изменения рынка. Разработка Legacy программ, например, Revit и Archicad, тормозится. Небольшие CAD и BIM стартапы или уничтожаются, или покупаются за пару миллионов (или как Plngrid, Aconex уже миллиардов) долларов - и уходят в бюрократическую систему дедлайнов и костылей; а к самостоятельной разработке новых идей и инструментов у корпораций, кажется, нет ни интереса, ни творческих способностей.

Олигополия в САПРОлигополия в САПР

Кризис программного обеспечения в САПР и в других технологиях носит также системный и поколенческий характер. Проблема в том, что сейчас у руля BlackRock, Vanguard, Oracle, Autodesk и других компаний стоит поколение X или Baby-Boomers, которые ещё помнят деколонизацию доминионов и карибский кризис в 60е.

И, конечно, мы не можем не испытывать уважения к этому поколению (наших родителей), но очевидно, что технологии развиваются слишком быстро, чтобы отдавать управление новыми технологиями людям из BlackRock или Autodesk, которые родились в то время, когда человек ещё не изобрёл пульт от телевизора, а компьютеры были размером с дом.

Определение поколенийОпределение поколений

В целом укрупнение капитала и монополизация рынка с дальнейшими построениями олигополий или прямых монополистов это естественный ход капитализма. Таким образом, капитализм на стероидах создал бюрократию управления или, другими словами, плановую экономику на мировом уровне.

Только если в Советском союзе при плановой экономике получаемая прибыль принадлежала всем членам общества, то в мировой плановой экономике прибыль получают только акционеры основных инвестиционных фондов.

Плановая экономика тогда и сейчасПлановая экономика тогда и сейчас

Ни в коем случае нельзя обвинять в алчности структуры, построенные BlackRock и Vanguard: на их месте любая организация и возможно любой человек поступил бы точно так же. Мы можем быть благодарны им за то, что конкретно этот тупиковый путь выбрали именно они.

Успокаивает только тот факт, что могущество теневых банков и бюрократия в масштабах всей планеты - недавнее явление, которое наука и политика только начинают понимать. Это тренд всего лишь последних 20 лет и, благодаря истории, мы уже знаем, что плановая экономика нежизнеспособна в рамках одной страны, и такая модель ручного управления уж точно не имеет смысла в долгосрочной перспективе в масштабах всей планеты.

Нам помогают проблемы и кризисы. Большие корпорации, благодаря постоянной поддержке мамы BlackRock и папы Vanguard, не способны сами создать для себя трудные времена, которые могли бы помочь компаниями и технологиям выйти на новый уровень развития.

Тот уже не хитрый, о ком все говорят, что он хитер.

Александр Суворов

Логично, что BlackRock и Vanguard уйдут в историю со своей бюрократией и сложными закрытыми конструкциями, точно так же, как эта бюрократия и вертикальная система связей исчезла из плановой экономики Советского Союза.Для поражения BlackRock и Vanguard не хватает только сильного соперника, которым может стать сегодня децентрализированная экономика.

Благодаря прозрачности информации: журналистам, появлению камер и фотоаппаратов - в конце 20 века люди перестали убивать массово других людей. А в 21 веке, благодаря интернету и децентрализованным приложениям, на наших глазах при помощи open source кода создаётся новая децентрализованная экономика, за которой пытаются угнаться старые корпорации со своим другом BlackRock.

Эти многие западные компании и структуры в будущем ещё ждут своя перестройка и своя гласность.

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

Неизвестный автор

Остаётся надеяться на кризисы и чёрных лебедей, вроде COVID-19, благодаря которым специалисты со всего мира после 2021 года, возможно, перестанут торопиться переезжать в другие страны и искать своё место в этой, хоть и денежной, но очень забюрократизированной и устаревшей структуре. Такие новые уникальные специалисты, вроде Gabor Bojar, Mike Riddle, Samuel Geisberg, могут уже сегодня заниматься разработкой новых САПР-BIM технологий из любого доступного места.

Новый мир программного обеспечения и технологий будет намного прозрачней, способствуя тем самым увеличению количества разработчиков, созданию новых удалённых рабочих мест и открытию новых возможностей монетизации.

Про решения Оpen source, монетизацию про то почему IFC это не open source поговорим в следующей части.


Если Вам интересна тема openSource и BIM (продукты с открытым кодом в строительстве) подключайтесь к обсуждению в группе телеграмм - bimopensource: https://t.me/bimopensource

Буду благодарен за репост в социальных сетях и рад вашим комментариям, уточнениям и критике.

Схема связей BIM программ указанных в статье в хорошем качестве доступна по ссылке.

Предыдущие статьи по теме:

Сравнение технологий в строительстве и 5D проектирование в Азии и Европе: Казахстан, Австрия, Германия, Китай, Украина

Войны лоббистов и развитие BIM. Часть 4: Борьба CAD и BIM. Монополии и лоббисты в строительной отрасли

Подробнее..

Создаём мини PHP SDK для подписи запросов к Oracle Cloud Infrastructure API

11.02.2021 04:19:49 | Автор: admin

Идея написать эту библиотеку возникла, когда захотелось в полной мере воспользоваться всеми преимуществамибесплатного предложенияOracle Cloud Infrastructure, а именно 10 ГБ хранилища объектов (Object Storage) и 10 ТБ исходящего трафика в месяц. Разница сAWSS3 простоогромнейшая. К сожалению,OracleCloudне имеетв наличииSDKдля всё еще самого популярного языка программирования для разработки веб-сайтов. Хорошая новость состоит в том, что сервисчастично совместимсAmazonS3, а это означает, что можно применить уже имеющиеся и отлично задокументированныеинструменты разработчика, в том числе дляPHP.

Тем, кому не терпится увидеть код, добро пожаловатьhttps://github.com/hitrov/oci-api-php-request-sign.

Действительно, с имеющимися инструментами можно выполнять почти все операции, которые можно представить - для создания, чтения и удаления корзин (buckets) и объектов (файлов). Корзины могут быть как публичными (с возможностью листинга файлов и без) и приватными. Есть возможность загружать файлы в приватную корзину, имея лишь секретныйURL(сгенерированный вручную с помощьюCLIили веб-интерфейса - консолиOracleCloud). На самом деле этого уже может быть достаточно для многих сценариев, особенно если генерировать стойкие к подбору имена файлов - в случае, если вы не хотите выставлять их на публику.

Меня интересовала возможность расшаривать файлы, то есть делиться общедоступными ссылками на файлы, и, конечно же, ограничивать доступ при необходимости. При небольшом количестве файлов можно делать это вручную, но мы собрались здесь, чтобы иметь программный доступ. ВAWS S3этоназываетсяPre-Signed URL,ауOracle -Pre-Authenticated Request.

Установка AWS PHP SDK

composer require aws/aws-sdk-php

Ниже будет показано, где взять доступы (AWS_ACCESS_KEY_IDи AWS_SECRET_ACCESS_KEY.

Namespace же можно увидеть

$namespaceName = 'frpegp***';$bucketName = 'test******05';$region = 'eu-frankfurt-1';$endpoint = "https://$namespaceName.compat.objectstorage.$region.oraclecloud.com";$s3 = new Aws\S3\S3Client([    'version' => 'latest',    'region'  => $region,    'endpoint' => $endpoint,    'signature_version' => 'v4',    'use_path_style_endpoint' => true,    'credentials' => [        'key'    => 'AKI***YYJ', // remove if you have env var AWS_ACCESS_KEY_ID        'secret' => 'ndK***cIf', , // remove if you have env var AWS_SECRET_ACCESS_KEY    ],]);$cmd = $s3->getCommand('GetObject', [    'Bucket' => $bucketName,    'Key' => 'fff.txt']);$request = $s3->createPresignedRequest($cmd, '+20 minutes');

К сожалению, данная операция, хотя и не вызывает ошибку, отдавая в ответPSR-7request, но возвращаемый имURLвида

https://{namespace}.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/{bucket}/fff.txt?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=***%2F20210210%2Feu-frankfurt-1%2Fs3%2Faws4_request&X-Amz-Date=20210210T185244Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=a167a***9a857

просто не работает.

<?xml version="1.0" encoding="UTF-8"?><Error>    <Message>The required information to complete authentication was not provided.</Message>    <Code>SignatureDoesNotMatch</Code></Error>

Поскольку совместимость для данной операции не была заявлена, странно было бы ожидать иного, но попробовать стоило :)

Здесь я попробую очень кратко описать, что необходимо для подписи запроса кAPI, ведь все изложено довольно подробноздесь, пусть и с примерами для иных языков программирования.

Разумеется, подпись будет работать для всех запросов начиная от создания\остановки\бэкапаавтономной базы данных, управленияDNSи заканчивая отправкойEmail. Всё что указано в API Reference and Endpoints.

Прежде всего, для того, чтобы начать работу, нужны ключи доступа, в веб-интерфейсе (консоли)OracleCloud необходимо зайти вUserSettings

Действия в профиле Oracle CloudДействия в профиле Oracle Cloud

API KeysAdd API Key

API Keys - Add API KeyAPI Keys - Add API Key

Downloadprivatekey(сохраняем в надежном месте), затемAdd

Download Private Key and AddDownload Private Key and Add

Сохраняем все значения из текстового поля, они нам понадобятся через минуту

Configuration File exampleConfiguration File example

Для того, чтобы воспользоваться AWS PHP SDK, вам необходимы Customer Secret Keys (они же AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY в понимании Amazon.

Установка Oracle Cloud Infrastructure mini PHP SDK(никаких внешних зависимостей!)

composer require hitrov/oci-api-php-request-sign

Пакет использует стандартнуюPSR-4 автозагрузку классов.

require 'vendor/autoload.php';use Hitrov\OCI\Signer;

Для авторизации нужно задать переменные среды (замените на значения, взятые из текстового поля, проставьте путь к файлу с приватным ключом).

OCI_TENANCY_ID=ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsqOCI_USER_ID=ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjqOCI_KEY_FINGERPRINT=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34OCI_PRIVATE_KEY_FILENAME=/path/to/privatekey.pem

В этом случае конструктор не принимает аргументов.

$signer = new Signer;

Переменным среды есть несколько альтернативhttps://github.com/hitrov/oci-api-php-request-sign#alternatives-for-providing-credentials, не стану дублировать это здесь.

МыпопробуемвыполнитьCreatePreauthenticatedRequest.

Вся сложность (если можно так выразиться) абстрагирована в один публичный метод

public function getHeaders(    string $url, string $method = 'GET', ?string $body = null, ?string $contentType = 'application/json', string $dateString = null): array

Пример использования

$curl = curl_init();$url = 'https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/{namespaceName}/b/{bucketName}/p/';$method = 'POST';$body = '{"accessType": "ObjectRead", "name": "read-access-to-image.png", "objectName": "path/to/image.png", "timeExpires": "2021-03-01T00:00:00-00:00"}';$headers = $signer->getHeaders($url, $method, $body, 'application/json');var_dump($headers);$curlOptions = [  CURLOPT_URL => $url,  CURLOPT_RETURNTRANSFER => true,  CURLOPT_ENCODING => '',  CURLOPT_MAXREDIRS => 10,  CURLOPT_TIMEOUT => 5,  CURLOPT_FOLLOWLOCATION => true,  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,  CURLOPT_CUSTOMREQUEST => $method,  CURLOPT_HTTPHEADER => $headers,];if ($body) {  // not needed for GET or HEAD requests  $curlOptions[CURLOPT_POSTFIELDS] = $body;}curl_setopt_array($curl, $curlOptions);$response = curl_exec($curl);echo $response;curl_close($curl);
array(6) {  [0]=>  string(35) "date: Mon, 08 Feb 2021 20:49:22 GMT"  [1]=>  string(50) "host: objectstorage.eu-frankfurt-1.oraclecloud.com"  [2]=>  string(18) "content-length: 76"  [3]=>  string(30) "content-type: application/json"  [4]=>  string(62) "x-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="  [5]=>  string(538) "Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\""}
{  "accessUri": "/p/AlIlOEsMok7oE7YkN30KJUDjDKQjk493BKbuM-ANUNGdBBAHzHT_5lFlzYC9CQiA/n/{namespaceName}/b/{bucketName}/o/path/to/image.png",  "id": "oHJQWGxpD+2PhDqtoewvLCf8/lYNlaIpbZHYx+mBryAad/q0LnFy37Me/quKhxEi:path/to/image.png",  "name": "read-access-to-image.png",  "accessType": "ObjectRead",  "objectName": "path/to/image.png",  "timeCreated": "2021-02-09T11:52:45.053Z",  "timeExpires": "2021-03-01T00:00:00Z"}

Вот и всё!

По большому счету, клиентский код более ни в чем не нуждается. Остальное для тех, кому любопытно в образовательных целях.

1) Прежде всего, нам необходимо собрать список подписываемых заголовков (SIGNING_HEADERS_NAMES). Он всегда содержит

  • date

  • (request-target)

  • host

ДляPOST|PUT|PATCHзапросов добавляются еще три

  • content-length

  • content-type

  • x-content-sha256

$signingHeadersNames = $signer->getSigningHeadersNames('POST');

2) SHA256 хэш тела запроса кодированный вbase64

$bodyHashBase64 = $signer->getBodyHashBase64($body);

3) Сформировать строку для подписи, в нашем случае она будет выглядеть следующим образом

date: Mon, 08 Feb 2021 20:51:33 GMT(request-target): post /n/{namespaceName}/b/{bucketName}/p/host: objectstorage.eu-frankfurt-1.oraclecloud.comcontent-length: 76content-type: application/jsonx-content-sha256: X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
$signingString = $signer->getSigningString($url, $method, $body, 'application/json');

Хэш мы получили в (2).Важно, что дата и время не должны отличаться от текущих на более, чем 5 минут.

4) Подписать строку из (3) приватным ключом с помощью алгоритмаRSA-SHA256

$signature = $signer->calculateSignature($signingString, $privateKeyString);

5) Сформировать KEY_ID данными, которые вы скопировали при создании API Key, это строка, разделенная слешами

"{OCITENANCYID}/{OCIUSERID}/{OCIKEY_FINGERPRINT}"

$keyId = $signer->getKeyId();

6) Теперь мы готовы сгенерировать заголовок авторизации(версия 1останется таковой до отдельного уведомления отOracle)

Authorization: Signature version=\"1\",keyId=\"{KEY_ID}\",algorithm=\"rsa-sha256\",headers=\"{SIGNING_HEADERS_NAMES_STRING}\",signature=\"{SIGNATURE}\"

гдеSIGNING_HEADERS_NAMES_STRING это список из (1), разделенный пробелами.

date (request-target) host content-length content-type x-content-sha256

$signingHeadersNamesString = implode(' ', $signingHeadersNames);$authorizationHeader = $signer->getAuthorizationHeader($keyId, $signingHeadersNamesString, $signature);

Пример вывода

Authorization: Signature version=\"1\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34\",algorithm=\"rsa-sha256\",headers=\"date (request-target) host content-length content-type x-content-sha256\",signature=\"LXWXDA8VmXXc1NRbMmXtW61IS97DfIOMAnlj+Gm+oBPNc2svXYdhcXNJ+oFPoi9qJHLnoUiHqotTzuVPXSG5iyXzFntvkAn3lFIAja52iwwwcJflEIXj/b39eG2dCsOTmmUJguut0FsLhCRSX0eylTSLgxTFGoQi7K/m18nafso=\"

Реальные заголовки запроса - см. выводvar_dump()выше - должны содержать всё из (3), за исключением поля(request-target)и его значения. И, конечно же, заголовок авторизации (6).

МнепомогластатьяOracle Cloud Infrastructure (OCI) REST call walkthrough with curl. Некоторые имена методов позаимствованы из официальногоGoLangSDK. Тест-кейсы оттуда же.

Подробнее..

Unit-тесты в СУБД как мы делаем это в Спортмастере, часть третья

29.04.2021 16:13:12 | Автор: admin

Привет, привет!

Пару лет назад было решено поделиться историей про автоматизированное тестирование СУБД и наш опыт применения в Спортмастере. С результатами можно ознакомиться здесь и здесь.

И сейчас, спустя значительное время, хочется подвести итоги и порефлексировать о системе. Да и даже просто ответить на вопрос: Как там ваши автотесты?

Спойлер

Краткое описание предыдущих частей

Есть система лояльности Спортмастера:

  • огромная, сложная и высоконагруженная система 24/7

  • важный функционал для бизнеса

  • активно развивается

  • есть сложные вычислительные алгоритмы

  • много потребителей

  • система преимущественно содержит серверную логику на Oracle

Хотелось повысить качество выпускаемого продукта и сократить время на тестирование, поэтому внедрили систему автоматизированного тестирования на PL/SQL:

  • ядро системы это open source библиотека utPLSQL v 2.3 от Стивена Фейерштейна

  • вокруг utPLSQL развёрнуты самописные модули, которые облегчают работу с автотестами:

    • модуль запуска автотестов

    • модуль генерации тестовых данных

    • модуль управления метаданными

    • модуль отчётности

    • и т.д.

  • сформирован каталог автотестов с определением ключевых настроек

  • автоматизированы запуск автотестов, отчётность и накат изменений

А что же сейчас?

Самое важное, что стоит сказать про систему автоматизированного тестирования она успешно работает, приносит пользу и постоянно развивается. А каждая ошибка, найденная автотестом, приводит примерно к такому состоянию:

Но это всё демагогия, поэтому перейдём к качественным показателям:

  1. Количество автотестов: 2400

  2. Время работы полного запуска: 40 секунд

  3. Показатель Code Coverage: 55%

Скорость работы

Одним из ключевых параметров системы автоматизированного тестирования является время работы автотестов. В каких-то системах всегда запускаются все тесты, а в каких-то выделяется определённая группа тестов и принимается решение, что такого запуска достаточно для уверенности в работоспособности. Но так или иначе со скоростью работы сталкиваются все, а уж всем автоматизаторам веба и тем более древних приложений я совсем не завидую (отдельный привет TestComplete!).

Автоматизация тестирования на уровне СУБД позволяет избежать большого числа проблем, связанных со внешней средой, но для быстрой работы тестов всё равно необходимо немного пошаманить.

Изначально, наши автотесты работали порядка 30 минут. Небольшое погружение в сторону параллельного запуска позволило сократить общее время работы до 5 минут, но и на этом мы не остановились. Для достижения текущего эталонного результата в 40 секунд было сделано:

  • Разбиение всех автотестов на логические функциональные блоки

  • Обеспечение изолированности тестовых данных под каждый функциональный блок автотестов

    • Каждый функциональный блок должен работать с персональными тестовыми данными. По окончанию теста система возвращается в исходное состояние.

    • Иногда возврат системы в исходное состояние невозможен или слишком трудоёмок. В этом случае автотест должен работать на данных, которые не мешают работе остальной системе и не блокируют следующий запуск автотеста или параллельную работу автотестов. Например, в уникальные ключи тестовых объектов можно зашивать код автотеста и текущую дату и время.

  • Запуск каждого функционального блока в отдельном потоке

  • Формирование сводной отчётности по полному запуску автотестов

Code Coverage

Я всегда с большой улыбкой относился к метрикам покрытия кода, потому что они, конечно, что-то говорят про вашу систему и автотесты, но вот что именно не очень понятно. При этом идеал в 100%-ное покрытие практически недостижим. А даже если и достижим, то никак не гарантирует, что в системе ошибок нет.

А при тестировании серверной части всё становится ещё более непонятно. Ведь работа системы зависит от данных в таблицах. Есть sql-запросы, которые в принципе не поддаются анализу по покрытию. И разве хоть какая-то метрика может дать адекватную оценку состоянию автотестов?

Но так как вопросы про покрытие задаются слишком часто, пришлось внедрять в систему автоматического тестирования code coverage, благо что Oracle, начиная с версии 12.2, подобный функционал предоставляет.

Это оказалось совсем несложным:

  • перед запуском автотестов вызвать: dbms_plsql_code_coverage.start_coverage

  • выключить функционал по окончанию всех работ: dbms_plsql_code_coverage.stop_coverage

  • написать запрос, который считает покрытие

А мы, получив приятную цифру в 50% покрытие, пошли заниматься более интересными вещами.

Автоматическая генерация кода

Наращивание количества автотестов это простая и понятная задача. Были бы ресурсы, а автотесты всегда появятся. Но, конечно же, хочется сократить издержки на выпуск автотестов. А самый быстрый способ написания кода не писать код совсем!

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

Автоматически сгенерённый код должен содержать:

  1. Инициализацию всех входных и выходных переменных простых типов

  2. Инициализацию всех входных и выходных коллекций

  3. Процедуры для сравнения двух коллекций одного типа

  4. Вызов тестируемого метода

  5. Базовые проверки выходных значений

Хотелось бы конечно, чтобы автотесты начали разрабатываться полностью сами, но с чего-то начинать надо? Реализовав описанное решение, мы стали экономить лишние 10-15 минут при создании каждого автотеста. Дополнительно, автоматическая генерация кода оказалась очень полезной в процессе адаптации новых сотрудников на проекте.

utPLSQL v3

В качестве базиса системы автоматизированного тестирования используется utPLSQL v2, в то время как уже очень давно вышла 3-я версия фреймворка и именно она продолжает активно развиваться. Стоит отметить, что utPLSQL v3 - это фундаментальная переработка старого решения с реализацией нового и классного функционала.

Так почему же у нас в проекте используется более старая версия фреймворка? К сожалению, utPLSQL v 3 не поддерживает несколько важных для нас фич. Что-то разработчикам кажется концептуально неправильным, до чего-то не доходят руки. Все проблемы решаемы, благо что код библиотеки так и остался открытым и может быть самостоятельно изменён. Соответствующая задача в техническом долге заведена, но она не является наиболее приоритетной в нашей дорожной карте развития автотестов.

Заключение

На проекте лояльности Спортмастера уже несколько лет успешно работает система автоматизированного тестирования на PL/SQL. Основные показатели системы и некоторые технические решения освещены в данной статье. Но мы не останавливаемся в развитии и помимо планового расширения покрытия постоянно находим новые вызовы.

Было бы очень интересно узнать, с какими проблемами вы сталкивались при реализации автотестирования и какие решения находите.

Всем добра!

Подробнее..

Перевод Иммутабельность в Java

15.04.2021 20:09:13 | Автор: admin

Привет, Хабр. В преддверии скорого старта курса Подготовка к сертификации Oracle Java Programmer (OCAJP) подготовили для вас традиционный перевод материала.

Приглашаем также всех желающих поучаствовать в открытом демо-уроке Конструкторы и блоки инициализации. На этом бесплатном вебинаре мы:
- Разберём конструктор на запчасти
- Определим финалистов (финальные переменные)
- Наведём порядок (инициализации)


Иммутабельный (неизменяемый, immutable) класс это класс, который после инициализации не может изменить свое состояние. То есть если в коде есть ссылка на экземпляр иммутабельного класса, то любые изменения в нем приводят к созданию нового экземпляра.

Чтобы класс был иммутабельным, он должен соответствовать следующим требованиям:

  • Должен быть объявлен как final, чтобы от него нельзя было наследоваться. Иначе дочерние классы могут нарушить иммутабельность.

  • Все поля класса должны быть приватными в соответствии с принципами инкапсуляции.

  • Для корректного создания экземпляра в нем должны быть параметризованные конструкторы, через которые осуществляется первоначальная инициализация полей класса.

  • Для исключения возможности изменения состояния после инстанцирования, в классе не должно быть сеттеров.

  • Для полей-коллекций необходимо делать глубокие копии, чтобы гарантировать их неизменность.

Иммутабельность в действии

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

import java.util.Map;public final class MutableClass {  private String field;  private Map<String, String> fieldMap;public MutableClass(String field, Map<String, String> fieldMap) {  this.field = field;  this.fieldMap = fieldMap;}public String getField() {  return field;}public Map<String, String> getFieldMap() {  return fieldMap;}}

Теперь посмотрим на него в действии.

import java.util.HashMap;import java.util.Map;public class App {public static void main(String[] args) {  Map<String, String> map = new HashMap<>();  map.put("key", "value");      // Инициализация нашего "иммутабельного" класса  MutableClass mutable = new MutableClass("this is not immutable", map);  // Можно легко добавлять элементы в map == изменение состояния  mutable.getFieldMap().put("unwanted key", "another value");  mutable.getFieldMap().keySet().forEach(e ->  System.out.println(e));}}// Вывод в консолиunwanted keykey

Очевидно, что мы хотим запретить добавление элементов в коллекцию, поскольку это изменение состояния объекта, то есть отсутствие иммутабельности.

import java.util.HashMap;import java.util.Map;public class AlmostMutableClass {  private String field;  private Map<String, String> fieldMap;public AlmostMutableClass(String field, Map<String, String> fieldMap) {  this.field = field;  this.fieldMap = fieldMap;}public String getField() {  return field;}public Map<String, String> getFieldMap() {  Map<String, String> deepCopy = new HashMap<String, String>();  for(String key : fieldMap.keySet()) {    deepCopy.put(key, fieldMap.get(key));  }  return deepCopy;}}

Здесь мы изменили метод getFieldMap, который теперь возвращает глубокую копию коллекции, ссылка на которую есть в AlmostMutableClass. Получается, что если мы получим Map, вызвав метод getFieldMap, и добавим к нему элемент, то на map из нашего класса это никак не повлияет. Изменится только map, которую мы получили.

Однако если у нас остается доступ к исходной map, которая была передана в качестве параметра конструктору, то все не так уж и хорошо. Мы можем изменить ее, тем самым изменив состояние объекта.

import java.util.HashMap;import java.util.Map;public class App {public static void main(String[] args) {  Map<String, String> map = new HashMap<>();  map.put("good key", "value");      // Инициализация нашего "иммутабельного" класса  AlmostMutableClass almostMutable = new AlmostMutableClass("this is not immutable", map);    // Мы не можем изменять состояние объекта   // через добавление элементов в полученную map  System.out.println("Result after modifying the map after we get it from the object");  almostMutable.getFieldMap().put("bad key", "another value");  almostMutable.getFieldMap().keySet().forEach(e -> System.out.println(e));    System.out.println("Result of the object's map after modifying the initial map");  map.put("bad key", "another value");  almostMutable.getFieldMap().keySet().forEach(e -> System.out.println(e));      }}// Вывод в консолиResult after modifying the map after we get it from the objectgood keyResult of the object's map after modifying the initial mapgood keybad key

Мы забыли, что в конструкторе нужно сделать то же самое, что и в методе getFieldMap. В итоге конструктор должен выглядеть так:

public AlmostMutableClass(String field, Map<String, String> fieldMap) {  this.field = field;        Map<String, String> deepCopy = new HashMap<String, String>();  for(String key : fieldMap.keySet()) {    deepCopy.put(key, fieldMap.get(key));  }  this.fieldMap = deepCopy;}// Вывод в консолиResult after modifying the map after we get it from the objectgood keyResult of the object's map after modifying the initial mapgood key

Хотя использование иммутабельных объектов дает преимущества, но их использование не всегда оправдано. Обычно нам нужно как создавать объекты, так и модифицировать их для отражения изменений, происходящих в системе.

То есть нам нужно изменять данные, и нелогично создавать новые объекты при каждом изменении, так как это увеличивает используемую память, а мы хотим разрабатывать эффективные приложения и оптимально использовать ресурсы системы.

Иммутабельность строк в Java

Класс String, представляющий набор символов, вероятно, самый популярный класс в Java. Его назначение упростить работу со строками, предоставляя различные методы для их обработки.

Например, в классе String есть методы для получения символов, выделения подстрок, поиска, замены и многие другие. Как и другие классы-обертки в Java (Integer, Boolean и т.д.), класс String является иммутабельным.

Иммутабельность строк дает следующие преимущества:

  • Строки потокобезопасны.

  • Для строк можно использовать специальную область памяти, называемую "пул строк". Благодаря которой две разные переменные типа String с одинаковым значением будут указывать на одну и ту же область памяти.

  • Строки отличный кандидат для ключей в коллекциях, поскольку они не могут быть изменены по ошибке.

  • Класс String кэширует хэш-код, что улучшает производительность хеш-коллекций, использующих String.

  • Чувствительные данные, такие как имена пользователей и пароли, нельзя изменить по ошибке во время выполнения, даже при передаче ссылок на них между разными методами.


Подробнее о курсе Подготовка к сертификации Oracle Java Programmer (OCAJP).

Смотреть вебинар Конструкторы и блоки инициализации.

Подробнее..
Категории: Java , Oracle , Блог компании otus , String , Ocajp

Recovery mode Обработка финансовой информации в продуктах Oracle OFSS предусматривает постепенный отказ от использования JVM в Oracle

09.04.2021 16:11:40 | Автор: admin

Из-за множества вопросов по сертификации продуктов Oracle OFSS (Oracle Financial Services Software) наша техническая поддержка сообщает, что в ноте OFSS Certified Configurations (Doc ID 2636856.1) сделана попытка сертифицировать набор релизов OFSS, находящихся в Premier Support новых версий по технологическим компонентам, таким, например, как база данных, версия компонент промежуточного слоя, операционных систем, браузеров и других компонент.

Практически, все сводится к тому, что вендор выставляет рекомендуемые конфигурации продуктов к использованию FMW 12.2.1.4 и DB 19.6. Давайте рассмотрим, на какие продукты OFSS и как это повлияет.

Как известно, в стек продуктов OFSS включены продукты:

  • Oracle FLEXCUBE Universal Banking;

  • Oracle Banking Payments;

  • Oracle Banking Corporate Lending;

  • Oracle Banking APIs;

  • Oracle Banking Digital Experience;

  • Oracle FLEXCUBE Enterprise Limits and Collateral Management;

  • Oracle Financial Services Lending and Leasing;

  • Oracle FLEXCUBE Core Banking;

  • Oracle FLEXCUBE Investor Servicing;

  • Oracle Banking Liquidity Management;

  • Oracle Banking Virtual Account Management;

  • Oracle Banking Corporate Lending Process Management;

  • Oracle Banking Credit Facilities Process Management.

Напомним, что продукты Oracle Financial Services Software в нашей стране есть в банковском секторе персонального и корпоративного уровня, страховых компаниях. Есть внедрения решений по управлению рисками и проверке законодательных требований к финансовым операциям, проверки работоспособности приложений для бухгалтерского, управленческого учета, управления бизнес-процессами и человеческими ресурсами, инструментами управления закупочной деятельностью.

Памятуя о том, что тема сертификации всех продуктов и технологий практически неисчерпаема даже для одного релиза OFSS, в год 25-летия языка Java мы, кроме сугубо технической информации, обнаружили одно очень важное замечание в самом конце этой ноты.

Чтобы упростить понимание ситуации до выпуска ноты, заметим, что нынешняя архитектура базы с настраиваемыми технологиями поддержки языка Java, других языков высокого уровня, собственной JVM с настраиваемым объемом Java Pool Size, загрузчиком классов приложений, обработчиками XSD, XML, JSON, Xpath и ряда других вспомогательных технологий обеспечивает технологический стек для любого приложения FMW (Oracle Fusion Middleware), работающего внутри базы данных. C версии сервера старше 12, Oracle полностью соблюдает стандарты обработки XML.

Если же вы до сих пор работаете на 11.2.0.4, то мы напоминаем, что по документу Release Schedule of Current Database Releases (Doc ID 742060.1) поддержка версии закончилась с января 2021 года, при этом объявлен дополнительный приобретаемый уровень поддержки Market Driven Support (MDS), оказываемый только Oracle. По нашему мнению, работа на современных серверах с количеством SGA не более 70GB в начале третьего десятилетия 21 века выглядит немного устаревшей.

Продолжим обсуждение ноты Doc ID 2636856.1. При последовательном переводе ноты содержащийся в ней комментарий означает, что продукты OFSS версий до v14.0 задействовали возможности Java-машины, встроенной в СУБД для поддержки специфической функциональности. С момента выпуска ноты Oracle больше не рекомендуется использовать Java внутри базы данных (для задач OFSS, прим. автора). Сертификация последнего технологического стека выполнена на основе того, что поддержка ограничена техническими возможностями Java, работающей внутри сервера Oracle.

На текущий момент, Java-машина настолько часто используется самими механизмами базы, что есть необходимость напомнить читателям, что, хотя ее переустановка обычно сложностей не вызывает, но апгрейд базы до новых версий невозможен при малейших проблемах в ее функционировании.

К сожалению, требуется указать, что ряд явных багов Java-машины в версиях Oracle Server 18с и 19с имеют непубличный статус, хотя могут существенно повлиять на обработку XML, XSD и Unicode символов. Например, Bug 24008722, отраженный в документе Doc ID 2450530.1, может не позволить работать с тэгами вида <xs:pattern Value="(doc|docx)"/> в некоторых XSD схемах, он же может стать причиной невозможности обработки символов вне US7ASCII (Bug 29715647).

Следовательно, если у вас есть код, выполняющий указанные операции на Oracle Server 18с и 19с, есть смысл еще раз проверить его работоспособность. Для 12-х версий можно скачать патчи.

Данную заметку можно рассматривать как краткий ответ на вопрос - Так можно ли использовать Java-машину Aurora внутри сервера Oracle и для каких целей.

Подробнее..
Категории: Oracle , Jvm , Ofss , Mig , Realese , Oracle fusion middleware

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru