統計情報

統計情報を使う

MySQL Native Driver は、クライアントとサーバー間の通信に関する統計情報を収集する機能をサポートしています。収集できる統計情報は主に2つのタイプに分けられます。

  • クライアントの統計情報

  • 接続の統計情報

mysqli 拡張機能を使っている場合、これらの統計情報は以下の2つのAPIを呼び出すことで取得できます。

注意:

MySQL Native Driver を使っているすべての拡張機能が統計情報を収集します。たとえば、ext/mysqlext/mysqli を MySQL Native Driver を使ってコンパイルし、ext/mysqlext/mysqli の関数を呼び出すと、収集される統計情報の値が変わります。MySQL Native Driver を使ってコンパイルされた MySQL 拡張機能の呼び出しが、どの程度統計情報に影響を与えるかはわかりません。PDO MySQL Driver や ext/mysqlext/mysqli を、オプションで MySQL Native Driver を使うように設定することができます。こうすると、すべての拡張機能で統計情報を変化させることができます。

クライアントの統計情報にアクセスする

クライアントの統計情報にアクセスするには、mysqli_get_client_stats() 関数を呼び出す必要があります。この関数を呼び出すのに引数は必要ありません。

この関数は、統計情報の名前をキーとして対応するデータを値とする連想配列を返します。

クライアントの統計情報は phpinfo() 関数を呼び出してもアクセスできます。

接続の統計情報にアクセスする

接続の統計情報にアクセスするには mysqli_get_connection_stats() 関数を使います。この関数は接続ハンドルを引数にとります。

この関数は、統計情報の名前をキーとして対応するデータを値とする連想配列を返します。

結果セットをバッファリングさせるか否か

結果セットはバッファリングさせることもできますし、しないこともできます。デフォルトの設定では、ext/mysqlext/mysqli は通常の (プリペアドステートメントでない) クエリの場合結果セットをバッファリングします。バッファリングされた結果セットはクライアント側でキャッシュされます。クエリが実行された後、すべての結果がMySQLサーバから取得され、クライアント側でキャッシュに保存されます。結果セットをバッファリングすることの大きな利点は、一度クライアントが結果を取得すると、サーバがすべての結果セットに割り当てられたリソースを開放できることです。

一方、結果セットをバッファリングしない場合、結果セットはサーバ側にバッファリングするよりも長く残ります。仮にクライアント側でのメモリ使用量を削減したいが、サーバ側の負荷が高くなっても構わない場合、結果セットをバッファリングしないようにします。仮にサーバの負荷が高く、バッファリングしていない結果セットの量がサーバ側で多いことが分かっている場合、その負荷をクライアント側に移すことを検討すべきです。クライアントは通常の場合サーバよりも分散しやすいからです。ここでいう 負荷 とはメモリバッファに対するものだけでなく、サーバが結果セットを開放する前に他のリソース、たとえばファイルハンドルやスレッドを開きっぱなしにする必要があることも指しています。

プリペアドステートメントはデフォルトでは結果セットをバッファリングしません。しかし、mysqli_stmt_store_result() 関数を使えば、結果セットのバッファリングを有効にすることができます。

MySQL Native Driver が返す統計情報

以下の表で、mysqli_get_client_stats(), mysqli_get_connection_stats() 関数が返す統計情報のリストを示します。

MySQL Native Driver が返す統計情報: ネットワーク関連
統計情報 統計のカテゴリ 説明 注意点
bytes_sent Connection PHP から MySQLサーバに送信されたバイト数 圧縮プロトコルの効率をチェックするのに使えます
bytes_received Connection MySQLサーバから受け取ったバイト数 同上
packets_sent Connection MySQL のクライアントサーバプロトコルにおいて送信されたパケット数 クライアントサーバプロトコルの実装をデバッグするのに使われます
packets_received Connection MySQL のクライアントサーバプロトコルにおいて受信したパケット数 同上
protocol_overhead_in Connection MySQL のクライアントサーバプロトコルの受信側の通信にかかるオーバーヘッドをバイト単位で示します。現状はパケットヘッダ(4バイト)のみをオーバーヘッドと看做しています。 protocol_overhead_in = packets_received * 4で表されます。 同上
protocol_overhead_out Connection MySQL のクライアントサーバプロトコルの受信側の通信にかかるオーバーヘッドをバイト単位で示します。現状はパケットヘッダ(4バイト)のみをオーバーヘッドと看做しています。 protocol_overhead_out = packets_sent * 4で表されます。 同上
bytes_received_ok_packet Connection MySQL のクライアントサーバプロトコルにおけるOKパケットの受信量の合計をバイト単位で示します。 OKパケットはステータスメッセージも含むことができます。ステータスメッセージの長さは変化しうるため、OKパケットのサイズは固定ではありません。 クライアントサーバプロトコルの実装をデバッグするのに使われます。受信する合計バイト数には、パケットヘッダ(4バイト, protocol_overhead_in や protocol_overhead_out を参照) のサイズも含まれていることに注意してください
packets_received_ok Connection MySQL のクライアントサーバプロトコルにおけるOKパケットを受信した数です。 同上
bytes_received_eof_packet Connection MySQL のクライアントサーバプロトコルにおけるEOFパケットを受信量の合計をバイト単位で示します。EOFパケットはサーバのバージョンによってサイズが変わります。また、EOFパケットはエラーメッセージも伝えることができます。 同上
packets_received_eof Connection MySQL のクライアントサーバプロトコルにおけるEOFパケットの数を示します。EOFパケットの数は、PHPが期待するパケットを受け取らなかった場合であっても増加します。これは他のパケット数を示す統計情報と同じです。PHPが期待しないパケットの例は、エラーメッセージが挙げられます。 同上
bytes_received_rset_header_packet Connection MySQL のクライアントサーバプロトコルにおける結果セットにあるヘッダパケットの合計サイズをバイト単位で示します。パケットのサイズはペイロード(LOAD LOCAL INFILE, INSERT, UPDATE, SELECT, エラーメッセージ)に応じて変わります。 同上
packets_received_rset_header Connection MySQL のクライアントサーバプロトコルにおける結果セットにあるヘッダパケットの数を示します 同上
bytes_received_rset_field_meta_packet Connection MySQL のクライアントサーバプロトコルにおける結果セットにあるメタデータ(カラム情報) の合計サイズをバイト単位で示します。もちろん、メタデータのサイズは結果セットにあるカラムによって変わります。このパケットはペイロードが COM_LIST_FIELDS の場合(訳注:テーブルのカラム情報を得るためのMySQLプロトコル http://dev.mysql.com/doc/internals/en/text-protocol.html#com-field-list)の場合は、エラーメッセージかEOFパケットを返す可能性があります。 同上
packets_received_rset_field_meta Connection MySQL のクライアントサーバプロトコルにおける結果セットにあるメタデータ(カラム情報) のパケット数を示します。 同上
bytes_received_rset_row_packet Connection MySQL のクライアントサーバプロトコルにおける結果セットにある行情報パケットの合計サイズをバイト単位で示します。このパケットはエラー情報またはEOFパケットを送信する場合もあります。 bytes_received_rset_row_packet の数から、rows_fetched_from_server_normalrows_fetched_from_server_ps の値を引くことによって、エラー数やEOFパケットの数を割り出すことができます。 同上
packets_received_rset_row Connection MySQL のクライアントサーバプロトコルの結果セット行データパケットと、それらの合計サイズをバイト単位で示します。 同上
bytes_received_prepare_response_packet Connection MySQL のクライアントサーバプロトコルにおける、プリペアドステートメント初期化パケット(prepared statement init packets) が OK を返した合計サイズをバイト単位で示します。このパケットはエラーを送信する可能性もあります。このパケットのサイズは MySQL のバージョンによって変わります。: MySQL 4.1 では 9バイト、 MySQ 5.0 以降は 12 byte です。エラーが起きた回数を安全に知る方法はありません。たとえば、MySQL 5.0 以降の MySQL に常に接続している場合は、bytes_received_prepare_response_packet != packets_received_prepare_response * 12 の場合にエラーが起きていると推定できるかもしれません。ps_prepared_never_executedps_prepared_once_executed も参照してください。 同上
packets_received_prepare_response Connection MySQL のクライアントサーバプロトコルにおける、プリペアドステートメント初期化パケット(prepared statement init packets) が OK を返した数 同上
bytes_received_change_user_packet Connection MySQL のクライアントサーバプロトコルにおける、COM_CHANGE_USER パケットの合計サイズをバイト単位で示します。このパケットはエラーやEOFパケットを送信する可能性もあります。 同上
packets_received_change_user Connection MySQL のクライアントサーバプロトコルにおける、COM_CHANGE_USER パケットの数 同上
packets_sent_command Connection PHP から MySQL に送信されたMySQL クライアントサーバプロトコルコマンドの合計数。特定のどのコマンドが送信されたか、そしてそれらのうちどのくらいが実際に送信されたかを知る方法はありません。この統計値は、PHPバイナリで MySQLのサポートを無効にすることを確かめる手がかりを知るために、PHP がコマンドを送信しているかどうかを知る手段として使えるくらいです。また、データを MySQL に送信している間にエラーが起きた回数を知る方法もありません。記録されるエラーは command_buffer_too_small (後述) の値くらいです。 MySQL のクライアントサーバプロトコルのデバッグする用途だけに役立ちます。
bytes_received_real_data_normal Connection PHP クライアントが mysqlnd からテキストプロトコル経由で受け取ったペイロードの合計バイト数。 これは、プリペアドステートメントではないクエリから生成され、PHPクライアントが取得した結果セットに含まれる実際のデータサイズです。完全な結果セットは mysqlnd が MySQL から取得しますが、この統計値は PHP クライアントが mysqlnd から実際に取得した実際のデータのみを数えていることに注意してください。この統計値を増やすコードの例は以下のようになります:
$mysqli = new mysqli();
$res = $mysqli->query("SELECT 'abc'");
$res->fetch_assoc();
$res->close();

毎回取得(fetch)操作をするたびにこの値が増加します。

この統計値は、結果セットがクライアント上でバッファリングされただけで、実際に取得されていない場合は変化しません。たとえば、次のようなコードの場合です:

$mysqli = new mysqli();
$res = $mysqli->query("SELECT 'abc'");
$res->close();

この統計値は PHP 5.3.4 から利用可能です。

bytes_received_real_data_ps Connection PHP クライアントが mysqlnd からプリペアドステートメントプロトコル経由で受け取ったペイロードの合計バイト数。 これは、プリペアドステートメントプロトコルを使ってから生成され、PHPクライアントが取得した結果セットに含まれる実際のデータサイズです。この値は、PHPクライアントが読み取らなければ変化しません。完全な結果セットは mysqlnd が MySQL から取得しますが、この統計値は PHP クライアントが mysqlnd から実際に取得した実際のデータのみを数えていることに注意してください。bytes_received_real_data_normal も参照してください。この統計値は PHP 5.3.4 から利用可能です。

Result Set

MySQL Native Driver が返す統計情報: 結果セット
統計情報 統計のカテゴリ 説明 注意点
result_set_queries Connection 結果セットを生成したクエリの数。結果セットを生成するクエリの例: SELECT, SHOW. 結果セットのヘッダパケットを読み取っている間にエラーが発生した場合、この統計値はインクリメントされません たとえば、データベースに高い負荷をかけているクライアントを特定する目的で、PHP が MySQL に送信したクエリの数を間接的に測るのに使えます。
non_result_set_queries Connection 結果セットを生成しなかったクエリの数。結果セットを生成しないクエリの例:INSERT, UPDATE, LOAD DATA。結果セットのヘッダパケットを読み取っている間にエラーが発生した場合、この統計値はインクリメントされません。 同上
no_index_used Connection 結果セットを生成したが、インデックスを使わなかったクエリの数 (mysqld の起動オプション -log-queries-not-using-indexes も参照してください) こうしたクエリを記録したい場合、mysqli_report(MYSQLI_REPORT_INDEX) を使って ext/mysqli に例外をスローさせることができます。例外ではなく警告にとどめたい場合は、mysqli_report(MYSQLI_REPORT_INDEX ^ MYSQLI_REPORT_STRICT) を使ってください。  
bad_index_used Connection 結果セットを生成したが、良いインデックスを使わなかったクエリの数 (mysqld の起動オプション -log-slow-queries も参照してください) こうしたクエリを記録したい場合、mysqli_report(MYSQLI_REPORT_INDEX) を使って ext/mysqli に例外をスローさせることができます。例外ではなく警告にとどめたい場合は、mysqli_report(MYSQLI_REPORT_INDEX ^ MYSQLI_REPORT_STRICT) を使ってください。
slow_queries Connection 実行に long_query_time 秒以上かかり、少なくとも min_examined_row_limit 行以上調べる必要があるSQL mysqli_report()関数では記録できません
buffered_sets Connection 通常の クエリで返された結果セットのうち、バッファリングされたものの数。通常の というのは、右の「注意点」で述べている プリペアドステートメントのことではありません 結果セットをクライアント側にバッファリングするAPI呼び出しの例: mysql_query(), mysqli_query(), mysqli_store_result(), mysqli_stmt_get_result() 結果セットをクライアント側にバッファリングすると、サーバ側のリソースが迅速に解放され、結果セットを走査しやすくなります。欠点としては、クライアント側のメモリ消費が、バッファリングする分だけ増えてしまうということです。mysqlnd は、PHP の内部的なメモリ管理関数を使っているため、(MySQL Client Library とは異なり) PHP 側の memory_limit の設定を尊重することに注意してください。同じ理由で memory_get_usage() 関数の実行結果は、MySQL Client Library と比べて高いメモリ使用量を報告します。memory_get_usage() 関数は MySQL Client Library のメモリ使用量を全く計測しません。なぜなら、MySQL Client Library は この関数が監視する PHP の内部メモリ管理関数を使用していないからです!
unbuffered_sets Connection 通常の(プリペアドステートメントではない) クエリによって返された、バッファリングされていない結果セットの数 クライアント側で結果セットがバッファリングされないAPI呼び出しの例: mysqli_use_result()
ps_buffered_sets Connection プリペアドステートメントによって返される、バッファリングされた結果セットの数。デフォルトでは、プリペアドステートメントはバッファリングされません。 クライアント側で結果セットがバッファリングされるAPI呼び出しの例: mysqli_stmt_store_result
ps_unbuffered_sets Connection プリペアドステートメントによって返される、バッファリングされない結果セットの数。 デフォルトでは、プリペアドステートメントはバッファリングされません。
flushed_normal_sets Connection 通常の(プリペアドステートメントではない) クエリから返された、クライアントが読み取っていないため黙ってフラッシュされたデータが残っている結果セットの数。フラッシュはバッファリングされていない結果セットの場合だけ起こります。 バッファリングされていない結果セットは、新しいクエリが実行される前に完全に取得されなければなりません。そうでない場合、MySQL はエラーを生成します。アプリケーションがバッファリングされていない結果セットからすべての行を取得していない場合、mysqlnd は行をクリアするため暗黙のうちに結果セットをフラッシュします。rows_skipped_normal や、rows_skipped_ps も参照してください。暗黙のフラッシュが起こりうる原因を以下に示します:
  • クライアントアプリケーションが不完全な場合

  • クライアントは探していた情報を見つけたあと終了しますが、MySQL に必要以上のレコードを計算させてしまっている場合

  • クライアントアプリケーションが予期せず終了する場合

flushed_ps_sets Connection プリペアドステートメントのクエリから返された、クライアントが読み取っていないため黙ってフラッシュされたデータが残っている結果セットの数。フラッシュはバッファリングされていない結果セットの場合だけ起こります。 同上
ps_prepared_never_executed Connection 準備(prepare)されたが、決して実行されないステートメントの数 プリペアドステートメントはサーバのリソースを占有します。実行する予定がない場合、ステートメントを準備すべきではありません。
ps_prepared_once_executed Connection 一度だけ実行されたプリペアドステートメントの数 プリペアドステートメントの背後にあるアイディアのうちのひとつは、同じクエリは繰り返し繰り返し(異なるパラメーターで)実行されるんだから、ステートメントの実行が準備と実行に分かれていれば、クエリのパースやほかの準備処理はキャッシュできる、というものです。 このアイディアは準備を一度行い、その結果を キャッシュ します。たとえば解析ツリーを複数のステートメントの実行時に再利用するのです。プリペアドステートメントが一度だけしか実行されない場合、二段階に処理が分かれていることは 通常のクエリに比べて非効率かもしれません。なぜなら、すべてのキャッシュは余計なものであり、その情報を保持するためにサーバは(限られた)リソースを消費しているからです。結果的に、一度しか実行されていないプリペアドステートメントはパフォーマンスを害する原因になる可能性があります。
rows_fetched_from_server_normal, rows_fetched_from_server_ps Connection クライアントが消費していたかいないかに関わらず、MySQLから取得に成功した結果セット行の合計数。行によっては、クライアントアプリケーションは取得しないため暗黙のうちにフラッシュされている場合があります。 packets_received_rset_row も参照してください
rows_buffered_from_client_normal, rows_buffered_from_client_ps Connection 通常のクエリ、またはプリペアドステートメントから生成された、バッファリングに成功した行の合計数。これは MySQL から取得され、クライアントにバッファリングされた行の数です。バッファリングに成功した行については、ふたつの全く別な統計値があることに注意してください。(MySQL から mysqlnd の内部バッファに)バッファリングされた行の数と、(mysqlnd の内部バッファからクライアントアプリケーションへ)取得され、バッファリングされた行の数です。バッファリングされた行数が、取得されてバッファリングされた行より多い場合、クライアントアプリケーションが必要以上に大きな結果セットを生成しているため、クライアントが読み取らない行ができてしまっている可能性があります。 結果をバッファリングするクエリの例: mysqli_query(), mysqli_store_result()
rows_fetched_from_client_normal_buffered, rows_fetched_from_client_ps_buffered Connection バッファリングされた結果セットからクライアントによって取得された行の合計数。この結果セットは通常のクエリとプリペアドステートメントの両方から生成されたものです。  
rows_fetched_from_client_normal_unbuffered, rows_fetched_from_client_ps_unbuffered Connection バッファリングされて「いない」結果セットからクライアントによって取得された行の合計数。この結果セットは通常のクエリとプリペアドステートメントの両方から生成されたものです。  
rows_fetched_from_client_ps_cursor Connection プリペアドステートメントによって生成されたカーソルから、クライアントが取得した行の合計数  
rows_skipped_normal, rows_skipped_ps Connection 将来のために予約されています(今のところサポートされていません)  
copy_on_write_saved, copy_on_write_performed Process mysqlnd では、エクステンションから返された値は mysqlnd 内部にある通信結果のバッファを指しています。開発者が値を変更しなければ、取得されたデータは一度だけメモリに保持されます。値を変更した場合、mysqlnd は 内部にある通信結果のバッファを変更から保護するために コピーオンライト を実行しなければなりません。MySQL Client Library を使うと、取得したデータを二度メモリに保持します。MySQL Client Library の内部バッファと変数の値がエクステンションによって返されるのです。理論上、mysqlnd は40%のメモリを節約できます。しかし、メモリに保持されている量は memory_get_usage()関数では計測できないことに注意してください。  
explicit_free_result, implicit_free_result Connection, Process (プリペアドステートメントのクリーンアップ時のみ) 解放された結果セットの合計数 ここでいう「解放」とは明示的なもので、初期化コマンドで生成された結果セットを除きます。たとえば mysqli_options(MYSQLI_INIT_COMMAND , ...) 関数の呼び出しがそれにあたります。
proto_text_fetched_null, proto_text_fetched_bit, proto_text_fetched_tinyint proto_text_fetched_short, proto_text_fetched_int24, proto_text_fetched_int proto_text_fetched_bigint, proto_text_fetched_decimal, proto_text_fetched_float proto_text_fetched_double, proto_text_fetched_date, proto_text_fetched_year proto_text_fetched_time, proto_text_fetched_datetime, proto_text_fetched_timestamp proto_text_fetched_string, proto_text_fetched_blob, proto_text_fetched_enum proto_text_fetched_set, proto_text_fetched_geometry, proto_text_fetched_other Connection 通常のクエリ(MySQL テキストプロトコル) から取得したあるタイプのカラムの合計数 C API/ MySQL のメタデータと 統計の名前の対応:
  • MYSQL_TYPE_NULL - proto_text_fetched_null

  • MYSQL_TYPE_BIT - proto_text_fetched_bit

  • MYSQL_TYPE_TINY - proto_text_fetched_tinyint

  • MYSQL_TYPE_SHORT - proto_text_fetched_short

  • MYSQL_TYPE_INT24 - proto_text_fetched_int24

  • MYSQL_TYPE_LONG - proto_text_fetched_int

  • MYSQL_TYPE_LONGLONG - proto_text_fetched_bigint

  • MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDECIMAL - proto_text_fetched_decimal

  • MYSQL_TYPE_FLOAT - proto_text_fetched_float

  • MYSQL_TYPE_DOUBLE - proto_text_fetched_double

  • MYSQL_TYPE_DATE, MYSQL_TYPE_NEWDATE - proto_text_fetched_date

  • MYSQL_TYPE_YEAR - proto_text_fetched_year

  • MYSQL_TYPE_TIME - proto_text_fetched_time

  • MYSQL_TYPE_DATETIME - proto_text_fetched_datetime

  • MYSQL_TYPE_TIMESTAMP - proto_text_fetched_timestamp

  • MYSQL_TYPE_STRING, MYSQL_TYPE_VARSTRING, MYSQL_TYPE_VARCHAR - proto_text_fetched_string

  • MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB - proto_text_fetched_blob

  • MYSQL_TYPE_ENUM - proto_text_fetched_enum

  • MYSQL_TYPE_SET - proto_text_fetched_set

  • MYSQL_TYPE_GEOMETRY - proto_text_fetched_geometry

  • 上記にない MYSQL_TYPE_* (ないはずですが) - proto_text_fetched_other

MYSQL_*-type 定数は、 MySQL の各バージョンの同じSQLカラムタイプと結びついているとは限らないことに注意してください。

proto_binary_fetched_null, proto_binary_fetched_bit, proto_binary_fetched_tinyint proto_binary_fetched_short, proto_binary_fetched_int24, proto_binary_fetched_int, proto_binary_fetched_bigint, proto_binary_fetched_decimal, proto_binary_fetched_float, proto_binary_fetched_double, proto_binary_fetched_date, proto_binary_fetched_year, proto_binary_fetched_time, proto_binary_fetched_datetime, proto_binary_fetched_timestamp, proto_binary_fetched_string, proto_binary_fetched_blob, proto_binary_fetched_enum, proto_binary_fetched_set, proto_binary_fetched_geometry, proto_binary_fetched_other Connection プリペアドステートメント(MySQL バイナリプロトコル) から取得したあるタイプのカラムの合計数 カラムタイプと統計の名前の対応は、上の proto_text_* を参照してください
MySQL Native Driver が返す統計情報: データベース接続
統計情報 統計のカテゴリ 説明 注意点
connect_success, connect_failure Connection 接続を試みた結果が 成功 / 失敗 した回数の合計 再利用された接続や、他の種類の接続もすべて含みます
reconnect Process 既に開かれている接続ハンドルに対して(mysqli_real_connectを使って)行われた再接続の合計回数 次のコードは、再接続を行います。$link = new mysqli(...);$link->real_connect(...) しかし、次のコードは再接続を行いません。$link = new mysqli(...); $link->connect(...) なぜなら、このコードは新しい接続が確立される前に明示的に既存の接続を閉じるからです。
pconnect_success Connection 持続的接続を試みて成功した合計回数 connect_success は、持続的接続と通常の接続の両方の成功数を合計している点に注意してください。通常の接続の成功数は、connect_success - pconnect_success で求められます。
active_connections Connection アクティブな持続的接続と通常の接続の合計値  
active_persistent_connections Connection アクティブな持続的接続の合計値 アクティブな通常の接続の合計値は、active_connections - active_persistent_connections で求められます。
explicit_close Connection 明示的に閉じられた接続の合計数(ext/mysqli 限定). 明示的に接続を閉じるコードの例 :
$link = new mysqli(...); $link->close(...)
$link = new mysqli(...); $link->connect(...)
implicit_close Connection 暗黙的に閉じられた接続の合計数(ext/mysqli 限定). 暗黙的に接続を閉じるコードの例 :
  • $link = new mysqli(...); $link->real_connect(...)

  • unset($link)

  • 持続的接続の場合: プールされる接続は real_connect 関数を使って作成されますが、作成されたハンドルにはどんなオプションが設定されたかわからない場合があります。この場合、暗黙のうちに接続を閉じることで、どんなオプションが設定されたかわからない接続が返されることを防いでください。

  • 持続的接続の場合: mysqli::ping や mysqli::change_user を実行すると失敗し、ext/mysqli が接続を閉じてしまいます。

  • スクリプトの実行が終了する時: ユーザーが閉じていない接続は閉じられます。

disconnect_close Connection 接続を試み、C API のmysql_real_connect() を呼び出した後に失敗した回数 C API の呼び出しの際に渡された接続ハンドルを閉じるため、disconnect_close と呼ばれています。
in_middle_of_command_close Process コマンドの実行中(クエリを送信し、応答を受け取る前に残っていた結果セットが取得されなかったり、データを取得中だったり、LOAD DATA コマンドのデータを送信中だったりした場合)に閉じられた接続 非同期クエリを使っていない場合、コマンド実行中に接続が閉じられるのは、PHPスクリプトが予期しない箇所で終了し、PHPが接続を閉じた場合だけのはずです。
init_command_executed_count Connection 初期化コマンドが実行された合計回数。たとえば、以下のようなコードが実行された回数です。 mysqli_options(MYSQLI_INIT_COMMAND , ...) 初期化コマンドが成功した回数は init_command_executed_count - init_command_failed_count で求められます。
init_command_failed_count Connection 初期化コマンドが失敗した回数  
MySQL Native Driverが返す統計情報: COM_* コマンド
統計情報 統計のカテゴリ 説明 注意点
com_quit, com_init_db, com_query, com_field_list, com_create_db, com_drop_db, com_refresh, com_shutdown, com_statistics, com_process_info, com_connect, com_process_kill, com_debug, com_ping, com_time, com_delayed_insert, com_change_user, com_binlog_dump, com_table_dump, com_connect_out, com_register_slave, com_stmt_prepare, com_stmt_execute, com_stmt_send_long_data, com_stmt_close, com_stmt_reset, com_stmt_set_option, com_stmt_fetch, com_daemon Connection PHP から MySQL へ、特定の COM_* コマンドを送信しようとした合計回数

これらの統計値は、コマンドをチェックした後、対応する MySQLクライアントサーバプロトコルのパケットが送信される前にインクリメントされます。mysqlnd がパケットの送信に失敗したとしても、統計情報は減りません。パケットの送信にした場合、PHP は Error while sending %s packet. PID=%d. という、E_WARNING レベルの警告を発生させます。

使い方の例:

  • PHP があるコマンドを MySQLに送信しているかどうかをチェックする。たとえば、クライアントが COM_PROCESS_KILL を送信しているかどうかをチェックする。

  • COM_EXECUTE コマンドと COM_PREPARE コマンドの実行回数を比較することで、プリペアドステートメントの平均実行回数を割り出す。

  • COM_QUERY コマンドの実行回数がゼロかどうかをチェックすることで、PHP がプリペアドステートメントでない通常のクエリを実行しているかどうかをチェックする

  • COM_QUERYCOM_EXECUTE コマンドをチェックすることで、SQLを実行しすぎているPHPスクリプトを特定する

その他

MySQL Native Driver が返す統計情報: その他
統計情報 統計のカテゴリ 説明 注意点
explicit_stmt_close, implicit_stmt_close プロセス プリペアドステートメントが閉じられた合計回数 プリペアドステートメントは、常に明示的に閉じられるものとみなされます。ただし、prepare に失敗した場合を除きます。
mem_emalloc_count, mem_emalloc_ammount, mem_ecalloc_count, mem_ecalloc_ammount, mem_erealloc_count, mem_erealloc_ammount, mem_efree_count, mem_malloc_count, mem_malloc_ammount, mem_calloc_count, mem_calloc_ammount, mem_realloc_count, mem_realloc_ammount, mem_free_count Process メモリ管理に関する関数コールの回数 開発者だけが使うものです。
command_buffer_too_small データベース接続 PHP が MySQL にコマンドを送信する際、コマンドバッファの大きさが拡張された回数

mysqlnd は、内部的に mysqlnd.net_cmd_buffer_size(php.iniで設定) バイトを接続毎にメモリに割り当てます。MySQL のクライアントサーバプロトコルの場合、COM_QUERY (通常クエリ) コマンドがバッファサイズより大きい場合、mysqlnd はコマンドを送信するのに必要なサイズまでバッファを拡張します。ひとつの接続につきバッファが拡張された際はいつでも、command_buffer_too_small の値がひとつインクリメントされます。

mysqlnd が ほぼすべての接続で デフォルトの mysqlnd.net_cmd_buffer_size (php.ini で設定) バイトを超えてバッファを拡張しなければならない場合、メモリの再割り当てを防ぐために、デフォルトの値を増やすことを検討すべきです。

PHP 5.3.0 では、デフォルトのバッファサイズが 2K バイトでした。将来のバージョンでは、この値は 4K バイト以上になる見込みです。このデフォルトの値は php.inimysqlnd.net_cmd_buffer_size を設定するか、mysqli_options(MYSQLI_OPT_NET_CMD_BUFFER_SIZE, int size) 関数を使うことで変更することができます。

4096バイト以上のバッファサイズを設定することを推奨します。なぜなら、mysqlnd は MySQL からある通信パケットを読み取っているときにそれだけのメモリを使うからです。PHP 5.3.0 では、MySQL が現在設定されているバッファサイズ以上のパケットを送信しても、mysqlnd は絶対にバッファサイズを拡大しません。その結果として、mysqlnd はパケットをデコードできず、クライアントアプリケーションがエラーを発生させることになります。PHP 5.3.0 における mysqlnd.net_cmd_buffer_size のデフォルトである 2048 バイト以上に大きなパケットが送られてくる場合はふたつしかありません: とても長いエラーメッセージを送信した場合と、COM_LIST_FIELD (mysql_list_fields()関数から投げられる内部コマンド) から発生したパケットに含まれるカラムのメタデータが、とても長いデフォルト値(1900バイト以上)を持つ文字列型のカラムを持っていた場合です。この問題に関するバグレポートは存在していません - こんなことは滅多に起きないはずです。

PHP 5.3.2 の mysqlnd は 4096バイトより小さいバッファを設定できません。

connection_reused