hbm2ddl.auto=update
実稼働環境でデータベース スキーマを更新するように構成された Hibernate アプリケーションを実行しても問題ありませんか?
15 に答える
いいえ、安全ではありません。
Hibernate チームの最善の努力にもかかわらず、本番環境では自動更新に頼ることはできません。独自のパッチを作成し、DBA で確認してテストし、手動で適用します。
理論的には、hbm2ddl updateが開発で機能した場合、本番環境でも機能するはずです。しかし、実際には、常にそうであるとは限りません。
正常に機能したとしても、最適ではない可能性があります。DBA には、それなりの理由があります。
ミッション クリティカルではないアプリケーションを使用し、高給取りの DBA をスタッフに配置していませんが、本番環境で行っています。これは、人為的エラーの影響を受ける手動プロセスが 1 つ少ないだけです。アプリケーションは違いを検出して正しいことを実行できます。また、さまざまな開発環境やテスト環境でテストしたと思われます。
1 つの注意点 - クラスター化された環境では、複数のアプリが同時に起動してスキーマを変更しようとする可能性があるため、これを回避することをお勧めします。または、1 つのインスタンスのみがスキーマを更新できるメカニズムを導入します。
Hibernate の作成者は、著書「Java Persistence with Hibernate」で、本番環境でこれを行うことを思いとどまらせています。
警告: Hibernate ユーザーが SchemaUpdate を使用して実稼働データベースのスキーマを自動的に更新しようとしているのを見てきました。これはすぐに惨事に終わる可能性があり、DBA によって許可されません。
更新の変更ログを保持する LiquiBase XML を確認してください。私は今年までそれを使用したことがありませんでしたが、習得が非常に簡単で、DB のリビジョン管理/移行/変更管理が非常に簡単であることがわかりました。私はGroovy/Grailsプロジェクトに取り組んでおり、GrailsはそのすべてのORM(「GORM」と呼ばれる)の下でHibernateを使用しています。Liquibase を使用して、すべての SQL スキーマの変更を管理しています。これは、アプリが新しい機能で進化するにつれて、かなり頻繁に行っています。
基本的に、変更セットの XML ファイルを保持し、アプリケーションの進化に合わせて追加し続けます。このファイルは、プロジェクトの残りの部分とともに git (または使用しているもの) に保持されます。アプリがデプロイされると、Liquibase は接続先の DB の変更ログ テーブルをチェックして、既に適用されているものを認識し、ファイルからまだ適用されていない変更セットをインテリジェントに適用します。実際には非常にうまく機能し、すべてのスキーマ変更に使用すると、チェックアウトして展開するコードが完全に互換性のあるデータベース スキーマに常に接続できることを 100% 確信できます。
すばらしいことに、ラップトップで完全に空の状態の mysql データベースを使用してアプリを起動すると、すぐにスキーマがセットアップされます。また、スキーマの変更を最初に local-dev または staging db に適用することで、スキーマの変更を簡単にテストできます。
これを開始する最も簡単な方法は、おそらく既存の DB を取得し、Liquibase を使用して最初のbaseline.xml ファイルを生成することです。将来的には、それに追加するだけで、liquibase がスキーマ変更の管理を引き継ぐことができます。
Hibernate は、自分が何をしているのかを知らない人が自動更新を使用すべきではない状況で自動更新を使用する場合に、自分自身をカバーするために、prod で自動更新を使用しないことについての免責事項を記載する必要があります。
確かに、使用してはいけない状況のほうが、問題ない状況よりもはるかに多くなっています。
さまざまなプロジェクトで何年も使用してきましたが、一度も問題が発生したことはありません。それは不十分な答えではなく、カウボーイコーディングでもありません. 歴史的事実です。
「本番環境では絶対にやらない」と言う人は、特定の本番環境の展開、つまり自分がよく知っているもの (会社、業界など) について考えています。
「本番環境へのデプロイ」の世界は広大で多様です。
経験豊富な Hibernate 開発者は、特定のマッピング構成からどのような DDL が生成されるかを正確に知っています。期待どおりの結果が DDL (dev、qa、staging など) に含まれていることをテストして検証する限り、問題はありません。
多くの機能を追加する場合、スキーマの自動更新を使用すると時間を大幅に節約できます。
自動更新が処理しないもののリストは無限にありますが、いくつかの例は、データの移行、null 非許容列の追加、列名の変更などです。
また、クラスター化された環境では注意が必要です。
しかし、繰り返しになりますが、これらすべてを知っていれば、この質問をすることはないでしょう。ふーむ 。. . この質問をしている場合は、本番環境での使用を検討する前に、Hibernate と自動スキーマ更新の経験が豊富になるまで待つ必要があります。
私は反対票を投じます。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 は、この問題に対処するための適切なオプションです。
保存されているはずのデータが失われる可能性があるため、危険を冒すことはありません。hbm2ddl.auto=update は、dev データベースを最新の状態に保つ純粋な簡単な方法です。
私の場合(Hibernate 3.5.2、Postgresql、Ubuntu)、設定
hibernate.hbm2ddl.auto=update
は新しいテーブルのみを作成し、既存のテーブルに新しい列を作成しました。テーブルも列も削除せず、列も変更しませんでした。それは安全なオプションと呼ぶことができますが、
hibernate.hbm2ddl.auto=create_tables add_columns
より明確になるようなものです。
いいえ、絶対にしないでください。Hibernate はデータ移行を処理しません。はい、スキーマが正しく表示されますが、貴重な本番データがプロセスで失われないという保証はありません。
通常、大規模な組織のエンタープライズアプリケーションは、権限を減らして実行されます。
データベースのユーザー名には、必要な
DDL
列を追加する権限がない場合がhbm2ddl.auto=update
あります。
ウラジミールに同意します。私がそのようなコースを提案したとしても、私の会社の管理者は間違いなくそれを高く評価しないでしょう。
さらに、Hibernateを盲目的に信頼する代わりにSQLスクリプトを作成すると、使用されなくなったフィールドを削除する機会が得られます。Hibernateはそれを行いません。
また、本番スキーマを新しいスキーマと比較すると、データモデルで変更したワットについてさらに優れた洞察が得られることがわかりました。もちろん、あなたはそれを成し遂げたので知っていますが、今ではすべての変更を一度に見ることができます。あなたを「一体何?!」のようにさせるものでさえ。
スキーマデルタを作成できるツールがあるので、それは大変な作業ではありません。そして、あなたは何が起こるかを正確に知っています。
アプリケーションのスキーマは時間とともに進化する可能性があります。バージョンが異なる可能性がある複数のインストールがある場合は、アプリケーション、何らかのツールまたはスクリプトがスキーマとデータをあるバージョンから次のバージョンに段階的に移行できることを確認する方法が必要です。
Hibernate マッピング (またはアノテーション) にすべての永続性を持たせることは、スキーマの進化を制御下に置くための非常に良い方法です。
スキーマの進化には、考慮すべきいくつかの側面があることを考慮する必要があります。
列とテーブルを追加する際のデータベース スキーマの進化
古い列、テーブル、およびリレーションの削除
新しい列をデフォルトで埋める
Hibernate ツールは、(私の経験のように) 多くの異なる種類のデータベースに同じアプリケーションの異なるバージョンがある場合に特に重要です。
ポイント 3 は、Hibernate を使用している場合に非常に重要です。新しいブール値のプロパティまたは数値プロパティを導入する場合、Hibernate がそのような列で null 値を検出した場合、例外が発生した場合です。
したがって、私が行うことは、スキーマ更新の Hibernate ツール機能を実際に使用することですが、それに加えて、デフォルトの入力、使用されなくなった列の削除など、いくつかのデータおよびスキーマ メンテナンス コールバックを追加する必要があります。このようにして、利点 (データベースに依存しないスキーマ更新スクリプト、更新の重複コーディングの回避、持続性およびスクリプト内) を得ることができますが、操作のすべての側面もカバーされます。
したがって、たとえば、バージョンの更新が単純に varchar 値のプロパティ (したがって列) を追加するだけで構成されている場合、デフォルトで null になる可能性がありますが、自動更新を使用すると完了します。より複雑さが必要な場合は、より多くの作業が必要になります。
これは、更新時にアプリケーションがそのスキーマを更新できる (実行できる) ことを前提としています。つまり、スキーマで更新するためのユーザー権限が必要です。顧客のポリシーによってこれが妨げられている場合 (Lizard Brain のケースの可能性が高い)、データベース - 固有のスクリプトを提供する必要があります。