← 返回首页目录
# リンクサーバ経由のストアドプロシージャ実行エラー「分散トランザクションが無効」の原因と解決策
## 著者:吉祥法师
## 問題の概要
SQL Server 2005 Service Pack 2 および .NET Framework 2.0 SP1 の環境において、リンクサーバを経由してリモートサーバ上のストアドプロシージャを実行しようとした際に、特定のエラーメッセージが発生する現象について解説します。この問題は、リモートサーバ上のテーブルを更新するストアドプロシージャを、リンクサーバ経由で呼び出す場面で顕著に現れます。
具体的なエラーメッセージは以下の通りです:
> リンク サーバー "***" の OLE DB プロバイダ "***" から、メッセージ "パートナー トランザクション マネージャにより、リモート トランザクションまたはネットワーク トランザクションのサポートが無効にされました。" が返されました。
このエラーは、Microsoft Distributed Transaction Coordinator(MSDTC)が適切に動作していない場合に発生する典型的な障害であり、分散トランザクションの基盤となるコンポーネントの設定に問題があることを示しています。
## エラーの根本原因
この問題の本質は、**分散トランザクション**の処理に失敗している点にあります。SQL Server において、リンクサーバ経由でリモートデータベースの更新を行う場合、トランザクションの一貫性を保証するために、分散トランザクションコーディネーター(MSDTC)が介入します。しかし、MSDTCが適切に設定されていない、またはネットワーク経由での通信がブロックされている場合、上記のエラーが発生します。
具体的な原因として、以下の2つが主要な要因として考えられます。
### 原因1:MSDTCの設定未実施
リンクサーバを利用した分散トランザクションを正常に動作させるためには、**リンク元のサーバー**と**リンク先のリモートサーバー**の双方でMSDTCの設定を行う必要があります。片方のサーバーでしか設定が行われていない場合、トランザクションの調整が行われず、エラーが発生します。これは、分散トランザクションが「参加者全員の合意」を必要とする仕組みであるため、一方だけでは成立し得ないからです。
### 原因2:設定の見落とし
MSDTCの設定には多くの項目が存在し、その中には「ネットワークDTCアクセス」「トランザクションマネージャーの通信」など、分散トランザクションに直結する重要な設定が含まれます。設定項目の一つでも漏れがあると、エラーが解消されません。例えば、ファイアウォールの設定や、Windows ファイアウォールによるポートブロックも、見落としがちな要因です。
## 問題解決のための詳細な手順
以下の手順を、リンク元サーバーとリンク先サーバーの両方で実施してください。各サーバーの管理者権限が必要です。
### 手順1:MSDTCサービスの起動確認と設定
MSDTCサービスが実行されていることを確認し、分散トランザクションがネットワーク経由で送受信できるように設定を変更します。
1. **サービススナップインの起動**
Windowsの「コントロールパネル」→「管理ツール」→「サービス」を開きます。または、コマンドプロンプトから `services.msc` を実行して起動します。
2. **MSDTCサービスの確認**
サービスの一覧から「**Distributed Transaction Coordinator**」を見つけます。
- 状態が「**実行中**」であることを確認します。
- スタートアップの種類が「**自動**」に設定されていることを確認します。
- もし停止している場合は、右クリックメニューから「開始」を選択して起動します。自動起動が有効でない場合は、プロパティから変更します。
3. **MSDTCのセキュリティ設定の変更**
以下の手順で、分散トランザクションのネットワーク通信を許可します。
a. コマンドプロンプトを管理者として開きます。
b. 以下のコマンドを実行して、MSDTCの設定画面を表示します。
```
msdtc -security
```
c. 表示された「MSDTC セキュリティ設定」ダイアログで、以下の項目をチェックして有効にします。
- **ネットワークDTCアクセス**
- **受信を許可する**
- **送信を許可する**
d. 「OK」をクリックして設定を保存します。
e. 設定を反映させるために、MSDTCサービスを再起動します。
サービススナップインで「Distributed Transaction Coordinator」を右クリックし、「**再起動**」を選択します。または、コマンドプロンプトで以下のコマンドを実行します。
```
net stop msdtc && net start msdtc
```
### 手順2:Windows ファイアウォールのポート開放
MSDTCが通信するために、ファイアウォールで特定のポートを許可する必要があります。MSDTCは主に**TCP ポート135**(RPC Endpoint Mapper)を使用し、さらに動的に割り当てられるポート範囲(通常はTCP 1024-65535)も利用します。
1. **管理ツールから「セキュリティが強化されたWindowsファイアウォール」** を開きます。
2. **受信の規則**を選択し、新しい規則を作成します。
3. **ポート規則の作成**
- 規則の種類:**ポート**
- プロトコル:**TCP**
- 特定のローカルポート:**135**
- 操作:**接続を許可する**
- プロファイル:**ドメイン**、**プライベート**、**パブリック**のすべてを選択(必要に応じて環境に合わせて調整)
- 名前:「**MSDTC TCP 135**」など、識別しやすい名前を付けます。
4. **動的ポートのための規則**
同様に、以下のポート範囲を許可する規則も作成します。
- プロトコル:**TCP**
- 特定のローカルポート:**1024-65535**
- 操作:**接続を許可する**
- 名前:「**MSDTC 動的ポート**」
### 手順3:SQL Server および RPC サービスの再起動
設定を完全に反映させるために、関連するサービスを再起動します。
1. **サービススナップイン**を開きます。
2. 以下のサービスの順序で再起動します。
a. **Distributed Transaction Coordinator**(MSDTC)
b. **SQL Server (MSSQLSERVER)** または該当するSQL Serverインスタンス
c. **SQL Server Agent**(必要な場合)
d. **RPC(Remote Procedure Call)** サービス(これは通常自動で起動しており、手動で再起動できる場合は行いますが、システム全体に影響を与える可能性があるため注意が必要です。ここでは、SQL ServerとMSDTCの再起動で十分です。)
### 手順4:リンクサーバーの設定確認(オプション)
リンクサーバーの設定によっては、分散トランザクションの使用を制限している場合があります。SQL Server Management Studio(SSMS)でリンクサーバーのプロパティを確認します。
1. SSMS で **サーバーオブジェクト** → **リンクサーバー** を展開します。
2. 該当するリンクサーバーを右クリックし、「**プロパティ**」を選択します。
3. 「**サーバーオプション**」タブを開きます。
4. **「分散トランザクションの昇格を有効にする」** が **True** に設定されていることを確認します。False になっていると、分散トランザクションが使用できません。
### 手順5:代替手段の検討(MSDTCを使用しない方法)
もし上記の設定をどうしても実施できない、またはビジネス要件で制限がある場合は、MSDTCを必要としない別のアプローチを検討します。
#### 方法A:ストアドプロシージャの分割実行
分散トランザクションが必要となるのは、複数のサーバーにまたがる更新操作を一つのトランザクションとして扱う場合です。そこで、処理を以下のように分割します。
1. **リンク元サーバー**で、トランザクションの開始を明示的に行わずに、単一の更新を行うストアドプロシージャを呼び出します。
2. 更新の成功/失敗を個別に判断するロジックをアプリケーション側で実装します。
3. ロールバック処理もアプリケーション側で独自に管理する必要があります。
#### 方法B:OPENQUERY を使用した単純な更新
トランザクションが不要な単純な更新であれば、`EXEC` ではなく `OPENQUERY` を使用して直接SQLを実行することで、分散トランザクションを回避できる場合があります。
```sql
UPDATE OPENQUERY([リンクサーバー名], 'SELECT カラム1 FROM データベース名.スキーマ名.テーブル名 WHERE 条件')
SET カラム1 = 値;
```
ただし、この方法は更新対象のテーブルが単純で、トランザクションの一貫性が厳密に要求されない場合に限定されます。
## 高度なトラブルシューティング
### ログの確認
MSDTCのログを確認することで、詳細なエラー情報を得られます。
1. **イベントビューアー** → **アプリケーションとサービスログ** → **Microsoft** → **Windows** → **MSDTC** → **操作** を開きます。
2. エラー発生時刻のログを確認し、エラーの詳細から設定不備やネットワーク問題を特定します。
### 診断ツールの使用
Microsoft は、MSDTCの設定を診断するためのツールを提供しています。以下のコマンドを管理者権限で実行することで、設定の検証が可能です。
```
dtcping <リモートサーバーのホスト名>
```
このコマンドは、MSDTCがリモートサーバーと通信できるかどうかをテストします。通信に失敗する場合、ファイアウォールやDNS解決の問題が疑われます。
### ネットワークの確認
1. **Pingテスト**:両サーバー間でpingが通ることを確認します。
2. **ポートテスト**:Telnet や Test-NetConnection を使用して、TCP 135 ポートが開いているか確認します。
## まとめ
リンクサーバ経由のストアドプロシージャ実行で発生する分散トランザクションエラーは、MSDTCの設定不備が主な原因です。問題を解決するためには、リンク元とリンク先の両方のサーバーで、MSDTCサービスの起動確認、ネットワークDTCアクセスの許可、ファイアウォールのポート開放、関連サービスの再起動を実施する必要があります。これらの基本的な設定を確実に行うことで、ほとんどのケースは解決します。
もしMSDTCの利用がどうしても難しい場合は、アプリケーション側でトランザクション管理を代替する方法や、OPENQUERYを用いた直接更新など、MSDTCに依存しないアプローチを検討することも有効です。
最後に、この問題はSQL Server 2005 SP2と.NET Framework 2.0 SP1という特定の環境で発生していますが、同様の手順はより新しいバージョンのSQL Server(SQL Server 2008以降)でも適用可能です。分散トランザクションを利用する際は、常にOSレベル、SQL Serverレベル、ネットワークレベルの3層で設定を確認する習慣が重要です。