sql >> データベース >  >> RDS >> Access

TRANSACTION_MUTEXおよびマルチセッショントランザクションアクセス

    最近、高いTRANSACTION_MUTEXに遭遇しました クライアントシステムでの累積待機時間。この待機タイプが「高待機」リストの一番上にあると思ったケースを思い出せませんでした。このタイプの全体的な待機時間をどのような要因で押し上げることができるのか知りたいと思いました。

    BooksOnlineのTRANSACTION_MUTEXの定義 これは、「複数のバッチによるトランザクションへのアクセスの同期中に発生する」ということです。 SQL Serverエンジン内の多くの領域でこのタイプの機能が公開されていないため、調査は次のテクノロジに絞り込まれました。

    • 非推奨のsp_getbindtoken およびsp_bindsession バインドされた接続を処理するために使用されるシステムストアドプロシージャ
    • 分散トランザクション
    • MARS(複数のアクティブな結果セット)

    私の目標は、各テクノロジーをテストし、それがTRANSACTION_MUTEXに影響を与えたかどうかを確認することでした。 待機タイプ。

    私が実行した最初のテストでは、非推奨のsp_getbindtokenを使用しました およびsp_bindsession ストアドプロシージャ。 sp_getbindtoken sp_bindsessionで使用できるトランザクション識別子を返します 同じトランザクションで複数のセッションをバインドします。

    各テストシナリオの前に、テストSQLServerインスタンスの待機統計を必ずクリアしました。

    DBCC SQLPERF('waitstats', CLEAR);
    GO

    私のテストSQLServerインスタンスは、SQL Server 2012 SP1 Developer Edition(11.0.3000)を実行していました。私はCreditサンプルデータベースを使用しましたが、スキーマとデータの配布はこの記事の主題に直接関連しておらず、運転するために必要ではなかったため、必要に応じてAdventureWorksなどの他の種類のサンプルデータベースを使用できます。 TRANSACTION_MUTEX 待ち時間。

    sp_getbindtoken / sp_bindsession

    SQL Server Management Studioの最初のセッションウィンドウで、次のコードを実行してトランザクションを開始し、他の計画されたセッションによる参加用のバインドトークンを出力しました。

    USE Credit;
    GO
     
    BEGIN TRANSACTION;
     
    DECLARE @out_token varchar(255);
     
    EXECUTE sp_getbindtoken @out_token OUTPUT;
     
    SELECT @out_token AS out_token;
    GO

    これにより、@out_tokenが返されました S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---の 。 2つの別々のSQLServerManagement Studioクエリウィンドウで、次のコードを実行して既存のセッションに参加しました(共有トランザクションにアクセスします)。

    USE Credit;
    GO
     
    EXEC sp_bindsession 'S/Z5_GOHLaGY<^i]S9LXZ-5---.fE---';

    そして、最初のセッションウィンドウを開いたまま、次のループを開始して、現在の日時に等しい請求日で請求テーブルのテーブルを更新し、他の2つのウィンドウで同じロジックを実行しました(ループ):

    WHILE 1 = 1 
    BEGIN
        UPDATE  dbo.charge
        SET     charge_dt = SYSDATETIME();
    END

    数秒後、実行中の各クエリをキャンセルしました。 3つのセッションのうち、実際に更新を実行できたのは1つだけでしたが、他の2つのセッションは同じトランザクションにアクティブに参加していました。そして、TRANSACTION_MUTEXを見た場合 待機タイプ、実際に増加したことがわかります:

    SELECT  [wait_type],
            [waiting_tasks_count],
            [wait_time_ms],
            [max_wait_time_ms],
            [signal_wait_time_ms]
    FROM sys.dm_os_wait_stats
    WHERE wait_type = 'TRANSACTION_MUTEX';

    この特定のテストの結果は次のとおりです。

    wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
    TRANSACTION_MUTEX    2                     181732         93899              0

    したがって、2つの待機中のタスク(ループを介して同じテーブルを同時に更新しようとした2つのセッション)があったことがわかります。 SET NOCOUNT ONを実行していなかったので 、最初に実行されたUPDATEのみを確認できました ループに変更が加えられました。いくつかの異なるバリエーション(たとえば、全体で4つのセッション、待機中の3つ)とTRANSACTION_MUTEXを使用して、この同様の手法を試しました。 インクリメントは同様の動作を示しました。 TRANSACTION_MUTEXも見ました セッションごとに異なるテーブルを同時に更新する場合の累積–したがって、TRANSACTION_MUTEXを再現するために、ループ内の同じオブジェクトに対する変更は必要ありませんでした。 待ち時間の蓄積。

    分散トランザクション

    次のテストでは、TRANSACTION_MUTEXかどうかを確認しました。 分散トランザクションの待機時間が増加しました。このテストでは、2つのSQL Serverインスタンスと、2つのインスタンスの間に接続されたリンクサーバーを使用しました。 MS DTCが実行され、適切に構成されていたため、ローカルのDELETEを実行する次のコードを実行しました。 およびリモートのDELETE リンクサーバーを介して変更をロールバックします:

    USE Credit;
    GO
     
    SET XACT_ABORT ON;
     
    -- Assumes MS DTC service is available, running, properly configured
    BEGIN DISTRIBUTED TRANSACTION;
     
    DELETE [dbo].[charge] WHERE charge_no = 1;
    DELETE [JOSEPHSACK-PC\AUGUSTUS].[Credit].[dbo].[charge] WHERE charge_no = 1;
     
    ROLLBACK TRANSACTION;

    TRANSACTION_MUTEX ローカルサーバーでアクティビティが表示されませんでした:

    wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
    TRANSACTION_MUTEX    0                     0              0                  0

    ただし、待機中のタスクの数はリモートサーバーで増加しました:

    wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
    TRANSACTION_MUTEX    1                     0              0                  0

    したがって、同じトランザクションに何らかの形で複数のセッションが関与する1つの分散トランザクションがあることを考えると、これを確認するという私の期待が確認されました。

    MARS(複数のアクティブな結果セット)

    複数のアクティブな結果セット(MARS)の使用についてはどうですか? TRANSACTION_MUTEXも表示されると思いますか MARSの使用に関連して蓄積しますか?

    このために、SQL Server2012インスタンスとCreditデータベースに対してMicrosoftVisual Studioからテストされた次のC#コンソールアプリケーションコードを使用しました。私が実際に行っていることのロジックはあまり役に立ちません(各テーブルから1行を返します)が、データリーダーは同じ接続と接続属性MultipleActiveResultSets上にあります はtrueに設定されているため、実際にMARSがTRANSACTION_MUTEXを駆動できるかどうかを確認するだけで十分でした。 蓄積も:

    string ConnString = @"Server=.;Database=Credit;Trusted_Connection=True;MultipleActiveResultSets=true;";
    SqlConnection MARSCon = new SqlConnection(ConnString);
     
    MARSCon.Open();
     
    SqlCommand MARSCmd1 = new SqlCommand("SELECT payment_no FROM dbo.payment;", MARSCon);
    SqlCommand MARSCmd2 = new SqlCommand("SELECT charge_no FROM dbo.charge;", MARSCon);
     
    SqlDataReader MARSReader1 = MARSCmd1.ExecuteReader();
    SqlDataReader MARSReader2 = MARSCmd2.ExecuteReader();
     
    MARSReader1.Read();
    MARSReader2.Read();
     
    Console.WriteLine("\t{0}", MARSReader1[0]);
    Console.WriteLine("\t{0}", MARSReader2[0]);

    このコードを実行した後、TRANSACTION_MUTEXの次の累積が表示されました :

    wait_type            waiting_tasks_count   wait_time_ms   max_wait_time_ms   signal_wait_time_ms
    TRANSACTION_MUTEX    8                     2              0                  0

    ご覧のとおり、MARSアクティビティ(ただし、簡単に実装されたもの)により、TRANSACTION_MUTEXが上昇しました。 待機タイプの蓄積。また、接続文字列属性自体はこれを駆動しませんが、実際の実装は駆動します。たとえば、2番目のリーダーの実装を削除し、MultipleActiveResultSets=trueを使用して単一のリーダーを維持しました。 、そして予想通り、TRANSACTION_MUTEXはありませんでした 待ち時間の蓄積。

    結論

    高いTRANSACTION_MUTEXが表示されている場合 ご使用の環境で待機している場合は、この投稿で、これらの待機がどこから来ているのか、および待機が必要かどうかを判断するための3つの方法についての洞察が得られることを願っています。


    1. FORCEPLANを使用してT-SQL結合のクエリオプティマイザをオーバーライドする

    2. ORA-00604 ORA-12705

    3. 新しいPostgreSQLJSONデータ型内のフィールドを使用してクエリを実行するにはどうすればよいですか?

    4. MySQL:データベースに対する**すべての**権限を付与します