Как стать автором
Обновить

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

В разделе
«Специфика работы с PostgreSQL»
Неплохо бы указать, что в PostgreSQL 11 проблема добавления поля с неким дефолт значением и создания индексов решаются хорошо.
По поводу «Не секрет, что роли как сущности живут не на уровне отдельной базы данных, но на уровне всего сервера баз данных, по крайней мере, в Postgres.» — в PostgreSQL да, но в общем так не стоит заявлять. Это не секрет, что в SQL Server роли живут в базе (Database roles)
Я так полагаю, что «миграцией» Вы назвали database deployment patch.

Тогда фраза
Случись такое, что вы еще не используете Migrations или нечто подобное, самое время начать. Да, Pentium 4 тоже устарел.
выглядит немного напыщенной, т.к. подобный решений существует не один десяток (DbMaestro, FlyWay) + несметное количество самописных тулов.
Спасибо за комментарий :)
Да, есть некоторое разнообразие в терминологии, вероятно database deployment patch это один из вариантов. M.Fowler использует термины «database changes are migrations», тут единого
стандарта нет.

Migrations или нечто подобное… выглядит немного напыщенной, т.к. подобный решений существует не один десяток… вы правы, но я и не утверждаю что Migrations это
единственное решение в своем классе, как видите.
Я просто не совсем точно выразился. Я ничего не имею против каких-то самописных решений, но, согласитесь, «изобретение велосипеда» не всегда что-то полезное.
Вот если в Вашем решении есть какие-то, действительно, интересные решения — например, как Вы обеспечиваете миграцию данных при применении патчей и, особенно, при их откате, то вот это было бы очень интересно почитать и сравнить со свои опытом.
И, к сожалению, как раз об этом ничего нет. Т.е. как бы сказано «А», но не сказано «Б».
Вообще то я не говорил что у нас есть собственное решение, Migrations штука вполне стандартная и общедоступная. Тем не менее, вы угадали. Мы отказались от Migrations в сторону своего решения.

Я планирую написать вторую статью в продолжение, если к этой будет интерес.
Опять же, в целом вы правильно мыслите, кроме стандартных команд Migrations (init, up, down, status) мы добавили: sign, snapshot, copy и diff. Кроме того, мы частично автоматизировали UNDO, так что проблем с несимметричностью изменений должно стать меньше. На систематизацию простых миграций данных тоже есть планы.
У всех подобных решений (change-driven deployment), на мой взгляд, есть досточно много недостатков, чтобы их считать чем-то современным и прогрессивным.
Просто для контраста представьте, что Вы заставляете разработчиков приложений не комитить конечный код java-классов, javascript и прочего, а писать патчи (вставки/изменения/удаления строк) к тому, чтобы из какого-то умозрительного состояния файлов на сервере приложений получить тот самый конечный вид файлов приложения, который нужен. Вас бы посчитали сумашедшим или мазохистом, ведь так?
Но почему-то такой подход для изменения объектов в базе данных считается вполне приемлемым.

У нас вот тоже «исторически» внедрён подобный подход к deployment изменений в базах данных (а это десятки схем и несколько разных по сути видов баз данных — editorial, staging, customer-facing, ...) — простенькие Python скрипты — фактически просто подключение к базе и выполнение скриптов + обвязка. Этот тул и для Oracle и для PostgreSQL/Greenplum работает. Патчи в Git организованы по определённым правилам — сгруппированы по компонентам и по типам объектов, есть нумерация и шаблоны имён. Есть и checkpoint таблицы для учёта того, какие патчи установлены, какие нет и т.п.
Но! Попробуйте с таким подходом создать схему с нуля, склонировать её куда-то или попытаться сравнить реальное состояние схемы с тем, что у вас вроде как есть в Git с историей (но в виде патчей, а не конечных состояний). Попробуйте сделать тот же rollback в любой предыдущий коммит или diff с любым предыдущим состоянием объектов в базе.
Кроме того, к сожалению, наивно надеяться на то, что патчи разработчики будут делать правильные — idempotent — и повторное выполнение не приведёт к ошибке (простейший CREATE TABLE без IF EXISTS, например). И т.д. и т.п.

И теперь сравните это со state-driven deployment подходом — вы коммитите ровно то состояние объектов, которое нужно иметь в базе, а как его достигнуть (CREATE TABLE или ALTER TABLE) — дело движка deployment + hooks. Это же почти как и в application code deployment.
Например, так реализован db deployment в RedGate (Source Control for Oracle) и DaticalDB (основанный на open-source liquibase).
По мне — это и есть то, к чему стоит стремиться в database deployment.
Конечно, не все виды баз, не все типы объектов поддерживаются тем же RedGate и DaticalDB, но принцип очень правильный, с моей точки зрения. Они стоят денег, причём, честно не всегда адекватно (DaticalDB).

И конечно же основная проблема в любом подходе к database deployment — это сохранение и миграция данных. Тут одними техническими решениями не обойтись — нужна чёткая и иногда даже жёсткая дисциплина в подготовке db deployment.
У меня статья короче чем ваш комментарий, ну, поехали.
У всех подобных решений (change-driven deployment)...

Люди приходят к change-driven deployment не на пустом месте, а потому что есть
состояние которое нельзя потерять. В случае с кодом, который вы конечно привели
для контраста, старое состояние кода не имеет ценности и всегда его можно заменить
полным новым состоянием кода. Исключения: erlang и хранимые процедуры.

У нас вот тоже «исторически» внедрён подобный подход

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

Но! Попробуйте с таким подходом создать схему с нуля

Вы правы, с этим есть проблемы. В лучшем случае это долго, в худшем — не работает.
За миграциями приходится следить. Мне приходилось несколько раз патчить их ретроспективно.

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

Увы, вы правы. Средненькое решение тут — тестировать, хорошее — генерировать UNDO автоматически.

(Вторая половина ответа в следующем комментарии).
Люди приходят к change-driven deployment не на пустом месте, а потому что есть
состояние которое нельзя потерять. В случае с кодом, который вы конечно привели
для контраста, старое состояние кода не имеет ценности и всегда его можно заменить
полным новым состоянием кода. Исключения: erlang и хранимые процедуры.


Конечно — часто делается это, чтобы хоть что-то было для deployment.
Не всегда хранимые процедуры (и даже представления) можно заменить — в PostgreSQL это как раз сложнее, чем в Oracle и всегда есть ньюансы.
У меня статья короче чем ваш комментарий

Каюсь — грешен этим.

Я планирую написать вторую статью в продолжение, если к этой будет интерес.
Опять же, в целом вы правильно мыслите, кроме стандартных команд Migrations (init, up, down, status) мы добавили: sign, snapshot, copy и diff. Кроме того, мы частично автоматизировали UNDO, так что проблем с несимметричностью изменений должно стать меньше. На систематизацию простых миграций данных тоже есть планы.

Будет любопытно почитать.
Тема для меня интересная и отчасти болезненная — через много пришлось пройти на собственном опыте.
Зато, в результате, сейчас есть опыт автоматизации db deployment в Oracle/Greenplum пары десятков компонентов (~50 схем) с помощью скриптов на Python + GitHub + Jenkins + Docker — всё внутри AWS. DBA нынче не просто DBA ;-)
Зато, в результате, сейчас есть опыт автоматизации db deployment в Oracle/Greenplum пары десятков компонентов (~50 схем) с помощью скриптов на Python + GitHub + Jenkins + Docker — всё внутри AWS. DBA нынче не просто DBA ;-)

Вы можете показать свое решение? Было бы интересно посмотреть, если конечно это не закрытая информация.
Вы можете показать свое решение? Было бы интересно посмотреть, если конечно это не закрытая информация.


Весь код я показать не могу — это всё лежит в private GitHub repo, но схему взаимодействия и идею попробую обрисовать (это может занять какое-то время)
И теперь сравните это со state-driven deployment подходом

Подход интересный, но организационно сложнее.

(ссылка на Red Gate)
1. А как будет собираться состояние к релизу — из тех патчей/ченжей/миграций?
2. Тогда получается что либо перед либо после релиза нужно собрать финальное состояние и положить его в код? Вроде как лишний шаг.

Мне кажется что такой вариант идеально подошел ты тому, мифическому, Oracle DBA из начала статьи.

И конечно же основная проблема в любом подходе к database deployment — это сохранение и миграция данных.

Миграция данных куда хуже, полностью с вами согласен.
Даже просто откатить DROP TABLE уже непростая задача.
Подход интересный, но организационно сложнее.


Это скорее не сильно сложнее технически (как бы такое утверждение не казалось бы слишком оптимистичным), а сложнее для изменения культуры разработки, т.к. database developer-ы меньше готовы к восприятию версионирования объектов базы данных, технологии релизов, насколько это всё давно естественно и как бы само собой подразумевается в разработке кода приложений. Культура совсем другая нужна.

Если оценить, то ведь и типов объектов в базе данных, которые применяются в приложениях сейчас обычно не так много, да и видов операций тоже. Т.е. написать генератор перехода состояний не так уж и сложно. Я это делал (несмотря на то, что я — Oracle DBA) на perl даже для версионирования контента таблиц метаданных (конечно, без LOB и очень простых и небольших).
Вам надо было посмотреть на RedGate Source Control в связке с Schema Comparison.

1. А как будет собираться состояние к релизу — из тех патчей/ченжей/миграций?

Абсолютно также как и application deployment — при таком подходе применимы любые современные методики и разработки и релизов (CI/CD).
В том и суть, что Source Control не хранит никаких патчей, а хранит стандартизированные DDL объектов, что мне не нравится, кстати. Я в своей давнишней поделке для описания аттрибутов объектов использовал XML, а сейчас бы выбрал JSON. Патчи генерятся на лету уже Schema Comparison, где происходит сравнение двух «endpoint», каждый из которых может быть или коннектом к базе, или snapshot (снимок структуры объектов) или как раз путь к рабочему каталогу в Git с теми DDL, которые сгенерированы Source Control. Snapshot — вообще очень удобная штука — нет прямого доступа к Prod — попросил сделать snapshot и дальше можно его использовать для сравнения, генерации патчей — создания пустых схем и т.п.
(ссылка на Red Gate)
2. Тогда получается что либо перед либо после релиза нужно собрать финальное состояние и положить его в код? Вроде как лишний шаг.


Конечные состояния объектов всегда в Git — как вы их собираете в релизы — это обычная тема application deployment методик.

Если бы RedGate Deployment Pack не был бы только под Windows, с фокусом сейчас только на SQL Server, без поддержки PostgreSQL, и трудным расширением проприетарного функционала, то мог бы получиться очень продвинутый инструмент. Но и даже в этом виде + VM или docker и какие-никакие command line возможности вполне прилично работают с Oracle, как минимум.
Я с ними общался на Pipeline конференции пару лет назад — планов по поддержке PostgreSQL у них не было и до сих пор нет.
Миграция данных куда хуже, полностью с вами согласен.
Даже просто откатить DROP TABLE уже непростая задача.


Вот тут технически и огранизационно нужно запрещать выполнять деструктивные операции в их простом прямолинейном виде. Парой слов тут не обойтись, а уже хочется и спать :)
А что там с миграцией из ORM баз?
Они щас в соседнем топике обсуждаются — habr.com/post/413597
А ничего. Модели ORM использовать внутри миграций запрещено. Точка.
Потому что может случится казус что модели не существует / она изменена, и миграция уже не соотвествует модели ORM.

PS Вся статья выглядит как попытка откровения, но в 2k18 после десятка лет существования рельсов это скорее капитанство
Однажды довелось собирать обновление базы для боевой системы из 100+ скриптов изменений, разбросанных по почте. Отдельный вопрос, как такое произошло, но самое интересное, что базу тогда собрали и систему запустили (седых волос только добавилось). Тогда я сказал себе «никогда больше»
По этому у вас ник 911? :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий