都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

待ち事象の一つである、『 TRANSACTION_MUTEX 』 を取り上げてみる

 病み上がりです。アレルギー持ちなので、発症すると辛いです。桜の季節も終わりましたね。なんとなく、もの悲しい今日この頃....
f:id:koogucc11:20150406151227j:plain
 
 さて、気を取り直してブログ書きます。SQL Server のチューニングにおいて、データベースサーバにどのような待ち事象が発生しているかを把握することは非常に重要です。SQL Server の待ち事象で代表的なものは、ASYNC_NETWORK_IO、SOS_SCHEDULER_YIELD、PAGEIOLATCH_***、WRITELOG 等があります。今回は 『 TRANSACTION_MUTEX 』 について取り上げたいと思います。待ち事象については、sys.dm_os_wait_stats で確認することができます。早速実行してみましょう。

SELECT * FROM sys.dm_os_wait_stats
ORDER BY wait_type

f:id:koogucc11:20150413091752p:plain

 TRANSACTION_MUTEX は、分散トランザクション、MARS の環境下で発生する待ち事象です。MUTEX とか名前からして、まさに待ちっぽいですね。MUTEX とは、

2 つ以上のスレッドが同時に共有リソースにアクセスする必要がある場合は、システムには同期機構を使用して、一度に 1 つのスレッドがリソースを使用することを保証する必要があります。 Mutex は、共有リソースへの排他アクセス権を 1 つのスレッドにだけ付与する同期プリミティブです。 あるスレッドがミューテックスを取得すると、ミューテックスを取得しようとしている 2 つ目のスレッドは最初のスレッドがミューテックスを解放するまで中断されます。

早速実験してみましょう。今回は MARS で実験してみます。使用するデータベースは、AdventureWorks2014 です。

using System;
using System.Data.SqlClient;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string con = @"Server=******;Database=AdventureWorks2014;Trusted_Connection=True;MultipleActiveResultSets=true;";
            var conn = new SqlConnection(con);

            conn.Open();

            var cmd1 = new SqlCommand("SELECT * FROM Person.BusinessEntity;", conn); //--①
            var cmd2 = new SqlCommand("SELECT * FROM Person.Person;", conn);         //--②
            var cmd3 = new SqlCommand("SELECT * FROM Person.EmailAddress;", conn);   //--③
            var cmd4 = new SqlCommand("SELECT * FROM Person.PersonPhone;", conn);    //--④

            var rd1 = cmd1.ExecuteReader();
            var rd2 = cmd2.ExecuteReader();
            var rd3 = cmd3.ExecuteReader();
            var rd4 = cmd4.ExecuteReader();

            rd1.Read();
            rd2.Read();
            rd3.Read();
            rd4.Read();
        }
    }
}

 通常上記のように同一コネクション上で①~④のように処理する場合、それぞれのステートメントの実行時間には差があるのが普通だと思います。そのため、TRANSACTION_MUTEX の待機状態が発生します。上記の①~④の処理を5回実行すると、sys.dm_os_wait_stats の結果は下記のようになります。
f:id:koogucc11:20150413164401p:plain
 
 今回の例ではそれぞれの処理が軽いため、ほとんど待ちは発生していない状態です。それぞれのステートメントが非常に重い場合、それなりの待ち時間が発生する可能性があります。MARS に対応したアプリケーションで、同一コネクションで複数結果セットを得るような構造の場合は、注意が必要ですね。しかし、待ち事象は奥が深いですね。勉強することまだまだ一杯ありますね。(ブログネタ、本当に尽きません。)

※実際の環境で IN-Memory も使ってみたいです。

SQL Server Internals: In-Memory OLTP: Inside the SQL Server 2014 Hekaton Engine (English Edition)

SQL Server Internals: In-Memory OLTP: Inside the SQL Server 2014 Hekaton Engine (English Edition)