すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:ステートメントキュー

最終更新日:Mar 19, 2024

同時ステートメントの実行中、MySQLサーバーとエンジンは互いに競合する可能性があります。 この問題を解決するために、AliSQLは、同じリソースを必要とするステートメントが同じバケットにキューできるようにするステートメントキュー機能を提供します。 たとえば、同じバケット内のテーブルキューの同じ行を必要とするステートメントです。 この機能は、潜在的な競合によって引き起こされるオーバーヘッドを削減し、ApsaraDB RDS for MySQLインスタンスのパフォーマンスを向上させるのに役立ちます。

背景情報

同時ステートメントの実行中に、MySQLサーバーとエンジンは、いくつかのシリアル操作で互いに競合する可能性があります。 たとえば、トランザクションロックの競合は、DMLステートメントの実行中に一般的です。 InnoDBストレージエンジンは、行への正確なリソースロックをサポートします。 複数のDMLステートメントが行内で同時に実行されると、深刻な競合が発生する可能性があります。 データベースシステムの全体的なスループットは、同時DMLステートメントの数に比例して低下します。 AliSQLは、競合オーバーヘッドを削減し、インスタンスのパフォーマンスを向上させるステートメントキュー機能を提供します。

前提条件

RDSインスタンスは、次のMySQLバージョンとRDSエディションのいずれかを実行します。

  • RDS Basic EditionまたはRDS High-availability Editionで20191115以降のマイナーエンジンバージョンを使用したMySQL 8.0

  • RDS Basic EditionまたはRDS High-availability Editionで20200630以降のマイナーエンジンバージョンを使用したMySQL 5.7

変数

AliSQLは、ステートメントキューのバケット数とサイズを定義するために使用される2つの変数を提供します。

  • ccl_queue_bucket_count: ステートメントキューで許可されているバケットの数。

    • 有効な値: 1 ~ 64。

    • デフォルト値: 4。

  • ccl_queue_bucket_size: バケットごとに許可される同時ステートメントの数。

    • 有効な値: 1 ~ 4096

    • デフォルト値: 64。

説明

ApsaraDB RDSコンソールで変数を変更できます。 詳細は、「インスタンスパラメーターの変更」をご参照ください。

構文

AliSQLは2つのヒントをサポートします。

  • ccl_queue_value

    AliSQLは、ハッシュアルゴリズムを使用して、指定されたフィールドの値に基づいて各ステートメントが配置されるバケットを決定します。

    構文:

    /* + ccl_queue_value([int | string]) */

    例:

    update /* + ccl_queue_value(1) */ t set c=c + 1 (id = 1);
    
    update /* + ccl_queue_value('xyz') */ t set c=c + 1ここでname = 'xyz'; 
  • ccl_queue_field

    AliSQLは、ハッシュアルゴリズムを使用して、WHERE句で指定されたフィールドの値に基づいて、各ステートメントが配置されるバケットを決定します。

    構文:

    /* + ccl_queue_field (文字列) */

    例:

    update /* + ccl_queue_field(id) */ t set c=c + 1ここで、id = 1およびname = 'xyz';
    説明
    • 上記のヒントは更新後に配置する必要があります。

    • ccl_queue_fieldヒントは、一度に1つのフィールドのみを指定します。 /* + ccl_queue_field(id name) */ ヒントに構文エラーが含まれている場合、同時実行制御 (CCL) キューは有効になりません。 /* + ccl_queue_field(id) ccl_queue_field(name) */ ヒントが重複している場合、最初のヒントで指定されたフィールドが優先されます。

    • ccl_queue_fieldヒントで指定されたフィールドは、WHERE句で使用する必要があります。

    • ccl_queue_fieldヒントでは、WHERE句はrawフィールドでのみバイナリ演算子をサポートします。 これらの生フィールドは、関数または計算操作を使用して変更されていません。 さらに、このようなバイナリ演算子の右オペランドは、数値または文字列でなければなりません。

関数

AliSQLには、ステートメントキューのステータスを照会するために使用される2つの関数があります。

  • dbms_ccl.show_ccl_queue()

    この関数は、現在のステートメントキューのステータスを照会するために使用されます。

    mysql> dbms_ccl.show_ccl_queue() を呼び出します。------ ------- ------------------- -----------------------------------------
    | ID | TYPE | CONCURRENCY_COUNT | 一致 | 実行中 | 待機中 |
    ------ ------- ------------------- -----------------------------------------
    | 1 | キュー | 64 | 1 | 0 | 0 |
    | 2 | キュー | 64 | 40744 | 65 | 6 |
    | 3 | キュー | 64 | 0 | 0 | 0 |
    | 4 | キュー | 64 | 0 | 0 | 0 |
    ------ ------- ------------------- -----------------------------------------
    セットの4列 (0.01秒) 

    下表に、各パラメーターを説明します。

    パラメーター

    説明

    CONCURRENCY_カウント

    許可される同時ステートメントの最大数。

    マッチした

    指定されたルールにヒットしたステートメントの総数。

    ランニング

    同時に実行されているステートメントの数。

    待っている

    キューで待機しているステートメントの数。

  • dbms_ccl.flush_ccl_queue()

    この関数は、ステートメントキューに関するデータをメモリから削除するために使用されます。

    mysql> call dbms_ccl.flush_ccl_queue(); クエリOK、影響を受ける0行 (0.00秒)
    
    mysql> dbms_ccl.show_ccl_queue() を呼び出します。------ ------- ------------------- -----------------------------------------
    | ID | TYPE | CONCURRENCY_COUNT | 一致 | 実行中 | 待機中 |
    ------ ------- ------------------- -----------------------------------------
    | 1 | キュー | 64 | 0 | 0 | 0 |
    | 2 | キュー | 64 | 0 | 0 | 0 |
    | 3 | キュー | 64 | 0 | 0 | 0 |
    | 4 | キュー | 64 | 0 | 0 | 0 |
    ------ ------- ------------------- -----------------------------------------
    セットの4列 (0.00秒) 

実践

機能テスト

ステートメントキューは、ステートメントアウトライン機能と連携して、アプリケーションコードのオンライン更新をサポートできます。 詳細については、「ステートメントアウトライン」をご参照ください。 次の例では、Sysbenchを使用してupdate_non_indexスクリプトを実行します。

  • テスト環境

    • テーブルのスキーマ

      テーブル 'sbtest1' の作成 (
        'id' int(10) 符号なしNOT NULL AUTO_INCREMENT、
        'k' int (10) unsigned NOT NULL DEFAULT '0',
        'c' char(120) NOT NULL DEFAULT ''、
        'pad'char (60) NOT NULL DEFAULT ''、
        主要なキー ('id') 、
        キー 'k_1 ' ('k')
      エンジン=InnoDB AUTO_INCREMENT=2デフォルト料金=utf8 MAX_ROWS=1000000; 
    • ステートメント

      更新sbtest1 SET c='xyz' WHERE id=0;
    • Script

      . /sysbench \
      -- mysql-host= {$ip} \
      -- mysql-port= {$port} \
      -- mysql-db=test \
      -- test=./sysbench/share/sysbench/update_non_index.lua \
      -- oltp-tables-count=1 \
      -- oltp_table_size=1 \
      -- num-threads=128 \
      -- mysql-user=u0 
  • テストの実行手順

    1. オンラインモードでステートメントアウトラインを作成します。

      mysql> CALL DBMS_OUTNN.add_optimizer_outline ('test', '', 1, 
                                                   ' /* + ccl_queue_field(id) */ ' 、
                               "UPDATE sbtest1 SET c='xyz' WHERE id=0");
      クエリOK、影響を受ける0行 (0.01秒) 
    2. 作成したステートメントアウトラインを表示します。

      mysql> dbms_outln.show_outline() を呼び出します。------ -------- ------------------------------------------------------------------ ---------------------------------- -------------------------------- ------------------ --------------------------------------------- +
      | ID | スキーマ | DIGEST | タイプ | スコープ | POS | ヒント | ヒット | オーバーフロー | DIGEST_TEXT |
      ------ -------- ------------------------------------------------------------------ ---------------------------------- -------------------------------- ------------------ --------------------------------------------- +
      | 1 | test | 7b945614749e541e0600753367884acff5df7e7ee2f5fb0af5ea58897910f023 | OPTIMIZER | | 1 | /* + ccl_queue_field(id) */ | 0 | 0 | UPDATE 'sbtest1' SET 'c' = ? どこ 'id' = ? |
      ------ -------- ------------------------------------------------------------------ ---------------------------------- -------------------------------- ------------------ --------------------------------------------- +
      1行セット (0.00秒) 
    3. ステートメントのアウトラインが有効になっていることを確認します。

      mysql> UPDATE sbtest1 SET c='xyz' WHERE id=0について説明します。---- ----------- ---------------------------------------------------------------------------------------------------------------
      | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
      ---- ----------- ---------------------------------------------------------------------------------------------------------------
      | 1 | UPDATE | sbtest1 | NULL | range | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using where |
      ---- ----------- ---------------------------------------------------------------------------------------------------------------
      セットの1列、1警告 (0.00秒)
      
      mysql> 警告を表示します。+ ------ ------ + ----------------------------------------------------------------------------------------------------------------------------- +
      | レベル | コード | メッセージ |
      + ------ ------ + ----------------------------------------------------------------------------------------------------------------------------- +
      | 注 | 1003 | update /* + ccl_queue_field(id) */ 'test'.'sbtest1' set 'test'.'sbtest1'.'c' = 'xyz' ここで ('test'.'sbtest1'.'id' = 0) |
      + ------ ------ + ----------------------------------------------------------------------------------------------------------------------------- +
      1行セット (0.00秒) 
    4. 使用されているステートメントキューのステータスを照会します。

      mysql> dbms_ccl.show_ccl_queue() を呼び出します。------ ------- ------------------- -----------------------------------------
      | ID | TYPE | CONCURRENCY_COUNT | 一致 | 実行中 | 待機中 |
      ------ ------- ------------------- -----------------------------------------
      | 1 | キュー | 64 | 0 | 0 | 0 |
      | 2 | キュー | 64 | 0 | 0 | 0 |
      | 3 | キュー | 64 | 0 | 0 | 0 |
      | 4 | キュー | 64 | 0 | 0 | 0 |
      ------ ------- ------------------- -----------------------------------------
      セットの4列 (0.00秒) 
    5. テストを開始します。

      sysbench \
      -- mysql-host= {$ip} \
      -- mysql-port= {$port} \
      -- mysql-db=test \
      -- test=./sysbench/share/sysbench/update_non_index.lua \
      -- oltp-tables-count=1 \
      -- oltp_table_size=1 \
      -- num-threads=128 \
      -- mysql-user=u0 
    6. テスト結果を確認します。

      mysql> dbms_ccl.show_ccl_queue() を呼び出します。------ ------- ------------------- -----------------------------------------
      | ID | TYPE | CONCURRENCY_COUNT | 一致 | 実行中 | 待機中 |
      ------ ------- ------------------- -----------------------------------------
      | 1 | キュー | 64 | 10996 | 63 | 4 |
      | 2 | キュー | 64 | 0 | 0 | 0 |
      | 3 | キュー | 64 | 0 | 0 | 0 |
      | 4 | キュー | 64 | 0 | 0 | 0 |
      ------ ------- ------------------- -----------------------------------------
      セットの4列 (0.03秒)
      
      mysql> dbms_outln.show_outline() を呼び出します。------ --------- ---------- ---------------------------------------------------------------- --------------------------------------------- +
      | ID | スキーマ | DIGEST | タイプ | スコープ | POS | ヒント | ヒット | オーバーフロー | DIGEST_TEXT |
      ------ --------- ---------- ---------------------------------------------------------------- --------------------------------------------- +
      | 1 | test | xxxxxxxxx | OPTIMIZER | | 1 | /* + ccl_queue_field(id) */ | 115795 | 0 | UPDATE 'sbtest1' SET 'c' = ? どこ 'id' = ? |
      ------ --------- ---------- ---------------------------------------------------------------- --------------------------------------------- +
      1行セット (0.00秒) 
      説明

      クエリ結果に基づいて、合計115,795のステートメントがステートメントアウトラインのルールにヒットし、合計10,996のステートメントがステートメントキューのルールにヒットし、合計63のステートメントが同時に実行され、4つのステートメントがキューで待機しています。

パフォーマンステスト

  • テスト環境

    • アプリケーションは、Alibaba Cloud ECS (Elastic Compute Service) インスタンスにデプロイされています。

    • RDSインスタンスは、8 CPUコアと16 GBのメモリを提供し、拡張SSD (ESSD) を使用します。

    • RDSインスタンスはRDS High-availability Editionを実行し、非同期データレプリケーションを使用します。

  • テスト ケース

    次のテストケースは、IDが1に設定されているレコードに対して同時更新を実行するために使用されます。

    pathtest = string.match(test, "(.*/)")
    
    pathtestの場合
     dofile(pathtest .. "oltp_common.lua")
    else
     require("oltp_common")
    終了
    
    関数thread_init()
     drv = sysbench.sql.driver()
     con = drv:connect()
    終了
    
    関数event()
     ローカルval_name
     val_name = "'sdnjkmoklvnseajinvijsfdnvkjsnfjvn" .. sb_rand_uniform(1、4096) .. "'"
     query = "UPDATE sbtest1 SET c=" .. val_name .. "WHERE id=1"
     rs = db_query (クエリ)
    終了 
  • テスト結果

    ステートメントキュー機能を有効にすると、1秒あたりのクエリ数 (QPS) が大幅に増加し、同時クエリの数が多い場合はその増加が顕著になります。

    説明

    ステートメントキュー機能が無効になっている場合、ストレステストのスレッド数が4,096すると、プライマリ /セカンダリの切り替えが発生します。 その結果、QPSは0となる。