2013-08-26 12 views
5

Ich habe ein Problem im Zusammenhang mit sqlalchemy und postgresql.sqlalchemy, postgresql und Beziehung stecken in "Leerlauf in der Transaktion"

class Profile(Base): 
    ... 

    roles = relationship('Role', secondary=role_profiles, 
         backref='profiles', lazy='dynamic') 

Beim Laufen (current_user ist eine Instanz der Klasse Profile):

roles = current_user.roles.filter().all() 

mit sqlalchemy ich idle in transaction für alle wählt zum Lesen des Profils in postgresql erhalten.

Edit:

Von Echo der Abfrage, die ich sehen, dass alle Auswahl beginnt mit:

BEGIN (implicit) 

Ein weiterer edit:

Nach der Zugabe von

pool_size=20, max_overflow=0 

zu der create_engine es scheint wie die idle in transaction -Statements werden zurückgesetzt, wenn die Anzahl der Leerlauf zu groß werden. Irgendeine Idee dazu und wäre das eine schlechte Lösung für das Problem?

Wie verwalte ich das und wie würde ich gehen, um die BEGIN für selects loswerden?

+0

hast du 'pool_timeout = 90' zum Beispiel versucht? Ich fand es [hier im Dokument] (http://docs.sqlalchemy.org/en/rel_0_7/core/engines.html?highlight=pool_timeout) –

+0

Ich denke nicht, dass das das Problem wirklich behebt. Ich möchte loswerden von Selects oder automatisch Commit auf Selects loswerden. – Asken

+1

Sie beenden Transaktionen nicht ordnungsgemäß. Sie müssen Ihre Transaktionen entweder "festschreiben" oder "zurücksetzen". Der 'Beginn'-Teil ist implizit (wie Sie angemerkt haben), aber er muss korrekt beendet werden. Außerdem: Warum haben Sie eine leere Filteranweisung? Ist das sinnvoll? Sind Sie in einem Webkontext oder in einem anderen? Schließlich, obwohl sehr unrecommended, könnten Sie 'Autocommit'-Modus verwenden (aber wirklich, nicht). – javex

Antwort

0

SQLA arbeitet standardmäßig immer in einer Transaktion (einige Informationen here). In einem Web-Kontext würden die meisten Frameworks diese Transaktion für Sie am Ende der Anforderung durchführen (z. B. pyramid_tm). Wenn Sie kein Framework verwenden oder dies ein anderer Anwendungstyp ist, sollten Sie das Commit oder Rollback durchführen, wenn Sie fertig sind oder an einem geeigneten Punkt.

Es kann möglich sein, SQLA so zu konfigurieren, dass es eine Transaktion nicht automatisch startet, aber soweit ich sehen kann, ist es nicht so, wie es verwendet werden soll, so dass Sie wahrscheinlich mehr Glück haben, nicht dagegen anzukämpfen :).

2

mit SQLAlchemy Ab 0.8.2 Sie die impliziten BEGIN Anweisungen deaktivieren können, wenn dieser Änderung create_engine()

engine = create_engine(uri, isolation_level="AUTOCOMMIT") 

Es gibt einige subtile Auswirkungen nennen.Erstens gibt Aussagen, die nicht ruhig in ungekündigten Transaktion versteckt wurden, werden

session.execute("DELETE FROM department WHERE department_id=18") 
sys.exit(0) 

Standard ruhig ignoriert werden:

LOG: statement: BEGIN 
LOG: statement: show standard_conforming_strings 
LOG: statement: DELETE FROM department WHERE department_id=18 
LOG: unexpected EOF on client connection with an open transaction 

autocommit:

LOG: statement: show standard_conforming_strings 
LOG: statement: DELETE FROM department WHERE department_id=18 

Zweitens Aktualisierung mehrere Updates sind nicht mehr automatisch, und rollback() ist nur bedingt wirksam ve:

department = Department(u"HR") 
session.add(department) 
session.flush() 
employee = Employee(department.department_id, u'Bob') 
session.add(employee) 
session.rollback() 

Standard:

LOG: statement: BEGIN 
LOG: statement: INSERT INTO department (name) VALUES ('HR') RETURNING department.department_id 
LOG: statement: ROLLBACK 

autocommit:

LOG: statement: INSERT INTO department (name) VALUES ('HR') RETURNING department.department_id 

Einstellung SQLAlchemy des isolation_level auf dem Motor-Objekt für viele Anwendungen wirksam ist. Es bedauerlich, dass Session.begin() nicht immer bedeutet BEGIN TRANSACTION;

Verwandte Themen