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;
エラー処理部分 (begin try/begin catch) と派手な @@fetch_status チェック (実際には静的カーソルは必要ありません) を省略しました。このデモ コードは、実行中にいくつかの異なるトランザクションが開始されることを示しています (異なるトランザクション ID)。多くの場合、バッチは処理される各アイテムにトランザクション セーブポイントも展開するため、リンクにあるパターンと同様のパターンを使用して、例外を引き起こすアイテムを安全にスキップできますが、セーブポイントと DTC が混在しないため、これは分散トランザクションには適用されません。 .