Этот код был взят из класса гема 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
, если оно существует?
Я говорю о конкретном примере. У вас есть 5 моделей с 5 различными подключениями, каждый раз, когда Rails использует модель, которую он выполняет, establish_connection
. Глядя на код в ActiveRecord, когда он выполняет establish_connection
, он создает новый пул с подключениями к этому конкретному соединению. Мне интересно, каждый раз, когда Rails вызывает модель establish_connection
, создает ли она новый пул или берет существующий.
Пример: вы заходите на мой сайт и видите список товаров. Вы только что выполнили действие, вызывающее Product.all
, которое выполняет establish_connection
в некоторой базе данных на Amazon. Затем я перехожу к списку продуктов, что происходит? Получу ли я установленное соединение или создаю новый пул с этим соединением?
Обновление 2
Я предполагаю, что в первый раз, когда Rails загружает мои модели, он создает пулы с разными подключениями. После, когда я использую Model.method
, он просто захватывает соединение, связанное с моделью, и выполняет метод.
Я не уверен, что происходит, когда две модели имеют два равных соединения (не в абстрактном классе, а в собственном классе). Будет ли это создавать два одинаковых пула соединений или ActiveRecord достаточно умен, чтобы отловить этот случай?
3 ответа
Вам действительно не нужно вызывать establish_connection
для каждой модели. Вы можете просто сделать следующее:
ActiveRecord::Base.establish_connection(
{ :adapter => 'mysql2',
:database => 'some_database',
:host => 'localhost',
:username => 'root',
:password => "" }
)
И у вас будет доступ к подключению. (Этот фрагмент кода был извлечен из реального кода (кроме имени базы данных :)).
Но согласно API я думаю, что Rails не берет существующее соединение из другой модели (поправьте меня, если я ошибаюсь).
Также здесь есть ссылка на документацию. Вы можете узнать больше о связи там.
Надеюсь, я вам немного помог.
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
Однако вы не можете выполнять запросы, которые будут пересекать базы данных.
Этот комментарий:
# 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.