ADG Оставить заявку
Блог Регуляторика 5 мин чтения

Аудит СУБД под импортозамещение: хранимые процедуры MS SQL и совместимость с PostgreSQL 9.3

Проводим аудит баз данных госклиента под импортозамещение: оцениваем совместимость T-SQL процедур с PL/pgSQL и строим дорожную карту миграции на PostgreSQL 9.3.

Контекст момента

Программа импортозамещения ПО в госсекторе получает первые официальные ориентиры: замена зарубежных СУБД на отечественные или open-source становится ожидаемым требованием

Весной мы уже смотрели первые сигналы импортозамещения и делали карту зависимостей от зарубежных вендоров. Тогда MS SQL в списке «критических зависимостей» шёл отдельной строкой - большой, дорогой, с кучей хранимой логики внутри. Теперь у нас первый живой проект, где это не теория.

Госклиент попросил оценить: можно ли мигрировать на PostgreSQL и что это вообще означает в рублях и месяцах. Не «а давайте попробуем», а именно аудит с конкретным выходом - дорожная карта с приоритетами и рисками. Мы взялись.

Что смотрели

У клиента несколько баз на MS SQL Server 2008 R2. Операционные данные, справочники, пара аналитических схем. Приложения - смесь самописного .NET и коробочного отраслевого ПО. Хранимые процедуры есть, и их немало: часть логики исторически ушла в базу, как это часто бывает в госсекторе, где приложение могло меняться несколько раз, а процедуры - жить своей жизнью.

Аудит мы разбили на три части:

  • Инвентаризация объектов - таблицы, представления, функции, процедуры, триггеры, задания SQL Server Agent, связанные серверы, репликация.
  • Анализ совместимости T-SQL с PL/pgSQL - прошлись по каждой процедуре руками, категоризировали по уровню сложности переноса.
  • Оценка зависимостей приложений - где приложение ходит напрямую в SQL, где через ORM, где используются специфические возможности MS SQL.

Что показал анализ процедур

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

Первая - переносится относительно прямо. Простые SELECT с JOIN, INSERT/UPDATE/DELETE, несложная обработка параметров. Синтаксис T-SQL и PL/pgSQL похож - переписать можно за час-два на процедуру, если понимаешь что делаешь. Таких оказалось чуть меньше половины.

Вторая - требует внимательной переработки. Тут несколько типовых ситуаций: временные таблицы с #temp-синтаксисом (в PostgreSQL это CREATE TEMP TABLE, поведение немного другое в части видимости в транзакциях), TRY/CATCH с XACT_ABORT (в PL/pgSQL обработка ошибок через EXCEPTION-блок с другой семантикой отката), табличные переменные DECLARE @t TABLE. Курсоры есть, и некоторые написаны так, что проще переписать в set-based логику, чем портировать курсор один в один.

Третья - отдельный разговор. Несколько процедур используют возможности, у которых в PostgreSQL 9.3 нет прямого аналога или аналог устроен принципиально иначе. OPENROWSET для чтения из внешних источников - в PostgreSQL это dblink или foreign data wrapper, но настройка другая. Полнотекстовый поиск через CONTAINS и FREETEXT - в PostgreSQL есть tsvector/tsquery, но синтаксис и поведение отличаются, плюс нужно пересмотреть конфигурацию словарей под русский язык. Ещё пара процедур использует CLR - это уже за пределами любого автоматического переноса.

Специфика MS SQL, которая мешает

Несколько вещей оказались неочевидными на входе в аудит.

Collation и сортировка. MS SQL у клиента настроен с Cyrillic_General_CI_AS - регистронезависимое сравнение строк по умолчанию. В PostgreSQL по умолчанию сравнение регистрозависимое. Там, где приложение или процедура полагается на нечувствительность к регистру без явного UPPER() - это тихая бомба. Нашли несколько мест в условиях WHERE и при поиске по справочникам.

NULL-семантика в сортировке. В MS SQL ORDER BY по умолчанию кладёт NULL последними по возрастанию. В PostgreSQL - первыми. Для отчётных запросов, где порядок строк важен, это видимое отличие.

Identity и sequences. IDENTITY-столбцы в MS SQL и SERIAL/SEQUENCE в PostgreSQL работают похоже, но поведение при SET IDENTITY_INSERT ON - специфическая MS SQL вещь, которую нужно обходить отдельно при миграции данных.

Связанные серверы. Один из серверов использует linked server для обращения к другой базе на другом хосте. В PostgreSQL это решается через postgres_fdw, но это отдельная настройка и отдельное тестирование.

Дорожная карта: что предложили

По итогам аудита клиент получил документ с разбивкой на этапы.

Этап 1 - подготовительный. Развернуть тестовый PostgreSQL 9.3, перенести схему через pg_dump-совместимые инструменты (мы смотрели на pgloader и частично ручной DDL), перенести данные, составить полный список несовместимостей по группам из аудита.

Этап 2 - портирование процедур. Начать с первой группы (прямой перенос), параллельно прорабатывать решения для второй. Третья группа - отдельное проектирование: CLR-логику, скорее всего, придётся выносить на уровень приложения.

Этап 3 - тестирование приложений. Самый непредсказуемый по срокам кусок. Коробочное отраслевое ПО у клиента - вопрос к вендору: поддерживает ли он PostgreSQL вообще. Пока ответа нет, и это честно написано в дорожной карте как блокирующий риск.

Этап 4 - переключение. Параллельная работа на обеих СУБД с репликацией изменений, переключение, период наблюдения.

Сроки мы намеренно не фиксировали жёстко: без ответа от вендора коробочного ПО строить план в неделях - это просто нарисовать числа.

Где мы сейчас

Аудит завершён, дорожная карта у клиента. Этап 1 начинаем в июле. Самый интригующий вопрос - что скажет вендор отраслевой системы. По опыту, у них либо «да, поддерживаем PostgreSQL» с кучей оговорок, либо «нет, только MS SQL» и тут уже разговор другой.

Импортозамещение СУБД на практике оказывается не столько технической задачей по переносу SQL-кода, сколько инвентаризационным проектом: понять что вообще есть, где реальные зависимости, и честно разложить риски по полочкам. Перепортировать процедуры - трудоёмко, но понятно. Убедить вендора коробочного ПО поддержать PostgreSQL - это уже другой разговор.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.