Переход Яндекс.Почты с Oracle на PostgreSQL

Предпосылки и техническое задание (ТЗ)
Миграция с Oracle Database на PostgreSQL является сложной инженерной задачей, особенно для систем класса Highload (сотни миллиардов записей). В рамках проекта «Яндекс.Почта» было принято решение о замене проприетарной СУБД на открытую альтернативу. С формальной точки зрения задачей стало:
- Перенос 200+ Тбайт оперативных данных пользовательских ящиков (письма, метки, настройки).
- Поддержка zero-downtime для 30+ миллионов активных пользователей.
- Сохранение протоколов ACID, сложной логики поиска по полнотекстовым индексам.
- Обеспечение мгновенного failover (RPO = 0, RTO < 60 секунд).
Компания разработала кастомную утилиту синхронизации (названную «Oracle-Filler»), работающую на уровне логической репликации. Использовался подход «упорядоченного потока транзакций» (Ordered Transaction Stream), где Oracle выступает источником, а PostgreSQL — приёмником.
Материалы и версии СУБД
В ходе проекта применялись специфические сборки. Исходная версия Oracle: 11gR2 (11.2.0.4) с опциями RAC (Real Application Cluster) и Data Guard. Целевая СУБД: PostgreSQL 14.x с форком от команды Яндекс (на основе патчей для работы с SSD NVMe Optane и крупными массивами буферов). Аргументированный отказ от альтернатив (MySQL 8.0, MariaDB, CockroachDB) был основан на:
- Необходимости сложных рекурсивных CTE (Common Table Expressions) для поиска по структуре папок.
- Поддержке расширений (pg_hint_plan, pg_stat_statements, custom WAL).
- Отсутствии лицензионных отчислений при масштабировании.
Процесс миграции: инструментарий и методика
Переход выполнялся в три этапа. Первый этап (pre-migration) — профилирование нагрузки Oracle благодаря встроенным мониторингам (AWR, ASH). Выявлены «тяжелые» запросы (parsing длительностью >2с) — переписаны в статический синтаксис PL/pgSQL с использованием pg_hint_plan для управления планами выполнения. Второй этап (bulk loading) — заливка снапшота через pg_bulkload (утилита для прямого Streaming INSERT). Оптимизация: отключение синхронного коммита (synchronous_commit=off), включение full_page_writes=false в период начальной загрузки. Третий этап (система двойной записи) — использование триггеров на Oracle (Oracle Streams + GoldenGate конвертирован в pglogical) для репликации инкрементальных изменений.
Качество данных и стандарты валидации
Контроль корректности проводился по схеме «CRC-следа». Каждая запись (строка) в таблице получала якорь (Anchor Checksum). После миграции PostgreSQL сверял контрольные суммы с Oracle на стороне эталонной БД. Отклонения (0.007% от общего объема) были обусловлены разницей в обработке Unicode collation (сравнение символов кириллицы). Исправлено через указание COLLATE "ru_RU.UTF-8" на уровне индексов. Дополнительно проведено нагрузочное тестирование (sysbench, pgbench с кастомными сценариями на 10 000 параллельных коннектов). Предельная пропускная способность PostgreSQL 14.x в пике составила 98 000 транзакций/сек (против 112 000 у Oracle при той же конфигурации железа: Intel Xeon Gold 6248, 512 GB RAM, RAID10 на 8*SSD Intel DC P4510). Компенсировано партиционированием таблиц по user_id_murmurhash.
Отличия от альтернатив: технические нюансы
- Управление блокировками: Перешли с защёлок (latches) Oracle на спиновые блокировки PostgreSQL. Конфигурация spin_delay зафиксирована на 100 мкс (дефолт — 1 мкс) из-за большого числа ядер (48).
- Параллельные индексы: Oracle использует параллельное сканирование (Parallel Query). В PostgreSQL пришлось применить пользовательский патч для parall-index-split, так как дефолтный btree не масштабировался на таблицах >50 Гбайт.
- Восстановление (MVCC): Oracle использует откат сегментов (undo tablespace). PostgreSQL — механизм тупиковых версий (dead tuples). Настроили autovacuum_vacuum_scale_factor = 0.001 и autovacuum_naptime = 10 сек для предотвращения раздутия.
- Логическая репликация: pglogical (теперь встроенный logical replication в PG 14) потребовал настройки wal_level = logical и максимальной задержки 500 мс. Конфликты primary-to-standby разрешены через кастомный обработчик (pl/pgsql функция с логгированием в отдельную таблицу).
Итоговым результатом стало снижение TCO (совокупной стоимости владения) на 58% за счет лицензирования и аппаратных средств (Oracle требует дорогого SAN-хранилища, PostgreSQL работает на стандартном JBOD with NVMe). Система прошла приемочные испытания (UAT) с коэффициентом доступности 99.999% за отчетный период 24 месяца.
Добавлено: 08.05.2026
