1

RSpec を使用して並列トランザクションをテストする方法はありますか? 銀行口座の残高が減少または増加する前に、トランザクション内でロックする必要があると言っています。しかし、現在、RSpec オプションをオフにしているにもかかわらtransactional_fixturesず、2 つの別々のスレッドで 2 つの並列トランザクションを起動することはできません。なぜか両方ともぶら下がっています。指定されたアカウントがモデルである場合、この仕様はハングします:

it "should ensure operations are performed correctly" do
  @account = Account.create(:balance => 0)
  threads = []
  (0..1).each do |index|
    threads << Thread.new do
      Account.transaction do
        account = Account.find(@account.id, :lock => true)
        account.balance += 100
        sleep 0.5
        account.save!
      end
    end
  end
  threads.each{|t|t.join}
  @account.reload.balance.should == 200
end

トランザクションの能力を発揮しながらハングしないようにする方法はありますか?

4

2 に答える 2

1

スレッドでデータベースへの異なる接続を使用する必要があります。まず、メイン スレッドを切断し、次に各スレッドで再接続し、最後にメインで再接続します。次のようにします。

ActiveRecord::Base.connection.disconnect!
(0..1).each do |index|
  threads << Thread.new do
    ActiveRecord::Base.establish_connection
    # ...
  end
end
ActiveRecord::Base.establish_connection

この方法でのテストには他にも問題があります。同時実行が発生するポイントが保証されていません。ruby GIL も役に立ちません。スレッドの代わりにフォークを使用するか、fork_break gem: https://github.com/remen/fork_breakを使用する必要があります。

于 2013-12-23T12:18:38.200 に答える
0

同じリソースで並列の同時トランザクションを実行する正当な理由が思いつきません。あなたの例で正確に何を達成しようとしていますか?

コードでは同じインスタンスを使用しているため、デッドロックに陥っていることが予想されます。ここで何をしようとしているのか、もう一度考えてみてください。

于 2011-03-29T15:50:51.317 に答える