SqlBulkCopy вызывает тупик на SQL Server 2000 - PullRequest
1 голос
/ 13 мая 2010

У меня есть настраиваемый исполняемый файл импорта данных в .NET 3.5, который SqlBulkCopy позволяет в основном быстрее вставлять большие объемы данных. Приложение в основном берет входной файл, массирует данные и массово загружает их в SQL Server 2000. Он был написан консультантом, который создавал его в среде базы данных SQL 2008. Будет ли эта разница env причиной этого? В SQL 2000 есть утилита bcp, на которой базируется BulkCopy. Итак, когда мы запустили это, это вызвало ошибку тупика.

Сведения об ошибке: Транзакция (идентификатор процесса 58) была заблокирована для ресурсов блокировки с другим процессом и была выбрана в качестве жертвы тупика. Перезапустите транзакцию.

Я пробовал множество способов решить эту проблему. как временная установка переменной строки подключения MultipleActiveResultSets = true, которая не была идеальной, но все равно выдает ошибку взаимоблокировки. Я также удостоверился, что это не было проблемой времени ожидания соединения.

вот функция. Любой совет?

/// <summary>
    /// Bulks the insert.
    /// </summary>
    public void BulkInsert(string destinationTableName, DataTable dataTable)
    {
        SqlBulkCopy bulkCopy;

        if (this.Transaction != null)
        {
            bulkCopy = new SqlBulkCopy
                (
                    this.Connection,
                    SqlBulkCopyOptions.TableLock,
                    this.Transaction
                );
        }
        else
        {
            bulkCopy = new SqlBulkCopy
                (
                    this.Connection.ConnectionString,
                    SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.UseInternalTransaction
                );
        }

        bulkCopy.ColumnMappings.Add("FeeScheduleID", "FeeScheduleID");
        bulkCopy.ColumnMappings.Add("ProcedureID", "ProcedureID");
        bulkCopy.ColumnMappings.Add("AltCode", "AltCode");
        bulkCopy.ColumnMappings.Add("AltDescription", "AltDescription");
        bulkCopy.ColumnMappings.Add("Fee", "Fee");
        bulkCopy.ColumnMappings.Add("Discount", "Discount");
        bulkCopy.ColumnMappings.Add("Comment", "Comment");
        bulkCopy.ColumnMappings.Add("Description", "Description");


        bulkCopy.BatchSize = dataTable.Rows.Count;
        bulkCopy.DestinationTableName = destinationTableName;
        bulkCopy.WriteToServer(dataTable);

        bulkCopy = null;
    }

Ответы [ 4 ]

0 голосов
/ 13 мая 2010

Мне наконец удалось получить локальную копию нашей производственной базы данных (~ 50 гигабайт) для тестирования приложения. Оказывается, заключение сделки было сугубо экологической проблемой. Спасибо, ребята.

0 голосов
/ 13 мая 2010

Эти вставки выполняются одновременно? Существует известная проблема с SqlBulkCopy при выполнении одновременных вставок с подсказкой TABLOCK в таблицу с кластерными индексами. Это приводит к тупику. Смотрите следующее:

http://msdn.microsoft.com/en-us/library/ms186341(SQL.90).aspx

0 голосов
/ 13 мая 2010

Несколько активных результирующих наборов не имеют значения для вставок - я даже не думаю, что SQL Server 2000 поддерживает его, поскольку он был добавлен позже.

SQL Server 2000 не имеет такой сложной эскалации блокировки, как в более поздних версиях - я ожидаю, что это то, что вы видите. Я предполагаю, что у консультанта нет рабочей нагрузки, кроме BCP, в таблице назначения, в то время как у вашего приложения есть активность в таблице назначения, отличная от массовой вставки.

Я хотел бы рассмотреть вопрос о том, чтобы сначала выполнить массовую вставку в промежуточную таблицу (таким образом, нет никаких шансов на возникновение взаимоблокировок), а затем максимально эффективный запрос на вставку / обновление (возможно, во многих небольших пакетах) в нативном SQL SP.

0 голосов
/ 13 мая 2010

Я использую BCP довольно регулярно, и я никогда не видел случая, чтобы для BatchSize было установлено значение, отличное от типичного значения 1000.

Это поле не предназначено для представления всего количества строк, как показано в вашем коде, но для представления управляемых фрагментов данных, отправляемых на сервер во время копирования, что-то вроде размера IP-пакета.

Вы можете попробовать изменить это значение на 1000 вместо всей таблицы.

Возможно, вы также захотите взглянуть на панели диспетчера процессов / блокировок в SQL Enterprise Manager или SQL Management Studio (в зависимости от версии клиентского инструмента) и посмотреть, что процесс делает с точки зрения блокировок.

...