Блеск и нищета технологии Edition-based redefinition в Oracle Database: часть 2. Нищета
Блеск и нищета технологии Edition-based redefinition в Oracle Database: часть 2. Нищета
«Внедрять или не внедрять?» - вот в чем вопрос
В предыдущей части статьи мы познакомились с технологией Edition-based redefinition (EBR) и поговорили о том, для чего она используется и какими плюсами обладает. Если вы еще не знакомы с EBR, то читайте первую часть статьи.

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

С чего все началось?
В 2020 году руководство банка предложило внедрить EBR для нашей системы с целью уменьшения общегодового Downtime и получения возможности быстро и безболезненно исправлять критичные ошибки.
Перед внедрением мы провели исследование, чтобы узнать, насколько уменьшится общегодовое время простоя системы. Вычисленное уменьшение Downtime выглядело прилично, внедрению EBR дали зеленый свет.
Нам помогали коллеги, уже работавшие с этой технологией. Но система, которую они использовали, была меньше по объему данных и хранимого кода, поэтому перевести нашу систему на EBR стало вызовом для обеих команд. Весь процесс занял у нас полгода, как это было - сейчас расскажу.
Отмечу, что EBR до сих пор является достаточно сырой, а в 2020 году с нее практически капало, так что мы заводили задачи на Oracle при очень некорректной работе технологии. Насколько я знаю, у EBR до сих пор существуют ограничения:
  • не более 2000 редакций;
  • зависимость редакций друг от друга линейная.
Слева ожидания от ветвления редакций EBR, справа реальность
Начало работы. Первые трудности
Для работы с EBR мы установили несколько патчей от Oracle. Патч с исправлением некоторых ошибок нам пришлось ждать очень долго, из-за этого часть задач мы не успели сделать в срок.

Также, в процессе внедрения EBR, мы поменяли джобы установки патчей в Jenkins (Если вам интересно как работают процессы CI/CD в нашем банковском проекте - пишите в комментарии, я расскажу отдельно), чтобы установка автоматически происходила с созданием редакций EBR.

Самой главной нашей задачей было подготовить саму базу для внедрения, так как для корректной работы EBR существуют определенные требования к объектам и к процессу разработки:
  • запрещено изменять объекты в родительских редакциях, для которых нет актуализированных версий в дочерних. В этом случае необходимо вначале актуализировать объект в дочерней редакции, которая является непосредственным потомком текущей;
  • перед тем как выдать грант на объект, его нужно актуализировать в текущей редакции. Если пакет нельзя перекомпилировать (в случае, если выполняем выдачу грантов вручную на горячей базе), то для выдачи гранта необходимо определить редакцию, в которой объект был последний раз актуализирован, после чего дать ему грант в этой редакции. Для этого мы создали специальную функцию;
  • для компиляции большого числа невалидов нам пришлось написать функцию валидации объектов, которая работает только с конкретной редакцией. Старую функцию, которая делала это в параллели, мы перестали использовать, так как она компилировала объекты во всех редакциях. Во время разработки на dev-среде необходимо запускать функцию валидации, если пакет используют связанные объекты;
  • при непосредственной разработке на базе необходимо запускать процедуру валидации объектов (см. выше) после актуализации пакетов, на которые могут ссылаться другие пакеты, иначе это может привести к их развалу через некоторое время;
  • неверсионируемые объекты не могут ссылаться на версионируемые, поэтому функциональные индексы для таблиц необходимо создавать, используя функции в специальных noneditionable пакетах;
  • editionable abstract data type (ADT) не могут быть evolved (таким образом, типы в editioned схемах необходимо редактировать через drop/create);
  • Все новые объекты PL/SQL при разработке обязательно должны создаваться как Editionable.
Также, по-хорошему, при использовании EBR, для каждой таблицы должно создаваться Editionable View, которое будет использоваться в объектах PL/SQL, так как таблица – это всегда Noneditionable объект, и, если этого не сделать, то в некоторых редакциях объекты будут ссылаться на несуществующие столбцы.

Расскажу на довольно распространенном в сети примере:

Предположим, у нас есть таблица TPERSON, в которой есть поле FULL_NAME, где хранятся ФИО клиентов. Но появилась задача разделить фамилию, имя и отчество на разные столбцы SONAME, NAME и MIDDLE_NAME. Если мы добавим данные столбцы, то пакеты в предыдущих редакциях станут невалидными. Для того, чтобы этого не происходило, необходимо, чтобы пакеты не обращались напрямую к таблице, а обращались к представлению VPERSON. Например, для старых редакций представление будет содержать следующий код:

Create or replace view VPERSON as
Select full_name, birthday, ... from TPERSON;
А для новых редакций:
Create or replace view VPERSON as
Select name, soname, middle_name, birthday, ... from TPERSON;

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

Следующей проблемой стало то, что в нашей системе много кода, и большую его часть написал вендор. И на предложение переделать все таблицы на Editionable view нам выкатили счет, сравнимый с ВВП небольшого города, и срок в пять лет. Такой вариант нас не устроил, поэтому изменения, требующие модификации таблиц, мы продолжаем производить с Downtime, как раньше. Благо, такие изменения производятся нечасто.

В итоге, на EDITIONABLE VIEW в старом коде мы решили не переходить, но некоторые преобразования все же сделать пришлось:
  • мы вынесли все функции, используемые в функциональных индексах, в отдельный noneditionable пакет и перестроили индексы;
  • написали новые правила разработки и обучили разработчиков;
  • позаимствовали и доработали функции выдачи грантов, валидации объектов, проверки редакций и логирования у помогавшей нам с переводом системы команды;
  • определили, какие объекты должны быть noneditionable, а какие нет. Noneditionable, например, были типы, которые отвечают за взаимодействие с другими системами;
  • пересоздали публичные синонимы, такие как editionable. Если этого не сделать, то синоним может инвалидироваться. Попытка его перекомпилить ничего не дает, а если попытаться удалить в редакции, то он обозначится как non-existance, и пересоздать его не получится. Это одна из проблем, возникшая на тестовых контурах, и решить ее получается только удалением из корневой редакции ORA$BASE
Еще одна проблема, с которой мы столкнулись, – у нас есть интеграция с другими системами, которые сохраняют стабильное соединение долго и не переключаются на новые редакции. Их нужно было «насильно» вырубать, что означало необходимость Downtime для них. Пусть это и был Downtime, длящийся секунды, но иногда мы не могли себе позволить и этого. Было решено в дальнейшем избавиться от этого легаси и перенастроить взаимодействие.

Мы продолжили тестировать и исследовать. Сделали множество деплоев, проверяли как это будет работать. Заметили дополнительно следующие моменты:
  • для того, чтобы PL/SQL developer начал открывать пакеты из новой редакции по умолчанию, его необходимо перезапустить. Если этого не делать, то новые окна открываются в старой редакции;
  • объекты могут развалиться, если существуют несоответствия временных меток компиляции связанных объектов. Для обнаружения этих проблем мы сделали специальное представление VTIMESTAMP_MISMATCHES, которое сравнивает timestamp у связанных объектов и выводит их в случае несоответствия. Проблемные объекты, найденные с помощью данного представления, подлежат компиляции (для пакетов необходимо актуализировать и тело, и спецификацию в одной и той же редакции) и последующей валидации с помощью написанной процедуры

Запуск
Спустя 6 месяцев работы мы поняли, что готовы запустить и установить первый патч на продуктив с использованием EBR. И вот оно чудо. Все прошло гладко! Гладко на первый взгляд… Уже на следующий день мы словили ошибку - в какой-то момент пакеты развалились. В дальнейшем мы отловили еще море ошибок, по некоторым писали в службу поддержки Oracle, а некоторые задачки системы обеспечили бессонные ночи всей команде. Список ошибок, их описание и методы решения, которые мы нашли, смотрите в таблице ниже.

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

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

Сейчас мы используем установку с EBR для внеочередных патчей (исправление критичных багов), если не планируется планового Downtime, и если это не слишком маленькое изменение. Например, когда требуется обновить один пакет, затрагивающийся одним отчетом, запускаемым раз в день, то смысла в создании новой редакции не возникает. На тестовые, за исключением стендов регрессионного тестирования, и разработческие стенды мы ничего с EBR не устанавливаем. Точнее, не создаем новые редакции, так как в процессе работы возникали путаницы. К примеру: тестировщик не перезапустил PL/SQL developer, заметил в системе ошибку и решил посмотреть еще и на код, но увидел код из старой редакции. И, соответственно, потратил больше рабочего времени, чтобы разобраться в причине ошибки.

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

Возвращаясь к главному вопросу этой статьи: «Внедрять или не внедрять?», я отвечу так: технология EBR будет вам полезна, если
1) у вас не так много программного кода, и вы сможете переписать взаимодействие со всеми noneditionable объектами;
2) у вас не так часто происходит выход новых версий, так как лимит в 2000 редакций при деплое несколько раз в день можно исчерпать довольно быстро;
3) если вы нечасто используете функциональные индексы;
4) если систему вы пишете полностью сами и не зависите от вендора, который будет запрашивать большие деньги за разработку «по-новому»;
5) и если у вас не так много интеграций с другими системами или, хотя бы, интеграция настроена нормально, так, что системы могут переподключаться без проблем и Downtime

И однозначное «внедрять!»: если у вас нет ни одной строчки кода. Смело внедряйте EBR на новые проекты.

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