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

339

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

cretzel
источник
6
Мы делаем это. Никогда не было проблем.
критцель
4
Очень хороший вопрос Я сталкиваюсь с этим сейчас. Так что теперь 2018 год - через 10 лет, что ты думаешь? Безопасно ли использовать обновление Hibernate на важных производственных базах клиентов со сложными схемами?
Кирилл Ch

Ответы:

388

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

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

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

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

Владимир Дюжев
источник
33
Почему это небезопасно?
критцель
74
Это небезопасно, поскольку применяемые исправления могут иметь побочные эффекты, которые hbm2ddl вряд ли может предсказать (например, отключение триггеров, которые были установлены для изменяемой таблицы). Для сложных схем самый безопасный способ - ручной. Автомат с пострегрессионным тестированием далекой секунды. Все ИМХО.
Владимир Дюжев
18
Также обновление схемы БД должно выполняться профессионалами (dbas). Восстановление после неудачного изменения БД в лучшем случае затруднительно. Вова не упомянул об этом - но что произойдет, если обновление hibernate решит удалить столбец и добавить его заново, потому что изменился тип или размер. И допустим, в столбце указаны все адреса электронной почты ваших пользователей? :-) пока, пока компания ..... Вы хотите, чтобы изменение DDL генерировалось автоматически - но вы абсолютно хотите, чтобы изменение было проверено человеком.
Пэт
9
Вы не делаете резервные копии своих баз данных перед обновлением?
Джейкоб
21
Кстати, в данный момент обновление схемы Hibernate не удаляет таблицы или столбцы.
Брайан Детерлинг
70

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

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

Брайан Детерлинг
источник
2
Мы используем его в производстве, аналогичный вариант использования. Аналитическая платформа, которая не является критически важной. Мы развернули 16K раз в 4 средах (4 года) без особых проблем с гибернацией. Мы небольшая команда, и все мы в основном начинающие в SQL RDBS и лучше верим в схему обработки Hibernate, чем мы сами. Интересно, какова частота ошибок при наличии администратора базы данных для управления миграцией и изменениями схемы? Это лучше, чем 0 в ~ 16K развертывается?
user3263752
Что бы вы сказали по поводу этого комментария? stackoverflow.com/questions/221379/…
Шива Кумар
52

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

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

Римский
источник
1
Это было написано в 2006 году?
user3263752
28

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

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

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

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

http://www.liquibase.org/

jpswain
источник
Отлично, именно то, к чему я собирался перейти. Я считаю, что лучше всего сделать один шаг вперед, добавив hbm2ddl.auto=updateтак, чтобы ваши сопоставления классов / БД были проверены и вы имели полный контроль над созданием БД с помощью ликвидазы. Что вы думаете?
bholagabbar
Ой, я имел в видуvalidate
bholagabbar
liquibase лучше справляется со сценарием, используя поддержку «include-import», такую ​​как поддержка версий и поддержку версий, и атрибут «Type» для файлов, который помогает вам иметь разные файлы SQL для разных сред, имеющих отношение «родитель-потомок». в двух словах, иди традиционным SQL Mgmt. в производстве. Для разработки нам нужна скорость для производства, нам нужны гарантии, стабильность и резервное копирование.
Каран Кау
26

Я бы проголосовал нет. 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

cliff.meyers
источник
1
Я только что попробовал первую часть вашего примера - в моем случае изменился @Column(length = 45)на @Column(length = 255). Можно убедиться, что Hibernate 4.3.6.Final правильно обновил схему базы данных, используя hbm2ddl.auto=update. (Стоит упомянуть, что в базе данных в настоящее время нет никаких данных - только структура.)
Стив Чамберс
Очень возможно, что они исправили эту ошибку где-то в течение последних 6 лет или около того. Однако, если у вас есть данные в схеме и внесены изменения, которые привели к уменьшению ширины столбца, вы столкнетесь с ошибками или усечением неуправляемых данных.
cliff.meyers
1
flywaydb нужен SQL-скрипт, созданный вручную, он должен быть лучше, чем то, что может делать автоматическая программа, но кто может написать большой скрипт, тогда это проблема.
Бон Рикимару
25

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

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

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

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

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

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

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

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

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

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

john.stein
источник
19

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

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

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

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

введите описание изображения здесь

Влад Михалча
источник
Это идеальный ответ и согласен с ним. Но я действительно нахожу идею создания первого сценария базы данных вручную громоздким (то есть V1_0__initial_script.sql в случае примера в ссылке). Есть ли способ, которым я могу создать сценарий из моей существующей базы разработки, которую Hibernate создал для меня, и сохранить в V1_0_intial_script.sql ??
HopeKing
1
Используйте, SchemaExportкак продемонстрировано в этом тесте .
Влад Михалча
Спасибо. Я столкнулся с дампом из одной строки "mysqldump -u root -p --no-data dbname> schema.sql". Есть ли какой-то недостаток в использовании созданного из этого дампа?
HopeKing
1
Нет проблем с использованием дампа БД.
Влад Михальча,
8

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

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

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

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

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

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

Крис
источник
4
Я не согласен с комментарием NoSQL. Он определенно находится на подъеме и имеет свое место, но есть много приложений, которые абсолютно зависят от соответствия ACID для целостности данных с параллелизмом и транзакциями, которые просто не может обеспечить NoSQL.
jpswain
7

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

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

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

user1027272
источник
6

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

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

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

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

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

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

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

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

Dherik
источник
4

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

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

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

Аникет Кулькарни
источник
это проблема, с которой я часто сталкиваюсь. Мы пытаемся использовать hibernate для первоначального создания БД, но зачастую это невозможно.
Дан
5
Это не «проблема», это правильная вещь.
Владимир Дюжев
2

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

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

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

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

extraneon
источник
«Существуют инструменты, которые могут сделать дельту схемы для вас»: не могли бы вы указать на некоторые из таких инструментов?
Даниэль Кэссиди
Я думаю, что apexsql.com/sql_tools_diff.asp делает это, и, возможно, больше приложений. Я обычно делаю это вручную, выкидывая схему и изменяя (используя diff).
Extraneon
2

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

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

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

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

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

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

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

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

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

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

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

Пьетро Полсинелли
источник