Понимание того, как install_connection работает в 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
в какой-либо базе данных на Amazon. Затем я прихожу к списку продуктов, что происходит? Ухватить ли я установленное соединение или создать новый пул с этим соединением?
Обновление 2
Я предполагаю, что Rails впервые загружает мои модели, создавая пулы с разными соединениями. После того, как я использую некоторый Model.method
, он просто захватывает соединение, связанное с моделью, и выполняет этот метод.
Я не уверен, что произойдет, когда 2 модели имеют два равных соединения (не в абстрактном классе, а в классе self). Будет ли это создавать два одинаковых пула соединений или достаточно ActiveRecord, чтобы поймать этот случай?
Ответы
Ответ 1
Вам действительно не нужно вызывать establish_connection
для каждой модели. Вы можете просто сделать следующее:
ActiveRecord::Base.establish_connection(
{ :adapter => 'mysql2',
:database => 'some_database',
:host => 'localhost',
:username => 'root',
:password => "" }
)
и у вас будет доступ к соединению. (Этот фрагмент кода был извлечен из реального кода (кроме имени базы данных:))).
Но по API я считаю, что Rails не использует существующее соединение с другой моделью (исправьте меня, если я ошибаюсь).
Также здесь ссылка на документацию. Вы можете больше узнать о подключении.
Надеюсь, я помог вам немного.
Ответ 2
AR вызывает connect_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
Вы не можете делать запросы, которые будут перекрещивать базы данных.
Ответ 3
Этот комментарий:
# 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.
from: https://github.com/rails/rails/blob/dd944cbf5879e675fff541d1be7c7eb6c3382d01/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L242-251
Должен объяснить ситуацию