在我们知道如何处理这些负面会话之前,我们需要知道它们是什么以及它们是如何引起的。有不同的负值,在本技巧中,我们将重点介绍 -2 值的 SPID。
SPID 等于 -2 的会话是孤立的分布式事务。分布式事务是调用托管在不同服务器上的数据库的数据库事务。孤立的,也称为不确定的 MSDTC 事务,是具有未知事务状态的 Microsoft 分布式事务,因为 MSDTC 服务由于 MSDTC 服务崩溃或意外重启而无法正确识别它。
首先要排除故障的是 MSDTC 本身。通过在服务器上的 Windows 运行框中键入dcomcnfg转到组件服务。
在组件服务中,浏览到计算机 -> 我的电脑 -> 分布式事务协调器 如下所示。然后找到相应的 DTC 服务。下面你可以看到有几个在这个服务器上运行,本地 DTC 和集群 DTC。获得正确的 DTC 后,转到交易统计并查看 当前部分中的不确定交易,如下所示:
如果发现一个In Doubt不为 0的值,转到 transaction list,可以看到这些标记为不确定的事务。右键单击此事务并选择Resolve (如下图所示中止) 。
如果没有发现 In Doubt 中的事务或该进程仍在 SQL Server 中运行,该怎么办?
在这种情况下,事务仍在进行中,但 MSDTC 看不到它,因为它失去了对事务的跟踪,因此它不会显示为内部进程。现在我们必须使用 SQL Server 来处理它,因为事务仍在访问资源并阻塞数据库资源。如果 SQL Server 没有提交或回滚事务的信息,阻塞将不会停止。
解决此类问题的旧方法是重新启动 SQL Server。但是现在我们只需要另一种方法来终止这个会话,但我们不能使用它的 SPID,因为它是负数。
为了杀死这些负 SPID,我们需要使用工作单元 ID,它是由 MSDTC 分配给事务的 24 个字符的 GUID。这个值之所以有用是因为它在操作系统和 SQL Server 引擎之间是通用的。
为了检索此值,我们将使用以下查询在sys.dm_tran_locks 系统表中查询 request_session_id 等于 -2 的会话:
USE Master; GO SELECT DISTINCT(request_owner_guid) as UoW_Guid FROM sys.dm_tran_locks WHERE request_session_id =-2 GO
获得 GUID 后,您可以将此值与 KILL 语句一起使用,如下所示:
KILL 'EB159BBE-B3D5-4F25-971A-F221F09188E1' -- 用上面查询中的 UoW_Guid 值替换 GUID 值
这应该会终止会话,现在会话不再被阻止并且孤立事务停止。