2016-03-29 8 views
2

Ohne manuellen Checkout/Check-in für den Verbindungspool wird ein Anforderungszyklus eine einzelne Verbindung für serielle Anforderungen verwenden? Um zum Beispiel die folgenden Ausschnitt gegeben:Rails-Verbindungspool innerhalb des Aktionspaketanforderungszyklus Gleiche Verbindung

def show 
    @user = User.find(...) 
    @post = @user.posts.find(...) 
    @blog = Blog.find(...) 
    ... 
end 

Wird jede der erzeugten SQL-Aufrufe (SELECT * FROM users ..., SELECT * FROM posts ... und SELECT * FROM blogs ...) garantiert werden, um die gleiche Verbindung jeweils verwenden oder wird es möglicherweise Kasse/checkin ein neues/alte Verbindung zwischen Abfragen?

Darüber hinaus "blockiere" lange laufende Transaktionen den Verbindungspool (vorausgesetzt, dies kann nur passieren, wenn eine einzelne Verbindung am Anfang einer Anfrage nicht auscheckt und am Ende eincheckt)?

User.transaction do 
    @user.touch 
    sleep 5 
    @user.touch 
end 

VS:

@user.touch 
sleep 5 
@user.touch 

Antwort

0

Das legt nahe, dass documentation on ConnectionPooldort an die DB nur eine einzige Verbindung ist für jeden Thread verwendet.

mich in den Rails 4.2 Quellcode tauchen Lassen Sie diese Behauptung zu untermauern:

  • Alle Suchmethoden (wie Model.find(...)), die schließlich im FinderMethods Modul definiert sind, auf dem connection Objekt eine Abfrage-Methode aufrufen.

  • Die connection (die auch als ActiveRecord::Base.connection verwiesen werden kann) ist defined im ConnectionHandling Modul und es nur Anrufe der ConnectionHandler zu retrieve a connection.

  • Die ConnectionHandler, nachdem er die richtige Datenbank zu finden, Verbindung von zu bekommen (ein Schienen-Projekt können mehrere Datenbanken verwenden), ruft schließlich die connection method.

Dieses Verfahren (wie in der source code docs beschrieben) liefert die Verbindung mit dem aktuellen Thread zugeordnet. Intern verwendet es einen Verbindungscache, wobei der Schlüssel die Thread.current.object_id ist, d. H. Eine eindeutige ID des aktuellen Threads.

Also, basierend auf diesen Informationen, können wir schlussfolgern, dass, wenn Sie mit manuell erstellten Threads in Ihrem Code gearbeitet haben oder Sie die Verbindung selbst ausgecheckt haben, serielle Abfragen in einem bestimmten Modell/Controller immer aufgerufen werden sollten auf einer einzigen Verbindung zum db. Und sie sollten nie zwischen Ihren Abfragen auschecken/einchecken, da der Thread normalerweise nie während einer einzelnen Anfrage geschaltet wird.

Auf der anderen Seite verwenden alle Teile des Codes, die unterschiedliche Threads zu dem Anforderungsthread verwenden, eine andere Verbindung aus dem Pool. Beispiele können Hintergrundjobs, manuell erstellte Threads oder verschiedene Threads des Puma application server sein.

Ab Ihrer zweiten Frage zum Blockieren - lange laufende Abfragen werden sicherlich die aktuelle connection blockieren, aber der Verbindungspool selbst sollte in der Zwischenzeit für andere Threads immer noch perfekt verfügbar sein (außer es gibt mehr Threads als konfigurierte Verbindungen im Pool - Der Thread, der versucht, die neue Verbindung abzurufen, muss warten, bis einige der anderen Threads seine Arbeit beendet haben.

Verwandte Themen