mehrere Verbindungen mit MySQL

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Nabend,
ist zwar kein wirkliches Python-Problem, aber ich hoffe mal man kann mir auf die Sprünge helfen.

Ich habe eine MySQL- Datenbank aufgesetzt. Ein Python-Script wird regelmäßig aufgerufen, sucht nach neuen Daten auf der Festplatte und schreibt mir diese in die Datenbank.
Zusätzlich habe ich ein Web-Frontend das auf die Datenbank zugreift und mir die Daten darstellt.
Im großen und ganzen funktioniert das ganze schon mal. Wenn jedoch durch mein Skript neue Daten in die db geschrieben werden kann ich sie mir nicht direkt anzeigen lassen - das Webfrontend bekommt beim Abruf aus der db immer die gleichen(noch alten) Daten ausgeben.
Starte ich nun mein Frontend neu wird eine neue Verbindung zur Datenbank hergestellt. Danach kann ich auch die zuletzt eingetragenen Daten abrufen. Das gleiche funktioniert natürlich auch wenn ich die Verbindung zur db zur laufzeit einfach trenne und neu herstelle.

Die beiden Programme benutzen zur Verbindung mit der Datenbank den gleichen Benutzernamen. Alles findet direkt auf localhost statt. Die Datenbankverbindung läuft in beiden Programmen mit Python und MySQLdb.

Ich werde das Gefühl nicht los das ich irgendwas ganz einfaches übersehen habe...
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Poste doch mal ein bisschen Code von den zwei Komponenten.
An deiner Beschreibung ist mir spontan nichts Besonderes aufgefallen.

Hinweis: Größere Code-Ausschnitte bitte auslagern, z.B. http://paste.pocoo.org/
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

naja, was soll ich da großartig an Code posten? Die Datenbankzugriffe mache ich über normale sql Statements.

die Verbindung wird wie in der Doku erstellt mit

Code: Alles auswählen

db = MySQLdb.connect(host = "127.0.0.1",
                              passwd = self.cfg["DB_PASS"],
                              user = self.cfg["DB_USER"],
                              db= self.cfg["DB_NAME"],
                              use_unicode = True)
c = MySQLdb.cursors.DictCursor(db)

die Daten werden eingetragen mit:

Code: Alles auswählen

    def insert(self,  data):
        self.c.execute("""INSERT INTO  logdata
                                    (timestamp, temp_sens_1, temp_sens_2, temp_sens_3, temp_sens_4, temp_sens_5,
                                     temp_sens_6, temp_sens_7, temp_sens_8, temp_sens_9, temp_sens_10, irradiation,
                                     pulse, digit_in, rotation_speed_1, rotation_speed_2, rotation_speed_3, rotation_speed_4,
                                     rotation_speed_5, rotation_speed_6, rotation_speed_7, error_mask, messages, system,
                                     pattern, heat_val_hk1, state_hk1_module, heat_val_hk2, state_hk2_module, heat_val_hk3,
                                     state_hk3_module, heat_val_heating, state_heating, version)
                                     VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
                                     %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )
                                """,  data)
        self.db.commit()
abgerufen wird vorerst mit:

Code: Alles auswählen

    def get_all(self):
        self.c.execute("""SELECT * FROM logdata""")
        return self.c.fetchall()
Beide Scripte benutzen das gleiche Python-Modul für Zugriffe auf die Datenbank. Die Statements sind meiner Meinung nach auch nicht das Problem - da die Daten ja eingetragen werden und auch abgerufen werden können. Ich vermute das Problem eher bei irgendwelchen Verbindungseinstellungen oder bei irgendwelchen Einstellungen für MySQL.

Zuerst hatte ich ein fehlendes commit beim eintragen der Daten vermutet - allerdings stehen (und bleiben) die Daten ja in der Datenbank. Gibt es noch einen ähnlichen Befehl der dafür sorgt das die neu eingetragenen Daten auch an alle anderen Clients ausgeliefert werden? Eine Art Cache?
... ich hab echt keinen Plan wonach ich suchen soll
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Vielleicht hilft ja ein "FLUSH TABLE":
http://dev.mysql.com/doc/refman/5.1/en/flush.html

Aber normal müsste das auch so gehen. Wie ist denn deine Systemkonfiguration?

Testweise könntest du es auch mal mit dem normalen Cursor (anstatt diesem DictCursor versuchen) vielleicht macht der auch Probleme.

Code: Alles auswählen

c = db.cursor()
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Ohne es getestet zu haben: Erzeuge mal den Cursor bei jedem Zugriff neu. Dieses 'self.c.blabla' sieht ganz so aus als würdest du ihn zentral vorhalten und immer wieder verwenden. Vielleicht hat der 'gebrauchte' Cursor einfach noch nicht mitbekommen, daß sich an der Tabelle was geändert hat?
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

:oops: ja, das ich die Verbindung zur Datenbank und auch den Cursor offen halte hätte ich wohl sagen sollen. Mein Fehler.
Das habe ich aus einem etwas älterem Webprojekt behalten und einfach angepasst. Damals hatte ich nur eine Verbindung meiner Webapplikation vorgesehen. Das war kein Problem.

Wenn ich jetzt den Cursor vor einer Abfrage neu erstelle habe ich das gleiche Verhalten wie vorher - vorerst erstelle ich vor einer Abfrage aus der db einen neue Verbindung - das finde ich aber eher suboptimal...

Ich habe auch mal die Vorschläge von ice2k3 ausprobiert - `FLUSH TABLE` hörte sich gut an. Half leider nicht wirklich weiter. Ich habe auch mal verschiedene Andere Varianten ausprobiert wie `RESET QUERY CACHE` leider alles ohne Erfolg
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Auf welcher Technologie basiert denn Dein Webprojekt? Es muss sich dabei ja um einen Ansatz handeln, der permanent läuft...
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

Hi,
ja das ist ein kleines Bottle Projekt das über mod_wsgi auf dem Apache eingebunden ist. Das läuft wie du schon richtig sagtest permanent. Das Problem tritt aber auch schon mit den normalen Enticklungsserver auf.... der wird ja auch nicht ständig gestartet
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

ok, nachdem ich mich noch mal ein Wenig mit der Doku zu MySQL befasst habe habe ich mal die Speicher-Engine von InnoDB auf MyISAM umgestellt. Siehe da - es funktioniert. Da ich auch keine transaktionssichere Enginge beötige denke ich das ich das so lassen werde.
Ich kann ganz normal meine einmal erstellte Datenbankverbindung mit dem einmalig erstellten Cursor verwenden.

...muss mich wohl nur noch mal bei Gelegenheit mit den einzelnen DB- Engines auseinandersetzen und schauen was ich da noch alles nicht berücksichtigt habe...
Danke noch mal für eure Hilfe
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich benutze auch Bottle + MySQL für eine Intranet Projekt.

Ich baue jede Verbindung zur DB aber immer dann auf (und wieder ab ;-) ), wenn's nötig ist. Eine persistente Verbindugn braucht man in der Regel eher nicht. Und ich verwendet die MyISAM-Engine. Klappt alles 1A. :-)

Wo war denn jetzt bei dir das Problem? Die persistente Verbindung oder eine falsche Nutzung von InnoDB?

Gruß, noisefloor
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

hi,
das Problem `vermute` ich war die Verwendung von InnoDB in der Verbindung mit mehreren Clients die Daten in der Datenbank ändern. Ich habe mich durch einige Dokus gelesen, sicher bin ich mir noch nicht - da habe ich zu wenig Erfahrungswerte.
Für mich sieht es so aus als ob eine Transaktion noch nicht abgeschlossen war und ich noch den Zustand der Daten ausgeliefert bekam zum letzten konsistenten Zeitpunkt. Obwohl die Transaktionen eigentlich automatisch als abgeschlossen gelten sollten.

Naja - mit der MyISAM-Engine läufts rund. Keine Probleme mehr - auch meine Datenbankverbindung lasse ich bestehen und baue sie nur wieder neu auf wenn die Datenbank sie nach einem Timeout schliesst.
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

THX.

Gruß, noisefloor
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Bin kein Experte in diesen Dingen. Kann es sein, das InnoDB Fehler Anzeigt, die MyISAM schlicht unterm Tisch fallen lässt? Von daher kann man evtl. nicht wirklich von "rund laufen" sprechen ;)

Stichwort wonach ihr suchen solltet, wäre "Connection Pool" ?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Käptn Haddock
User
Beiträge: 169
Registriert: Freitag 24. März 2006, 14:27

jens hat geschrieben:Bin kein Experte in diesen Dingen. Kann es sein, das InnoDB Fehler Anzeigt, die MyISAM schlicht unterm Tisch fallen lässt? Von daher kann man evtl. nicht wirklich von "rund laufen" sprechen ;)

Stichwort wonach ihr suchen solltet, wäre "Connection Pool" ?
Das eine ist transaktionssicher, das andere nicht. D.h. wenn eine Transaktion was zum Schreiben gesperrt hat, bekommt eine andere nur 'veraltete' Daten zu sehen, bzw wird blockiert, bis die erste fertig ist. Gemeinhin ist das auch so beabsichtigt, zumindest, wenn man Wert auf seine Daten legt ;).
Da MyISAM sich aber nicht um Transaktionen schert, bringt es also auch keine Fehler ;) (bin allerdings kein MySQL-Experte...)

CU Uwe
---------------------------------
have a lot of fun!
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
jens hat geschrieben:Bin kein Experte in diesen Dingen. Kann es sein, das InnoDB Fehler Anzeigt, die MyISAM schlicht unterm Tisch fallen lässt?
Nee, das ist in der Tat der Unterscheid zwischen den transaktions-sichern DB-Engines und der nicht-transaktionsabsierten MyISAM Engine. Geschrieben wird es ja immer - der Unterschied ist, wann es auch lesbar ist, ist. Warum das so ist oder ob es daran liegt, dass sich InnoDB bei persistenten Verbindungen anders verhält kann ich auch nicht sagen. Ich nehm' immer MyISAM. ;-)

Gruß, noisefloor
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Was ich meinte: Die Frage ist, ob bei MyISAM die Daten auch wirklich konsistent bleiben. Die Fehler, die bei InnoDB auftreten, sind vielleicht in Indiz dafür, das die aktuelle Lösung nicht brauchbar ist...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Lonestar
User
Beiträge: 147
Registriert: Samstag 9. August 2008, 08:31

jens hat geschrieben:Was ich meinte: Die Frage ist, ob bei MyISAM die Daten auch wirklich konsistent bleiben. Die Fehler, die bei InnoDB auftreten, sind vielleicht in Indiz dafür, das die aktuelle Lösung nicht brauchbar ist...
Hi,
da nur einer von meinen beiden Clients Daten in die Datenbank schreiben wird und der andere Client ausschliesslich Daten abfragt kann ich doch auf Transaktionen verzichten. Denn der Client der Daten schreibt hat immer einen Konsistenten Datensatz vor sich.
Wie ich schon gestern geschrieben habe habe ich mit Transaktionen bisher noch keine Erfahrungen gesammelt. Ich habe bisher gedacht das meine Schnittstelle das im Hintergrund für mich erledigen würde. Falls da jemand ein kleines Beispiel mit MySQLdb hat würde ich mir das gerne mal anschauen.

Sebastian
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:


GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@jens:
Die Frage ist, ob bei MyISAM die Daten auch wirklich konsistent bleiben.
Tun sie. Auch bei MyISAM wird ein Lock auf die Tabelle beim Schreiben gesetzt, d.h. es gibt keine konkurrierenden Schreibzugriffe auf die Tabelle. Außerdem bin ich mir ziemlich sicher, dass MyISAM auch ACID-konform ist, also wird "alles-oder-nichts" geschrieben. :-)

Interessant bei dem Problem hier, warum der Commit mit InnoDB nicht geschrieben wird...

Gruß, noisefloor
Snoda
User
Beiträge: 32
Registriert: Mittwoch 1. Februar 2006, 14:34

Also meiner Erfahrung nach funktioniert das, wenn man die connection des lesenden cursors vor dem lesen ebenfalls 'commited'... auch bei innodb
Hello world!
Antworten