Seite 1 von 1

MySQL threadsafe verwenden?

Verfasst: Dienstag 26. Juni 2007, 16:34
von Volvic
hi,

ich stehe vor dem problem das MySQL (das protkoll) nur eine aktion je connection gleichzeitig ausführen kann (was mich auch eigentlich garnicht stört). ich benutze in meinem programm 10 worker threads die manchmal eine mysql aktion ausführen müssen. als eigene lösung dachte ich mir das ich einfach eine Queue.Queue benutze und einen extra thread der diese Queue permanent abfrägt. das problem wäre dann aber wenn ich werte aus einer mysql tabelle lesen möchte eben mit dieser methode blöd darstehen würde.
hat jemand vielleicht eine bessere idee? ich dachte auch schon evtl an das locken der threads, was ich aber nur ungern machen möchte.

PS: ich verwende für die verbindung MySQLdb

mit freundlichen grüßen
- Volvic

Verfasst: Dienstag 26. Juni 2007, 17:43
von EyDu
Ich hab' dir mal einen möglichen Ansatz skizziert. Du bräuchtest nur noch einen Datenbank-Thread, welcher die Anfragen in einer Queue entgegen nimmt und diese nacheinander mit "commit" abarbeitet.

In "SQLStatement" kannst du anfragen stecken, die eine Änderung durchführen, in "SQLExpression" eine Anfrage, die ein Ergebnis liefert. Dieses wird dann in "result" abgelegt.

Nach Abarbeitung einer Anfrage wird "done" gesetzt um der anfragend Thread mitzuteilen, dass die Anfrage abgearbeitet ist.

Das "_before" habe ich einfach mal aus Gründen der Symmetrie eingefügt, vielleicht braucht man es ja bei Gelegenheit noch mal.

Code: Alles auswählen

import threading

class SQLRequest(object):
    def __init__(self, sql):
        self.sql = sql
        self.done = threading.Event()

    def commit(self, dbcursor, dbparams):
        self._before(dbcursor, dbparams)
        dbcursor.execute(self.sql, dbparams)
        self._after(dbcursor)
        self.done.set()

    def _before(self, dbcursor, dbparams):
        pass

    def _after(self, dbcursor):
        pass

class SQLStatement(SQLRequest):
    def _after(self, dbcursor):
        dbcursor.commit()

class SQLExpression(SQLRequest):
    def _after(self, dbcursor):
        self.result = dbcursor.fetchall()

Verfasst: Dienstag 26. Juni 2007, 23:29
von Volvic
dankeschön, werde ich nun mal ausprobieren :)

Re: MySQL threadsafe verwenden?

Verfasst: Mittwoch 27. Juni 2007, 21:26
von gerold
Volvic hat geschrieben:ich benutze in meinem programm 10 worker threads die manchmal eine mysql aktion ausführen müssen.
Hallo Volvic!

CherryPy gibt dir die Möglichkeit, eine Connection an einen Thread zu binden. Damit kannst du eine Verbindung zum MySQL-Server **je** Thread aufmachen. Somit hast du dann 10 Threads und 10 Verbindungen offen. -- ideal!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import cherrypy

# Ganz egal wo im Programm du bist. "cherrypy.thread_data" enthält immer nur
# die **im aktuellen Thread** zugewiesenen Daten. Das wird im Hintergrund 
# durch die Verwendung von "threading.local" erreicht. Dieser Platz ist dadurch
# ideal dafür geeignet, eine Connection zu einer MySQL-Datenbank aufzunehmen.
thread_data = cherrypy.thread_data

# Wenn es die Verbindung noch nicht gibt, dann Verbindung initialisieren...
if not hasattr(thread_data, "conn"):
    thread_data.conn = "Irgendeine Datenbankverbindung"

# Verbindung verwenden...
print thread_data.conn
mfg
Gerold
:-)

Verfasst: Mittwoch 27. Juni 2007, 21:37
von gerold
...Hier noch ein kleiner Nachtrag:

Da steht alles drinn, was man so brauchen könnte und wie man die Sache am Schönsten angehen kann.

http://tools.cherrypy.org/wiki/Databases

mfg
Gerold
:-)

Verfasst: Donnerstag 28. Juni 2007, 18:41
von Volvic
vielen dank :)

Re: MySQL threadsafe verwenden?

Verfasst: Dienstag 11. Dezember 2007, 06:40
von Damaskus

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import cherrypy

# Ganz egal wo im Programm du bist. "cherrypy.thread_data" enthält immer nur
# die **im aktuellen Thread** zugewiesenen Daten. Das wird im Hintergrund 
# durch die Verwendung von "threading.local" erreicht. Dieser Platz ist dadurch
# ideal dafür geeignet, eine Connection zu einer MySQL-Datenbank aufzunehmen.
thread_data = cherrypy.thread_data

# Wenn es die Verbindung noch nicht gibt, dann Verbindung initialisieren...
if not hasattr(thread_data, "conn"):
    thread_data.conn = "Irgendeine Datenbankverbindung"

# Verbindung verwenden...
print thread_data.conn
Moin,
eine Frage hab ich noch dazu.
Wie kann ich die 10 offenen Verbindungen die cherrypy beim start erstellt dann wieder schließen. Bzw. worum es mir geht ist eher wie kann ich bei einem Shutdown des cherrypy Servers die ganzen offenen Verbindungen schließen?
Denn cherrypy kennt keine möglich eine bestimmte Funktion vor dem shutdown auszuführen.
Oder irre ich mich da?

Danke.

Mfg
Damaskus

Re: MySQL threadsafe verwenden?

Verfasst: Dienstag 11. Dezember 2007, 09:53
von gerold
Damaskus hat geschrieben:worum es mir geht ist eher wie kann ich bei einem Shutdown des cherrypy Servers die ganzen offenen Verbindungen schließen?
Hallo Damaskus!

Ich denke mal, dass die Connections beim Zerstören von *thread_data* automatisch geschlossen werden. -- Gleich wie beim File-Objekt. Dieses wird ja auch geschlossen, auch wenn man *close()* nicht explizit vor dem Ende eines Programmes aufruft.

Hattest du Probleme die darauf hinweisen, dass die Connections nicht geschlossen werden?

lg
Gerold
:-)

Verfasst: Dienstag 11. Dezember 2007, 10:04
von BlackJack
Ansonsten könnte man das mit dem `atexit`-Modul machen.

Re: MySQL threadsafe verwenden?

Verfasst: Dienstag 11. Dezember 2007, 18:39
von Damaskus
gerold hat geschrieben:
Damaskus hat geschrieben:worum es mir geht ist eher wie kann ich bei einem Shutdown des cherrypy Servers die ganzen offenen Verbindungen schließen?
Hallo Damaskus!

Ich denke mal, dass die Connections beim Zerstören von *thread_data* automatisch geschlossen werden. -- Gleich wie beim File-Objekt. Dieses wird ja auch geschlossen, auch wenn man *close()* nicht explizit vor dem Ende eines Programmes aufruft.

Hattest du Probleme die darauf hinweisen, dass die Connections nicht geschlossen werden?

lg
Gerold
:-)
Hallo Gerold,
es war eher nur ein Gedankengang von mir.
Ich hab das heute mal getestet und es ist so wie du vermutet hast das die Connections mit dem zerstören von "thread_data" geschlossen werden.

Allerdings ergibt sich jetzt ein neues Problem. Die Connections die offen sind, bleiben bei MySQL dauerhaft im "sleep" Status was mir wiederum nicht gefällt.
Aber dazu bastel ich mir noch eine Kontroll/Steuerungsfunktion.

Gruß
Damaskus