服务器上的MSDTC不可用

59

我在SQL Server上遇到了一个奇怪的错误。在早期帖子中我找不到解决方案。

以下是我的存储过程:

create proc _upJM_SyncAll_test
as
begin
    DECLARE @SQLString nvarchar(max)

set @SQLString = N'
DELETE FROM OPENQUERY([LOCAL_MYSQL],''SELECT acSubject FROM _utjm_setitemprices'') where acSubject not in (select acSubject from _uvJM_SetSubj)
DELETE FROM OPENQUERY([LOCAL_MYSQL],''SELECT acSubject FROM _utjm_setsubj'') where acSubject not in (select acSubject from _uvJM_SetSubj)

update a
set acName2 = b.acName2,
    acName3 = b.acName3,
    acAddress = b.acAddress,
    acPost = b.acPost,
    acPostName = b.acPostName, 
    acCountry = b.acCountry, 
    acVATCodePrefix = b.acVATCodePrefix,
    acCode = b.acCode, 
    anDaysForPayment = b.anDaysForPayment
from OPENQUERY([LOCAL_MYSQL],''SELECT * FROM _utjm_setsubj'') a join _uvJM_SetSubj b on (a.acSubject = b.acSubject)
where 1=1
and (   isnull(a.acName2,'''') <> isnull(b.acName2,'''') OR 
        isnull(a.acName3,'''') <> isnull(b.acName3,'''') OR 
        isnull(a.acAddress,'''') <> isnull(b.acAddress,'''') OR 
        isnull(a.acPost,'''') <> isnull(b.acPost,'''') OR 
        isnull(a.acPostName,'''') <> isnull(b.acPostName,'''') OR 
        isnull(a.acCountry,'''') <> isnull(b.acCountry,'''') OR 
        isnull(a.acVATCodePrefix,'''') <> isnull(b.acVATCodePrefix,'''') OR 
        isnull(a.acCode,'''') <> isnull(b.acCode,'''') OR 
        isnull(a.anDaysForPayment,'''') <> isnull(b.anDaysForPayment,'''')
)

insert into OPENQUERY([LOCAL_MYSQL],''SELECT * FROM _utjm_setsubj'') (acSubject, acName2, acName3, acAddress, acPost, acPostName, acCountry, acVATCodePrefix, acCode, anDaysForPayment)
select b.acSubject, b.acName2, b.acName3, b.acAddress, b.acPost, b.acPostName, b.acCountry, b.acVATCodePrefix, b.acCode, b.anDaysForPayment
from OPENQUERY([LOCAL_MYSQL],''SELECT * FROM _utjm_setsubj'') a right join _uvJM_SetSubj b on (a.acSubject = b.acSubject)
where a.acSubject is null '

EXECUTE sp_executesql @SQLString;
end

当我在管理工作室中运行这样的过程时:
  exec dbo._upJM_SyncAll_test

一切都很好。我没有收到错误消息,同步也正常工作。

但是当我像这样在触发器中执行时:

create trigger _utrJM_SetSubj on tHE_SetSubj after insert, update, delete
as
begin
    exec dbo._upJM_SyncAll_test
end

我遇到了这个错误:

Msg 8501, Level 16, State 3, Procedure _upJM_SyncAll_test, Line 54
服务器上的 MSDTC 不可用。

_upJM_SyncAll_test 过程仅有 39 行...


你为什么要使用动态SQL呢?似乎并不必要。 - Lamak
好的,就像这样... 链接服务器[LOCAL_MYSQL]已经启动并运行,但有可能会出现无法访问的情况。在这种情况下,如果sp_executesql返回错误,我会执行其他操作。请注意,_upJM_SyncAll_test只是本文的测试过程,而_upJM_SyncAll则更为复杂。 - Kiki
9个回答

147

在我的情况下,该服务已经停止。 解决方法:需要启动MSDTC服务。

  1. 进入服务。(开始>设置>控制面板>管理工具>服务)
  2. 找到名为'分布式事务协调器'的服务,右键单击(并选择)> 启动
  3. 将此服务设置为自动运行,以永久解决此问题。

9
此外,将服务设置为自动启动可能会很有用。右键单击服务 -> 属性 -> 启动类型,选择“自动”。否则,每次您的机器重新启动(或服务因任何原因停止)都需要手动设置。 - Rob
这是一个比被接受的答案更好、更简单的解决方案。 - static_void

24

触发器包含在插入、更新和删除语句所需的隐式事务中。由于您在事务中连接到了一个链接服务器,因此SQL Server会将其升级为分布式事务。

您需要配置MSDTC,可以打开MMC并加载MSDTC插件,也可以使用以下脚本打开入站和出站事务。

https://technet.microsoft.com/en-us/library/cc731495.aspx

REG QUERY "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccess
REG QUERY "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessTransactions
REG QUERY "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessInbound
REG QUERY "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessOutbound
PAUSE

REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /f /v NetworkDtcAccess /t REG_DWORD /d 1
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /f /v NetworkDtcAccessTransactions /t REG_DWORD /d 1
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /f /v NetworkDtcAccessInbound /t REG_DWORD /d 1
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /f /v NetworkDtcAccessOutbound /t REG_DWORD /d 1
PAUSE

net stop MSDTC
net start MSDTC
PAUSE

1
第一次暂停后,您可以将/f选项添加到所有命令中:“强制覆盖现有的注册表条目而不提示。”否则,这将无法正常工作。除此之外,这个工作完美,谢谢! - codea
感谢提供的 Technet 链接。我按照其中的说明解决了我的问题。 - Rich
一个问题是启动 MSDTC,但是什么是“打开入站和出站事务”以及为什么需要它? - Jim Aho

23
我遇到了同样的错误,但问题并不像分布式事务协调器服务没有运行那么简单。我通过Windows自动收到了一个驱动程序更新,导致COM+出现问题,即使MSDTC服务正在运行也无法正确通信。我的情况是HP热键驱动程序出了问题,但我在研究中发现其他制造商的音频驱动程序也会导致此类问题。
要检查您是否有类似的问题,请启动组件服务(dcomcnfg.exe),然后展开“组件服务> 计算机>我的计算机”,从这里单击“COM +应用程序”,以查看是否会弹出错误消息“COM +无法与Microsoft Distributed Transaction Coordinator通信”,或者导航中的“My Computer”图标上将出现红色错误。
对我而言,解决方法是禁用“HP Hotkey Service”和“HotKeyServiceUWP”服务。一旦这些服务被禁用,MSDTC立即开始工作。

1
老兄,你的解决方案真是救了我一命。非常感谢! - Oleks
非常感谢!这让我开始怀疑是联想造成的问题。结果发现需要暂时禁用 LenovoSmartStandby 服务才能解决。请参阅此链接以获取更多信息。 - Frank Fu
1
天啊!我遇到了完全相同的问题,这种几率有多小啊!非常感谢你! - Alex
2
在我的情况下 - Lenovo ThinkPad P52 - 原因是“Dolby DAX API Service”。 - nzeemin
2
禁用所有HP服务对我有用,错误消失了。(在Win 10上测试过) - mggSoft
显示剩余5条评论

4

通过禁用冲突的服务/驱动程序,解决了我的问题。我禁用了所有的HP服务(HP应用程序助手、HP CASL、HP系统信息),现在它可以正常工作。


1
"HP 打印和扫描医生" - Mark Sowul

1
“分布式事务协调器”服务未运行,因此启动了该服务并将服务类型更改为自动。

0

Powershell 解决方案:

Get-Service -Name MSDTC | Set-Service -StartupType Automatic

0

我遇到了与Azure SQL相关的同样问题。(在这里发布一下,以防有人遇到同样的Azure SQL问题。) 原因是在连接启用了Azure中的Read Scale Out选项的Azure SQL DB时,应用程序意图被设置为只读选项(ApplicationIntent=ReadOnly)。

为了快速解决,我们从应用程序中删除了ApplicationIntent=ReadOnly配置。

要了解更多信息以及正确的解决方案,请参阅以下链接:

https://techcommunity.microsoft.com/t5/azure-database-support-blog/lesson-learned-173-msdtc-on-server-xxxxx-is-unavailable/ba-p/2376529


0

最近在我的工作机器上出现了这个问题(Win 10,MSSQL 2016 SP2 Express)。我没有链接服务器。这个问题突然出现了。MSDTC服务正在运行,MSSQL使用Mgmt Studio正常工作。然而,我的.NET 4.7.1单元测试应用程序拒绝连接数据库,并显示“MSDTC on server '...' is unavailable”错误。

我找到的临时解决方法是在连接字符串的末尾添加“Enlist=False;”,以避免完全使用MSDTC进行连接。

这个解决方案的来源是这个主题下的评论:https://learn.microsoft.com/en-us/archive/blogs/distributedservices/intermittent-error-msdtc-on-server-servername-is-unavailable


0
在我的情况下,我有一个位于远程服务器上的Microsoft SQL Server的命名实例,我的应用程序的错误输出如下:
System.Data.SqlClient.SqlException (0x80131904): MSDTC on server 'SERVER\INST_NAME' is unavailable.

尝试更改SQL连接字符串,例如将SERVER\INST_NAME替换为SERVER,TCP_PORT_NUMBER并没有帮助。我仍然遇到了相同的错误,于是决定安装默认实例(MSSQLSERVER),使SQL Server名称变为仅为SERVER。这解决了问题,因为RPC和MSDTC开始解析名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接