上一篇文章我给你介绍了WinDbg的入门,还有你如何能附加到SQL Server。今天的文章,我们继续往前一步,我会向你展示使用WinDbg调试SQL Server查询需要的步骤。听起来很有意思?我们开始吧!

假设在你面前有个简单的查询,你想在WinDbg里调试那个特定的查询。听起来很简单,但一旦你开始考虑这个问题,就会碰到很多问题:

  • 在我特定执行的查询上,我如何标识出正确的工作者线程?
  • 在sqlservr.exe里,我应该在哪里设置断点?

我们来具体讲解下这2个问题。

标识出正确的工作者线程

当你在SQL Server里执行一个查询,默认情况下你是不知道查询是在哪个线程上运行的。幸运的是SQL Server在DMV sys.dm_os_threads里提供os_thread_id列来告诉我们。OS线程ID就是用来执行指定查询的。不幸的是你需要从sys.dm_exec_requests直到sys.dm_os_threads连接多个表才可以得到需要的信息。我们来看下面的查询:

 SELECT R.Session_Id, Th.os_thread_id FROM sys.dm_exec_requests R
JOIN sys.dm_exec_sessions S ON R.session_id = S.session_id
JOIN sys.dm_os_tasks T ON R.task_address = T.task_address
JOIN sys.dm_os_workers W ON T.worker_address = W.worker_address
JOIN sys.dm_os_threads Th ON W.thread_address = Th.thread_address
WHERE S.is_user_process = 1
GO

在WinDbg里用CTRL+BREAK中断sqlservr.exe。为了切换到sys.dm_os_thread提供的系统线程ID,你可以用下列WinDbg命令:

~~[tid]s

占位符tid的值就是实际的系统线程ID——16进制值。因此你需要来自sys.dm_os_thread的os_thread_id列值转为16进制值,用刚才提到的命令。当你的系统线程ID是4910时,你应该用下列WinDbg命令切换到正确的线程:

~~[132E]s

当你的查询运行时,对于你的产寻,sys.dm_os_thread只显示系统线程ID。因此就有下一个问题:对于一个执行的查询,我如何获得“正确的”系统线程ID。我这里用一个小技巧:首先我运行一个简单的WAITFOR DELAY命令(例如1分钟),然后再运行实际的查询。如果你用这个方法,你需要保证在1个批处理里提交2个T-SQL查询。不然的话,SQL OS调度会放置WAITFOR语句和实际的查询在2个不同的线程!我们来看实际的代码:

WAITFOR DELAY '00:01:00'

SELECT
soh.*,
d.*
FROM Sales.SalesOrderHeader soh
INNER JOIN Sales.SalesOrderDetail d ON soh.SalesOrderID = d.SalesOrderID
WHERE soh.SalesOrderID = 71832
AND d.SalesOrderDetailID = 111793
GO

在等待期间,你需要进行下列操作:

  1. sys.dm_os_thread为你等待的查询获得在不同会话里系统线程ID
  2. 转化系统线程ID为16进制值
  3. 用CTRL+BREAK中断sqlservr.exe
  4. 用~~[tid]命令切换到正确的系统线程ID
  5. 在指定线程上设置断点
  6. 继续sqlservr.exe的运行
  7. 等待直到触发断点

你要在用WAITFOR DELAY语句引起的延迟时间内完成所有这些操作。如果超过这个时间,这个方法就不可靠了。因此在刚开始的时候,你可以用WAITFOR DELAY设置长一点的延迟时间,直到用这个方法你已经有经验了。

在sqlservr.exe里设置“好的”断点

现在你已经从sys.dm_os_thread获得了系统线程ID,而且你用WinDbg挂起了sqlservr.exe的执行。下一步你要在sqlservr.exe里设置断点,这样的话你可以在你的查询里调试并单步执行通过。但什么是好的断点呢?这个看情况:)执行计划里的每个运算符都是用独立的C++类实现的,它里面包含不同的函数。其中一个熟知的函数是GetRow,它返回一行到执行里上迭代器。我的方法如下:在执行计划里,尝试在最左的一个迭代器里设置断点。从我的经验里发现,每个SELECT查询开始于sqlmin!CQueryScan::GetRow的函数调用。

刚开始在指定类和函数上设置断点应该非常有用。当然你需要花很长时间(当单步执行通过代码时),指导你碰到SQL Server有意思的部分,像B树管理器,或者闩锁/旋转锁的实现。但初次试验时,建议你在特定函数设置断点就可以了。你要确保断点设置在正确的线程上,因为你只想调试你特定查询,没别的!用bm命令在指定线程和符号名上设置断点:

~tid bm sqlmin!CQueryScan::GetRow

但你还要意识到你不必提供系统线程ID。bm命令期望一个从零开始数字线程号。当你用~~[132E]s切换到正确的系统线程时,你会在WinDbg左下角看到线程号:

当WinDbg提示像47的线程号,你可以用下列命令在正确的线程上,在sqlmin!CQueryScan::GetRow函数设置断点:

~47 bm sqlmin!CQueryScan::GetRow

设置断点后,你可以用F5继续sqlservr.exe的运行。几秒后(取决于在WAITFOR语句上设置的延迟)WinDbg应该会在特定的断点中断:

现在好戏才开始:你可以用k命令探索当前的调用堆栈,你可以对汇编代码单步执行通过,看看其他函数是如何调用的。梦想有多远,你的选择就有多远(Your choices are endless, and only limited by your imagination.)。

小结

希望这篇文章已经给你以下内容深入的介绍:

sqlservr.exe里对于指定的查询进行调试时,如何成功的设置断点。

请继续关注并玩“坏”WinDbg!

感谢关注!

参考文章:

https://www.sqlpassion.at/archive/2014/05/13/debugging-a-sql-server-query-with-windbg/

使用WinDbg调试SQL Server查询的更多相关文章

  1. 如何设断点????-----使用WinDbg调试SQL Server查询

    http://www.cnblogs.com/woodytu/p/4665427.html http://www.sqlservercentral.com/blogs/aschenbrenner/20 ...

  2. 使用WinDbg调试SQL Server——入门

    这篇文章我想探究下SQL Server里完全不同的领域:如果使用WinDbg(来自针对Windows的调试工具)调试SQL Server.在我们进入枯涩细节之前,我想详细解释下为什么选择这样晦涩的话题 ...

  3. 使用WinDbg调试SQL Server——入门:Woodytu

    http://www.cnblogs.com/woodytu/p/4663525.html https://www.sqlpassion.at/archive/2014/05/13/debugging ...

  4. Windbg调试Sql Server 进程

    http://blog.csdn.net/bcbobo21cn/article/details/52261466 http://www.sqlservercentral.com/blogs/asche ...

  5. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  6. [转] 利用SET STATISTICS IO和SET STATISTICS TIME 优化SQL Server查询性能

    首先需要说明的是这篇文章的内容并不是如何调节SQL Server查询性能的(有关这方面的内容能写一本书),而是如何在SQL Server查询性能的调节中利用SET STATISTICS IO和SET ...

  7. SQL SERVER 查询性能优化——分析事务与锁(五)

    SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...

  8. SQL Server 查询性能优化 相关文章

    来自: SQL Server 查询性能优化——堆表.碎片与索引(一) SQL Server 查询性能优化——堆表.碎片与索引(二) SQL Server 查询性能优化——覆盖索引(一) SQL Ser ...

  9. 利用SET STATISTICS IO和SET STATISTICS TIME 优化SQL Server查询性能

    首先需要说明的是这篇文章的内容并不是如何调节SQL Server查询性能的(有关这方面的内容能写一本书),而是如何在SQL Server查询性能的调节中利用SET STATISTICS IO和SET ...

随机推荐

  1. 【地图API】地址录入时如何获得准确的经纬度?淘宝收货地址详解

    用户需求:管理者需要录入一批商户,并在地图上把商户展示出来.但发现一些商户的地址描述并不清楚,导致商户位置出错.如何获得更加准确的商户位置呢? 分析:假设地址准确的,可以通过地址解析,得到准确的经纬度 ...

  2. Lotus中关于字符串处理的函数汇总

    我们在使用LotusScript编写代理程序的时候,很多时候我们会遇到需要处理字符串的情况,本文就对平时遇到的相关函数做一个汇总. Sub Initialize  Dim testStr As Str ...

  3. PHP ERROR : Call to undefined function curl_init()

    在使用PHP 的Curl方法时出现了以下错误 可能的解决办法: 在php.ini 中确保 启用了php_curl.dll组件 确保PHP版本 (PHP 4 >= 4.0.2, PHP 5, PH ...

  4. nginx模块开发篇 (阿里著作)

    背景介绍 nginx历史 使用简介 nginx特点介绍 nginx平台初探(100%) 初探nginx架构(100%) nginx基础概念(100%) connection request 基本数据结 ...

  5. C# Activex开发、打包、签名、发布 C# Activex开发、打包、签名、发布 [转]

    C# Activex开发.打包.签名.发布 2013-06-22 12:01:20 浏览:3823 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠HTML ...

  6. 用户管理 之 在Linux系统中,批量添加用户的操作流程

    一.阅读此文件您需要掌握的基础知识: <Linux 用户(user)和用户组(group)管理概述><用户(user)和用户组(group)配置文件详解><Linux 用 ...

  7. 【原创】开源BI领袖-SpagoBI5.X最详细的中文版介绍

    SpagoBI是唯一100%的开源商业智能套件由 Engineering Group的SpagoBI实验室(www.eng.it)开发和管理.它提供了强大的分析能力,从传统的报表和图表功能到自助分析. ...

  8. Eclipse+Selenium自动化测试脚本设计V1.0

    Eclipse+Selenium自动化测试脚本设计V1.0 http://www.docin.com/p-803032251.html

  9. 2dtoolkit获取sprite像素大小的方法

    获取sprite像素的方法 Vector2 GetPixelSize(tk2dSpriteDefinition def){ ].x; ].y; // Calculate dimensions in p ...

  10. 数据库时间createtime字段 数据类型的选取

    之前是一直在用datetime类型(db)精度到yyyy-MM-dd HH:mm:ss 或者 date类型 精度到 yyyy-MM-dd 用了框架自动注入功能,自己也没去深入没去管他的set赋值值等等 ...