SqlBulkCopy.WriteToServer (DataTable) иногда не работает во время процесса перестроения индекса моей таблицы
Это можно легко смоделировать с помощью следующего способа:
- Создать таблицу с10 столбцов с кластеризованным индексом (первичный ключ) и 2 некластеризованных индекса
- Заполнение таблицы 500 000 фиктивных данных
- Создание программы для вставки 100 записей в таблицу (запустить еев цикле 50 раз)
Во время работы программы продолжайте выполнять команду перестроения индекса, пока программа не остановится:
ALTER INDEX [IX_11] ON [dbo] .TableA1 REBUILDWITH (SORT_IN_TEMPDB = OFF, ONLINE = ON)
ALTER INDEX [IX_12] ON [dbo] .TableA1 REBUILD WITH (SORT_IN_TEMPDB = OFF, ONLINE = ON)
Вы будетев состоянии видеть, что иногда нет ошибок (и число скопированных строк, возвращаемых SQLBulkCopy, составляет 50000), но в базе данных только 49000
Код:
SqlConnection conn = new SqlConnection(strConnection);
conn.Open();
using (SqlTransaction transaction = conn.BeginTransaction())
{
try
{
using (SqlBulkCopy bulkCopyItem = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction))
{
try
{
bulkCopyItem.BulkCopyTimeout = 300;
foreach (DataColumn col in DataTableABC.Columns)
{
bulkCopyItem.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
bulkCopyItem.BatchSize = 100;
bulkCopyItem.DestinationTableName = "dbo.TableA1";
bulkCopyItem.WriteToServer(DataTableABC); // prove await also can cause problem
transaction.Commit();
}
catch (Exception ex)
{
_logger.Error("Message=" + ex.Message + " ;" + TaskNo);
transaction.Rollback();
}
}
}
catch (Exception ex)
{
_logger.Error("Message=" + ex.Message + " ;" + TaskNo);
}
}
conn.Close();
Примечание:
- Сбой довольно часто с "исключением изменения схемы ...".Это нормально, мы можем повторить попытку при появлении ошибки.Проблема в том, что SQLBulkCopy не возвращает никаких ошибок, а данные не вставляются в БД
- Работает нормально, используя SqlBulkCopyOptions.UseInternalTransaction
- Работает нормально, если BatchSize <> 0 (так долго, как размер пакета)меньше, чем фактическое количество строк, он работает нормально)
Поскольку я хочу использовать существующую транзакцию и выполнять пакетную обработку (100 за раз, и BatchSize = 100), я не могу найти какие-либолучший способ решить это.Это происходит только во время запуска задания перестроения индекса
Есть идеи, как избежать этой проблемы?Спасибо