Pull to refresh

Comments 34

Так что делать с легаси ораклиной?
Микросервисы это всё понятно. Особенно новые.
А как быть с полсотней разработчиков разной степени криворукости, которым ушатывать тестовую бд. Но не простую, а тестовый контур сверхбрльшой БД? Которая завязана кучей щупалец с другими сервисами?
Как взять ее под контроль версий?

Выглядит как запрос на отдельную статью о том, как мы решали аналогичную боль =)
Напишем статью, если это и правда востребовано. Ставьте upvote, если откликнулось.
Если коротко, то это процесс + техническое решение, основная цель которых — контроль и проверки на всех этапах.
Было бы интересно почитать

Так же. С какого-то момента все изменения схемы — ченжсетами в любом формате. Перед продом стоит препрод, на который нельзя накатить что-то руками. На нём все update+rollback прогоняются вашим CI/CD перед мёржем, после чего делается флэшбэк (если это ораклина), а после мёржа делается update. Для чистоты совести можете обновлять его по выходным.

Но не простую, а тестовый контур сверхбрльшой БД


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

По поводу несоответствия состояния прода предполагаемому статусу мне нравится такое решение: перед деплоем на прод берется продовая база, кидается на тест и выполняются вообще все ендпоинты API в порядке CRURD и только потом на прод.

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

дак без данных берем и кидает, в чем проблема то?) Единственное что тесты на круды придется чуть сложнее писать

Ну ка по подробнее. Зачем тестовая бд без данных?
Как на ней проверять интерфейсы, нагрузку и прочее.
Цель накатить пустую схему и получить с этого профит (не понятно какой)?

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

Миграции это и есть интеграция гита с базой. Просто не очевидная для вас

Ну да, конечно, особенно учитывая количество приседаний.

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

Когда столкнулись с такой задачей, напедалили на Node.JS свою нехитрую утилиту, которая соединяется в обе базы, сравнивает содержимое конкретных таблиц из конфига и генерирует DML SQL скрипты. github.com/qiwi/pg_comparator
Кстати, эту утилиту тогда сделал школьник-стажер под моим менторством. Об этом мы рассказывали в другой статье habr.com/ru/company/qiwi/blog/434636
Статья по ссылке — про сравнение двух состояний схемы. Нам нужно было актуализировать в тесте содержимое (данные) справочных таблиц, которое нагенерили пользователи в проде. Стандартных легковесных инструментов сходу не нашли. Буду рад если подкинете такой.

Как пишете и отлаживаете скрипты миграции данных из одной версии базы к другой? Что делаете, если в тестинге миграция работает, а в проде — нет?

Мы стараемся обеспечить максимальную изоморфность сред. Пока не было ситуации, когда в тестинге работает, а в проде — нет. Если такая ситуация возникнет, то в первую очередь будем искать дырку в процессе) А уже потом править ченджсет, если потребуется.

В тестинге находится копия продовой базы? Если да — то как обеспечиваете защиту персональных данных там? Если нет, то ведь нет и никаких гарантий, что поведение скриптов миграции будет одинаковым на проде и в тестинге — довольно часто в проде накапливается "мусор" из-за менее строгих проверок данных в прошлом.


Например, было в табличке пользователей поле email, и оно не было с ограничением на уникальность, хотя в коде давно уже на уникальность проверка есть. В какой-то момент захотели и в базе сделать его уникальным, но, при миграции в проде, оказалось, что на заре сервиса было зарегистрировано несколько пользователей с одинаковым email. Как действуете в подобных случаях?

Переливка данных из прода в тестинг всегда проходит через фазу деперсонализации, на которой чувствительная информация маскируется. Этот процесс у нас не включен в ci и проходит в полуручном режиме.
Хороший пример с email) Проверку на уникальность в приложении мы тоже сделали бы через уникальный индекс на базе и поиск по нему. Есть еще вариант со вставкой и отловом исключения, но мы стараемся избегать exceptions as control flow. В любом случае, мы столкнулись бы с проблемой неуникальных данных еще в момент реализации такой проверки. Что бы мы делали с такими записями — вопрос бизнес логики приложения и продукта. Универсального ответа не могу дать.

Ну я специально его придумывал, по мотивам реального случая. Проверку уникальности через индекс я поддерживаю, собственно, если идти по этому пути — проблема и возникнет ровно в момент миграции базы в проде, и решать надо было бы именно на стадии миграции, ведь в старом коде проверки не было, и поэтому записи УЖЕ есть в базе.

Только не уникальный индекс а уникальный частичный индекс.
upper(email) where is_deleted=false
Круто. Надеюсь, что и мы прикрутим к своему проекту Liquibase.

Довелось мне как-то поработать с выходцами из qiwi. Теперь я хотя бы знаю что они не шутили, а правда так мыслили, спасибо.

интересная тема, отладка и тестирование базы данных. даже писал помню статью на хабре по этому поводу, неоднозначное впечатление я так понял она произвела, но и полностью мой подход не опровергли… посмотрите, может вам чем-то буду полезен. хотя там без легаси и на. net но суть та же, думаю сможете воспроизвести. ключевой момент — изоляция обращений к базе в DAL и тестирование его на реальной базе без mock

Спасибо за наводку, отличная статья! И дискуссия интересная в комментах)

Все это, конечно, замечательно, но что делать с шардингом.

ИМХО тут надо различать логическую структуру БД и её физическую реализацию.
Как бы проблема шардинга, не должна касаться программистов, желательно, чтобы это была внутренняя кухня ДБА.
Здесь ТС рассматривает пайплайн для разработчиков.
Чтобы «отделить» программистов от ручных изменений в БД.
Т.к. все актуальные СУРБД к такому использованию приспособлены менее чем никак, то получается все очень неуклюже.

К сожалению, шардинг практически никогда не удается изолировать от аппликейшн-уровня. Он всегда «протекает» в той или иной степени, и в особенности — для случая реляционной СУБД (вернее, для случая «реляционных БД», это ж шардинг, БД много). Соответственно, мигратор должен уметь не просто тупо накатывать-откатывать на одну базу, но делать это на несколько баз, да еще желательно работать с микрошардами (в постгресе одна микрошарда может быть одной схемой или одним префиксом имени таблицы).


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

Лично мне не нравится идея с упаковкой скриптов в докерфайл. Постгрес поддерживает монтирование файлов с init sql скриптами и sh через волюм. Это удобнее, IMHO.

Действительно, монтировать том в контейнер с базой удобно еще и тем, что это дает возможность иметь локально персистентную базу. Тут кому как удобнее, на самом деле. Я описал концепцию в ее самом простом виде.
Хорошего средства для автоматизации контроля версий БД на MSSQL я так и не смог найти, поэтому написал свою утилиту ImportExportDataSql (выложил в бесплатное пользование на обозрение).
Недавно добавил возможность экспорта конфигурации БД.
Экспорт данных в ней тоже имеется (в форматах CSV и SQL).
Настройки хранятся в XML файле, что удобно при переносе сразу нескольких таблиц (результатов SELECT запросов). Написал запросы SELECT один раз и эти запросы выгружаются в формате SQL, в котором уже имеются проверки на уникальность, чтобы не возникало ошибок нарушения ключей.
Что касается сбора всех изменений структуры БД — написал системный триггер, который сохраняет историю изменений в отдельную таблицу с помощью функции EVENTDATA().
Sign up to leave a comment.