Sql-Server

為 SQL Server 中的所有連接設置 ARITHABORT ON 的後果是什麼?

  • June 5, 2019

所以我確定我的 SQL Server 的不穩定行為是因為 .Net SqlClient 數據提供程序的預設設置為SET ARITHABORT OFF. 話雖如此,我已經閱讀了各種討論實現這一點的最佳方式的文章。對我來說,我只想要一個簡單的方法,因為 SQL Server 正在受苦,而且我的查詢調整還沒有完全超越應用程序(顯然SET在 sp 中添加不起作用)。

在 Erland Sommarskog 關於該主題的精彩文章中,他基本上建議採取安全的方法,通過更改應用程序來發出SET ARITHABORT ON連接。但是,在來自 dba.stackexchange question的這個答案中,Solomon Rutzky 提供了實例範圍和數據庫範圍的方法。

在此實例範圍內設置我在這裡遺漏了什麼後果?正如我所看到的……因為SSMS預設設置了這個,我認為為所有連接設置這個伺服器範圍ON沒有什麼害處。ON歸根結底,我只需要這個 SQL Server 的執行高於一切。

存在一些預設值僅僅是因為沒有人真正知道更改它們會產生什麼影響。例如,在使用“美國英語”作為作業系統語言的系統上安裝時,預設的實例級排序規則是SQL_Latin1_General_CP1_CI_AS. 這是沒有意義的,因為SQL_*排序規則是為了兼容 SQL Server 2000 之前的版本。從 SQL Server 2000 開始,您實際上可以選擇 Windows 排序規則,因此美國英語系統的預設值應該更改為Latin1_General_CI_AS. 但是,我想微軟沒有人真正知道這將對所有各種潛在的子系統和系統儲存過程等產生什麼影響。

因此,我不知道將其設置為 ON 作為數據庫預設值甚至是實例範圍的任何特定負面影響。同時,我還沒有測試過。但即使我已經對其進行了測試,我可能仍然不會使用與您的應用程序相同的程式碼路徑,所以這是您真正需要在您的環境中測試的東西。將其設置為ON在您的開發和 QA 環境中的實例級別,看看它是如何工作的一兩個月。然後在 Staging / 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 .

(the^是 DOS 行繼續符;.最後一行的 the 只是強制多行,以便於複製和粘貼)

在 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,因此它們接受預設設置

我建議更改實例範圍的預設連接選項(如上所示)。這將比更新應用程序不那麼突兀。如果您發現更改實例範圍的設置有問題,我只會更新應用程序。

PS我做了一個簡單的測試,改變tempdb而不改變實例範圍的設置,它似乎沒有用*。*

引用自:https://dba.stackexchange.com/questions/237860