【问题标题】:How can I establish a connection to multiple databases, with the same adapter(postgres), using active_record gem?如何使用 active_record gem 使用相同的适配器(postgres)建立与多个数据库的连接?
【发布时间】:2019-02-11 04:57:24
【问题描述】:

你好吗?当我尝试在 postres 中建立与两个数据库的连接时,我遇到了一些麻烦。我将尝试描述场景:

这是我的 pg.yml:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5
  host: localhost
  user: xxxxx
  password: xxxxx

development:
  <<: *default
  database: not_legacy

legacy:
  <<: *default
  database: legacy

这是我的 Legacy::Base 类:

#/models/legacy/base.rb

require 'active_record'
require 'erb'

module Legacy
  class Base < ActiveRecord::Base
    self.abstract_class = true

    conf_contents = File.read('config/pg.yml')
    conf_evaluated = ::ERB.new(conf_contents).result
    conf = YAML.load(conf_evaluated)

    ActiveRecord::Base.establish_connection conf['legacy']
  end
end

这是我的 NotLegacy::Base 类:

#/models/not_legacy/base.rb

require 'active_record'
require 'erb'

module NotLegacy
  class Base < ActiveRecord::Base
    self.abstract_class = true

    conf_contents = File.read('config/pg.yml')
    conf_evaluated = ::ERB.new(conf_contents).result
    conf = YAML.load(conf_evaluated)

    ActiveRecord::Base.establish_connection conf['not_legacy']
  end
end

另外,我有两个类继承自前面描述的类。 这是旧版::公司:

#/models/legacy/company.rb    

require_relative 'base'

module Legacy
  class Company < Base
    self.table_name = "company"
  end
end

和 NotLegacy::Company:

#/models/not_legacy/company.rb    

require_relative 'base'

module NotLegacy
  class Company < Base
    self.table_name = "company"
  end
end

现在,如果我去控制台并执行类似的操作(我正在打印 conf 值):

irb(main):001:0> load 'app/models/legacy/company.rb'
CONFS: {"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>5, "host"=>"localhost", "user"=>"xxxxx", "password"=>"xxxxx", "database"=>"legacy"}
=> true
irb(main):002:0> Legacy::Company.count
=> 8
irb(main):003:0> load 'app/models/not_legacy/company.rb'
CONFS: {"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>5, "host"=>"localhost", "user"=>"xxxxx", "password"=>"xxxxx", "database"=>"not_legacy"}
=> true
irb(main):004:0> NotLegacy::Company.count
=> 1

此时似乎一切正常,因为在 legacy 数据库中有 8 条记录 用于公司,而在 not_legacy 数据库中有只有 1 条记录。但如果我再次调用 Legacy::Company,我会得到:

irb(main):005:0> Legacy::Company.count
=> 1
irb(main):005:0> NotLegacy::Company.count
=> 1

似乎第二个连接(与 not_legacy 数据库建立的连接)覆盖第一个连接(与旧数据库建立的连接)。

如果你们中的任何人能解释一下为什么会发生这种情况以及如何解决它,我将非常感激

谢谢。

【问题讨论】:

  • 请看一下,我想你会在这里得到答案stackoverflow.com/a/1832441/3445936
  • @rohit 是的,我想它是完美的参考,但是 rails 可以处理多个数据库但切换有点困难。
  • 我建议研究像 octopusactive_record_shards 这样的开源 gem,因为编写自己的分片逻辑涉及线程安全问题和复杂性。

标签: ruby-on-rails ruby database postgresql activerecord


【解决方案1】:

首先我想了解一下您是如何完成代码流的,

当您加载任何类时,会执行其代码并定义方法,通过编写的静态代码创建您的连接并执行establish_connection

Rails 应用程序的单个瞬间可以连接到单个数据库

您最好编写代码来切换不同的数据库以访问不同的数据库连接。

Legacy::CompanyNotLegacy::Company 两个模型具有来自不同数据库的相同表名 companies。但是,当您连接特定数据库时,两个模型(已加载)都将指向当前数据库中的 companies 表。

So what is current database mean to both model ? -> 上次被establish_connection加载的那个。

所以这有点乏味,但如果你处理不同的数据库,你必须不断地从一个数据库切换到另一个数据库。

【讨论】:

    【解决方案2】:

    关于 config/database.yml

    other_base:
      adapter: postgresql
      encoding: unicode
      pool: 5
      host: localhost
      user: xxxxx
      password: xxxxx
    

    在你的模型上

    class YourModel < ActiveRecord::Base
       self.establish_connection :other_base
    end
    

    【讨论】:

      猜你喜欢
      • 2021-03-29
      • 1970-01-01
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      相关资源
      最近更新 更多