我们决定在query_abort
所有数据库服务器上测试并可能实施新的扩展事件跟踪,以了解有关超时查询的更多信息。目前,我们使用rpc_completed
带有status=2
过滤器的事件。
我们将使用此Microsoft 视频中详细介绍的SQLCallStackResolver 工具,并使用该工具处理的列。task_callstack_rva
这是我们从一份声明中得到的痕迹之一SELECT
:
00 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
00 SqlDK!ThreadScheduler::SwitchWorker
01 SqlDK!SOS_Scheduler::Switch
02 SqlDK!SOS_Scheduler::SuspendNonPreemptive
03 SqlDK!WaitableBase::Wait
04 sqllang!TDSSNIClient::WriteStatus
05 sqllang!WaitOnWriteAsyncToFinish
06 sqllang!write_data
07 sqllang!flush_buffer
08 sqllang!CTds74::SendRowImpl
09 SqlTsEs!CEsExec::GeneralEval4
0a sqllang!CXStmtQuery::ErsqExecuteQuery
0b sqllang!CXStmtSelect::XretExecute
0c sqllang!CExecStmtLoopVars::ExecuteXStmtAndSetXretReturn
0d sqllang!CMsqlExecContext::ExecuteStmts<1,0>
0e sqllang!CMsqlExecContext::FExecute
0f sqllang!CSQLSource::Execute
10 sqllang!process_request
11 sqllang!process_commands_internal
12 sqllang!process_messages
13 SqlDK!SOS_Task::Param::Execute
14 SqlDK!SOS_Scheduler::RunTask
15 SqlDK!SOS_Scheduler::ProcessTasks
16 SqlDK!Worker::EntryPoint
17 SqlDK!ThreadScheduler::RunWorker
18 SqlDK!SystemThreadDispatcher::ProcessWorker
19 SqlDK!SchedulerManager::ThreadEntryPoint
<frame id="28" address="0x776D11E7" />
1d WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
1e ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
据我所知,查询正在处理并进入多个状态和等待,例如分配给调度程序。但是这些信息如何帮助我们了解导致超时的原因呢?事实上,在我看来,一切都很顺利。
调用堆栈没有任何上下文(您看不到任何东西的状态),它只是线程作为该程序的一部分所采用的路径。有时这些很有用,有时却没有。
在这种情况下,调用堆栈相当良性,你是对的。您必须使用逻辑推理能力,根据客户端应用程序、SQL 日志以及任何其他可能有帮助的可用数据来找出可能发生的情况。
框架
0x19
-0x13
是样板任务执行。框架
0x12
-0x10
是用于处理传入服务器的请求的样板。框架
0x0f
-0x0a
只是处理来自语言源的选择语句。帧
0x08
-0x03
将数据发送回客户端并等待数据发送或已收到的确认。框架
0x02
-0x00
将这个工作人员移出running
和移入suspended
(等待),同时交换新的runnable
工作人员(idle
如果没有runnable
项目,则交换线程)。如果您根据上述数据在没有上下文的情况下进行一些疯狂的猜测,可能是连接已断开、客户端(或驱动程序)发送了注意、IO 等待时间过长且超时而中止本身等
这有什么帮助?不确定,取决于您从客户端或其他工具收集了多少数据。就像网络捕获一样,仅从一侧获取数据通常没有多大帮助,您需要同时从两侧获取数据以了解每一方的想法以及问题可能发生的位置/原因。