我在.NET 3.5中有一个自定义数据导入可执行文件,SqlBulkCopy基本上可以更快地插入大量数据。该应用程序基本上采用输入文件,按摩数据并批量上传到SQL Server 2000.它是由一个使用SQL 2008数据库环境构建它的顾问编写的。这种环境差异会导致这种情况吗? SQL 2000确实有bcp实用程序,这是BulkCopy所基于的。因此,当我们运行它时,它触发了死锁错误。
错误详细信息:事务(进程ID 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;
}
答案 0 :(得分:0)
我经常使用BCP,而且我从未见过将BatchSize设置为除典型值1000以外的任何其他情况的情况。
此字段无意表示代码中显示的整个行数,而是表示在复制期间要发送到服务器的可管理数据块,类似于IP数据包大小。
您可以尝试将此值更改为1000而不是整个表。
您可能还想查看SQL企业管理器或SQL Management Studio中的进程/锁定管理器窗格(取决于您的客户端工具版本),并查看进程在锁定方面的作用。
答案 1 :(得分:0)
这些插入是否同时进行?在具有聚簇索引的表上使用TABLOCK提示进行并发插入时,SqlBulkCopy存在已知问题。它会导致死锁。请参阅以下内容:
http://msdn.microsoft.com/en-us/library/ms186341(SQL.90).aspx
答案 2 :(得分:0)
多个活动结果集与插入无关 - 我甚至认为SQL Server 2000不支持它,因为它是稍后添加的。
SQL Server 2000没有像以后的版本那样复杂的锁升级 - 我希望你看到的就是这样。我假设顾问在目标表上没有BCP以外的工作负载,而您的应用程序在目标表上除了批量插入之外确实有活动。
我会考虑首先将批量插入到临时表中(因此不存在死锁的可能性),然后尽可能高效地在本机SQL SP中插入/更新查询(可能在许多小批量中)。
答案 3 :(得分:0)
我终于能够获得我们的生产数据库的本地副本(~50演出)来测试应用程序。事实证明,交易严重是一个环境问题。谢谢费拉斯。