SQL Server は、MS DTC (Microsoft Distributed Transaction Cordinator) をトランザクションマネージャーとして使用して、分散トランザクションの実行を行うことができます。
分散トランザクションについては、トランザクションのロックおよび行のバージョン管理ガイド で解説が行われています。
フローについては、1.3.1.2.3.2 Transaction Enlistment and Completion になるかと思いますが、コミットを「準備フェーズ」と「コミットフェーズ」の 2 フェーズで管理を行う 2 フェーズコミット (2PC) により、トランザクションの管理が行われます。
SQL Server の場合、インスタンス内の複数のデータベースにまたがる処理については、管理ガイドでは次のように記載されています。
数のデータベースにまたがる 1 つのSQL Server データベース エンジン内のトランザクションは実質的には分散トランザクションです。 ただし、SQL Server インスタンスは分散トランザクションを内部で処理するため、ユーザーにはローカル トランザクションとして動作しているように見えます。
実質は分散トランザクションではあるのですが、ローカルトランザクションのように見える処理が行われるため、MS DTC は使用されずに、処理が行われていたかと思います。
リンクサーバー / トランザクションスコープ (Transaction Scope) / BEGIN DISTRIBUTED TRANSACTION 等を使用した場合、実行方法によっては、MS DTC を使用した分散トランザクションとして実行され、分散トランザクションで実行される場合には、インダウト (in-doubt) トランザクション (未解決 / 不確定 / 不定トランザクション) の発生についての考慮が必要なケースが出てきます。
コミット時のインダウトトランザクションとしては、上記の図の xa_commit の部分になるかと思います。
分散トランザクションに参加しているトランザクションは最終的には、トランザクションマネージャーからの commit 要求により、各トランザクションのコミットが行われますが、コミットフェーズにおいて、特定のインスタンスでは、コミットが完了しなかったようなケースが発生した場合には、インダウト トランザクションとして、不確定のトランザクションをどのように取り扱うかを決めなくてはいけません。
インダウト トランザクションは 2PC の特定のタイミングでトランザクションを未確定にしなくてはいけないのですが、意図的に発生させる方法について残しておきたいと思います。
なお、windbg を使用して無理やり発生させていますが、本投稿では windbg の使用方法などについては触れませんのでご了承ください。
Read the rest of this entry »