SqlBulkCopy.WriteToServer erfüllt BulkCopyTimeout nicht zuverlässig

.net c# sqlbulkcopy sql-server-2008 timeout

Frage

Ich muss sequenzielle Timeout-Ausnahmen von SqlBulkCopy zählen. Um dies zu testen, verwende ich eine externe App, um eine Transaktion zu starten und die Zieltabelle zu sperren.

Nur beim ersten Aufruf gibt SqlBulkCopy eine erwartete Zeitüberschreitungsausnahme aus. Wir haben versucht, eine externe Verbindung und Transaktion sowie eine Verbindungszeichenfolge und eine interne Transaktion zu verwenden. Bei der externen Verbindung und Transaktion hat die infinite wait nie die Verbindung geöffnet oder die Transaktion begonnen oder ausgeführt, sondern immer bei .WriteToServer() .

Gibt es dafür einen Ansatz, bei dem SqlBulkCopy.WriteToServer() zuverlässig eine Timeout-Ausnahme .BulkCopyTimeout , wenn das Limit von .BulkCopyTimeout ist?

public void BulkCopy(string connectionString, DataTable table, int bulkTimeout)
{
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
        connectionString, 
        SqlBulkCopyOptions.UseInternalTransaction))
    {
    bulkCopy.BulkCopyTimeout = bulkTimeout;//e.g. 120 sec.
    //... fill with data, map columns...
    bulkCopy.WriteToServer(table);
    // ^^^^ waits indefinitely, doesn't throw until *after*
    //      the lock is released.
    }
}

Ich bevorzuge es, Ausnahmen zuzulassen, anstatt sie im Rahmen des using Blocks zu behandeln, aber ich kann immer wieder neu starten. Vielen Dank für einen Einblick.

Update 1:

Immer noch keine Lösung. Interessantes Verhalten jedoch entdeckt - ein normaler SqlCommand wird eine TimeoutException wie erwartet während derselben Sperre auslösen, die die SqlBulkCopy.WriteToServer-Methode auf unbestimmte Zeit blockiert.

Hier sind die Ansätze, die wir versucht haben - und die fehlgeschlagen sind - SqlBulkCopy.WriteToServer zu veranlassen, Zeitüberschreitungen zu verursachen, wenn sie erwartet werden:

  • MARS (Mehrere aktive Ergebnismengen) ein / aus
  • Tabellensperre vs. aus
  • Ziel als Heap-Tabelle im Vergleich zur indizierten Tabelle
  • Längere / kürzere BulkTimeout-Werte (10 Sekunden bis 5 Minuten)
  • Interne vs externe Transaktion

Als Workaround wechsle ich vorerst zwischen a) dem Aufruf von WriteToServer in einen asynchronen Wrapper, damit ich es selbst einstellen kann und b) WriteToServer nur einmal aufrufen; Warten Sie nach Timeouts, bis ein regulärer SqlCommand erfolgreich ausgeführt wurde, bevor Sie WriteToServer erneut versuchen. Mit diesen Ansätzen bin ich zumindest in der Lage, den Ausführungsfluss zu kontrollieren.

Akzeptierte Antwort

Haben Sie versucht, die Option SqlBulkOptions.TableLock an SqlBulkCopy zu übergeben? Diese Option (Zitat) bedeutet, dass:

Erhalten Sie eine Massenaktualisierungssperre für die Dauer der Massenkopieroperation.

Wenn es also eine andere Verarbeitung gibt, die die Tabelle sperrt, würde dies verhindern, dass die Sperre gewonnen wird, und theoretisch eine zuverlässige Zeitüberschreitung.

Aktualisieren:
Ich habe mein eigenes Testgeschirr aufgebaut und kann nicht reproduzieren. Um die Tabelle zu sperren, habe ich eine Transaktion in SSMS mit SELECT * FROM TargetTable WITH (HOLDLOCK) . Ich habe die gleiche BulkCopy-Methode verwendet, die Sie in die Frage einbezogen haben, indem Sie interne Transaktionen mit einem Zeitlimit für das Massenladen von 30 Sekunden verwenden. Jeder Versuch, die Massenkopie durchzuführen, wird nach 30 Sekunden wie erwartet abgebrochen. Es ist dann erfolgreich, wenn ich die SSMS-Transaktion zurücksetze.

Ich verwendete SQL Server 2008 Express, .NET 3.5.

Es ist nicht so wie nach dem ersten Versuch, das Bulk-Load-Timeout wird nicht korrekt übergeben? dh es wird nicht irgendwie auf "unbestimmt" gesetzt.

Update 2:
Auch eingeschaltet mehrere Active Result Sets unterstützt in der Verbindungszeichenfolge, immer noch für mich jedes Mal Zeitüberschreitung.


Beliebte Antwort

Ich hatte dieses Problem später und für die Lösung dieses Problems setzte BulkCopyTimeout auf Null.

bulkCopy.BulkCopyTimeout = 0;


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