web-dev-qa-db-ja.com

SQL Serverのすべての接続でARITHABORTをONに設定すると、どのような影響がありますか?

したがって、SQLサーバーの不安定な動作は.Net SqlClientデータプロバイダーのデフォルト設定SET ARITHABORT OFFが原因であると判断しました。そうは言っても、これを実装する最良の方法を議論するさまざまな記事を読んだことがあります。私にとっては、SQL Serverに問題があり、クエリチューニングがアプリ全体で完全に超越していない(そして、spにSETを追加しても機能しない)ため、簡単な方法が欲しいだけです。

Erland Sommarskogの見事な article に関するトピックでは、基本的にはアプリを変更して接続にSET ARITHABORT ONを発行することで安全なアプローチを取ることを提案しています。ただし、dba.stackexchange question からのこの回答では、Solomon Rutzkyがインスタンス全体とデータベース全体の両方のアプローチを提供しています。

これをインスタンス全体に設定すると、どのような影響がありますか?ご覧のとおり、SSMSにはデフォルトでONが設定されているため、すべての接続でサーバー全体にこのONを設定しても問題はありません。結局のところ、何よりもこのSQL Serverを実行する必要があります。

10
Eric Swiggum

デフォルトを変更することによる影響が誰にもわからないというだけの理由で、デフォルトがいくつか存在します。たとえば、OS言語として「米国英語」を使用するシステムにインストールする場合のデフォルトのインスタンスレベルの照合はSQL_Latin1_General_CP1_CI_ASです。 SQL_*照合はSQL Server 2000以前の互換性のためのものであるため、これは意味がありません。 SQL Server 2000以降では、実際にWindows照合を選択できるため、米国英語システムのデフォルトすべきLatin1_General_CI_ASに変更されました。しかし、Microsoftの誰もが、さまざまな潜在的なサブシステムやシステムストアドプロシージャなどのすべてにどのような影響があるかを本当に知っているとは思いません。

そのため、データベースのデフォルトとして、またはインスタンス全体でONに設定したことによる特定の悪影響については知りません。同時に、私はそれをテストしていません。しかし、それをテストしたとしても、アプリケーションと同じコードパスをまだ使用していない可能性があるため、これは実際に環境でテストする必要があるものです。開発環境とQA環境のインスタンスレベルでONに設定し、1〜2か月間どのように機能するかを確認します。次に、ステージング/ UATで有効にします。すべてが数週間うまく機能し続ける場合は、その構成の変更を本番環境にロールします。重要なのは、毎日ヒットしないさまざまなコードパスをテストするために、できるだけ多くの時間を与えることです。一部は、毎週または数か月または毎年ヒットします。一部のコードパスは、サポート、または誰かが何年も前に作成し、ユーザーに通知せずにランダムな間隔でのみ使用されるアドホックレポートまたはメンテナンス手順によってのみヒットします(いや、決して発生しません;-)。

それで、私は一度も変更したことがないので、デフォルトの「ユーザーオプション」設定がまだあるインスタンスでいくつかのテストを行いました。

ご注意ください:

  • @@OPTIONS/'user options'はビットマスクされた値です
  • 64はARITHABORT ONのビットです

セットアップ

SQLCMD(ODBCを使用)とLINQPad(.NET SqlClientを使用)の両方でテストしました。

SQLCMD -W -S (local) ^
-Q"SELECT CONCAT(DB_NAME(), N': ', @@OPTIONS & 64, N' (', ses.[client_interface_name], N')') FROM sys.dm_exec_sessions ses WHERE ses.[session_id] = @@SPID;"
echo .

^はDOS行の継続文字です。最後の行の.は、余分な行を強制的にコピーして貼り付けやすくするためのものです)

LINQPadでは:

using (SqlConnection connection =
    new SqlConnection(@"Server=(local);Trusted_Connection=true;Database=tempdb;"))
{
  using (SqlCommand command = connection.CreateCommand())
  {
    command.CommandText = @"SELECT @RetVal =
CONCAT(DB_NAME(), N': ', @@OPTIONS & 64, N' (', ses.[client_interface_name], N')')
FROM  sys.dm_exec_sessions ses
WHERE ses.[session_id] = @@SPID;";
    SqlParameter paramRetVal = new SqlParameter("@RetVal", SqlDbType.NVarChar, 500);
    paramRetVal.Direction = ParameterDirection.Output;
    command.Parameters.Add(paramRetVal);

    connection.Open();
    command.ExecuteNonQuery();

    Console.WriteLine(paramRetVal.Value.ToString());
  }
}

テスト1:前

SQLCMDは次を返します:

master: 0 (ODBC)

LINQPadは次を返します:

tempdb: 0 (.Net SqlClient Data Provider)

デフォルトの接続オプションの変更:

次のT-SQLは、設定されている可能性のある他のオプションを削除せずにARITHABORTを有効にし、ARITHABORTがビットマスク値にすでに設定されている場合は何も変更しません。

DECLARE @UserOptions INT;

-- Get current bitmasked value and ensure ARITHABORT is enabled:
SELECT @UserOptions = CONVERT(INT, cnf.[value_in_use]) | 64 -- enable "ARITHABORT"
FROM   sys.configurations cnf
WHERE  cnf.[configuration_id] = 1534 -- user options

-- Apply new default connection options:
EXEC sys.sp_configure N'user options', @UserOptions;
RECONFIGURE;

テスト2:後

SQLCMDは次を返します:

master: 64 (ODBC)

LINQPadは次を返します:

tempdb: 64 (.Net SqlClient Data Provider)

結論

とすれば:

  1. ARITHABORT OFFを使用してもメリットはないようです
  2. ARITHABORT ONを持っていることには利点があります
  3. デフォルトの接続設定(接続によってオーバーライドされない限り)= OFF
  4. ODBCまたはOLEDB/.NET SqlClientがARITHABORTを設定しようとするように見えないため、デフォルト設定を受け入れます

(上記のように)インスタンス全体のデフォルト接続オプションを変更することをお勧めします。これは、アプリケーションの更新よりも邪魔になりません。私はアプリのみを更新しますifインスタンス全体の設定の変更で問題が見つかりました。

追伸tempdbnotを変更してインスタンス全体の設定を変更する簡単なテストを行いましたが、うまくいかなかったようです。

11
Solomon Rutzky