我正在尝试在rails中实现多线程方法,以便我可以非常快速地创建/更新多个记录。
这是我的计划的大纲。
ActiveRecord::Base.transaction do
(1..10).each do |i|
arr[i] = Thread.new {
<some logic on obj>
...
...
obj.save!
}
end
arr.each {|t| t.join}
end
这会在我的日志上发出警告。
DEPRECATION WARNING: Database connections will not be closed automatically,
please close your database connection at the end of the thread by calling `close`
on your connection.
它给了我一个错误
could not obtain a database connection within 5 seconds (waited 5.059358 seconds).
The max pool size is currently 5; consider increasing it.
我试过了: - 更改database.yaml并增加poolize和timeout。 - 以下列方式修改现有代码。
ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
begin
ActiveRecord::Base.transaction do
(1..10).each do |i|
arr[i] = Thread.new {
<some logic on obj>
...
...
obj.save!
ActiveRecord::Base.connection.close
}
end
arr.each {|t| t.join}
end
ensure
ActiveRecord::Base.connection.close if ActiveRecord::Base.connection
ActiveRecord::Base.clear_active_connections!
end
我仍然收到相同的警告和错误。 我显然在这里错过了这个概念。我该如何处理?
答案 0 :(得分:22)
要防止多线程中的连接泄漏,您必须手动管理连接。你可以尝试:
Thread.new do
ActiveRecord::Base.connection_pool.with_connection do
# Do whatever
end
end
ActiveRecord::Base.connection_pool.with_connection
的一个问题是它总是准备连接,即使内部的代码不需要它。
我们可以使用ActiveRecord::Base.connection_pool.release_connection
:
Thread.new do
begin
# Do whatever
ensure
ActiveRecord::Base.connection_pool.release_connection
end
end
答案 1 :(得分:0)
如果要在N个线程中运行,请确保池中有N个连接
# ActiveRecord::Base.connection_config
# # => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}
否则您将能够从the pool获取连接。