1

我嘗試瞭解在生產中的問題,所以我扔在開發的控制器操作中這個片段進行測試:爲什麼不能同時運行這些線程化的ActiveRecord查詢?

start = Time.now 
num_threads = 6 
results = Queue.new 
saved_results = [] 
threads = [] 
connections = [] 
semaphore = Mutex.new 

# start threads 
(1..num_threads).each do |i| 
    threads << Thread.new do 
    #semaphore.synchronize { connections << ActiveRecord::Base.connection } # for cleanup? 

    #ActiveRecord::Base.connection.execute("select sleep(1.6);") # runs sequentially 
    sleep(1.6)             # runs concurrently 
    result = User.find_by_id(i) 
    results << [i, result] 
    end 
end 

# end option 1 - let everyone finish 
threads.each(&:join) 

# end option 2 - simulate early exit condition 
#while saved_results.count < 3 do saved_results << results.pop end 
#threads.each(&:exit) 

# cleanup/close open connections? 
#connections.select(&:active?).each(&:disconnect!) 

elapsed = Time.now - start 
render :text => [ elapsed.to_s, saved_results.size, results.size ].join(", ") 

sleep(1.6)執行大約1.6秒,符合市場預期。

但是,ActiveRecord select sleep(1.6);需要6 * 1.6 = 9.6秒,儘管mysql控制檯show processlist;顯示爲每個線程*打開獨立連接。

發生了什麼事?爲什麼ActiveRecord查詢不能同時運行?我也在生產控制檯中體驗過這一點。

我確實有config.threadsafe!設置在config/environment.rb。如果有關係,我使用Rails 2.3。

*這些連接必須手動關閉?生產總是有很多無所事事的開放式連接,導致Mysql::Error: Too many connections。我可能會提出這個問題作爲另一個問題。

回答

0

一些言論:

  • 軌2.3本身AFAIK本身不是真正線程安全的,因爲軌道3.X它。但對於這種情況,我認爲並不重要。
  • 你應該至少使用ruby 1.9。 1.8中的「綠色線程」並不理想。雖然踩紅寶石1.9仍然不是最佳的,但它更好。對於真正的線程,你應該檢查出jruby或rubinius(沒有GIL)。
  • 你應該使用mysql2寶石。 mysql gem在等待來自數據庫的響應時保持GIL。
+0

剛剛用mysql2進行了測試,並且此示例正常工作。我最近遇到了另一個與半相關的問題:http://stackoverflow.com/questions/26001994和使用mysql2在那裏沒有幫助 – Kache

相關問題