web-dev-qa-db-ja.com

Hibernate:本番環境でhbm2ddl.auto = update?

実稼働環境でデータベーススキーマを更新するためにhbm2ddl.auto=updateで設定されたHibernateアプリケーションを実行しても大丈夫ですか?

313
cretzel

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

Hibernateチームの最善の努力にもかかわらず、単純に自動更新生産中に頼ることはできません。独自のパッチを作成し、DBAでレビューし、テストしてから、手動で適用します。

理論的には、hbm2ddl updateが開発で機能していれば、本番でも機能するはずです。しかし、実際には、常にそうであるとは限りません。

うまくいったとしても、最適ではないかもしれません。 DBAには、理由があります。

366

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

1つ注意点-クラスター環境では、複数のアプリが同時に起動し、スキーマを変更しようとする可能性があるため、回避する必要がある場合があります。または、スキーマの更新を1つのインスタンスのみに許可するメカニズムを導入します。

69
Brian Deterling

Hibernateの作成者は、本の本番環境でそうすることを推奨しません "Hibernateを使用したJava Persistence"

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

50
Roman

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

基本的に、アプリケーションの進化に合わせて追加し続ける変更セットのXMLファイルを保持します。このファイルは、プロジェクトの他の部分とともにgit(または使用しているもの)に保持されます。アプリがデプロイされると、Liquibaseは接続しているDBのchangelogテーブルをチェックするため、すでに適用されているものを把握し、ファイルからまだ適用されていない変更セットをインテリジェントに適用します。実際には非常にうまく機能し、すべてのスキーマの変更に使用する場合、チェックアウトしてデプロイするコードは常に完全に互換性のあるデータベーススキーマに接続できると確信できます。

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

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

http://www.liquibase.org/

28
jpswain

Hibernateは、何をしているかわからない人が自動更新を使用すべきでない状況で使用する場合に、自動更新を使用しないことに関する免責事項をprodに記載して自分自身をカバーする必要があります。

使用すべきではない状況が、問題のない状況よりもはるかに多いことを認めました。

私はこれを何年もさまざまなプロジェクトで使用してきましたが、一度も問題を抱えたことはありません。それは不完全な答えではなく、カウボーイコーディングでもありません。それは歴史的な事実です。

「本番環境では絶対にしない」と言う人は、特定の本番環境の展開、つまり、彼がよく知っているもの(会社、業界など)を考えています。

「運用展開」の世界は広大で多様です。

経験豊富なHibernate開発者は、特定のマッピング構成からDDLがどのような結果になるかを正確に知っています。あなたが期待するものがDDLで終わることをテストして検証する限り(dev、qa、ステージングなどで)、あなたは大丈夫です。

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

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

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

しかし、このことをすべて知っていれば、この質問をすることはないでしょう。うーん。 。 。この質問をする場合は、prodでHibernateを使用することを検討する前に、Hibernateと自動スキーマ更新の多くの経験を得るまで待つ必要があります。

24
john.stein

私はいいえ投票します。 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

24
cliff.meyers

この記事 で説明したように、実稼働環境でhbm2ddl.autoを使用するのは得策ではありません。

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

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

Hibernate User Guide でも、実稼働環境ではhbm2ddlツールの使用を避けることをお勧めします。

enter image description here

13
Vlad Mihalcea

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

  1. 後方互換性のアプローチ、つまりdeprecateオブジェクトと属性を削除/変更するのではなく、オブジェクトモデルを設計します。つまり、オブジェクトまたは属性の名前を変更する必要がある場合は、古いものをそのままにして、新しいものを追加して、何らかの移行スクリプトを作成します。オブジェクト間の関連付けを変更する必要がある場合、すでに実稼働している場合、これは設計がそもそも間違っていたことを意味するため、古いデータに影響を与えずに新しい関係を表現する新しい方法を考えてみてください。

  2. 常にbackup展開前のデータベース。

私の感覚では、この投稿を読んだ後、この議論に参加している人々の90%が、実稼働環境でこのような自動化を使用するという考えだけで恐ろしいということです。いくつかのDBAでボールを投げます。ただし、すべてのプロダクション環境がDBAを提供するわけではなく、開発チームの1人が余裕がない(少なくとも中規模のプロジェクトの場合)ことを考慮してください。だから、みんながすべてをしなければならないチームについて話しているなら、ボールは彼らの上にあります。

この場合、なぜ両方の世界の最高のものを手に入れようとしないのですか?このようなツールは支援の手を差し伸べるために用意されており、慎重な設計と計画があれば、多くの状況で役立ちます。そして、私を信じて、管理者は最初は納得するのが難しいかもしれませんが、ボールが手にないことを知っているなら、彼らはそれを愛するでしょう。

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

7
chris

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

7
Jaap Coomans
  • 私の場合(Hibernate 3.5.2、Postgresql、Ubuntu)、hibernate.hbm2ddl.auto=updateを設定すると、新しいテーブルが作成され、既存のテーブルに新しい列が作成されます。

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

6
user1027272

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

実稼働環境で自動更新オプションを使用したアプリケーションの経験があります。

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

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

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

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

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

そして、他の投稿とは異なり、自動更新が有効になったとは思えません(他の投稿で述べたように)「非常によく支払われた」DBAに関連していると思います...テーブルと列を/変更/削除します。これらの簡単な日常のタスクは、開発者が実行および自動化することができ、HibernateとDBAが「非常に高額な支払い」を行うことなく、DBAチームがレビューするためだけに渡されます。

5
Dherik

いいえ、絶対にやらないでください。 Hibernateはデータの移行を処理しません。はい、スキーマは正しく表示されますが、貴重な実稼働データがプロセスで失われないことは保証されません。

4
Robert
  • 通常、大規模な組織のエンタープライズアプリケーションは、低い権限で実行されます。

  • データベースユーザー名には、hbm2ddl.auto=updateが必要とする列を追加するためのDDL特権がない場合があります。

4
Rajeev Goel

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

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

また、本番スキーマと新しいスキーマを比較すると、データモデルで変更したものをよりよく理解できることがわかります。もちろん、あなたはそれを作ったから知っていますが、今ではすべての変更を一度に見ることができます。あなたを「一体何だ!」.

スキーマデルタを作成できるツールがありますので、面倒な作業でもありません。そして、あなたは何が起こるかを正確に知っています。

2
extraneon

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

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

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

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

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

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

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

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

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

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

これは、更新時にアプリケーションがそのスキーマを更新できること(実行可能)を想定しています。これは、スキーマで更新するためのユーザー権限が必要であることも意味します。顧客のポリシーがこれを妨げている場合(リザードブレインの場合)、データベースを提供する必要があります-特定のスクリプト。

2