したがって、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を実行する必要があります。
デフォルトを変更することによる影響が誰にもわからないというだけの理由で、デフォルトがいくつか存在します。たとえば、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'
はビットマスクされた値です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());
}
}
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;
SQLCMDは次を返します:
master: 64 (ODBC)
LINQPadは次を返します:
tempdb: 64 (.Net SqlClient Data Provider)
とすれば:
ARITHABORT OFF
を使用してもメリットはないようですARITHABORT ON
を持っていることには利点がありますOFF
ARITHABORT
を設定しようとするように見えないため、デフォルト設定を受け入れます(上記のように)インスタンス全体のデフォルト接続オプションを変更することをお勧めします。これは、アプリケーションの更新よりも邪魔になりません。私はアプリのみを更新しますifインスタンス全体の設定の変更で問題が見つかりました。
追伸tempdb
とnotを変更してインスタンス全体の設定を変更する簡単なテストを行いましたが、うまくいかなかったようです。