sexta-feira, 18 de agosto de 2017

O estranho caso do timeout ao invocar uma procedure pela aplicação


Está semana, no estranho mundo das coisas que só acontecem comigo, passei por mais uma estranha situação ao invocar uma procedure pela aplicação estourava um timeout e ao invocar a procedure pelo "terminal" do Sql Server a execução era instatânea. Nesse momento todos os fantasmas do "Não use Entity Framework" vieram a minha mente junto com milhões de pensamentos catastróficos sobre as consequências dessa escolha e quando estava para entrar em pânico, ou seja, os primeiros resultados da consulta marota no Google não retornaram o Santo Graal parei para pensar se no banco funciona e na aplicação não então existe alguma configuração ou parâmetro que está causando a instabilidade, e seguindo esta linha encontrei a salvação no Stackoverflow. A raiz e solução estavam em ativar o parâmetro ARITHABORT. Fui no SQL Server Management Studio, vulgarmente chamado de terminal do SQL Server e desliguei o parâmetro SET ARITHABORT OFF e invoquei a procedure e cinco minutos depois o esperado timeout estava lá e na minha mente suja eu mandava os urubus que são contra o Entity Framework para um bom lugar. Então a dica era quente, mas eu já estava indo para o próximo problema "Como fazer isso pela aplicação"?", mas como estávamos numa situação a ponto de entrar em pânico, uma voz salvadora e imperativa apontou o dedo e disse "Altere a procedure e ative o parâmetro" e assim foi feito e a aplicação Geradora de Erros Improváveis e Previsíveis sobrevive ao pequeno apocalipse.

Agora vamos as explicações.
Por que o erro ocorre na aplicação e não no terminal do sql server?
Porque o SQL Server Management Studio se conecta ao banco com o ARITHABORT ativado e a aplicação não.

O que este parâmetro faz?
Termina a query quando um overflow ou divisão por zero ocorre.

E??
Infelizmente não consegui entender o que isso afeta a query, a única coisa que aprendi e entendi é que
as sessões sempre devem ser iniciadas com o glorioso ARITHABORT ligado. Então o próximo passou é fazer o Ado.Net conectar sempre assim e ler mais sobre o assunto.

Referências
https://docs.microsoft.com/en-us/sql/t-sql/statements/set-arithabort-transact-sql

https://stackoverflow.com/questions/834124/ado-net-calling-t-sql-stored-procedure-causes-a-sqltimeoutexception/839055#839055

https://stackoverflow.com/questions/2248112/query-times-out-when-executed-from-web-but-super-fast-when-executed-from-ssms

http://www.sommarskog.se/query-plan-mysteries.html [Tenho que ler, mas parece ser o guia definitivo]

Nenhum comentário:

Postar um comentário