我正在开发一个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
模式下,请求按此顺序进行并执行。
MyModel
与数据库“a”建立连接。MyModel
与数据库“b”建立连接。MyModel.find_*()
哪个数据库可以访问? “a”或“b”?我认为这就是我们所谓的“线程安全”或“竞争条件”,如果是这样,那么在每个子域使用一个数据库实现应用程序时,我们如何避免它呢?
在上面的问题中,我的假设是同时执行两个请求是生产服务器的正常行为。或者是否有更好的方法。我对生产服务器的经验不多,所以请提供建议。
答案 0 :(得分:0)
好像你正在使用复制...但是我确实建议你从newrelic观看以下演员,以便更好地了解数据库缩放:
答案 1 :(得分: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的人都将始终访问域A =没有竞争条件的数据库。
通常情况下,我发现除非您正在攻击内核代码,否则竞争条件的解决方案不是线程安全的......而是重新考虑问题。