Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby中,是否可以跨线程共享数据库连接?_Ruby_Multithreading_Heroku - Fatal编程技术网

在Ruby中,是否可以跨线程共享数据库连接?

在Ruby中,是否可以跨线程共享数据库连接?,ruby,multithreading,heroku,Ruby,Multithreading,Heroku,我有一个小的ruby脚本,它可以输出80000条左右的记录。 每个记录涉及的处理器和内存负载都比蓝精灵球要小,但遍历所有记录仍需要大约8分钟 我本想使用线程,但当我尝试时,我的数据库连接就用完了。当然是在我尝试连接200次的时候,我真的可以更好地限制它。。但是,当我把这段代码推到Heroku(我有20个连接供所有工作人员共享)时,我不想因为这个进程升级而有机会阻塞其他进程 我曾考虑过重构代码,使之与所有SQL结合在一起,但这会让人感觉非常混乱 所以我想知道让线程共享连接有什么诀窍吗?考虑到我不希

我有一个小的ruby脚本,它可以输出80000条左右的记录。
每个记录涉及的处理器和内存负载都比蓝精灵球要小,但遍历所有记录仍需要大约8分钟

我本想使用线程,但当我尝试时,我的数据库连接就用完了。当然是在我尝试连接200次的时候,我真的可以更好地限制它。。但是,当我把这段代码推到Heroku(我有20个连接供所有工作人员共享)时,我不想因为这个进程升级而有机会阻塞其他进程

我曾考虑过重构代码,使之与所有SQL结合在一起,但这会让人感觉非常混乱

所以我想知道让线程共享连接有什么诀窍吗?考虑到我不希望连接变量在处理过程中发生变化,我实际上有点惊讶于线程叉需要创建一个新的DB连接

任何帮助都会非常酷(就像我一样)。。谢谢


超级精心设计的示例
下面是一个100%人为的例子。它确实显示问题。
我在一个非常简单的线程中使用ActiveRecord。似乎每个线程都在创建自己与数据库的连接。我的假设基于下面的警告信息

START_TIME = Time.now

require 'rubygems'
require 'erb'
require "active_record"

@environment = 'development'
@dbconfig = YAML.load(ERB.new(File.read('config/database.yml')).result)
ActiveRecord::Base.establish_connection @dbconfig[@environment]

class Product < ActiveRecord::Base; end

ids = Product.pluck(:id)
p "after pluck #{Time.now.to_f - START_TIME.to_f}"

threads = [];
ids.each do |id|
  threads << Thread.new {Product.where(:id => id).update_all(:product_status_id => 99); }
  if(threads.size > 4)
    threads.each(&:join)
    threads = [] 
    p "after thread join #{Time.now.to_f - START_TIME.to_f}"
  end
end

p "#{Time.now.to_f - START_TIME.to_f}"
请参阅此gem并回答,您可能需要一个连接池:

另一个选项是在EM.defer块中使用和运行任务,使DB访问以非阻塞方式发生在回调块中(在reactor中)

或者,也是一个更健壮的解决方案,选择一个轻量级的后台处理队列,如beanstalkd,请参阅以获取更多选项-这将是我的主要建议

编辑

此外,您可能没有200个内核,因此创建200多个并行线程和db连接并不会真正加快进程(实际上会减慢进程),请查看是否可以找到一种方法将问题划分为多个集合,这些集合等于您的内核数加1,并以这种方式解决问题


这可能是解决您的问题的最简单的解决方案

我曾考虑过重构代码
-我怀疑您实际上需要-80000 DB访问,正如您所暗示的,无论您做什么,访问速度都会很慢。您能展示一些代码吗?如果您使用的是ActiveRecord,那么它已经被共享了。慢速是关于透视的。:)如果我没有建立一个可以处理几百万的系统,8分钟8万就可以了。可悲的是,我觉得代码没有什么特别之处。只是一个连接和更新记录的小脚本。感谢连接池链接,这可能就是问题所在。我的300行ruby应用程序已经在一个延迟的工作中运行,这就是为什么我一直在寻找一些东西。有250兆的内存和3兆的内存是很糟糕的,但同时有10分钟的时间完成一项工作,需要8兆(或更多)。我想用速度换取ram,而“核心+1”线程似乎是实现这一点的一种方法。在你回答之前,我甚至不能有两个线程,因为连接是我的极限。再次感谢!我尝试了第二个链接,每次尝试在线程中连接时,我的简单小应用程序都会崩溃。事件机会触发到DB的不同连接:(EM.defer使用线程池执行其代码(默认值为10线程iirc)这意味着不会有超过100%的线程连接,并且如果系统有适当的线程数,您的cpu仍应固定在100%。EM擅长的另一件事是最大限度地使用您的cpu,这意味着如果您确保所有IO调用都无阻塞,您的应用程序将不会等待db响应和o这意味着如果你有x个核,你可以设置x个EM反应器,并且假设你的反应器写得很好,你应该能够从你的系统中挤出最后一点处理能力。
"after pluck 0.6663269996643066"
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.  For example: ActiveRecord::Base.connection.close
. (called from mon_synchronize at /Users/davidrawk/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/monitor.rb:211)
.....
"after thread join 5.7263710498809814"   #THIS HAPPENS AFTER THE FIRST JOIN.
.....
"after thread join 10.743254899978638"   #THIS HAPPENS AFTER THE SECOND JOIN