SQL Server转储介绍III

obuntu obuntu 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
之前曾介绍过SQL Server的DUMP文件,现在来看一个从DUMP文件获取查询语句的例子。手工生成DUMP文件可以参考前面的帖子(SQL Server 转储介绍 I 和 SQL Server 转储介绍II),在WIN7或者Windows Server 2008上,还可以在任务管理器用右键进行文件转储。在分析DUMP文件之前,需要设置好windbg的使用环境,主要是设置symbol的路径,以前的帖子里也有介绍:)。


然后就可以使用windbg进行DUMP文件分析了,打开windbg->File->Open Crash Dump 打开具体的转储文件。然后找到具体执行SQL 语句的线程,寻找方法也很简单,在windbg的命令行里面输入~*kv,找到有sqlservr!CMsqlExecContext::ExecuteStmts<1,1>的线程就可以了。然后再用~ns,设置到线程n。
设置到具体线程后,用kv命令查看调用栈信息。接下来就可以根据调用栈来获取具体的SQL 执行语句了。
0:000> ~46s
ntdll!ZwWaitForSingleObject+0xa:
00000000`76f6f6fa c3 ret
0:046> kvnf
# Memory Child-SP RetAddr : Args to Child : Call Site
00 00000000`0fe3b688 000007fe`fd6f10ac : 00000000`80cb61a0 00000000`0fe3b780 00000000`00000001 00000000`0144105c : ntdll!ZwWaitForSingleObject+0xa
01 8 00000000`0fe3b690 00000000`013b889e : 00000000`000007d0 00000000`012b5f80 00000000`00000000 00000000`00000669 : KERNELBASE!WaitForSingleObjectEx+0x79
02 a0 00000000`0fe3b730 00000000`013b8799 : 00000000`00000000 00000000`007c8c00 ffffffff`ffffffff 00000000`0fe3b870 : sqlservr!Np::StatusWriteNoComplPort+0x6e
03 b0 00000000`0fe3b7e0 00000000`013b85cc : 00000000`007ce240 00000000`007ce240 00000000`0fe3b8b0 00000000`00000000 : sqlservr!SNIStatusWriteNoComplPort+0x59
04 60 00000000`0fe3b840 00000000`0101f671 : 00000000`00000000 00000000`00001000 00000000`00000000 00000000`8135cad0 : sqlservr!TDSSNIClient::WriteStatus+0x99
05 30 00000000`0fe3b870 00000000`00f93ba3 : 00000000`80c70750 00000000`80c70c40 00000000`00000001 00000000`80c70750 : sqlservr!write_data+0x1bf
06 1e0 00000000`0fe3ba50 00000000`013acaea : 00000000`80cb61a0 00043300`00100004 00000000`00000000 00000000`00000000 : sqlservr!flush_buffer+0xf3
07 50 00000000`0fe3baa0 00000000`00fb3b69 : 00000000`00000000 00000000`00000000 00000000`8136b690 00000000`00000000 : sqlservr!CKatmaiTds::SendRowImpl+0x19c
08 280 00000000`0fe3bd20 00000000`00f9287e : 00000000`00000000 00000000`00000000 00000000`80c70140 00000000`80c704f0 : sqlservr!CXStmtQuery::ErsqExecuteQuery+0x5ce8
09 2f10 00000000`0fe3ec30 00000000`00f90fe3 : 00000000`8135ecb0 00000000`0144cc96 00000000`80a72140 00000000`00000000 : sqlservr!CMsqlExecContext::ExecuteStmts<1,1>+0xb6c
0a 290 00000000`0fe3eec0 00000000`00f91499 : 00000000`80a72140 00000000`8135d3d0 00000000`8135d300 00000000`00000000 : sqlservr!CMsqlExecContext::FExecute+0x593
0b 180 00000000`0fe3f040 00000000`00f93ff2 : 00000000`00000000 00000000`8135d3d0 00000000`8135dc30 00000000`00000000 : sqlservr!CSQLSource::Execute+0x2f9
0c 120 00000000`0fe3f160 00000000`00f8ebbb : 00000000`8135cfa0 00000000`007c8c00 00000000`00000000 00000000`00000000 : sqlservr!process_request+0x370
0d 2c0 00000000`0fe3f420 00000000`00f12abb : 00000000`00000000 00000000`00000000 00000000`00479988 00726574`6e696f50 : sqlservr!process_commands+0x2b2
0e 200 00000000`0fe3f620 00000000`00f10fda : 00000000`00000000 00000000`00000000 00000000`80cb61a0 00000000`80cb61a0 : sqlservr!SOS_Task::Param::Execute+0x11b
0f 120 00000000`0fe3f740 00000000`00f12665 : 00000000`0fe3f7f8 00000000`00479948 00000000`00479948 00000000`00000000 : sqlservr!SOS_Scheduler::RunTask+0xca
10 90 00000000`0fe3f7d0 00000000`014babb0 : 00000000`00479940 00000000`80cb61a0 00000000`00479948 00000000`00418270 : sqlservr!SOS_Scheduler::ProcessTasks+0x95
11 70 00000000`0fe3f840 00000000`014bc4b0 : 00000000`80cb61a0 00000000`00480080 000007ff`fff9e000 000007ff`fff9f4a8 : sqlservr!SchedulerManager::WorkerEntryPoint+0x110
12 c0 00000000`0fe3f900 00000000`014ba060 : 00000000`80cb61a0 000007ff`fff9f4a8 00000000`00418190 000007fe`fd6f6cf9 : sqlservr!SystemThread::RunWorker+0x60
13 30 00000000`0fe3f930 00000000`014ba9ef : 000007ff`fff9f4a8 000007ff`fff9f4a8 00000000`056f3e30 00000000`00418190 : sqlservr!SystemThreadDispatcher::ProcessWorker+0x12c
14 90 00000000`0fe3f9c0 00000000`680137d7 : 000007ff`fff9f4a8 00000000`0081ac10 00000000`00000000 00000000`00000000 : sqlservr!SchedulerManager::ThreadEntryPoint+0x12f
15 90 00000000`0fe3fa50 00000000`68013894 : 00000000`680c95c0 00000000`0081ac10 00000000`00000000 00000000`00000000 : msvcr80!endthreadex+0x47
16 30 00000000`0fe3fa80 00000000`7685f56d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : msvcr80!endthreadex+0x104
17 30 00000000`0fe3fab0 00000000`76f52cc1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
18 30 00000000`0fe3fae0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d

用kvnf命令查看的调用者说明如下:
第一列“#”,表示调用栈的序号;第二列"memory"表示栈所占用的空间;第三列Child-SP则是函数的入栈地址,在有的平台上会显示为ChildEBP,EBP和ESP在汇编里面就是存放栈的具体地址的;第四列的“RetAddr”表示函数返回地址;第五列的“Args to Child ”表示对应函数的参数地址,只显示前3个,但这三个地址在有些情况下会不准确;第六列的“Call Site”则是具体的函数调用名,像sqlservr!CMsqlExecContext::ExecuteStmts<1,1>中的sqlservr表示具体的执行程序,CMsqlExecContext表示具体的类,ExecuteStmts表示具体的方法(从中也可以看出SQL Server是用C++来编写的~)。

接下来就可以根据调用栈来获取实际的SQL 语句了。
在这里我们关注的是process_request这个函数:
0c 120 00000000`0fe3f160 00000000`00f8ebbb : 00000000`8135cfa0 00000000`007c8c00 00000000`00000000 00000000`00000000 : sqlservr!process_request+0x370
从第一个参数地址入手,按照下面的步骤就可以获取实际的SQL 执行语句。
0:046> dd 8135cfa0+0x20 l1
00000000`8135cfc0 8135cea0
0:046> dd 8135cea0+0x28 l1
00000000`8135cec8 80317970
0:046> dd 80317970+0x200 l1
00000000`80317b70 813645b0
0:046> dd 813645b0+0x20 l1
00000000`813645d0 81364610
0:046> dd 81364610 l1
00000000`81364610 813646a0
0:046> du 813646a0
00000000`813646a0 "while 1=1..select * from obuntu_"
00000000`813646e0 "testOR_CōOP._ON_?脶"

上述命令中的dd和du是查看内存的指令,更灵活的用法可以参考windbg的手册。至于为什么在地址后面要加上一些偏移(如0x20,0x28,0x2000),我们一般是无法获悉的,但一般情况下,我们可以按照上述步骤获取SQL 语句。我也是下面的这两篇帖子中看到分析SQL dump文件,比较感兴趣,所以给大家介绍下。
《How do I find what queries were executing in a SQL memory dump?》
《Finding which queries were executing from a SQL Memory Dump – revisited》


其中第二个帖子里面,因为作者用到了private symbol(微软不公开的),也就是说他有SQL Server的源码,所以我们没办法重现。而第一个帖子里面的使用方法,在我的环境里是可以实现的。其实分析这样的dump文件跟版本和编译环境是有很大关系的,我的环境参数如下:
--SQL Server:
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64) Jul 9 2008 14:17:44 Copyright (c) 1988-2008 Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
--OS:
Windows 7 Version 7600 MP (4 procs) Free x64
Product: WinNt, suite: SingleUserTS Personal
kernel32.dll version: 6.1.7600.16385 (win7_rtm.090713-1255)


本来想通过反汇编研究下为什么取那样的偏移,无奈道行尚浅,看到几千上万的汇编代码直接晕过去了。不过我们可以通过编写个C程序,用windbg分析下调用栈的情况。

C代码如下:

#include <stdio.h>

void add(int *a, int *b,int *c)
{
*c = *a + *b;
}

int main()
{
int a = 10;
int b = 5;
int c;
add(&a,&b,&c);

printf("c:%d\n",c);

}


编译执行后,用windbg->File->Open Executeable打开编译后的exe文件,然后用bp命令在exe文件里面的add函数打上断点,然后输入g命令直接运行,windbg会在add函数里面停住,接着用kv命令看下具体的调用栈信息。然后可以用dd命令查看add函数对应的三个参数地址的实际值。具体如下:



在图中,可以看到“Args to Child”列里面的第一个地址的值为0000000a,也就是十进制10,刚好是a的值;第二个地址的值为00000005,十进制5,是b的值;第三个地址的值为cccccccc,这是因为我们还没执行到让参数c获取值的地方,系统会自动给这样的参数赋值为cccccccc。

所以,对于SQL Server文件,我们也可以根据这样的方法来一个个分析函数的值,但花费的时间相对来说会很多的。同时,根据上述例子打断点的思想,我们如果从一个因异常而dump出的文件中分析出了出错的地方,还可以在windbg->File->Attach to a Process,附加SQL Server的进行,进行单步跟踪,同时根据反汇编信息获得具体的错误内容。(但请注意,如果用windbg附加一个正在运行的进程时,在windbg退出后,也会推出进程,所以千万不要在生产环境上做这样的一个实验!!!!)。

其实,SQL Server是一个比较稳定的数据库系统,如果出现了dump文件,一般要么是碰到微软的BUG,要么是数据库出现了致命的问题。对于这种东西,如果没有微软的支持,我们是很难定位出具体的问题所在。所以,我们只能规避它,要么重装系统,要么重装SQL Server,要么重建数据库,如果还搞定不了的话,还是求助微软吧。

写这帖子,只是给有兴趣的人一点参考,也希望能共同探索~。现在流行微博,也发一个,大家有兴趣的话,可以多多交流:) http://weibo.com/huangqingxin
...全文

相关推荐

【信息科学与工程学】【安全领域】第三十五篇 网络安全算法表

编号算法名称算法的逐步骤思考推理的数学方程式和分解的数学方程式参数/变量列表复杂度(时间/空间)1​AES (高级加密标准)​1. 密钥扩展:从初始密钥生成轮密钥。 2. 初始轮: 3. 主轮循环(Nr-1轮):  - SubBytes:(非线性字节替换)  - ShiftRows:对状态矩阵的行进行循环移位。  - MixColumns:(在GF(2⁸)上的矩阵乘法)  - AddRoundKey: 4. 最终轮:执行SubBytes、ShiftRows、AddR

flyair_China

论文复现基于欠谐振工作区间的全桥LLC变换器混合控制仿真建模与动态性能分析(Simulink仿真实现)

内容概要:本文系统解读了一套完整的多机器人路径规划(MAPF)MATLAB代码库,重点剖析了基于优先级规划与Petri网融合的多智能体无冲突路径生成框架。文章详细阐述了该框架的四层架构设计:几何层负责地图解析与栅格化处理,拓扑层构建四邻域图与Petri网模型,调度层实现基于优先级启发式的路径规划与冲突消解,呈现层完成动画与视频可视化输出。核心创新包括动态边权膨胀机制、节点预留历史查询、几何惩罚驱动的局部同步以及Petri网双阶段优化策略,显著提升了算法在大规模场景下的求解效率与鲁棒性。; 适合人群:具备一定编程基础和算法基础,从事机器人路径规划、智能交通、仓储物流调度等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:① 学习和复现基于优先级规划的多智能体无冲突路径生成方法;② 掌握动态边权膨胀、节点预留历史等关键技术以提升路径规划效率;③ 利用Petri网进行整数规划求解并实现双阶段优化;④ 构建可扩展的多机器人系统仿真平台并实现轨迹可视化。; 阅读建议:建议读者按照文中所述的数据流顺序逐步学习各模块设计,重点关注四层架构之间的接口关系与信息传递机制。在实践过程中应结合提供的完整代码与测试案例,调试并验证不同同步策略的效果差异,并尝试对框架进行功能扩展,如引入回溯机制以提高算法完备性。

大龙不吃小鱼干

基于容积卡尔曼滤波CKF的车辆状态估计Carsim和Matlab联合仿真(说明文档+仿真源文件+运行说明)

内容概要:本资源提供了基于容积卡尔曼滤波(CKF)的车辆状态估计算法在Carsim与Matlab/Simulink环境下的联合仿真解决方案,包含完整的说明文档、仿真源文件及运行指南。通过Carsim构建高精度车辆动力学模型,Simulink实现CKF算法设计与状态估计,有效融合两者优势,实现了对车辆关键状态参数(如质心侧偏角、横摆角速度、车速等)的高精度实时估计。该方法克服了传统传感器直接测量成本高、安装难的问题,提升了车辆动态性能分析与控制系统的智能化水平。; 适合人群:适用于从事车辆工程、智能驾驶、控制理论与应用等相关领域的科研人员、高校研究生及企业研发工程师,尤其适合具备一定Carsim和Matlab联合仿真基础的技术人员。; 使用场景及目标:①开展车辆状态估计算法的研究与验证,提升无人车、ADAS系统中的感知能力;②完成学术论文复现、毕业课题设计或工程项目开发中的核心算法模块搭建;③深入理解非线性滤波算法(如CKF)在实际车辆系统中的建模与应用流程。; 阅读建议:建议用户结合说明文档逐步运行仿真程序,重点关注Carsim与Simulink的接口设置、信号交互机制以及CKF算法模块的设计逻辑,同时可通过修改工况条件和噪声参数来测试算法鲁棒性,强化理论与实践的结合。

大龙不吃小鱼干

高校技术转移办公室在推动成果转化过程中面临哪些信息整合难题?.docx

高校技术转移办公室在推动成果转化过程中面临哪些信息整合难题?

BIZKEEN

回流焊温度曲线合格判据分析器

【适用方向】工程数据分析与报表 【工具用途】 「回流焊温度曲线合格判据分析器」用于半导体制造过程中的工程计算与分析, 帮助工艺、设备、质量与生产工程师快速完成日常数据处理工作。 【能解决什么】 · 免去手工Excel 反复整理与公式编写,直接导入数据即可出结果 · 计算过程透明,关键参数可按现场实际调整 · 输出图表与明细报表,便于直接用于汇报与存档 【包内内容】 · 工具源码(Python,可直接运行) · 使用说明(数据格式与操作步骤) · 依赖清单与示例数据 【适用人群】 半导体 FAB / 晶圆厂:工艺、设备、质量、IE、生产工程师; 以及 MES 与智能制造方向的技术人员。 【使用说明】 解压后按说明导入数据运行即可;工具在本地处理数据,不联网。

半导体智能制造 | MES工程师实战笔记
评论 80
收藏 已收藏
分享
返回顶部
obuntu
MS-SQL Server 34,876 成员 254,635 内容