使用连接池处理活动记录超时的正确方法是啥?
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 连接的正确方法是啥?