SqlAlchemy Session close Problem

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
s45f
User
Beiträge: 12
Registriert: Donnerstag 27. Februar 2014, 13:47

Hey zusammen,

ich hab ein Problem das sich eine Verbindung zur Datenbank nicht korrekt beendet und offen bleibt, was zu späteren Problemen (timeout) und somit Script abbruch führt.

Der Part um den es sich dreht

Code: Alles auswählen

def db_update()
'''Some Python Code'''
with closing(session()) as s:
    for elem in row:
        if s.query(Table).filter(Table.column1 == elem[0], Table.column2 == elem[1]).count():
            pass   
        else:
            insert = Table(Table.column1 == elem[0], Table.column2 == elem[1])
            s.add(insert)
            s.commit()
Es scheint so zu sein das das if Abfrage die Verbindung nicht schließt nachdem die Funktion abgearbeitet ist.
Hat Jemand eine Idee wie man das ganze möglichst elegant löst ?
BlackJack

@s45f: Ich vermute Du suchst das Problem an der falschen Stelle. Die Session muss die Verbindung nicht schliessen. Die kann die Verbindung auch einfach wieder an den Verbindungs-Pool zurückgeben. Damit hat beispielsweise MySQL gerne mal die von Dir beschriebenen Probleme. Gegenmassnahme: Ein maximalalter für Pool-Verbindungen beim erstellen der Engine angeben. Beispiel:

Code: Alles auswählen

    engine = create_engine(
        'mysql://{0}:{1}@{2}/{3}?charset=utf8'.format(
            config.user, config.password, config.server, config.db_name
        ),
        echo=bottle.DEBUG,
        pool_recycle=3600  # <- !!!
    )
s45f
User
Beiträge: 12
Registriert: Donnerstag 27. Februar 2014, 13:47

@Backjack:
Danke, wollte mir gerade selbst antworten ;)
Bin zu der gleichen Erkentniss gekommen, allerdings mit einer etwas abweichenden Lösung

Code: Alles auswählen

from sqlalchemy.pool import NullPool

engine = create_engine(
        'mysql://{0}:{1}@{2}/{3}?charset=utf8'.format(
            config.user, config.password, config.server, config.db_name
        ),
         poolclass=NullPool
        )
Was ist da jetzt besser?
Gar kein Pool aufzumachen, oder den Timeout auf 1h zu setzen?

Danke für deine Antwort

PS: hab deine "format"-engine gleich mal übernommen, das spart mir doch gleich noch die händische anpassung zwischen dev und live system ;)
BlackJack

@s45f: Ist halt die Frage ob Du bei jeder Session auch eine neue Verbindung auf- und wieder abbauen möchtest. Würde ich persönlich nur machen wenn es stört das Verbindungen offen sind und diese kaum genutzt werden. Und ich würde es nicht machen wenn in kurzer Zeit viele Sessions verwendet werden.

Ich habe eigentlich immer Webanwendungen wo mehrere Benutzer jeweils mehrere Webanfragen (Webanfrage = Session) absetzen, da möchte ich einen Pool, oder Programme die nur eine Session verwenden und etwas umfangreicheres mit der Datenbank machen. Dafür bräuchte ich keinen Pool, aber er stört auch nicht weil die Programme im Grunde zuende sind nach dem die Session nicht mehr verwendet wird. Das heisst die haben trotz Pool auch nur eine Verbindung zur Datenbank und diese wird am Programmende geschlossen. Das es per Default einen Pool gibt, deutet IMHO darauf hin, dass das in 99% der Fälle sinnvoll ist oder zumindest nicht stört.
Antworten