2017-10-19 4 views
-1

並列ループ内のデータベース呼び出しを見たコードを見つけました。ですから、Parallelループは複数のスレッドで実行されるため、データベース呼び出しはスレッドセーフです。ここでC#並列ループ内のデータベース呼び出し

はあなたのレビューのための小さなコードです:

Parallel.ForEach(list, item => 
{ 
    //this function update the user status by connecting with database 
    _IUserRepository.UpdateUserStatus(item.UserId, item.status); 
}); 

は、ユーザステータスのupdationを待って、並列ループの各スレッドですか?

UserId, Status 
1,0 
1,1 
1,0 
1,1 
  • は何のid = 1を持つユーザの最終ステータスになります。私たちは以下のように、リスト内のレコードを持っている場合、どうなりますか

  • デッドロックや競合の可能性はありますか?

ありがとう!

+0

未知のコードのスレッドの安全性について話すことは不可能です。 *パフォーマンス*複数の接続が同じリソースで競合するため、おそらく多くの問題が発生します。パフォーマンス上の問題がある場合、問題はコード自体であり、並列化では改善されません。 –

+2

たとえば、実行するすべてが単一の行の更新である場合、各更新に費やされる時間のほぼ80%がネットワークトラフィックです。バッチ* 100の更新をまとめて実行するか、値をテーブル値のパラメータとして渡すと、パフォーマンスが約80倍向上します。さらに、SqlBulkCopyを使用して変更をステージングテーブルにプッシュし、サーバー上で単一のUPDATEを実行します。 SqlBulkCopyは最小限のログとロックを使用します。すべての行をログに記録するのではなく、ページ全体を記録します。ステージングテーブルでは、ロックの問題もありません。 –

+0

もっと世俗的な問題 - 'UserID'がインデックスの最初の列でない場合、すべてのUPDATEは完全なテーブルスキャンになります。それをインデックス化してパフォーマンスを向上させるには、 –

答えて

2

_IUserRepository.UpdateUserStatusがスレッドセーフで、ソースコードがないためにこのコードが「スレッドセーフ」かどうかはわかりません。スレッドセーフであると仮定すると、あなたの場合のユーザーの最終的なステータスはまだindetermindateです。UPDATEステートメントデータベースが最後にヒットし、指定されたユーザーの以前のすべての変更が上書きされます。デッドロックについては、私はここでデッドロックすることはできません。つまり、すでに同じユーザーに対して複数の更新を行っていて、そのようなリストでステータスが異なる場合は、あまり意味がありません。指定されたユーザーの1つのエントリのみがそのようなリストに存在する必要があります(したがって、ユーザーIDによってキーが付けられているDictionaryである必要があります)。

0

スレッドごとに並列ループが発生していますが、ユーザーステータスの更新を待っていますか?

私は答えが異なると思います。データベースのトランザクションレベルによって異なります。レベルが高いほど、DB内の同じレコードを更新するときにスレッドが互いに待つ機会が増えます。リストが異なるユーザーのリストである場合、私はそれが当てはまるはずではないと考えます。

id = 1のユーザーの最終ステータスはどうなりますか?

これは確かに予測できません。すべての実行のために異なる答えで終わることができます。しかし、私はこのコードがこのシナリオのために書かれたのではなく、異なるユーザーのリストがある場合について書かれていると思います。さもなければコードは意味をなさない。

デッドロックや競合状態はありますか?

デッドロックなし、競合状態はい、上記の例を考慮した場合のみです。しかし、再び言及したように、私はこのコードが異なるユーザーのリストに適用されると思います。

関連する問題