.net - net - pool de conexiones sql server
¿El grupo de conexiones de SQL Server no detecta conexiones cerradas? (2)
Durante años, he experimentado problemas muy extraños en todas mis aplicaciones web que se conectan a un servidor SQL.
El problema es que si algo le sucede al servidor de la base de datos (reinicio del servidor u otro problema), la aplicación web deja de funcionar a partir de ese momento, incluso si el servidor de la base de datos está activo y mucho después.
Lo que sucede es que todas las operaciones de ADO.NET (ExecuteNonQuery, CreateReader, BeginTransaction, ...) fallan con una excepción InvalidOperationException : " Operación no válida . La conexión está cerrada ". Parece que una llamada a SqlConnection.Open () recupera una conexión del grupo de aplicaciones que está ... ¡cerrado!
De acuerdo con la documentación, la agrupación de conexiones debería eliminar automáticamente las conexiones cortadas de la agrupación de conexiones, pero al parecer una conexión cerrada no se considera "cortada", por lo que la llamada a SqlConnection.Open () felizmente devuelve una conexión cerrada, asumiendo que es Abierto, sin comprobar esto.
Mi solución actual es verificar el estado de la conexión justo después de abrirla:
using (SqlConnection connection = new SqlConnection( connectionString ))
{
connection.Open();
if (connection.State != ConnectionState.Open)
{
SqlConnection.ClearAllPools();
connection.Open();
}
// ...
}
Esta solución parece funcionar por ahora, pero no me siento cómodo haciendo esto.
Así que mis preguntas son:
- ¿Por qué SqlConnection.Open () devuelve conexiones cerradas desde el grupo de conexiones?
- ¿Mi solución es válida?
- ¿Hay una mejor manera de manejar esto?
Hace un tiempo hice una investigación similar sobre la agrupación de conexiones, por una razón ligeramente diferente, pero espero que sea de alguna utilidad. Lo que encontré es:
- incluso cuando cierra una conexión en el código, se devuelve al grupo sin que la conexión realmente se cierre, lista para su uso posterior.
- si esa conexión se corta (es decir, se reinicia SQL Server), cuando la conexión se devuelve desde el grupo para que otra persona que llama la use y esa persona que realiza una llamada. Esto es parte del beneficio de rendimiento de la agrupación de conexiones, ya que no se está volviendo al servidor de base de datos para conectarse.
- cuando realmente intenta ejecutar un comando contra la conexión (por ejemplo, ExecuteNonQuery) es en ese punto que realmente lanza una excepción
Las conexiones se eliminan automáticamente de la piscina, lo que descubrí fue que esto ocurría normalmente unos minutos después de su último uso. Por lo tanto, puede tratarse de un problema de tiempo, y se están solucionando, pero no antes de que las conexiones se intenten volver a utilizar.
Estos fueron algunos artículos que miré, en ese momento:
Sql Server Grupo de Google
Uso de la agrupación de conexiones en ASP.NET
Editar:
Parece extraño que la mala conexión permanezca en la agrupación para siempre. ¿Está seguro de que definitivamente lo es, y no es solo una mala conexión múltiple? Si está seguro, entonces parece que esas conexiones no se están liberando correctamente dentro de su código. This es otro muy buen artículo que leí hace un tiempo, que dice (cita):
Conexiones de lavado automático
Si una conexión agrupada permanece en el estado "cerrado pero reutilizable" entre 4 y 8 minutos (un intervalo elegido al azar), el mecanismo de agrupación de conexiones cierra la conexión física y descarta la conexión agrupada. Eso es a menos que el número de conexiones restantes sea mayor que el mínimo configurado para el grupo (el valor predeterminado es 0). Tenga en cuenta que la aplicación debe haber cerrado una conexión (y haber sido liberada de nuevo al grupo) antes de que pueda estar sujeta a la liberación automática. Si no cierra la conexión en el código o huérfano del objeto Connection, el mecanismo de agrupación no hará nada. No, no hay argumentos ConnectionString para cambiar el valor del tiempo de espera.
Hemos visto el mismo problema desde C ++ usando ADO. Hace unos años, después de trabajar con el Soporte de Microsoft, también implementamos una lógica de reintento similar en el código y restablecimos el grupo de conexiones que resolvió el problema.
Si hay una mejor solución, la gente de Soporte de Microsoft no lo sabía o no estaba compartiendo (en ese momento de todos modos).