使用连接池处理活动记录超时的正确方法是啥?

Posted

技术标签:

【中文标题】使用连接池处理活动记录超时的正确方法是啥?【英文标题】:what's the proper way to handle timeouts for active record with a connection pool?使用连接池处理活动记录超时的正确方法是什么? 【发布时间】:2011-06-22 08:49:00 【问题描述】:

我发现了一个奇怪的错误undefined method `run_callbacks' for nil:NilClass,并能够使用此示例代码重现它。

基本上问题是活动记录超时(默认为 5 秒)但抛出未定义的方法异常,这对我来说似乎是错误的。

但无论如何,处理这个问题的正确方法是什么?在我的真实代码中,我有一堆忙于实际工作的线程,但偶尔我会遇到这个错误。所以想象puts 是真正的代码。发生这种情况时,我希望现有线程继续工作。

threads = []
10.times do |n|

 threads <<  Thread.new 
    ActiveRecord::Base.connection_pool.with_connection do |conn|
      puts "#n #conn"
      res =  conn.execute("select sleep(6)", :async => true)
    end
  
end

# block and wait for all threads to finish
threads.each  |t| puts "joined" ; t.join 
rescue Exception => e
  puts  $!, $@
end

如果我按原样运行此代码,则会出现异常。如果我将睡眠时间减少到 4 秒,我不会。这是 6s sleep 的输出。

joined
0 #<ActiveRecord::ConnectionAdapters::mysql2Adapter:0xb73c6380>
1 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c5548>
2 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4fe4>
3 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4a80>
4 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c451c>
joined
joined
joined
joined
joined
undefined method `run_callbacks' for nil:NilClass
/usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:212:in `checkin'
sqltst.rb:31:in `join'
sqltst.rb:31
sqltst.rb:31:in `each'
sqltst.rb:31

【问题讨论】:

如果你尝试在线程内捕获异常,你会得到同样的错误吗? 如何处理它取决于您查询的性质。我假设由于它们在单独的线程中运行,因此每个线程中的查询在上下文中是相互隔离的。在这种情况下,我肯定会处理线程本身的错误。超时重试 3 次,然后设置“线程返回码”并退出线程。如果您正在进行更新,那么当然可以将它们打包到一个事务中 - ActiveRecord 支持这一点。 如果您只是想编写代码以继续运行,您是否尝试过在代码块末尾添加“rescue nil”? 【参考方案1】:

您应该在 database.yml 中设置 pool: 10。看来你已经达到极限了。

【讨论】:

【参考方案2】:

自从发布此问题以来,ActiveRecord 在这方面做了很多工作。这里有一些很好的解释:http://bibwild.wordpress.com/2012/03/15/activerecord-concurrency-currently-good-news-and-bad/

【讨论】:

以上是关于使用连接池处理活动记录超时的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring 和 DBCP 处理 JDBC 连接的正确方法是啥?

在MySQL,Grails 2应用程序更长时间不活动期间保持池连接活动(或将它们计时并获得新的连接)的正确方法

如何在 reactor-netty 中配置池连接空闲超时

手写数据库连接池实战

MySql连接空闲8小时自动断开的原因及连接池配置方法

超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。