的ActiveRecord :: ConnectionTimeoutError

时间:2012-12-03 01:19:52

标签: ruby activerecord

我收到此错误:

'could not obtain a database connection within 5 seconds (waited 5.001017 seconds). The max pool size is currently 16; consider increasing it.'

首先我得到了这个错误,我将计数从5提升到16.但它仍然在发生,我是唯一一个测试数据库的人。当我是唯一的用户时,为什么会发生这种情况?

我不在轨道上。我正在使用:

ActiveRecord::Base.establish_connection ({
    :adapter => 'mysql2',
    :database => 'ck',
    :host => 'localhost',
    :username => 'root',
    :password => '',
    :pool => 16,
    })

并使用Sinatra。

由于

4 个答案:

答案 0 :(得分:12)

正如Frederick所指出的,您需要将已打开的ActiveRecord连接返回到连接池。

如果您在线程模式下使用Thin服务器,则需要将其添加到Sinatra应用程序中:

after do
  ActiveRecord::Base.connection.close
end

...而不是使用ConnectionManagement建议。原因是Thin将请求处理分为两个线程,而关闭ActiveRecord连接的线程与打开它的线程不同。由于ActiveRecord按线程ID跟踪连接,因此会混淆并且无法正确返回连接。

答案 1 :(得分:5)

听起来您在请求结束时没有返回到池的连接。如果没有,则每个使用db的请求将消耗1个连接,最终您将耗尽池并开始收到您描述的错误消息

Active Record提供了一个机架中间件来处理这个ActiveRecord::ConnectionAdapters::ConnectionManagement,它应该像中间件链中的早期一样处理事情,而不是任何访问活动记录的东西。

您也可以自己处理连接管理。 docs有更多细节,但有一种方法是将所有数据库访问都放在像这样的块中

ActiveRecord::Base.connection_pool.with_connection do
  ...
end

在块开始时检查连接并在之后检查它。

答案 2 :(得分:1)

最好使用ActiveRecord提供的middleware

use ActiveRecord::ConnectionAdapters::ConnectionManagement

答案 3 :(得分:0)

正如Frederick所指出的,您需要将已打开的ActiveRecord连接返回到连接池。

正如kuwerty建议的那样,当您使用Thin时,ConnectionManagement将不会返回到池的连接。我建议不要像kuwerty所说的那样关闭当前的连接,而是像这样返回到池的连接。

after do
  ActiveRecord::Base.clear_active_connections!
end

对于想要重现问题的人,请尝试this example

编辑:

我解释了为什么使用中间件ActiveRecord::Connectionadapters::ConnectionManagement不能在线程模式下使用Thin,你可以找到here