クラスター環境 (Always On FCI) の SQL Server で MSDTC を利用した分散トランザクションを実行する際に必要となる Windows Firewall の許可設定についてのメモ。
MSDTC を設定する際の基本的な作業については、次の記事を見ておけば良いかと。
MSDTC を使用する場合に、有効化する Windows Fireall のルール
MSDTC を有効にする場合、次のような設定を有効化し、分散トランザクションに関しての Windows Firewall のルールの有効化を行うかと思います。
Enable-NetFirewallRule -Group "@FirewallAPI.dll,-33502"
上記のコマンドはグループとして「分散トランザクション コーディネーター」が設定されているルールを一括で有効にするものとなりますので、「受信の規則」「送信の規則」の両方で必要となるルールが有効化されます。
発生していたエラー
SQL Server ならびに MSDTC のクラスター化されているリソースが、次の画像のように同一のノード内で実行されているのであれば、このルールが有効化されていれば問題はないかと思います。
しかし、次の画像のように SQL Server と MSDTC が異なるノード上で動作している場合、各ノードで上述の分散トランザクション コーディネーターのルールが有効化されていても、DTC にアクセスができないという事象が発生しました。
同一のノード上で両リソースが実行されている場合は、以下のクエリが正常に完了しています。
しかし、SQL Server と MSDTC のクラスターリソースが異なるノード上で実行されている場合は、エラーとなりました。
問題の回避方法
問題が発生している状況ですが、次のようなパケットの送信で止まっていました。
MSDTC のリソースが動作しているノード (10.59.0.2) の Process ID 3996 (msdtc.exe) から、SQL Server のリソースが動作しているノード (10.59.0.1) の SQL Server のプロセス (sqlservr.exe) に対しての通信がブロックされていることが問題となっているようです。
通常、SQL Server を動作させている環境で、Windows Firewall の許可ルールを設定する場合、TCP 1433, 1434 を許可することになるかと思います。
しかしこの許可設定だけでは、SQL Server のプロセスが開いている RPC 動的ポートに対してのアクセスが行うことができず、通信がブロックされていました。
これを回避する場合、次のようなルールをクラスターの各ノードで設定すれば対応ができそうでした。
# SQL Server 2019 で実行する場合 New-NetFirewallRule -DisplayName "SQL Server RPC" -Action Allow -Program "%ProgramFiles%\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Binn\sqlservr.exe" -Protocol "TCP" -Direction Inbound -LocalPort "RPC" # SQL Server 2022 で実行する場合 New-NetFirewallRule -DisplayName "SQL Server RPC" -Action Allow -Program "%ProgramFiles%\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Binn\sqlservr.exe" -Protocol "TCP" -Direction Inbound -LocalPort "RPC"
Windows Firewall を無効にしていたり、SQL Server 向けの Widnows Firewall 設定をプロセス名で指定し、すべてのポートを許可している場合は今回のような対応は不要かと思いますが、MSDTC 関連のアクセスが Firewall でブロックされているようであれば本投稿のような設定も検討してみるとよいのではないでしょうか。