EXEC 过程不创建事务。一个非常简单的测试将显示这一点:
create procedure usp_foo
as
begin
select @@trancount;
end
go
exec usp_foo;
usp_foo 中的@@trancount 为0,因此EXEC 语句不会启动隐式事务。如果您在进入 UpdateRemoteServer 时启动了事务,则意味着有人启动了该事务,我不能说是谁。
话虽如此,使用远程服务器和 DTC 来更新项目的性能会很差。其他服务器至少也是 SQL Server 2005 吗?也许您可以对更新请求进行排队,并在本地和远程服务器之间使用消息传递,并让远程服务器根据消息中的信息执行更新。它将表现得更好,因为两个服务器只需要处理本地事务,并且由于排队消息的松散耦合,您可以获得更好的可用性。
更新
游标实际上不会启动事务。典型的基于游标的批处理通常是基于游标和批量更新到一定大小的事务。这对于通宵作业来说相当普遍,因为它可以提供更好的性能(由于更大的事务大小而导致日志刷新吞吐量)并且可以中断和恢复作业而不会丢失所有内容。批处理循环的简化版本通常如下所示:
create procedure usp_UpdateRemoteServer
as
begin
declare @id int, @batch int;
set nocount on;
set @batch = 0;
declare crsFoo cursor
forward_only static read_only
for
select object_id
from sys.objects;
open crsFoo;
begin transaction
fetch next from crsFoo into @id ;
while @@fetch_status = 0
begin
-- process here
declare @transactionId int;
SELECT @transactionId = transaction_id
FROM sys.dm_tran_current_transaction;
print @transactionId;
set @batch = @batch + 1
if @batch > 10
begin
commit;
print @@trancount;
set @batch = 0;
begin transaction;
end
fetch next from crsFoo into @id ;
end
commit;
close crsFoo;
deallocate crsFoo;
end
go
exec usp_UpdateRemoteServer;
我省略了错误处理部分(开始尝试/开始捕获)和花哨的@@fetch_status 检查(静态游标实际上并不需要它们)。此演示代码显示在运行期间启动了几个不同的事务(不同的事务 ID)。很多时候,批次还在处理的每个项目上部署事务保存点,以便他们可以安全地跳过导致异常的项目,使用类似于我链接中的模式,但这不适用于分布式事务,因为保存点和 DTC 不混合.