まず第一に、DB のアップグレードは悪ですが、そのブログでは完全な悪夢について説明しています。
アップグレード アプローチに基づいてプログラマー コンピテンシー マトリックスを作成できます。
- レベル 0: アップグレードは一切ありません。顧客はおびえ、アプリケーションによって提供される UI またはサードパーティの DB 管理ソリューションを使用してデータを手動で移動します (信じてください、それは実際に可能です)。
- レベル 1: DB ダンプをアップグレードするスクリプトがあります。顧客は安全だと感じていますが、今後 1 ~ 2 年間は些細で非常に苛立たしい問題を解決してくれます。システムは機能していますが、変更は許可されていません。
- レベル 2: テーブルの変更。特にアップグレード中に問題が発生した場合は、途方もないダウンタイムが発生します。大きな問題があり、100% 安全な結果が得られる保証は事実上ありません。データ変換は、バグのあるスクリプトによって管理されます。顧客は満足していません。
- レベル 3: スキーマのない設計: バグのあるスクリプトが DB の構成を変換できるようにするための 1 ~ 2 時間のダウンタイム (多くの場合、このステップは DB を損傷する可能性があります)。サポート担当者は、すべてのコーヒー備蓄を完全に使い果たしました。
- レベル 4: レイジーで透過的なアップグレード: ダウンタイムはありませんが、いくつかの問題が発生する可能性があります。顧客はほぼ満足していますが、以前の経験を覚えています。
- レベル 5: 理想的なアーキテクチャであり、明示的なアップグレードは必要ありません。完全な幸福。顧客は、アップグレード手順が何であるかを知りません。開発者は生産的で落ち着いています。
すべての技術的な問題について説明しますが、その前に次のことを述べさせてください (かなり長い回答をお許しください)。
- 現在、開発サイクルは非常に圧縮されており、DB は巨大です
- ほぼすべての機能がスキームの変更を導入し、互換性を損なう可能性があるため、シンプルで安定したアップグレード手順を用意するか、機能を延期する可能性があります
- 問題が顧客によって特定される可能性があるため、いくつかのアップグレード手順が必要な緊急のホットフィックス ビルドが必要になる可能性があります。
- 一般的に言えば、あなたとあなたの顧客との間の障壁を避ける方がはるかに良いです
レベル 0 とレベル 1
どちらの場合も明白でばかげています。誰でもそれを避けるべきです。
レベル 2
変更は小さなテーブルではそれほど悪くありませんが、大きなテーブルでは問題になる可能性があります。非常に大きなテーブル (>1Gb) では、ALTER TABLE が完了するまでに数時間または数日かかる場合があります。さらに、スキーマのアップグレードの問題のみが解決されますが、保存されたデータはどうなりますか? また、このアプローチの背後にある実際の障害を理解するために、物理的なデータ レイアウトについて検討することをお勧めします。手順全体が安全ではない可能性があるため、バックアップがあることを確認してください。
ソリューション:
レベル 3
スキーマのアップグレードの問題は、スキーマを上位層に移動することで解決されます。スキーマレス ソリューションは、主にリレーショナル モデルの背後にあるすべての機能を無効にするため、多少制限があります。高速アップグレードとリレーショナル代数を使用する機能の両方を備えたハイブリッド アプローチを提案できます。いくつかの興味深い記事があります:
アップグレード手順の複雑さは依然として存在し、アプリケーション レベルに移動しただけであることに注意してください。関連するシナリオは多数ありますが、ここでは、私が数年間使用してきた 1 つのハイブリッド システムについて説明します。データモデルを「関係を持つエンティティ」と表現できます。エンティティ間の関係は DB レベルで表現され、エンティティ自体は XML BLOB として格納されていました。
このシステムは成熟しており、十分な数の顧客を抱えていました。多くの機能リクエストがあったため、R&D チームと QA チームは少しストレスを感じていました。最初のアップグレード手順は、DB から XML BLOB を読み取り、DOM API を使用してアップグレードし、DB に書き戻すスタンドアロンの Java アプリケーションとして実装されていました。実際のアプローチは非常に簡単に見えますが、背後にはいくつかの隠れた問題があります。
- アップグレード ロジックには多少のバグがある可能性があるため、間違った XML データを書き込む可能性があり、顧客のダウンタイムが大幅に増加します。
- 1 ~ 2 GB の XML の読み取り、変換、書き込みには時間がかかる場合があります。
- アップグレード手順のすべてのステップは、自動化されたテストでカバーする必要があります (CI は必須です)。
- 隠れた不具合は 1 日か 2 日で見つかる可能性があるため、新しいデータが挿入されるため、バックアップは役に立ちません。
- ビルド間のアップグレードが必要な場合は特に、アップグレード コードが少し面倒になる可能性があります (アジャイル チームの通常の要件)。
より厳密なアップグレード手順の定義、検証ルール、および実際のデータ (すべての顧客から収集された) に対して CI システムによって実行される広範なテストを使用して、すべての潜在的なリスクを軽減しようとしました。古いアップグレード スクリプトによってずっと前に導入された古い問題が原因で、いくつかの手順が失敗するのを見て驚きました。その隠れた問題を修正するために、個別のアップグレード手順が開発されました。アップグレード時間を合理的な 20 ~ 30 分に短縮するために、いくつかの最適化も実行されました。コンソールベースのプログレスバーの実装が残りを行いました。
簡単な注意: エンドユーザーは、実行時間の長い (> 2 分) 操作の進行状況を確認したいと考えています。そんな「楽しみ」を忘れずに実装してください。
当初、DB バージョンは別のテーブルに格納されていました。このアプローチは使用しないでください。エンティティを個別にバージョン管理し、アップグレード中に DB 全体がロックされるのを回避する方がはるかに優れています。
例として 1 つのアップグレード手順を示します (すべての検証および検証手順は処理ロジックの背後<build/>
に隠されています)。<version/>
「-」は少ないことを意味し、「*」は任意のビルドを意味します
<?xml version="1.0"?>
<upgrade>
<version name="-7.4">
<build name="*">
<script class="upgrade.version7.Replace...Script"/>
<script class="upgrade.version7.Update...Script"/>
<!-- 5 scripts skipped -->
</build>
</version>
<version name="-7.6">
<build name="*">
<script class="core.DatabaseUpdateVersion" version="7.6.48"/>
</build>
</version>
<version name="7.6">
<build name="*">
<script class="upgrade.version7.Update...Script"/>
<script class="core.DatabaseUpdateVersion" version="8.0.40"/>
<!-- 7 scripts skipped -->
</build>
</version>
<version name="8.0">
<build name="-53">... </build>
<build name="+52">... </build>
</version>
<version name="8.1">
<build name="-8"> ... </build>
<build name="-9">...</build>
<build name="-26">...</build>
<build name="-40">...</build>
<build name="-45">...</build>
<build name="-56">...</build>
<build name="-61">...</build>
<build name="-63">...</build>
<build name="-64">...</build>
<build name="-68">...</build>
<build name="-69">...</build>
<build name="-77">...</build>
<build name="-79">...</build>
<build name="-80">...</build>
<build name="-86">...</build>
<build name="-88">...</build>
<build name="-89"> ... </build>
</version>
<version name="8.2">...</version>
</upgrade>
各スクリプトは小さな Java または Groovy の実装です (XSLT も使用されました)。その後、ダウングレード手順も開発されましたが、これはまったく別の話です。
アプリケーション層のレベル 4
データ スキームにより、非常に多くの興味深いことが可能になります。たとえば、XML をprotobufに置き換えることができます。いつものように、これを行うにはいくつかの理由があります (より簡単である、より高速であるなど)。ビルダーの概念が気に入らない場合は、代わりに倹約を使用できます。
とにかく、protobuf を使用すると、(格納されたデータに関して) 下位互換性のあるシステムをほとんど問題なく作成できます。ところで、良い利点。システムに下位互換性があるため、遅延型で完全に透過的なアップグレードを簡単に実装できます。これは、バックグラウンド プロセスまたはリクエストに応じたアップグレードなどの場合があります。幸いなことに、ダウンタイムがなく、ユーザーは満足しており、アップグレードをより頻繁に行うことができます。つまり、迅速に開発し、顧客の要求に迅速に対応し、より多くの成功を収めることができます。
レベル 5
申し訳ありませんが、今回はありません。アップグレード戦略には注意してください。いくつかのスキーマが定義されたシステムを販売し、自分自身をロックアウトするのは非常に簡単です。新機能なし -- 顧客なし。
シンプルだが非常に便利なチェックリスト:
- お客様から寄せられた問題を迅速に解決できますか?
- お客様がシステムをアップグレードしても安全ですか (少なくともミッション クリティカルな場合)?
- 問題を特定するのにどれくらいの時間が必要ですか?
- 自動検証はありますか?
読んでくれてありがとう。