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”?

我相信这就是我们所说的“线程安全”或“竞争条件”,如果是这样,那么在每个子域使用一个数据库实现应用程序时,我们如何避免它呢?

在上述问题中,我的假设是同时执行两个请求是生产服务器的正常行为。或者有没有更好的方法。我对生产服务器没有太多经验,所以请指教。

4

2 回答 2

0

如果有两个模型和两个数据库,为什么不为每个数据库子类化 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

等等。显然,这仅在您拥有少量、固定数量的域/数据库对时才有效。但如果是这样 - 这意味着任何进入 DomainA 的人都将始终访问 Domain A 的数据库 = 没有竞争条件。

一般来说,我发现除非你正在破解内核代码,否则对竞争条件的解决方案不是线程安全......而是重新思考问题。

于 2010-09-06T14:13:11.873 回答
0

似乎您正在使用复制...但是我建议您观看 newrelic 的以下演员表,以更好地了解数据库扩展:

扩展您的数据库 - 第 1 部分

扩展您的数据库 - 第 2 部分

于 2009-12-17T11:20:36.527 回答