Seite 1 von 1
Datenbankverbindung "abschiessen"
Verfasst: 19. Februar 2011 10:00
von chrislo1976
Hallo zusammen!
Weiß jemand von euch ob es möglich ist eine QSqlDatabase-Verbindung "gewaltsam" zu kappen, wenn z.B. eine Query nach einer gewissen Zeit nicht abgeschlossen wird?
In meinem Testfall läuft eine Datenbankverbindung und -query in einem separaten Thread. Es werden zyklisch Daten von der DB ausgelesen. Nach jedem Auslesen wird ein Signal an den Hauptthread gesendet.
Der Hauptthread prüft ob dieses Signal regelmäßig ankommt. Wenn nicht, und wenn dann eine gewisse Zeit abgelaufen ist, wird der Thread beendet, bzw. das versucht.
Aber selbst wenn der Thread terminiert wurde scheint die Datenbank noch zu bestehen, weil dies im Aktivitätsmonitor von MSSQL so angezeigt wird.
Ich habe sowohl die moveToThread-Variante probiert, als auch ein Ableiten von QThread, wo die DB-Klasse dann in QThread::run erzeugt wird.
Hat jemand von euch sowas schon mal gemacht/gebraucht und kann mir dazu evtl. ein paar Infos und Tipps geben?
Danke!
Gruß,
Christian
Verfasst: 19. Februar 2011 10:34
von franzf
QSqlDatabase speichert die angelegten connections selber. Wenn dein Thread azs dem Scope läuft, werden die Connections NICHT gelöscht.
Was du versuchen kannst:
Nach dem Timeout deine QSqlDatabase per close() gewaltsam schließen, danach per QSqlDatabase::removeDatabase() deine DB entfernen.
Lies dir aber durch, was zu close() und removeDatabase() steht.
Ich würde aber versuchen herauszubekommen, was die DB veranlasst nicht im Zeitrahmen zu antworten.
Gib dir vor dem exec() den Query-String aus. In welchen Intervallen schickst du Queries an die DB? Wie viele Tabellen/Datensätze sind in der DB? Kannst du die Queries optimieren? Wie lange wartet dein Timer? Was machst du während dem Query im Hauptthread? Kann es sein, dass einfach nur der DB-Thread blockiert wird?
Evtl. ist es aber auch nur ein Performanceproblem des MS Sql Servers:
http://www.solvatec.com/index.php/progr ... sql-server
Verfasst: 19. Februar 2011 10:47
von solarix
Wenn nicht, und wenn dann eine gewisse Zeit abgelaufen ist, wird der Thread beendet, bzw. das versucht.
Aber selbst wenn der Thread terminiert wurde scheint die Datenbank noch zu bestehen, weil dies im Aktivitätsmonitor von MSSQL so angezeigt wird.
Ich weiss jetzt nicht,
wie du versucht hast, den Thread zu beenden. Aber ich kann zumindest sagen, dass dies äusserst schwierig ist und man daher eigentlich nie einen Thread "gewaltsam" beenden sollte.
Variante "delete": funktioniert sowieso nicht, weil die run-Methode ein unabhängiger Thread darstellt und daher einfach weiterläuft (bis zum Crash, weil die Membervariabeln freigegeben wurden).
Variante "terminate": funktioniert zwar, aber lässt die globalen Ressourcen (Heap, Filedeskriptoren/Sockets) unangetastet. Deswegen entstehen so Memoryleacks, offene Files und eben auch offene TCP/IP-Connections.
Daher: siehe franzf: versuche herauszufinden, was genau denn schiefgeht..
hth..
Edit: brauchst du im Mainthread weitere DB-Connections..?
Verfasst: 19. Februar 2011 11:11
von chrislo1976
Hallo!
Danke für eure Hinweise, manches davon ist/war mir schon bewusst.
Ich würde diese Vorgehensweise ja auch gern vermeiden, aber:
Wir sprechen im konkreten Fall eine Oracle-Datenbank an. Im produktiven Einsatz ist derzeit noch ein Visualisierungssystem, das eine eigene Interpretersprache besitzt.
Darin besteht schon das Problem dass eine Abfrage teilweise tagelang nicht zurückkehrt, solange bis das eben bemerkt wird. Leider kann man diese Visu nur wieder in Gang bringen, wenn man diese neustartet.
Manuell! Das darf deswegen keine Dauerlösung sein.
Diese Oracle-DB gehört nicht zu unserem System, die betreut und verwaltet der Kunde selbst. Wir lesen von dort nur gewisse Daten zyklisch aus.
Auf Anfrage hat mir der Kunde auch bestätigt dass es dort Datenbank- und/oder Netzwerkprobleme gibt. Genaueres ist aber nicht zu erfahren.
Natürlich könnte ich den schwarzen Peter auch dem Kunden zuschieben, aber da tut man sich auch nicht immer einen Gefallen...
Ich hab dann einen kleinen Dienst erstellt, der das Auslesen aus der Oracle-DB übernimmt (testweise). Als SQL-Treiber habe ich das OCI-Plugin kompiliert und verwendet.
Mit diesem Dienst tritt das Problem genau so auf. Mit C++/Qt hab ich aber mehr Möglichkeiten darauf zu reagieren, deswegen hab ich diese Versuche der Zwangsbeenden gemacht.
Ein Kollege meinte dass es evtl. eine mögliche Lösung wäre, die Datenbankabfrage nicht in einen separaten Thread sondern einen separaten Prozess auszulagern.
Im Endeffekt eine eigene kleine Anwendung. Diese Anwendung könnte man im Dienst starten und, wenn wieder so ein timeout vorkommt, diesen beenden oder ebenfalls abschießen.
Dabei dürften doch keine "unaufgeräumten" Dinge übrigbleiben?!
Gruß,
Christian
Verfasst: 19. Februar 2011 11:24
von solarix
Ein Kollege meinte dass es evtl. eine mögliche Lösung wäre, die Datenbankabfrage nicht in einen separaten Thread sondern einen separaten Prozess auszulagern.
Im Endeffekt eine eigene kleine Anwendung. Diese Anwendung könnte man im Dienst starten und, wenn wieder so ein timeout vorkommt, diesen beenden oder ebenfalls abschießen.
Dabei dürften doch keine "unaufgeräumten" Dinge übrigbleiben?!
Dein Kollege hat recht: Wenn man den Aufwand für die IPC nicht scheut, ist das der letzte Ausweg..
Verfasst: 19. Februar 2011 11:35
von chrislo1976
solarix hat geschrieben:Dein Kollege hat recht: Wenn man den Aufwand für die IPC nicht scheut, ist das der letzte Ausweg..
Tja, man scheut denn Aufwand eigentlich schon. Aber was hilfts?!
Die Kommunikation wäre eigentlich sehr minimal, zumindest mal für den Anfang...
Ich werd da mal ein wenig Zeit investieren bzw. investieren lassen (den Kollegen!)
Gruß,
Christian