デッドロックの原因となるSQLBulkCopy

c# deadlock sqlbulkcopy sql-server

質問

私は次のコードを持っています。実際にSQLBulkCopyを使ってデータを送り先に挿入します。このコードは、デッドロックのためにソースSQLサーバーで頻繁に失敗しています。私たちが一括コピーを実行している間、コピーされているテーブルが使用されている可能性があります(私はいくつかの挿入/選択が実行されていることを意味しました)。

それが問題を引き起こしているのか、「TABLOCK」ヒントに何があるのでしょうか?私の理解によると、TABLOCKは共有ロックのみを取得し、問題ではありません。

using (var reader = srcConnection.ExecuteReader($"select * from [{DatabaseName}].[{schemaName}].[{tableName}]"))
{
    const SqlBulkCopyOptions bulkCopyOptions = SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers |
                                               SqlBulkCopyOptions.KeepNulls | //Do not replace nulls with defaults in destination
                                               SqlBulkCopyOptions.KeepIdentity;
        //Use the identity values from source, do not generate identities in destination.

    using (var bcp = new SqlBulkCopy(dstConnection.ConnectionString, bulkCopyOptions))
    {
        const int threeMinutes = 60*3;

        bcp.BulkCopyTimeout = threeMinutes; //Timeout is for a single batch
        bcp.BatchSize = 5000;
        bcp.DestinationTableName = $"[{DestinationDatabaseName}].[{schemaName}].[{tableName}]";
        bcp.EnableStreaming = true;

        foreach (var col in table.Columns.Cast<Column>().Where(c => !c.Computed))
        {
            bcp.ColumnMappings.Add(col.Name, col.Name);
        }

        bcp.WriteToServer(reader);
    }
}

人気のある回答

一括挿入は、テーブルに行を挿入する必要があります。行を挿入するには、排他ロックが必要です。取得される正確なロックは、並行性モデルによって異なります。

TableLockオプションを指定すると、プロセスは排他テーブルロックを取得しようとします。プロセスが最初に共有テーブルロックを取得し、他のプロセスが行ロックを共有しており、両方のプロセスがロックを排他ロックにアップグレードしようとすると、デッドロックが発生する可能性があります。

デッドロックの詳細については、いくつかの方法があります。



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