および は、SQL スロットリング機能を提供します。この機能を使用すると、特定のエンドポイントに対してスロットリングルールを設定し、異常なトラフィックがサービスに影響を与えるのを防ぐことができます。このトピックでは、SQL スロットリング機能の使用方法について説明します。
概要
SQL スロットリング機能を使用すると、特定のエンドポイントに対してスロットリングルールを設定できます。SQL テンプレートを使用して、現在のエンドポイントで実行される SQL ステートメントを照合し、その最大同時実行数または 1 秒あたりのクエリ数 (QPS) を制限できます。この機能は、次のシナリオで使用できます。
-
低速 SQL クエリにより PolarDB クラスターのデータベースの負荷が高くなり、通常の業務に影響が出ている場合。
-
特定タイプの危険な SQL クエリに利用可能なリソースを制限したり、その実行を完全にブロックしたりする必要がある場合。
操作手順
SQL スロットリング機能を有効にするには、お問い合わせください。
-
PolarDB コンソールにログインします。左側メニューで、クラスター をクリックします。クラスターが配置されている [リージョン] を選択し、クラスター ID をクリックしてクラスター詳細ページを開きます。
-
左側メニューで、 をクリックします。
-
SQL スロットリング タブで、新しい をクリックして新しい SQL スロットリングルールを作成します。
-
SQL スロットリングルールの作成 ダイアログボックスで、次のパラメーターを設定し、[OK] をクリックします。
カテゴリ
パラメーター
説明
[基本情報]
[ルール名]
スロットリングルールの名前。名前は次の要件を満たす必要があります:
-
30 文字以内であること。
-
大文字、小文字、数字のみを含むこと。
[説明]
オプション。管理を容易にするためのスロットリングルールの説明。64 文字以内で入力する必要があります。
[EndpointId]
スロットリングルールを適用するエンドポイントを選択します。
説明-
スロットリングルールは、アクティブリクエストベースの負荷分散を使用するクラスターエンドポイントまたはカスタムエンドポイント (読み書きまたは読み取り専用) に対してのみ設定できます。SQL スロットリングは、プライマリエンドポイントや、接続ベースの負荷分散を使用する読み取り専用エンドポイントではサポートされていません。
-
ルールはエンドポイント固有です。あるエンドポイントに設定されたルールは、そのエンドポイントへの接続にのみ影響します。
[設定]
[ルールタイプ]
ルールタイプを選択します。同時実行数制限 と QPS 制限 がサポートされています。
説明[接続あたりの QPS のスロットリング] は、単一接続の 1 秒あたりのリクエスト数を制限します。このタイプは、接続プールまたは永続的な接続が使用されるシナリオに適しています。短時間の接続の場合は、[アクティブな同時実行ステートメントのスロットリング] を使用してください。
[現在のモード]
SQL テンプレートの一致モードを選択します。テンプレートマッチング と 全文マッチング がサポートされています。2つのモードの違いの詳細については、「テンプレートマッチと全文一致の比較」をご参照ください。
[データベースアカウント名]
ルールを適用するアカウントを指定します。最大 10 個のアカウントをカンマで区切って指定できます。空のままにした場合、ルールはすべてのアカウントに適用されます。
[データベース名]
ルールを適用するデータベースを指定します。最大 10 個のデータベースをカンマで区切って指定できます。空のままにした場合、ルールはすべてのデータベースに適用されます。
[SQL テンプレート]
SQL テンプレートを設定します。詳細については、「SQLテンプレートと一致モード」をご参照ください。
[待ち行列の最大長]
待機キューの最大長。値の範囲は 0~1024 です。一致した SQL クエリの同時実行数または QPS がルールの上限に達すると、プロキシはクエリを待機キューに追加して再試行します。キュー内のクエリ数がこの上限を超えると、新しいリクエストは失敗し、エラーが返されます。このパラメーターを正しく設定することで、多数の SQL クエリがスロットリングされた場合に、待機キューが無限に増大してデータベースプロキシでメモリ不足 (OOM) エラーが発生するのを防ぎます。
[Maximum Active Concurrent Statements]
アクティブな同時実行ステートメントの最大数。
説明このパラメーターは、同時実行数制限 で [アクティブな同時実行ステートメントのスロットリング] を選択した場合にのみ必須です。
[各接続の最大 QPS]
各接続の最大 QPS。
説明このパラメーターは、QPS 制限 で [接続あたりの QPS のスロットリング] を選択した場合にのみ必須です。
-
仕組み
SQL スロットリングは、データベースプロキシレベルで実装されています。データベースプロキシでスロットリングルールを設定して、転送される特定の SQL ステートメントの同時実行数または QPS を制御します。このプロセスでは、データベースクラスターの読み書きノードまたは読み取り専用ノードにオーバーヘッドは発生しません。そのため、ルールはプロキシ経由でトラフィックをルーティングするクラスターエンドポイントとカスタムエンドポイントに対してのみ設定できます。
SQLテンプレートと一致モード
テンプレートマッチと全文一致の比較
SQL テンプレートは、 または クラスターの標準構文に従う任意の SQL ステートメントです。データベースプロキシは、選択された一致モードに基づいてテンプレートを異なる方法で前処理します。
-
次の SQL テンプレートでスロットリングルールを設定するとします:
SELECT * FROM tbl WHERE id < 1;-
[テンプレートマッチ] を選択すると、SQL テンプレートが正規化されます。余分なスペースやコメントが削除され、単一引用符で囲まれた文字列や数字などの定数がワイルドカードに置き換えられます。結果は次のようになります:
-- テンプレート化された結果 SELECT * FROM tbl WHERE id < ? -
[全文一致] を選択すると、SQL テンプレートも正規化されますが、定数は置き換えられません。結果は次のようになります:
-- 正規化された結果のみ SELECT * FROM tbl WHERE id < 1
その後、データベースプロキシは、その後の照合で使用するために処理された SQL の一意の識別子を生成します。
-
-
スロットリングルールが有効になると、データベースプロキシは受信した各 SQL ステートメントを同様に前処理します。たとえば、次の受信 SQL ステートメントを例にとります:
SELECT * FROM tbl WHERE id < 100;2種類の正規化された SQL が生成され、それらの一意の識別子が計算されて、スロットリングルールと照合されます。
-- テンプレート化された結果 SELECT * FROM tbl WHERE id < ? -- 正規化された結果のみ SELECT * FROM tbl WHERE id < 100
SQL スロットリングルールが有効になると、データベースプロキシは SQL ステートメントを転送する前に、設定されたルールに対してステートメントを評価します。ルールが[テンプレートマッチ]で設定されている場合、照合にはテンプレート化された結果が使用されます。ルールが[全文一致]で設定されている場合、正規化された結果のみが使用されます。一致が見つかると、その同時実行数または QPS が計算され、プロキシは対応するスロットリングアクションを実行します。
したがって、前述の例の SQL ステートメントと SQL テンプレートでは、ルールが[テンプレートマッチ]で設定されている場合にのみ一致が見つかります。
パラメータ化クエリ
SQL テンプレートは、標準の PostgreSQL パラメータバインディング構文を使用するパラメータ化クエリをサポートします。
SELECT * FROM tbl WHERE id < $1 AND name = $2 LIMIT 1;
[テンプレートマッチ] と [全文一致] の両方のモードで、パラメータ化された部分はワイルドカードとしてフォーマットされます。
-- テンプレート化された結果
SELECT * FROM tbl WHERE id < ? AND name = ? limit ?
-- 正規化された結果のみ
SELECT * FROM tbl WHERE id < ? AND name = ? limit 1
したがって、次の SQL ステートメントの場合:
SELECT * FROM tbl WHERE id < $1 AND name = 2 LIMIT 100;
[Current Mode] が [テンプレートマッチ] に設定されている場合、一致が見つかります。[Current Mode] が [全文一致] に設定されている場合、一致は見つかりません。
SQL テンプレートでパラメーターマーカーとして ? 文字を使用することはできません。
-- 無効な SQL テンプレートです。これは標準の PostgreSQL 構文に準拠しておらず、どの SQL とも一致しません。
SELECT ?, ?, ?;
-- 有効な SQL テンプレート
SELECT $1, $2, $3;
プリペアドステートメント
アプリケーションがプリペアドステートメントを使用する場合、PREPARE ステートメント自体はスロットリングをトリガーしません。EXECUTE ステートメントのみがスロットリングをトリガーします。EXECUTE ステートメントの場合、対応する PREPARE ステートメントの SQL 部分がフォーマットまたはテンプレート化されて、ルールと照合されます。
プリペアドステートメントの詳細については、「PREPARE」をご参照ください。
例
次の SQL テンプレートでスロットリングルールを設定し、一致モードに[テンプレートマッチ]を選択します。
SELECT * FROM tbl WHERE id < $1 AND name > $2;
次の SQL ステートメントの場合:
-- PREPARE ステートメントはスロットリングをトリガーしません。
PREPARE s1 AS SELECT * FROM tbl WHERE id < $1 AND name > 100;
-- EXECUTE ステートメントは、対応する PREPARE ステートメントの SQL 部分を使用してスロットリングルールと照合します。
EXECUTE s1;
EXECUTE s1;
EXECUTE s1;
3つの EXECUTE ステートメントはスロットリングルールに一致し、スロットリングされます。
同様に、スロットリングルールの SQL テンプレートで PREPARE ステートメントを使用する場合、PREPARE ステートメントの SQL 部分のみがフォーマットまたはテンプレート化されます。したがって、ルールを作成する際、次の2つの SQL テンプレートは同等です。
-- テンプレート 1
PREPARE s1 AS SELECT * FROM tbl WHERE id < $1 AND name > $2;
-- テンプレート 2
SELECT * FROM tbl WHERE id < $1 AND name > $2;
拡張問い合わせプロトコルのサポート
プリペアドステートメントと同様に、アプリケーションドライバーが拡張問い合わせプロトコルを使用する場合、Execute メッセージのみがスロットリングをトリガーします。各 Execute メッセージについて、データベースプロキシは対応する Parse メッセージを見つけ、その SQL を使用してスロットリングルールと照合します。したがって、SQL スロットリングは拡張問い合わせプロトコルをサポートしているため、通常、アプリケーションが使用するプロトコルを気にする必要はありません。
拡張問い合わせプロトコルの詳細については、「コミュニティのドキュメント」をご参照ください。
制限事項
現在、SQL スロットリング機能には次の制限事項があります。
-
複数ステートメントのスロットリングはサポートされていません。複数ステートメントを使用する場合、設定されたスロットリングルールはトリガーされません。
複数ステートメントとは、セミコロンで区切られた複数の SQL ステートメントを含む単一の SQL テキストを指します。以下は、JDBC ドライバーを使用して実行される複数ステートメントの例です。
Statement statement = connection.createStatement(); statement.execute("select 1; select 2; select 3");複数ステートメントは、複数のスロットリングルールに同時に一致する可能性があります。予期しない動作を防ぐため、複数ステートメントのスロットリングはサポートされていません。
-
トランザクション制御文やストアドプロシージャなど、一部の特殊なステートメントのスロットリングはサポートされていません。COMMIT などのトランザクション制御文をスロットリングすると、トランザクションが正常に終了しなくなります。このため、これらはスロットリングルールから除外されます。
-
クライアントまたはドライバーがステートメントのバッチ処理モードを使用する場合、バッチ処理された SQL クエリは、一致した最初のスロットリングルールのみをトリガーします。以下は、JDBC ドライバーを使用したステートメントのバッチ処理の例です。
Statement statement = connection.createStatement(); statement.addBatch("select 1"); statement.addBatch("select 2"); statement.addBatch("select 3"); int[] result = statement.executeBatch(); statement.close(); connection.close();複数ステートメントと同様に、ステートメントのバッチ処理を使用する場合、ドライバーは通常、複数の SQL クエリの拡張問い合わせプロトコルメッセージを結合して一度に送信します。これにより、複数のスロットリングルールが同時に一致する状況が発生する可能性もあります。この場合、最初に一致したスロットリングルールのみが有効になります。上記の例では、エンドポイントに次の3つの SQL テンプレートのスロットリングルールが設定されている場合:
-- テンプレート 1 SELECT 1; -- テンプレート 2 SELECT 2; -- テンプレート 3 SELECT 3;一致するのはテンプレート 1 のみです。
-
テンプレート内のキーワードの大文字と小文字は、スロットリングしたい SQL テキスト内のそれと一致している必要があります。
-
SQL テンプレートは、要素の数が異なる可能性がある
INやANYなどの可変長式のテンプレート化をサポートしていません。例:-- SQL テンプレート SELECT * FROM tbl WHERE id IN ($1, $2, $3); -- SQL1、テンプレートに一致可能 SELECT * FROM tbl WHERE id IN (1, 6, 8); -- SQL2、テンプレートに一致不可能 SELECT * FROM tbl WHERE id IN (1, 6, 8, 8); -
スロットリングルールが設定されていない場合、最初に追加するルールは既存の接続には適用されません。コンソールでいずれかのルールがすでに設定されている (有効または無効) 場合、その後のルールの追加、変更、または削除は、すべての接続に対してリアルタイムで有効になります。
説明-
アプリケーションが永続的な接続を使用しており、新しいルールをすぐに有効にしたい場合は、エンドポイントに任意のルールを設定して無効にすることを推奨します。そうすれば、その後に追加または変更するルールは、新規および既存の両方の接続に対して有効になります。
-
お使いの PolarProxy のバージョンが 2.3.58 以降の場合、スロットリングルールの追加、変更、削除は、すべての接続に対してリアルタイムで有効になります。
-
スロットリングの動作
SQL スロットリングは、SQL テンプレートと待機キューを使用して、QPS またはアクティブな同時実行数を制限します。SQL ステートメントは、その QPS または同時実行数がそのルールでカウントされる前に、スロットリングルールに一致する必要があります。同時実行数または QPS がルールで設定された上限を超えると、データベースプロキシは SQL ステートメントを待機キューに入れて、遅延後に再試行します。これにより、データベース上の同時実行数または QPS が設定された上限内に収まります。
待機キューの遅延時間は、ルールで設定された QPS または同時実行数に反比例します。特定のルールでキューで待機できる SQL ステートメントの最大数は、[Maximum Waiting Queue Length] パラメーターによって制限されます。この上限を超えると、プロキシは SQL ステートメントを転送せず、クライアントに次のエラーを返します。
SELECT 123;
Current query is being throttled and waiting queue is full.
上記のエラーは、現在の接続のトランザクション状態を中断したり変更したりしません。このエラーを受け取った後も、クライアントはトランザクションをコミットまたはロールバックすることを選択できます。
さらに、スロットリングルールで [Maximum Active Concurrent Statements] または [Maximum QPS per Connection] を 0 に設定した場合、ルールに一致する SQL ステートメントは拒否され、転送されません。クライアントは上記のエラーを直接受け取ります。この方法を使用して、特定のタイプの SQL ステートメントを完全にブロックできます。
-
待機キューには最小再試行間隔があります。高い最大 QPS を設定した場合、実際の QPS は設定値よりわずかに低くなる可能性があります。
-
高可用性のために、データベースプロキシは通常2つ以上のノードでデプロイされ、クライアント接続はそれらの間でランダムに分散されます。[Maximum Active Concurrent Statements] と 待ち行列の最大長 パラメーターはノードレベルで設定されます。各ノードは独立して同時実行数とキューの長さをカウントするため、実際の同時実行数を正確に制御することはできません。ノード数を N、単一ノードの設定を C (Maximum Active Concurrent Statements) および Q (Maximum Waiting Queue Length) と仮定します。クライアントの同時実行数の範囲は
[C+Q, N×(C+Q)]であり、データベースのアクティブな同時実行数の範囲は[C, N×C]です。 -
SQL スロットリングルールを設定すると、プロキシは、一致が見つかるかどうかに関係なく、各 SQL ステートメントをテンプレート化し、一意の識別子を生成し、ルールと照合する必要があります。そのため、SQL スロットリングを有効にすると、転送パフォーマンスが5%~10%低下する可能性があります。スロットリングは、低速 SQL クエリが通常の業務に大きな影響を与えている場合にのみ使用してください。低速 SQL クエリを解決したら、コンソールでスロットリングルールを無効にできます。無効化されたルールは有効になりませんが、保存されているため、いつでも再度有効にできます。