SqlBulkCopyは、トランザクション内でテーブルへの他の書き込みを防止するときに挿入します。

asp.net c# sql sqlbulkcopy sql-server

質問

私のWebアプリケーションでは、パフォーマンスを向上させるために、多数のデータを一度に挿入することができます.SqlBulkCopyクラスを使用しています。 2つの異なるテーブルに挿入する1回の操作で複数回実行されます。ユーザーが操作を取り消した場合、または失敗した場合は、データをロールバックして、分離レベルのスナップショットを使用してトランザクション内のすべてをラップする必要があります。

Snapshotアイソレーションを使用すると、他のユーザーが同時にテーブルに書き込み/読み取りを行うことができると私は理解していました。ただし、1つのデータアップロードが発生している間は、親トランザクション全体が完了するまで、テーブルへの他の書き込みをブロックします。

この問題を示す簡単なコードをいくつか示します。私は多くの機能を除外していますが、アイデアは変わりません。私はいくつかのメモリコレクションを繰り返し、テーブルにバルクコピーし、それらをリタイアし、別のテーブルに一括コピーします。

using (var transaction = myDbContext.Database.BeginTransaction(
System.Data.IsolationLevel.Snapshot))
 {
   var myCollectionOfObjects;

   while(!GetData(ref myCollectionOfObjects))  
   {     

    SqlBulkCopy bulkCopy = new SqlBulkCopy(myCon, transaction);

    //Sets the columns + rows
    SetUp(bulkCopy);

    bulkCopy.WriteToServer();
    //After the bulkcopy operation is complete
    // we retrieve the rows inserted and do another bulk copy to a different table

    var recentlyAddedRows = GetRecentlyAddedRow();

    SqlBulkCopy otherTableBulkCopy = new SqlBulkCopy(myCon, transaction);


    SetUpBulkCopyForOtherTable(otherTableBulkCopy);

    otherTableBulkCopy.WriteToServer();         
     }
    transaction.Commit();
 }

したがって、あるユーザーが現在このトランザクションの内部にいる場合、ロールバックしていてもテーブルへの他のすべての書き込みトランザクションはブロックされ、同じ機能を実行しているか、テーブルへの書き込みを試みている他のユーザーはブロックされます。

これは予想された動作ですか、これを回避する方法はありますか?

編集

SQLに適用されているロックを見ると、bulkcopyクラスが原因で、排他ロック(X)がテーブルオブジェクトに設定されているように見えます。一度に1つずつ挿入する場合と同じようにインテントロックが適用されますテーブル(IX)に。まだ周りに道があるかどうかわからないが、これはロックのエスカレーションによるものだと思う。

表のインデックスの許可ページロックを変更し、一括コピーのバッチサイズを変更すると、いくつかのテストで完全にロックされてしまいましたが、それらは気になります。

人気のある回答

IsolationLevelは読み取りのみを指し、書き込みは指しません。クライアントのいずれかがデータを書き込んでいる場合、もう一方のクライアントはトランザクションの開始前と同じようにデータを読み取ることができますが、同時に書き込むことはできません。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ