SQL Server における分散トランザクション 1

 

神谷 雅紀
Escalation Engineer

 

 

分散トランザクション

分散トランザクションとは、複数のリソースマネージャーで実行されるトランザクションを、ひとつのトランザクションとして実行するトランザクションです。

 

image

 

 

リソースマネージャー

リソースマネージャー (RM) とは、トランザクションによって更新されるデータを管理しているコンポーネントです。通常は、SQL Server や Oracle などのデータベース管理システムです。

 

トランザクションマネージャー

トランザクションマネージャー (TM) とは、トランザクションを管理し、各リソースマネージャーに対してトランザクションに関する指示を出すソフトウェアコンポーネントです。SQL Server は、トランザクションマネージャーとして、Microsoft Distributed Transaction Coordinator (分散トランザクションコーディネーター / MS DTC) を使用します。

 

SQL Server における分散トランザクション実行時のソフトウェア構成

SQL Server やアプリケーションは、MS DTC Proxy を使用して MS DTC とのやり取りを行います。

最も一般的な形は次の図のように、それぞれの Windows で動作している MS DTC を使用して分散トランザクションを実行します。

尚、通常リソースマネージャは複数 (上図のように右側のサーバーが複数ある構成) になりますが、以下の図は簡略化のためにリソースマネージャをひとつとしています。

 

image

 

ローカル MS DTC を使用するように構成されている Windows では、使用する MS DTC をアプリケーションコードの中で指定し、Windows の設定を上書きすることができます。アプリケーションによって明示的に指定されていない場合やリモート MS DTC を使用するように構成された Windows では、その設定に従います。設定は、[コンピューターの管理] – [コンポーネントサービス] – [マイコンピューター] の [プロパティ] で行います。

 

image

 

この設定を変更することで、リモート MS DTC を使用するように構成することも可能です。

リモート MS DTC を使用する構成が有効な場合については、SQLCATのブログを参照してください。

https://blogs.msdn.microsoft.com/sqlcat/2010/05/11/resolving-dtc-related-waits-and-tuning-scalability-of-dtc/

 

 

image

 

分散トランザクションの流れ

1) SQL Server と MS DTC 間の接続確立

SQL Server は、起動時または最初に分散トランザクションが実行された時に、MS DTC Proxy を通じて MS DTC に接続します。この時、自分自身のインスタンスを識別するための固有のリソースマネージャー ID を渡します。AlwaysOn 可用性グループが DTC_SUPPORT = PER_DB に設定されている場合は、各プライマリーレプリカごとに固有のリソースマネージャ ID を渡します。

MS DTC とのセッションが確立すると、MS DTC の情報を取得します。その中には MS DTC が動作しているコンピューターの名前も含まれます。

 

image

 

このような初期化処理が終わると、Errorlog には以下のようなエントリが記録されます。

 

2016-10-19 17:05:32.37 spid116 Initializing Microsoft Distributed Transaction Coordinator (MS DTC) resource manager [df796691-315b-4dd2-9acd-11ad222e1e58] for server instance Server1\SQL16. This is an informational message only. No user action is required.

 

- MS DTC への接続は DtcGetTransactionManager を呼び出すことで行います。- MS DTC の情報の取得は、ITransactionImportWhereabouts::GetWhereabouts で行います。

 

2) アプリケーションと MS DTC 間の接続確立

アプリケーションも MS DTC Proxy を通じて MS DTC に接続します。

 

3) アプリケーションによるトランザクションの開始

アプリケーションは、MS DTC に対して、トランザクションの開始を通知します。

 

image

 

- トランザクションの開始は、 ITransactionDispenser::BeginTransaction を呼び出すことで行います。- アプリケーションは、開始されたトランザクションを表す ITransaction オブジェクトを受け取ります。

 

4) アプリケーションによる SQL Server 側 MS DTC 情報の取得

アプリケーションは、ODBC, OLEDB, ADO.NET などを使用して SQL Server との接続を確立し、その接続を通じて SQL Server 側 MS DTC の情報を取得します。SQL Server がアプリケーションに渡す情報は、1) で取得した MS DTC の情報です。

この時、SQL Server でトレースを採取していると、DTCTransaction\Get address トレースイベントおよび dtc_transaction\Get address 拡張イベントが生成されます。

 

image

 

5) アプリケーションによる SQL Server 側 MS DTC へのトランザクションエクスポート

アプリケーションは、SQL Server 側 MS DTC にトランザクションをエクスポートするようにアプリケーション側 MS DTC に指示します。加えて、トランザクションオブジェクトの cookie を取得し、SQL Server との接続を通じて、それを SQL Server に渡します。

 

image

 

- アプリケーションによるトランザクションのエクスポートは、ITransactionExportFactory::Create によって ITransactionExport を取得し、ITransactionExport::Export によって行います。- cookie の取得は、ITransactionExport::GetTransactionCookie により行います。

 

6) SQL Server のトランザクションへの参加

SQL Server は、cookie を受け取ると、その cookie を使用して、トランザクションをインポートし、トランザクションに参加します。

この時、Enlisting in a DTC transaction, Propagate Transaction イベントが生成されます。

 

image

 

- トランザクションのインポートは、ITransactionImport::Import によって行います。- トランザクションへの参加は、IResourceManager::Enlist によって行います。Enlist には SQL Server により実装されている callback インターフェース ITransactionResourceAsync が渡されます。- sys.dm_tran_active_transactions の transaction_uow に示される Unit Of Work (UOW) は ITransaction::GetTransactionInfo によって取得される XACTTRANSINFO に含まれています。

 

6) アプリケーションによるデータ更新

アプリケーションは、開始したトランザクション内でデータ更新等のトランザクションを実行します。

 

7) トランザクションのコミット (2 フェーズコミット)

7-1) アプリケーションは、アプリケーション側 MS DTC に対して、トランザクションのコミットを要求します。

7-2) アプリケーション側 MS DTC は、SQL Server 側 MS DTC に対して、トランザクションのコミットの準備を要求し、その要求は SQL Server に対しても行われます。(フェーズ 1)

この時、Preparing Transaction イベントが生成されます。

 

image

 

- アプリケーションは、トランザクションをコミットするために ITransaction::Commit を呼び出します。

 

7-3) SQL Server がコミットの準備を完了すると、SQL Server は SQL Server 側 MS DTC に対してコミットの準備が完了したことを通知し、その通知はアプリケーション側 MS DTC にも通知されます。

 

image

 

7-4) 準備完了通知を受け取ったアプリケーション側 MS DTC は、SQL Server 側 MS DTC に対してトランザクションのコミットを要求し、その要求は SQL Server に対しても行われます。(フェーズ 2)

この時、Transaction is committing イベントが生成されます。

 

7-5) SQL Server でのコミットが完了すると、その完了が SQL Server 側 MS DTC に通知され、それはアプリケーション側 MS DTC にも通知されます。

- MS DTC は、SQL Server の ITransactionResourceAsync::PrepareRequest および ITransactionResourceAsync::CommitRequest を呼び出すことで、SQL Server に準備およびコミットを要求します。- 準備、コミットの完了は、それぞれ ITransactionEnlistmentAsync::PrepareRequestDoneITransactionEnlistmentAsync::CommitRequestDone によって MS DTC に通知します。

 

7-6) アプリケーション側 MS DTC から アプリケーションに対して、コミットの完了が通知されます。

 

以上が分散トランザクションが開始されてから終了するまでの流れです。

 

次回以降で、トランザクションのロールバック、MS DTC が停止や再起動した場合、SQL Server が停止や再起動した場合、フェールオーバークラスター環境、可用性グループ環境などを取り上げる予定です。