MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  プリペアドステートメントおよびストアドプログラムのキャッシュ

8.10.3 プリペアドステートメントおよびストアドプログラムのキャッシュ

セッション中にクライアントが複数回実行する可能性がある特定のステートメントに対し、サーバーはステートメントを内部構造に変換し、実行時にその構造が使用されるようにキャッシュします。 キャッシュによって、セッション中にそれが再度必要になった場合に、ステートメントを再変換するオーバーヘッドが避けられるため、サーバーはより効率的に実行できます。 変換とキャッシュは、次のステートメントに対して行われます。

  • SQL レベルで処理されるもの (PREPARE ステートメントを使用して) とバイナリクライアント/サーバープロトコルを使用して処理されるもの (mysql_stmt_prepare() C API 関数を使用して) の両方のプリペアドステートメント。 max_prepared_stmt_count システム変数は、サーバーがキャッシュするステートメントの合計数を制御します。 (すべてのセッションでのプリペアドステートメントの合計数。)

  • ストアドプログラム (ストアドプロシージャーおよび関数、トリガー、およびイベント)。 この場合、サーバーはプログラム本体全体を変換し、キャッシュします。 stored_program_cache システム変数は、サーバーがセッションあたりにキャッシュするストアドプログラムのおおよその数を示します。

サーバーは、セッション単位でプリペアドステートメントおよびストアドプログラム用のキャッシュを保守します。 1 つのセッションでキャッシュされたステートメントは、ほかのセッションからアクセスできません。 セッションが終了すると、サーバーはそのためにキャッシュされたすべてのステートメントを破棄します。

サーバーがキャッシュされた内部ステートメント構造を使用する場合、構造が古くなっていないことに注意する必要があります。 ステートメントによって使用されているオブジェクトにメタデータの変更があり、現在のオブジェクト定義と内部ステートメント構造で表されている定義に不一致が発生することがあります。 メタデータの変更は、テーブルの作成、削除、変更、名前変更、切り捨てを行う DDL ステートメントや、テーブルの解析、最適化、修復を行う DDL ステートメントなどに対して発生します。 テーブルの内容の変更 (INSERTUPDATE などによる) ではメタデータが変更されず、SELECT ステートメントも変更されません。

次にこの問題を説明します。 クライアントがこのステートメントを準備するとします。

PREPARE s1 FROM 'SELECT * FROM t1';

SELECT * は内部構造からテーブル内のカラムのリストに展開します。 テーブル内のカラムのセットが ALTER TABLE によって変更されている場合、プリペアドステートメントが古くなります。 クライアントが次回 s1 を実行したときにサーバーがこの変更を検出しない場合、プリペアドステートメントは誤った結果を返します。

プリペアドステートメントによって参照されているテーブルやビューのメタデータの変更に原因がある問題を避けるため、サーバーはこれらの変更を検出し、次回の実行時にステートメントを自動的に再準備します。 つまり、サーバーはステートメントを再解析し、内部構造を再構築します。 再解析は、キャッシュ内に新しいエントリのための空きを作るために暗黙的に、または FLUSH TABLES によって明示的に、参照されているテーブルやビューがテーブル定義キャッシュからフラッシュされたあとにも行われます。

同様に、ストアドプログラムによって使用されているオブジェクトに変更が発生した場合、サーバーはプログラム内の影響のあるステートメントを再解析します。

サーバーは式内のオブジェクトのメタデータの変更も検出します。 これらは、DECLARE CURSOR などのストアドプログラムに固有のステートメントや IFCASE、および RETURN などのフロー制御ステートメントで使用できます。

ストアドプログラム全体の再解析を避けるため、サーバーは必要に応じて、プログラム内の影響のあるステートメントや式のみを再解析します。 例:

  • テーブルまたはビューのメタデータが変更されているとします。 再解析は、テーブルやビューにアクセスするプログラム内の SELECT * に対して行われますが、テーブルやビューにアクセスしない SELECT * に対しては行われません。

  • ステートメントが影響を受ける場合、サーバーは可能なかぎり部分的にのみそれを再解析します。 この CASE ステートメントを考慮します。

    CASE case_expr
      WHEN when_expr1 ...
      WHEN when_expr2 ...
      WHEN when_expr3 ...
      ...
    END CASE

    メタデータの変更が WHEN when_expr3 にのみ影響する場合、その式が再解析されます。case_expr およびその他の WHEN 式は再解析されません。

再解析では、元の内部形式への変換に有効であったデフォルトのデータベースと SQL モードが使われます。

サーバーは最大 3 回再解析を試みます。 すべての試みが失敗した場合、エラーが発生します。

再解析は自動ですが、それが行われた場合、プリペアドステートメントとストアドプログラムのパフォーマンスが低下します。

プリペアドステートメントの場合、Com_stmt_reprepare ステータス変数が再準備の数を追跡します。


関連キーワード:  ステートメント, テーブル, キャッシュ, サーバー, インデックス, 変更, InnoDB, 解析, プリペアドステートメント, ストアドプログラム