У меня есть следующий код, который фактически вставляет данные в пункт назначения, используя SQLBulkCopy. Этот код часто не работает на исходном SQL-сервере из-за взаимоблокировки. FYI таблица, которая копируется, может быть использована (я имел в виду, что некоторые вставки / выборки будут выполняться), пока мы выполняем массовую копию.
Это вызвало проблему или подсказку «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
, ваш процесс попытается получить эксклюзивную блокировку таблицы. Это может привести к взаимоблокировкам, если ваш процесс сначала получит общую блокировку таблицы, другой процесс имеет разделенные блокировки строк, и оба процесса пытаются обновить свои блокировки до исключительных блокировок.
Существует несколько способов получить дополнительную информацию о взаимоблокировках: