sql >> Database teknologi >  >> RDS >> Database

Find databaseforbindelseslækager i din applikation

Gæsteforfatter:Michael J Swart (@MJSwart)

Vi blev for nylig overrasket over en række undtagelser, som vores ansøgning gav. Vores applikation fejlede, da vi forsøgte at åbne en SqlConnection. Undtagelserne så således ud:

Fejl System.InvalidOperationException:

Timeout udløb. Timeoutperioden forløb, før der blev opnået forbindelse fra poolen. Dette kan være sket, fordi alle poolede forbindelser var i brug, og den maksimale poolstørrelse blev nået.

Forbindelsespuljer

Husk, at .Net bruger forbindelsespuljer for at undgå omkostningerne ved at etablere en forbindelse ved hver forespørgsel. Forbindelsespuljer opretholdes for hver forbindelsesstreng, og som standard er antallet af forbindelser i poolen begrænset til hundrede. Et hundrede forbindelser er normalt tilstrækkeligt. Vi har aldrig før haft et problem med denne undtagelse, og vores servere havde ikke mere travlt end normalt, så vi var tøvende med at øge værdien af ​​MaxPoolSize. Vi begyndte at have mistanke om lækager af databaseforbindelse.
 

Lækager til databaseforbindelse

Ligesom hukommelseslækager kan databaseforbindelseslækager forekomme, hvis du ikke bortskaffer dine databaseforbindelser i tide. SqlConnections er ID-disposable, så det er en bedste praksis at bruge brugssætningen:

using (SqlConnection conn = new SqlConnection(connectionString)) 
{
  conn.Open();
  // etc...
}

Så snart du er færdig med SqlConnection, bliver den bortskaffet, og den faktiske forbindelse vender straks tilbage til forbindelsespuljen, så den kan bruges af en anden. Ellers forbliver forbindelsen i brug, indtil processen afsluttes, eller affaldsopsamlingen renser den.

Sådan finder du din forbindelseslækage

Så hvis din applikation oplever forbindelsestimeout på grund af en databaseforbindelseslækage, hjælper stacksporingerne dig muligvis ikke. Ligesom en undtagelse uden hukommelse på grund af en hukommelseslækage har stak-sporet information om offeret, men ikke årsagen. Så hvor kan du gå hen for at finde lækagen?
 
Selvom databaseforbindelseslækager er et klientproblem, kan du finde hjælp fra databaseserveren. På databaseserveren, se på forbindelser pr. proces pr. database for at få et groft estimat af størrelsen af ​​hver pulje:

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;

Programnavn, værtsnavn, proces-id og databasenavn er normalt gode nok til at identificere forbindelser, der kommer fra den samme forbindelsespulje.

Dette får mig til at stille et par flere spørgsmål om pools med mange forbindelser. Givet en pool, er der sessioner, der har sovet i et stykke tid, og i så fald, hvor længe har de sovet, og hvad var den sidste SQL-sætning, de udførte?

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;

Teksten kan nu bruges til at søge i din applikations kodebase for at finde ud af, hvor du kan have en databaseforbindelseslækage.

Disse forespørgsler er nyttige til fejlfinding af en databaseforbindelseslækage, og de kan også bruges til at oprette en skærm eller et sundhedstjek.

Bortskaf dine engangsartikler, brug disse anvendelser, forsegl disse lækager!

Om forfatteren

Michael J Swart er en passioneret databaseprofessionel og blogger, der fokuserer på databaseudvikling og softwarearkitektur. Han nyder at tale om alt data relateret og bidrage til samfundsprojekter. Michael blogger som "Database Whisperer" på michaeljswart.com.
  1. Skift type af en kolonne med tal fra varchar til int

  2. Endnu et argument for lagrede procedurer

  3. Hvordan skriver man en begrænsning vedrørende et maks. antal rækker i postgresql?

  4. MariaDB JSON_VALUE() Forklaret