Autor convidado:Michael J Swart (@MJSwart)
Recentemente, fomos surpreendidos por várias exceções que nosso aplicativo lançou. Nosso aplicativo estava falhando ao tentar abrir um SqlConnection. As exceções ficaram assim:
Erro System.InvalidOperationException:
O tempo limite expirou. O período de tempo limite decorrido antes de obter uma conexão do pool. Isso pode ter ocorrido porque todas as conexões em pool estavam em uso e o tamanho máximo do pool foi atingido.
Pools de conexão
Lembre-se de que o .Net usa pools de conexão para ajudar a evitar a sobrecarga de estabelecer uma conexão em cada consulta. Os pools de conexão são mantidos para cada cadeia de conexão e, por padrão, o número de conexões no pool é limitado a cem. Cem conexões geralmente são suficientes. Nunca tivemos problemas com essa exceção antes e nossos servidores não estavam mais ocupados do que o normal, por isso hesitamos em aumentar o valor de MaxPoolSize. Começamos a suspeitar de vazamentos de conexão de banco de dados.
Vazamentos de conexão de banco de dados
Assim como os vazamentos de memória, os vazamentos de conexão de banco de dados podem ocorrer se você não descartar suas conexões de banco de dados em tempo hábil. SqlConnections são IDisposable, portanto, é uma prática recomendada usar a instrução using:
using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); // etc... }
Assim que você terminar com o SqlConnection, ele será descartado e a conexão real retornará imediatamente ao pool de conexões para que possa ser usada por outra pessoa. Caso contrário, a conexão permanece em uso até que o processo termine ou a coleta de lixo a limpe.
Encontrando vazamentos de conexão
Portanto, se seu aplicativo apresentar tempos limite de conexão devido a um vazamento de conexão de banco de dados, os rastreamentos de pilha podem não ajudá-lo. Assim como uma exceção de falta de memória devido a um vazamento de memória, o rastreamento de pilha tem informações sobre a vítima, mas não a causa raiz. Então, onde você pode encontrar o vazamento?
Mesmo que os vazamentos de conexão do banco de dados sejam um problema do cliente, você pode encontrar ajuda no servidor do banco de dados. No servidor de banco de dados, observe as conexões por processo por banco de dados para obter uma estimativa aproximada do tamanho de cada pool:
select count(*) as sessions, s.host_name, s.host_process_id, s.program_name, db_name(s.database_id) as database_name from sys.dm_exec_sessions s where is_user_process = 1 group by host_name, host_process_id, program_name, database_id order by count(*) desc;
Nome do programa, nome do host, ID do processo e nome do banco de dados geralmente são bons o suficiente para identificar conexões provenientes do mesmo pool de conexões.
Isso me leva a fazer mais algumas perguntas sobre pools com muitas conexões. Dado um pool, há sessões que estão dormindo há algum tempo e, em caso afirmativo, há quanto tempo elas estão dormindo e qual foi a última instrução SQL que elas executaram?
declare @host_process_id int = 1508; declare @host_name sysname = N'SERV4102'; declare @database_name sysname = N'My_Database'; select datediff(minute, s.last_request_end_time, getdate()) as minutes_asleep, s.session_id, db_name(s.database_id) as database_name, s.host_name, s.host_process_id, t.text as last_sql, s.program_name from sys.dm_exec_connections c join sys.dm_exec_sessions s on c.session_id = s.session_id cross apply sys.dm_exec_sql_text(c.most_recent_sql_handle) t where s.is_user_process = 1 and s.status = 'sleeping' and db_name(s.database_id) = @database_name and s.host_process_id = @host_process_id and s.host_name = @host_name and datediff(second, s.last_request_end_time, getdate()) > 60 order by s.last_request_end_time;
O texto agora pode ser usado para pesquisar a base de código do seu aplicativo para localizar onde você pode ter um vazamento de conexão de banco de dados.
Essas consultas são úteis para solucionar um vazamento de conexão de banco de dados e também podem ser usadas para criar um monitor ou uma verificação de integridade.
Descarte seus descartáveis, use esses usos, vede esses vazamentos!