我有一个 C# 应用程序,它使用存储过程将数据插入到 SQL Server (2008) 表中。我正在使用多线程来执行此操作。正在从线程内部调用存储过程。 现在我的存储过程在插入数据时使用“tablock”。 执行此代码时出现以下错误: “事务(进程 ID)在锁定资源上与另一个进程发生死锁,并已被选为死锁牺牲品。重新运行事务。”
任何人都可以帮我解决这个问题吗?
当两个 Sql Server 进程以不同的顺序访问相同的资源时,就会发生这种情况。因此,他们最终都在等待另一个进程,这是一个死锁。
有多种方法可以预防,包括:
with (nolock)
锁定提示进行查询。例如如果 Proc1 锁定 table1 然后锁定 table2,但 Proc2 锁定 table2 然后锁定 table1,就会出现问题。您可以重写任一过程以按相同的顺序获取锁以避免此问题。
您可以将查询封装在一个 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。
确定要更新或插入的字段,该字段具有非聚集索引。如果不可用,您可以先在此表上创建此字段的非聚集索引,然后在创建后按照以下步骤操作。
右键单击表并选择属性。
在属性的右侧面板中选择选项。
在锁定选项卡中,允许页面锁定设为“假”,允许行锁定必须为“真”,然后按确定。
我也有这个问题,所以我在所有加入我的存储过程后使用了
WITH (NOLOCK)
,所以它有效,我可以解决我的问题。
只是为了其他人的利益需要在这里更新,对我来说这是一个奇怪的错误消息,花了很多时间来解决错误消息。最后在网上得到一条线索,我应该使用查询选项 MAXDOP 1 来避免并行性。当我选择它时,错误消息完全不同。其实是在varchar列插入语句导致的字符串截断,调整了要摄取的字符串长度,一切恢复正常。
希望对某人有帮助。
这是 S Kumar Dubey 来自 MSDN 的解决方案
Execute SP: SP_LOCK In Results 你会得到SPID, DBID, OBJID, INDID, TYPE, RESOURCE, MODE, STATUS 现在检查状态列,如果是 显示等待然后杀死该 SPID。杀死特定的 SPID 执行 SP:杀死 65(其中 65 是 SPID)
看来您需要成为 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 { }
}