为SQL Server中的所有连接设置ARITHABORT ON的后果是什么?


10

因此,我确定SQL Server的行为不稳定是由于.Net SqlClient数据提供程序的默认设置为SET ARITHABORT OFF。话虽如此,我已经阅读了各种文章,讨论了实现此目标的最佳方法。对我来说,我只想采用一种简单的方法,因为SQL Server遭受了麻烦,而且我的查询调优还没有完全跨应用程序(显然,SET在sp中添加不能正常工作)。

在Erland Sommarskog 关于该主题的精彩文章中,他基本上建议通过更改要SET ARITHABORT ON为连接发布的应用程序来采用安全的方法。但是,在dba.stackexchange 问题的此答案中,Solomon Rutzky 提供了实例范围和数据库范围的方法。

在此设置整个实例范围时,我在这里缺少什么后果?正如我所看到的...由于SSMS ON默认情况下已设置了此设置,所以我认为在ON所有服务器范围内都设置此服务器范围没有什么害处。归根结底,我只需要此SQL Server才能执行最重要的任务。


阅读了您在问题中链接的大部分答案后,现在似乎默认情况下它处于关闭状态,某些客户端专门将其打开,但是EF / SqlClient并未触摸它,这意味着它保持为关闭状态。
所罗门·鲁兹基

1
没有EF,但是您对EF如何覆盖实例范围的设置提出了一个有趣的观点。因此,如果连接可以替代此设置,则显然,最可行的方法是从建立到SQL Server的连接中(如果有可能的话)...
Eric Swiggum

1
“始终在登录会话中将ARITHABORT设置为ON。将ARITHABORT设置为OFF会对查询优化产生负面影响,从而导致性能问题。” 这篇文章从微软称:docs.microsoft.com/en-us/sql/t-sql/statements/...
Shiwangini Shishulkar

我已经测试了各种场景,最后我得出的结论是,此设置和参数嗅探是同伴。如果有ARITHABORT OFF,那就很好。对于所有传入连接,请保持关闭状态。(祝你好运)。但是,当进入连接并将其设置为ON时,SQL会生成一个新的查询计划,这可能会影响性能。我的看法是,在实例级别将其设置为默认用户选项,然后相应地调整查询。
Eric Swiggum

Answers:


11

存在一些默认值仅仅是因为没有人真正知道更改它们的后果。例如,在使用“美国英语”作为操作系统语言的系统上安装时,默认的实例级排序规则为SQL_Latin1_General_CP1_CI_AS。这是没有意义的,因为SQL_*归类是针对SQL Server 2000以前的兼容性。从SQL Server 2000开始,您实际上可以选择Windows排序规则,因此,美国英语系统的默认设置应该已更改为Latin1_General_CI_AS。但是,我想微软没有人真正知道会对所有各种潜在子系统和系统存储过程等产生什么影响。

因此,我不知道将其设置为数据库默认值或实例范围内的任何特定的负面影响。同时,我尚未对其进行测试。但是,即使我已经对其进行了测试,我仍可能不会使用与您的应用程序相同的代码路径,因此您确实需要在环境中对其进行测试。设置为ON在您的开发和质量检查环境中的实例级别上,并观察它在一两个月内如何工作。然后在暂存/ UAT中启用它。如果在数周内一切正常,将配置更改滚动到“生产”。关键是要给尽可能多的时间来测试每天都不会遇到的各种代码路径。有些是每周,每月或每年受到打击。某些代码路径只会受到支持,或者某些人几年前创建并从未告诉过您的临时报告或维护过程,只会被随机使用(nah,这永远不会发生;-)。

因此,我对仍具有默认“用户选项”设置的实例进行了一些测试,因为我从未更改过它。

请注意:

  • @@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,因此它们接受默认设置

我建议更改实例范围的默认连接选项(如上所示)。与更新应用程序相比,这不会那么麻烦。仅您发现更改实例范围的设置有问题时,我才会更新应用程序。

PS我做了一个简单的测试,更改tempdb更改实例范围的设置,它似乎不起作用。


1
呵呵,在与Paul White讨论了该问答之后,似乎将SET ANSI_WARNINGS ON传递给了ARITHABORT隐式设置为ON。但是,如果在连接中也传递了SET ARITHABORT OFF,即使使用ANSI_WARNINGS覆盖它,SQL Server仍会像选择ARITHABORT OFF一样“起作用”,就像选择奇怪的计划一样。我发现这令人难以置信。因此,毫无疑问,这需要在连接中进行设置,并且SET ARITHABORT OFF甚至不存在。案件在我眼中
closed绕

@EricSwiggum您发现了有趣的线程。但是,我看不到您如何从该信息中得出结论,需要在连接中进行设置。如果没有当前压倒一切的话,那么我们就知道SET ARITHABORT OFF存在。那么,为什么要担心它的存在呢?我们看到的唯一被默认值覆盖的实例是SSMS将其设置为ON(这是一件好事)。无论哪种方式,我都通过测试以及我认为最合理的建议(根据现有信息)更新了答案。
所罗门·鲁兹基

1
我同意,启用默认情况下的实例范围设置。但是最终,连接控制了设置。在各种技术/协议连接到SQL的共享实例的情况下呢?我的意思是,我是否必须像疯子一样四处奔走并大喊“ SET ARITHABORT ON”才能发展?或者,至少,如果可能的话,提倡不要使用ARITHABORT。.我也感到奇怪的是,直到我第六年担任全职DBA时,我才意识到这一点。或在某些情况下,我没有足够认真地研究它。支持我Paul或Erland,大声笑,这是怎么回事?
埃里克·维格古姆

@EricSwiggum 1)如果您更改实例级别的默认值,则无需大喊大叫。2)ARITHABORT OFF 如果您发现它的任何实际发生,则只需促进它的缺失。到目前为止,可能没有。3)由于这会影响查询计划,因此表可能没有足够的数据以致使SQL Server需要考虑某些选择,而现在那里有更多选择,而有些则不好。也许还有其他瞬态因素,例如过时的统计信息等。不确定。
所罗门·鲁兹基

@EricSwiggum我在这里与您不同意。我认为这与我在回答之初提到的内容(即美国英语系统的默认排序规则)非常相似:微软担心旧版系统在升级时会出错(即向后兼容保证),其弊大于利。增加了非理想方案的安装基础/范围。这使得保留过去成为越来越大的吸引力,并且事情变得越来越好的机会越来越少。在这些情况下,最好先撕掉创可贴并立即解决。
所罗门·鲁兹基
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.