将Rails 3.1与多个数据库连接


77

在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

@Tommyixi,您好:这是很久以前的事情,此后发生了很多变化。回想起来,我现在认为,将它们聚合到一个数据库中比将其拆分成多个数据库是一个更好的解决方案
Fer Martin

Answers:


142

为了解决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

为了避免这些讨厌的凭证被包含在您的应用程序代码中。

编辑:如果要在多个模型中重用此连接,则应创建一个新的抽象类并从中继承,因为连接与类紧密耦合(如hereherehere所述),并将为每个班级。

如果是这样,请按以下步骤进行设置:

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吗?
罗伯·奥迪

@AzizLightestablish_connection "log_database_#{Rails.env}"
Unixmonkey 2012年

12
被警告。看来,使用此方法会使其他数据库上的连接保持打开状态,而无需重新使用它们。这将使您的应用程序在重负载下停止运行。
匿名

10
@Altonymous好点。我认为您指的是这种行为:github.com/rails/rails/issues/7019连接已耦合到该类;因此,如果需要重用连接,则应在抽象类上建立连接并从其继承而不是从AR :: Base继承。我更新了答案以反映这一点。
Unixmonkey

是的 完善。如果您不久之后,我将回答这个问题。:P
匿名

18

连接到不同的数据库非常容易:

# 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项目,因为这将为控制器的数据检索增加很多开销,这可能会使事情变慢。

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

将数据库合并为一个不是一种选择吗?它将使您的生活更加轻松!


1
问题是上述示例无法正确使用连接池
Sam Saffron'7

11

找到了一篇很棒的文章,该文章将指出其他人执行此操作的正确方法,请访问 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在多个数据库上进行迁移(尽管我不确定这是很难做到的,但有可能)。这只是连接和查询您无法控制的其他数据库的好方法。


5

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

establish_connection "legacy_#{Rails.env}"

3

下面的文章指出定义新的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连接到多个数据库并进行迁移


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.