ホット行は、頻繁に更新または変更されるデータベース内の行です。 並行性の高いシナリオでは、複数のトランザクションがホット行を同時に更新しようとする可能性があり、これにより、行ロックの競合と待ち時間が大幅に発生します。 この競合は、システム性能を著しく低下させ得ます。 この問題を解決するために、PolarDBはデータベースカーネルレベルで革新的な最適化を実装して、ロックの競合を軽減し、システムパフォーマンスを向上させます。
背景情報
痛みのポイント:
トランザクションがデータベース内の行を更新すると、トランザクションがコミットまたはロールバックされるまで、行はロックされたままになります。 複数のトランザクションが同時に同じ行を更新しようとすると、1つのトランザクションのみが続行できます。 他のトランザクションは待機する必要があります。 同じホット行での更新のこのシリアル化では、従来のデータベースとテーブルのシャーディングポリシーは、パフォーマンスに限られた利点しか提供しません。
eコマースプラットフォームでは、購入制限やフラッシュセールなどのプロモーション戦略により、データベース内のホットな行を短期間で更新するリクエストが急増することがよくあります。 この結果、行ロックの競合が激しくなり、待ち時間が長くなります。 更新要求の待ち時間が長くなると、システムのパフォーマンスが低下し、ユーザーエクスペリエンスに悪影響を及ぼします。
ハードウェアの強化は、前述の問題に対する効果的な解決策ではありません。 この問題を解決するために、PolarDBはデータベースカーネルレベルで革新的な最適化を実装します。 これにより、システムは、特定の時間間隔で、ホット行の更新要求と、同じホット行のグループ更新要求とを自動的に識別することができます。 更新の異なるグループは、パイプライン手法を使用することによって並列に処理されます。 最適化により、トランザクションの待ち時間が短縮され、システムパフォーマンスが大幅に向上します。
解決策
シリアル処理からパイプライン処理への移行
並列処理は、データベースシステムのパフォーマンスを向上させる最も効果的な方法です。 ただし、システムが同じホット行を並行して更新する要求を処理するときに問題が発生します。 PolarDBは、ホット行の更新要求の並列処理を最大化する革新的なパイプラインアプローチを使用して、上記の問題を解決します。
ホット行の更新に使用されるSQL文は、
autocomit
またはCOMMIT_ON_SUCCESSラベルでマークされます。 最適化されたMySQLカーネルレイヤーは、マークされた更新リクエストを自動的に認識できます。 レイヤーは、特定の時間間隔で更新要求を収集し、プライマリキーまたは一意のキーに基づいて、更新要求をさまざまなバケットにハッシュ
します。 各バケット内の更新は、到着順序に基づいてグループ化され、処理されます。更新要求を処理するためにパイプライン手法を使用するために、2つの実行ユニットがグループ化されたオペレーションを管理するために使用されます。 第1のグループの更新要求がコミットされる準備ができると、第2のグループは新しい更新要求の収集を開始します。 第2のグループの更新要求がコミットされる準備ができたとき、第1のグループの更新要求がコミットされ、新しい更新要求が収集されます。 2つのグループは、並列処理を可能にする周期的に動作します。
マルチコアCPUは業界で広く使用されています。 このパイプライン手法は、ハードウェア資源を最大限に活用し、CPU利用率を高め、データベースシステムの並列処理能力を改善し、データベースシステムのスループットを最大化することができます。
行ロック取得の待ち時間を減らす
データベース内の行が更新されると、データの整合性を確保するために行がロックされます。 別の操作が同じ行にアクセスしようとする場合、操作はロックが使用可能になるまで待機する必要があります。 ロック要求を直ちに処理できない場合、要求は待機状態に入ります。 これにより、処理遅延が増加し、デッドロック検出がトリガーされ、追加のリソースが消費されます。
解決策は、時系列に基づいて更新をグループ化する方法を導入します。 グループ内の最初の更新要求はリーダーと呼ばれます。 リーダーは行を読み取り、ロックします。 同じグループ内の後続の更新要求は、フォロワーと呼ばれます。 フォロワーが行のロックを要求すると、最初にリーダーがすでにロックを保持しているかどうかを確認します。 リーダーがロックを持っている場合、フォロワーはすぐにロックを取得します。
この戦略は、行ロックが要求される回数を最小限に抑え、ロックを取得するために必要な時間を短縮します。 その結果、データベースシステム全体の性能が向上します。
B-treeインデックスの横断を減らす
MySQLは、B-treeインデックスに基づいてデータを管理します。 各クエリ中に、MySQLはすべてのインデックスをトラバースして必要な行を見つけます。 テーブルが大きく、複数のインデックスレベルを持つ場合、インデックスをトラバースするのに長時間が必要になります。
前のセクションで説明した更新要求グループ化メカニズムでは、各グループのリーダーのみがインデックスをトラバースして、関連する行を見つける必要があります。 リーダーが行を更新した後、更新された行はメモリにキャッシュされます。 同じグループ内のフォロワーが行ロックを取得した後、フォロワーはすべてのインデックスをトラバースする必要なく、メモリから行を直接読み取ることができます。
このメカニズムは、インデックストラバーサルの数と時間の消費を減らします。
前提条件
PolarDBクラスターは、次のデータベースエンジンバージョンのいずれかを実行します。
リビジョンバージョンが20200601以降のPolarDB for MySQL 5.6。
リビジョンバージョンが5.7.1.0.17以降のPolarDB for MySQL 5.7。
リビジョンバージョンが8.0.1.1.10以降のPolarDB for MySQL 8.0。
PolarDB for MySQLクラスターでは、バイナリログ機能が有効になっています。
rds_ic_reduce_hint_enableパラメーターはOFFに設定されています。
クラスターのマイナーデータベースエンジンのバージョンを更新する方法については、「マイナーバージョンの更新」をご参照ください。
クラスターパラメーターの変更方法については、「クラスターパラメーターとノードパラメーターの設定」をご参照ください。
MySQL設定ファイルとの互換性のため、PolarDBコンソールコンソールのすべてのパラメーターの先頭にloose_ があります。 PolarDBコンソールでrds_ic_reduce_hint_enableパラメーターを変更する場合は、loose_ プレフィックスがloose_rds_ic_reduce_hint_enableのMySQL互換バージョンを使用します。
制限事項
ホット行更新の最適化機能は、次のシナリオではサポートされていません。
ホット行を含むテーブルはパーティション分割されます。
ホット行を含むテーブルに対してトリガーが定義されます。
ステートメントキューメカニズムは、ホット行に適用されます。
グローバルバイナリロギングが有効で、セッションレベルのバイナリロギングが無効の場合、ホット行更新最適化機能を
update
ステートメントに使用することはできません。
使用量
ホット行更新の最適化機能を有効にする
PolarDBコンソールで次のパラメーターを使用して、ホット行更新の最適化機能を有効または無効にできます。
パラメーター
説明
ホットスポット
ホット行更新最適化機能を有効にするかどうかを指定します。 有効な値:
オン
OFF (デフォルト)
説明クラスターパラメーターの変更方法の詳細については、「クラスターパラメーターとノードパラメーターの設定」をご参照ください。
MySQL設定ファイルとの互換性のため、PolarDBコンソールコンソールのすべてのパラメーターの先頭にloose_ があります。 PolarDBコンソールでhotspotパラメーターを変更する場合は、loose_ プレフィックスがloose_hotspotのMySQL互換バージョンを使用します。
ホット行更新最適化機能には、3つの新しいオプティマイザヒントが含まれます。
ヒント
必須ですか?
説明
必須/任意
更新が成功すると、トランザクションをコミットします。
省略可能
更新が失敗したときにトランザクションをロールバックします。
省略可能
要求が1行のみを更新することを明示的に指定します。 複数の行または行が更新されない場合、更新は失敗します。
説明トランザクションのヒントが有効になると、トランザクションは自動的にコミットされます。 したがって、トランザクションの最後のSQLステートメントにヒントを配置する必要があります。
例:
sbtest
テーブルの列c
の値を更新します。UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
関連する API
カスタムパラメーター設定
PolarDBコンソールで次のパラメーターを変更することはできません。 パラメーターを変更するには、クォータセンターに移動し、PolarDBホットスポット行パラメーター調整クォータ名を見つけて、[操作] 列の [適用] をクリックします。
パラメーター | 説明 |
hotspot_for_自動コミット |
|
hotspot_update_max_wait_time | グループ内のリーダーが、同じデータ行に対する更新要求のグループ化および処理中のプロセス中に、フォロワーがグループに参加するのを待つ最大時間。
|
hotspot_lock_type | 同じデータ行に対する更新要求のグループ化および処理中に新しい種類の行ロックを使用するかどうかを指定します。 有効な値:
説明
|
パラメーター設定の表示
次のステートメントを実行して、ホット行更新最適化機能のパラメーター設定を表示できます。
SHOW variables LIKE "hotspot%";
サンプル結果:
+------------------------------+-------+
|Variable_name | Value |
+------------------------------+-------+
|hotspot | OFF |
|hotspot_for_autocommit | OFF |
|hotspot_lock_type | OFF |
|hotspot_update_max_wait_time | 100 |
+------------------------------+-------+
ホット行更新最適化機能の使用状況の表示
次のステートメントを実行して、ホット行更新最適化機能の使用状況を表示できます。
SHOW GLOBAL status LIKE 'Group_update%';
パフォーマンステスト
テストテーブルとステートメント:
テーブル
CREATE TABLE sbtest (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id));
文
UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
テストツール: Sysbench。
テストシナリオと結果
シナリオ1: 1つのホット行と8コアCPU
このシナリオでは、8コアCPUが使用され、ホット行を更新するために多数の同時要求が送信されます。 ホット行更新最適化機能を有効にすると、データベースのパフォーマンスは最大64倍向上します。
シナリオ2: 1つのホット行と32コアCPU
このシナリオでは、32コアのCPUが使用され、ホット行を更新するために多数の同時要求が送信されます。 ホット行更新最適化機能を有効にすると、1秒あたりのピーククエリ (QPS) が63倍に増加します。 同時リクエスト数が8,000に達すると、データベースのパフォーマンスは46倍向上します。
シナリオ3: 8つのホット行と32コアCPU
このシナリオでは、32コアのCPUが使用され、8つのホット行を更新するために多数の同時要求が送信されます。 ホット行更新最適化機能が有効になった後、ピークQPSは20倍改善されます。
ホット行更新最適化機能が無効になっており、同時リクエストの数が16,000に達すると、データベース障害が発生し、結果は返されません。 対照的に、ホット行更新最適化機能が有効になっている場合、行データは予想通りに更新され、QPS値は安定したままです。