2015-04-02 34 views
32

我在SQL Server上出现这个奇怪的错误。而且我在旧帖子中找不到解决方案。服务器服务器上的MSDTC不可用

我有这样的过程:

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 on server 'server' is unavailable.

程序_upJM_SyncAll_test只有39行...

+0

为什么你首先使用动态SQL ?,看起来好像没有必要 – Lamak 2015-04-02 13:32:55

+0

好像这样..链接服务器[LOCAL_MYSQL]启动并运行,但它可能会发生,无法访问。在这种情况下,如果sp_executesql返回错误我做了别的..请注意,_upJM_SyncAll_test只是测试过程中的这篇文章,_upJM_SyncAll更复杂。 – Kiki 2015-04-02 13:43:34

回答

17

触发器都包括在插入,更新和删除语句所需的隐式事务。由于您正在连接到事务内的链接服务器,因此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" /v NetworkDtcAccess /t REG_DWORD /d 1 
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessTransactions /t REG_DWORD /d 1 
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessInbound /t REG_DWORD /d 1 
REG ADD "HKLM\Software\Microsoft\MSDTC\Security" /v NetworkDtcAccessOutbound /t REG_DWORD /d 1 
PAUSE 

net stop MSDTC 
net start MSDTC 
PAUSE 
+1

第一次暂停后,可以将/ f选项添加到所有命令:“强制覆盖现有注册表项而不提示。”否则这将无法正常工作。除此之外,这个工作完美,谢谢! – codea 2015-12-02 13:17:16

+0

感谢您的technet链接。我按照其中的说明解决了我的问题。 – Rich 2017-07-10 18:37:23

88

在我的情况下,服务被停止。解决方法:需要打开MSDTC服务

  1. 转到服务。 (开始>设置 - >控制面板 - >管理工具>服务)
  2. 查找(它并选择)被称为“分布式事务处理协调”和 右键单击服务>开始
  3. 使这个服务过解决这个问题的永久
+7

此外,自动启动服务可能很有用。右键单击服务 - >属性 - >启动类型并选择'自动'。否则,每次重新启动计算机时都需要执行此操作(或者因为任何原因停止服务) – Rob 2016-09-22 04:45:40

+0

谢谢。也为我工作。 – 2017-12-21 10:48:34

0

“分布式事务处理协调器”服务没有运行,所以启动的服务和改变服务类型设置为自动运行自动