web-dev-qa-db-ja.com

sp_Blitzが照合エラーで失敗する

SQL Serverのバージョン(select @@ VERSIONからの出力):Microsoft SQL Server 2017(RTM-CU19)(KB4535007)-14.0.3281.6(X64)(ビルド14393:)

ブレントオザーからsp_Blitzをインストールしました。ストアドプロシージャは正常に作成されました。

コードからのバージョン情報:SELECT @Version = '7.93', @VersionDate = '20200217';

インスタンスには、照合SQL_Latin1_General_CP1_CI_ASの4つのシステムデータベースと、照合SQL_Latin1_General_CP1_CS_ASの2つのユーザーデータベースがあります。

sp_Blitzを実行しようとすると、次のようになります。

メッセージ468、レベル16、状態9、プロシージャsp_Blitz、行896 [バッチ開始行0]等しい操作で、 "SQL_Latin1_General_CP1_CS_AS"と "SQL_Latin1_General_CP1_CI_AS"の照合の競合を解決できません。

トラブルシューティングの支援に感謝します(私は主にレビューのためにSQL Serverを渡されたOracleの人で、これは最初から明らかなことの良い出発点になるかもしれないものとして覚えていました)。

4
SJWales

コメントからの解決策の追加:ストアドプロシージャは、大文字と小文字を区別するユーザーデータベースで作成され、大文字と小文字を区別するTempDBにコピーしようとしました。

大文字と小文字を区別するユーザーデータベースからsp_Blitzを削除し、それをマスターにインストールすると(システムデータベースの照合順序を反映します)、問題なく動作しました。

6
Brent Ozar

ベンダーの推奨される使用法に異議を唱えるものではありませんが、私が知る限り、「標準的な」条件下では、sp_BlitzをユーザーDBにインストールすると問題なく機能します、インスタンスとは異なる照合順序を持つものでも。照合不一致エラーが発生するような(典型的な)でないでしょうか?含まれているデータベースを使用する(「CONTAINMENT = PARTIAL」など)。このエラーは、含まれるDBでは、[tempdb]userデータ([tempdb]メタデータではなく)のデフォルトの照合が実際には含まれるDBのデフォルトであるために発生します照合(テーブル変数が常に機能する方法と同様)。

「一般的な」条件では、sp_Blitzに含まれる多くのクエリに次のWHERE述語が含まれます(dテーブルエイリアスはsys.databases用):

                    AND d.name NOT IN ( SELECT DISTINCT
                                              DatabaseName
                                        FROM  #SkipChecks
                                        WHERE CheckID IS NULL OR CheckID = 1)

sys.databases.nameはインスタンスレベルの照合と#SkipChecks.DatabaseNameを使用しているため、このストアドプロシージャがデータベースでインスタンスレベルの照合とは異なるデフォルトの照合を使用して作成されたとしても、正常に機能します。 CREATE TABLEステートメントのCOLLATE句)は、[tempdb]のデフォルトの照合を使用します。これは、時間の99.999%がインスタンスレベルの照合でもあることを意味します。

O.P.が受け取っていたエラーを再現する唯一の方法は、以下を実行することです。

EXEC sp_configure 'contained database authentication', 1;
RECONFIGURE;

ALTER DATABASE [{user_db_containing_spBlitz}] SET CONTAINMENT = PARTIAL;

ユーザーDBの照合順序がインスタンスとは異なる(したがって[tempdb]とは異なる)と仮定すると、実行時に次のエラーが発生しますsp_Blitz

メッセージ468、レベル16、状態9、手順dbo.sp_Blitz、行XXXXX [バッチ開始行YYYYY]
等号演算での「{contained_db_default_collat​​ion}」と「{instance_collat​​ion}」の照合の競合を解決できません。

繰り返しになりますが、ベンダー(ブレントなど)がこのストアドプロシージャを[master]にインストールすることを意図していると述べている場合は、おそらく推奨事項に従うのが最善です。それは自明ではない振る舞いなので、実際に何が起こっていたかを説明しているだけです。

ALSO、これは、インスタンスレベルの照合が何であっても動的に置き換えられる特別な照合名から本当に恩恵を受ける別のケースです。これまでのところ、データベースの照合順序であるDATABASE_DEFAULTがあり、その照合順序に関係なく、含まれているDBを支援することを目的としたCATALOG_DEFAULTがあります(ただし、この場合は役に立ちません)。インスタンスレベルを表すものではありません。 sp_Blitz、Ola HallengrenのDBメンテナンススクリプトなど、インスタンス全体を操作することを目的とした汎用スクリプトおよび特定のシステムにコード化されておらず、必然的にこの問題に遭遇し、それを機能させるために不必要な譲歩をしなければならないでしょう。したがって、この状況を修正するために私の次の提案に投票してください:

COLLATE DATABASE_DEFAULTのように機能するように特別な照合順序INSTANCE_DEFAULTを追加しますが、インスタンスのデフォルトの照合順序を使用します

一時テーブルを[DatabaseName] sysname COLLATE INSTANCE_DEFAULTで作成できる場合、このコードは、どのDBが配置されていても、含まれていてもいなくても、常に機能します。機能するだけです。

3
Solomon Rutzky