我有一個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