我有一个要通过链接服务器执行的查询。查询看起来像这样:
USE db1;
SET xact_abort ON;
DECLARE @statement NVARCHAR(max);
SET @statement = 'EXECUTE (''INSERT INTO T1(V1, V2) VALUES (1, 2)'') AT LS1';
BEGIN try
BEGIN TRANSACTION
EXEC Sp_executesql @statement
COMMIT TRANSACTION
END try
BEGIN catch
IF ( Xact_state() ) = -1
BEGIN
PRINT Error_message()
ROLLBACK TRANSACTION
END
IF ( Xact_state() ) = 1
BEGIN
PRINT 'COMMIT OPEN TRANSACTION'
COMMIT TRANSACTION
END
INSERT INTO tblerrmsg (errornumber, errorseverity, errorstate, errorline, errormessage) EXECUTE Usp_geterrorinfo;
END catch
此操作失败,并在我的TblErrMsg表中添加了一个条目。
错误编号= 8501,错误严重性= 16,错误状态= 3,错误行= 1,错误消息=服务器“ XXX”上的MSDTC不可用。
因此,我研究了特定的错误消息,并检查了服务器上是否正在运行“分布式事务处理协调器服务”,但是情况已经如此。即使重新启动服务也没有带来任何变化。接下来,我尝试删除该事务并执行以下过程:
USE db1;
DECLARE @statement NVARCHAR(max);
SET @statement = 'EXECUTE (''INSERT INTO T1(V1, V2) VALUES (1, 2)'') AT LS1';
BEGIN try
EXEC Sp_executesql @statement
END try
BEGIN catch
PRINT Error_message()
END catch
这一次它起作用了。没有错误,并且INSERT也起作用。所以我想知道真正的问题是什么。显然,执行该过程或链接服务器连接似乎没有问题。
有人遇到过类似的问题,或者对此行为有解释吗?
答案 0 :(得分:0)
在指定显式事务时,您可能缺少关键字DISTRIBUTED。
代替
BEGIN TRANSACTION
尝试
BEGIN DISTRIBUTED TRANSACTION
根据Docs,这是指定“ ...由Microsoft分布式事务处理协调器(MS DTC)管理的Transact-SQL分布式事务的开始”的方式。
没有显式事务,默认行为afaik是跨链接服务器的事务不能保证是原子的,也不能回滚。这就是为什么在未指定显式事务的情况下它起作用的原因。
当指定的BEGIN TRANSACTION不带'DISTRIBUTED'语句时,该语句将询问该过程包含链接服务器引用时不可能发生的事情。