2009-12-01 6 views
49

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

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

+0

http://imnithin.github.io/multiple-database.html – Nithin

ответ

38

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

Вот некоторые ссылки:

+0

Не мог бы сказать это лучше. Среды также облегчают работу с другой системой db между производством и разработкой, например. Я бы не рекомендовал это делать. – marcgg

+0

Я планирую сделать аналогичный выбор, потому что я ожидаю, что в некоторых таблицах базы данных будут сотни миллионов записей.Разделение базы данных на отдельные экземпляры на одного клиента позволит мне иметь один сервер приложений с несколькими серверами баз данных. – Mika

+0

Ваши последние две ссылки больше не актуальны. И первая может устареть с новой версией рельсов. Пожалуйста, вставьте соответствующие фрагменты кода в ответ. – ndn

4

Вы должны также проверить этот проект под названием DB Заклинатель: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/

DbCharmer является простой, но мощный плагин для ActiveRecord, который делает несколько вещей:

  1. позволяет Вам легко управлять соединения (switch_connection_to метод)
  2. Позволяет переключать AR моделей AR моделей соединений по умолчанию к отдельные серверы/базы данных
  3. Позволяет легко выбрать, где ваш запрос должен идти (on_* методы семьи)
  4. Позволяет автоматически отправлять запросы чтения ваших рабов в то время как мастера обработает все обновления.
  5. Добавляет несколько баз данных миграции в ActiveRecord
+1

Плагин был убит автором, начиная с 02.01.2015, никто не вмешался, чтобы его сохранить. – Smar

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. У меня была база данных для каждого клиента, и я назвал базы данных с их идентификаторами.Поэтому я создал метод, чтобы изменить соединение внутри 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-Заклинатель: 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

Рельсы действительно используют пул соединений, это должно предотвратить чрезмерное использование определенного предела подключения. – Anatoly

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, чтобы решить эту проблему.

Смежные вопросы