Ruby on rails Rails 4.2:如何动态更改线程使用的连接?
如何更改一个线程的连接?我想这样做:Ruby on rails Rails 4.2:如何动态更改线程使用的连接?,ruby-on-rails,ruby,multithreading,activerecord,database-connection,Ruby On Rails,Ruby,Multithreading,Activerecord,Database Connection,如何更改一个线程的连接?我想这样做: # 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 } 我希望这两个线
# 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使用一个连接来实现这一点。因此,我所有同时运行两个查询并争取时间的努力都失败了——Rails将我的请求缩减到一个单一的同步池中。我也尝试了以下方法,但尽管Rails创建了一个新连接,ActiveRecord(“用户”)却没有使用它:
# 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”,但也没有成功
有没有可能每个线程都有自己的连接?如何设置线程连接?好的,我知道了。但我必须对“检索连接”进行一些修改才能实现这一点。我把这个放在我的应用程序上。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:这满足了我的需要,但我想知道是否有一个本机方法来更改线程的连接。我的做法太难看了:/因此,如果你知道更好的方法,请分享。根据,你必须将应用程序代码包装在executor块中
试试这个(对于Rails版本:4):
假设您在config/database.yml
中的池大小值大于1,这应该可以工作
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 }