了解establish_connection如何在ActiveRecord中工作

时间:2011-08-25 13:24:24

标签: ruby-on-rails ruby activerecord

此代码取自ActiveRecord 2.3.14的gem class ConnectionHandler

def establish_connection(name, spec)
  @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
end

每次ruby在模型上调用establish_connection时,它都会创建一个新的连接池。

我的问题:

如果我有5个模型使用establish_connection到同一个数据库,那么Rails是否足够智能选择已有的池而不是创建具有相同连接凭据的新池?如果我的5个模型是使用establish_connection的某个抽象类的子类,是否也会发生这种情况?它是否总是从@connection_pools中选择一个连接(如果它存在?)

更新1

我说的是一个具体的例子。你有5个模型,有5个不同的连接,每次Rails使用它执行的模型establish_connection。查看ActiveRecord中的代码,当它执行establish_connection时,它会创建一个与该特定连接有连接的新池。我想知道的是,每次Rails调用模型establish_connection时,它是创建新池还是现有池。

示例:您访问我的网站并查看产品列表。您刚刚点击了一个调用Product.all的操作,该操作会对亚马逊上的某个数据库执行establish_connection。然后,我来到产品列表,会发生什么?我是否已获取已建立的连接,或者是否正在创建具有该连接的新池?

更新2

我的猜测是,第一次Rails加载我的模型时,它会创建具有不同连接的池。之后,当我使用一些Model.method时,它只是抓取与模型关联的连接并执行该方法。

我不确定当2个模型有两个相等的连接时会发生什么(不是在抽象类中而是在自习类中)。这会产生两个相同的连接池,还是ActiveRecord足够智能来捕捉这种情况?

3 个答案:

答案 0 :(得分:15)

AR仅为ActiveRecord :: Base调用一次Establish_connection。所有子类都使用一个连接。

您可以在某些子类上自己手动调用建立连接。这对于一次使用两个数据库非常方便,例如

class MyMainUser < ActiveRecord::Base; end 
class MyOtherDb < ActiveRecord::Base; end
class MyOtherUser < MyOtherDb; end

MyOtherDb.establish_connection ...

MyMainUser.first # uses default db
MyOtherUser.first # uses other db

您无法进行跨数据库的查询。

答案 1 :(得分:9)

您真的不必在每个型号上调用establish_connection。你可以简单地做下一步:

ActiveRecord::Base.establish_connection(
 { :adapter => 'mysql2',
   :database => 'some_database',
   :host => 'localhost',
   :username => 'root',
   :password => "" }
)

您将可以访问连接。 (这段代码是从实际代码中提取的(数据库名称:)除外)。) 但根据API,我认为Rails不接受其他模型的现有连接(如果我错了,请纠正我) 这里还有一个link to documentation。你可以在那里阅读更多有关连接的信息。
我希望我能帮助你。

答案 2 :(得分:2)

此评论:

# Check-out a database connection from the pool, indicating that you want
# to use it. You should call #checkin when you no longer need this.
#
# This is done by either returning an existing connection, or by creating
# a new connection. If the maximum number of connections for this pool has
# already been reached, but the pool is empty (i.e. they're all being used),
# then this method will wait until a thread has checked in a connection.
# The wait time is bounded however: if no connection can be checked out
# within the timeout specified for this pool, then a ConnectionTimeoutError
# exception will be raised.

来自:https://github.com/rails/rails/blob/dd944cbf5879e675fff541d1be7c7eb6c3382d01/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L242-251

应该说明情况