代码之家  ›  专栏  ›  技术社区  ›  luca

Rails中的多个数据库

  •  50
  • luca  · 技术社区  · 15 年前

    能做到吗?在单个应用程序中,它使用sqlite管理许多项目。 我想要的是为我的应用程序正在管理的每个项目建立一个不同的数据库。因此,一个相同结构的数据库的多个副本,但其中包含不同的数据。我将根据URI上的参数选择要使用的副本。

    这是为1完成的。安全性。我是这类编程的新手,我不希望在进行另一个项目时由于某种原因而发生这种情况,因为另一个项目会被破坏。2。轻松备份和存档旧项目

    7 回复  |  直到 7 年前
        1
  •  39
  •   Simone Carletti    15 年前

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

    以下是一些参考资料:

        2
  •  26
  •   adeandrade    13 年前

    如果您能够控制和配置每个Rails实例,并且由于它们处于待机状态而浪费资源,那么就可以省去一些麻烦,只需更改database.yml就可以修改每个实例上使用的数据库连接。如果您关心性能,这种方法不会降低性能。

    对于仅绑定到一个数据库上单个唯一表的模型,可以在模型内部调用establish_connection:

    establish_connection "database_name_#{RAILS_ENV}"
    

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

    您将有一些模型使用一个数据库中的表,其他不同的模型使用其他数据库中的表。

    如果您有相同的表,在不同的数据库中是通用的,并且由单个模型共享,那么ActiveRecord将不会帮助您。早在2009年,我就要求在我正在工作的一个项目中使用Rails2.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 :change_database
    

    因此,对于每个控制器的每个操作,当定义和设置参数[:company_id]时,它会将数据库更改为正确的数据库。

    为了处理迁移,我扩展了ActiveRecord::Migration,使用一种方法查找所有客户并使用每个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
    

    请注意,通过这样做,您将不可能在同一操作中从两个不同的数据库进行查询。你可以打电话 转换数据库 但是,当您尝试使用执行查询的方法时,如果对象不再链接到正确的数据库,就会变得很糟糕。此外,很明显您将无法联接属于不同数据库的表。

    要正确处理这一点,ActiveRecord应该大大延长。现在应该有一个插件来帮助您解决这个问题。一个快速的研究给了我这个:

    DB CalMe: http://kovyrin.github.com/db-charmer/

    我愿意试试。让我知道什么对你有用。

        3
  •  12
  •   rdaniels    11 年前

    我通过使用另一个数据库将它添加到我的模型顶部来克服这个问题。

    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"
        )
    
        4
  •  4
  •   SquareCog    15 年前

    您还应该查看这个名为db charmer的项目: 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
        5
  •  2
  •   Steven Soroka    13 年前

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

    一个简单的解决方案是清除活跃的连接!在控制器的后过滤器中。

    after_filter :close_custom_db_connection
    
    def close_custom_db_connection
      MyModelWithACustomDBConnection.clear_active_connections!
    end
    
        6
  •  0
  •   rdaniels    7 年前

    在config/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'] %>
    

    然后,在您的模型中,您可以使用

    class Customers < ActiveRecord::Base
      establish_connection "db2_#{Rails.env}".to_sym
    end
    
        7
  •  0
  •   Andrew Kane    7 年前

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

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