次のように、トリガーを定義したMyTable
というテーブルがあります。
CREATE TRIGGER dbo.trg_Ins_MyTable
ON dbo.MyTable
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
insert SomeLinkedSrv.Catalog.dbo.OtherTable
(MyTableId, IsProcessing, ModifiedOn)
values (-1, 0, GETUTCDATE())
END
GO
MyTable
に行を挿入しようとすると、次のエラーメッセージが表示されます。
メッセージ3910、レベル16、状態2、行1別のセッションで使用中のトランザクションコンテキスト。
リンクサーバーとして適切に定義されたSomeLinkedSrv
があります(たとえば、select * from SomeLinkedSrv.Catalog.dbo.OtherTable
は問題なく動作します)。
エラーを回避し、レコードを挿入してトリガーを実行するにはどうすればよいですか?
MARSが有効になっている場合、ループバックリンクサーバーは分散トランザクションで使用できません。
ループバックリンクサーバーは、分散トランザクションでは使用できません。分散トランザクション内からループバックリンクサーバーに対して分散クエリを試行すると、エラー3910: "[Microsoft] [ODBC SQL Server Driver] [SQL Server] Transaction context in use by another session。"などのエラーが発生します。複数のアクティブな結果セット(MARS)が有効になっていない接続によって発行されたINSERT ... EXECUTEステートメントがループバックリンクサーバーに対して実行される場合、この制限は適用されません。接続でMARSが有効になっている場合でも、制限が適用されることに注意してください。
http://msdn.Microsoft.com/en-us/library/ms188716(SQL.105).aspx
ストアドプロシージャで使用されているリンクサーバーを削除し、同じリンクサーバーでストアドプロシージャを呼び出して解決しました。それはDEV環境で働いていませんでした。
解決します。同じリンクサーバーを使用して2番目のプロシージャを呼び出し、その後、同じリンクサーバーを使用していたプロシージャを呼び出しました。
それは非常に簡単です。リンクサーバーの制限を知る必要があるだけです。
リモートデータベースが同じサーバー上にある場合は、データベースサーバーのIP /ホスト名とポートを指定せずにリンクサーバーを構成します。データベース名だけで十分です。
UPDATEクエリを実行しようとすると、同じトランザクションコンテキストが別のセッションエラーで使用されていました。
BEGIN TRAN
--ROLLBACK TRAN
--COMMIT TRAN
UPDATE did
SET did.IsProcessed = 0,
did.ProcessingLockID = NULL
FROM [proddb\production].DLP.dbo.tbl_DLPID did (NOLOCK)
WHERE did.dlpid IN ('bunch of GUIDs')
--WHERE did.DLPID IN (SELECT DLPID FROM @TableWithData)
しかし、ProdDb\ProductionサーバーのDLPデータベースでこれをすでに実行しようとしていることに気付きませんでした。その「[proddb\production] .DLP.dbo」を削除したら、クエリからのプレフィックス、それはうまくいきました。
私の場合、SQL 2005を使用していて、リンクサーバーでInsert .... execを実行すると、「別のセッションで使用されているトランザクションコンテキスト」が表示されました。私に対する修正は、SP2ビルド3161からSP3にパッチを適用することでした。 SP2累積5は修正されるはずです。
DEV環境でも同じエラーが発生し、リンクされたデータベースを別のSQLインスタンスに移動すると問題が解決しました。本番環境では、これらのデータベースはすでに別のインスタンスにあります