手动 AG 故障转移后超出最大工作线程数

Fre*_*gen 3 troubleshooting availability-groups sql-server-2016

我们有两个 SQL Server 2016 SP2 CU6 Enterprise 在物理硬件(32 核)上运行,其中一个 AG 包含 5 db。二级不可读。今天我们做了一个有计划的手动故障转移,所以我们可以在另一台服务器上做维护工作。我们在没有重负载的情况下进行了故障转移。

故障转移是通过 SSMS 的 GUI 执行的,没有出现错误。但是几分钟后,我们接到了很多用户无法登录的电话。我们第一次尝试进行故障排除是与 SSMS 建立连接,但这给出了我们无法连接的错误,我不记得确切的错误消息。

接下来我们在记事本中查看错误日志文件,它就像SQL Server引擎挂起一样。故障转移后没有新条目添加到日志中。

由于问题的紧迫性,我们重新启动了主服务器上的 SQL Server 服务,问题消失了。
我们本可以尝试建立 DAC 连接以查看问题所在,但目的是让服务器尽快恢复在线状态。

一切恢复正常后,我们开始分析日志文件。
在旧主服务器的错误日志中,我们发现了几个错误 35278。在故障转移时没有长时间运行的事务在运行。

接下来是 AlwaysON_health 事件文件,这里的条目在故障转移后刚刚停止。

接下来我们看了一下*_*_SQLDIAG_*_*.xel文件。在这里,我们很幸运。

我们注意到的第一件事是:

<queryProcessing maxWorkers="960" workersCreated="1064"
 workersIdle="23" tasksCompletedWithinInterval="19" pendingTasks="34"
 oldestPendingTaskWaitingTime="1316776"
Run Code Online (Sandbox Code Playgroud)

由于某种原因,超过了最大工人数量,这可以解释为什么没有人可以连接。

这是待处理的任务:

<pendingTasks><br>
   <entryPoint name="Process Command" count="14" /><br>
   <entryPoint name="SNI New Connection" count="2" /><br>
   <entryPoint name="SNI Accept Done" count="3" /><br>
   <entryPoint moduleName="sqlmin.dll" imageBase="0x7ff827e80000" size="0x251e000" address="0x7ff8286622e0" count="6" /><br>
   <entryPoint moduleName="sqlmin.dll" imageBase="0x7ff827e80000" size="0x251e000" address="0x7ff8292b1190" count="2" /><br>
   <entryPoint moduleName="sqldk.dll" imageBase="0x7ff827120000" size="0x4c9000" address="0x7ff827125e60" count="7" />  <br>
</pendingTasks>
Run Code Online (Sandbox Code Playgroud)

该文件中还有几个被阻止的进程。他们都有一个waitresource该样DATABASE: 5:5DATABASE: 5:15DATABASE: 5:26,...
这些过程都有lastbatchstarted,并lastbatchcompleted设置为1900-01-01。等待时间等于故障转移发生的时间。
在我们的监控中,我们看到总共有 950 个被阻塞的进程。

这是阻塞进程报告的示例:

<blocked-process-report monitorLoop="0">
 <blocked-process>
  <process id="process13f08032ca8" taskpriority="0" logused="10000" waitresource="DATABASE: 5:3 " waittime="1334205" schedulerid="4" kpid="11752" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="1900-01-01T00:00:00" lastbatchcompleted="1900-01-01T00:00:00" lastattention="1900-01-01T00:00:00" clientapp="our_app" hostname="host2021" hostpid="14196" loginname="user1" isolationlevel="read committed (2)" xactid="0" currentdb="1" currentdbname="master" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack />
   <inputbuf>
   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process status="suspended" waitresource="DATABASE: 5:3 " waittime="1335893" spid="70" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="1900-01-01T00:00:00" lastbatchcompleted="1900-01-01T00:00:00" lastattention="1900-01-01T00:00:00" clientapp="our_app" hostname="host1" hostpid="1324" loginname="user1" isolationlevel="read committed (2)" xactid="0" currentdb="1" currentdbname="master" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack />
   <inputbuf>
   </inputbuf>
  </process>
 </blocking-process>
</blocked-process-report>
<blocked-process-report monitorLoop="0">
 <blocked-process>
  <process id="process13f08033848" taskpriority="0" logused="10000" waitresource="DATABASE: 5:3 " waittime="1335893" schedulerid="4" kpid="12004" status="suspended" spid="70" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="1900-01-01T00:00:00" lastbatchcompleted="1900-01-01T00:00:00" lastattention="1900-01-01T00:00:00" clientapp="our_app" hostname="host1" hostpid="1324" loginname="user1" isolationlevel="read committed (2)" xactid="0" currentdb="1" currentdbname="master" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack />
   <inputbuf>
   </inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process status="background" waittime="1139955" spid="141" sbid="0" ecid="0" priority="0" trancount="0">
   <executionStack />
   <inputbuf>
   </inputbuf>
  </process>
 </blocking-process>
</blocked-process-report>
Run Code Online (Sandbox Code Playgroud)



其中一个阻塞进程以用户身份执行SA并具有 command UNKNOWN TOKEN。在last_wait_type这个会议的是PARALLEL_REDO_WORKER_WAIT_WORK,有一个last_request_start_time是等于我们做的故障切换时间。
我没想到会在主服务器上找到这种等待类型。
说不PARALLEL_REDO_WORKER_WAIT_WORK应该在主要的情况下是正确的吗?

同样在我们的监控中,我们发现了大约 1000 个具有状态SLEEPING且具有last_request_start_time01/01/1900 的会话。
这看起来一点都不正常。

有人可以解释那些待处理的任务是什么吗?
我对根本原因的猜测是 1000 个具有 status 的会话SLEEPING,它们都使用了一个工人。这导致了挂起的任务,并且由于阻塞过程,没有工人可以做任何工作。这导致某处的故障转移卡住了。
这是正确的吗?

Sea*_*ser 6

由于问题的紧迫性,我们重新启动了主服务器上的 SQL Server 服务,问题消失了。

由于没有完成调查或数据收集,很难准确说出当时发生了什么。

由于某种原因,超过了最大工人数量,这可以解释为什么没有人可以连接。

是的,出于某种原因,我们没有关于该原因的任何数据:( 看起来服务器有 32 个处理器,这应该足以处理可用性组中的 5 个数据库。还有更多我们要么不做的'不知道或者你不解释。

说不PARALLEL_REDO_WORKER_WAIT_WORK应该在主要的情况下是正确的吗?

由于我们不知道这方面的数据库上下文,因此无法说。我会说,如果有只是一个单一的可用性组和这种情况下是主要的则没有,就不能期望。但是,如果还有我们不知道的其他可用性组并且这是次要的,那么是的,这是意料之中的。同样,我们没有所有的信息。这还假设在任何数据库上都没有需要排空的重做队列——我们也不知道或没有这些信息。

有人可以解释那些待处理的任务是什么吗?

Process Commands尝试连接上执行的东西。在SNI*正在作出新的连接。

还有一个阻塞进程,经过我们的监控,这个进程是以用户身份执行的,SA并且有命令UNKNOWN TOKEN

它阻塞了多少个会话?挡住了什么?等等。同样,缺乏信息所以不能说它是否是什么。

同样在我们的监控中,我们发现大约 1000 个会话状态为 SLEEPING,并且 last_request_start_time 为 01/01/1900。这看起来一点都不正常。

他们从哪里来?他们上次跑了什么?如果您有一个可读的辅助副本并且有人想要运行一堆报告或查询,这可能是正常的。再次,需要更多信息。

这是正确的吗?

它可能是。很明显,你的工作线程用完了,这种情况如何以及为什么发生是未知的,因为没有足够的数据。

在我们的监控中,我们看到总共有 950 个被阻塞的进程。

这是你的根本问题。看起来clientapp="our_app"已连接(全部在 master 中)并且正在对数据库进行某种类型的查询。似乎数据库还没有完成重做(因此是等待类型),并且您的所有会话都相互备份。