Understanding MySQL Internalsを読む(4)

以前の記事

THDクラス

MySQLのCoreなクラスのひとつ、THDについて。THDクラスはMySQLの上位層(データベース管理レベルのこと、ストレージエンジンの上)で動作する多くの関数の第一引数に指定されている超重要なクラス。Threadの略。MySQLはひとつの接続にひとつのスレッドを割り当てて処理を行うが、その各スレッドごとに用意されるもの。

クラス定義はsql/sql_class.hにて行われていて、メソッドの実装はsql/sql_class.ccに行われている。THDクラス自身はStatementクラス、Open_table_stateクラスを基底クラスを持つ。

以下はTHDクラスのメンバ一覧表。(注:メンバは本書籍をベースに並べていますが、hostなど一部のメンバはSecurityContextクラス(おそらくver5.0で追加)に移されて、thd->security_ctxの配下に対してアクセスする必要があるようになっています。要は実装ベースで確認したいひとは勝手にソース読んで下さいということで。)

メンバの型と名前 説明
LEX* lex 現在処理中のクエリのパースツリー。ver4.1からは基底クラスのStatementクラスで定義されている。
char* query 現在処理中のクエリの文字列。ver4.1からはStatementクラスで定義されている。
uint32 query_length 現在処理中のクエリ文字列のバイト長。ver4.1からはStatementクラスで定義されている。
Item* free_list 現在処理中のクエリのパースツリーの全てのノードに対するLinked List。クエリ実行後の掃除(sql/sql_parse.ccのfree_items())の際に使用される。ver4.1からはStatementクラスで定義されている。
MEM_ROOT mem_root このスレッド用のメモリプール。alloc_root()で割り当てて、free_root()で解放する。ver4.1からはStatementクラスにて。
NET net クライアントとの接続ディスクリプタ
MEM_ROOT warn_root warningsとerrorを扱うためのメモリプール。
Protocol* protocol MySQL Client/Serverプロトコルディスクリプタ。現在実行中のクエリが通常のStatementなのか、Prepared Statementなのかにより参照先の実体が異なる。
HASH user_vars クエリの中にユーザ定義変数を格納するためのハッシュ。SET @a=31; SELECT col1 FROM t1 WHERE col2=@a; などで使用。
String packet ネットワーク送受信のために使われる動的バッファ。
struct system_variables variables SESSIONスコープで利用可能なシステム変数群をメンバに持つ変数(構造体)。例えば次の操作でアクセスされると、、SET SESSION sort_buffer_size=256000、、variables.sortbuff_sizeの値が256000に変更される。
Statement_map stmt_map 使用している全てのPrepared Statementとカーソルの格納場所。
char* host 接続元ホスト名(実測値)。(ver5.0以上ではhost,priv_host,user,priv_user,ip,host_or_ipなどの接続情報はthd->security_ctx配下にある。)
char* priv_host 接続元ホスト名(認証値)。接続時にmysql.userテーブルを使って認証されたもの。(例えば個別登録していないドメイン/ホスト名だけれども%で許可された場合、hostとpriv_hostの値は異なることになる。)
char* user 接続ユーザ名(ユーザ指定値)。
char* priv_user 接続ユーザ名(認証値)。接続時にmysql.userテーブルを使って認証されたもの。(例えば個別登録していないユーザ名だけれどもanonymous扱いで許可された場合、userとpriv_userの値は異なることになる。)
char* db 現在選択中のデータベース。
uint32 db_length 選択中のデータベースの名前のバイト長。
char* ip 接続元のIPアドレスの文字列。
char* host_or_ip 接続先のホスト名。IPアドレスからホスト名が解決できなかった場合(DNS参照失敗等による)、IPアドレスの文字列。
const char* proc_info SHOW PROCESSLISTで返されるinfoの値。何か長時間かかる処理が行われる前に、値が設定されることが多い。性能問題の解析に有用。
ulong client_capabilities クライアントによるMySQLプロトコルの対応度合を表すビットマスク。サーバが前方互換性、後方互換性を保ってクライアントと通信するためのもの。またSSLや通信データ圧縮を使用しているかどうかの情報も持つ。
ulong master_access 現在の接続に対するグローバルなアクセス権限を保持するビットマスク。
ulong db_access 現在の接続による選択中のデータベースに対するアクセス権限を保持するビットマスク。
ulong col_access SHOW TABLESコマンド実行時に返すべきテーブル名を判定する際に使用されるビットマスク。権限が無い場合はそのテーブル名は結果から除外される。変数名からするとカラム関連の権限なのかと思いきや、そうではない。
TABLE* open_tables このスレッドで使用されているテーブルのLinked List。ここでいうテーブルは、一時テーブルを除く、SELECT/UPDATE/DELETE/INSERT/REPLACE/ALTERコマンドで使用されたもの。HANDLERコマンドやサブクエリで使用されたテーブルは含まない。クエリ完了時にこのリストにあるテーブルは自動的にcloseされる。
TABLE* handler_tables このスレッドで使用されている、HANDLER OPENコマンドでopenされたテーブルのLinked List。
TABLE* temporary_tables このスレッドで使用されている一時テーブルのLinked List。一時テーブルはCREATE TEMPORARY TABLEコマンドで接続ごとに作成できる他、Opitimizerによって内部的に作成される場合がある。
TABLE* derived_tables このスレッドで使用されている、サブクエリにより生成されたテーブルのLinked List。FROM句でサブクエリを使うと生成される。例えば次のSQL文によりテーブルが生成される。SELECT AVG(a) FROM (SELECT COUNT(*) AS a, b FROM t1 GROUP BY b) AS t_derived WHERE n > 100; このt_derivedが生成されたテーブル。
MYSQL_LOCK* lock このスレッドにより暗黙的にロックされた全てのテーブルのディスクリプタのLinked List。"LOCK TABLES"コマンドによる明示的にロックされたテーブルは含まない。ここでいうロックとは、SELECT/INSERT/UPDATEなどの処理する際に内部的に発生したもの。同時にロックするのは1つのグループのテーブルのみ。1つのグループのテーブルは同時にロックを取得する必要がある。この変数に値が設定される(0以外)場合には、locked_tablesは0である必要がある。
MYSQL_LOCK* locked_tables このスレッドにより"LOCK TABLES"コマンドで明示的にロックされた全てのテーブルのディスクリプタのLinked List。この変数に値を設定する(0以外)場合には、lockは0である必要がある。(要するに、明示的ロックとは暗黙的ロックを同時に使ってはいけないということ。たぶんatomicに処理できないためにデッドロックの可能性がでてくるとかの理由で。)
struct st_my_thread_var *mysys_var このスレッドがpthread_cond_wait等で待機する際に使用するPOSIXスレッドの状態変数などの情報を格納している構造体。shutdown時やkillコマンド実行時に待機中のスレッドを起こすのに使用される。詳細はsql/sql_class.ccのTHD::enter_cond()、THD::exit_cond()、THD::awake()などを参照。もしこのスレッドが待機中ではない場合、この変数の値は0に設定される。pthread_cont_waid()を呼ぶ場合、THD::enter_cond()を事前に呼んでおき、復帰したらTHD::exit_cond()を呼ぶこと。
enum enum_server_command command 現在処理中のサーバコマンド。最も良く使用されるのがCOM_QUERY。サーバコマンドの一覧はinclude/mysql_com.hのenum_server_commandに定義されている。
uint32 server_id レプリケーションSlaveにおけるSQLスレッドにて使用される変数。レプリケーションに参加する全てのmysqldはユニークなIDを設定ファイル等で与えられている必要がある。Slaveではレプリケーションによるデータ更新時には、Master側のIDをバイナリログに記録する。Slave自身に対する更新の際には、Slave側のIDをバイナリログに記録する。これにより(おそらく循環型レプリケーション等での)更新処理の無限ループが発生する可能性を排除している。このIDはクエリの初期処理中に設定されるため、更新時のバイナリログに値を出力することができる。
delayed_insert *di 現在使用中のDELAYED INSERTディスクリプタ。"INSERT DELAYED"クエリを処理する際に使用される。
struct st_transactions transaction トランザクションディスクリプタ。論理的な更新ログの管理、変更のあったテーブルを追跡(クエリキャッシュのため)するのに使用される。
Statement *current_statement 現在使用中のPrepared Statementディスクリプタ。Prepared Statementが使用されていない場合には値は0になっている。
uint server_status クライアントにステータスメッセージを報告する際に使用されるビットマスク。ここでいうステータスとは「トランザクション中」「まだ追加取得すべき検索結果が存在する」「クエリがインデックスを有効に利用していない」など。
ulonglong next_insert_id SET insert_id=XXXで指定された値。AUTO_INCREMENTで次に使用される値となる。
ulonglong last_insert_id AUTO_INCREMENTで使用された最新の値。SQL関数のlast_insert_id()で取得可能。SELECT last_insert_id()。
table_map used_tables クエリを処理する上で確認する必要があるテーブルを追跡するために使用されるビットマスク。この変数はオプティマイザにより頻繁に利用される。
USER_CONN *user_connect 接続ユーザのリソース制限に関するディスクリプタ
CHARSET_INFO *db_charset 接続中のデータベースの文字コードディスクリプタ
List warn_list クエリ実行中に発生したwarnings。SHOW WARNINGSコマンドで確認できる。
ulong query_id 実行中のクエリに対する内部的なID。新しく受け付けたクエリは常に前回よりも高いIDを持つ。
ulong thread_id mysqldからこのスレッドに割り当てられたID。SHOW PROCESSLISTで取得し、KILLコマンドで指定可能。
pthread_t real_id このスレッドのPOSIXスレッドID。
uint system_thread クライアント用スレッド以外のスレッドに設定される変数。クライアント用スレッドでは0。クライアント用以外とは、例えばDelayed Insert用のスレッドとか、レプリケーション用のSQLスレッドとか、イベントスケジューラとか。
bool slave_thread レプリケーションSlave用スレッドの場合には1(true)。
bool bootstrap bootstrap用スレッドの場合には1(true)。mysqldが--bootstrapオプション付きで起動した場合に、標準入力(stdin)からクエリを読んで実行する。標準入力が閉じられるとexitする。THDインスタンスのこの値を使用してその挙動の管理を行っている。bootstrap実行モードは、mysqldのインストール処理中にシステムテーブルを作成するために使用される。
bool volatile killed 終了要求を受けた場合に1(true)が設定される。各スレッドは長い処理を行う際に、頻繁にこの値を確認しなければならない。この変数が設定された場合には、スレッドは可及的速やかに終了処理を行ってexitしなければならない。

THDはこんなところ。