Mantenere "viva" la connessione MySQL

Ciao, occasionalmente (in ambiente Desktop) ho dei problemi con MySQL che semplicemente si disconnette, lasciandomi un errore “MySQL has gone away”

Per ovviare al problema avrei pensato di effettuare un controllo con un metodo (chiamiamolo CheckConnessione) prima di ogni select/update che nel caso riallacci la connessione.

Si tratterebbe ora di andare a scovare tutte queste chiamate al database e anteporre questo metodo CheckConnessione, ma oggi mi passato per la mente di creare una sottoclasse di un RecordSet e di un DatabaseRecord e andare ad inserire nel loro Constructor la chiamata al metodo CheckConnessione.

Entrami i modi sicuramente genererebbero pi query di quelle necessarie al programma… ma al momento non ho altre idee di come prevenire un eventuale disconnessione dal database. Qualcuno di voi incappato nel problema e ha trovato qualche soluzione elegante ?

Grazie

fai una sottoclasse del database, ridefinisci le funzioni con cui accedi al db (sqlSelect ad esempio) e in caso di errore di disconnessione ti riconnetti e ripeti la richiesta.
Ovviamente fai anche una verifica per evitare di andare in loop nel caso il server sia proprio andato via…

Cavolo Antonio, questa tosta…

Se implemento il metodo SQLSelect in una sottoclasse di MySQLCommunityServer ovviamente mi si genera un metodo vuoto e scrivere il codice per restituire il Recordset va ben oltre i miei limiti !
Speravo in una magia sotto il cofano ma effettivamente se non ritorno nulla SQLSelect mi genera un NilObjectException con una chiamata tipo:

Dim myRec As RecordSet = myDB.SQLSelect("select id from test")

Qualcosa ho fatto… ma dubito sia quello che intendevi tu…

Ho rimosso il metodo SQLSelect (non ne vengo proprio fuori) dalla mia sottoclasse di MySQLCommunityServer e ho creato il metodo “TryQuery” (che ritorna un recordset) con questo codice:

  Dim rec As RecordSet = Me.SQLSelect("SELECT id from myTable LIMIT 1")
  If rec = Nil Then
    If not Me.Connect Then
      MsgBox "mancata connessione db"
      Quit
    End If
  End If
  
  rec = Me.SQLSelect(sqlString)
  
  Return rec

Dove “SELECT id from myTable LIMIT 1” una query a una tabella “sicura” che non pu assolutamente ritornare un nil… salvo che il database si sia disconnesso e in quel caso ritento la connessione.

Le mie query adesso hanno questo aspetto:

Dim myRec As RecordSet = myDB.TryQuery("select id from test")

Questo il massimo a cui sono arrivato, mancherebbe (immagino) un loop for con un delay di tot secondi nella parte

If not Me.Connect Then
  MsgBox "mancata connessione db"
  Quit
End If

dove se dopo un certo numero di tentativi il database non risponde allora lascio perdere e vado a bere un caff.

Pu andare ?

Si, ma cos devi andare a riscrivere il codice dove chiami la select.

Invece nella sottoclasse in SqlSelect potresti fare:

dim rec as recordSet=super.sqlSelect(sql) //Chiamo la super classe per la vera select
if rec=nil and errorCode=<quello della disconnessione> then  //il rec nil potrebbe essere lecito, controlla la connessione
    if me.connect then //Riprovo a connettermi
        return me.sqlSelect //Mi richiamo
    else
        quit  //esco
    end if
end if
return rec

in questo modo la select sempre la stessa nel codice (cambi la classe di riferimento)
Magari potresti mettere un contatore di tentativi di riconnessione (con uno static) per evitare di richiamarti in eccesso, ma visto che esci in caso di mancata connessione, potrebbe non essere necessario

“Super” mi mancava, grazie infinite Antonio!

Trovo molto interessante domanda a questo proposito. Sto usando Google Traduttore perch non ho imparato a scrivere in italiano. Anche se capisco bene.

Penso che la tua domanda si riferisce a “Scope”. E 'importante capire questo concetto per utilizzare correttamente realbasic bene. Se si imposta la “variabile” in App (App.db come SQLiteDatabase), questo problema si verifica?

Non so se questo messaggio pu essere comprimibile. Tutto funziona Goodle Translate. :slight_smile:

Ciao Armando,

Credo di non aver capito bene la tua domanda, comunque la variabile del database inserita in un modulo per cui accessibile da ogni parte del codice.

Temo cumunque che indipendentemente da dove la so dichiari il server Mysql che ogni tanto chiude il collegamento.

Le mie scuse. Non avevo capito che la variabile viene dichiarata in un modulo. L’italiano parlato in molto più facile per me che la scrittura italiana.
Saluti!

Nessun problema :slight_smile:
Ciao !

Scusa @Antonio Rinaldi , ho ancora un punto oscuro… nella sottoclasse di MySQLCommunityServer ho inserito il metodo “InsertRecord” e ho messo questo codice …

super.InsertRecord(tableName, dbRecord)
  
if Me.Error Then
    System.DebugLog "LOCAL - "+Str(Me.ErrorCode) + " - " + Me.ErrorMessage
end if
  
if Me.Error and Me.errorCode = 2006 then
    if me.connect = False then Return False
    super.InsertRecord(tableName, dbRecord)
end if
  
Return True

in pratica specifico un return type come Boolean eppure il compilatore non mi da errori di compilazione su una istruzione tipo

databaseLocale.InsertRecord "myTable", myRec

É normale che agisca così ?

Grazie.

le parentesi in xojo ho notato sono una cosa superflua

cint(pippo)
cint pippo

nthfield(prova,"§",1)
nthfield prova, “§”, 1
sono la stessa identica cosa …

@Matteo Lovatti
Insert record non ha un valore di ritorno per cui se chiami
databaseLocale.InsertRecord “myTable”, myRec
in realtà chiami la super

Tu hai definito (da quello che ho capito) una
function insertRecord ( tabella as string, record as databaserecord) as boolean

@Massimiliano Chiodi
Se aspetti in valore di ritorno le parentesi sono utili…
Se lo ignori è come se chiamassi una sub per cui puoi ometterle

dim pippo as String dim n as Double n=cdbl(pippo) //OK n=cdbl pippo //KO call cdbl pippo //OK call cdbl(pippo) //OK