多个数据库连接
我正在尝试了解获得与数据库的连接的最佳方法。
目前,我有一个解析URL的方法(根据URL的不同,应用程序必须连接到另一个数据库,例如customer1.example.com将连接到customer1数据库)并调用
ActiveRecord::Base.establish_connection(conn_string)
其中conn_string包含数据库的名称。
调用此方法(set_db)
before_filter :set_db
在我的应用程序控制器中,因此基本上对于我收到的每个请求,都将解析URL,然后应用程序会尝试建立一个connect_connection。
我想知道我是否可以在某个地方建立连接池....我们对此有何建议?让Singleton保持所有连接并返回正确的连接更好吗?
谢谢!
罗伯托
解决方案
我不是Ruby程序员,但总的来说,连接池是个好主意。我们可以使该连接池成为一个单例并分发/收回连接。池可以在恢复连接后检查是否一切仍然正常。
对于每个连接,我们应该具有不同的生命周期和所有权,因此两个线程不会同时使用一个连接。
临时表要小心,因为它们属于一个数据库会话。我们遇到了一个错误,即在高负载情况下我们遇到了奇怪的错误。最后,我们记得我们在应用程序中使用了临时表。在高负载情况下,数据库连接断开,并由连接对象自动重新生成,而应用程序代码不知道它(我们已经实现了重新连接,但是忘记了在这种情况下这是一个问题)。我们想要读取的临时表不见了。
数据库是否在同一服务器上?
我有一个应用程序,其中某些模型对象来自一个数据库,而其他模型对象则来自不同的数据库。我重写了table_name函数以指定数据库。如果它们是不同的服务器将不起作用,但将适用于同一服务器中的不同数据库。
class xx < ActiveRecord.base def self.table_name "otherdatabase.table" end
看起来数据库池可能正在兴起即将推出的Rails版本。
Edge Rails的新功能
首先是关于初始帖子上留下的评论:这与红宝石无关。它与导轨的设计有关。
话虽如此,我们可能会劫持ActiveRecord :: Base行为,以保持由键索引的连接的哈希(在情况下,键将是用户名),然后拦截Establishment_connection以检查池中是否已打开连接
这将需要我们重新打开ActiveRecord base,这会使更改取决于AR内部。
我不会讨论我们关于合并的问题。但是,我确信池化将大大改善性能。我也有一个安装,其中每个客户端都有它自己的数据库,并且代码库在它们之间共享。
可以在Apache Rewrite配置的Rails外部实现解析URL的方法,因为可以将多个主机映射到单个客户。另外,我使用客户"密钥"来访问Web服务器磁盘上的缓存文件。重写配置如下所示:
RewriteMap accounts prg:domain_mapper.rb RewriteMap lowercase int:tolower RewriteCond %{HTTP_HOST} ^(.*)$ RewriteCond ${accounts:${lowercase:%1}} ^(.+)$ RewriteRule . - [E=ACCOUNT:%1] RequestHeader set Customer-Key %{ACCOUNT}e
客户密钥将直接映射到将在before_filter方法中连接的数据库名称。
到目前为止,在Rails端切换数据库连接还不是性能问题。 MySQL配置存在问题,我们面临的问题是数据库太多,请求太多导致MySQL中打开的数据库太多。
我确定我们一直在考虑迁移问题。从<2000数据库模式开始,这并不是问题。现在有超过15,000个客户数据库(并且还在不断增长),因此我们将它们合并回少量的分片数据库中。