Jakie są konsekwencje ustawienia ARITHABORT na wszystkie połączenia w SQL Server?

10

Stwierdziłem więc, że nieprawidłowe działanie mojego SQL Server wynika z domyślnego ustawienia .Net SqlClient Data Provider na SET ARITHABORT OFF. Powiedziawszy to, czytałem różne artykuły, które debatują o najlepszym sposobie realizacji tego. Dla mnie chcę po prostu łatwego sposobu, ponieważ cierpi SQL Server, a moje dostrajanie zapytań nie zostało w pełni przekroczone w całej aplikacji (i oczywiście dodanie SETIN SP NIE DZIAŁA).

W genialnym artykule Erlanda Sommarskoga na ten temat zasadniczo sugeruje bezpieczne podejście, zmieniając aplikację tak, aby wydawała SET ARITHABORT ONpołączenie. Jednak w tej odpowiedzi na pytanie dba.stackexchange Solomon Rutzky oferuje zarówno podejście do całej instancji, jak i do bazy danych.

Jakich konsekwencji brakuje mi tutaj przy ustawianiu tego całego wystąpienia? Jak widzę ... ponieważ SSMS ma ten zestaw ONdomyślnie, nie widzę żadnej szkody w ustawieniu tego ONserwera dla wszystkich połączeń. Na koniec potrzebuję tylko tego SQL Servera, aby działał ponad wszystko.

Eric Swiggum
źródło
Po przeczytaniu większej części mojej odpowiedzi, do której odsyłałeś w pytaniu, wydaje się teraz, że jest domyślnie WYŁĄCZONA, niektórzy klienci specjalnie ją włączają, ale EF / SqlClient jej nie dotyka, co oznacza, że ​​pozostaje WYŁĄCZONA.
Solomon Rutzky
1
Bez EF, ale poruszasz interesujący punkt, w jaki sposób EF może zastąpić ustawienie dla całej instancji. Tak więc, jeśli połączenie może to zastąpić, oczywiście najbardziej niezawodnym miejscem do posiadania tego zestawu jest połączenie ustanowione z SQL Server, jeśli to w ogóle możliwe ...
Eric Swiggum
1
„Zawsze ustawiaj ARITHABORT na WŁ. Podczas sesji logowania. Ustawienie ARITHABORT na WYŁ. Może negatywnie wpłynąć na optymalizację zapytań, prowadząc do problemów z wydajnością.” ten artykuł z Microsoft mówi: docs.microsoft.com/en-us/sql/t-sql/statements/…
Shiwangini Shishulkar
Testowałem różne scenariusze, moje ostateczne zdanie ze wszystkich polega na tym, że to ustawienie i wąchanie parametrów są typami osób towarzyszących. Jeśli tak ARITHABORT OFF, to dobrze. Nie wyłączaj wszystkich połączeń przychodzących. (Powodzenia w kontrolowaniu tego). Ale gdy pojawia się połączenie z ustawionym na WŁĄCZONE, SQL generuje nowy plan zapytań, co może mieć wpływ na wydajność. Moje podejście, ustaw je jako domyślną opcję użytkownika na poziomie instancji i odpowiednio dostosuj zapytania.
Eric Swiggum,

Odpowiedzi:

11

Istnieją pewne domyślne ustawienia, ponieważ nikt tak naprawdę nie wie, jaki byłby skutek ich zmiany. Na przykład domyślne sortowanie na poziomie instancji podczas instalacji w systemie, który używa języka „US English” jako języka systemu operacyjnego SQL_Latin1_General_CP1_CI_AS. Nie ma to sensu, ponieważ SQL_*zestawienia dotyczą zgodności z wersją wcześniejszą niż SQL Server 2000. Począwszy od SQL Server 2000 można właściwie wybrać sortowanie w systemie Windows, dlatego domyślne ustawienie dla systemów w języku angielskim w USA powinno zostać zmienione na Latin1_General_CI_AS. ALE, myślę, że nikt w Microsoft naprawdę nie wie, jaki będzie wpływ na wszystkie potencjalne podsystemy i procedury przechowywane w systemie itp.

Tak więc nie jestem świadomy żadnego konkretnego negatywnego wpływu ustawienia go na ON jako domyślną bazę danych lub nawet na całą instancję. Jednocześnie go nie testowałem. Ale nawet gdybym go przetestował, nadal mogę nie używać tych samych ścieżek kodu co Twoja aplikacja, więc jest to coś, co naprawdę musisz przetestować w swoim środowisku. Ustaw naONna poziomie instancji w środowiskach deweloperów i kontroli jakości i zobacz, jak to działa przez miesiąc lub dwa. Następnie włącz to w Staging / UAT. Jeśli wszystko pójdzie dobrze przez kilka tygodni, przenieś tę zmianę konfiguracji do Produkcji. Kluczem jest poświęcenie jak największej ilości czasu na przetestowanie różnych ścieżek kodu, które nie są trafiane codziennie. Niektóre trafiają co tydzień lub miesiące lub co roku. Niektóre ścieżki kodu są dotknięte jedynie wsparciem lub raportem ad hoc lub procesem konserwacji, o którym ktoś utworzył lata temu i o którym nigdy nie mówił, i przyzwyczaja się tylko w przypadkowych odstępach czasu (nie, to się nigdy nie zdarza ;-).

Przeprowadziłem więc testy na instancji, która wciąż ma domyślne ustawienie „opcji użytkownika”, ponieważ nigdy go nie zmieniłem.

Proszę zanotować:

  • @@OPTIONS/ 'user options'jest wartością maski bitowej
  • 64 to bit ARITHABORT ON

USTAWIAĆ

Testowałem zarówno z SQLCMD (który używa ODBC), jak i LINQPad (który używa .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 .

( ^jest to znak kontynuacji linii DOS; w .ostatnim wierszu jest tylko wymuszenie dodatkowej linii, aby ułatwić kopiowanie i wklejanie)

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

TEST 1: Przedtem

SQLCMD zwraca:

master: 0 (ODBC)

LINQPad zwraca:

tempdb: 0 (.Net SqlClient Data Provider)

ZMIEŃ DOMYŚLNĄ OPCJĘ POŁĄCZENIA:

Poniższy T-SQL włącza ARITHABORTbez usuwania innych opcji, które mogą być ustawione, i bez zmiany czegokolwiek, jeśli ARITHABORTjest już ustawiony w wartości maski bitowej.

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;

TEST 2: Po

SQLCMD zwraca:

master: 64 (ODBC)

LINQPad zwraca:

tempdb: 64 (.Net SqlClient Data Provider)

Wniosek

Jeśli się uwzględni:

  1. Wydaje się, że nie ma z tego żadnej korzyści ARITHABORT OFF
  2. Ma to korzyść ARITHABORT ON
  3. Domyślne ustawienie połączenia (chyba że zostanie zastąpione przez połączenie) = OFF
  4. Nie wydaje się, aby próbowała ustawić ODBC lub OLEDB / .NET SqlClient ARITHABORT, dlatego akceptują ustawienie domyślne

Sugerowałbym zmianę domyślnych opcji połączenia dla całej instancji (jak pokazano powyżej). Byłoby to mniej nachalne niż aktualizowanie aplikacji. Zaktualizowałbym aplikację tylko wtedy , gdy znajdziesz problem ze zmianą ustawień dla całej instancji.

PS Zrobiłem prosty test, zmieniając tempdbi nie zmieniając ustawienia dla całej instancji i nie działało.

Solomon Rutzky
źródło
1
Huh, po przeczytaniu tego pytania i odpowiedzi z Paulem White'em na ten temat, wydaje się, że przekazanie SET ANSI_WARNINGS ON, domyślnie ustawia ARITHABORT na ON. JEDNAK, jeśli SET ARITHABORT OFF również zostanie przekazane w połączeniu, nawet jeśli ANSI_WARNINGS je przesłoni, serwer SQL będzie nadal „działał” tak, jak ARITHABORT jest wyłączony, podobnie jak przy wybieraniu dziwnych planów. Uważam to za ... zadziwiające. Bez wątpienia należy to ustawić w połączeniu I USTAWIENIE ARITHABORT WYŁ. Nawet nie może istnieć. Sprawa zamknięta w moich oczach ... sqlservercentral.com/forums/topic/…
Eric Swiggum
@EricSwiggum Znaleziony interesujący wątek. Nie widzę jednak, w jaki sposób wnioskujesz na podstawie tych informacji, że należy je ustawić w połączeniu. Jeśli nic nie jest obecnie nadrzędnym, a potem wiemy, że SET ARITHABORT OFFto nie występuje. Więc po co się martwić, że będzie obecny? jedynym przypadkiem, w którym widzieliśmy miejsce, w którym wartość domyślna jest zastępowana, jest ustawienie SSMS na ON(co jest dobrą rzeczą). Tak czy inaczej zaktualizowałem swoją odpowiedź testowaniem i tym, co uważam za najbardziej logiczną rekomendację (na podstawie istniejących informacji).
Solomon Rutzky
1
Zgadzam się, włącz ustawienie domyślne dla całej instancji. Ale ostatecznie połączenie kontroluje to, co jest ustawione. Co z przypadkami współużytkowanych instancji, w których różne technologie / protokoły łączą się z SQL? Mam na myśli, czy muszę biegać i krzyczeć „SET ARITHABORT ON”, aby rozwijać się jak szalony człowiek? a przynajmniej promuj brak ARITHABORT OFF, jeśli to możliwe. Dziwne jest też to, że do tej pory nie widziałem tego, mój szósty rok w pełnym wymiarze godzin. a może jest to przypadek, w którym nie przyjrzałem się wystarczająco mocno. Wspieraj mnie Paul lub Erland, LOL, o co chodzi?
Eric Swiggum,
@EricSwiggum 1) Nie musiałbyś biegać i krzyczeć, jeśli zmienisz domyślne ustawienie na poziomie instancji. 2) Musisz promować nieobecność, ARITHABORT OFF jeśli znajdziesz jakieś rzeczywiste przypadki. Do tej pory prawdopodobnie nie ma żadnych. 3) Ponieważ wpływa to na plany zapytań, być może tabele nigdy nie miały wystarczającej ilości danych, aby SQL Server miał pewne opcje do rozważenia, w których teraz jest więcej możliwości, a niektóre są złe. A może istnieją inne czynniki przejściowe, takie jak nieaktualne statystyki itp. Nie do końca pewne.
Solomon Rutzky
@EricSwiggum Nie zgadzam się z tobą. Myślę, że jest to bardzo podobne do tego, o którym wspomniałem na początku mojej odpowiedzi (tj. Domyślnego zestawienia dla systemów w języku angielskim w USA): obawa Microsoftu przed błędami starszych systemów podczas aktualizacji (tj. Gwarancja kompatybilności wstecznej) wyrządza więcej szkody niż pożytku, ponieważ w rzeczywistości zwiększa bazę instalacji / zakres scenariusza innego niż idealny. Dzięki temu pozostanie w przeszłości stale rośnie, a szansa na poprawę sytuacji jest coraz mniejsza. Są to przypadki, w których lepiej jest zerwać opaskę i po prostu pozbyć się bólu.
Solomon Rutzky