SqlBulkCopy fügt ein, wenn innerhalb einer Transaktion andere Schreibvorgänge für eine Tabelle verhindert werden

asp.net c# sql sqlbulkcopy sql-server

Frage

In meiner Webanwendung können Benutzer viele Daten gleichzeitig einfügen. Um die Leistung zu verbessern, verwende ich die SqlBulkCopy-Klasse. Es wird mehrmals für eine einzelne Operation ausgeführt und in zwei verschiedene Tabellen eingefügt. Wenn der Benutzer den Vorgang abbricht oder es fehlschlägt, müssen die Daten zurückgesetzt werden, damit ich alles in eine Transaktion mit Isolationsstufe Snapshot einbinden kann.

Es war mein Verständnis, dass die Verwendung der Snapshot-Isolation anderen Benutzern erlauben würde, gleichzeitig in die Tabellen zu schreiben / zu lesen. Während eines Datenuploads werden jedoch alle anderen Schreibvorgänge in der Tabelle blockiert, bis die gesamte übergeordnete Transaktion abgeschlossen ist.

Hier ist ein vereinfachter Code, der das Problem zeigt. Ich schließe viele Funktionen aus, aber die Idee bleibt die gleiche. Ich iteriere über eine bestimmte Anzahl von In-Memory-Datensammlungen, kopiere sie in eine Tabelle, ziehe sie zurück und kopiere sie in eine andere Tabelle.

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();
 }

Wenn sich also ein Benutzer gerade in dieser Transaktion befindet, werden alle anderen Schreibtransaktionen für die Tabelle blockiert, so dass andere Benutzer, die die gleiche Funktion ausführen oder versuchen, in die Tabelle zu schreiben, blockiert werden.

Ist dies das erwartete Verhalten und gibt es eine Möglichkeit, dies zu umgehen?

Bearbeiten

Wenn man sich die in SQL angewendeten Sperren anschaut, dann scheint dies auf die Klasse bulkcopy zurückzuführen zu sein, die zu einer exklusiven Sperre (X) auf dem Tabellenobjekt führt, als ob man sie einzeln einfügen würde, wenn nur eine Absichtssperre angewendet wird auf dem Tisch (IX). Ich bin mir immer noch nicht sicher, ob es einen Weg gibt, aber ich nehme an, dass dies auf eine Eskalation zurückzuführen ist.

Das Ändern der Seitensperre zulassen für die Tabellenindexe und das Ändern der Stapelgrößen der Massenkopien haben in einigen meiner Tests die volle Sperre erreicht, sind aber temperamentvoll.

Beliebte Antwort

Der IsolationLevel bezieht sich nur auf Lesevorgänge und nicht auf Schreibvorgänge. Wenn einer Ihrer Kunden Daten schreibt, sollte der andere Client in der Lage sein, die Daten so zu lesen, wie sie vor dem Start der Transaktion waren, jedoch wird es nicht in der Lage sein, gleichzeitig zu schreiben.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum