我可以在我的web应用程序中使用c#锁来防止SQL Server死锁吗?

本文关键字:SQL Server 死锁 web 我的 应用程序 我可以 | 更新日期: 2023-09-27 18:03:32

我正在使用c#在Visual Studio 2010中编写一个web应用程序。web应用程序执行复杂的SQL Server 2008语句,如果在同一时间多次调用同一个.aspx页面,有时会导致死锁。建议的解决方案是使用SQL server手段来防止这些死锁,但我的问题是,我真的不太了解它,这不是c#,我知道得更好。

所以我想知道,我在ASP中使用锁的缺点是什么。. NET页面(或c#中的锁,或Windows命名的互斥锁),而不是通过SQL服务器进行锁定来防止这些死锁?

p。此SQL Server数据库仅供此web应用程序使用。

EDIT:下面是执行SQL语句的c#代码:

int iNumRows = 0;
using (SqlConnection cn = new SqlConnection(strConnection))
{
    cn.Open();
    using (SqlCommand cmd = new SqlCommand(strSQL, cn))
    {
        //Use C# lock here
        iNumRows = Convert.ToInt32(cmd.ExecuteScalar());
        //Release C# lock here
    }
}

下面是一个SQL示例(实际上是由c#脚本动态组成的):

SET XACT_ABORT ON;
BEGIN TRANSACTION;
DELETE FROM [dbo].[t_Log_2] 
      WHERE [idtm]<'2011-03-12 08:41:57';
WITH ctx AS(
     SELECT MIN([idtm]) AS mdIn, 
            MAX([odtm]) AS mdOut 
           FROM [dbo].[t_Log_2] 
          WHERE [type] = 0 
            AND [state] = 0 
            AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4' 
            AND [odtm] >= '2013-03-11 06:33:32' 
            AND [idtm] <= '2013-03-11 06:43:12' 
           ) 
INSERT INTO [dbo].[t_Log_2] 
([oid],[idtm],[odtm],[type],[state],[huid],
 [cnm],[cmdl],[batt],[dvtp0],[dvtp1]) 
SELECT 
    2, 
    CASE WHEN mdIn IS NOT NULL 
          AND mdIn < '2013-03-11 06:33:32' 
         THEN mdIn 
         ELSE '2013-03-11 06:33:32' 
         END,
    CASE WHEN mdOut IS NOT NULL 
          AND mdOut > '2013-03-11 06:43:12' 
         THEN mdOut 
         ELSE '2013-03-11 06:43:12' 
         END,
    0,
    0,
    N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4',
    null,
    null,
    0,
    1,
    null 
FROM ctx 
SELECT ROWCOUNT_BIG()
DELETE FROM [dbo].[t_Log_2] 
      WHERE [type] = 0 
        AND [state] = 0 
        AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4' 
        AND [odtm] >= '2013-03-11 06:33:32' 
        AND [idtm] <= '2013-03-11 06:43:12' 
        AND [id] <> SCOPE_IDENTITY()
DELETE FROM [dbo].[t_Log_2] 
      WHERE [type] = 0 
        AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4' 
        AND [idtm] >= (SELECT [idtm] FROM [dbo].[t_Log_2] 
                                    WHERE [id] = SCOPE_IDENTITY()) 
        AND [odtm] <= (SELECT [odtm] FROM [dbo].[t_Log_2] 
                                    WHERE [id] = SCOPE_IDENTITY()) 
        AND [id] <> SCOPE_IDENTITY() 
;WITH ctx1 AS( 
     SELECT [idtm] AS dI 
       FROM [dbo].[t_Log_2] 
      WHERE [id] = SCOPE_IDENTITY() 
             )
UPDATE [dbo].[t_Log_2] 
        SET [odtm] = ctx1.dI 
       FROM ctx1 
      WHERE [id] <> SCOPE_IDENTITY() 
        AND [type] = 0 
        AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4' 
        AND [idtm] < ctx1.dI 
        AND [odtm] > ctx1.dI 
;WITH ctx2 AS(
     SELECT [odtm] AS dO 
       FROM [dbo].[t_Log_2] 
      WHERE [id] = SCOPE_IDENTITY() 
             ) 
UPDATE [dbo].[t_Log_2] 
        SET [idtm] = ctx2.dO 
       FROM ctx2 
      WHERE [id] <> SCOPE_IDENTITY() 
        AND [type] = 0 
        AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4' 
        AND [idtm] < ctx2.dO 
        AND [odtm] > ctx2.dO 
COMMIT TRANSACTION;
SET XACT_ABORT OFF

我可以在我的web应用程序中使用c#锁来防止SQL Server死锁吗?

在ASP中使用锁的缺点是什么?. NET页面(或c#中的锁,或Windows命名的互斥锁),而不是通过SQL服务器进行锁定来防止这些死锁?

将导致活锁而不是死锁。

当等待图包含一个循环(A等待B, B等待A)时,会发生死锁。SQL Server定期检查所有的等待图并查找循环。当检测到一个这样的循环时,通过选择受害者并中止其事务来打破循环。

如果你把这些锁移到SQL Server控制域之外,例如:在进程互斥、临界区、c#事件或其他情况下,等待图周期仍然会发生,但现在这个周期将通过应用程序完成,因此SQL Server将无法检测到(A在SQL中等待B,但B在应用程序中等待A)。因为死锁监视器不会看到一个周期,所以它不会运行死锁解析算法(选择一个受害者,中止它的事务),并且死锁将永远保持。恭喜,现在您的应用程序只是挂起,而不是引发死锁异常!

你不必相信我的话,其他更有经验的人已经被这个问题烧伤了,并且吸取了惨痛的教训,但幸运的是,把它写下来,这样你就可以用简单的方法学习。你正在阅读的这个网站就是一个例子。

解决死锁在SQL Server是相当容易的,一旦你明白了这个问题。如果捕获并附加死锁图(XML,而不是图片!)以及表的确切定义,也许我们可以提供帮助。唉,你已经忽略了这样的请求,所以我想唯一要问的问题是你想要更多的绳子吗?

在不知道足够细节的情况下,无法找到真正导致死锁的地方,我可以猜测这可能是因为键范围导致了死锁,这意味着死锁发生在表t_log_2的索引上,因为你有删除和更新,它们肯定不是发生在同一行上,但它们可以发生在相同的键范围上,或者一个进程可以持有A范围,请求B范围,另一个进程可以持有B范围和请求A范围。您可以使用SQL Profiler跟踪死锁并查看死锁究竟发生在哪里。或者,简单地说,如果不会对性能造成太大影响,您可以将事务隔离级别设置为[repeatable read]甚至[serializable]。


SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
....
BEGIN TRANSACTION
....