【问题标题】:Connecting Rails 3.1 with Multiple Databases将 Rails 3.1 与多个数据库连接起来
【发布时间】:2011-05-25 09:50:18
【问题描述】:

在 ShowNearby,我们一直在进行从 PHP 到 RoR 3.1 的大规模迁移,我们面临的几个问题可能你们中的一些人以前已经解决过。

我们有大量数据,我们决定将我们的数据库分成几个我们可以单独处理的数据库。例如,我们的帐户、地点、日志等被拆分到多个数据库中

我们需要获得迁移、固定装置、模型,才能很好地发挥作用,但到目前为止它一直很混乱。我们对解决方案可接受的一些要求:

  • 一个模型应该与其中一个数据库中的一个表相关。
  • rake db:drop - 应该删除我们在 database.yml 中指定的所有数据库环境
  • rake db:create - 应该创建我们在 database.yml 中指定的所有数据库环境
  • rake db:migrate - 应该运行迁移到各种数据库
  • rake db:test - 应该抓取固定装置并将它们放入各种数据库和测试单元/功能/等中

我们正在考虑为每个数据库设置单独的 Rails 项目,并将它们与 ActiveResource 连接起来,但我们认为这不是很有效。你们中有人处理过类似的问题吗?

【问题讨论】:

  • 我们也在考虑从 PHP 应用程序升级到 Rails 应用程序;你有什么运气吗?
  • 嗨@Tommyixi:这是很久以前的事了,从那以后发生了很多变化。现在回想起来,我认为将它们聚合到一个数据库中比将其拆分到多个数据库中更好

标签: ruby-on-rails ruby ruby-on-rails-3 rails-activerecord activeresource


【解决方案1】:

对于 Wukerplank 的回答,您还可以像往常一样将连接详细信息放在 database.yml 中,名称如下:

log_database_production:
  adapter: mysql
  host: other_host
  username: logmein
  password: supersecret
  database: logs

然后在你的特殊模型中:

class AccessLog < ActiveRecord::Base
  establish_connection "log_database_#{Rails.env}".to_sym
end

防止那些讨厌的凭据出现在您的应用程序代码中。

编辑:如果你想在多个模型中重用这个连接,你应该创建一个新的抽象类并从它继承,因为连接与类紧密耦合(如here,@ 987654322@ 和 here),并且将为每个类创建新的连接。

如果是这种情况,请像这样设置:

class LogDatabase < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "log_database_#{Rails.env}".to_sym
end

class AccessLog < LogDatabase
end

class CheckoutLog < LogDatabase
end

【讨论】:

  • 如何考虑环境变化?因此,例如在开发中我想establish_connection 使用log_dev 数据库,但在生产中我想establish_connection 使用log 数据库。我可以打电话给Rails.env 吗?
  • @AzizLight establish_connection "log_database_#{Rails.env}"
  • 提前警告。似乎使用此方法会使其他数据库上的连接保持打开状态,而不会重用它们。这将使您的应用程序在重负载下停止运行。
  • @Altonymous 好点。我认为您指的是这种行为:github.com/rails/rails/issues/7019 连接与类耦合;所以如果你需要重用连接,你应该在一个抽象类上建立它并从它继承而不是AR::Base。我更新了我的答案以反映这一点。
  • 是的。完美的。如果你没有很快回复,我会回复这个答案。 :P
【解决方案2】:

连接到不同的数据库非常简单:

# model in the "default" database from database.yml
class Person < ActiveRecord::Base

  # ... your stuff here

end

# model in a different database
class Place < ActiveRecord::Base

  establish_connection (
    :adapter  => "mysql",
    :host     => "other_host",
    :username => "username",
    :password => "password",
    :database => "other_db"
  )

end

我会警惕设置多个 Rails 项目,因为您会为控制器的数据检索增加大量开销,这可能会使事情变慢。

至于您关于迁移、固定装置、模型等的问题:我认为不会有简单的方法,所以请单独发布问题并尽可能具体。

将数据库合并为一个不是一种选择?它会让你的生活更轻松!

【讨论】:

  • 问题是上面的示例不能正确使用连接池
【解决方案3】:

找到了一篇很棒的帖子,可以为其他人指出正确的做法,请查看http://blog.bitmelt.com/2008/10/connecting-to-multiple-database-in-ruby.html

设置如下:

database.yml(数据库配置文件)

support_development:
    adapter: blah
    database: blah
    username: blah
    password: blah

support_base.rb(模型文件)

class SupportBase < ActiveRecord::Base
    self.abstract_class = true #important!
    establish_connection("support_development")
end

tst_test.rb(模型文件)

class TstTest < SupportBase 
    #SupportBase not ActiveRecord is important!

    self.table_name = 'tst_test'

    def self.get_test_name(id)
        if id = nil
            return ''
        else
            query = "select tst_name from tst_test where tst_id = \'#{id}\'"
            tst = connection.select_all(query) #select_all is important!
            return tst[0].fetch('tst_name')
        end
    end
end

PS,这确实不包括迁移,我认为您不能使用 rake 在多个数据库上进行迁移(尽管我不确定这是一个很难的“不能做”,但它可能是可能的) .这只是连接和查询您无法控制的其他数据库的好方法。

【讨论】:

    【解决方案4】:

    您可能还想附加 Rails 环境,因此您的开发和测试数据库不一样。

    establish_connection "legacy_#{Rails.env}"
    

    【讨论】:

      【解决方案5】:

      following article 建议定义新的 Rake 任务以实现针对多个数据库的迁移。每个任务都建立自己的连接,然后使用此连接和特定的数据库文件夹执行迁移。

      它还定义了一个熟悉的db:migrate,它调用另外两个任务。

      包括这里,以防链接不可用:

      desc "Migrate the database through scripts in db/migrate directory."
      
      namespace :db do
        task :migrate do
          Rake::Task["db:migrate_db1"].invoke
          Rake::Task["db:migrate_db2"].invoke
        end
      
        task :migrate_db1 do
          ActiveRecord::Base.establish_connection DB1_CONF
          ActiveRecord::Migrator.migrate("db/migrate/db1/")
        end
      
        task :migrate_db2 do
          ActiveRecord::Base.establish_connection DB2_CONF
          ActiveRecord::Migrator.migrate("db/migrate/db2/")
        end
      end
      

      来源: Ruby on Rails Connect to Multiple Databases and Migrations

      【讨论】:

        【解决方案6】:

        嘿,这篇文章已经过时了,但我找到了一个适用于 Rails 3.2 的解决方案,可能对其他人有所帮助。 https://stackoverflow.com/a/16542724/1447654

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-02
          • 1970-01-01
          • 2012-05-15
          • 1970-01-01
          • 1970-01-01
          • 2015-06-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多