我的公司即将结束从我们的 Rails 2.x 应用程序到 Rails 4 的大规模迁移/升级。是的,我知道在撰写本文时,Rails 4 处于 RC 而不是最终版本,但我们的目标是等到 4.0 最终版就准备好了。我们经历了整个升级过程,根据需要更换和升级宝石,但最终遇到了一个非常大的砖墙。
一些快速背景:
我们使用独角兽来提供我们的应用程序
我们有两个 PostgreSQL 数据库,每个都在不同的服务器上。一个是master,另一个是热复制只读standby。我们应用程序中的两个控制器根据我们的数据提供报告。这些报告通常是 SQL 密集型的,因此我们拥有无缝数据库池 gem,这些控制器操作中的所有查询都通过 PostgreSQL 备用只读框。
不幸的是,无缝数据库池尚未更新为与 Rails 4 一起使用。我们已经研究了章鱼和其他各种宝石,但没有运气。我最近刚刚想到了如何通过忘记使用 gem 来处理这个问题的想法,只是在请求这些特定控制器时切换连接,然后确保在请求完成后连接切换回另一个数据库业务,因此未来对该独角兽工作者的请求将默认为主数据库。
我想知道这是否是一个非常糟糕的主意,以及其他人是否有更好的建议。
数据库.yml:
production:
host: primary_db_host_ip
adapter: postgresql
encoding: unicode
database: my_app_production
pool: 5
username: ****
password: ****
standby_by:
host: standby_db_host_ip
adapter: postgresql
encoding: unicode
database: my_app_production
pool: 5
username: ****
password: ****
应用程序/控制器/application_controller.rb:
class ApplicationController < ActionController::Base
...
...
private
def switch_db
ActiveRecord::Base.establish_connection("standby_db")
yield
ensure
ActiveRecord::Base.establish_connection("production")
end
end
应用程序/控制器/special_controller.rb:
class SpecialController < ApplicationController
around_action :switch_db
...
...
end
更新:特别是对于那些询问如何知道它是否没有准备好 Rails 4 的人来说,这是无缝数据库池发生的错误......
undefined method `reset_transaction' for nil:NilClass (NoMethodError)
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:336:in `proxy_connection_method'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:122:in `block in reset_transaction'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:243:in `use_master_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:121:in `reset_transaction'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:6:in `initialize'
/home/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/monitor.rb:232:in `initialize'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract_adapter.rb:90:in `initialize'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:152:in `initialize'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:48:in `new'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/seamless_database_pool-1.0.12/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb:48:in `seamless_database_pool_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:440:in `new_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:450:in `checkout_new_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:421:in `acquire_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:356:in `block in checkout'
/home/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:355:in `checkout'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:265:in `block in connection'
/home/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:264:in `connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_adapters/abstract/connection_pool.rb:546:in `retrieve_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_handling.rb:79:in `retrieve_connection'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/activerecord-4.0.0.rc1/lib/active_record/connection_handling.rb:53:in `connection'
config/unicorn.rb:16:in `block in reload'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/unicorn-4.6.2/lib/unicorn/http_server.rb:495:in `call'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/unicorn-4.6.2/lib/unicorn/http_server.rb:495:in `spawn_missing_workers'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/unicorn-4.6.2/lib/unicorn/http_server.rb:142:in `start'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/gems/unicorn-4.6.2/bin/unicorn_rails:209:in `<top (required)>'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/bin/unicorn_rails:23:in `load'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/bin/unicorn_rails:23:in `<main>'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/bin/ruby_noexec_wrapper:14:in `eval'
/home/.rvm/gems/ruby-2.0.0-p195@theapp/bin/ruby_noexec_wrapper:14:in `<main>'