Seite 1 von 1

[gelöst] MySql auto-reconnect

Verfasst: 31. Juli 2008 14:11
von pfid
Hallo,

ich wollte fragen ob es irgendeine Patentlösung gibt, um die Verbindung zu einer MySql Datenbank automatisch wiederherzustellen wenn man eine QSqlQuery ausführen möchte und die Verbindung unterbrochen wurde.
Ich habe nur beschränkt Möglichkeiten, das Timeout serverseitig hochzusetzen (vom Provider aus steht das irgendwo um eine Minute). Ich will nicht zwangsläufig eine stundenlange Verbindung, ich möchte aber keine Fehler bekommen bzw. nicht das Programm neu starten müssen wenn die Verbindung weg ist. Ein Timer-Event dass einmal pro Minute eine Abfrage ausführt möchte ich auch nicht unbedingt machen, wäre am Ende aber vielleicht eine Notlösung. Dann aber im eigenen Thread, da ich nicht will dass mir der Timer irgendwie im Gui Thread umpfuscht.

Am liebsten wärs mir, wenn direkt beim QSqlQuery::exec festgestellt werden könnte, ob die Verbindung weg ist, und diese dann direkt neu aufgebaut wird. Also vielleicht so:

Code: Alles auswählen

if (!query.exec())
   maybe_reconnect_and_repeat_query(query);
Hatte sowas ähnliches schonmal versucht, und nach einem QSqlDatabase::close() und QSqlDatabase::open() war die Verbindung immer noch nicht wieder da. Wie macht man das richtig?

Richtig nervig wirds dann allerdings, wenn ich so einen Mechanismus auch für die QSqlTableModels implementieren muss. Da müsste ich dann beim auto-Submit bzw. beim select mitbekommen, dass die Verbindung weg ist. Dann die Verbindung neu aufbauen und die Abfrage erneut ausführen.

Qt bringt da meines Wissens noch nichts mit (nicht für MySql, für die anderen iirc schon). Hat da jemand eine gute Idee?


[edit] gelöst, ähnlich wie hier:

http://qtforum.de/forum/viewtopic.php?t ... 51738fd333

qt quellen/qmysqldriver::open() angepasst und manuell ein mysql_options mit MYSQL_OPT_RECONNECT eingefügt. funktioniert tadellos.

Verfasst: 1. August 2008 16:26
von patrikD
Hi pfid,

bin mir nicht ganz sicher aber versuch mal unter QSqlDatabase::setConnectOptions:
MYSQL_OPT_RECONNECT=1

Dann dürfte das der Server für dich übernehmen.

lg

Verfasst: 1. August 2008 17:06
von pfid
Cool, werde ich mal probieren. Wäre schön wenn das klappt :)

[edit] trotzdem noch die frage, wie man die datenbank ordentlich neu verbindet. auch wenn o. g. feature funktioniert, möchte ich die möglichkeit, die datenbank neu zu verbinden, in form von buttons anbieten, für den fall dass jemand das programm nutzt, und seine mysql version das reconnect feature noch nicht unterstützt (<5.0.1.3?)

Verfasst: 1. August 2008 17:58
von patrikD
open() und close() werden da nicht helfen. denke du musst die connection wegwerfen über "removeDatabase".
Aber:
Warning: There should be no open queries on the database connection when this function is called, otherwise a resource leak will occur.
Haben damit aber schlechte Erfahrung gemacht. Musst sehr genau darauf achten das alle Queries freigegeben werden, sonst gibts meker, nicht nur ein Speicherleck!
Andere Möglichkeit ist einfach ne neue Connection mit addDataBase zu machen(am besten mit anderem Namen), das dürfte funktionieren und die alte wird serverseitig ja zurückgesetzt und das Qt-Modul kümmert sich um den Speicher der alten.

lg

Verfasst: 1. August 2008 23:15
von pfid
Scheint nicht zu klappen. Bekomme immer noch
MySQL server has gone away QMYSQL: Unable to execute query
Der Code:

Code: Alles auswählen

db->setConnectOptions("MYSQL_OPT_RECONNECT=1");

Verfasst: 2. August 2008 12:35
von patrikD
Schade :(
Aber wenn Patrik08 recht hat, dann ist es wohl leider wirklich so, dass QT nur die paar Connection-Parameter unterstützt die in der Doku angegeben sind. Aber vielleicht hilft dir ja der Verbindungs-Check aus dem Thread "Shard mem und MySql".
Aber wenn du ne Lösung finden solltest wäre es toll wenn du sie posten könntest, würde mich auch interessieren.

Lg

Verfasst: 4. August 2008 13:07
von pfid
Noch ne Idee. "MYSQL_OPT_RECONNECT=1" gibt es faktisch ja bei MySQL (Link), und wird per
mysql_options()
der MySQL API gesetzt, sofern man direkt die MySQL API verwendet.

Könnte man dann nicht in den Qt Quellen schauen, wo die DB-Verbindung geöffnet wird, und an dieser Stelle hardcoded ein mysql_options() Statement absetzen?
Bleibt nur die Frage ob das QSqlDatabase::setConnectionOptions() nicht bereits selbst macht. Jedenfalls kriege ich bei
QSqlDatabase::setConnectionOptions(MYSQL_OPT_RECONNECT=1)
auf der Konsole den Fehler, dass MYSQL_OPT_RECONNECT keine gültige Option sei, was ja laut Google und Mysql Doku nicht stimmt. D.h. Qt hat ne eigene Liste an gültigen Parametern, und MYSQL_OPT_RECONNECT ist wohl nicht dabei.

Werde mir das heute abend mal anschauen, muss Qt eh nochmal durchkompilieren weil ich demnächst statisch linken möchte.

Verfasst: 4. August 2008 15:18
von patrikD
Hi pfid,

ist tatsächlich so, dass QT die Parameter selbst mapped und das dieser nicht unterstützt wird (siehe "setOptionFlag" in qsql_mysql.cpp).
Das gleiche Problem hab ich gerade auch mit shared-mem connection. Bin gerade bei es einzubauen und wenn es funzt poste ich es.

lg

Verfasst: 4. August 2008 16:07
von pfid
patrikD hat geschrieben: ist tatsächlich so, dass QT die Parameter selbst mapped und das dieser nicht unterstützt wird
Das finde ich aber ziemlich schräg. Wieso wird nicht einfach alles 1:1 durchgereicht und bei Fehler entsprechend reagiert?
Return Values

Zero for success. Non-zero if you specify an unknown option.
Nun denn, vielleicht ist das tatsächlich eine Option. Würde mich freuen wenn das klappt.

Verfasst: 4. August 2008 19:10
von patrikD
fürs autoreconnect ist es relativ simpel:

in der qsql_mysql.cpp:(~zeile 1045)

Code: Alles auswählen

static void setOptionFlag(uint &optionFlags, const QString &opt)
.....
    else if (opt == QLatin1String("MYSQL_OPT_RECONNECT"))
        optionFlags |= MYSQL_OPT_RECONNECT;
    else
        qWarning("QMYSQLDriver::open: Unknown connect option '%s'", opt.toLocal8Bit().constData());
einbauen. Und den mysql plugin neu kompilieren. Den Rest übernimmt das Plugin schon, wenn ich den Code richtig deute. Kanns gerade leider nicht austesten aber feedback wäre toll.

lg