Этот код был взят из класса гема ActiveRecord 2.3.14 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 в некоторой базе данных на Amazon. Затем я перехожу к списку продуктов, что происходит? Получу ли я установленное соединение или создаю новый пул с этим соединением?

Обновление 2

Я предполагаю, что в первый раз, когда Rails загружает мои модели, он создает пулы с разными подключениями. После, когда я использую Model.method, он просто захватывает соединение, связанное с моделью, и выполняет метод.

Я не уверен, что происходит, когда две модели имеют два равных соединения (не в абстрактном классе, а в собственном классе). Будет ли это создавать два одинаковых пула соединений или ActiveRecord достаточно умен, чтобы отловить этот случай?

34
Filip 25 Авг 2011 в 17:24

3 ответа

Лучший ответ

Вам действительно не нужно вызывать establish_connection для каждой модели. Вы можете просто сделать следующее:

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

И у вас будет доступ к подключению. (Этот фрагмент кода был извлечен из реального кода (кроме имени базы данных :)).
Но согласно API я думаю, что Rails не берет существующее соединение из другой модели (поправьте меня, если я ошибаюсь).
Также здесь есть ссылка на документацию. Вы можете узнать больше о связи там.
Надеюсь, я вам немного помог.

9
Lluís 2 Апр 2014 в 11:20

AR вызывает create_connection только один раз, для ActiveRecord :: Base. Все подклассы используют одно соединение.

Вы можете вручную установить соединение самостоятельно на некоторых подклассах. Это очень удобно для одновременного использования двух баз данных, например,

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

Однако вы не можете выполнять запросы, которые будут пересекать базы данных.

18
Mark Devo Lanett 20 Сен 2011 в 04:57

Этот комментарий:

# 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.

От:

halogenandtoast 14 Сен 2011 в 18:48