web-dev-qa-db-ja.com

DACPACとデータベースのドリフト:何も変更されていなくても、dbユーザーは常にドリフトとして検出されます

SSDT DBプロジェクトにログインとユーザーを含め、「データベースが登録済みバージョンからドリフトしたときにパブリッシュをブロックする」オプションを使用してDACPACをデプロイしようとすると、何も変更されていなくても、常にデータベースユーザーのドリフトが検出されます。

たとえば、以前はデータベースが存在せず、すべてが正常に機能する新しいサーバーにプロジェクトを公開します。ログインとユーザーが適切に作成された、などです。次に、同じプロジェクトを同じサーバーにすぐに公開します。dbユーザーが移動したため、展開はブロックされます。しかし、SQLインスタンスの変更やプロジェクトの更新は行っていません。

SSDTプロジェクトからログインとユーザーを削除すると、すべてが期待どおりに機能します。つまり、ドリフト検出から誤検知が発生せず、他のタイプのオブジェクトをエラーなしで更新してデプロイできます。

これは、ログインおよびユーザー用のスクリプトです。

CREATE LOGIN AppAcct WITH PASSWORD = 'Password1';
GO

CREATE USER AppAcct FOR LOGIN AppAcct
    WITH DEFAULT_SCHEMA = dbo;
GO

GRANT CONNECT TO AppAcct;
GO

そして、これは私が使用している公開プロファイルです:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <IncludeCompositeObjects>True</IncludeCompositeObjects>
    <TargetDatabaseName>DacpacDrift</TargetDatabaseName>
    <DeployScriptFileName>DacpacDrift.sql</DeployScriptFileName>
    <TargetConnectionString>Data Source=.\dev14;Integrated Security=True;Pooling=False</TargetConnectionString>
    <BlockWhenDriftDetected>True</BlockWhenDriftDetected>
    <RegisterDataTierApplication>True</RegisterDataTierApplication>
    <ProfileVersionNumber>1</ProfileVersionNumber>
    <ScriptDatabaseOptions>True</ScriptDatabaseOptions>
    <BlockOnPossibleDataLoss>True</BlockOnPossibleDataLoss>
    <DropObjectsNotInSource>True</DropObjectsNotInSource>
  </PropertyGroup>
</Project>

ドリフトレポートは次のようになります。

<?xml version="1.0" encoding="utf-8"?>
<DriftReport xmlns="http://schemas.Microsoft.com/sqlserver/dac/DriftReport/2012/02">
  <Additions />
  <Removals />
  <Modifications>
    <Object Name="[AppAcct]" Parent="" Type="SqlUser" />
  </Modifications>
</DriftReport>

この例ではSQL Server 2014をターゲットとするVisual Studio 2013を使用していますが、同じ問題が発生した他のバージョンのSQL Serverも入手しています。そして、私がVisual Studioから直接公開している場合は、それが違いを生みます。

これは、問題の根本的な原因を絞り込み、簡単に再現できるようにするために私が作成した不自然な例です。実際には、SQLログインには固定SIDとハッシュ化されたパスワードがあり、他のユーザーがドメインアカウントにマッピングされます。最終的には、ターゲットインスタンスごとに異なるセキュリティが必要になりますが、今のところ、一般的なログインとユーザーがプロジェクトの一部として機能するようにしておくことにします。

データベースのドリフトが発生する可能性が高い環境にいるので、本当の目標はドリフト検出を正しく機能させることです。プロジェクト外で(または展開前または展開後のスクリプトとして)アクセス許可を管理することはできますが、DACPAC展開でもドリフトとして扱われます。

私はデータ層アプリケーションに比較的慣れていないので、DACPACの展開を管理する方法を根本的に誤解している可能性は十分にありますが、ユーザーとログインをSSDT DBプロジェクトに追加しようとするまで、問題なく機能していました。

何が欠けていますか?

[〜#〜]更新[〜#〜]

私は @ dbajonmの提案 を試してみましたが、それでは自分がなりたい場所の約半分にしか到達できません。

ユーザーを削除してプロジェクトから適切にログインし、テストインスタンスのターゲットデータベースに手動で追加しました。最終的には、展開後のスクリプトでそれらを管理する必要がありますが、ここでは、ドリフトの問題を整理しようとしています。

ログインやユーザーなどを無視するように公開プロファイルを更新しました。少し試行錯誤した結果、プロファイルに次の新しい設定ができました。

<ExcludeUsers>True</ExcludeUsers>
<ExcludeLogins>True</ExcludeLogins>
<IgnorePermissions>True</IgnorePermissions>
<IgnoreRoleMembership>True</IgnoreRoleMembership>

さて、パブリッシュしようとすると、生成されたスクリプトでユーザーやその権限、ロールメンバーシップが削除されません。私が実際にそのDACPACを展開するのであれば、アクセス許可を壊すことはないので、それはそれに関しては良いことです。問題は、展開スクリプトで無視されたユーザーがデータベースのドリフトとして検出されるため、公開が引き続きブロックされることです。

つまり、私の質問の根本は、簡単に言えば:

  • プロジェクトにユーザーとログインをデプロイ可能なオブジェクトとして含めると(つまり、スクリプトのビルドアクション=ビルド)、変更されていなくても、常にドリフトとして検出されます。
  • プロジェクトにユーザーとログインを含めない場合、それらを手動でデプロイする(またはデプロイ後のスクリプトを使用する)必要があります。その場合それらは常にデータベースドリフトとして検出されます

私が何をしていても、データベースのドリフトのため、展開は常にブロックされているようです。これはおそらく正しいのでしょうか? データベースユーザーを含むデータベースのドリフトを確実に検出する方法は本当にありませんか(つまり、それらのほとんどすべて)?

とにかくドリフトを無視して公開できることは知っていますが、それではドリフトの検出が多かれ少なかれ役に立たなくなります。私は、データベースに対して直接開発するのではなく、データベースコードをバージョン管理にふさわしいファーストクラスの市民として扱うようにグループを導こうとしています。移行中は、SSDTの外部でデータベースの変更を行うようにします。ドリフト検出が私にとって非常に重要な理由です。ドリフト検出から常に誤検知が発生している場合、それは価値があるよりも面倒になります。

6
Matt

DACPACの外部のユーザーとログインを処理するには、次のオプションを設定します。これは、パブリッシュ構成ファイルまたはプロジェクト設定(両方のシナリオ)内にあります。

VSから:プロジェクトのプロパティ>デバッグ>詳細...>無視>除外されたオブジェクトタイプ。次に、「ログインの除外」、「ユーザーの除外」、データベースロールなどを確認します。公開/デプロイで比較するときに除外するものは何でもかまいません。

パブリッシュ構成ファイルから、以下を使用します

    <ExcludeUsers>True</ExcludeUsers>
    <ExcludeLogins>True</ExcludeLogins>

この除外オプションは設定内に埋め込まれています。ただし、このオプションは2014年まで利用できなかったため、オンプレミスのSQLデータベースに歯が食い込んでしまいました。少なくとも私たちはそれを今持っています!

Visual StudioとビルドサーバーのSSDTを最新に保つことが不可欠です。

1
dbajonm

データベースプロジェクトとDacPacsを使用するプロセスでは、DacPacsを使用して、継続的なメンテナンスとサポートの一環として変更される基本コンポーネント以外のものを展開しないことにしました。これは単なるテーブル、ビュー、ストアドプロシージャ、拡張プロパティ、ユーザー定義データとテーブルタイプ、スカラーとテーブル値関数です。

代わりに、開発チームとデータベースチームを含む協調的なアプローチによって、セキュリティとデータベースの設定を管理します。

もちろん、私たちはデータベースをゼロから頻繁に作成していて、セキュリティが非常に安定しており、頻繁に変更を加える必要はありませんが、セキュリティはプロジェクトに含まれています。最初にログインで発生したビルドエラーの問題を修正するために、Create Userオブジェクトを変更してパスワードを削除しました。

ログインなしでユーザー[user]を作成します。

これらのユーザーオブジェクトでドリフトが検出される問題はありませんでした。このアプローチを試して、問題が解決するかどうかを確認できます。

1
MikeZ