web-dev-qa-db-ja.com

バックアップを取得してSQL Serverデータベースを運用サーバーに展開することに問題はありますか?

これは少し説明の多い質問ですが、説明したシナリオは間違っているとすでに想定しています。

DBAは、私が作成したMS SQL Server 2008データベースを含むアプリケーションを配備しています。開発マシンからデータベースのバックアップをとって、運用サーバーに復元して展開できるようにするように頼まれました。これはグリーンフィールドデプロイメントであるため、移行する既存のデータはありません。私は、DDLスクリプトを提供することを期待していました。これを入念にテストし、必要なすべてが含まれていることを確認しました。 SSMSで実行すると、ワンクリックでデータベースが作成されます。

私にとって、展開にバックアップ機能を使用することは適切ではないように思われますが、SQLサーバーの専門家であることがなければ、それを行わない確実な理由は考えられません。たとえば、開発マシンからのデータベースの「汚染」があると思いました。おそらく、どこかに格納されているコンピュータ名、ディレクトリ構造、またはユーザー名です。これは事実ですか、それともバックアップと復元は有効な導入手法ですか?

7
Stephen Hewlett

デプロイメントとしてバックアップファイルを使用すると、すべてがうまくいきません。しかし、DDLを提供するのはDBAの負担ではなく、開発です。設計および開発の成果物は、データベースのインストールおよびアップグレードスクリプトである必要があります。データベースの内容を手動で変更しないでください。アプリを使用してすべてを変更する必要があります。 Railsインフラストラクチャ全体でこれをスペードで取得します migrations インフラストラクチャとそれを採用するようにしてください。同様の手法を使用して長い間提唱してきましたが、 Versionコントロールとデータベース

最初に、ソースコードベースのデプロイメント/アップグレードがバイナリベースのデプロイメント(.bakまたはdiffツール)よりも優れている理由を説明します。

  • ソースコードをソース管理にチェックインできます。これだけで議論全体が解決するはずです。ソース管理は、あなたに履歴を与えます。将来は、ノートのチェックを振り返って読んで、現在の状態の背後にある理由を理解することができます。
  • ソースコードを一目ですばやく検査できます。あなたはそれを見てそれを読みます。バイナリデータベースを接続する必要があり、基本的なプロパティさえ読み取るためにメタデータカタログの広範な知識が必要です
  • ソースコードはきれいです。 CREATE TABLE Foo (...)を見ると、意図が明確に伝わっています。バイナリ配布では、オブジェクトを抽出したい場合、大量のデフォルトプロパティが表示されます。あなたは元の意図を失います。
  • チェックイン時にソースコードをピアレビューできます。
  • ソースコードは連続した配置に統合されます

また、バックアップによる展開が悪い(非常に悪い)理由についても説明します。

  • あなただけの問題を延期しました。アプリの最初の更新では、データを失うことなく更新を展開するという問題に直面します。これは、デプロイの翌日、本番環境で問題に気づいたときに発生する可能性があり、開発DBに一致するように本番DBを変更するにはどうすればよいでしょうか。
  • データベースは自己完結型ではありません。展開では、DBの外部にあるオブジェクト(ログイン、SQLエージェントジョブ、メンテナンスプランなど)が呼び出されますが、バックアップでは展開できません。
  • 何をデプロイしたかは決してわかりません。開発中に残った忘れられたテーブル?テストデータ?データベースをクリーンアップするのは非常に困難ですが、ソースコードを最新かつ正しい状態に保つことは自然なことです。
10
Remus Rusanu

いいえ、initialデプロイメントのバックアップを使用することに問題はありません。実際、これが最も安全であると言えるでしょう。それを行う方法。本番環境とテスト環境で異なるサーバー名やデータベース名などのハードコーディングされたものがない限り、実際に発生する可能性のある「汚染」はありません。

ただし、バックアップ/復元(データベースに制限された独自のDDLスクリプトのように)では、サーバーレベルのログイン、リンクサーバー、SQLエージェントジョブなどは提供されません。

たとえば、次のように元のテーブルを作成した場合、DDLスクリプトでは必ずしも得られないバックアップで得られるいくつかの他の利点があります。

CREATE TABLE dbo.foo
(
  bar INT PRIMARY KEY,
  mort INT FOREIGN KEY REFERENCES dbo.mort(MortID),
  x TINYINT CHECK (x IN (1,2)),
  y INT NOT NULL DEFAULT 1
);

これらの制約はすべて、PK__foo__DE90ECFFA28BBAB8のようなシステム生成の名前を持っています。本番環境でこの同じスクリプトを実行すると、テスト環境から正確なテーブル定義をスクリプト化しない限り、名前は異なります。テストからドロップ/作成/変更スクリプトを生成し、それらを本番環境で実行する必要がある場合、これは後で問題を引き起こす可能性があります。

バックアップを取得すると、ルックアップテーブルなどのすべてのデータも取得されます。バックアップを手動で作成して、そのデータを実稼働環境に取り込む必要があります。 (ただし、本番環境でしたくないテストデータもすべて消去する必要があります。)

そして、これを自分でスクリプト化する弱点は、すべてのオブジェクトが正しい依存関係の順序で作成されていることを確認する必要があることです。オブジェクトが正しい順序で生成されなかったため、テストで配置されている依存関係が本番環境にはない場合があります。

つまり、バックアップはよりクリーンです。また、データベースを展開するときにテストする必要があるため、「汚染」をすばやく見つけ、両方の環境で修正する必要があります。

データベースが最初にデプロイされた後、明らかに変更を後でデプロイする唯一の方法は、それらをスクリプト化することです。 Red-GateのSQL Compareを使用して比較/デプロイスクリプトを生成するのは、とても幸運です。 Remusは完全に正しいですが、そのソース管理はこれに対する最良の解決策ですが、実際には、ソース管理は通常、CREATE TABLEスクリプトを格納します。別の列のデータ型-テーブルを削除して再作成するのではなく、変更のみをプロダクションに適用するある種のdiffスクリプトを構築する必要があります。

他のデータベースにある、または別のサーバーにある可能性があるローカルルックアップテーブルのようなものがある場合は、コードにそれらの名前をハードコーディングする代わりに、同義語を使用する必要があります。そうすれば、すべてのモジュールで3つまたは4つの部分の名前をすべて見つけてデプロイメント時に更新するのではなく、同義語が各環境で正しいことを確認するだけで済みます。また、環境間で異なるローカルファイルパスがある場合は、それらのパスをプロシージャなどにハードコーディングするのではなく、中央のプロパティテーブルを使用してください。

理論的には、後でバックアップと復元の方法を使用することもできますが、運用データベースが既に使用されている場合は適切に機能しません。テストからデータベースを復元し、運用で収集されたデータを失わないようにするのは少し難しいです。 。

5
Aaron Bertrand

これに対する答えはイエスとノーの両方だと思います。あなたが言った:

これはグリーンフィールドデプロイメントであるため、移行する既存のデータはありません。

これが初期展開である場合、本番環境で使用する開発データベースのバックアップをとっても問題はありません。つまり、あなた(またはうまくいけばDBA)は明らかにデータベースをクレンジングし、データベースバックアップで復元された可能性のあるセキュリティユーザーやその他の問題を削除する必要があります。

ただし:

長期的なソリューションとしては、いいえ。クライアントがデータベースの使用を開始すると、クライアントはそこにデータを保持するため、データベースを復元することができないため、これは良い展開手法ではありません。

したがって、最初の展開に戻って、空のデータベースのバックアップを復元しても問題ありませんが、この時点で、バージョン管理を使用して更新と将来の展開を管理し、展開可能なデータベースのクリーンなバージョンを維持します。

手順:

  1. クリーンなデータベースを作成します(必要に応じてバックアップから復元します)
  2. この時点でバージョン管理
  3. データベースの更新をスクリプト化し、それらをバージョン管理する
  4. 新しいバージョン/リリースをデプロイする準備ができたら、クリーンなデータベースに対して新しいスクリプトを実行して、バージョンXからバージョンYに取得し、ソース管理にあるバージョンを更新します。
  5. 最後に、クライアントデータベースに対してスクリプトを実行して更新します。

データベースに加えた更新は、展開前にローカルでテストされ、クライアントデータベースの更新は、あるバージョンから別のバージョンに更新するスクリプトを実行する場合にすぎません。ソース管理は、適用されたスクリプトと共に、データベースのクリーンバージョン間の履歴を提供します。

2
Tanner

私はそれをしないと言います。可能な限り標準的なステートメントから作成されたSQLスクリプトを使用し、そのバージョンのスクリプトが機能したSQLサーバーのバージョンをメモします。

後日ソフトウェアの再インストールを行う必要があるときに、バックアップを介して配布されたソフトウェアに問題がありました。

展開に使用された元のバックアップイメージは古く、利用可能な新しいイメージがないため、新しいバージョンのSQL Serverは古い形式のバックアップをサポートしていなかったため、古いバージョンのSQLサーバーを使用する必要がありました。次に、ほぼすべてのアプリケーション更新を順番に適用するプロセスで、元のバージョンで必要だったよりも新しいSQLサーバーバージョンが必要なアプリケーション更新のために、SQLサーバーのアップグレードを古いSQLサーバーバージョンの上に適用する必要がありました。 「展開バックアップ」イメージ。

DBAとして、私はこれを理解して実際に必要な手順を実行するのは非常にイライラするものだと感じました。追加のボーナスとして、災害復旧時にこれを実行していたため、元の「デプロイメントバックアップ」をインストールしないとインストールできない最新バージョンのソフトウェアが必要だったため、バックアップから現在の本番データベースを復元できました。

2
BeowulfNode42