use*_*146 5 ruby multithreading ruby-on-rails thread-safety
我正在使用 Rails 3 和 Ruby 1.9。
我在各种 Rails 测试(和控制台)中运行 2 种方法。方法被调用index_cases,index_new_cases方法体如下所示。该index_new_cases方法的内容可能不相关(我正在使用 Sunspot gem 索引 ModelCase 信息),但为了完整性我将其保留在那里。
我有 3 case_numbers。每个case_number匹配ModelCase数据库中的一个(即数据库中有 3ModelCase条记录)。
当我使用这 3 个case_numbers对index_cases方法运行测试时,该index_new_cases方法不会使用该ModelCase.where…方法检索任何案例。但是,如果我删除方法中的“线程”调用index_cases,该index_new_cases函数现在会检索所有 3 个案例并正确索引它们。
谁能向我解释为什么我的线程找不到数据库记录?我的线程实现是错误的吗?谢谢!
def index_cases(case_numbers)
threads = []
case_numbers.each_slice(500) do |slice_of_case_numbers|
threads << Thread.new(slice_of_case_numbers) do |a_slice|
index_new_cases(a_slice)
end
end
threads.each {|thr| thr.join}
end
def index_new_cases(case_numbers)
cs = ModelCase.where(case_number: case_numbers).includes(:child_tables)
puts cs.size # prints 0 with threading and 3 without threading
Sunspot.index(cs)
Sunspot.commit
end
Run Code Online (Sandbox Code Playgroud)
此方法(无线程)可以正常工作以查找和索引我的数据库记录
def index_cases(case_numbers)
#threads = []
case_numbers.each_slice(500) do |slice_of_case_numbers|
#threads << Thread.new(slice_of_case_numbers) do |a_slice|
index_new_cases(slice_of_case_numbers)
#end
end
#threads.each {|thr| thr.join}
end
Run Code Online (Sandbox Code Playgroud)
我有一个非常相似的问题,尽管只是在测试中。
问题在于测试用例中使用的事务(当事务固定装置打开时) - 只要事务未提交,其他连接就看不到数据的更改。
请参阅http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
因此,在操作完成之前,在您的连接之外不会看到对数据库的更改。
线程应该有一个到数据库的新连接。并且由于在使用事务性fixtures时,整个测试运行都包含在一个事务中,除了它们自己创建的内容之外,线程中的任何内容都不会被线程看到。
您可以关闭事务,幸运的是也可以用于单个测试:http : //ar.rubyonrails.org/classes/Fixtures.html