2012-05-25 19 views
7

Buscar en Google este mensaje de error ADO indica que se encuentra comúnmente en el desarrollo ASP.NET, pero no he encontrado mucha mención de cuándo ocurre en las aplicaciones Delphi. Tenemos algunos sitios de clientes que experimentan problemas transitorios de red, y este es el mensaje de error sintomático. Podemos duplicarlo en pruebas de oficina fácilmente; Simplemente cerrar un servicio MS SQL Server, mientras que su objeto TADOConnection Delphi está conectado a una base de datos en esa instancia del servidor y se obtiene esta excepción: (¿o usted)Recuperación automática cuando DBNETLIB ConnectionWrite Error de red general hace que las conexiones ADO se desconecten en las aplicaciones Delphi?

[DBNETLIB][ConnectionWrite (send()).]General network error. Check your network documentation. 

Sí, la captura de esta excepción, y sabes que este error ha ocurrido. Excepto que se trata de una aplicación de 800 KLOC + con más de 10.000 bloques de prueba-excepto en las acciones de la base de datos, cualquiera de los cuales podría fallar con este error.

TADOConnection tiene algunos eventos de error, ninguno de los cuales se dispara en este caso. Sin embargo, la conexión ADO en sí tiene una falla una vez que esto ocurre, incluso si reinicia la base de datos SQL, TDOConnection.Connected sigue siendo cierto, pero le está mintiendo. Realmente está en un estado de falla.

Así pues, mi pregunta es:

¿Se puede detectar este estado de fallo, y recuperarse de ella, de cualquier manera que es menos trabajo que va en 10.000 individuo try-excepto los bloques y el establecimiento de alguna mundial "volver a conectar la variable global ADO"?

Espero que haya una manera de entrar en TADOConnection.ConnectionObject (el objeto OLEDB COM ADO bruto subyacente) y detectar esta condición de error cuando estamos comenzando una nueva consulta, para que podamos restablecer la ADOConnection y continuar la próxima vez que ejecutemos una consulta. Dado que nuestro código está organizado de una manera que nos permitiría detectar esto "después de la falla" mucho más fácilmente de lo que nos permitiría hacerlo de la manera en que lo haría en una aplicación de demostración de 10 líneas.

This other SO question se pregunta por qué sucede, es decir no lo que estoy pidiendo, por favor no me dan respuestas "prevención", que sé de ellos ya, estoy buscando para una recuperación y detección-de- técnica de conexión ADO detenida, salvo capturar las excepciones. De hecho, este es un buen ejemplo de excepciones que salieron mal; ADO es un objeto schrodingers-cat en este modo de falla.

Conozco los artículos de MS Knowledgebase y las diversas soluciones que flotan en Internet. Pregunto acerca de RECUPERACIÓN sin perder los datos de los clientes, una vez que la condición de error (que a menudo es transitoria en nuestra situación) ha desaparecido. Eso significa que congelamos nuestra aplicación, mostramos la excepción al cliente y, cuando el cliente hace clic en Reintentar o Continuar, intentamos reparar y continuar. tenga en cuenta que nuestro código actual tiene un millón de código try-except-log-and-continue, que se interpondrá en nuestro camino, por lo que espero que alguien responda que un manejador de aplicaciones para excepciones no controladas es la mejor manera, pero lamentablemente no podemos usarlo Realmente espero sin embargo que sea posible detectar un objeto de conexión ADO congelado/fallado/muerto.

Esto es lo que tengo:

try 
    if fQueryEnable and ADOConnection1.Connected then begin 
    qQueryTest1.Active := false; 
    qQueryTest1.Active := true; 
    Inc(FQryCounter); 
    Label2.Caption := IntToStr(qQueryTest1.RecordCount)+' records'; 

    end; 
except 
     on E:Exception do begin 
     fQueryEnable := false; 
     Memo1.Lines.Add(E.ClassName+' '+E.Message); 
     if E is EOleException and Pos('DBNETLIB',E.Message)>0 then begin 
      ADOConnectionFaulted := boolean; { Global variable. } 
     end; 
     raise; 
     end; 
end; 

El problema con la solución anterior es que tengo que copiar y pegar unos 10.000 lugares en mi solicitud.

+0

Algo así como un TTimer y una simple consulta como SELECT @@ VERSION y variable de estado global? – whosrdaddy

+0

Nunca tuve que enfrentar este problema ya que he creado un contenedor para todas mis aplicaciones que manejan este tipo de situaciones. Un poco apesta si necesitas cambiar 10k ubicaciones :(. – whosrdaddy

+0

Sí, un "perro guardián ADO". Y otro malvado TTimer. :-) –

Respuesta

8

Bueno, nadie ha respondido esta pregunta, y creo que algún seguimiento sería útil.

Aquí es lo que he aprendido:

  • No hay situaciones donde fiables en un entorno de prueba se puede reproducir este error de red general. Es decir, estamos lidiando con resultados irreproducibles, que es donde muchos desarrolladores se lanzan al hackeo del mal en un intento de "parchear" sus sistemas rotos.

  • La reparación de la falla subyacente siempre ha sido mejor que arreglarla en código, cuando la biblioteca de SQL muestra un "Error general de red". Ninguna reparación nunca se ha demostrado que es posible, porque por lo general significa "la red es tan poco fiable que TCP se ha renunciado a la entrega de mis datos", esto ocurre cuando:

    • dispone de un cable de red incorrecta.

    • Tiene direcciones IP duplicadas en una red.

    • Tiene servidores DHCP en duelo que manejan diferentes pasarelas predeterminadas.

    • Tiene segmentos de ethernet locales que tienen poca conectividad entre ellos.

    • Tiene un conmutador o concentrador de Ethernet que está fallando.

    • Estás siendo bloqueado de forma intermitente por un firewall que no funciona.

    • Es posible que su cliente haya cambiado algo en su red y que ahora no pueda usar su software. (Esto último realmente sucede más de lo que podría pensar)

    • Alguien puede haber configurado un alias SQL usando cliconfg u otros elementos de configuración del lado del cliente que son específicos de la configuración de registro de una sola estación de trabajo, y esta configuración local puede dar como resultado comportamiento que es difícil de diagnosticar y puede estar limitado a una o varias estaciones de trabajo en una red grande.

Ninguna de las anteriores puede ser detectado y reportado ya sea a nivel TCP o SQL. Cuando SQL finalmente se da por vencido, y le da a este "Error General de Red", ninguna cantidad de engatusamiento de mi software hará que se deshaga, y aunque lo hiciera, estaría haciendo un "try/except"/ignorar "antipattern". Este error es tan grave que debemos elevarlo hasta el usuario, registrarlo en el disco en un registro de errores, renunciar (salir del programa) y decirle al usuario que la conexión de red no funciona.

+1

Otro lugar donde esto sucede es donde Windows tiene TCP/IP V4 y TCP/IP V6 ambos habilitados en una computadora en una red de área local, y no tiene IP V6 habilitado en el otro lado de la red, y de todos modos LLMNR o algo más en Windows aún intenta usa IP V6 cuando no debería. La rareza se produce. –

+0

+1. Tenga en cuenta que en el mundo de los dispositivos móviles es mucho más común reintentar automáticamente (por lo general, utilizando un retroceso exponencial: https://www.google.com/search?q=connection+retry+algorithm) porque las redes inalámbricas (WiFi, G3, BT) son tan poco confiables. Pero en ambos entornos, en algún momento, debe preguntarle a un usuario qué hacer (si no se trata de un proceso de servidor). –

+0

Comentario realmente tardío aquí, pero [esta respuesta] (http://stackoverflow.com/questions/3211625/general-network-error-after-a-night-of-inactivity/3211950#3211950) describe una posible forma de repetir este error. Aunque esos pasos probablemente serían muy difíciles de seguir en cualquier aplicación real sin forzarlo a detenerse en algún tipo de punto crítico de depuración, ya que el tiempo entre "abrir una conexión DB" y "usar la conexión DB" sería típicamente casi instantáneo. – jadarnel27

2

he visto que esto ocurra debido a la mala codificación también ..

Si abre un conjunto de registros utilizando una conexión y si vuelve a utilizar la misma conexión en un bucle para otro conjunto de registros, mientras que la primera conexión no es cerrado entonces que puede causar errores similares.

Otra ocasión muy rara en las aplicaciones web es que mientras se recicla el grupo de aplicaciones puede recibir un error similar.

Tenemos diferentes sitios en un mismo servidor donde he notado que con la misma aplicación pero con diferentes personalizaciones, solo un sitio está causando este problema. Eso lleva a los hallazgos anteriores.

Este blog me ayudó a encontrar los temas:

http://offbeatmammal.hubpages.com/hub/Optimising_SQL_Server

+0

Eso suena como un tipo de resultado potencial bastante "aleatorio" de intercambio de objetos malo/abismal entre subprocesos –

Cuestiones relacionadas