Without manually calling checkout / checkin on the connection pool will a request cycle use a single connection for serial requests? For example, given the following snippet:
def show
@user = User.find(...)
@post = @user.posts.find(...)
@blog = Blog.find(...)
...
end
Will each of the generated SQL calls (SELECT * FROM users ..., SELECT * FROM posts ... and SELECT * FROM blogs ...) be guaranteed to use the same connection in each case or will it potentially checkout / checkin a new / old connection between queries?
Furthermore - do long running transactions 'block' the connection pool (assuming this can only happen if a single connection isn't checkout on the start of a request and checkin at the end)?
User.transaction do
@user.touch
sleep 5
@user.touch
end
VS:
@user.touch
sleep 5
@user.touch
The documentation on ConnectionPool suggests that there is only a single connection to the db used for each thread.
Let me dive in the Rails 4.2 source code to support this claim:
All finder methods (such as Model.find(...)) that are defined in the FinderMethods module eventually call some query method on the connection object.
The connection (which can be also referenced as ActiveRecord::Base.connection) is defined in the ConnectionHandling module and it just calls the ConnectionHandler to retrieve a connection.
The ConnectionHandler, after finding the right database to get connection from (a rails project may use multiple databases), finally calls the connection method.
This method (as described in the source code docs) returns the connection associated with the current thread. Internally it uses a connections cache where the key is the Thread.current.object_id, i.e. a unique ID of the current thread.
So, based on this information, I think we can conclude that unless you worked with manually created threads in your code or unless you checked out the connection by yourself, serial queries in a given model / controller should always be called on a single connection to the db. And they should never checkout / checkin in between your queries as the thread is normally never switched during a single request.
On the other hand, all parts of code that use different threads to the request thread will use a different connection from the pool. Examples might be background jobs, manually created threads or different threads of the Puma application server.
As of your second question about blocking - long-running queries will certainly block the current connection but the connection pool itself should still be perfectly available for other threads in the meantime (unless there are more threads than configured connections in the pool - the thread trying to retrieve the new connection would have to wait until some of the other threads finishes its work).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With