質問
開発サーバー、テストサーバー、運用サーバー間でデータベース スキーマとデータを管理する方法の良い例を見つけるのに苦労しました。
これが私たちのセットアップです。各開発者は、アプリと MySQL データベースを実行する仮想マシンを持っています。それは、彼らがやりたいことを何でもできる個人的なサンドボックスです。現在、開発者は SQL スキーマに変更を加え、SVN にコミットするテキスト ファイルへのデータベースのダンプを実行します。
私たちは、コミットされた最新のコードを常に実行する継続的統合開発サーバーをデプロイしたいと考えています。これを今実行すると、ビルドごとに SVN からデータベースがリロードされます。
「リリース候補」を実行するテスト(仮想)サーバーがあります。現在、テストサーバーへの展開は非常に手動プロセスであり、通常、SVNから最新のSQLをロードして微調整することが含まれます。また、テストサーバー上のデータは不整合です。最後にコミットした開発者がサンドボックス サーバー上に持っていたテスト データがすべて残ることになります。
すべてがうまくいかないのは、運用環境へのデプロイメントです。ライブ データをテスト データで上書きすることはできないため、すべてのスキーマ変更を手動で再作成する必要があります。データを操作するために大量のスキーマ変更や変換スクリプトがあった場合、これは非常に面倒なことになる可能性があります。
問題がスキーマだけであれば、もっと簡単な問題になりますが、データベースには、セキュリティ テーブルや権限テーブルのメタデータなど、開発中に更新される「ベース」データもあります。
これが、継続的インテグレーションとワンステップ ビルドに移行する上で私が考える最大の障壁です。どうやって あなた 解決しますか?
追加の質問:データベースのバージョンを追跡して、特定のデータベース インスタンスをアップグレードするためにどのスクリプトを実行するかを知るにはどうすればよいでしょうか?Lance が以下に挙げているようなバージョン テーブルは標準的な手順ですか?
タランティーノについて言及していただきありがとうございます。私は .NET 環境にいませんが、 DataBaseChangeManagement wiki ページ とても役に立ちます。特にこれ パワーポイントプレゼンテーション (.ppt)
の名前をチェックする Python スクリプトを作成します。 *.sql
指定されたディレクトリ内のスクリプトをデータベース内のテーブルに対して実行し、ファイル名の最初の部分を形成する整数に基づいて、そこにないスクリプトを順番に実行します。それが非常に簡単な解決策である場合は、おそらくそうであると思われますが、ここに投稿します。
これを実行するためのスクリプトがあります。DB が存在しない場合は初期化を処理し、必要に応じてアップグレード スクリプトを実行します。既存のデータベースを消去したり、ファイルからテスト データをインポートしたりするためのスイッチもあります。約 200 行なので、投稿しません (興味があればペーストビンに置くかもしれませんが)。
解決
良い選択肢がいくつかあります。私なら「バックアップを復元する」戦略は使いません。
すべてのスキーマ変更のスクリプトを作成し、CI サーバーでデータベース上でそれらのスクリプトを実行します。現在のデータベースのバージョンを追跡するバージョン テーブルを用意し、新しいバージョンの場合にのみスクリプトを実行します。
移行ソリューションを使用します。これらのソリューションは言語によって異なりますが、.NET の場合は Migrator.NET を使用します。これにより、データベースのバージョンを管理し、バージョン間を上下に移動できるようになります。スキーマは C# コードで指定されます。
他のヒント
開発者は、単にデータベース全体をソース管理にダンプするだけでなく、開発中のバグや機能ごとに変更スクリプト (スキーマとデータの変更) を作成する必要があります。これらのスクリプトは、現在の運用データベースを開発中の新しいバージョンにアップグレードします。
ビルド プロセスでは、運用データベースのコピーを適切な環境に復元し、ソース管理からすべてのスクリプトを実行して、データベースを現在のバージョンに更新できます。すべてのスクリプトが正しく実行されることを確認するために、これを毎日行っています。
Ruby on Rails がこれをどのように行うかを見てみましょう。
まず、いわゆる移行ファイルがあります。これは基本的にデータベース スキーマとデータをバージョン N からバージョン N+1 (またはバージョン N+1 から N にダウングレードする場合) に変換します。データベースには現在のバージョンを示すテーブルがあります。
テスト データベースは、単体テストの前に常に完全に消去され、ファイルからの固定データが設定されます。
本 データベースのリファクタリング:進化したデータベース設計 データベースの管理方法についてアイデアが得られるかもしれません。短いバージョンは次の場所でも読むことができます http://martinfowler.com/articles/evodb.html
ある PHP+MySQL プロジェクトでは、データベースのリビジョン番号をデータベースに保存しており、プログラムがデータベースに接続すると、最初にリビジョンがチェックされます。プログラムに別のリビジョンが必要な場合は、データベースをアップグレードするためのページが開きます。各アップグレードは PHP コードで指定され、データベース スキーマが変更され、既存のデータがすべて移行されます。
- データベースに次のように名前を付けます - db_dev 、 db_test 、 db_qa 、 db_prod (もちろん、データベース名をハードコーディングすべきではありません)
- したがって、同じ物理サーバー上に異なるタイプのデータベースをデプロイすることもできます (これはお勧めしませんが、そうする必要があるかもしれません...リソースが不足している場合)
- これらの間でデータを自動的に移動できることを確認してください
- データベース作成スクリプトを母集団から分離する = いつでもデータベースを最初から再作成し、(古いデータベース バージョンまたは外部データ ソースから) 母集団にデータを投入できるようにする必要があります。
- コード内でハードコード接続文字列を使用しないでください (構成ファイル内でなくても) - 動的に設定する構成ファイル接続文字列テンプレートで使用します。再コンパイルが必要な application_layer の各再構成は不良です。
- データベースのバージョン管理とデータベース オブジェクトのバージョン管理を使用してください。余裕がある場合は既製の製品を使用し、そうでない場合は独自に開発してください。
- 各 DDL 変更を追跡し、履歴テーブルに保存します ( ここの例 )
- 毎日のバックアップ!バックアップから失われたものをどれだけ早く復元できるかをテストします (自動復元スクリプトを使用します)
- DEV データベースと PROD がまったく同じ作成スクリプトを持っている場合でも、データに問題が発生する可能性があるため、開発者が PROD の正確なコピーを作成してそれを操作できるようにしてください (これについてはマイナス評価を受けることはわかっていますが、考え方とビジネスプロセスは、ファンに問題が発生した場合にはるかにコストが安くなります。したがって、プログラマーに、それが作成したものに合法的に添字を付けるよう強制しますが、これを確実にしてください
これは私が常に不満に思っていることであり、それがこの問題に対する私たちの解決策です。数年間、私たちはリリースごとに個別の変更スクリプトを維持しました。このスクリプトには、最後の製品リリースからの差分が含まれます。アプリケーションのリリースごとにバージョン番号が増加し、次のようになります。
- dbChanges_1.sql
- dbChanges_2.sql
- ...
- dbChanges_n.sql
これは、次の 2 つの開発ラインの維持を開始するまでは十分に機能しました。新規開発用のトランク/メインラインと、バグ修正や短期的な機能強化など用のメンテナンス ブランチ。必然的に、ブランチ内のスキーマに変更を加える必要が生じました。この時点で、トランクには dbChanges_n+1.sql がすでに存在していたので、最終的には次のようなスキームを採用することになりました。
- dbChanges_n.1.sql
- dbChanges_n.2.sql
- ...
- dbChanges_n.3.sql
繰り返しになりますが、これでも十分に機能していましたが、ある日調べてみると、メインラインに 42 個の差分スクリプト、ブランチに 10 個の差分スクリプトがあることがわかりました。ああ!
最近では、単純に 1 つのデルタ スクリプトを保守し、SVN にバージョン化させています。リリースごとにスクリプトを上書きします。そして、ブランチ内でスキーマを変更することを避けます。
ですから、私もこれには満足していません。私は Rails からの移行というコンセプトがとても気に入っています。かなり魅了されてしまいました リキベース. 。これは、増分データベース リファクタリングの概念をサポートします。一見の価値はありますので、すぐに詳しく見ていきます。経験のある人はいますか?あなたの結果について知りたいです。
次のようなツールの使用を検討することもできます SQL比較 データベースのさまざまなバージョン間の違いをスクリプト化して、バージョン間を迅速に移行できるようにします。
OPと非常によく似たセットアップがあります。
開発者はプライベート DB を備えた VM で開発します。
[開発者は間もなくプライベート ブランチにコミットする予定です]
テストはさまざまなマシンで実行されます(実際にはサーバーでホストされているVMで)[まもなくHudson CIサーバーによって実行されます
リファレンス ダンプをデータベースにロードしてテストします。開発者スキーマパッチを適用し、開発者のデータパッチを適用します
次に、単体テストとシステム テストを実行します。
本番環境はインストーラーとして顧客に展開されます。
私達がすること:
サンドボックス DB のスキーマ ダンプを取得します。次にSQLデータダンプ。それを前のベースラインと比較します。そのデルタのペアは、n-1 を n にアップグレードします。
ダンプとデルタを構成します。
したがって、バージョン N CLEAN をインストールするには、空のデータベースにダンプを実行します。パッチを適用するには、間にあるパッチを適用します。
( Juha さんは、現在の DB バージョンを記録するテーブルを持つという Rail のアイデアは良いものであり、更新のインストールの困難を軽減するはずだと述べました。)
デルタとダンプはベータ テストの前にレビューする必要があります。開発者が自分でテスト アカウントを DB に挿入しているのを見てきたので、これを回避する方法はわかりません。
をチェックしてください データベースデプロイ, 、Java ツールと .net ツールがすでに利用可能であるため、SQL ファイル レイアウトとスキーマ バージョン テーブルの標準に従って、Python バージョンを記述することができます。
申し訳ありませんが、私は他の投稿者と同意します。開発者は変更をスクリプト化する必要があります。
多くの場合、単純な ALTER TABLE は機能せず、既存のデータも変更する必要があります。開発者は、どのような移行が必要かを考慮し、それらが正しくスクリプト化されていることを確認する必要があります (もちろん、これは、次の時点で慎重にテストする必要があります)リリースサイクル)。
さらに、少しでも賢明であれば、開発者に変更のロールバックのスクリプトを作成してもらい、必要に応じて変更を元に戻せるようにすることもできます。これもテストして、ロールバックがエラーなしで実行されるだけでなく、DB が以前と同じ状態のままであることを確認する必要があります (これは常に可能または望ましいわけではありませんが、ほとんどの場合は適切なルールです)。 。
それをどうやって CI サーバーに接続するのか、私にはわかりません。おそらく、CI サーバーには既知のビルド スナップショットが必要であり、毎晩そのスナップショットに戻り、それ以降のすべての変更が適用されます。おそらくこれが最善です。そうしないと、移行スクリプトが壊れると、その夜のビルドだけでなく、その後のすべてのビルドも壊れてしまいます。
.NET環境を使用している場合、解決策は次のとおりです。 タランティーノ. 。これはすべて (どの SQL スクリプトをインストールするかを含む) NANT ビルドで処理されます。
私はツールを書きました( DBDiff を開く) はデータベース スキーマを比較し、移行スクリプトを提案します。データを削除または変更する変更を行うと、エラーがスローされますが、スクリプトに提案が表示されます (例:新しいスキーマに列が欠落している場合、その列の名前が変更されているかどうかがチェックされ、xx (名前変更ステートメントを含む script.sql.suggestion が生成) が作成されます。
http://code.google.com/p/migrationscriptgenerator/ SQL Server のみです、申し訳ありません :( これもかなりアルファ版ですが、非常に摩擦が少ないです (特にタランティーノや http://code.google.com/p/simplescriptrunner/)
私の使用方法は、.sln に SQL スクリプト プロジェクトを作成することです。また、ローカルに db_next データベースがあり、(Management Studio または Hibernate スキーマのエクスポート または LinqToSql CreateDatabase か何か)。次に、_dev および _next DB を使用して migrationscriptgenerator を実行すると、DB が作成されます。移行するための SQL 更新スクリプト。
コマンドラインを使用しています mysql-diff:2 つのデータベース スキーマ間の差異 (ライブ DB またはスクリプトから) を ALTER スクリプトとして出力します。mysql-diff はアプリケーションの起動時に実行され、スキーマが変更された場合は開発者に報告します。そのため、開発者は ALTER を手動で記述する必要がなく、スキーマの更新は半自動的に行われます。
Oracle データベースには使用します oracle-ddl2svn ツール。
次の工程を自動化するツールです
- すべての DB スキームに対してスキーム DDL を取得します
- バージョンコントロールの下に置きます
インスタンス間の変更は手動で解決されました