Ich habe eine Flask-Webanwendung, die SQLAlchemy verwendet, um auf eine PostgreSQL-Datenbank zuzugreifen.Flask und SQLAlchemy verursacht eine Menge IDLE in Transaktionsverbindungen in PostgreSQL
Wenn ich die Anwendung starte, wird sofort eine "in transaction" Verbindung in PostgreSQL erstellt.
Wenn die Anwendung eine Zeitlang verwendet wurde, werden mehrere dieser Verbindungen in pg_stat_activity angezeigt.
Nach einiger Zeit scheint es, dass Deadlocks auf einigen Ressourcen auftritt, und ich muss die Anwendung neu starten, um es wieder funktionsfähig zu bekommen.
Ich habe gelesen, dass dies passieren kann, wenn ich von einer Sichtfunktion zurückkomme, die Datenbank vor dem Schließen der Db-Sitzung verwendet. Also, um dieses Problem zu vermeiden, habe ich die folgenden Dekorateur erstellt:
@app.teardown_appcontext
def shotdown_session(exception=None):
db.session.remove()
Dies sollte dazu führen, alle Sitzungen nach jeder Anfrage geschlossen werden und effektiv das Problem, „in der Transaktion“ Verbindungen zu vermeiden.
Leider scheint es keine Wirkung zu haben.
Also, wie kann ich dieses Problem wirklich lösen?
UPDATE:
sollte ich wohl hinzufügen, dass ich, dass meine Dekorateur Funktion überprüft haben, tatsächlich ausgeführt werden. Ich überprüfte diese durch einen Druck auf sie und fügte hinzu:
@app.teardown_appcontext
def shotdown_session(exception=None):
print "@app.teardown_appcontext: shotdown_session()"
db.session.remove()
Ich habe auch festgestellt, dass es in der Tat nach der Rückkehr der View-Funktion durch Hinzufügen eines Druck auf die View-Funktion auch ausgeführt wird:
[...]
products = db.session.query(...).all()
print "BEFORE RETURN"
return render_template("show_products.html", products=products)
Dies erzeugt Protokollzeilen wie diese:
* Running on http://0.0.0.0:5000/
* Restarting with reloader
BEFORE RETURN
@app.teardown_appcontext: shotdown_session()
10.0.0.100 - - [03/Dec/2014 13:41:30] "GET /product/51 HTTP/1.1" 200 -
ich vor jeder Rückkehr eine db.session.remove() -Aufruf auch den Code ging durch und fügte in jeder Funktion db.session mit . Dies wird die in der Transaktion loswerden, aber es verursacht auch Probleme. Ich übergebe SQLAlchemy-Modellobjekte aus der Datenbank an die Vorlagen. Einige Vorlagen führen dann einige Operationen an diesen Modellobjekten durch, die dazu führen, dass die Anwendung fehlschlägt, da das Objekt nicht mehr an eine Sitzung gebunden ist.
EDIT 2014.12.08:
Verbindung einrichten kann hier gesehen werden:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from flask_sqlalchemy import SQLAlchemy
from config import cfg
engine = create_engine(cfg["db_uri"], echo=False, pool_size=10)
db = SQLAlchemy()
Base = db.Model
Session = scoped_session(sessionmaker(bind=engine))
Die Struktur der gesamten Anwendung kann hier gefunden werden: http://paste.yt/p3219.html
Wie sieht Ihre sqlalchemy Engine oder der Verbindungscode aus? Machst du irgendetwas mit Autocommit oder anderen Optionen? – aezell
Ich habe oben die SQL Engine-Konfiguration hinzugefügt. Ich habe auch Auszüge aus relevanten Dateien hinzugefügt, um die gesamte Struktur der Anwendung zu zeigen. Wenn Sie irgendwelche allgemeinen Inputs oder Verbesserungen zu meiner Arbeit haben, lassen Sie es mich wissen :) – Thomas
Verwenden Sie ein Pooling für Postgres selbst, wie zum Beispiel pgbouncer oder so? Die Kombination solcher Tools mit dem SQLAlchemy-Pooling kann zu ungewöhnlichen Verbindungsproblemen führen. – aezell