
我们首先了解下X/Open这个组织,它是由UNIX系统制造商在1984年确定并推广信息技术领域的开放标准。最初是为UNIX操作系统定义的单项规范,以提高应用程序的互操作性并降低移植软件的成本。也就是X/Open 分布式事务处理 (X/Open DTP) ,X/Open DTP XA 标准定义了资源管理器用于与事务管理器通信的应用程序编程接口。XA 接口使资源管理器能够加入事务、执行两阶段提交以及在失败后恢复有疑问的事务。
X/Open 分布式事务处理 (DTP) 模型主要组件:
应用程序(AP)定义事务边界(开始结束),并定义构成事务的特定于应用程序的操作。
事务管理器 (TM) 为事务分配标识符,监视它们的进度,并对事务的完成和失败负责。
资源管理器 (RM) 提供对共享资源(例如实例、数据库)的访问。

From IBM
Microsoft 分布式事务协调器 (MSDTC) DTC 提供了与符合 X/Open DTP XA 标准的产品的互操作性衡量标准。DTC XA 映射器允许符合 OLE 事务的资源管理器参与由符合 XA 的事务管理器协调的事务。Microsoft 分布式事务协调器 (MS DTC) DTC 可以充当 XA 兼容的资源管理器或事务管理器。当 DTC 充当 XA 兼容资源管理器时,它允许 SQL Server、消息队列(也称为 MSMQ)和其他 OLE 事务兼容资源管理器参与由 X/Open DTP XA 兼容事务控制的事务处理监视器。当 DTC 充当符合 XA 的事务管理器时,Oracle、IBM DB/2、Sybase、Informix 和其他符合 XA 的资源管理器可以参与 DTC 控制的事务。当 DTC 显示跨 XA 兼容资源管理器的事务的信息时,DTC 不显示事务的 XID。相反,它显示事务的 OLE 事务工作单元标识符 (UOW)。 https://publications.opengroup.org/c193部署过Windows故障转移集群实例(Windows FCI,Windows Failover Cluster Instance)的同学应该都会配置MSDTC ,你知道MSDTC 如何工作、有什么影响吗?当我们在一个数据库中跨另一个数据库进行操作时,就涉及到了分布式事务。如链接服务器(linked servers)跨实例操作,或者同一个实例跨数据库操作。在默认情况下,系统使用的是本地MSDTC,但在应用的高可用集群中(如 AlwaysOn FCI、AlwaysOn AG),就需要集群MSDTC来维护分布式事务的完整性。(此处的FCI、AG、DB作为资源管理器,MSDTC作为事务管理器)
只有本地 MSDTC。当我们的应用程序运行一个事务,在该服务器(或者另一台服务器)上的数据库中插入记录时,本地 MSDTC 会加入该事务。MSDTC的工作是记录事务并确保任何有疑问的事务被中止(回滚)或提交(前滚)。可以选择使用本地 MSDTC 或集群 MSDTC。配置群集 MSDTC 配置比较简单,需要共享存储。当主节点宕机时,SQL实例资源和群集 MSDTC 都会故障转移到备节点,由于集群 MSDTC 使用共享存储,因此它仍然具有日志并可以处理任何有疑问的事务。如果使用本地 MSDTC,意味着MSDTC 没有高可用。当主节点故障,本地 MSDTC 存在不确定事务。故障转移后,新的主节点的本地 MSDTC 会尝试联系旧主节点的本地 MSDTC 并检索任何可疑事务的状态。如果尝试3次都无法联系旧的主节点,则 SQL 实例将从sp_configure 中配置的“in-doubt xact resolution”来执行响应的操作。sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
sp_configure 'in-doubt xact resolution'
GO
in-doubt xact resolution 有3个配置值(更改立即生效):
in-doubt xact resolution默认为0,如果集群使用本地MSDTC,并且使用分布式事务时主节点宕机,备节点数据库将出现可疑状态无法恢复。这时候必须强制事务提交或中止以释放锁才能使数据库资源可用。运行命令“dcomcnfg”或者 “comexp.msc” 打开“服务组件” —> 计算机 —> 我的电脑 —> 分布式事务协调器—> 本地DTC/集群 DTC —> 事务列表 —> 右键要处理的事务 —> 解析 —> 提交/中止/忽略。

也可以使用 KILL 命令手动解决有疑问的事务并使数据库联机。
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH COMMIT
KILL 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' WITH ROLLBACK
ALTER DATABASE [DB] SET ONLINE
MSDTC 在可用性组中的工作方式与在 AlwaysOn FCI 中的工作方式完全相同。 | |
| |
| 支持跨实例事务; 不支持同一个实例内的跨数据库事务; |
| |
第二个区别是使用 DTC_SUPPORT = PER_DB。AlwaysOn AG 在创建的时候可通过WITH DTC_SUPPORT = PER_DB 子句创建可用性组,也可通过 ALTER 语句更改此设置。在AlwaysOn FCI中,实例本身成为资源管理器,每个实例都会创建一个具有唯一资源管理器标识符 (RMID) 的资源管理器并将其注册到 DTC。但在AlwaysOn AG中,每个数据库都成为自己的资源管理器,若要在故障转移中支持分布式事务,每个数据库都应充当单独的资源管理器,并且必须具有唯一的 RMID。当可用性组具有 DTC_SUPPORT = PER_DB 时,SQL Server 将为每个数据库创建资源管理器,并且使用唯一的 RMID 将它们向 DTC 注册。在此配置中,数据库充当于 DTC 事务的资源管理器。(注意,每个分布式事务的 DTC 不超过 32 个登记,如果你的事务涉及到 32 个以上的数据库则发生报错)对于应用程序而言,管理分布式事务很像管理本地事务。当事务结束时,应用程序会请求提交或回滚事务。不同的是,分布式提交必须由事务管理器管理,以尽量避免出现因网络故障而导致事务由某些资源管理器成功提交,但由另一些资源管理器回滚的情况。通过分两个阶段(准备阶段和提交阶段)管理提交进程可避免这种情况,这称为两阶段提交。
SQL Server 在启动时将登记哪个 MSDTC 协调器呢?在Windows Server 2016以前的版本中,用通过服务组件打开我的电脑属性,可用看到是否使用本地协调器。
若要禁用本地DTC,不选择即可,但需要集群的DTC。在Windows 2016 版本中,可用禁用该 Distributed Transaction Coordinator 服务。在集群中,如果有分布式事务,我建议大家都使用集群MSDTC而不是本地MSDTC。SQL 实例仅在启动时向 MSDTC 协调器登记一次,并且不会再次尝试。在 AG 中如果启用WITH DTC_SUPPORT = PER_DB,则每个数据库启动时都会登记。如果群集中运行多个 SQL Server 实例,并且只创建一个群集 MSDTC,那么每个实例都使用相同的 MSDTC。如果您有大量分布式事务,这可能会成为瓶颈。在AlwaysOn FCI中,我们可以为每个实例创建一个 MSDTC,在通过msdtc.exe手动映射到响应的SQL实例。msdtc -tmMappingView *
msdtc -tmMappingSet -name MyMSDTC -service MSSQLServer -ClusterResourceName ClusterDTC
msdtc -tmMappingClear -name MyMSDTC
BEGIN DISTRIBUTED TRANSACTION
/*
COMMIT TRANSACTION;
ROLLBACK TRANSACTION;
*/
这里我打开一个分布式事务,当并未提交或回滚。在组件服务中,我们可用查看事务相关统计
