上周,在SQL Server数据库下面遇到了一个有意思的SQL阻塞(SQL Blocking)案例。其实个人对SQL Server的阻塞还是颇有研究的。写过好几篇相关文章。 至于这里为什么要总结一下这个案例,因为这个案例有点意思:

1:使用DMV视图捕获到的Blocking SQL为一个查询语句(这个不是真正引起阻塞的源头SQL语句),等待事件为LCK_M_S。

2:出现阻塞的会话非常多,阻塞的量非常大,使用DMV视图始终捕获不到相关表的DML操作语句。捕获到全是SELECT语句。

我们知道,在SQL Server中SELECT查询是不会阻塞SELECT查询的(不了解这个问题的,具体可以参考博客SQL Server中SELECT会真的阻塞SELECT吗? )。而且被阻塞的语句的等待类型为LCK_M_S,那么可以肯定:那个阻塞的源头会话中,存在对该表的DML操作,而且事务由于某些原因未提交。只是那个会话最后执行的SQL语句为一个SELECT查询。因为有时候,我们根本不能定位到SQL阻塞的源头SQL语句,具体参考我的博客“为什么数据库有时候不能定位阻塞(Blocker)源头的SQL语句,此处不做重复赘述。

我们用一个简单的例子来模拟这个真实的案例,如需所示,首先创建一个测试表:

CREATE TABLE TEST (id    INT);
GO
INSERT INTO TEST VALUES(1);

然后再通过2个会话,模拟这样的阻塞案例,如下所示:

会话A:

SET IMPLICIT_TRANSACTIONS ON;
GO
INSERT INTO TEST VALUES(2)
GO
SELECT  * FROM TEST WHERE ID =1;

注意:先设置开启隐式事务,第一次执行插入数据语句,然后执行SELECT查询。

会话B:

SELECT * FROM TEST WHERE id=1;

会话C:

SELECT wt.blocking_session_id                    AS BlockingSessesionId
      ,sp.program_name                        AS Blocking_ProgramName
      ,COALESCE(sp.LOGINAME, sp.nt_username)    AS Blocking_HostName    
      ,ec1.client_net_address                    AS ClientIpAddress
      ,db.name                                AS DatabaseName        
      ,wt.wait_type                            AS WaitType                    
      ,ec1.connect_time                        AS BlockingStartTime
      ,wt.WAIT_DURATION_MS/1000                AS WaitDuration
      ,ec1.session_id                            AS BlockedSessionId
      ,h1.TEXT                                AS BlockedSQLText
      ,h2.TEXT                                AS BlockingSQLText
FROM sys.dm_tran_locks  AS tl WITH(NOLOCK)
INNER JOIN sys.databases AS db  WITH(NOLOCK)
  ON db.database_id = tl.resource_database_id
INNER JOIN sys.dm_os_waiting_tasks AS wt  WITH(NOLOCK)
  ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.dm_exec_connections  ec1 WITH(NOLOCK)
  ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections  ec2 WITH(NOLOCK)
  ON ec2.session_id = wt.blocking_session_id
LEFT OUTER JOIN master.dbo.sysprocesses AS sp WITH(NOLOCK)
  ON SP.spid = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 

在会话C中查看SQL阻塞情况,如下截图所示,我们看到是SELECT查询阻塞了SELECT查询。

如上测试所示,因为是构造模拟案例,开启了“上帝视角”,所以你不会觉得有什么问题,实际情况是:应用程序是一个Java应用程序,而且是O/R Mapping框架(com.j256.ormlite),我将上面情况反馈给开发、Support人员,明确告诉他们阻塞的会话肯定有一个DML操作。让他们查找定位代码。但是诸多原因、因素叠加在一起(外包项目;沟通问题;对数据库的阻塞的的理解),沟通的效果让人很是无语。只能拿出确切的证据。由于那个框架开启了隐性事务(事后跟踪、分析发现的),而且UPDATE语句非常快,你使用DMV视图定位到的阻塞源头都是SELECT语句。显然这个不是我想要的。

于是,我打算使用SQL Server Profiler里面的“Blocked process report”事件来定位阻塞的源头,在跟踪之前,修改'blocked process threshold (s)'的值。如下所示,

exec sp_configure 'show advanced options',1;
 
reconfigure with override
 
exec sp_configure 'blocked process threshold (s)',4
 
reconfigure with override

然后设置SQL Server Profiler的相关选项和过滤条件。就像我下面的测试的一样,Blocked process report依然无法定位到阻塞的源头SQL语句,如下所示:

<blocked-process-report monitorLoop="3262026">
 <blocked-process>
  <process id="process1f9b22ca8" taskpriority="0" logused="0" waitresource="RID: 1:1:574:1" waittime="10174" ownerId="2680347313" transactionname="SELECT" lasttranstarted="2018-11-26T14:09:55.130" XDES="0x123391a20" lockMode="S" schedulerid="2" kpid="8604" status="suspended" spid="104" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2018-11-26T14:09:55.120" lastbatchcompleted="2018-11-26T14:09:37.887" lastattention="1900-01-01T00:00:00.887" clientapp="Microsoft SQL Server Management Studio - Query" hostname="GETNB00021" hostpid="10560" loginname="xxxx" isolationlevel="read committed (2)" xactid="2680347313" currentdb="1" lockTimeout="4294967295" clientoption1="671091040" clientoption2="390200">
   <executionStack>
    <frame line="1" stmtstart="24" stmtend="90" sqlhandle="0x02000000d8cd0821e4e62d2f8f098831e46f98ca20ba31ae0000000000000000000000000000000000000000"/>
    <frame line="1" stmtend="60" sqlhandle="0x0200000012eff610783e49a674c5361fd9c8bb38747a966a0000000000000000000000000000000000000000"/>
   </executionStack>
   <inputbuf>
SELECT  * FROM TEST WHERE ID =2;   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process status="sleeping" spid="89" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2018-11-26T14:09:52.927" lastbatchcompleted="2018-11-26T14:09:52.927" lastattention="1900-01-01T00:00:00.927" clientapp="Microsoft SQL Server Management Studio - Query" hostname="GETNB00021" hostpid="10560" loginname="xxxx" isolationlevel="read committed (2)" xactid="2680346553" currentdb="1" lockTimeout="4294967295" clientoption1="671091040" clientoption2="390202">
   <executionStack/>
   <inputbuf>
SELECT  * FROM TEST WHERE ID =1;
   </inputbuf>
  </process>
 </blocking-process>
</blocked-process-report>

最后,只能使用SQL Server Profiler跟踪某个登录名(Login Name)一小段时间,根据会话ID一段时间内执行过的SQL来推理、判断定位阻塞的源头,从而找到具体原因,这个例子里面,ORM框架开启了隐性事务,在SQL Server Profiler里面捕获到开启隐性事务以及UPDATE操作。至此。问题终于解开了谜底。当然本文不是按照当时的逻辑来写的,而是在知道原因后,模拟构造案例重新的。所以总感觉字里行间写不出那种味道。

SET IMPLICIT_TRANSACTIONS  ON;

.............

IF @@TRANCOUNT > 0 COMMIT TRAN set implicit_transactions off

转载于:https://www.cnblogs.com/kerrycode/p/10020273.html

一个特殊的SQL Server阻塞案例分析相关推荐

  1. SQL Server 阻塞原因分析

    这里通过连接在sysprocesses里字段值的组合来分析阻塞源头,可以把阻塞分为以下5种常见的类型(见表).waittype,open_tran,status,都是sysprocesses里的值,& ...

  2. 需要我们了解的SQL Server阻塞原因与解决方法 - sym_cn

    2019独角兽企业重金招聘Python工程师标准>>> 这里通过连接在sysprocesses里字段值的组合来分析阻塞源头,可以把阻塞分为以下5种常见的类型(见表).waittype ...

  3. sql server操作案例

    今天没事做,总结了下sql server的些知识: --创建表 CREATE TABLE users (id INT ,name VARCHAR(50),age INT )--添加数据 SELECT ...

  4. SQL性能优化案例分析

    这段时间做一个SQL性能优化的案例分析, 整理了一下过往的案例,发现一个比较有意思的,拿出来给大家分享. 这个项目是我在项目开展2期的时候才加入的, 之前一期是个金融内部信息门户, 里面有个功能是收集 ...

  5. 快速迁移数据中心:华为云数据库SQL Server实践案例技术解析

    1.   简介 企业或用户将数据中心部署在线下,采用独立软件提供商(Independent Software Vendor)软件进行管理.线下数据运维成本较高,故障容灾单一化,是目前遇到的瓶颈.采用云 ...

  6. SQL Server阻塞与锁

    在讨论阻塞与加锁之前,需要先理解一些核心概念:并发性.事务.隔离级别.阻塞锁及死锁. 并发性是指多个进程在相同时间访问或者更改共享数据的能力.一般情况而言,一个系统在互不干扰的情况下可以激活的并发用户 ...

  7. SQL Server事务日志分析

    refs: 1.)  https://blog.51cto.com/ultrasql/1953572 fn_dblog()和fn_dump_dblog()函数介绍 SQL Server有两个未公开的函 ...

  8. sql server小型案例-自动生成销售单号的触发器

    sql server实现自动生成销售单号的触发器 1.有关系统 最近在做信息系统课程设计的小项目,我们团队所做的是一个简单的自动贩卖机销售管理系统,其中我负责的部分是销售管理,其中需要实现的一个功能是 ...

  9. sql server php 案例,php连接sql server 2008案例

    背景: 最近一个项目,由于新学了php练手就接了,而没想到,给的数据库是sql server,而且我的系统是ubuntu,不得已找了台电脑连接. 环境介绍: 操作系统:windows xp 环境:wa ...

  10. SQL Server 索引使用分析(1)- 索引结构

    原文出处 [url]http://www.blue1000.com/bkhtml/2006-08/45511.htm[/url] 一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微 ...

最新文章

  1. 安卓四大组件之Service
  2. 智邦国际怎么样?企业管理软件好不好?
  3. 计算机进入安全模式,电脑怎么进入安全模式
  4. 永恒python怎么强化_永恒python加6_pythontip 挑战python (6-10)
  5. 逻辑漏洞之任意用户登陆漏洞
  6. 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其他的空间。表中不允许又重复的数据
  7. python外卷(10)--取整
  8. jq之mouseleave()
  9. Spring Boot 日志配置 ——logback
  10. 【JZOJ4762】【NOIP2016提高A组模拟9.7】千帆渡
  11. 同步与异步,如何解决线程安全问题—synchronized详解,对象锁与类锁,静态与非静态同步方法详解
  12. Office 2016 每次打开都有配置进度 解决办法
  13. 试验设计——均匀试验设计·好格子点法
  14. 2018年3大UI设计趋势,你知道吗?
  15. 有关上传到APPStore上iphone5,5c,4s下载应用,出现该APP与设备不兼容问题
  16. webrtc编译中的错误解决
  17. 解决TIM版无法修改个人文件夹位置
  18. 两数之和(LeetCode)
  19. JCR到底是什么?你真的了解吗?期刊引证报告(JCR)的前世今生
  20. 葫芦娃手游服务器未响应,葫芦娃充值没反应 充值元宝未到账解决办法

热门文章

  1. poj 2231 Moo Volume 暴力一定超时啊
  2. InDesign 教程,如何创建沉浸式文档?
  3. 在 MacBook 中如何将外置屏幕设置为主屏幕?
  4. 中兴2018年上半年业绩惨不忍睹,押宝5G建设能否让其起死回生?
  5. Convirt管理机Socat驻留进程故障处理
  6. extended-insert对mysqldump及导入性能的影响
  7. saltstack 自动化运维神器(四)salt-ssh
  8. 树莓派(RespberryPi)安装手记
  9. poj 3422 (费用流)
  10. ElasticSearch - 聚合 aggs