多个数据库连接

时间:2020-03-06 15:04:36  来源:igfitidea点击:

我正在尝试了解获得与数据库的连接的最佳方法。

目前,我有一个解析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个客户数据库(并且还在不断增长),因此我们将它们合并回少量的分片数据库中。