2009-12-01 45 views
49

Việc này có thể thực hiện được không? Trong một ứng dụng duy nhất, quản lý nhiều dự án với SQLite. Điều tôi muốn là có một cơ sở dữ liệu khác nhau cho từng dự án mà ứng dụng của tôi đang quản lý .. vì vậy nhiều bản sao của cơ sở dữ liệu có cấu trúc giống nhau, nhưng với dữ liệu khác nhau trong chúng. Tôi sẽ chọn bản sao nào để sử dụng dựa trên các thông số trên URI.Nhiều cơ sở dữ liệu trong Rails

Điều này được thực hiện cho 1. bảo mật .. Tôi là người mới trong loại lập trình này và tôi không muốn điều đó xảy ra vì một số lý do khi làm việc trên Dự án khác bị hỏng .. 2. dễ dàng sao lưu và lưu trữ các dự án cũ

+0

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

Trả lời

38

Rails theo mặc định không được thiết kế cho kiến ​​trúc đa cơ sở dữ liệu và, trong hầu hết các trường hợp, nó không có ý nghĩa gì cả. Nhưng có, bạn có thể sử dụng các cơ sở dữ liệu và kết nối khác nhau.

Dưới đây là một số tài liệu tham khảo:

+0

Không thể nói rõ hơn. Môi trường cũng giúp dễ dàng có một hệ thống db khác nhau giữa sản xuất và phát triển chẳng hạn. Tôi sẽ không khuyên bạn nên làm suy nghĩ này – marcgg

+0

Tôi có kế hoạch làm một sự lựa chọn tương tự vì tôi mong đợi một số bảng cơ sở dữ liệu để có hàng trăm triệu bản ghi.Việc tách cơ sở dữ liệu thành các cá thể riêng biệt trên mỗi máy khách sẽ cho phép tôi có một máy chủ ứng dụng đơn lẻ với nhiều máy chủ cơ sở dữ liệu. – Mika

+0

Hai liên kết cuối cùng của bạn không còn liên quan nữa. Và cái đầu tiên có thể trở nên lỗi thời với một phiên bản mới của đường ray. Vui lòng nội tuyến các phần liên quan của mã trong câu trả lời. – ndn

4

Bạn cũng nên kiểm tra dự án này được gọi là DB Charmer: http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/

DbCharmer là một plugin mạnh mẽ đơn giản cho ActiveRecord mà không một vài điều:

  1. Cho phép bạn dễ dàng quản lý kết nối (switch_connection_to phương pháp)
  2. Cho phép bạn chuyển đổi mô hình AR mô hình AR kết nối mặc định cho một máy chủ/cơ sở dữ liệu riêng biệt
  3. Cho phép bạn dễ dàng chọn nơi truy vấn của bạn nên đi (on_* phương pháp dành cho gia đình)
  4. Cho phép bạn tự động gửi truy vấn đọc đến nô lệ của bạn trong khi các bậc thầy sẽ xử lý tất cả các bản cập nhật.
  5. Thêm nhiều cơ sở dữ liệu di cư đến ActiveRecord
+1

Plugin đã bị tác giả giết chết kể từ ngày 2 tháng 1 năm 2015, không ai đã bước vào để duy trì nó. – Smar

26

Nếu bạn có thể kiểm soát và cấu hình mỗi Rails dụ, và bạn có thể đủ khả năng lãng phí tài nguyên vì trong số đó là ở chế độ chờ, tiết kiệm cho mình một số rắc rối và chỉ cần thay đổi database.yml để sửa đổi kết nối cơ sở dữ liệu được sử dụng trên mọi cá thể. Nếu bạn lo ngại về hiệu suất, cách tiếp cận này sẽ không cắt nó.

Đối với mô hình ràng buộc vào một bảng độc đáo duy nhất trên chỉ có một cơ sở dữ liệu bạn có thể gọi establish_connection bên trong mô hình:

establish_connection "database_name_#{RAILS_ENV}" 

Như đã trình bày ở đây: http://apidock.com/rails/ActiveRecord/Base/establish_connection/class

Bạn sẽ có một số mô hình sử dụng bảng từ một cơ sở dữ liệu và các mô hình khác sử dụng bảng từ cơ sở dữ liệu khác.

Nếu bạn có bảng giống hệt nhau, phổ biến trên các cơ sở dữ liệu khác nhau và được chia sẻ bởi một mô hình duy nhất, ActiveRecord sẽ không giúp bạn. Trở lại năm 2009 tôi yêu cầu điều này trên một dự án tôi đã làm việc trên, bằng cách sử dụng Rails 2.3.8. Tôi đã có một cơ sở dữ liệu cho mỗi khách hàng, và tôi đặt tên cho các cơ sở dữ liệu với các ID của họ.Vì vậy, tôi đã tạo ra một phương pháp để thay đổi các kết nối bên trong 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 

Và thêm phương pháp đó như là một before_filter cho tất cả các bộ điều khiển:

before_filter :change_database 

Vì vậy, đối với mỗi hành động của mỗi bộ điều khiển, khi params [ : company_id] được xác định và đặt, nó sẽ thay đổi cơ sở dữ liệu thành đúng.

Để xử lý di cư Tôi mở rộng ActiveRecord :: Migration, với một phương pháp mà sẽ tìm kiếm tất cả các khách hàng và lặp một khối với mỗi 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 

Lưu ý rằng bằng cách làm này, nó sẽ không thể cho bạn để thực hiện các truy vấn trong cùng một hành động từ hai cơ sở dữ liệu khác nhau. Bạn có thể gọi change_database một lần nữa nhưng sẽ khó chịu khi bạn thử sử dụng các phương thức thực hiện truy vấn, từ các đối tượng không còn được liên kết với cơ sở dữ liệu chính xác nữa. Ngoài ra, rõ ràng là bạn sẽ không thể tham gia các bảng thuộc về các cơ sở dữ liệu khác nhau.

Để xử lý đúng cách này, ActiveRecord sẽ được mở rộng đáng kể. Nên có một plugin ngay bây giờ để giúp bạn với vấn đề này. Một nghiên cứu nhanh chóng đã cho tôi một điều này:

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

tôi sẵn sàng thử nó. Hãy cho tôi biết những gì làm việc cho bạn.

2

Điều đáng chú ý là trong tất cả các giải pháp này bạn cần phải nhớ đóng các kết nối cơ sở dữ liệu tùy chỉnh. Bạn sẽ hết các kết nối và xem các vấn đề thời gian chờ yêu cầu lạ khác.

Một giải pháp dễ dàng là clear_active_connections! trong một after_filter trong bộ điều khiển của bạn.

after_filter :close_custom_db_connection 

def close_custom_db_connection 
    MyModelWithACustomDBConnection.clear_active_connections! 
end 
+4

Đường ray sử dụng hồ bơi kết nối, nên tránh sử dụng quá mức giới hạn kết nối nhất định. – Anatoly

12

Tôi lừa bóng qua này bằng cách thêm này để phía trên cùng của mô hình của tôi bằng cách sử dụng cơ sở dữ liệu khác

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

trong cấu hình của bạn/database.yml làm điều gì đó như thế này

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

sau đó trong các mô hình của mình, bạn có thể tham khảo db2 với

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

Những gì bạn đã mô tả trong câu hỏi là đa nhiệm (cơ sở dữ liệu có cấu trúc giống nhau với các dữ liệu khác nhau trong mỗi). Các Apartment gem là tuyệt vời cho việc này.

Đối với câu hỏi chung về nhiều cơ sở dữ liệu trong Rails: ActiveRecord hỗ trợ nhiều cơ sở dữ liệu, nhưng Rails không cung cấp cách quản lý chúng. Gần đây tôi đã tạo ra đá quý Multiverse để giải quyết vấn đề này.

Các vấn đề liên quan