2010-10-01 7 views
4

J'ai récemment commencé à rencontrer des problèmes de connexion à la base de données avec SQL Server sur ma machine de développement.Comment résoudre un problème de pool de connexion?

System.InvalidOperationException: Expiration du délai. Le délai d'expiration s'est écoulé avant l'obtention d'une connexion du pool

Comment puis-je surveiller le pool de connexions pour savoir ce qui se passe?

Plus d'info:

Je n'ai pas eu beaucoup de chance avec - je suis certainement pas les connexions qui fuient. Chaque connexion est dans une instruction using. Lorsque le problème survient, la fenêtre Analyseur de performances s'ouvre et ne s'affiche pas à proximité de la limite du pool (qui est 100), généralement autour de 2 à 5 connexions, donc je ne pense pas que le pool soit être épuisé alors peut-être que c'est un timeout.

Cependant, j'ai mis le ConnectionTimeout à 0 - ce qui, selon la documentation, signifie qu'il devrait toujours attendre pour se connecter - mais je ne le vois pas. Quand ça arrive, ça arrive assez vite - je cours sous le débogueur de VS2010 - en démarrant une nouvelle instance de mon application - et cela peut arriver dans une seconde ou deux de démarrage - en démarrant l'application là-bas sont plusieurs requêtes qui se produisent. Le serveur SQL réel sur lequel je suis exécuté est SQL Express 2008. Je devrais peut-être essayer de l'exécuter sur SQL Server 2008 et voir si je vois un comportement différent.

D'autres idées?

Répondre

3

Jetez un oeil à la ADO.NET Performance Counters liée à la mise en commun.

Votre symptôme décrit souvent une fuite de connexion. Assurez-vous que toutes les connexions sont éliminées lorsque vous avez terminé avec elles, de préférence en les enveloppant dans une instruction using.

+0

Se mettre d'accord. Assez difficile pour max une piscine en général – gbn

1

est un code ici pour essayer la piscine et le basculement vers non mis en commun: utiliser ce sous si un problème se produit avec la piscine:

Public Sub OpenConn() 
    Dim sTempCNString As String = cn.ConnectionString 

    Try 
     ' add a timeout to the cn string, following http://www.15seconds.com/issue/040830.htm 
     Dim iTimeOut As Integer = utils_Configuration.Get_ConfigInt("DBConnectTimeout", 0) 
     If (iTimeOut > 0 And Not cn.ConnectionString.ToLower.Contains("timeout")) Then 
      Diagnostics.Debug.Print("<><><><><><><> SHORT CONNECT WITH POOLING <><><><><><><><><> ") 
      cn.ConnectionString += ";Connect Timeout=" & iTimeOut.ToString() & ";" 
     End If 

     cn.Open() 
     IsOperational = True 
    Catch ex As Exception 
     Diagnostics.Debug.Print("ERROR IN OPENING, try no pool") 
     ' see http://www.15seconds.com/issue/040830.htm 
     ' turn off pooling 
     Diagnostics.Debug.Print("<><><><><><><> CONNECT WITHOUT POOLING <><><><><><><><><> ") 
     Dim sAddOn As String = ";Pooling=false;Connect Timeout=45;" 
     cn.ConnectionString = sTempCNString & sAddOn 
     cn.ConnectionString = cn.ConnectionString.Replace(";;", ";") 
     cn.Open() 
    End Try 
End Sub 

Voici un code pour surveiller la piscine:

Option Explicit On 
Option Strict On 

Imports System.Data.SqlClient 
Imports System.Diagnostics 
Imports System.Runtime.InteropServices 
Imports Microsoft.VisualBasic 


' ref: http://msdn2.microsoft.com/en-us/library/ms254503.aspx 

Public Class utils_SqlPerfMon 

    Private PerfCounters(9) As PerformanceCounter 
    Private connection As SqlConnection 
    Public sConnectString As String = "" 
    Public sResult As String = "" 

    Public Sub New() 
     sConnectString = Tools.GetMainDBConn().ConnectionString 
     connection = New SqlConnection(sConnectString) 
     Exec() 
    End Sub 

    Public Sub New(ByVal strC As String) 
     sConnectString = strC 
     connection = New SqlConnection(sConnectString) 
     Exec() 
    End Sub 

    Public Sub Exec() 

     Me.SetUpPerformanceCounters() 
     Diagnostics.Debug.Print("Available Performance Counters:") 

     ' Create the connections and display the results. 
     Me.CreateConnectionsAndDisplayResults() 

    End Sub 

    Private Sub CreateConnectionsAndDisplayResults() 
     ' List the Performance counters. 
     WritePerformanceCounters() 

     Dim connection1 As SqlConnection = New SqlConnection(_ 
      Me.sConnectString) 
     connection1.Open() 

     Diagnostics.Debug.Print("Opened the 1st Connection:") 
     WritePerformanceCounters() 

     connection1.Close() 
     Diagnostics.Debug.Print("Closed the 1st Connection:") 
     WritePerformanceCounters() 


     Return 


    End Sub 

    Private Enum ADO_Net_Performance_Counters 
     NumberOfActiveConnectionPools 
     NumberOfReclaimedConnections 
     HardConnectsPerSecond 
     HardDisconnectsPerSecond 
     NumberOfActiveConnectionPoolGroups 
     NumberOfInactiveConnectionPoolGroups 
     NumberOfInactiveConnectionPools 
     NumberOfNonPooledConnections 
     NumberOfPooledConnections 
     NumberOfStasisConnections 
     ' The following performance counters are more expensive to track. 
     ' Enable ConnectionPoolPerformanceCounterDetail in your config file. 
     '  SoftConnectsPerSecond 
     '  SoftDisconnectsPerSecond 
     '  NumberOfActiveConnections 
     '  NumberOfFreeConnections 
    End Enum 

    Private Sub SetUpPerformanceCounters() 
     connection.Close() 
     Me.PerfCounters(9) = New PerformanceCounter() 

     Dim instanceName As String = GetInstanceName() 
     Dim apc As Type = GetType(ADO_Net_Performance_Counters) 
     Dim i As Integer = 0 
     Dim s As String = "" 
     For Each s In [Enum].GetNames(apc) 
      Me.PerfCounters(i) = New PerformanceCounter() 
      Me.PerfCounters(i).CategoryName = ".NET Data Provider for SqlServer" 
      Me.PerfCounters(i).CounterName = s 
      Me.PerfCounters(i).InstanceName = instanceName 
      i = (i + 1) 
     Next 
    End Sub 

    Private Declare Function GetCurrentProcessId Lib "kernel32.dll"() As Integer 

    Private Function GetInstanceName() As String 
     'This works for Winforms apps. 
     'Dim instanceName As String = _ 
     ' System.Reflection.Assembly.GetEntryAssembly.GetName.Name 

     ' Must replace special characters like (,), #, /, \\ 
     Dim instanceName As String = _ 
      AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _ 
      .Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_") 

     'For ASP.NET applications your instanceName will be your CurrentDomain's 
     'FriendlyName. Replace the line above that sets the instanceName with this: 
     'instanceName = AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _ 
     ' .Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_") 

     Dim pid As String = GetCurrentProcessId.ToString 
     instanceName = (instanceName + ("[" & (pid & "]"))) 
     Diagnostics.Debug.Print("Instance Name: {0}", instanceName) 
     Diagnostics.Debug.Print("---------------------------") 
     Return instanceName 
    End Function 

    Private Sub WritePerformanceCounters() 
     Dim sdelim As String = vbCrLf ' "<br>" 
     Diagnostics.Debug.Print("---------------------------") 
     sResult += "---------------------------" 
     sResult += sdelim 

     Dim strTemp As String = "" 
     For Each p As PerformanceCounter In Me.PerfCounters 
      Try 
       Diagnostics.Debug.Print("{0} = {1}", p.CounterName, p.NextValue) 
       strTemp = p.CounterName & "=" & p.NextValue.ToString 
      Catch ex As Exception 
       strTemp = "" 
      End Try 
      sResult += strTemp 
      sResult += sdelim 
     Next 
     Diagnostics.Debug.Print("---------------------------") 
     sResult += "---------------------------" 
      sResult += sdelim 
    End Sub 


    Private Shared Function GetSqlConnectionStringDifferent() As String 
     ' To avoid storing the connection string in your code, 
     ' you can retrive it from a configuration file. 
     Return ("Initial Catalog=AdventureWorks;Data Source=.\SqlExpress;" & _ 
      "User Id=LowPriv;Password=Data!05;") 
    End Function 


End Class