# A Tour of the MySQL Source Code ## Getting Started 以下のクエリをサンプルに見ていく ```sql SELECT lname, fname, DOB FROM Employees WHERE Employees.department = "EGR" ``` ### クエリ実行時の全体の概要 (MySQL 5.6) ![IMG_9931](https://hackmd.io/_uploads/B1M1vsY1R.jpg) - handle_connections_socket() - listener loop を実装 - コネクションごとにスレッドを作成 - 8.0 だとこれ...? - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/conn_handler/connection_handler_per_thread.cc#L245 - do_handle_one_connection() - コマンドを特定する - 8.0 には無さそう - do_command() - クエリを読んで適切なネットワークを選ぶ(?) - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_parse.cc#L1307 - dispatch_command - クエリを parser に送る - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_parse.cc#L1687 - query parser - Lex と YACC で構成される - Lex 字句解析プログラム - YACC 構文解析プログラム - mysql_execute_command() - parse されたクエリが渡される - コマンドを実行する - クエリを適切なサブ関数にルーティングする - 今回の場合だと、mysql_select() - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_parse.cc#L2915 - join->prepare() - クエリの実行を最適化するために呼ばれる - 8.0 だとこれ - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_resolver.cc#L178 - join->optimize() - 同じく optimize - 8.0 だとこれ - https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_optimizer.cc#L336 - join->exec() - クエリの実行 - 8.0 だと見つからず - do_select() - join->exec() の次 - 制限と射影の操作を実行する - 制限: where 句の処理、射影: 特定の列だけ取る処理と理解 - 8.0 だと見つからず - sub_select() - ストレージエンジンからタプルを読み、それを処理して、クライアントに返す - この後、処理のコントロールが handle_connections_sockets() に戻る - 8.0 だと見つからず ### MySQL 8.0.32 の場合 ここで、8.0.32 で単なる SELECT 文で JOIN::optimize に対してブレークポイントを置く ``` (gdb) bt #0 JOIN::optimize (this=0xfffed0112b58, finalize_access_paths=true) at /mysql-8.0.32/sql/sql_optimizer.cc:336 #1 0x0000aaaacf471a80 in Query_block::optimize (this=0xfffed0ace708, thd=0xfffed0001070, finalize_access_paths=true) at /mysql-8.0.32/sql/sql_select.cc:1813 #2 0x0000aaaacf5228f0 in Query_expression::optimize (this=0xfffed0ace620, thd=0xfffed0001070, materialize_destination=0x0, create_iterators=true, finalize_access_paths=true) at /mysql-8.0.32/sql/sql_union.cc:1006 #3 0x0000aaaacf46f234 in Sql_cmd_dml::execute_inner (this=0xfffed0111bf8, thd=0xfffed0001070) at /mysql-8.0.32/sql/sql_select.cc:763 #4 0x0000aaaacf46e8b4 in Sql_cmd_dml::execute (this=0xfffed0111bf8, thd=0xfffed0001070) at /mysql-8.0.32/sql/sql_select.cc:578 #5 0x0000aaaacf3e5840 in mysql_execute_command (thd=0xfffed0001070, first_level=true) at /mysql-8.0.32/sql/sql_parse.cc:4688 #6 0x0000aaaacf3e7854 in dispatch_sql_command (thd=0xfffed0001070, parser_state=0xffff447cb428) at /mysql-8.0.32/sql/sql_parse.cc:5322 #7 0x0000aaaacf3de900 in dispatch_command (thd=0xfffed0001070, com_data=0xffff447cbd40, command=COM_QUERY) at /mysql-8.0.32/sql/sql_parse.cc:2036 #8 0x0000aaaacf3dcd10 in do_command (thd=0xfffed0001070) at /mysql-8.0.32/sql/sql_parse.cc:1439 #9 0x0000aaaacf61695c in handle_connection (arg=0xaaaae9cec490) at /mysql-8.0.32/sql/conn_handler/connection_handler_per_thread.cc:302 #10 0x0000aaaad1525670 in pfs_spawn_thread (arg=0xaaaae9da9bd0) at /mysql-8.0.32/storage/perfschema/pfs.cc:2986 #11 0x0000ffff915cd5c8 in start_thread (arg=0x0) at ./nptl/pthread_create.c:442 #12 0x0000ffff91635edc in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:79 ``` join->exec が Sql_cmd_dml::execute になっていて、その中で optimize を呼ぶ構成に変わっている...? Sql_cmd_dml::execute_inner を見る限りそのように見える。 unit は Query_expression. https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_select.cc#L760 ### query_expression / query_block query_expression と query_block の関係は以下のブログが参考になった。 - query expression: UNION やカンマ区切りで繋がれた一つの SQL - query block: UNION で繋がれる前の個々の SQL - slave として query expression を持つ - https://dev.mysql.com/doc/dev/mysql-server/latest/classQuery__block.html#a40dab0c91def435d77a74f4629140080 ```sql (SELECT * FROM ttt1) UNION ALL (SELECT * FROM (SELECT * FROM ttt2) AS a, (SELECT * FROM ttt3 UNION ALL SELECT * FROM ttt4) AS b) ``` ![query_expression_block](https://hackmd.io/_uploads/SJGQbntk0.png) https://help.aliyun.com/zh/polardb/polardb-for-mysql/architecture-of-mysql-server-in-mysql-8 ### Query_expression::execute https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/sql_union.cc#L1808 ### The mysqld_main() function メモリにロードされて呼ばれる最初の関数 8.0 だとここ https://github.com/mysql/mysql-server/blob/1bfe02bdad6604d54913c62614bde57a055c8332/sql/mysqld.cc#L8379 疑問点: mysqld_main() で handle_connection (無限ループ)を読んでる?