Обновить

Шпаргалка по работе с PostgreSQL для бэкенд-разработчиков

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели14K
Всего голосов 31: ↑25 и ↓6+20
Комментарии24

Комментарии 24

>>Миграции — это код, который нельзя откатить

На этих словах статью можно закрыть.

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

Миграции должны иметь механизм отката и он есть, для этого и делают up и down миграции. Up это накат изменений, Down это откат этих изменений. Если у вас нет механизма отката миграции, то грош цена вашему проекту (сервису).

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

Временами приходится таким образом конфликты решать, когда успел собственные миграции поверх необновлённой ветки применить

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

Например, частая ошибка — это добавить новое поле в большую таблицу с дефолтным значением. Это будет долгая блокирующая операция, так как PostgreSQL будет копировать дефолтное значение во все записи в таблице.

Да уж семь лет как не блокирует. Кому нужен очередной сборник мифов из интернета?

А вот это так просто просто шедевр:

Сгенерируйте побольше данных в локальной БД для проверки индексов.

Мне кажется кто-то опытный (возможно из постгреспро) должен уже написать аналогичную статью, но уже "по делу" и развеять все мифы раз и навсегда.

>> Кому нужен очередной сборник мифов из интернета?

Тем кто идет на собеседования и будет общаться с людьми продолжающими жить в мифах (ну или все знания которых получены из таких статей)

Спасибо за комментарий) Смотря что в дефолтном значении. Добавил уточнение

-- up
UPDATE users SET status = 'active' WHERE status = 'new';
-- down
UPDATE users SET status = 'new' WHERE status = 'active';

Мимо. Второй скрипт не откатит состояние таблицы к тому, которое было до наката первого скрипта. Подсказать, почему, или и так понятно? )

Подсказать, почему, или и так понятно? )

Мастер интриги )

Так вроде довольно очевидно и без подсказки )

Достаточно представить таблицу, в которой 1000 записей со статусом active, 1000 записей со статусом new, мысленно применить к ней два скрипта и подумать, что будет в итоге.

Да вы ещё и адмирал ))

Спасибо за комментарий) Это просто "наивный" пример, чтобы было понятно о чем речь.

У вас очень много по статье таких "наивных" неправильных примеров. Проблема как раз в этом - материал вроде бы расчитан на новичков, которые могут взять и скопировать такой пример, не подумав достаточно, и огрести себе проблем с этим в дальнейшем. Из-за чего окажется, что полезность вашей статьи по общему объему причиненных последствий скорее отрицательная.
Мое мнение, что лучше никаких примеров не давать, чем давать такие.

Мне вот стало интересно, вот люди пишут пишет даун миграции дают пример который не верный, другие подсвечивают ошибки, но никто толком не объясняет что в общем случае ап миграции невозможно ревертнуть.

Возьмём этот же пример, кажется что можно сохранить айдишники всех обновленных строк и тогда можно откатить. Но это только кажется, т.к. между накатом и откатом строка может поменяться по любой причине и тогда откатывать применявшуюся строку нельзя. Ок давайте смотреть на айди и статус, все равно нельзя потому что статус может тоже поменяться. Ок берём айди + апдэйтед_эт + статус, но тогда некоторые строки могут не откатиться. Это наверное самый безопасный откат, но где же хранить эти данные? Да и при таком раскладе все равно 100% откат невозможен в принципе.

Вопрос, а если нельзя в принципе откатиться гарантировано то зачем вообще заниматься этой хернёй?

Спасибо за комментарий) Да чаще всего возможность отката есть только через короткий промежуток времени и это может быть нужно во время релиза. Заниматься этим стоит, когда есть высокие риски ошибок в большом релизе и продумывать стратегию быстрого отката. Иногда приходится для отката временно сохранять какие-то данные чтобы откатиться. Но это очень сильно спасает, когда что-то пошло нет так в проекте, где каждая минута простоя стоит миллионы. Без этого восстановление работы может занять непредсказуемо много времени. Добавлю уточнение спасибо

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

У всех все по-разному конечно организовано, но мне вот не очень понятно как вообще в теории даже люди организуют запуск даун миграций на проде? Ап миграции обычно идут в комплекте с новым релизом тут все понятно, а как даун миграция доставляется до прода? Нельзя просто так взять и после ап миграции запустить даун, т.к. уже развернутая версия прода может тупо крашиться из за даун миграции. Раскатать предыдущую версию? Но она уже может и не запуститься, никто никогда не тестирует форвард совместимость. В общем вопрос о том как даже на бумаге/чисто в теории организовать более менее безопасную даун миграцию вообще не тривиален, а на практике если у вас нет строго бюрократического процесса релиза ваша даун миграция скорее ещё больше усугубит проблему из за которой ее решили запустить.

В общем, я вам, про даун миграции вообще не верю.

Почему вы мне не верите? Я вас никогда не обманывал)

А если серьезно, то конечно откат миграций я видел не раз. Многое зависит от процессов, а они в свою очередь от требований к проекту.

Например, если проект имеет низкую нагрузку или стоимость простоя не велика, то часто принебрегают стратегиями отката, а в случае каких-то проблем, просто готовят новый релиз с исправлением ошибки.

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

Для каждого релиза обязательно подробно расписываем план релиза и план отката. Если после релиза что-то пошло не так, а откат невозможен, то к автору этого релиза будут большие вопросы. Автоматизация в пайплайнах gitlab и доставка down миграции выглядит так же, как и up. В большинстве релизов сначала выполняется up миграция, а потом деплой, а значит в случае отката версии кода нужно откатить и миграции. Иногда миграции не откатывают если проблема очевидна и можно собрать новый релиз в ближайшее время. Во время релиза катим не master ветку а релизный tag, новый код в mater попадает только после успешного релиза это упрощает процесс отката и не блокирует другие релизы в случае отката первого.

Форвард совместимость мы тестируем всегда. Это обязательно нужно делать при наличии высоких рисков + у нас несколько ДЦ и планировать релиз и откат нужно с учетом этого.

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

По поводу отдельной статьи на эту тему подумаю, возможно напишу)

...в общем случае ап миграции невозможно вернуть/развернуть...

...зачем вообще заниматься этой..

В общем случае нельзя статическими, заранее подготовленными скриптами вернуться к логически первоначальному результату :)

В частных случаях, если мы говорим про DML, через миграции практически всегда обновляются справочники, то есть части которые изменяются только через миграции и можно прогнозировать что и когда может измениться. Если говорить про DDL там проблем ещё меньше.

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

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

Откатит, если до первого скрипта не было ни одного status = 'active' :) Но так как этого мы не знаем, то делать так конечно категорически нельзя. Интересно, в Бегете реально так делают?

Это вредный совет:

  • Первичные ключиid (не user_id в таблице users)

  • Внешние ключиuser_id (не userId или owner)

Я всегда придерживаюсь другого правила. Для каждой таблицы придумываю 2--4-буквенное сокращение и использую его как префикс для всех колонок этой таблицы. А если в таблице есть внешний ключ, то эта колонка называется точно так же, как в родительской таблице.

Т.е. если таблица users будет ссылаться на таблицу accounts, то в таблице users будут колонки usr_id, acc_id.

При таком наименовании у JOIN в запросах не придётся перечислять условия равенства, а достаточно написать NATURAL JOIN (в более сложных случаях иногда требуется JOIN USING). И если состав внешнего ключа поменяется, то текст запроса менять не придётся.

Да это тупо читать проще, сложнее закосячить. Не понимаю смысла ходить и всем рассказывать что поле должно называться id, а не user_id

Спасибо за комментарий) Подход с унифицированными именами столбцов действительно имеет преимущества для NATURAL JOIN.

Однако в своей практике я предпочитаю избегать NATURAL JOIN из-за его неявного поведения. Чтобы он гарантированно работал правильно, необходимо, чтобы все таблицы в проекте строго следовали единым правилам именования. В больших проектах с множеством разработчиков всегда есть риск, что новый член команды создаст таблицу по другим правилам, или что при изменении схемы добавятся столбцы с совпадающими именами. За этим сложно следить, особенно если это монолит, в котором работает несколько команд, и их состав периодически меняется.

Я предпочитаю явно указывать условия в ON - это делает запросы более предсказуемыми и устойчивыми к изменениям. А если не использовать NATURAL JOIN, то префиксы к каждому столбцу в таблице могут быть избыточны.

С начало думал, что увидел знакомые слова(спасибо автору), почитал комментарии, такое впечатление, что мне "глаза выдавили".

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
beget.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия