Always On FCI (フェールオーバークラスターインスタンス) の SQL Server の分散トランザクション (MSDTC) で、意図的に未解決(in-doubt) のトランザクションを作成して検証をしたいケースがあったので意図的に作り出す方法を。
以前は SQL Server の分散トランザクション使用時のインダウトトランザクション (未解決のトランザクション) について で作り出していましたが、FCI であればもう少しシンプルな方法で作り出すことができます。
FCI で意図的に未解決のトランザクションを作り出す方法
サービスの再起動を伴う方法となりますが、「分散トランザクションのトランザクションが存在している状態で MSDTC アクセスができなくなる」というような状態を作り出すことによって未解決のトランザクションを作り出すことができます。
最初に、SQLQueryStress 等のツールで次のようなクエリを実行しておきます。
SET XACT_ABORT ON; BEGIN TRAN INSERT INTO T1 VALUES(1) INSERT INTO [SQL-CL02].[DB01].[dbo].[T1] VALUES (1) COMMIT TRAN
今回は次のような設定で実行しています。
このようなクエリを実行している最中に、次のようなコマンドを実行して MSDTC が停止している状態で、SQL Server のサービスを再起動します。
Start-ClusterResource -Name MSDTC-SQL-CL01-DTC Start-Sleep -Seconds 10 Test-ClusterResourceFailure -Name MSDTC-SQL-CL01-DTC Stop-ClusterGroup -Name "SQL Server (MSSQLSERVER)" Start-ClusterGroup -Name "SQL Server (MSSQLSERVER)"
これを実行すると、SQL Server のサービスは起動しているが MSDTC は障害が発生している状態となります。
これにより、SQL Server のサービスが再起動したタイミングで MSDTC にアクセスすることができず、サービスの再起動前に実行していた分散トランザクションの復元ができない状態となります。
この状態で SQL Server に接続をしてみると、分散トランザクションを実行していたデータベースが「未確認」の状態となります。
ERRORLOG を確認すると、次のようなメッセージが出力され、未解決の分散トランザクションが存在する状態になっていることが確認できます。
Resource Manager Creation Failed: 0x8004d01c(XACT_E_CONNECTION_DOWN) SQL Server detected a DTC/KTM in-doubt transaction with UOW {F75BDB59-DB62-4550-B02D-C1287A0B9AFA}.Please resolve it following the guideline for Troubleshooting DTC Transactions. Error: 3437, Severity: 21, State: 3. An error occurred while recovering database 'DB01'. Unable to connect to Microsoft Distributed Transaction Coordinator (MS DTC) to check the completion status of transaction (0:3406620). Fix MS DTC, and run recovery again. Parallel redo is shutdown for database 'DB01' with worker pool size [2]. Error: 3414, Severity: 21, State: 2. An error occurred during recovery, preventing the database 'DB01' (5:0) from restarting. Diagnose the recovery errors and fix them, or restore from a known good backup. If errors are not corrected or expected, contact Technical Support. Recovery is complete. This is an informational message only. No user action is required. Attribute synchronization initialized Attribute synchronization manager initialized
この状態になった場合の解決方法については、次のドキュメント / 記事が参考となります。
未解決のトランザクションが数個なのであれば、トランザクション単位で次のようなクエリを実行することで、トランザクションの取り消しを行うことができます。(UOW の GUID については ERRORLOG から確認することができます)
KILL '<UOW>' WITH ROLLBACK GO ALTER DATABASE <DB 名> SET ONLINE GO 実行例: KILL 'F75BDB59-DB62-4550-B02D-C1287A0B9AFA' WITH ROLLBACK GO ALTER DATABASE DB01 SET ONLINE GO
複数の未解決のトラザクションが存在する場合、一つ一つ UOW を指定して DB のオンライン化を試す必要があるのですが、大量のトランザクションが未解決となってしまっている場合一つ一つを取り消して行くことは難しいかと思います。
そのような場合は、次のように in-doubt xact resolution を設定することで一括で処理することができます。
EXEC sp_configure 'show advanced options', 1 RECONFIGURE EXEC sp_configure 'in-doubt xact resolution', 2 RECONFIGURE GO ALTER DATABASE DB01 SET ONLINE GO -- 既定値に戻す場合は次のクエリを実行 EXEC sp_configure 'in-doubt xact resolution', 0 RECONFIGURE GO
上記のサンプルクエリはロールバックを行っていますが、「KILL ‘<UOW>’ WITH COMMIT」「EXEC sp_configure ‘in-doubt xact resolution’, 1」でコミットを行うことも可能です。
分散トランザクションを実行している最中で、MSDTC のサービスを起動 / 停止を繰り返すことで、SQL Server のサービスを再起動しなくても未解決のトランザクションが発生した状態を作り出すこともできるのですが、発生する確度が低く、すぐに状況を作り出すことも難しいため、SQL Server のサービス再起動が許容されるのであれば、このような方法を使ってしまったほうが手っ取り早いかと思います。