如何更改一个线程的连接?我想这样做:
# slow query process at background
Thread.new do
User.all { |user| user.update_attributes(some_field: (rand * 100).to_i) }
end
# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
我希望这两个线程(主要和我创建的一个)以异步方式运行,但我发现Rails使用一个连接来执行此操作。因此,我在同一时间运行2个查询并获得时间的所有努力都被破坏了--Rails在单个和同步池中逐渐减少了我的请求。我也试过了下面的内容,但是虽然Rails创建了一个新连接,但ActiveRecord(" User")并没有使用它:
# slow query process at background
Thread.new do
conn = ActiveRecord::Base.connection_pool.checkout()
User.all {|user| user.update_attributes(some_field: (rand * 100).to_i) }
ActiveRecord::Base.connection_pool.checkin(conn)
end
我曾试图设置" ActiveRecord :: Base.connection = conn"但也没有用。
每个线程都可以拥有自己的连接吗?如何设置线程连接?
答案 0 :(得分:0)
根据rails guide,您必须将应用程序代码包装在执行程序块中。
尝试一下(对于Rails版本:4):
Thread.new do
ActiveRecord::Base.connection_pool.with_connection do
User.all { |user| user.update_attributes(some_field: (rand * 100).to_i) }
end
end
# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
如果config/database.yml
中的池大小值大于1,这应该可以工作。
答案 1 :(得分:-1)
好的,我明白了。但是我不得不在“retrieve_connection”上做一点破解来实现这个目标。我把它放在我的application.rb上:
module ActiveRecord
module ConnectionAdapters
class ConnectionHandler
def retrieve_connection(klass) #:nodoc:
pool = retrieve_connection_pool(klass)
raise ConnectionNotEstablished, "No connection pool for #{klass}" unless pool
conn = Thread.current["connection"] || pool.connection
raise ConnectionNotEstablished, "No connection for #{klass} in connection pool" unless conn
conn
end
end
end
end
我只是将“conn = pool.connection”修改为“conn = Thread.current [”connection“] || pool.connection”。这允许我使用自定义线程变量定义连接。有了这个黑客,我的代码看起来像这样:
# slow query process at background
Thread.new do
Thread.current["connection"] = ActiveRecord::Base.connection_pool.checkout()
User.all {|user| user.update_attributes(some_field: (rand * 100).to_i) }
ActiveRecord::Base.connection_pool.checkin(Thread.current["connection"])
end
# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
甚至更好,为每次更新创建一个新的线程:
# slow query process at background
User.all do |user|
Thread.new do
Thread.current["connection"] = ActiveRecord::Base.connection_pool.checkout()
user.update_attributes(some_field: (rand * 100).to_i)
ActiveRecord::Base.connection_pool.checkin(Thread.current["connection"])
end
end
# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
PS: 这符合我的需求,但我想知道是否没有本地方法来更改线程的连接。我做的方式太难了:/所以,如果你知道更好的方法,请分享。