Quais são as ramificações da configuração do ARITHABORT ON para todas as conexões no SQL Server?

10

Portanto, determinei que o comportamento irregular do meu SQL Server se deve à configuração padrão de .Net SqlClient Data Provider SET ARITHABORT OFF. Com isso dito, li vários artigos que debatem a melhor maneira de implementar isso. Para mim, eu só quero uma maneira fácil, porque o SQL Server está sofrendo e meu ajuste de consulta não transcendeu completamente no aplicativo (e, obviamente, adicionar o SETsp não funciona).

No brilhante artigo de Erland Sommarskog sobre o assunto, ele basicamente sugere uma abordagem segura, alterando o aplicativo para emitir SET ARITHABORT ONa conexão. No entanto, nesta resposta de uma pergunta do dba.stackexchange , Solomon Rutzky oferece uma abordagem para toda a instância e para o banco de dados.

Que ramificações estou faltando aqui ao definir essa instância para todo? A meu ver ... como o SSMS tem esse conjunto ONpor padrão, não vejo mal em configurar esse ONservidor para todas as conexões. No final do dia, eu só preciso desse SQL Server para executar acima de tudo.

Eric Swiggum
fonte
Lendo grande parte da minha resposta que você vinculou na pergunta, agora parece que ela está DESLIGADA por padrão, alguns clientes a ativam especificamente, mas o EF / SqlClient não a toca, o que significa que permanece desativada.
Solomon Rutzky
11
Não há EF, mas você levanta um ponto interessante sobre como o EF pode substituir a configuração em toda a instância. Assim, se uma conexão pode substituir esse, obviamente, o lugar mais confiável para ter este conjunto é de dentro da conexão que é estabelecida para SQL Server, se possível ...
Eric Swiggum
11
"Sempre defina ARITHABORT como ON em suas sessões de logon. Definir ARITHABORT como OFF pode afetar negativamente a otimização da consulta, levando a problemas de desempenho." este artigo da microsoft diz: docs.microsoft.com/en-us/sql/t-sql/statements/…
Shiwangini Shishulkar
Eu testei vários cenários, minha opinião final de tudo é que essa configuração e detecção de parâmetros são companheiros de cama. Se você tiver ARITHABORT OFF, então tudo bem. Mantenha-o desligado para todas as conexões de entrada. (Boa sorte em controlar isso). Porém, quando uma conexão entra em ON, o SQL gera um novo plano de consulta e isso pode afetar o desempenho. Minha opinião, ative-a como a opção de usuário padrão no nível da instância e ajuste as consultas adequadamente.
Eric Swiggum 24/09/19

Respostas:

11

Existem alguns padrões simplesmente porque ninguém sabe realmente qual seria o efeito de alterá-los. Por exemplo, o agrupamento padrão no nível da instância ao instalar em um sistema que usa "inglês dos EUA" como o idioma do sistema operacional SQL_Latin1_General_CP1_CI_AS. Isso não faz sentido, pois os SQL_*agrupamentos são para compatibilidade anterior ao SQL Server 2000. A partir do SQL Server 2000, era possível escolher um agrupamento do Windows e, portanto, o padrão para sistemas em inglês dos EUA deveria ter sido alterado para Latin1_General_CI_AS. MAS, acho que ninguém na Microsoft sabe realmente qual será o impacto para todos os vários subsistemas potenciais e procedimentos armazenados do sistema etc.

Portanto, não conheço nenhum impacto negativo específico de configurá-lo como LIGADO como um padrão de banco de dados ou mesmo para toda a instância. Ao mesmo tempo, eu não testei. Mas, mesmo que eu o tenha testado, talvez ainda não use os mesmos caminhos de código que seu aplicativo, portanto, isso é algo que você realmente precisa testar em seu ambiente. Defina comoONno nível da instância em seus ambientes Dev e QA e veja como isso funciona por um mês ou dois. Em seguida, ative-o no armazenamento temporário / UAT. Se tudo continuar funcionando por várias semanas, role essa alteração de configuração para Produção. A chave é conceder o máximo de tempo possível para testar vários caminhos de código que não são atingidos diariamente. Alguns são atingidos semanalmente ou meses ou anualmente. Alguns caminhos de código são atingidos apenas pelo suporte ou por algum relatório ad hoc ou processo de manutenção que alguém criou anos atrás e nunca lhe contou e só é usado em intervalos aleatórios (nah, isso nunca acontece ;-).

Portanto, fiz alguns testes em uma instância que ainda possui a configuração "opções do usuário" padrão, pois nunca a alterei.

Observe:

  • @@OPTIONS/ 'user options'é um valor mascarado
  • 64 é o bit para ARITHABORT ON

CONFIGURAÇÃO

Testei com o SQLCMD (que usa ODBC) e o LINQPad (que usa o .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 .

(o ^é o caractere de continuação de linha do DOS; o .da última linha é apenas para forçar a linha extra para facilitar a copiar e colar)

No 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());
  }
}

TESTE 1: Antes

SQLCMD retorna:

master: 0 (ODBC)

O LINQPad retorna:

tempdb: 0 (.Net SqlClient Data Provider)

MUDAR A OPÇÃO DE CONEXÃO PADRÃO:

O T-SQL a seguir é ativado ARITHABORTsem remover nenhuma outra opção que possa ser definida e sem alterar nada, se ARITHABORTjá estiver definido no valor de máscara de bit.

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;

TESTE 2: Depois

SQLCMD retorna:

master: 64 (ODBC)

O LINQPad retorna:

tempdb: 64 (.Net SqlClient Data Provider)

Conclusão

Dado que:

  1. Não parece haver nenhum benefício em ter ARITHABORT OFF
  2. Há benefício em ter ARITHABORT ON
  3. A configuração de conexão padrão (a menos que substituída pela conexão) = OFF
  4. Não parece que o ODBC ou OLEDB / .NET SqlClient tente definir ARITHABORT, portanto eles aceitam a configuração padrão

Eu sugeriria alterar as opções de conexão padrão para toda a instância (como mostrado acima). Isso seria menos invasivo do que atualizar o aplicativo. Eu atualizaria o aplicativo apenas se você encontrar um problema ao alterar a configuração de toda a instância.

PS: Fiz um teste simples alterando tempdbe não alterando a configuração de toda a instância e ela não pareceu funcionar.

Solomon Rutzky
fonte
11
Depois de ler estas perguntas e respostas com Paul White sobre o assunto, parece que passar SET ANSI_WARNINGS ON, implicitamente define ARITHABORT como ON. No entanto, se SET ARITHABORT OFF também for passado na conexão, mesmo com ANSI_WARNINGS substituindo-o, o SQL Server ainda "atuará" como ARITHABORT OFF, como na escolha de planos estranhos. Eu acho isso ... incompreensível. Portanto, sem dúvida, isso precisa ser definido na conexão E SET ARITHABORT OFF nem pode existir. Caso encerrado nos meus olhos ... sqlservercentral.com/forums/topic/...
Eric Swiggum
@EricSwiggum Tópico interessante que você encontrou. No entanto, não vejo como você conclui a partir dessas informações que elas precisam ser definidas na conexão. Se nada está substituindo isso no momento, sabemos que nãoSET ARITHABORT OFF está presente. Então, por que se preocupar com a presença? a única instância que vimos em que o padrão é substituído é o SSMS configurando-o para (o que é uma coisa boa). De qualquer maneira, atualizei minha resposta com testes e o que considero a recomendação mais lógica (por informações existentes). ON
Solomon Rutzky
11
Concordo, ative a configuração de toda a instância como padrão. Mas, finalmente, a conexão controla o que está definido. E o caso de instâncias compartilhadas em que várias tecnologias / protocolos estão se conectando ao SQL? Quero dizer, eu tenho que correr e gritar "SET ARITHABORT ON" para se desenvolver como um homem louco? ou, no mínimo, promova a ausência de ARITHABORT OFF, se possível. Também acho estranho que eu não tenha visto isso chegar a um ponto até agora, meu sexto ano como DBA em tempo integral. ou talvez seja um caso em que eu não tenha examinado o assunto com força suficiente. Apoie-me Paul ou Erland, risos, o que há com isso?
Eric Swiggum
@EricSwiggum 1) Você não precisaria correr gritando nada se alterar o padrão no nível da instância. 2) Você só precisaria promover a ausência de ARITHABORT OFF se encontrar alguma incidência real dela. Até agora, provavelmente não há. 3) Como isso afeta os planos de consulta, pode ser que as tabelas nunca tenham dados suficientes para fazer com que o SQL Server tenha certas opções a serem consideradas, onde agora há mais opções e algumas são ruins. Ou talvez haja outros fatores transitórios, como estatísticas desatualizadas, etc. Não há muita certeza.
Solomon Rutzky
@EricSwiggum Não estou discordando de você lá. Eu acho que isso é muito semelhante ao que eu mencionei no início da minha resposta (ou seja, o agrupamento padrão para sistemas em inglês dos EUA): o medo da Microsoft de sistemas herdados de obter erros ao atualizar (ou seja, garantia de compatibilidade com versões anteriores) causa mais mal do que bem, na verdade aumenta a base de instalação / escopo do cenário não ideal. Isso torna uma atração cada vez maior permanecer no passado e uma chance cada vez menor de as coisas melhorarem. Nesses casos, é melhor retirar o curativo e acabar com a dor agora.
Solomon Rutzky