2009-12-01 30 views
49

¿Se puede hacer esto? En una sola aplicación, eso administra muchos proyectos con SQLite. Lo que quiero es tener una base de datos diferente para cada proyecto que mi aplicación esté administrando ... así que hay varias copias de una base de datos estructurada de manera idéntica, pero con datos diferentes en ellas. Voy a elegir qué copia usar base en params en el URI.Múltiples bases de datos en Rails

Esto se hace para 1. la seguridad .. Soy un newbe en este tipo de programación y no quiero que suceda que por alguna razón mientras se trabaja en un proyecto, otro se corrompe .. 2. fácil copia de seguridad y archivo de proyectos anteriores

+0

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

Respuesta

38

Los rieles de forma predeterminada no están diseñados para una arquitectura de bases de datos múltiples y, en la mayoría de los casos, no tienen ningún sentido. Pero sí, puede usar diferentes bases de datos y conexiones.

Aquí hay algunas referencias:

+0

No podría haberlo dicho mejor. Los entornos también hacen que sea más fácil tener un sistema db diferente entre producción y desarrollo, por ejemplo. No recomendaría hacer esto. – marcgg

+0

Planeo hacer una elección similar porque espero que ciertas tablas de bases de datos tengan cientos de millones de registros.Dividir la base de datos en instancias separadas por cliente me permitiría tener un solo servidor de aplicaciones con múltiples servidores de bases de datos. – Mika

+0

Sus dos últimos enlaces ya no son relevantes. Y el primero podría quedar obsoleto con una nueva versión de los rieles. Por favor, inserte las piezas de código relacionadas en la respuesta. – ndn

4

También debe comprobar a cabo este proyecto llamado DB Charmer: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/

DbCharmer es un plugin simple pero potente para ActiveRecord que hace un par de cosas:

  1. le permite administrar fácilmente conexiones (switch_connection_to método)
  2. le permite cambiar los modelos AR modelos AR conexiones por defecto a una servidores/bases de datos separadas
  3. le permite elegir dónde debe ir la consulta (familia on_* métodos)
  4. le permite enviar automáticamente leer consultas a sus esclavos, mientras que los maestros se ocuparía de todas las actualizaciones.
  5. agrega varias migraciones de bases de datos a ActiveRecord
+1

El complemento ha sido eliminado por el autor, a partir del 02.01.2015, nadie ha intervenido para mantenerlo. – Smar

26

Si usted es capaz de controlar y configurar cada Rails ejemplo, y que pueden permitirse el derroche de recursos a causa de ellos estar en modo de espera, ahorrar un poco de apuro y sólo cambia el database.yml para modificar la conexión de base de datos utilizada en cada instancia. Si le preocupa el rendimiento, este enfoque no lo reducirá.

Para los modelos con destino a una sola tabla única en una sola base de datos que puede llamar establish_connection dentro del modelo:

establish_connection "database_name_#{RAILS_ENV}" 

Como se describe aquí: http://apidock.com/rails/ActiveRecord/Base/establish_connection/class

va a tener algunos modelos que utilizan las tablas de una base de datos y otros modelos diferentes que usan tablas de otras bases de datos.

Si tiene tablas idénticas, comunes en diferentes bases de datos y compartidas por un único modelo, ActiveRecord no lo ayudará. Allá por el año 2009 lo solicité en un proyecto en el que estaba trabajando, utilizando Rails 2.3.8. Tenía una base de datos para cada cliente y nombré las bases de datos con sus ID.Así que he creado un método para cambiar la conexión en el interior 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 

y ha añadido que el método como before_filter a todos los controladores:

before_filter :change_database 

Así, por cada acción de cada controlador, cuando params [ : company_id] está definido y configurado, cambiará la base de datos a la correcta.

Para manejar las migraciones extendí ActiveRecord :: Migración, con un método que busca todos los clientes y itera un bloque con cada 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 

Tenga en cuenta que al hacer esto, sería imposible para usted realizar consultas dentro de la misma acción desde dos bases de datos diferentes. Puede llamar al change_database nuevamente, pero se pondrá desagradable cuando intente usar métodos que ejecuten consultas, desde los objetos que ya no están vinculados a la base de datos correcta. Además, es obvio que no podrá unir tablas que pertenecen a diferentes bases de datos.

Para manejar esto correctamente, ActiveRecord debería extenderse considerablemente. Debería haber un complemento ahora para ayudarlo con este problema. Una investigación rápida me dio éste:

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

estoy dispuesto a intentarlo. Déjame saber lo que funciona para ti.

2

Vale la pena señalar que, en todas estas soluciones, debe recordar cerrar las conexiones de bases de datos personalizadas. Usted se quedará sin conexiones y verá problemas extraños de tiempo de solicitud de lo contrario.

¡Una solución fácil es clear_active_connections! en un after_filter en su controlador.

after_filter :close_custom_db_connection 

def close_custom_db_connection 
    MyModelWithACustomDBConnection.clear_active_connections! 
end 
+4

Los rieles usan el grupo de conexiones, debe evitar el uso excesivo del límite de conexión determinado. – Anatoly

12

que haber pasado por esto añadiendo esto a la parte superior de mis modelos usando la otra base de datos

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

en tu config/database.yml hacer algo como esto

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'] %> 

entonces en sus modelos puede hacer referencia a db2 con

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

Lo que has descrito en la pregunta es multitenancy (bases de datos idénticamente estructuradas con datos diferentes en cada una). El Apartment gem es ideal para esto.

Para la pregunta general sobre varias bases de datos en Rails: ActiveRecord admite varias bases de datos, pero Rails no proporciona una forma de administrarlas. Hace poco creé la gema Multiverse para solucionar esto.

Cuestiones relacionadas