2008-09-19 13 views
9

Actualización: Parece que la consulta no arroja ningún tiempo de espera. La conexión se está agotando.Excepción de tiempo de espera de conexión para una consulta con ADO.Net

Este es un código de muestra para ejecutar una consulta. A veces, al ejecutar consultas que requieren mucho tiempo, arroja una excepción de tiempo de espera.

I no se puede utilizar alguna de estas técnicas: 1) Aumentar el tiempo de espera. 2) Ejecútelo de forma asíncrona con una devolución de llamada. Esto necesita ejecutarse de manera síncrona.

por favor sugiera cualquier otra tecnología para mantener viva la conexión mientras se ejecuta una consulta que consume tiempo.

private static void CreateCommand(string queryString, 
    string connectionString) 
{ 
    using (SqlConnection connection = new SqlConnection(
       connectionString)) 
    { 
     SqlCommand command = new SqlCommand(queryString, connection); 
     command.Connection.Open(); 
     command.ExecuteNonQuery(); 
    } 
} 
+0

Lo siento, necesito una aclaración: ¿por qué no puedes aumentar el tiempo de espera? –

+0

Está en contra de los estándares de la compañía. :(Traté de optimizar la consulta tanto como puedo, pero aún tarda algo de tiempo. – dragon

+10

Si no puede aumentar el tiempo de espera y no puede disminuir el tiempo de ejecución y tiene que hacerlo sincrónicamente, entonces ha definido un problema irresoluble. –

Respuesta

16

dado que está utilizando ExecuteNonQuery que no devuelve ninguna fila que, puede probar este enfoque basado en votación. Ejecuta la consulta de una manera asyc (sin devolución de llamada) pero la aplicación esperará (dentro de un ciclo while) hasta que se complete la consulta. Desde MSDN. Esto debería resolver el problema del tiempo de espera. Por favor pruébalo.

embargo, estoy de acuerdo con otros que usted debe pensar más sobre la optimización de la consulta para realizar menos de 30 segundos.

 IAsyncResult result = command.BeginExecuteNonQuery(); 

     int count = 0; 
     while (!result.IsCompleted) 
     { 
      Console.WriteLine("Waiting ({0})", count++); 
      System.Threading.Thread.Sleep(1000); 
     } 
     Console.WriteLine("Command complete. Affected {0} rows.", 
     command.EndExecuteNonQuery(result)); 
+0

Gracias. Esto parece estar funcionando. Esperará un poco más de tiempo si aparece algo mejor. – dragon

+0

Comprobar el resultado. Completado es redundante. – CSharper

+0

El OP indicó que es esa consulta la que agota el tiempo de espera. Ya sea sincrónico o asincrónico, un problema de tiempo de espera de consulta seguiría siendo el mismo. e.g put WAITFOR DELAY '00: 01: 00 'en su consulta. Si su comando. Timeout es 30s, esto aún arrojará un tiempo de espera de consulta de 30 segundos con llamadas asincrónicas o sincronizadas. – stephbu

0
command.CommandTimeout *= 2; 

que se duplicará el tiempo de espera predeterminado, que es de 30 segundos.

O, coloque el valor de CommandTimeout en un archivo de configuración, para que pueda ajustarlo según sea necesario sin volver a compilar.

+0

No puedo cambiar el tiempo de espera. Está en contra de los estándares aquí. ( – dragon

+0

Bummer. Perdí eso. ¡Qué mal! – core

+1

No está aumentando el tiempo de espera de la conexión, sin embargo ... solo está aumentando el tiempo de espera en el comando. En otras palabras, una vez que finaliza la vida útil del comando, también aumenta la duración del tiempo de espera. Tal vez eso es suficiente para que pueda sortear su estándar (insertar epíteto aquí)? – nathaniel

0

Si no puede aumentar el tiempo de espera, su única opción es reducir el tiempo de la consulta para ejecutar dentro del tiempo de espera predeterminado de 30 segundos.

+0

¿Está documentado esto en algún lugar? ¿Realmente no puedes aumentar la longitud, solo disminuir? – BuddyJoe

+0

Esa no es la forma en que respondí la pregunta: el usuario pregunta qué puede hacer si aumentar el tiempo de espera es * no * una opción. Así que le contesté sugiriendo que debería disminuir el tiempo en que se ejecuta su consulta para mantenerse dentro del límite de tiempo de espera. El tiempo de espera puede configurarse o desactivarse arbitrariamente. – Seibar

0

Debe dividir su consulta en varios trozos que se ejecutarán dentro del período de tiempo de espera.

+0

es solo una consulta. a veces lleva un poco más de tiempo. Estoy buscando alguna forma de mantener viva la conexión. – dragon

+0

La ÚNICA manera de mantener viva la conexión es aumentar el tiempo de espera. Eso es lo que aumenta el tiempo de espera ... mantiene viva la conexión. – Seibar

1

Tengo que estar de acuerdo con Terrapin.

Tiene algunas opciones sobre cómo bajar el tiempo. En primer lugar, si su empresa emplea DBA, recomendaría pedirles sugerencias.

Si eso no es una opción, o si quieres probar algunas otras cosas por primera vez aquí son sus tres opciones principales:

  1. romper la consulta en componentes que se ejecutan en el tiempo de espera. Este es probablemente el más fácil.
  2. Cambiar la consulta para optimizar la ruta de acceso a través de la base de datos (en general, presionar un índice lo más cerca que pueda)
  3. Cambiar o agregar índices para afectar la ruta de acceso de su consulta.
4

Primero debe verificar su consulta para ver si está optimizada y de alguna manera no se está ejecutando en los índices que faltan. 30 segundos se asignan para la mayoría de las consultas, incluso en bases de datos grandes si se ajustan correctamente. Si tiene una prueba sólida utilizando el plan de consulta de que la consulta no se puede ejecutar más rápido que eso, entonces debe aumentar el tiempo de espera, no hay otra manera de mantener la conexión, ese es el propósito del tiempo de espera para finalizar la conexión si el la consulta no se completa en ese marco de tiempo.

1

Si tiene problemas con el uso del proceso predeterminado para cambiar el valor de tiempo de espera, lo más probable es que tenga que trabajar mucho más. Las siguientes opciones vienen a la mente

  1. Validar con su DBA y otro de revisión de código que realmente se ha optimizado la consulta de la mejor manera posible
  2. El trabajo sobre la estructura de base de datos subyacente para ver si hay alguna ganancia que puede obtener en el lado DB, creando/modificando idex (es).
  3. Divídalo en varias partes, incluso si esto significa ejecutar procedimientos con múltiples parámetros de retorno que simplemente llaman a otro parámetro. (Esta opción no es elegante, y sinceramente, si su código REALMENTE va a tomar tanto tiempo, me gustaría ir a la administración y volver a discutir el tiempo de espera de 30 segundos)
+0

cierto. El problema es que la gerencia quiere que explore todas las opciones. :) – dragon

1

Recientemente tuvimos un problema similar en SQL Base de datos del servidor 2000

Durante su consulta, ejecute esta consulta en la base de datos maestra en el servidor db y ver si hay algún bloqueo que debe solucionar:

select 
    spid, 
    db_name(sp.dbid) as DBname, 
    blocked as BlockedBy, 
    waittime as WaitInMs, 
    lastwaittype, 
    waitresource, 
    cpu, 
    physical_io, 
    memusage, 
    loginame, 
    login_time, 
    last_batch, 
    hostname, 
    sql_handle 
from sysprocesses sp 
where (waittype > 0 and spid > 49) or spid in (select blocked from sysprocesses where blocked > 0) 

SQL Server Management Studio 2008 también contiene un monitor de actividad muy fresca que le permite ver el estado de su base de datos durante su consulta.

En nuestro caso, fue una cerradura NETWORKIO que mantuvo la base de datos ocupado. Fue algún código VB heredado que no desconectó su conjunto de resultados lo suficientemente rápido.

0

que tienden a rechazar el aumento del tiempo de espera de conexión/comando ya que en mi mente que sería una cuestión de tomar el cuidado del síntoma, no el problema

+2

+1 ya que deja en claro por qué probablemente tienen esta política .. –

1

Si está prohibido el uso de las funciones de la API de acceso a datos para permitir una consulta a durar más de 30 segundos, entonces tenemos que ver el SQL.

Las mejoras de rendimiento que se harán mediante la optimización del uso de ADO.NET son leves en comparación con las ganancias de la optimización del SQL.

Y ya está utilizando el método más eficiente de ejecutar SQL. Otras técnicas serían increíblemente más lentas (aunque, si realizó una recuperación rápida de sus filas y un procesamiento realmente lento del lado del cliente usando DataSets, es posible que pueda obtener la recuperación inicial en menos de 30 segundos, pero lo dudo.)

Si sabíamos si estaban haciendo inserciones, entonces tal vez usted debe utilizar inserción masiva. Pero no sabemos el contenido de su sql.

0

propiedad CommandTimeout acaba de establecer de SqlCommand a 0, esto hará que el comando que esperar hasta que la consulta termina ... por ejemplo:

SqlCommand cmd = new SqlCommand(spName,conn); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandTimeout = 0; 
1

Este es un truco feo, pero podría ayudar a resolver su problema temporalmente hasta puede solucionar el problema real

private static void CreateCommand(string queryString,string connectionString) 
    { 
     int maxRetries = 3; 
     int retries = 0; 
     while(true) 
     { 
      try 
      { 
       using (SqlConnection connection = new SqlConnection(connectionString)) 
       { 
        SqlCommand command = new SqlCommand(queryString, connection); 
        command.Connection.Open(); 
        command.ExecuteNonQuery(); 
       } 
       break; 
      } 
      catch (SqlException se) 
      { 
       if (se.Message.IndexOf("Timeout", StringComparison.InvariantCultureIgnoreCase) == -1) 
        throw; //not a timeout 

       if (retries >= maxRetries) 
        throw new Exception(String.Format("Timedout {0} Times", retries),se); 

       //or break to throw no error 

       retries++; 
      } 
     } 
    } 
0

¿Ha pensado en dividir la consulta en varios trozos más pequeños?

Además, han se ejecutó la consulta en la DTA en:

Management Studio> Herramientas> DTA

Por último, podríamos echar un vistazo a la propia consulta?

aplausos

0

has necesitado envolver su SQL dentro de un procedimiento almacenado, que parecen tener una mejor gestión de memoria. He visto tiempos de espera como este antes en el plan de instrucción sql con consultas internas utilizando ADO clásico. es decir, seleccione * de (seleccione ....) t unión interior somthingTable. Donde la consulta interna estaba devolviendo una gran cantidad de resultados.

Otros consejos 1. Realizando lecturas con la pista de ejecución con (nolock), está sucio y no lo recomiendo pero tenderá a ser más rápido. 2. También vea el plan de ejecución de sql que intenta ejecutar y reduzca el escaneo de filas, el orden en el que une las tablas. 3. busque agregar algunos índices a sus tablas para lecturas más rápidas. 4. También he descubierto que eliminar filas es muy costoso, puede tratar de limitar el número de filas por llamada. 5. Cambiar variables @table con # tablas temporales también me ha funcionado en el pasado. 6. También es posible que haya guardado un plan de ejecución incorrecto (se escucha, nunca se ve).

Esperanza esto ayuda

0

Actualización: Parece que la consulta no hace tiro ningún tiempo de espera. La conexión es con tiempo de espera.

I.o.w., incluso si no ejecuta una consulta, ¿la conexión expira? porque hay dos tiempos de espera: conexión y consulta. Todo el mundo parece enfocarse en la consulta, pero si obtienes tiempos de espera de conexión, es un problema de red y no tiene nada que ver con la consulta: la conexión primero tiene que establecerse antes de que se ejecute una consulta, obviamente.

+0

Estoy de acuerdo. dragón, no puede obtener un tiempo de espera de conexión durante la ejecución normal del comando. Muestra tu excepción con una pila. – Shrike

0

Puede valer la pena intentar buscar los resultados de nuevo.

Cuestiones relacionadas