誤ってデータベース構造の Habraiser Shedal バージョン 移行のトピックに遭遇しました:基本的なアプローチ 。 詳細なコメントを書きたかったのですが、後者の作成日を見て、別のトピックを発行することにしました。
このトピックの目的は、データベースのバージョン管理のアプローチを確認することではありません-上記のリンクの記事で顕著に行われています-何らかの理由で私たちに合わなかったアプローチについては簡単なIMHOしかありません。
このトピックは、主にデータベースの移行と学習ツールに注目している開発者にとって興味深いものです。 長い間システムや技術を使用していて、それらに満足している場合、おそらくここで新しいことを学ぶことはないでしょう。
問題の声明
Kohanaフレームワークを使用して、PHP + MySQLで開発しています。 テストサーバーと運用環境への展開を何らかの形で自動化するために、データベース構造の移行プロセスを何らかの形で整理する必要がありました。 シンプルな名刺サイトだけでなく、非常に複雑なプロジェクトも作成します。 主なプロジェクトの大部分はそれほど大きくありません(データベース内に15〜30個のテーブル、50〜200人時)。 以下に書かれていることはすべて真実ですが、より複雑なプロジェクトや他のテクノロジー/フレームワークに適合しない可能性があります(多くのフレームワークにはデータベース移行の独自の実装があるため、もちろん他のバイクを使用しても意味がありません)
データベースの構造をソースコードと比較する方法
データベーススキーマ全体がバージョン管理システムに保存され、データベースを最新バージョンに移行するために、元のデータベースを最後のデータベースに変換するdiffスクリプトが生成されます。 理論的にはすべて問題ありませんが、実際には問題があります。
- 既存のツールは、この問題を常に(理論的にも)自動的に解決できるわけではありません。 最も単純な例は、列またはテーブルの名前を変更することです。
- 私は個人的に、プロダクション用のALTERスクリプトを生成するプログラムを信頼しません。つまり、使用する前に、手でそれらを表示/編集する必要があります。
いくつかのツールを試し、このオプションを放棄しました。
増分変更方法
いくつかのオプションがあります:手書きのALTERスクリプトを保存するか、PHP(またはアプリケーションを作成するもの)で記述します。 真空中でのこのような球状の移動の例:
class Migration_0001 extends Migration_Abstract { public function up() { $this->createTable("users") ->column("id", self::PK) ->column("username", self::VARCHAR); } public function down() { $this->dropTable("users"); } }
一般的に、かなり良いオプションです。 私の知る限り、これはDoctrineおよび他のフレームワークで実装されています。 反対の言葉:結局のところ、これはシステムの不必要な複雑さによって常に正当化されるとは限りません。 使用しなかった理由-箱から出して、Kohanaはこれらの移行をサポートしていません。これにもDoctrineを使用したくありません。 これは私たちのプロジェクトにも当てはまります。 あなたとすべてが異なる場合があります。
SQLでALTERスクリプトを手動で記述するとき、これが最も便利な方法のように思われました。 このミサのツールと技術者、上部のリンクのトピックにあるそれらへのリンク。 それらはすべて優れていますが、変更をローリングするためのすべての機能が複数の行に収まるようにシステムを簡素化することを決定し、このために既製のツールを使用する必要はありませんでした。
私たちの決定
まず、ロールバックの可能性を拒否します。 私は個人的には、ほとんどの場合、このオプションはまったく必要ないと考えており、多くの質問があります。 次に、移行スクリプト、その番号、およびデータベースの個別のバージョン番号の命名規則を廃止します。
すべてのデータベースの変更は、1つのフォルダー内の個別の.sqlファイル(多くの場合、デルタと呼ばれます)に保存されます。 変更はアルファベット順にロールされます。 適用されたデルタは、変更ログプレート(別の「初期」SQLダンプからロードされる)に保存されます。 移行時には、すべての未使用のデルタが適用されます。 それだけです デルタのあるフォルダーの例:
deltas
|- 0001-users.sql
|- 0002-users-add-username.sql
'- 0003-users-drop-last-login.sql
この移行システムを処理するコードは非常にシンプルで、どこにでも記述して埋め込むことができます。 たとえば、phingを使用します。 単純なphpファイルで十分です。
デルタスクリプトのエンドツーエンドの番号付けのルールが存在しないことにより、このアプローチの主な問題であるリポジトリの異なるブランチでの並行開発が奇跡的に解決されます。 説明します。
上記のように、トランクに3つのデルタがあるとします。 Vasyaはブランチを作成します。たとえば、チェックボックス「remember me」を追加するために、Petyaはこの時点でトランクのマイナーなバグを修正し続けます。 Vasyaはデルタ0004-user-tokens.sqlを追加し、Petyaはデルタ0004-users-change-username-length.sqlおよび0005-users-add-email.sqlを追加します 。 わかった マージ後、トランクの「番号」0004の下に2つのデルタがありますが、番号は重要ではありません。適用されないものすべてを適用するため、Vasyaの変更はペティアのトランクのベースに問題なく適用されます。
もちろん、テーブルの同じ列を変更しているときに競合が発生する可能性がありますが、この状況は非常にまれです。