为什么sleeping的会话会造成阻塞(2)

科技资讯 投稿 6400 0 评论

为什么sleeping的会话会造成阻塞(2)

背景

客户反馈系统突然从11:10开始运行非常缓慢,在SQL专家云中看到大量的产生阻塞的活动会话,KILL掉阻塞的源头马上又出现新的源头,实在没有办法只能重启应用程序断开所有数据库连接才解决,请我们协助分析根本的原因。

现象

进入活动会话原始数据页面,看到不同时间点的阻塞源头会话是不同的,但都是同一类的现象,阻塞源头会话的状态是sleeping,被阻塞的会话都在对同一个表执行UPDATE语句。

分析

本着这个经验,对这些sleeping的会话进行回溯,发现这些会话在sleeping之前,都曾经被阻塞过很长时间,根据慢语句的特征判断是执行超时了。

 

通过对存储过程进行分析,发现里面在用TRY CATCH的方式处理事务,因此推断该方式无法捕获应用程序端的超时错误,导致事务和连接的泄露,因为存储过程比较复杂,下面用一个测试来模拟。

测试

CREATE PROCEDURE dbo.usp_test
AS 
  BEGIN TRAN 

  BEGIN TRY 
    UPDATE 
      dbo.Table_2 WITH(ROWLOCK 
    SET 
      a = 'wang'

    UPDATE 
      dbo.Table_1 WITH(ROWLOCK 
    SET 
      a = 'wang'
  END TRY 
  BEGIN CATCH 
    IF @@ERROR = 0 
    BEGIN 
      GOTO succeed 
    END 
    ELSE 
    BEGIN 
      GOTO error 
    END 
  END CATCH

  succeed: 
    COMMIT TRAN 
    RETURN 1 
  error: 
    ROLLBACK TRAN 
    RETURN 0

新建一个查询,开始一个事务,然后执行UPDATE Table_1,不提交或者回滚事务,对表Table_1的排他锁一直存在,用来模拟对表Table_1的锁定。

 

 执行存储过程usp_test。updat dbo.Table_2很快执行完,在执行updat dbo.Table_1时产生阻塞,等待30秒后出现超时的报错。

 

 

解决

对于这类问题,根本的解决方法是修改应用程序,增加对于执行异常的捕获,检查是否存在事务并回滚,然后关闭数据库连接。

编程笔记 » 为什么sleeping的会话会造成阻塞(2)

赞同 (30) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽