web-dev-qa-db-ja.com

選択してリンクサーバーに挿入する

リンクサーバーで理解できない状況にあります。

したがって、2008R2サーバーから2014サーバーへのリンクサーバーがあります。以下のサンプルクエリは2008R2サーバーから実行されており、正常に動作します。

_SET XACT_ABORT ON;
 Declare @BatchSize int = 10
      DELETE from LINKEDSRV.DB.DBO.Table
      INSERT INTO LINKEDSRV.DB.DBO.Table (ECN)
      SELECT TOP (10) C1 from LINKEDSRV.DB.DBO.Table22 --order by C1
      SELECT * FROM LINKEDSRV.DB.DBO.Table
_

しかし、同じことを_order by C1_で実行すると、結果が返されません。

2番目のケース-TOP(10)TOP(@BatchSize)に置き換え、_order by_を使用しない場合も、結果が得られません。例えば

_SELECT TOP (@BatchSize) C1 from LINKEDSRV.DB.DBO.Table22 
_

私が_SET XACT_ABORT OFF_であれば、すべてのシナリオが機能します。リンクサーバーに関しては、XACT_ABORTには何らかの制限がありますか?

編集-さらにテストを行い、行数にも関係する必要があるようです。

可能なレポ

On ServerA

_use testdb
go
create table t1( c1 int, c2 datetime)
create table t2( c1 int, c2 datetime)

insert into t2 select 1, GETDATE()
insert into t2 select  * from t2 -- insert close to 5000 rows, I found the issue around over around 35000 rows
_

On ServerB

ServerAへのリンクサーバーを作成する

_SET XACT_ABORT ON;
Declare @BatchSize int = 10
delete from ServerA.testdb.dbo.t1
insert into ServerA.testdb.dbo.t1 (c1) 
select top (@BatchSize) c1 from ServerA.testdb.dbo.t2 --order by c2
select * from ServerA.testdb.dbo.t1
_

出力なし。しかし、テーブルt2の行数を約2000に減らすと、正常に機能します。

4
jesijesi

私がSET XACT_ABORT OFFであれば、すべてのシナリオが機能します。リンクサーバーに関しては、XACT_ABORTにはなんらかの制限がありますか?

XACT_ABORTの設定は、 サーバー間リモートストアドプロシージャのエラー処理 で説明されているように、リモートSQL Serverに伝達されます。

分散クエリと分散トランザクション に記載されているように、この設定は更新が可能かどうか、およびそれらの処理方法にも影響します。 SQL Serverはネストされたトランザクションをサポートするため、INSERTXACT_ABORT OFFで許可されます。

それにもかかわらず、SQL Serverがスキーマロックを解放しようとするとエラーが発生することが挿入中に2014サーバーのアクティビティを追跡すると明らかになるため、実装のバグがあるように見えます。

trace excerpt

このエラーは、リモートサーバー上のステートメント(スキーマロックの解放を試行)を中止しますが、XACT_ABORTOFFの場合、リモートサーバーは処理を続行します次のステートメント。スキーマロックの解放エラーにもかかわらず、挿入は完了します。

XACT_ABORTONの場合、リモートバッチ全体が中止されるため、挿入はロールバックされます。

ローカルで問題を再現できましたが、ORDER BY句は重要ではありませんでした。

INSERTを明示的なトランザクションでラップするなど、いくつかの方法で問題を回避できます(DTCが利用できると仮定)。

実装はカーソルモデルに基づいているため、リモート変更では4部構成の名前構文を使用しないことをお勧めします。通常、バルクメソッドを使用するか、リモートサーバーでデータをプルすることでプッシュするのではなく、パフォーマンスを向上させます。ローカルサーバー)。

関連するQ&Aを参照してください どちらが効率的ですか:リンクサーバーから選択するか、リンクサーバーに挿入しますか?

3
Paul White 9

私の経験では、リンクサーバーを介してマルチパートコマンドを実行すると、通常、特にテーブルが大きい場合に問題が発生します。これを試して :

SET XACT_ABORT ON;
Declare @BatchSize int = 10
delete from ServerA.testdb.bbo.t1
select top (@BatchSize) c1 INTO #t2temp from ServerA.testdb.dbo.t2
insert into ServerA.testdb.dbo.t1 (c1) 
SELECT * FROM #t2temp
select * from ServerA.testdb.dbo.t1
1
Ehsan Pourtorab