Hibernate: hbm2ddl.auto= обновление в производстве?

Можно ли запускать приложения Hibernate, настроенные с hbm2ddl.auto=update обновить схему базы данных в производственной среде?

15 ответов

Решение

Нет, это небезопасно.

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

Теоретически, если обновление hbm2ddl работало в разработке, оно должно работать и в производстве. Но на самом деле это не всегда так.

Даже если это работает хорошо, это может быть неоптимальным. АБД платят так много по причине.

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

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

Создатели Hibernate не рекомендуют делать это в производственной среде в своей книге "Сохранение Java в Hibernate":

ВНИМАНИЕ: Мы видели, как пользователи Hibernate пытались использовать SchemaUpdate для автоматического обновления схемы производственной базы данных. Это может быстро закончиться катастрофой и не будет разрешено вашим администратором базы данных.

Как я объяснил в этой статье, не очень хорошая идея hbm2ddl.auto в производстве.

Единственный способ управлять схемой базы данных - использовать сценарии инкрементной миграции, потому что:

  • Сценарии будут находиться в VCS вдоль вашей кодовой базы. Когда вы оформляете ветку, вы воссоздаете всю схему с нуля.
  • инкрементные сценарии могут быть проверены на сервере QA перед применением в производстве
  • нет необходимости в ручном вмешательстве, так как скрипты могут запускаться Flyway, следовательно, это уменьшает вероятность человеческих ошибок, связанных с выполнением скриптов вручную.

Даже руководство пользователя Hibernate советует вам избегать использования hbm2ddl инструмент для производственных сред.

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

Разумеется, ситуации, когда его не следует использовать, намного превосходят те, где все в порядке.

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

Человек, который говорит "никогда не делай этого на производстве", думает о конкретном наборе производственных процессов, а именно о тех, с которыми он знаком (его компания, его отрасль и т. Д.).

Вселенная "производственных развертываний" обширна и разнообразна.

Опытный разработчик Hibernate точно знает, что DDL получит в результате данной конфигурации сопоставления. Пока вы тестируете и проверяете, что то, что вы ожидаете, попадает в DDL (в dev, qa, staging и т. Д.), У вас все в порядке.

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

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

Также вам нужно позаботиться в кластерной среде.

Но опять же, если бы вы знали все это, вы бы не задавали этот вопрос. Хм,, Хорошо, если вы задаете этот вопрос, вам следует подождать, пока у вас не появится большой опыт работы с Hibernate и автоматическими обновлениями схемы, прежде чем вы решите использовать ее в prod.

Проверьте LiquiBase XML для ведения журнала изменений. Я никогда не использовал его до этого года, но обнаружил, что его очень легко освоить и сделать управление ревизиями БД / управление миграцией / изменениями очень надежным. Я работаю над проектом Groovy/Grails, и Grails использует Hibernate для всех своих ORM (называемых "GORM"). Мы используем Liquibase для управления всеми изменениями схемы SQL, что мы делаем довольно часто, так как наше приложение развивается с новыми функциями.

По сути, вы храните XML-файл наборов изменений, который вы продолжаете добавлять по мере развития вашего приложения. Этот файл хранится в git (или как вы его используете) с остальной частью вашего проекта. Когда ваше приложение развернуто, Liquibase проверяет свою таблицу изменений в БД, к которой вы подключаетесь, чтобы узнать, что уже применено, а затем разумно просто применяет любые изменения, которые еще не были применены из файла. Он прекрасно работает на практике, и если вы используете его для всех изменений схемы, вы можете быть на 100% уверены, что код, который вы извлекаете и разворачиваете, всегда сможет подключиться к полностью совместимой схеме базы данных.

Удивительная вещь в том, что я могу взять на своем ноутбуке совершенно пустую базу данных mysql, запустить приложение и сразу же настроить схему для меня. Это также облегчает тестирование изменений схемы, применяя их сначала к локальной dev-системе или промежуточной базе данных.

Самый простой способ начать работу с ним, вероятно, состоит в том, чтобы взять существующую БД и затем использовать Liquibase для создания исходного файла baseline.xml. Тогда в будущем вы можете просто добавить к нему и позволить liquibase взять на себя управление изменениями схемы.

http://www.liquibase.org/

Я бы проголосовал нет. Hibernate, кажется, не понимает, когда типы данных для столбцов изменились. Примеры (с использованием MySQL):

String with @Column(length=50)  ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)

@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed

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

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

Flyway - хороший вариант для решения этой проблемы:

http://flywaydb.org/

Я бы не стал рисковать, потому что вы можете потерять данные, которые должны были быть сохранены. hbm2ddl.auto=update - это простой способ поддерживать вашу базу данных в актуальном состоянии.

Мы делаем это в проекте, работающем уже несколько месяцев, и у нас до сих пор не было проблем. Имейте в виду 2 ингредиента, необходимые для этого рецепта:

  1. Проектируйте свою объектную модель с подходом обратной совместимости, который исключает объекты и атрибуты, а не удаляет / изменяет их. Это означает, что если вам нужно изменить имя объекта или атрибута, оставьте старое как есть, добавьте новое и напишите какой-нибудь скрипт миграции. Если вам нужно изменить связь между объектами, если вы уже находитесь в производстве, это означает, что ваш проект был в первую очередь неправильным, поэтому постарайтесь придумать новый способ выражения новых отношений, не затрагивая старые данные.

  2. Всегда делайте резервную копию базы данных перед развертыванием.

Я чувствую - после прочтения этого поста - что 90% людей, участвующих в этом обсуждении, приходят в ужас от мысли об использовании подобных автоматизаций в производственной среде. Некоторые бросают мяч в DBA. Уделите немного времени, чтобы учесть, что не все производственные среды предоставляют DBA, и не так много команд разработчиков могут себе их позволить (по крайней мере, для проектов среднего размера). Так что, если мы говорим о командах, где каждый должен делать все, мяч на них.

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

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

Это не безопасно, не рекомендуется, но возможно.

У меня есть опыт использования приложения с автоматическим обновлением на производстве.

Итак, основные проблемы и риски, обнаруженные в этом решении:

  • Развернуть в неправильной базе данных. Если вы допустите ошибку, чтобы запустить сервер приложений со старой версией приложения (EAR/WAR/etc) в неправильной базе данных... У вас будет много новых столбцов, таблиц, внешних ключей и ошибок. Та же проблема может возникнуть с простой ошибкой в ​​файле источника данных (скопировать / вставить файл и забыть изменить базу данных). В резюме, ситуация может быть катастрофой в вашей базе данных.
  • Запуск сервера приложений занимает слишком много времени. Это происходит потому, что Hibernate пытается найти все созданные таблицы / столбцы / и т. Д. Каждый раз, когда вы запускаете приложение. Он делает это, чтобы знать, что (таблица, столбец и т. Д.) Нужно создать. Эта проблема будет только усугубляться.
  • Инструменты базы данных практически невозможно использовать. Чтобы создать сценарии для базы данных, вам нужно подумать о том, что будет создано при автообновлении после запуска сервера приложений. Если вам нужно заполнить новый столбец (для каждого примера) некоторыми данными, вам нужно запустить сервер приложений, подождать, пока Hibernate создаст новый столбец, и после этого запустить скрипт SQL. Такие инструменты, как Flyway, практически невозможно использовать с включенным автообновлением.
  • Изменения базы данных не централизованы. Благодаря возможности Hibernate создавать таблицы и все остальное трудно наблюдать за изменениями в базе данных в каждой версии приложения, поскольку большинство из них выполняются автоматически.
  • Поощряет мусор в базе данных. Из-за простоты автоматического обновления существует вероятность того, что ваша команда пренебрегает удалением старых столбцов и старых таблиц.
  • Грядущая катастрофа. Неизбежный риск некоторой катастрофы на производстве (как некоторые люди упоминали в других ответах). Даже если приложение работает и может обновляться годами, я не думаю, что это безопасно. Я никогда не чувствовал себя в безопасности.

Поэтому я не буду рекомендовать использовать автообновление в производстве.

Если вы действительно хотите использовать автообновление в производстве, я рекомендую:

  • Раздельные сети. Ваша тестовая среда не может получить доступ к среде гомологов. Это помогает предотвратить развертывание, которое должно быть в тестовой среде, изменить базу данных омологации.
  • Управление порядком скриптов. Вам необходимо организовать выполнение сценариев до развертывания (изменение таблицы структур, удаление таблицы / столбцов) и сценариев после развертывания (заполнить информацию для новых столбцов / таблиц).

И, в отличие от других постов, я не думаю, что автообновление включено, это связано с "очень хорошо оплачиваемыми" администраторами баз данных (как упомянуто в других публикациях)... Администраторы баз данных имеют более важные дела, чем пишут операторы SQL для создания / изменить / удалить таблицы и столбцы. Эти простые каждодневные задачи могут быть выполнены и автоматизированы разработчиками и переданы только команде DBA для просмотра, не требуя, чтобы Hibernate и администраторы баз данных "очень хорошо оплачивались" для их написания.

  • В моем случае (Hibernate 3.5.2, Postgresql, Ubuntu) настройка hibernate.hbm2ddl.auto=update только создавал новые таблицы и создавал новые столбцы в уже существующих таблицах.

  • Он не удалял ни таблицы, ни столбцы, ни столбцы. Это можно назвать безопасным вариантом, но что-то вроде hibernate.hbm2ddl.auto=create_tables add_columns было бы более понятно.

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

  • Обычно корпоративные приложения в крупных организациях работают с ограниченными привилегиями.

  • Имя пользователя базы данных может не иметь DDL привилегия для добавления столбцов, которые hbm2ddl.auto=update требует.

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

Вся ваша настойчивость в отображениях (или аннотациях) Hibernate является очень хорошим способом для контроля над развитием схемы.

Следует учитывать, что эволюция схемы имеет несколько аспектов, которые следует учитывать:

  1. эволюция схемы базы данных с добавлением дополнительных столбцов и таблиц

  2. удаление старых столбцов, таблиц и отношений

  3. заполнение новых столбцов значениями по умолчанию

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

Точка 3 очень чувствительна в том случае, если вы используете Hibernate, как в случае, если вы вводите новое булево значение или числовое свойство, если Hibernate найдет какое-либо нулевое значение в таких столбцах, если вызовет исключение.

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

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

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

Я согласен с Владимиром. Администраторы в моей компании определенно не оценили бы это, если бы я даже предложил такой курс.

Кроме того, создание сценария SQL вместо слепо доверяющего Hibernate дает возможность удалять поля, которые больше не используются. Hibernate не делает этого.

И я считаю, что сравнение производственной схемы с новой схемой дает вам еще лучшее понимание того, как вы изменились в модели данных. Вы знаете, конечно, потому что вы сделали это, но теперь вы видите все изменения за один раз. Даже те, которые заставляют вас говорить "Какого черта?!".

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

Другие вопросы по тегам