03. august 2005 - 22:23Der er
30 kommentarer og 1 løsning
Connection Pool ?
Hejsa,
Jeg sidder og roder lidt med at få styr på min connection pool men fra tid til anden kommer denne fejl :
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached
Så læste jeg lidt på lektien og fandt et par steder hvor jeg ikkefik lukket for database forbindelsen, det hjalp lidt på det men stadig får jeg ovenstående fejl.
Jeg mangler lidt hjælp til at løse dette. Så det kunne være lidt fedt at få styr på hvordan jeg kan monitorere eller tjekke op på hvad, hvor og hvornår problemet opstår, er der en der kan hjælpe med det ?
generelt er det vel et spørgsmål om en fornuftig struktur i den kode som åbner forbindelser til databasen, dvs. try-catch-finally omkring relevant kode.
Eksempel:
try { // åben forbindelse try { // læs data eller hvad der nu skal gøres } catch(Exception exRead) { // fejlhåndter denne situation } finally { // Luk forbindelsen igen. // På dette niveau ved du at forbindelsen er oprettet // så du kan bare lukke den uden videre... } } catch(Exception exConn) { // Fejlhåndter denne situation. // Dette vil typisk være fejl der opstår under oprettelsen // af forbindelsen og den vil derfor ikke være åben på dette tidspunkt }
Det er i store træk også sådan jeg gør det, men jeg fandt frem til at jeg på en måde kunne monitorere antallet af connections på min sql server jeg kan blotikke finde ud af hvor det ligger ?
Jeg ved ikke umiddelbart hvordan man overvåger dette, men hvad vil du med den information. Det virker for mig som symptombehandling at overvåge antallet af forbindelser - du løber nok tør alligevel selvom du ved lige præcis hvormange der er tilbage :)
Hmmm... rent faktisk er det ikke engang symptombehandling... nå, hvad, man kan jo ikke være lige klog hver gang :)
Jeg spekulerede på om du kører på en MSDE, hvor der er begrænset antal samtidige forbindelser (er det ikke 5 man har), men det ville trods alt betyde at dit site skal være rimelig godt besøgt (eller dine databaseopslag ret komplekse og tidskrævende), hvis det er et problem... har du nogle tanker det dette?
ja men ved at have den kørende kan nemmere finde frem til hvor oghvornår det går galt, men jeg må jo lede lidt mere efter det så finder jeg det nok på et tidspunk
Jeg bruger en MsSql server 2000 med det hele og ikke MSDE den knækker nakken rimeligt hurtigt og jeg ved at der er en monitor til den, men kan fame ikke huske hvor jeg finder den :o(
Function LoadData() DbClass.SqlConnect 'laver forbindelse til database 'laver noget sql sager for at loade data i dataset DbClass.SqlClose 'lukker database forbindelse End Function
Og jeg skal ikke klikke mangange på forskellige links på siden før den går i sort ?
Hmmm... jeg vil tro det giver en eller anden form for "straf" mht. resurseforbrug på serveren ved at gøre det (ud over at det koster kassen til M$ ;) - såvidt jeg ved betaler man pr. connection, eller det er i det mindste en af måderne de tjener penge på SQL Server). Med mindre problemet er at du simpelthen har for få forbindelser i din pool til at understøtte applikationens behov, så er det vel blot symptombehandling (nu mener jeg det! :)). Men det kan du jo kun finde ud af hvis du kan se om forbindelserne bliver nedlagt igen efter en forhåbentlig kortere periode...
'--- Skaber forbindelse til sql server Private Shared Conn As SqlConnection
Public Shared Function SqlConnect() Dim Sql As String = "Data Source=server;Initial Catalog=database;User Id=xxxx;Password=yyyy;" Conn = New SqlConnection(Sql) Conn.Open() SqlConnect = Conn End Function
'--- Function der lukker forbindelse til database. Public Shared Sub SqlClose() Conn.Close() End Sub
Og disse 2 function kalder jeg så ved connect og close
Og en given function der loader data op i et dataset kunne se således ud :
Public Shared Function LoadProduct() Dim objConn As SqlConnection = DbClass.SqlConnect Dim objComm As New SqlDataAdapter("Select * From tbl_products", objConn) Dim objDS As New DataSet objComm.Fill(objDS, "tbl_products") Return objDS DbClass.SqlClose() End Function
Men hvad med SqlDataAdapter skal den oxo lukkes eller hvad sker der med den ?
Når du laver den klasse shared, bliver den så ikke også delt af alle besøgende på sitet og dermed skal den vel også være reentrant... og det er den vel ikke ligefrem med en "global" connection-variabel.
Hvad sker der hvis du prøver at fjerne den globalitet og oprette objektet hver gang du skal bruge en connection (altså din DbClass). Noget i stil med dette:
Function LoadData() Dim objDbClass As New DbClass() objDbClass.SqlConnect 'laver forbindelse til database 'laver noget sql sager for at loade data i dataset objDbClass.SqlClose 'lukker database forbindelse End Function
Jeg er ikke helt sikker på syntaksen for at oprette et objekt i VB.NET, men det kan du nok lige checke om jeg gør korrekt :)
Jo, jeg er klar over at det er mere besværligt, men jeg tror ærlig talt din shared class er årsagen til dit problem.
Jeg fatter det bare ikke nu har jeg ændret det til ikke shared og så snart jeg har klikket 100 gange på links der kræver database adgang ja så render den ud i den samme fejl igen :o(
Nu er jeg ikke helt klar over hvordan Return fungerer i VB.NET, men hvis det havde været C#, så ville den afslutte funktionen lige på stedet og dermed ikke få lukket forbindelsen... ved du om det samme er tilfældet i VB.NET?
Jeg har fundet flg. udsagn på MSDN under sprogreferencen til VB.NET:
"A Return statement returns execution to the expression that invoked the method. If the method is a subroutine, the statement is equivalent to an Exit Sub statement and no expression may be supplied. If the method is a function, an expression must be supplied that is classified as a value and whose type is implicitly convertible to the return type of the function. This form is equivalent to assigning to the function return local and then executing an Exit Function statement."
Jeg opfatter klart dette som en mulig årsag til dit problem idet DbClass.Close ikke bliver kaldt hvis det står efter et Return-udtryk.
Ok nu ser det ud til at virke jeg får i hvert fald ikke mere end et par logins vist i min monitor :o)
Men vil det sige at hvis der så er f.eks er 100 samtidige besøgende på min side så vil nummer 101 ikke kunne komme ind da der kun kan være 100 connections i pool'en ?
Hmm... uden at være helt sikker, vil jeg tro du selv har påvist, at der ikke kan være mere end 100 (eller hvilket antal du har sat op) samtidige forbindelser til databasen. Forsøg på flere forbindelser vil så resultere i en fejl.
Du kan nok lægge noget kode i fejlhåndteringen, som forsøger at gentage opslaget i en periode for at se om der skulle blive bedre plads i køen senere... bare husk at disse forsøg skal have en veldefineret grænse (f.eks. 5 sekunder eller 3 gange), så du ikke låser en bruger fordi der forsøges at oprette forbindelse til databasen i det uendelige :)
Jeg tror ikke på de vil bruge åbne forbindelser, de skal nok være lukket og frigivet inden de tages i brug igen.
Der er ikke længere problemer med at overskride connetions. Jeg satte monitorering på et af mine web-sites og lod den logge et par døgn og der er ikke på noget tidspunkt overskredet 10 connections selvom der har været flere brugere af gangen.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.