web-dev-qa-db-ja.com

リンクサーバー "linkedserver"の "SQLNCLI11"は、メッセージ "トランザクションマネージャーがリモート/ネットワークトランザクションのサポートを無効にしました。"を返しました。

SQL Server 2014 AGグループ(AG1)にデータベースがあります。-2つのノード。

両方のノードで、リンクサーバーがセットアップされます。 AGグループ(AG1)データベースのテーブルからデータを選択し、リンクサーバー(別のAGグループ(AG2)のデータベース)に挿入しています。トランザクションの唯一のステートメントは、挿入ステートメントです。分散トランザクションではありません。

次のエラーが発生するのはなぜですか?

リンクサーバー "LinkedserverListener"のOLE DBプロバイダー "SQLNCLI11"は、メッセージ "トランザクションマネージャーがリモート/ネットワークトランザクションのサポートを無効にしました。"を返しました。
メッセージ7391、レベル16、状態2、行2
リンクサーバー "LinkedServerListener"のOLE DBプロバイダー "SQLNCLI11"が分散トランザクションを開始できなかったため、操作を実行できませんでした。

サンプルコードは以下です。

Drop table #Myatran
Select 'ABC' name into #Myatran

DECLARE @pndstop_ps NVARCHAR(4000)
SET @pndstop_ps = 
N'
INSERT INTO '+ 'linkedserver'+'.DB.dbo.MyaTEST(Name) SELECT name FROM #Myatran
'
SET XACT_ABORT ON
BEGIN TRANSACTION

EXEC sp_executeSQl @pndstop_ps

SET XACT_ABORT OFF
1
AMMH

SQL Server 2014可用性グループ サポートしていません 分散トランザクション。

SQL Server 2016は 分散トランザクションのサポートに制限がありますが、SQL Server 2017が最もサポートされています

SQL Server Integration Services、bcp in/out、またはExtract-Transform-LoadまたはETL操作用のその他のツールの使用を検討してください。

ちなみに、あなたはこれに気づいていないかもしれませんが、INSERT INTO ...をリンクサーバー上のテーブルに挿入すると、ローカルSQL Serverが、ターゲットテーブルに挿入された各行に対して一連のカーソル呼び出しを実行します。

これを証明するために、リンクサーバーを作成し、次のコードを実行して簡単なテストベッドをセットアップしました。

まず、リンクサーバーのtempdbにテーブルを作成します。

DECLARE @cmd nvarchar(max);
SET @cmd = 'IF OBJECT_ID(''dbo.InsertTest'', N''U'') IS NOT NULL
DROP TABLE dbo.InsertTest;
CREATE TABLE dbo.InsertTest
(
    id int NOT NULL PRIMARY KEY CLUSTERED
);';

EXEC [LinkedServer].tempdb.sys.sp_executesql @cmd;

ここでは、いくつかの行を保持するためにtempdbにローカルテーブルを作成しています。

IF OBJECT_ID('dbo.InsertTest', N'U') IS NOT NULL
DROP TABLE dbo.InsertTest;CREATE TABLE dbo.InsertTest
(
    id int NOT NULL PRIMARY KEY CLUSTERED
);

INSERT INTO dbo.InsertTest (id)
SELECT ROW_NUMBER() OVER (ORDER BY c.object_id, c.column_id)
FROM sys.columns c;

ソーステーブルに行があるかどうかを確認する簡単なチェック:

SELECT CountOfRows = COUNT(1)
FROM dbo.InsertTest;
╔═════════════╗
║CountOfRows║
╠═════════════╣
║990 ║
╚═════════════╝

ここでは、ローカルのソーステーブルからリモートのリンクサーバーテーブルに行を挿入します。ターゲットサーバーで実行されるトレースを設定して、それに対して発行されたT-SQLステートメントを確認できるようにしました。

INSERT INTO [LinkedServer].tempdb.dbo.InsertTest (ID)
SELECT it.ID
FROM dbo.InsertTest it;

出力:

╔═════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════╗
║SET XACT_ABORT OFF║
╠═══════════════════════ ══════════════════════════════════════════════════ p 
║@ p1 int║[を宣言します。 ____。]║set @ p1 = NULL║
║declare @ p2 bigint║
║set @ p2 = NULL║
║exec [sys] .sp_getschemalock @ p1 output、@ p2 output、N '"tempdb"。 "dbo"。 "InsertTest"'║
║select @ p1、@ p2 p 
║declare @ p1 int║
║set @ p1 = NULL║
║declare @ p3 int║
║set @ p3 = 229378║
║declare @ p4 int║
║set @ p4 = 294916║
║declare @ p5 int║
║set @ p5 = NULL ║
║exec sp_cursoropen @ p1 output、N'select * from "tempdb"。 "dbo"。 "InsertTest" '、@ p3 output、@ p4 output、@ p5 output║
║select @ p1、@ p3、@ p4、@ p5║
║exec sp_cursor 180150027,4,0、N '[tempdb]。[dbo]。[InsertTest]'、@ id = 1║
║exec sp_cursor 180150027,4,0、N '[tempdb]。[dbo]。[InsertTest]'、@ id = 2║
║exec sp_cursor 180150027,4,0、N '[tempdb]。 [dbo]。[InsertTest] '、@ id = 3║
║exec sp_cursor 180150027,4,0、N' [tempdb]。[dbo]。[InsertTest] '、@ id = 4║
║exec sp_cursor 180150027,4,0、N '[tempdb]。[dbo]。[InsertTest]'、@ id = 5 
。
。
║exec sp_cursor 180150027,4,0、N '[tempdb]。[dbo]。[InsertTest]'、@ id = 987║
║exec s p_cursor 180150027,4,0、N '[tempdb]。[dbo]。[InsertTest]'、@ id = 988║
║exec sp_cursor 180150027,4,0、N '[tempdb]。[dbo] 。[InsertTest] '、@ id = 989║
║exec sp_cursor 180150027,4,0、N' [tempdb]。[dbo]。[InsertTest] '、@ id = 990║
 ║exec [sys] .sp_releaseschemalock 1║
║exec sp_cursorclose 180150027║
║exec sp_reset_connection║
╚════════════════ ══════════════════════════════════════════════════ ═══════════════════════════════════════════╝

ただし、次のようにターゲットサーバーから挿入を実行すると、

INSERT INTO dbo.InsertTest (ID)
SELECT it.ID
FROM [LinkedServer].tempdb.dbo.InsertTest it;

あなたはこれをトレースで見る:

╔════════════════════════╦════════════════════════ ════════════════════════╗
║TextData║。
╠══════════ ══════════════╬═══════════════════════════════════ ═════════════╣
║SET STATISTICS XML ON║║
║║INSERT INTO dbo.InsertTest(ID)║
║║SELECT it.ID║
║║FROM [CP708-D377\MV] .tempdb.dbo.InsertTest it; ║
║SET STATISTICS XML OFF║║
╚════════════════════════╩══════ ══════════════════════════════════════════╝

明らかに、ソースサーバーではなく、ターゲットサーバーで挿入を実行することは効果的です。

4
Max Vernon