2008-09-17 7 views
6

Ich benutze MySQL2, um eine Verbindung zu einer MySQL-Datenbank zu einer Reihe von Datenabfragen durchzuführen. Aufgrund der Tatsache, dass ständig in die Tabellen geschrieben wird, aus denen ich lese, und dass ich eine konsistente Sicht auf die Daten benötige, sperre ich zuerst die Tabellen. Allerdings hat MySQL in seiner Sperranfrage kein Konzept von 'NOWAIT'. Wenn also die Tabellen durch etwas anderes gesperrt sind, das sie für lange Zeit gesperrt hält, sitzt meine Anwendung dort und wartet. Ich möchte, dass ich zurückkommen und etwas sagen kann wie "Lock konnte nicht erhalten werden" und versuche es in ein paar Sekunden noch einmal. Mein allgemeiner Versuch dieses Timeout ist unten.Wie Timeout eine MySQL-Abfrage in C++

Wenn ich dies nach dem Sperren der Tabelle auf der Datenbank ausführen, bekomme ich die Nachricht, dass das Timeout erreicht wird, aber ich weiß nicht, wie man dann die mysql_query-Zeile zu beenden. Ich würde mich über jede Hilfe/Ideen freuen!

Antwort

0

Sie können die Blockierungsabfrage in einem anderen Thread ausführen und werden nie mit dem Timeout belästigt. Wenn einige Daten ankommen, benachrichtigen Sie den Thread, der über den Status der Transaktion informiert werden muss.

0

Wenn ich von Grund auf neu schreiben würde, würde ich das tun, aber dies ist eine Server-Anwendung, die wir nur ein Upgrade zu tun, anstatt eine große Nacharbeit.

0

anstatt zu versuchen, Transaktionen mit Tabellensperren vorzutäuschen, warum nicht zu innodb-Tabellen wechseln, wo Sie tatsächliche Transaktionen erhalten? Stellen Sie nur sicher, dass die Standardtransaktionsisolationsstufe auf REPEATABLE READ gesetzt ist.

0

Wie gesagt, es ist nicht so einfach zu "wechseln" oder zu re-architect, wenn dies ein Live-, in Produktionssystem ist. Ich bin etwas frustriert, dass MySQL keine Methoden zur Verfügung stellt, um nach Sperren zu suchen oder nicht auf eine Sperre warten zu müssen.

0

Ich weiß nicht, ob dies eine gute Idee in Bezug auf Ressourcenverbrauch und "Best Practices" und "Sauberkeit" und den ganzen Rest ist ... aber Sie haben jetzt wiederholt beschrieben die Handschellen, die Sie in Bezug auf binden Re-Architecting ein "sauberes" System ... so geht hier .....

Könnten Sie eine neue, separate Verbindung nur für das Senden der LOCK-Anweisung öffnen? Schließen Sie dann diese Verbindung, wenn Sie den Timeout-Alarm empfangen haben? Würde die LOCK-Anweisung durch das Schließen/Zerstören der Verbindung, die der LOCK-Anweisung zugewiesen war, nicht im Wesentlichen "abgebrochen" werden? Ich bin mir nicht sicher, ob solche Ereignisse eintreten würden, wie ich es beschrieben habe, aber vielleicht ist es etwas, das man testen kann.

0

Meine bisherige Erfahrung zeigt mir, dass das Schließen einer Verbindung, in der eine Abfrage ausgeführt wird, einen Seg-Fehler verursacht. Daher würde das Senden dieser Abfrage in eine andere Verbindung nicht wirklich helfen, da dies ebenfalls einen Fehler verursachen würde.

3

Sie implementieren können ein „cancel-like“ Verhalten auf diese Weise:

Sie die Abfrage auf einem separaten Thread ausführen, die am Laufen hält, ob das Timeout auftritt. Die Zeitüberschreitung tritt im Hauptthread auf und setzt eine Variable auf "1", um anzuzeigen, dass sie aufgetreten ist. Dann tust du, was du in deinem Hauptthread machen willst.

Der Abfragethread überprüft nach Abschluss der Abfrage, ob das Zeitlimit aufgetreten ist. Wenn nicht, erledigt es den Rest der Arbeit. Wenn es HAS hat, entsperrt es nur die Tabellen, die es gerade gesperrt hat.

Ich weiß, es klingt ein wenig verschwenderisch, aber die Lock-entsperren-Periode sollte grundsätzlich sofort sein, und Sie kommen so nah wie möglich an das gewünschte Ergebnis.