2012-01-25 12 views
15

Estoy viendo el temido error "El tiempo de espera transcurrido antes de obtener una conexión del grupo".¿Cómo encontrar fugas en la conexión del grupo de conexiones de db?

He buscado el código para cualquier conexión db sin cerrar, pero no pudo encontrar ninguna.

Lo que quiero hacer es esto: la próxima vez que recibamos este error, haga que el sistema voltee una lista de qué procs o solicitudes http tienen todos los identificadores, para poder averiguar qué código está causando el problema.

Aún mejor sería para ver cuánto tiempo se habían celebrado las manijas, así que podría detectar conexiones utilizadas, pero-no cerradas.

¿Hay alguna manera de hacer esto?

+0

¿Es posible que tenga más usuarios que conexiones en la piscina? –

+0

¿Almacena sus referencias de conexión en estado de sesión o en otro lugar que tenga una vida útil que exceda una solicitud http? – Jan

+0

No, solo se abrieron y (supuestamente) se cerraron en cada solicitud. – Jesse

Respuesta

5

Hay algunos buenos enlaces para agrupaciones de conexiones de monitoreo. Realice una búsqueda en google de "supervisión del grupo de conexiones .net".

Un artículo que me he referido hace un tiempo era Bill Vaughn's article (Tenga en cuenta que esto es viejo, pero todavía contiene información útil). Tiene algo de información sobre el monitoreo de grupos de conexiones, pero también algunos datos importantes sobre dónde podrían ocurrir las filtraciones.

Para el seguimiento, sugiere;

"Supervisión de la agrupación de conexiones

Bueno, por lo que se abrió una conexión y la cerró y me gustaría saber si la conexión sigue en su lugar-languideciendo en la agrupación de conexiones en un colchón aire. Bueno ., hay varias formas de determinar cuántas conexiones están todavía en su lugar (aún conectado) e incluso lo que están haciendo discuto varios de estos aquí y en mi libro:

· Utilice el Analizador de SQL con el SQLProfiler TSQL_Replay plantilla para la traza. Para aquellos de ustedes que estén familiarizados con el Analizador, , esto es más fácil que el sondeo usando SP_WHO.

· Ejecute SP_WHO o SP_WHO2, que devuelve información de la tabla sysprocesses en todos los procesos operativos que muestran el estado actual de cada proceso. En general, hay un proceso de servidor SPID por cada conexión . Si nombró su conexión, utilizando el argumento Nombre de la aplicación en la cadena de conexión, será fácil de encontrar.

· Utilice el Monitor de rendimiento (PerfMon) para supervisar las piscinas y conexiones. Discuto esto en detalle a continuación.

· contadores de rendimiento del monitor en el código. Esta opción le permite mostrar o simplemente monitorear el estado de su grupo de conexiones y la cantidad de conexiones establecidas. Discuto esto en una sección posterior en este documento."

Editar:

Como siempre, echa un vistazo a algunos de los other similar posts aquí en SO

Segunda edición:

Una vez que haya confirmado que las conexiones no son siendo recuperado por el grupo, otra cosa que podría intentar es utilizar el evento StateChange para confirmar cuándo se están abriendo y cerrando las conexiones. Si encuentra que hay muchas más El estado cambia a abierto que a cerrado, entonces eso indicaría que hay filtraciones en alguna parte. También puede registrar los datos en el evento modificado por el estado junto con una marca de tiempo, y si tiene otro registro en su aplicación, puede comenzar a analizar los archivos de registro para las instancias en las que parece haber cambios de estado de cerrado a abierto, con no corresponde abierto a cerrado. Consulte this link para obtener más información sobre cómo manejar StateChangedEvent.

+0

Si las conexiones permanecen abiertas en el grupo, ¿cómo se puede ver en SQL Profiler cuando se han quedado huérfanas? Parece que la información que quiero no está en el archivo db, sino en la capa de administración del grupo. – Jesse

+0

No puedo hacer ningún comentario sobre la opción Analizador de SQL ya que no la he usado para monitorear pools de conexiones. Más información sobre el tipo de información que puede obtener de PerfMon y contadores de rendimiento (las últimas parejas de las que habla se pueden encontrar en .) en estos solo ** después ** recibirás el "error temido" no te dirá ** cuando ** quedaron huérfanos. He sondeado los datos usando los contadores de rendimiento principalmente para confirmar esa cantidad de conexiones en el uso sigue creciendo sin ser recuperado. Una vez confirmado, tienes que cazarlo –

+0

Hmm. No es exactamente la bala de plata que estaba buscando, pero aprecio la explicación completa! – Jesse

13

Si tiene la suerte de que la creación/apertura de la conexión está centralizada, la siguiente clase debería facilitar la detección de conexiones filtradas. Disfrute :)

/// <summary> 
/// This class can help identify db connection leaks (connections that are not closed after use). 
/// Usage: 
/// connection = new SqlConnection(..); 
/// connection.Open() 
/// #if DEBUG 
/// new ConnectionLeakWatcher(connection); 
/// #endif 
/// That's it. Don't store a reference to the watcher. It will make itself available for garbage collection 
/// once it has fulfilled its purpose. Watch the visual studio debug output for details on potentially leaked connections. 
/// Note that a connection could possibly just be taking its time and may eventually be closed properly despite being flagged by this class. 
/// So take the output with a pinch of salt. 
/// </summary> 
public class ConnectionLeakWatcher : IDisposable 
{ 
    private readonly Timer _timer = null; 

    //Store reference to connection so we can unsubscribe from state change events 
    private SqlConnection _connection = null; 

    private static int _idCounter = 0; 
    private readonly int _connectionId = ++_idCounter; 

    public ConnectionLeakWatcher(SqlConnection connection) 
    { 
     _connection = connection; 
     StackTrace = Environment.StackTrace; 

     connection.StateChange += ConnectionOnStateChange; 
     System.Diagnostics.Debug.WriteLine("Connection opened " + _connectionId); 

     _timer = new Timer(x => 
     { 
      //The timeout expired without the connection being closed. Write to debug output the stack trace of the connection creation to assist in pinpointing the problem 
      System.Diagnostics.Debug.WriteLine("Suspected connection leak with origin: {0}{1}{0}Connection id: {2}", Environment.NewLine, StackTrace, _connectionId); 
      //That's it - we're done. Clean up by calling Dispose. 
      Dispose(); 
     }, null, 10000, Timeout.Infinite); 
    } 

    private void ConnectionOnStateChange(object sender, StateChangeEventArgs stateChangeEventArgs) 
    { 
     //Connection state changed. Was it closed? 
     if (stateChangeEventArgs.CurrentState == ConnectionState.Closed) 
     { 
      //The connection was closed within the timeout 
      System.Diagnostics.Debug.WriteLine("Connection closed " + _connectionId); 
      //That's it - we're done. Clean up by calling Dispose. 
      Dispose(); 
     } 
    } 

    public string StackTrace { get; set; } 

    #region Dispose 
    private bool _isDisposed = false; 

    public void Dispose() 
    { 
     if (_isDisposed) return; 

     _timer.Dispose(); 

     if (_connection != null) 
     { 
      _connection.StateChange -= ConnectionOnStateChange; 
      _connection = null; 
     } 

     _isDisposed = true; 
    } 

    ~ConnectionLeakWatcher() 
    { 
     Dispose(); 
    } 
    #endregion 
} 
+0

Esto nos ayudó a encontrar una conexión que se abrió y nunca se cerró . Clase realmente genial :) ¡Muchas gracias! – Challe

+0

¡Maravilloso! Me alegra saber que esto podría ser útil para otros. – LOAS

Cuestiones relacionadas