1

各サブドメインに個別のデータベースがあるRailsアプリケーションを開発しています。そして、私はこのようなことをしています。

#app/controller/application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :select_database

  private
  def select_database
    MyModel.use_database(request.subdomains.first)
  end
end

#app/model/my_model.rb
class MyModel < ActiveRecord::Base

  def self.use_database path
    establish_connection :adapter => 'sqlite3', :database =>
      File.join(RAILS_ROOT, "db", "sqlite3", path)
  end
end

これで、productionモードでは、要求がこの順序で来て実行されます。

  1. リクエスト「A」はサブドメインa.example.netMyModelに送信され、データベース「a」との接続を確立します。
  2. ここで、別のリクエスト「B」がサブドメインb.example.netMyModelに送信され、データベース「b」との接続を確立します。
  3. ここで、リクエスト「A」がどのデータベースにアクセスしようとした場合、MyModel.find_*()どのデータベースにアクセスしますか?「a」または「b」?

これが「スレッドセーフ」または「競合状態」と呼ばれるものだと思います。そうであれば、サブドメインごとに1つのデータベースを使用してアプリケーションを実装するときに、どうすればそれを回避できますか?

上記の質問では、2つのリクエストを同時に実行することは、運用サーバーの通常の動作であると想定しています。または、より良いアプローチがありますか。本番サーバーの経験はあまりないので、アドバイスをお願いします。

4

2 に答える 2

0

レプリケーションを使用しているようです...ただし、DBスケーリングについてより良いアイデアを得るために、newrelicからの次のキャストを視聴することをお勧めします。

データベースのスケーリング-パート1

データベースのスケーリング-パート2

于 2009-12-17T11:20:36.527 に答える
0

2 つのモデルと 2 つのデータベースがある場合、データベースごとに MyModel をサブクラス化しませんか?

class MyModelDomainA < MyModel
  DBA_PATH = "first/db/path"
  def self.use_database
    establish_connection :adapter => 'sqlite3', :database => File.join(RAILS_ROOT, "db", "sqlite3", DBA_PATH)
  end
end
# then in controller:
def select_database
  # or whatever string-manipulation you need to do... 
  # even have a lookup hash to get the correct model?
  model_klass = "MyModel#{request.subdomains.first.capitalize}"
  model_klass.constantize.use_database
end

など。明らかに、これは、ドメイン/データベースのペアが固定された少数の場合にのみ機能します。しかし、そうであれば、ドメイン A に入ってくる人は常にドメイン A のデータベースにアクセスすることを意味します = 競合状態はありません。

一般的に、カーネルコードをハッキングしていない限り、競合状態の解決策はスレッドセーフではなく、問題を再考することだと思います。

于 2010-09-06T14:13:11.873 に答える