it-swarm.com.de

Vermeidung von "MySQL-Server ist weg" auf selten genutzten Python/Flask-Servern mit SQLAlchemy

Wie kann Flask/SQLAlchemy so konfiguriert werden, dass eine neue Datenbankverbindung erstellt wird, wenn keine vorhanden ist?

Ich habe einen selten besuchten Python/Flask-Server, der SQLAlchemy verwendet. Es wird alle paar Tage besucht, und beim ersten Besuch wird häufig der Fehler "MySQL-Server ist weg" ausgegeben. Nachfolgende Seitenaufrufe sind in Ordnung, aber es erscheint unprofessionell, diesen ersten Fehler zu haben.

Ich würde gerne wissen, wie man das richtig angeht - Ratschläge wie "eine wirklich lange Pause machen", die in diesem Fall etwa 4 Tage dauern würde, scheinen nicht korrekt zu sein. Wie kann ich das Fehlen einer Datenbankverbindung testen und bei Bedarf eine erstellen?

41
Ollie Glass

Ich hatte zuvor Probleme damit und fand heraus, dass der Weg, um damit umzugehen, darin besteht, Sitzungen nicht zu halten. Das Problem ist, dass Sie versuchen, eine Verbindung zu lange offen zu halten. Verwenden Sie stattdessen eine Sitzung mit lokalem Thread-Bereich, wie in __init__.py oder in einem Hilfsprogrammpaket, das Sie überall importieren:

from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session( sessionmaker() )

Richten Sie dann einmal Ihre Engines und Metadaten ein. Auf diese Weise können Sie die Konfigurationsmechanik jedes Mal überspringen, wenn Sie die Verbindung herstellen oder trennen. Danach können Sie Ihre Datenbankarbeit wie folgt ausführen:

session = Session()
someObject = session.query( someMappedClass ).get( someId )
# use session like normal ...
session.close()

Wenn Sie alte Objekte behalten möchten und Ihre Sitzung nicht geöffnet lassen möchten, können Sie das obige Muster verwenden und alte Objekte wie folgt wiederverwenden:

session = Session()
someObject = session.merge( someObject )
# more db stuff
session.close()

Der Punkt ist, Sie möchten Ihre Sitzung öffnen, Ihre Arbeit erledigen und dann Ihre Sitzung schließen. Dadurch werden Timeouts sehr gut vermieden. Es gibt viele Optionen für .merge und .add, die es Ihnen ermöglichen, Änderungen, die Sie an freistehenden Objekten vorgenommen haben, hinzuzufügen oder neue Daten aus der Datenbank zu laden. Die Dokumente sind sehr ausführlich, aber sobald Sie wissen, wonach Sie suchen, ist es möglicherweise etwas einfacher, sie zu finden.

Um wirklich den ganzen Weg dorthin zu gelangen und zu verhindern, dass MySQL "wegfährt", müssen Sie das Problem lösen, dass Ihr Verbindungspool zu lange Verbindungen offen hält und eine alte Verbindung für Sie überprüft. 

Um eine neue Verbindung herzustellen, können Sie die pool_recycle-Option in Ihrem create_engine-Aufruf festlegen. Setzen Sie diesen pool_recycle auf die Anzahl Sekunden, die sich im Verbindungspool zwischen den Checkouts befindet, wenn eine neue Verbindung erstellt werden soll, anstatt dass eine vorhandene Verbindung zurückgegeben wird.

45
underrun

Ich hatte ein ähnliches Problem, aber für mich würde die Fehlermeldung "MySQL ist weg" irgendwo zwischen 5 Minuten und 2 Stunden pro Sitzung angezeigt. 

Ich benutze Flask-SQLAlchemy, also sollte es untätige Verbindungen schließen, schien das aber nicht zu tun, es sei denn, die Verbindung war über ein paar Stunden untätig.

Schließlich habe ich es auf die folgenden Flask-SQLAlchemy-Einstellungen eingegrenzt:

app.config['SQLALCHEMY_POOL_SIZE'] = 100
app.config['SQLALCHEMY_POOL_RECYCLE'] = 280

Die Standardeinstellungen für diese sind 10 bzw. 7200 (2 Stunden).

Es ist eine Frage des Spielens mit diesen Einstellungen, um sich Ihrer Umgebung anzupassen. 

Ich habe zum Beispiel an vielen Stellen gelesen, dass SQLALCHEMY_POOL_RECYCLE auf 3600 gesetzt werden sollte, aber das hat bei mir nicht funktioniert. Ich hoste mit PythonAnywhere und bricht MySQL-Verbindungen nach 5 Minuten (300 Sekunden) ab. Wenn Sie also meinen Wert auf unter 300 setzen, wurde das Problem gelöst. 

Ich hoffe, das hilft anderen, weil ich zu viel Zeit mit diesem Thema verschwendet habe.

http://flask-sqlalchemy.pocoo.org/2.1/config/#configuration-keys

21
omerk

Antwort von 2018: In SQLAlchemy v1.2.0 + steht Ihnen die Option connection pool pre-ping zur Verfügung, um dieses Problem mit "MySQL-Server ist weg" zu beheben.

Verbindungspoolvorbereitung - Der Verbindungspool enthält jetzt ein Optionale "Pre-Ping" -Funktion, die die "Liveness" eines gepoolten .__ prüft. Verbindung für jede Verbindungsprüfung, transparentes DBAPI-Verbindung, wenn die Datenbank getrennt ist. Dieses Feature Das Flag "Pool recycle" sowie das Problem .__ werden nicht mehr benötigt. von Fehlern, die ausgelöst werden, wenn eine gepoolte Verbindung nach einer Datenbank verwendet wird Neustart.

Mit dem neuen Argument ist ein pessimistischer Test von Verbindungen beim Checkout möglich:

engine = create_engine("mysql+pymysql://user:[email protected]/db", pool_pre_ping=True)
16
wim

WENN Sie Flask-SQLAlchemy verwenden:

Es scheint, als wäre ein Fix verfügbar: https://github.com/mitsuhiko/flask-sqlalchemy/issues/2

Leider wird der Patch bei der Standardinstallation (pip install flask-sqlalchemy) noch nicht richtig angewendet, insbesondere zu diesem Problem: https://github.com/e-dard/flask-sqlalchemy/commit/cf659f346e005d34257d256fa4c42889741fc31f

Die neueste Version von github zu erhalten, sollte dies beheben.

6
Desmond Lua

Als ich auf diesen Fehler stieß, speicherte ich ein LONGBLOB/LargeBinary-Bild ~ 1 MB groß. Ich musste die Einstellung max_allowed_packet config in MySQL anpassen. 

Ich habe mysqld --max-allowed-packet=16M verwendet

1
Matt

Wenn Sie "Pool" verwenden, sollten Sie "recycle less" als "wait_timeout" für DB "wait_timeout" auf 60 festlegen

from sqlalchemy.pool import Pool
pool.QueuePool(self.get_connection, max_overflow=0,pool_size=40,recycle=50)
0
alones