Несколько баз данных в Rails - PullRequest
       15

Несколько баз данных в Rails

51 голосов
/ 01 декабря 2009

Можно ли это сделать? В одном приложении, которое управляет многими проектами с SQLite. Я хочу иметь разные базы данных для каждого проекта, которым управляет мое приложение ... так что несколько копий идентично структурированной базы данных, но с разными данными в них. Я буду выбирать, какую копию использовать на основе параметров в URI.

Это сделано для 1. безопасности. Я новичок в этом виде программирования и не хочу, чтобы по какой-то причине во время работы над проектом был поврежден другой. и архив старых проектов

Ответы [ 8 ]

39 голосов
/ 02 декабря 2009

Rails по умолчанию не предназначен для архитектуры с несколькими базами данных и, в большинстве случаев, вообще не имеет смысла. Но да, вы можете использовать разные базы данных и соединения.

Вот несколько ссылок:

27 голосов
/ 04 октября 2011

Если вы можете контролировать и настраивать каждый экземпляр Rails, и вы можете позволить себе тратить ресурсы из-за того, что они находятся в режиме ожидания, избавьте себя от некоторых проблем и просто измените database.yml, чтобы изменить соединение с базой данных, используемое в каждом экземпляре. Если вы беспокоитесь о производительности, этот подход не снизит ее.

Для моделей, привязанных к единственной уникальной таблице только в одной базе данных, вы можете вызвать внутри модели установить_связь:

establish_connection "database_name_#{RAILS_ENV}"

Как описано здесь: http://apidock.com/rails/ActiveRecord/Base/establish_connection/class

Некоторые модели будут использовать таблицы из одной базы данных, а другие модели - таблицы из других баз данных.

Если у вас есть идентичные таблицы, общие для разных баз данных и совместно используемые одной моделью, ActiveRecord вам не поможет. Еще в 2009 году я требовал этого в проекте, над которым работал, используя Rails 2.3.8. У меня была база данных для каждого клиента, и я назвал базы данных с их идентификаторами. Поэтому я создал метод для изменения соединения внутри 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 :: 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

Обратите внимание, что, выполнив это, вы не сможете выполнять запросы в рамках одного и того же действия из двух разных баз данных. Вы можете снова вызвать change_database , но это будет неприятно, если вы попытаетесь использовать методы, выполняющие запросы, из объектов, больше не связанных с правильной базой данных. Кроме того, очевидно, что вы не сможете объединить таблицы, принадлежащие разным базам данных.

Для правильной обработки ActiveRecord должен быть значительно расширен. На данный момент должен быть плагин, чтобы помочь вам с этой проблемой. Быстрое исследование дало мне это:

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

Я готов попробовать. Дайте мне знать, что работает для вас.

12 голосов
/ 25 февраля 2014

Я преодолел это, добавив это в топ моих моделей, используя другую базу данных

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 голосов
/ 02 декабря 2009

Вы также должны проверить этот проект под названием 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
2 голосов
/ 14 декабря 2011

Стоит отметить, что во всех этих решениях вы должны помнить о необходимости закрытия пользовательских подключений к базе данных. У вас будет закончились соединения, и в противном случае вы увидите странные проблемы тайм-аута запроса.

Простое решение - clear_active_connections! в after_filter в вашем контроллере.

after_filter :close_custom_db_connection

def close_custom_db_connection
  MyModelWithACustomDBConnection.clear_active_connections!
end
0 голосов
/ 02 апреля 2019

Лучшее решение, которое я нашел до сих пор, это:

Есть 3 архитектуры баз данных, к которым мы можем обратиться.

  • Единая база данных для одного арендатора
  • Отдельная схема для каждого арендатора
  • Общая схема для арендаторов

Примечание: у них есть определенные плюсы и минусы, зависит от вашего варианта использования.

Я получил это из этого блога ! Стоит очень полезно для меня.

Вы можете использовать драгоценный камень Квартира для рельсов

Видеоролик вы можете посмотреть на Gorails для квартиры

0 голосов
/ 13 января 2018

То, что вы описали в этом вопросе, - это мультитенантность (идентично структурированные базы данных с разными данными в каждой). Квартира драгоценный камень отлично подходит для этого.

По общему вопросу о нескольких базах данных в Rails: ActiveRecord поддерживает несколько баз данных, но Rails не предоставляет способ управления ими. Недавно я создал камень Multiverse для решения этой проблемы.

0 голосов
/ 24 июля 2017

в вашем 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'] %>

тогда в ваших моделях вы можете ссылаться на db2 с помощью

class Customers < ActiveRecord::Base
  establish_connection "db2_#{Rails.env}".to_sym
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...