MYSQLdb - Cursor "aktualisieren"

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Repo9
User
Beiträge: 2
Registriert: Sonntag 24. April 2016, 09:50

Hallo zusammen,

gestern habe ich zum ersten mal eine mysql-Datenbank mit Python abgefragt. Ziel ist es, in einer Schleife laufend aktuelle Werte für ein Display aus der Datenbank auszulesen.

Zunächst habe ich die Verbindung zur Datenbank hergestellt:

Code: Alles auswählen

(...)
def DB_Verbindung_aufbauen():
    DB_Verbindung = MySQLdb.connect(
            host="123.456.789.123",
            db="Messwerte",
            user="xyz"
            )
    cursor = DB_Verbindung.cursor()
    return DB_Verbindung, cursor
    
(...)
    
DB_Verbindung, cursor = DB_Verbindung_aufbauen()
Dann kommt eine Schleife, in welcher mehrere DB-Abfragen ausgeführt werden:

Code: Alles auswählen

while True:
    cursor.execute(Abfrage_1)
    Wert1 = cursor.fetchone()[1]
    
    cursor.execute(Abfrage_2)
    Wert2 = cursor.fetchone()[1]
    (...)
    time.sleep(5)
Das Problem: Alle Abfragen (Abfrage_1, Abfrage_2, etc.) funktionieren genau einmal - im ersten Schleifendurchlauf. In allen weiteren Schleifendurchläufen werden die Werte nicht mehr aktualisiert, obwohl schon wieder neue Informationen in der Datenbank stehen.

Muß ich etwa nach jeder Abfrage den Cursor schließen und wieder neu erstellen oder mache ich grundsätzlich etwas falsch? Ein Schleifendurchlauf soll am Ende maximal 15 Sekunden dauern. Hat jemand einen Tip für mich?

Danke und viele Grüße!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Eigentlich sollte ein Cursor wiederverwendbar sein, ja ganz im Gegenteil ist das sogar explizit für Optimierungen so vorgesehen.

Wie lauten denn Deine Queries? Evtl. sind diese so restriktiv, dass die neuen / geänderten Datensätze einfach niemals Bestandteil des Ergebnisses sein können? Wie kommen denn neue Daten in die DB? Woher weißt Du dass da neue Daten sind bzw. wie prüfst Du das nach?

Deine ``DB_Verbindung_aufbauen`` Funktion finde ich übrigens wenig gelungen! Zum einen tut sie ja wesentlich mehr (eben z.B. zusätzlich ein Cursor-Objekt zurückgeben), zum anderen bietet sie eigentlich keinen Mehrwert gegenüber dem expliziten Erstellen in Deinem Abfragekontext. Lokal könnte man da sogar viel schöner mittels ``with`` arbeiten.

Grundsätzlich solltest Du Dir mal SQLAlchemy angucken - es mag am Anfang nach Overkill aussehen, macht sich aber schnell bezahlt!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Repo9
User
Beiträge: 2
Registriert: Sonntag 24. April 2016, 09:50

Die Abfragen sind ganz banal und liefern nur den aktuellsten Wert zurück. Nach folgendem Schema:

Code: Alles auswählen

SELECT Wert FROM Tabelle ORDER BY Datum DESC, Uhrzeit DESC LIMIT 1
Wenn ich die Abfrage manuell ausführe oder auch das Skript neu starte, sehe ich die aktuellen Werte. Nur im Python-Skript werden sie nicht aktualisiert. Die Werte kommen aus anderen Quellen in die Datenbank (d.h. nicht innerhalb dieses Skriptes).

Für mich hat das den Anschein, als würde bei der ersten Verwendung einer Tabelle die Tabelle gepuffert. Wenn ich am Schleifenbeginn die DB-Verbindung aufbaue und am Ende wieder schließe, funktioniert alles. Merkwürdig...

SQLAlchemy sieht interessant aus - werde ich mir ansehen. Die Funktion zur DB-Verbindung habe ich auch entfernt ;)
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Repo9: im Gegensatz zu Verbindungen, sind cursor sehr leichtgewichtig. Man sollte ihn nicht für längere Zeit benutzen. Es könnte sein, dass das cursor-Objekt für nachfolgende Abfragen Werte puffert, und Du deshalb bei immer der gleichen Abfrage auch immer das gleiche Ergebnis bekommst. Das richtige Maß ist daher, ein neuer cursor pro Aufgabe. Wenn in Deinem SELECT nur ein Feld steht, dann führt `cursor.fetchone()[1]` zu einem IndexError. Python zählt von 0 ab. Datum und Uhrzeit sollten in Deiner Datenbank in einem DATETIME-Feld stehen, dann brauchst Du auch nicht nach 2 Feldern sortieren.
BlackJack

Vielleicht fehlt auch einfach nur ein `commit()` falls die Datenbank bei Transaktionen garantiert beziehungsweise so eingestellt ist, dass Abfragen innerhalb einer Transaktion immer die gleichen Ergebnisse liefert („repeatable read“).
Antworten