Hibernate:hbm2ddl.auto = update in production?


338

hbm2ddl.auto=update本番環境でデータベーススキーマを更新するように設定されたHibernateアプリケーションを実行しても問題ありませんか?


6
私達はできる。問題はありませんでした。
cretzel

4
非常に良い質問です。今直面しています。それで今2018-10年後のあなたの意見は何ですか?複雑なスキーマを持つ重要なクライアントの本番データベースでHibernateの更新を使用しても安全ですか?
キリルCh

回答:


388

いいえ、安全ではありません。

Hibernateチームの最善の努力にもかかわらず、本番環境では自動更新依存することはできません。独自のパッチを作成し、DBAで確認してテストし、手動で適用します。

理論的には、hbm2ddl updateが開発で機能した場合、本番環境でも機能するはずです。しかし、実際には、常にそうであるとは限りません。

正常に機能しても、最適とは言えない可能性があります。DBAには理由があり、その分だけ給与が支払われます。


33
なぜ安全ではないのですか?
cretzel

74
適用されたパッチには、hbm2ddlが予測できない副作用(変更されたテーブル用にインストールされたトリガーを無効にするなど)が含まれている可能性があるため、安全ではありません。複雑なスキーマの場合、最も安全な方法は手動です。後退回帰テストを使用した自動は、もうすぐです。すべて私見。
Vladimir Dyuzhev、2008年

18
また、dbスキーマの更新は専門家(dbas)が処理する必要があります。悪いdb変更からの回復は、せいぜい困難です。Vovaはそれについて言及していませんでしたが、Hibernateの更新により、タイプまたはサイズが変更されたために列を削除して再追加する場合はどうなりますか。そして、列がすべてのユーザーのメールアドレスであるとしましょうか?:-) bye、bye company ..... DDLの変更を自動的に生成したいが、人間が変更を確認したい場合。
Pat

9
アップグレード前にデータベースをバックアップしませんか?
Jacob

21
Fwiw、現時点では、Hibernateのスキーマ更新はテーブルまたは列をドロップしません。
Brian Deterling

70

ミッションクリティカルではないアプリケーションを使用し、スタッフに高額なDBAがいない場合でも、本番環境でそれを行います。人為的エラーの影響を受けるのは、1つ少ない手動プロセスです。アプリケーションは違いを検出して正しいことを行うことができ、さらに、さまざまな開発環境やテスト環境でテストしたと考えられます。

注意点の1つ-クラスター環境では、複数のアプリが同時に表示されてスキーマを変更しようとする可能性があるため、これを回避することができます。または、1つのインスタンスのみがスキーマの更新を許可されるメカニズムを追加します。


2
プロダクションでも同様のユースケースを使用しています。ミッションクリティカルではない分析プラットフォーム。私たちは、4つの環境(4年間)で16K回デプロイしましたが、休止状態でそれほど問題はありませんでした。私たちは小規模なチームであり、すべてSQL RDBSの初心者であり、Hibernate処理スキーマを自分よりも信頼しています。移行とスキーマの変更を管理するスタッフにDBAがいると、エラー率はどうなるのでしょうか。〜16Kの展開で0よりも良いですか?
user3263752

patによるこのコメントについてどう思いますか?stackoverflow.com/questions/221379/...
シヴァクマール

52

Hibernateの作成者は、本「Java Persistence with Hibernate」の本番環境での使用を推奨していません。

警告:HibernateユーザーがSchemaUpdateを使用して本番データベースのスキーマを自動的に更新しようとしているのを見てきました。これは災害ですぐに終わり、DBAによって許可されません。


1
それは2006年に書かれたのですか?
user3263752

28

LiquiBase XMLをチェックして、更新の変更ログを保持してください。今年まで使用したことがありませんでしたが、DBのリビジョン管理/移行/変更管理を非常に簡単に習得して簡単にできることがわかりました。私はGroovy / Grailsプロジェクトに取り組んでおり、GrailsはそのすべてのORM(「GORM」と呼ばれます)にHibernateを使用しています。私たちはLiquibaseを使用してすべてのSQLスキーマの変更を管理します。これは、アプリが新機能で進化するにつれてかなり頻繁に行われます。

基本的に、アプリケーションの進化に応じて追加し続けるチェンジセットのXMLファイルを保持します。このファイルは、プロジェクトの残りの部分でgit(または使用しているもの)に保持されます。アプリがデプロイされると、Liquibaseは接続先のDBの変更ログテーブルをチェックして、すでに適用されているものを認識し、ファイルからまだ適用されていない変更セットをインテリジェントに適用します。これは実際には非常に優れており、すべてのスキーマ変更に使用すると、チェックアウトしてデプロイしたコードが常に完全に互換性のあるデータベーススキーマに接続できることを100%確信できます。

すばらしいのは、ラップトップで完全に空白のスレートmysqlデータベースを取得し、アプリを起動して、すぐにスキーマを設定できることです。また、スキーマの変更を最初にlocal-devまたはステージングデータベースに適用することで、スキーマの変更を簡単にテストできます。

これを使い始める最も簡単な方法は、おそらく既存のDBを取得してから、Liquibaseを使用して最初のbaseline.xmlファイルを生成することです。その後、あなたはそれに追加するだけで、liquibaseがスキーマの変更の管理を引き継ぐことができます。

http://www.liquibase.org/


完璧です、私がこれから移ろうとしていました。私は最高のことを感じています。一歩先に進むとhbm2ddl.auto=update、クラス/ DBマッピングが検証され、リキベースを通じてDB作成を完全に制御できるように追加することになります。どう思いますか?
bholagabbar 2017年

おっと、私は意味しましたvalidate
bholagabbar 2017年

liquibaseは、 "include-import"のようなサポートとバージョン管理のサポート、および親子関係を持つさまざまな環境でさまざまなSQLファイルを使用できるようにするファイルの "Type"属性を使用してスクリプトを管理するのに優れています。一言で言えば、伝統的なSQL管理を行ってください。生産中。開発にはSpeed For Productionが必要であり、保証と安定性とバックアップが必要です。
Karan Kaw 2017年

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


1
私はあなたの例の最初の部分を試しました-私の場合はに変更@Column(length = 45)@Column(length = 255)ます。Hibernate 4.3.6.Finalがを使用してデータベーススキーマを正しく更新したことを確認できますhbm2ddl.auto=update。(言及すべきことの1つは、現在データベースにはデータがなく、構造のみであるということです。)
Steve Chambers

彼らが過去〜6年程度のどこかでそのバグを修正した可能性は非常に高いです。ただし、スキーマにデータがあり、列幅が減少するような変更を加えた場合、エラーまたは管理されていないデータの切り捨てが発生します。
cliff.meyers 2014

1
flywaydbは手動で作成されたSQLスクリプトを必要とします。自動プログラムで実行できるものよりも優れているはずですが、だれが大きなスクリプトを作成できるかは問題です。
BANG力丸

25

Hibernateは、自動更新を使用しないことについての免責事項を製品で使用して、自分が何をしているのかわからない人が使用すべきでない状況でそれを使用する場合に備えて自分自身をカバーする必要があります。

それが使用されるべきではない状況が、大丈夫な状況よりもはるかに多いことを認めた。

私は何年にもわたってさまざまなプロジェクトで使用してきましたが、1つの問題が発生したことはありません。これは不十分な答えではなく、カウボーイコーディングでもありません。それは歴史的な事実です。

「本番環境では絶対に行わないでください」と言う人は、特定の本番デプロイメント、つまり彼がよく知っているデプロイメント(彼の会社、彼の業界など)について考えています。

「プロダクションデプロイメント」の世界は広大で多様です。

経験豊富なHibernate開発者は、特定のマッピング構成からどのDDLが生成されるかを正確に知っています。期待した結果がDDL(dev、qa、ステージングなど)に含まれることをテストおよび検証する限り、問題ありません。

多くの機能を追加する場合、自動スキーマ更新はリアルタイムの節約になります。

自動更新で処理されないもののリストは無限ですが、いくつかの例は、データの移行、null不可の列の追加、列名の変更などです。

また、クラスター環境では注意が必要です。

しかし、繰り返しになりますが、これらすべてを知っていれば、この質問をすることはないでしょう。うーん 。。。わかりました。この質問をする場合は、Hibernateと自動スキーマの更新に関する多くの経験があるまで待ってから、製品での使用を検討してください。


19

この記事で説明したようにhbm2ddl.auto、本番環境で使用することはお勧めできません。

データベーススキーマを管理する唯一の方法は、次の理由で増分移行スクリプトを使用することです。

  • スクリプトはコードベースに沿ってVCSに常駐します。ブランチをチェックアウトすると、スキーマ全体が最初から再作成されます。
  • 増分スクリプトは、本番環境に適用する前にQAサーバーでテストできます
  • スクリプトはFlywayで実行できるため、手動による介入の必要はなく、手動でのスクリプトの実行に関連する人為的エラーの可能性が減少します。

Hibernateユーザーガイドでも、hbm2ddl本番環境でのツールの使用を避けるようにアドバイスしています。

ここに画像の説明を入力してください


これは完璧な答えであり、それに同意します。しかし、私は本当に最初のデータベーススクリプトを手動で作成するアイデアを見つけます(つまり、リンクの例の場合はV1_0__initial_script.sql)。Hibernateが作成した既存の開発DBからスクリプトを作成してV1_0_intial_script.sqlに格納する方法はありますか?
HopeKing

1
SchemaExportこのテストケースで示されているように使用します。
Vlad Mihalcea

ありがとう。1行のダンプ "mysqldump -u root -p --no-data dbname> schema.sql"に遭遇しました。これから生成されたダンプを使用することに何か欠点はありますか?
HopeKing

1
DBダンプを使用しても問題はありません。
Vlad Mihalcea

8

私たちは、数か月間本番環境で実行されているプロジェクトでそれを行い、今のところ問題はありませんでした。このレシピに必要な2つの成分に留意してください。

  1. 下位互換性のあるアプローチでオブジェクトモデルを設計します。つまり、オブジェクトや属性を削除/変更するのではなく、廃止します。つまり、オブジェクトまたは属性の名前を変更する必要がある場合は、古い名前をそのままにして、新しい名前を追加し、ある種の移行スクリプトを記述します。オブジェクト間の関連付けを変更する必要がある場合、既に本番環境にいる場合、これはそもそも設計が間違っていたことを意味します。古いデータに影響を与えずに、新しい関係を表現する新しい方法を考えてみてください。

  2. 展開前に必ずデータベースをバックアップしてください。

私の感覚は、この記事を読んだ後、このディスカッションに参加している人々の90%が、このような自動化を本番環境で使用することを考えているだけで恐怖を感じることです。DBAにボール投げる人もいます。少し時間を取って、すべての本番環境がDBAを提供するわけではなく、多くの開発チームがDBAを提供できるわけではないことを考慮してください(少なくとも中規模プロジェクトの場合)。だから、誰もがすべてをしなければならないチームについて話している場合、ボールは彼らの上にあります。

この場合、両方の長所を活かそうとしないでください。このようなツールは、注意深い設計と計画により、多くの状況で役立ちます。そして私を信じて、管理者は最初は納得するのが難しいかもしれませんが、ボールが自分の手にはないことを知っていれば、彼らはそれを気に入るはずです。

個人的には、あらゆる種類のスキーマを拡張するために手動でスクリプトを作成することはありませんが、それは私の意見です。そして、最近、NoSQLスキーマレスデータベースの採用を開始した後、これらのスキーマベースの操作はすべて過去のものであることがすぐにわかります。そのため、視点を変えて先を見るほうがよいでしょう。


4
NoSQLのコメントに同意しません。それは間違いなく増加しており、その場所はありますが、同時実行性とNoSQLでは簡単に提供できないトランザクションのデータ整合性をACIDコンプライアンスに完全に依存する多くのアプリケーションがあります。
jpswain 2011

7

保存されているはずのデータが失われる可能性があるので、リスクを冒しません。hbm2ddl.auto = updateは、開発データベースを最新の状態に保つための純粋に簡単な方法です。


2
アップグレード前にデータベースをバックアップしませんか?
ジェイコブ

6
もちろん可能ですが、バックアップから復元するのは大変な作業です。整然とした方法でデータベースを更新することもできるので、バックアップを復元する手間がかかりません。
Jaap Coomans

6
  • 私の場合(Hibernate 3.5.2、Postgresql、Ubuntu)、設定hibernate.hbm2ddl.auto=updateは新しいテーブルのみを作成し、既存のテーブルに新しい列を作成しました。

  • テーブルの削除も、列の削除も、列の変更も行いませんでした。それは安全なオプションと呼ぶことができますが、何かhibernate.hbm2ddl.auto=create_tables add_columnsがより明確になるでしょう。


6

安全ではなく、推奨されていませんが、可能です。

本番環境で自動更新オプションを使用するアプリケーションの経験があります。

このソリューションで見つかった主な問題とリスクは次のとおりです。

  • 間違ったデータベースにデプロイします。間違ったデータベースで古いバージョンのアプリケーション(EAR / WAR / etc)を使用してアプリケーションサーバーを実行するという間違いを犯した場合...新しい列、テーブル、外部キー、およびエラーが多数発生します。同じ問題がデータソースファイルの単純な間違いでも発生する可能性があります(ファイルをコピー/貼り付け、データベースを変更するのを忘れた)。再開すると、状況はデータベースの惨事になる可能性があります。
  • アプリケーションサーバーの起動に時間がかかりすぎます。これは、Hibernateがアプリケーションを起動するたびに、作成されたすべてのテーブル/列などを検索しようとするためです。彼は何を作成する必要があるか(テーブル、列など)を知る必要があります。この問題は、データベーステーブルが大きくなるにつれて悪化します。
  • 使用するのがほとんど不可能であるデータベースツール。新しいバージョンで実行するデータベースDDLまたはDMLスクリプトを作成するには、アプリケーションサーバーの起動後に自動更新によって何が作成されるかを考える必要があります。たとえば、新しい列にデータを入力する必要がある場合は、アプリケーションサーバーを起動し、Hibernateが新しい列を作成するのを待って、その後にのみSQLスクリプトを実行する必要があります。ご覧のとおり、データベース移行ツール(Flyway、Liquibaseなど)は、自動更新を有効にして使用することはほとんど不可能です。
  • データベースの変更は一元化されていません。Hibernateがテーブルやその他すべてを作成する可能性があるため、アプリケーションの各バージョンでデータベースの変更を監視することは困難です。それらのほとんどは自動的に行われるためです。
  • データベースのゴミを奨励します。自動更新を「簡単に」使用できるため、休止状態の自動更新ではそれができないため、チームが古い列と古いテーブルを削除し忘れている可能性があります。
  • 差し迫った災害。本番環境で何らかの災害が発生する差し迫ったリスク(他の回答で言及されている人もいます)。アプリケーションを実行して何年も更新されている場合でも、安全な選択だとは思いません。このオプションを使用しても、安全だと感じたことはありません。

したがって、本番環境で自動更新を使用することはお勧めしません。

本番環境で自動更新を本当に使用したい場合は、以下をお勧めします。

  • 分離したネットワーク。テスト環境はホモログ環境にアクセスできません。これは、テスト環境にあるはずの展開がホモロゲーションデータベースを変更するのを防ぐのに役立ちます。
  • スクリプトの順序を管理します。デプロイ前に実行するスクリプト(構造テーブルの変更、テーブル/列のドロップ)とデプロイ後のスクリプト(新しい列/テーブルの情報を入力)を編成する必要があります。

そして、他の投稿とは異なり、自動更新が有効になっていて、「他の投稿で言及されているように」「非常に高額な」DBAに関連しているとは思いません。DBAには、SQLステートメントを記述してテーブルや列を作成、変更、削除するよりも、重要な作業があります。これらの単純な日常的なタスクは、開発者が実行および自動化でき、DBAチームがレビューするためにのみ渡され、HibernateとDBAがそれらを書くために「非常に有償」である必要はありません。


4

いいえ、絶対にしないでください。Hibernateはデータ移行を処理しません。はい、スキーマが正しく見えるようになりますが、貴重な本番データがプロセスで失われないことは保証されません。


4
  • 通常、大規模な組織のエンタープライズアプリケーションは、特権を減らして実行されます。

  • データベースユーザー名には、必要なDDL列を追加する権限がない可能性がありhbm2ddl.auto=updateます。


これは私がよく遭遇する問題です。最初のDB作成にhibernateを使用しようとしますが、それができない場合がよくあります。
Dan

5
これは「問題」ではありません。これは正しいことです。
ウラジミールデュジェフ

2

私はウラジミールに同意します。私の会社の管理者は、もし私がそのようなコースを提案したとしても、絶対に感謝しません。

さらに、Hibernateを盲目的に信頼する代わりにSQLスクリプトを作成すると、使用されなくなったフィールドを削除できます。Hibernateはそれを行いません。

また、プロダクションスキーマと新しいスキーマを比較すると、データモデルで変更したワットをさらに詳しく理解できることがわかります。もちろん、あなたはそれを作ったので知っていますが、今ではすべての変更を一度に見ることができます。「一体何を!?」みたいなものまで。

スキーマの差分を作成できるツールがあるため、大変な作業ではありません。そして、あなたは何が起こるかを正確に知っています。


「スキーマの差分を作成できるツールがあります」:そのようなツールをいくつか教えていただけますか?
ダニエルキャシディ

apexsql.com/sql_tools_diff.aspがこれを行うと思います。私は通常、手作業でスキーマをダンプし、(diffを使用して)diffします。
エクストラネオン

2

アプリケーションのスキーマは時間とともに進化する可能性があります。異なるバージョンの複数のインストールがある場合、アプリケーション、ある種のツールまたはスクリプトがスキーマとデータをあるバージョンから次のバージョンに段階的に移行できることを確認する方法が必要です。

Hibernateマッピング(またはアノテーション)にすべての永続性を持たせることは、スキーマの進化を制御し続けるための非常に良い方法です。

スキーマの進化には、考慮すべきいくつかの側面があることを考慮する必要があります。

  1. 列とテーブルを追加する際のデータベーススキーマの進化

  2. 古い列、テーブル、リレーションの削除

  3. 新しい列をデフォルトで埋める

Hibernateツールは、(私の経験のように)同じアプリケーションの異なるバージョンがさまざまな種類のデータベースにある場合に特に重要です。

ポイント3は、Hibernateを使用している場合に非常に敏感です。たとえば、新しいブール値のプロパティまたは数値のプロパティを導入した場合、Hibernateがそのような列でnull値を検出した場合、例外が発生します。

だから私は何をしますか:スキーマ更新のHibernateツール機能を実際に使用しますが、それに加えて、デフォルトの入力、使用されなくなった列の削除など、データとスキーマのメンテナンスコールバックを追加する必要があります。このようにして、利点(データベースに依存しないスキーマ更新スクリプト、および永続性とスクリプトでの更新の重複したコーディングの回避)が得られますが、操作のすべての側面もカバーします。

したがって、たとえば、バージョン更新がvarchar値のプロパティ(したがって列)を追加するだけの場合、デフォルトではnullになり、自動更新が行われます。さらに複雑さが必要な場合は、より多くの作業が必要になります。

これは、更新されたアプリケーションがそのスキーマを更新できる(実行できる)ことを前提としています。これは、スキーマに対して更新するユーザー権限が必要であることも意味します。顧客のポリシーがこれを防止する場合(おそらくトカゲの脳の場合)、データベース(特定のスクリプト)を提供する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.