我有一个C#应用程序正在使用存储过程将数据插入到SQL Server(2008)表中。我正在使用多线程来做到这一点。存储过程从线程内被调用。 现在我的存储过程在插入数据时使用“tablock”。 执行此代码时,出现以下错误: “事务(进程ID)与另一个进程在锁定资源上死锁,并被选为死锁受害者,重新运行事务。事务(进程ID)在另一进程的锁资源上死锁,并被选为死锁牺牲品。重新运行
任何人都可以请帮助我解决这个问题吗?
我有一个C#应用程序正在使用存储过程将数据插入到SQL Server(2008)表中。我正在使用多线程来做到这一点。存储过程从线程内被调用。 现在我的存储过程在插入数据时使用“tablock”。 执行此代码时,出现以下错误: “事务(进程ID)与另一个进程在锁定资源上死锁,并被选为死锁受害者,重新运行事务。事务(进程ID)在另一进程的锁资源上死锁,并被选为死锁牺牲品。重新运行
任何人都可以请帮助我解决这个问题吗?
这发生在两个Sql Server进程正在访问相同的资源时,但顺序不同。因此,他们最终都在等待另一个进程,这是一个僵局。
有许多的方法来防止它,其中包括:
with (nolock)
锁定提示进行查询。例如,如果Proc1锁定table1,然后锁定table2,但Proc2锁定table2,然后锁定table1,则会出现问题。您可以重写任一proc以相同的顺序锁定以避免此问题。
您可以封装在一个try catch块查询,并捕获错误号(与锁)
然后你就可以自动重试,达到一定的数量。所以你会做类似以下的事情;
DECLARE @RetryNo Int = 1
,@RetryMaxNo Int = 5;
WHILE @RetryNo < @RetryMaxNo
BEGIN
BEGIN TRY
-- put your query that generates locks here....
SELECT @RetryNo = @RetryMaxNo;
END TRY
BEGIN CATCH
IF ERROR_NUMBER() IN (1204, 1205, 1222)
BEGIN
SET @RetryNo += 1;
-- it will wait for 10 seconds to do another attempt
WAITFOR DELAY '00:00:10';
END
ELSE
THROW;
END CATCH
END
您还可以使用表格提示,如UPDLOCK。
你可以从锁对象使用SQL Server上
static object _lock = new object();
public static void _main()
{
lock (_lock)
{
_bulkcopy(myData);
}
}
public static void _bulkcopy(DataTable dt)
{
try
{
using (var connection = new SqlConnection(ConfigurationSettings.AppSettings.Get("DBConnection")))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
{
bulkCopy.BatchSize = 100;
bulkCopy.DestinationTableName = "dbo.MyTable";
try
{
bulkCopy.WriteToServer(dt);
}
catch (Exception)
{
transaction.Rollback();
connection.Close();
}
}
transaction.Commit();
}
}
catch { }
}
死锁,你必须在你的问题中添加存储过程的代码,以及你的数据库架构的相关部分。 – ken2k 2012-02-09 14:07:58