2009-12-01 63 views
49

可以这样做吗?在使用SQLite管理许多项目的单一应用程序中。 我想要的是我的应用程序正在管理的每个项目都有一个不同的数据库..因此,具有相同结构化数据库的多个副本,但具有不同的数据。我将根据URI上的参数选择使用哪个副本。Rails中的多个数据库

这是为1.安全..我是这种编程newbe,我不希望它发生,因为某种原因,而在一个项目上工作时,另一个得到损坏.. 2.容易旧项目的备份和归档

+0

http://imnithin.github.io/multiple-database.html – Nithin 2015-02-28 07:36:04

回答

38

Rails默认情况下不适用于多数据库体系结构,在大多数情况下,它根本没有意义。 但是,您可以使用不同的数据库和连接。

下面是一些参考:

+0

不能说更好。例如,环境也使生产和开发之间有一个不同的数据库系统变得更容易。我不会推荐做这个想法 – marcgg 2009-12-02 11:55:33

+0

我打算做一个类似的选择,因为我期望某些数据库表有数以百万计的记录。将数据库拆分为每个客户端的单独实例将使我可以拥有一台具有多个数据库服务器的应用程序服务器。 – Mika 2013-12-16 09:18:01

+0

您的最后两个链接不再相关。第一个可能会过时使用新版本的导轨。请在答案中列出相关的代码片段。 – ndn 2017-11-14 09:18:20

4

你也应该看看这个项目称为DB魔术师: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/

DbCharmer是ActiveRecord的一个简单而强大的插件,做了几件事情:

  1. 让您轻松管理AR模型的连接(switch_connection_to法)
  2. 让您切换AR模型为默认连接不同的服务器/数据库
  3. 让您轻松选择您的查询应该去(on_*方法家族)
  4. 允许您自动发送读取查询到你的奴隶,而主人将处理所有的更新。
  5. 添加多个数据库迁移到ActiveRecord的
+1

该插件已被作者杀死,截至2015年1月2日,没有人参与维护该插件。 – Smar 2015-02-02 13:14:28

26

如果你能控制和配置每个Rails的实例,你能负担得起浪费,因为他们的资源是处于待机状态,节省自己的一些麻烦,只需更改database.yml来修改每个实例上使用的数据库连接。如果你关心性能,这种方法不会削减它。

对于绑定到一个独特的表中只有一个数据库的模型,你可以调用establish_connection模型内部:

establish_connection "database_name_#{RAILS_ENV}" 

如下所述:http://apidock.com/rails/ActiveRecord/Base/establish_connection/class

你将不得不使用表有些机型从一个数据库以及其他使用其他数据库表格的不同模型。

如果您拥有相同的表格,这些表格在不同的数据库上是通用的,并且由单个模型共享,ActiveRecord将不会对您有所帮助。早在2009年,我就需要使用Rails 2.3.8开发一个项目。我为每个客户建立了一个数据库,并使用他们的ID命名数据库。因此,我创建的方法来改变内部ApplicationController中的连接:

def change_database database_id = params[:company_id] 
    return if database_id.blank? 

    configuration = ActiveRecord::Base.connection.instance_eval { @config }.clone 
    configuration[:database] = "database_name_#{database_id}_#{RAILS_ENV}" 

    MultipleDatabaseModel.establish_connection configuration 
end 

,并补充说方法作为的before_filter到所有控制器:

before_filter :change_database 

因此,对于每一个控制器的各动作,当PARAMS [ :company_id]被定义并设置,它会将数据库更改为正确的数据库。

要处理迁移我的ActiveRecord扩展迁移::,与查找所有客户的方法和迭代块,每个ID:

class ActiveRecord::Migration 
    def self.using_databases *args 
     configuration = ActiveRecord::Base.connection.instance_eval { @config } 
     former_database = configuration[:database] 

     companies = args.blank? ? Company.all : Company.find(args) 

     companies.each do |company| 
      configuration[:database] = "database_name_#{company[:id]}_#{RAILS_ENV}" 
      ActiveRecord::Base.establish_connection configuration 

      yield self 
     end 

     configuration[:database] = former_database 
     ActiveRecord::Base.establish_connection configuration 
    end 
end 

注意,通过这样做,就不可能为你在两个不同的数据库的同一个动作中进行查询。您可以再次调用change_database,但当您尝试使用不再链接到正确数据库的对象执行查询时,它会变得很讨厌。另外,显然你不能连接属于不同数据库的表。

为了正确处理这个问题,ActiveRecord应该有相当的扩展。现在应该有一个插件来帮助你解决这个问题。一个快速的研究给了我这一个:

DB-魔术师:http://kovyrin.github.com/db-charmer/

我愿意尝试。让我知道什么适合你。

2

值得注意的是,在所有这些解决方案中,您需要记住关闭自定义数据库连接。你用完连接,否则看到奇怪的请求超时问题。

一个简单的解决方案是clear_active_connections!在控制器的after_filter中。

after_filter :close_custom_db_connection 

def close_custom_db_connection 
    MyModelWithACustomDBConnection.clear_active_connections! 
end 
+4

Rails使用连接池,它应该防止过度使用某些连接限制。 – Anatoly 2014-01-31 23:02:11

12

我过去,这通过使用其他数据库

class Customer < ActiveRecord::Base 
    ENV["RAILS_ENV"] == "development" ? host = 'devhost' : host = 'prodhost' 

    self.establish_connection(
     :adapter => "mysql", 
     :host  => "localhost", 
     :username => "myuser", 
     :password => "mypass", 
     :database => "somedatabase" 
    ) 
0

在你的配置添加该我的模型顶部/ database.yml中做这样的事情

default: &default 
    adapter: postgresql 
    encoding: unicode 
    pool: 5 

development: 
    <<: *default 
    database: mysite_development 

test: 
    <<: *default 
    database: mysite_test 

production: 
    <<: *default 
    host: 10.0.1.55 
    database: mysite_production 
    username: postgres_user 
    password: <%= ENV['DATABASE_PASSWORD'] %> 

db2_development: 
    <<: *default 
    database: db2_development 

db2_test: 
    <<: *default 
    database: db2_test 

db2_production: 
    <<: *default 
    host: 10.0.1.55 
    database: db2_production 
    username: postgres_user 
    password: <%= ENV['DATABASE_PASSWORD'] %> 

然后在你的模特里你可以参考db2

class Customers < ActiveRecord::Base 
    establish_connection "db2_#{Rails.env}".to_sym 
end 
0

您在问题中描述的是多租户(每个数据库中具有不同数据的结构相同的数据库)。 Apartment gem非常适合这个。

对于Rails中多个数据库的一般问题:ActiveRecord支持多个数据库,但Rails没有提供管理它们的方法。我最近创建了Multiverse宝石来解决这个问题。