Perdida de conexión en consultas MySql/MariaDb

64 views
Skip to first unread message

Vicente C.

unread,
Feb 3, 2023, 10:59:26 AM2/3/23
to ado-h...@googlegroups.com, oo...@googlegroups.com
Hola a tod@s:

    Tengo un par de usuarios que por vivir en zonas rurales, la
conexión a internet ADSL/4G no es la mejor del mundo por no decir que
están más tiempo desconectados que conectados.

    En ambos casos tienen alojados los datos con los que trabajan en un
servidor vps(diferente alojamiento para cada usuario, no es la misma
empresa, una es Cubenode y otra Icloud) al cual pese a la mala conexión
que tiene, suelen trabajar sin problemas aproximadamente el 95% del
tiempo. El problema está en que falta un 5% y suele pasar cuando más lo
necesitan. Los cortes que tienen no les deja sin servicio minutos, el
problema es en momentos puntuales y la reconexión es prácticamente
inmediata. Pese a que tengo definida en mi aplicación una conexión
automática en caso de perdida... hay veces que no surte efecto y les
sale el mensaje de error en pantalla.

    He estado mirando ejemplo en la red pero no he encontrado o no he
sabido buscar bien, una forma de realizar una consulta(el tipo select) y
que en caso de que haya fallo en la conexión que se reconecte y vuelva a
realizar la consulta.

    ¿Alguien dispone de un ejemplo práctico en el cual realice dicha
operación?

    Un saludo.

Nippur Lagash

unread,
Feb 3, 2023, 12:26:44 PM2/3/23
to ado-h...@googlegroups.com, oo...@googlegroups.com
Hola Vic, no se que método usas para chequear la conexión y reconectar.
Suponiendo que usas el método ping, lo meteria en un while que salga por exito o que espere 10 minutos +-.

start=1
max=600 (10 minutos)
error = 0
while objeto_cnx-> ping()  do
     sleep(1)  espera 1 segundo
     start++
     if start > max
        error = 1
         exit
end
if error == 1
     "vaya a tomar un café"

Algo así se me ocurre.

Saludos,
Fer.MDQ


--
Has recibido este mensaje porque estás suscrito al grupo "ADO Harbour" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a ado-harbour...@googlegroups.com.
Para ver este debate en la Web, visita https://groups.google.com/d/msgid/ado-harbour/80194b2b-48b4-943a-11a0-7c6e4c2dbd20%40gmail.com.


--
Nippur
Mar del Plata
Buenos Aires
Argentina

David Field

unread,
Feb 3, 2023, 6:59:43 PM2/3/23
to ADO Harbour
Hola Vic,

La pérdida de la conexión puede ser por varias causas, el error que nos muestra harbour es "0x80004005"
Al consultar el error nativo de ADO este puede ser varios
            OleError := oConn:oC:Errors[0]
                IF OleError:NativeError = 2003        // se ha perdido conexión a internet
                    lOk := ReConnect( @cOpt )
                ELSEIF OleError:NativeError = 2013        // Se ha perdido la conexión ADO
                    lOk := ReConnect( @cOpt )
*                ElseIf OleError:NativeError = 2006        // Server has gone away
*                    lOk := ReConnect( @cOpt )
                Else    // No se conoce el error
                    cOpt += CRLF+ "MySQL Native Error "+STR(OleError:NativeError)

La primera y más común es que se pierda la conexión a internet (culpa del servicio de internet), la segunda es que se haya perdido la conexión con el motor SQL (posible cuando haya pasado mucho tiempo de inactividad, etc.), la menos común es que se pierda la conexión con el servidor (siempre y cuando este sea dedicado) y cuando esto sucede no hay nada que hacer hasta que vuelva a estar disponible...

Como bien mencionas, a veces se realiza una reconexión automática pero a veces esto resulta en un TIMEOUT y por tanto el mensaje de error.

Lo que mejor me ha funcionado para esto es realizar una reconexión.
Para esto es necesario que 'atrapes' el error y realizar la reconexión, PERO ado te da error si intentas cerrar la conexión cuando tienes recordsets abiertos y te da error si intentas utilizar el método OPEN del objeto conector si este está abierto, por lo tanto, mi solución fue abrir un nuevo objeto conector, asignar a todos los recordsets abiertos la nueva conexión y luego cerrar la conexión vieja.

Para actualizar la conexión de los recordset, cada vez que abro uno lo agrego a un arreglo y cada vez que cierro uno lo quito de ese arreglo y cuando requiero reasignar la conexión lo realizo en un método que creé llamado UpdateAdo que basicamente recorre el arreglo y asigna la nueva conexión.

METHOD PROCEDURE UpdateAdo(o)
*-----------------------------------------------------------------------------*
    AEVAL(::AdoArray, {|a| a:oRs:ActiveConnection := o})
Return


Esta es la forma en que yo lo hago.
            If oConn:oC:State = 0
                oCNew := oConn
            Else
                lNew := .T.
                oCNew := ADOConn()            // Crear nueva conexion
            Endif
             lRetry := .T.  
            oCNew:Open()                // Abrir
            While lRetry
                if oCNew:State = 0
                    if MsgYesNo("Se ha perdido la conexión al servidor"+hb_osNewLine()+;
                                    "        ¿Desea reintentar?", "Error de conexión")
                        oCNew:Open()                // Abrir
                    Else
                        lRetry := .F.
                    Endif
                else
                    lRetry := .F.
                    If lNew
                        oConn:UpdateAdo(oCNew:oC)            // Actualizar Recorsets con conexion
                        oControl:oSql:oC:Close()                      // Cerrar conexion actual
                        oControl:oSql:oC := oCNew:oC            // asignar nueva conexion
                    Endif
                endif
            Enddo 

Es algo engorroso pero no he encontrado otra forma de TRATAR de corregir esto.

Saludos,
David Field

Vicente C.

unread,
Feb 5, 2023, 2:52:42 PM2/5/23
to ado-h...@googlegroups.com

Buenas tardes David:

    Entiendo que se debe modificar la rutina de error de Ado(ADOError) para que capture, en mi caso el error 2013 y por si acaso el 2013.

    He realizado esos cambios en dicha rutina y al quedarse sin conexión con el servidor se queda "colgado" el programa y cuando vuelve a tener conexión es cuando sale el error pero muestra el mensaje de error de mi rutina(la que se encarga de generar el archivo en disco con los datos de dicho error y deja registrado que se ha perdido conexión con el servidor). No pasa para nada por la función ADOError. ¿No debería ir a la rutina de error de Ado y allí decidir que se hace?

    Creo que me estoy liando un poco con este tema jejeje.

    Un saludo.

--
Has recibido este mensaje porque estás suscrito al grupo "ADO Harbour" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a ado-harbour...@googlegroups.com.

David Field

unread,
Feb 6, 2023, 5:31:02 AM2/6/23
to ADO Harbour
Vic,

Esto no es algo sencillo, es necesario "atrapar el error" y dirigirlo, pueden darse situaciones en donde no es posible resolverlo, por ejemplo si se cae el servicio de internet, o se cae el servidor o se cae el servidor SQL.

Para "atraparlo" debes de en compasar toda llamada a SELECT con un TRY y CATCH o con un BEGIN SEQUENCE y RECOVER indicándole la rutina a ejecutar si existe error. 

Es algo difícil explicarte por este medio, sugiero que consultes la documentación relativa a BEGIN SEQUENCE.

Saludos,
David Field

Reply all
Reply to author
Forward
0 new messages