
В мире корпоративных финансовых технологий импортозамещение стало не просто трендом, а жизненной необходимостью. Особенно остро этот вопрос встает перед владельцами крупных систем, построенных на проприетарных решениях.
Привет! Мы – Дмитрий Харлан и Антон Ляшедько, представители команды развития системы бизнес-планирования ВТБ.
Наша история о том, как мигрировать монолитную систему с более чем 300 отчетами и объемом данных свыше 100 гигабайт за минимальное время простоя. Интегратором решения выступила «Балтийская технологическая компания».
Исходная ситуация: когда размер имеет значение
Представьте себе типичную для финтех-энтерпрайза систему, построенную на классическом стеке Java + Oracle Database. Система содержит в своем составе порядка 300 различных отчетов и оперирует массивом данных объемом свыше 100 гигабайт. За годы эксплуатации она обросла множеством бизнес-логики, реализованной как в Java-коде, так и непосредственно в базе данных через хранимые процедуры, функции и представления.
Техническое отступление: архитектурные паттерны финансовых систем.
Финансовые системы часто строятся по принципу "толстой" базы данных, где значительная часть бизнес-логики реализована средствами СУБД. Это связано с требованиями к производительности агрегационных операций и необходимостью обеспечения ACID-транзакций для финансовых расчетов. Oracle Database традиционно предоставляет богатый инструментарий для такой архитектуры: PL/SQL пакеты, материализованные представления с автоматическим обновлением, партиционирование таблиц по времени и другие энтерпрайз-функции.
В рамках стратегии импортозамещения перед командой встала задача перехода на открытое решение, максимально совместимое с существующей функциональностью Oracle. Выбор пал на PostgreSQL – одну из наиболее зрелых и функционально богатых open-source СУБД, которая в последние годы активно завоевывает позиции в энтерпрайз-сегменте.
Почему PostgreSQL?
PostgreSQL заслуженно считается одной из самых продвинутых открытых реляционных СУБД. Ее архитектура, основанная на принципах ACID-совместимости и многоверсионности (MVCC), обеспечивает высокий уровень надежности и производительности, необходимый для финансовых приложений. Система поддерживает сложные типы данных, включая JSON, массивы, геометрические типы, что делает ее универсальным решением для различных задач.
Техническое отступление: MVCC и его влияние на производительность.
Многоверсионная система управления параллелизмом (MVCC) в PostgreSQL работает принципиально иначе, чем механизмы блокировок в Oracle. Каждая транзакция видит снимок данных на момент своего начала, что исключает блокировки чтения. Однако это создает дополнительную нагрузку на подсистему очистки устаревших версий строк (VACUUM). При миграции критически важно правильно настроить параметры автовакуума, особенно для таблиц с высокой частотой обновлений.
Особенно важным для миграции с Oracle стал богатый набор SQL-функций PostgreSQL, включая оконные функции, рекурсивные запросы (CTE), а также возможность создания пользовательских функций на различных языках программирования.
Ограничения: когда время – критический фактор
Ключевым ограничением проекта стало требование уложить финальные работы по миграции в техническое окно продолжительностью около суток. Это означало, что традиционные подходы с длительным параллельным тестированием и постепенным переводом пользователей были неприменимы.
Техническое отступление: стратегии миграции данных
В теории миграции баз данных существует несколько основных подходов: "Big Bang" (единовременный перенос), "Trickle" (постепенная синхронизация), "Phased" (поэтапный перенос компонентов). Каждый имеет свои преимущества и недостатки. Big Bang минимизирует период несогласованности данных, но максимизирует риски. Trickle снижает риски, но требует сложной логики синхронизации. В нашем случае бизнес-требования однозначно указывали на Big Bang подход.
При первичном анализе системы выявились серьезные вызовы:
- Архитектурная неоднородность. За годы развития информационная система сменила несколько команд разработчиков, что привело к отсутствию единых паттернов реализации бизнес-логики. Часть функциональности была реализована в Java-коде, часть – в хранимых процедурах Oracle, часть – в представлениях базы данных.
- Vendor-specific функциональность. В коде активно использовались специфичные для Oracle возможности, такие как глобальные вре́менные таблицы (Global Temporary Tables), пакеты (Packages), специальные функции для работы с датами и строками.
Техническое отступление: глобальные временные таблицы Oracle
Global Temporary Tables в Oracle – это особый тип таблиц, структура которых видна всем сессиям, но данные изолированы по сессиям или транзакциям. Это мощный инструмент для промежуточных вычислений в сложных аналитических запросах. PostgreSQL не имеет прямого аналога, но похожую функциональность можно реализовать через обычные вре́менные таблицы, unlogged таблицы или использование схем, специфичных для сессий.
- Объем и сложность данных. Более 100 гигабайт данных с ��ложными взаимосвязями и зависимостями между таблицами делали невозможным использование простых инструментов экспорта-импорта.
Стратегическое решение: миграция "as is"
Учитывая жесткие временные рамки, было принято решение о миграции системы в режиме "as is" – без кардинального рефакторинга архитектуры, исправляя только вопросы совместимости между СУБД и адаптируя логику, реализованную средствами базы данных.
Работы были разделены на два крупных этапа:
1. Этап рефакторинга: адаптация всего кода для работы с PostgreSQL без переноса продакшн-данных;
2. Этап финального переноса: миграция данных и переключение на новую систему.
Выбор инструментария: Liquibase как основа
В качестве основного инструмента управления миграциями был выбран Liquibase – одна из наиболее зрелых систем управления версиями схемы базы данных в Java-экосистеме.
Техническое отступление: альтернативы Liquibase
На рынке существует несколько альтернатив Liquibase: Flyway (более простой, но менее функциональный), Alembic (для Python-экосистемы), Rails Migrations (для Ruby), собственные решения вендоров СУБД. Выбор Liquibase был обусловлен его зрелостью, богатой функциональностью для работы с данными (не только схемой), поддержкой различных форматов описания миграций и хорошей интеграцией с Java-стеком решения.
Преимущества Liquibase в контексте проекта:
а) Интеграция с DevOps-процессами. Liquibase органично встраивается в современные пайплайны непрерывной интеграции и доставки, поддерживая различные форматы описания миграций (XML, YAML, JSON, SQL) и интегрируясь с популярными системами сборки.
б) Командная работа. Файлы миграций могут храниться в том же Git-репозитории, что и основной код проекта, что обеспечивает версионность и синхронизацию изменений схемы с изменениями в приложении.
в) Стандартизация процессов. Единый подход к описанию миграций унифицирует работу команды и снижает вероятность ошибок.
г) Откат изменений. Возможность автоматической генерации rollback-скриптов критически важна для продакшн-систем.
Решение проблем совместимости
Одной из ключевых задач стала адаптация Oracle-специфичного функционала для PostgreSQL. Например, как упомянуто ранее, широко использовавшиеся в проекте глобальные вре́менные таблицы Oracle не имеют прямого аналога в PostgreSQL.
Техническое отступление: экосистема расширений PostgreSQL
PostgreSQL имеет уникальную архитектуру расширений, позволяющую добавлять новую функциональность без изменения ядра СУБД. Система расширений поддерживает добавление новых типов данных, операторов, функций, методов индексирования и даже языков программирования. Популярные расширения включают PostGIS для геоданных, TimescaleDB для временны́х рядов, pg_stat_statements для мониторинга производительности, orafce для совместимости с Oracle.
Для решения подобных задач был подобран и протестирован набор расширений PostgreSQL, реализующих необходимую функциональность. Экосистема расширений PostgreSQL чрезвычайно богата – от простых функций для совместимости с другими СУБД до сложных решений для работы с временными рядами, полнотекстовым поиском и аналитикой.
Весь процесс рефакторинга велся на минимальном объеме демонстрационных данных, что позволяло быстро итерироваться и тестировать изменения. Параллельно команда занималась подбором и тестированием оптимального способа финального переноса продакшн-данных.
Техническое отступление: стратегии тестирования миграций
При миграции критически важных систем применяется многоуровневое тестирование: модульное тестирование отдельных компонентов на совместимость, интеграционное тестирование взаимодействия компонентов, нагрузочное тестирование производительности на реальных объемах данных, и наконец, полное end-to-end тестирование всего процесса миграции. Каждый уровень выявляет свой класс проблем, и пропуск любого из них может привести к критическим ошибкам в продакшене.
Масштабная работа по тестированию функциональности
Особо следует отметить колоссальную работу, проделанную командой тестирования в рамках проекта миграции. Перед ними стояла задача, масштаб которой трудно переоценить: протестировать корректность работы более 300 различных отчетов, каждый из которых имел множественные параметры и конфигурации.
Команда QA разработала комплексную методологию тестирования, включавшую сравнение результатов выполнения отчетов на Oracle и PostgreSQL. Для каждого отчета создавались наборы тестовых данных, покрывающие различные граничные случаи и комбинации параметров. Особое внимание уделялось отчетам с агрегационными функциями, сложными соединениями таблиц и специфичными для Oracle конструкциями.
Техническое отступление: тестирование аналитической отчетности
Тестирование аналитических отчетов требует особого подхода из-за их специфики: большие объемы данных, сложная бизнес-логика, множественные параметры. Эффективные стратегии включают создание эталонных наборов данных, автоматизированное сравнение результатов (с учетом допустимых погрешностей для числовых данных), параметризованные тесты для покрытия различных комбинаций входных параметров и тестирование производительности для выявления деградации после миграции.
Процесс тестирования выявил множество тонких различий в поведении Oracle и PostgreSQL: от особенностей округления чисел с плавающей точкой до различий в обработке NULL-значений в агрегационных функциях. Каждое расхождение тщательно анализировалось, и принималось решение о необходимости адаптации кода или корректировки ожидаемых результатов.
Командой тестирования была создана детальная матрица покрытия, отслеживающая статус тестирования каждого отчета с различными наборами параметров. Это позволило обеспечить полноту тестового покрытия и избежать пропуска критически важных сценариев использования.
Архитектура финального переноса
Финальная схема миграции представляла собой сложный многоэтапный процесс, основанный на возможностях Liquibase по работе с CSV-файлами:
а) Этап экспорта. С помощью Liquibase данные выгружались из таблиц Oracle в CSV-формат. Этот подход обеспечивал структурированность процесса и возможность его повторения.
б) Подготовка шаблона. В Liquibase для PostgreSQL добавлялись changesets для загрузки данных в таблицы, но с пустыми CSV-файлами. Это состояние фиксировалось в Git как точка начала работы на PostgreSQL.
в) Подмена данных. Перед загрузкой на продакшн PostgreSQL пустые CSV подменялись на файлы с реальными данными, выгруженными из Oracle.
г) Выполнение миграции. Liquibase выполнялся на "чистом" PostgreSQL, создавая схему и загружая данные.
д) Очистка. После успешной миграции пустые CSV возвращались через Git reset, а хеши выполненных changesets в Liquibase перегенерировались для соответствия пустым файлам.
Техническое отступление: форматы обмена данными
Выбор CSV как промежуточного формата был обусловлен несколькими факторами: универсальность (поддерживается всеми СУБД), компактность (меньше накладных расходов по сравнению с XML/JSON), скорость обработки (оптимизированн��е парсеры), человекочитаемость (возможность ручной проверки). Альтернативами могли быть бинарные форматы (Parquet, Avro), но они требуют дополнительных инструментов и менее универсальны.
Такой подход позволял избежать хранения больших объемов данных в системе контроля версий, сохраняя при этом воспроизводимость процесса миграции.
Технические вызовы и их решение
Проблема масштабирования Liquibase
Основной технической проблемой стали архитектурные особенности Liquibase при работе с большими объемами данных. Система изначально проектировалась для управления схемой базы данных, а не для массового переноса данных.
Техническое отступление: управление памятью в JVM
Java Virtual Machine использует несколько областей памяти: heap (куча) для объектов, stack (стек) для локальных переменных и вызовов методов, method area для метаданных классов. При обработке больших файлов критичен размер heap, который ограничен параметрами -Xmx и -Xms. Garbage Collector также влияет на производительность: G1GC лучше подходит для больших heap, а Parallel GC – для пропускной способности. Настройка этих параметров критична для стабильной работы с большими объемами данных.
Экспериментальным путем было установлено, что для обработки CSV-файла размером около 500пятисот мегабайт Java heap пришлось увеличить до примерно 120ста двадцати гигабайт. При меньших значениях Liquibase завершался с ошибкой "OutOfMemoryError: Java heap space".
Автоматизация разделения данных
Эта особенность Liquibase потребовала дополнительной работы по разделению больших таблиц на части и соответствующему изменению changesets. Процесс был успешно автоматизирован с помощью Python-скриптов, которые:
- Анализировали размер CSV-файлов;
- Автоматически разделяли файлы, превышающие пороговые значения;
- Генерировали соответствующие changesets для каждой части;
- Обеспечивали корректную последовательность загрузки с учетом внешних ключей.
Техническое отступление: обработка внешних ключей при миграции
Внешние ключи создают граф зависимостей между таблицами, который необходимо учитывать при определении порядка загрузки данных. Существует несколько стратегий: топологическая сортировка таблиц по зависимостям, временное отключение проверки внешних ключей, использование отложенных ограничений (deferred constraints). В PostgreSQL можно использовать DEFERRABLE INITIALLY DEFERRED для откладывания проверки ограничений до конца транзакции, что упрощает загрузку взаимосвязанных данных.
Результаты и оптимизация
Финальный переезд прошел без происшествий, но этому предшествовала серьезная подготовительная работа. Процесс миграции репетировался около 30 раз, что позволило выявить и устранить все узкие места.
За время подготовки удалось сократить время миграции с первоначальных пяти дней до финальных 18 часов – результат, который укладывался в требуемое техническое окно.
Техническое отступление: профилирование и оптимизация миграций
Оптимизация времени миграции включает несколько аспектов: настройка параметров СУБД для массовой загрузки (увеличение shared_buffers, отключение fsync, настройка checkpoint_segments в PostgreSQL), оптимизация дискового I/O (использование SSD, RAID-конфигурации, файловых систем с журналированием), параллелизация операций загрузки, оптимизация сетевого взаимодействия. Каждый из этих факторов может дать значительный прирост производительности.
Ключевые факторы успеха:
Многократное тестирование. Каждая репетиция выявляла новые проблемы и позволяла оптимизировать процесс.
Автоматизация. Все критичные операции были автоматизированы, что исключило человеческий фактор в процессе миграции.
Мониторинг. Детальное логирование и мониторинг каждого этапа позволяли быстро локализовать проблемы.
Всесторонняя проверка функциональности. Масштабная работа команды тестирования по верификации каждого отчета и его параметров обеспечила уверенность в корректности миграции.
Преимущества выбранного подхода
Разработанное решение оказалось единственно возможным в данных условиях по нескольким причинам:
Минимизация рисков. Подход "as is" исключал внесение архитектурных изменений, которые могли бы привести к непредсказуемым последствиям.
Управляемость процесса. Использование Liquibase обеспечивало полный контроль над каждым этапом миграции с возможностью отката.
Воспроизводимость. Весь процесс был полностью автоматизирован и мог быть повторен в случае необходимости.
Соответствие временны́м ограничениям. Оптимизированный процесс укладывался в жесткие временны́е рамки.
Опыт этого проекта показывает, что даже самые сложные миграции корпоративных систем могут быть выполнены в сжатые сроки при правильном планировании, выборе инструментов и тщательной подготовке. Ключевым фактором успеха становится не избегание сложности, а ее структурирование и управление рисками на каждом этапе.
