2011-02-24 4 views
5

단일 MySQL 서버에서 여러 개의 Rails 앱을 실행하고 있습니다. 모두 동일한 앱을 실행하며 모든 데이터베이스는 동일한 스키마를 갖지만 각 데이터베이스는 다른 고객에 속합니다.레일스에서 ​​여러 데이터베이스를 반복적으로 반복하는 방법

개념적으로

, 여기에 내가하고 싶은 작업은 다음과 같습니다

Customer.all.each do |customer| 
     connection.execute("use #{customer.database}") 
     customer.do_some_complex_stuff_with_multiple_models 
    end 

, 기본 모델 클래스는 A/R 연결에서 다른 데이터베이스 연결을 캐시이가 웹 요청을 실행하면, 때문에이 방식이 작동하지 않습니다 풀. 따라서 "use"문을 실행하는 연결은 모델이 사용하는 연결이 아닐 수도 있습니다.이 경우에는 잘못된 데이터베이스를 쿼리합니다.

ActiveRecord::Base.clear_active_connections! 
ActiveRecord::Base.establish_connection(each_customer_database_config) 

내가 믿고 :

내가 대신 "사용"문에, 레일 A/R 코드 (버전 3.0.3)를 통해 읽고, 루프에서 실행이 코드를 함께했다 연결 풀이 스레드 당 하나이므로 연결 풀이 망가져 웹 요청이있는 하나의 스레드에 대해서만 다시 연결되는 것처럼 보입니다. 그러나 연결이 어떤 방식 으로든 공유되지 않는다면, 동일한 코드에서 다른 활성 웹 요청으로 인해 코드가 혼란에 빠지 길 바라지 않을 것입니다.

실행중인 웹 앱에서이 작업을 수행하는 것이 안전합니까? 이것을 할 수있는 다른 방법이 있습니까?

답변

0

지금 ActiveRecord의 연결은 클래스 수준이 될 수 있습니다. 1.9 루비 스레드가 빨려서 스레드가 아니라 프로세스를 사용하기 때문에 스레드별로 스레드가 표시됩니다.하지만 오랫동안 사실이 아닐 수도 있습니다.

그러나 AR은 모델 당 하나의 스레드를 사용하기 때문에. 보유한 각 데이터베이스에 대해 다른 모의 모델을 만들 수 있습니다. 따라서 this question에 주어진 답을 사용하십시오.

코드는 다음과 유사합니다. (나는 그것을 테스트하지 않았다)

1

다른 요청에 대해 새로운 데이터베이스 연결을 전환하는 것은 매우 비싼 작업이다. AR은 제한된 연결 풀을 유지합니다.

나는 스키마 개념을 가지고있는 PostgreSQL으로 이동해야 할 것 같아. 이상적인 SQL 세계에서

이 데이터베이스 MYSQL에서

database --> schemas --> tables 

의 구조, 데이터베이스와 스키마는 같은 일이다. Postgres에는 다른 고객을 위해 테이블을 저장할 수있는 별도의 스키마가 있습니다. 설정을 통해 AR 연결을 변경하지 않고 즉시 스키마를 전환 할 수 있습니다.

ActiveRecord::Base.connection.set_schema_search_path("CUSTOMER's SCHEMA") 

개발 중 일부 해킹이 필요합니다.

+1

그냥 infelicitously, MySQL은 _does_ 지원 SQL 스키마를 명확하지만, 원래하고는 그들에게 전화를 SQL 키워드 "SCHEMA"는 버전 5.0.2 (2004 년 12 월) 이후로 인식됩니다. "USE foo"를 MySQL에 사용하는 것은 PostgreSQL 연결의'search_path'를 단일 네임 스페이스 "foo"로 설정하는 것과 유사합니다. – pilcrow

+0

물론입니다. MYSQL에서 "create database abc"대신 "create schema abc"라고 쓸 수도 있습니다. – Jagira

1

연결/연결 해제로 데이터베이스를 전환하는 속도가 매우 느리고 AR 연결 풀로 인해 내부 캐시가 작동하지 않습니다. ActiveRecord::Base.table_name_prefix = "customer_"을 사용하고 데이터베이스를 일정하게 유지하십시오.

0

왜 똑같은 데이터베이스와 테이블을 유지하지 않고 각 모델을 고객으로 소유하고 계십시오.그런 다음에 해당 고객의 모든 모델을 찾을 수 있습니다. "데이터베이스"

Customer.all.each do |customer| 
    customer.widgets 
    customer.wodgets 
    # etc 
end 
관련 문제