MYSQLsql执行过程的一些跟踪分析(一)
与oracle或其他的数据库都差不多,一条sql的执行主要还是要经历了解析、优化、执行这几个过程,稍微具体下总结,MySQL的主要过程如下:
客户端发起连接-----连接器,主要分配线程,验证权限----分析器,对sql语句语法进行分析-----优化器,生成准确的执行计划-----执行器,执行语句,发起读写数据,返回结果--之后对数据读写是io线程与存储引擎的交互
在客户端连接部分,涉及到TCP三次握手过程,我已在《MYSQL 连接登录过程分析》中尝试进行分析。
http://blog.itpub.net/29863023/viewspace-2216731/
尝试用strace追踪mysqld进程,观察发起一个连接去执行sql时的情况:
[root@cwdtest1 ~]# strace -f -F -ff -o mysqld-strace -s 1024 -p 62509 strace: Process 62509 attached with 32 threads .... strace: Process 33059 attached
[root@cwdtest1 /]# mysql -uroot -pcwdroot mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 24 Server version: 5.7.23-23-log Source distribution Copyright (c) 2009-2018 Percona LLC and/or its affiliates Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select * from cwdtest.test; +---------+----------+ | col1 | col2 | +---------+----------+ | | aaaaaaaa | | ccccccc | NULL | +---------+----------+ 2 rows in set (0.00 sec) mysql> exit Bye
从performance_schema.threads中可以看到新增的54号前台线程thread/sql/one_connection,其os 线程id是33059
为昌江黎族等地区用户提供了全套网页设计制作服务,及昌江黎族网站建设行业解决方案。主营业务为网站制作、成都网站制作、昌江黎族网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
*************************** 31. row *************************** THREAD_ID: 54 NAME: thread/sql/one_connection TYPE: FOREGROUND PROCESSLIST_ID: 28 PROCESSLIST_USER: root PROCESSLIST_HOST: localhost PROCESSLIST_DB: NULL PROCESSLIST_COMMAND: Sleep PROCESSLIST_TIME: 10 PROCESSLIST_STATE: NULL PROCESSLIST_INFO: NULL PARENT_THREAD_ID: 1 ROLE: NULL INSTRUMENTED: YES HISTORY: YES CONNECTION_TYPE: Socket THREAD_OS_ID: 33059 《====== 31 rows in set (0.00 sec)
分析strace的过程信息:
获取线程id33059,之后设置 setsockopt状态。这里看到open /dev/urandom,这是获取一个随机编号
set_robust_list(0x7f9aa60ea9e0, 24) = 0 gettid() = 33059 setsockopt(67, SOL_TCP, TCP_NODELAY, [1], 4) = -1 EOPNOTSUPP (Operation not supported) setsockopt(67, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 open("/dev/urandom", O_RDONLY) = 68 read(68, "'\275|\274\277\200Uw\2205\3)M\4E\364C\372\210\222\235\345\33I\216\252\206M\336C;\372", 32) = 32 close(68) = 0
之后是密码验证,以及一些版本消息等
sendto(67, "Q\0\0\0\n5.7.23-23-log\0\34\0\0\0{PR&1|0 \0\377\367!\2\0\377\201\25\0\0\0\0\0\0\0\0\0\0\4\26:5.h\34U\"G%a\0mysql_native_password\0", 85, MSG_DONTWAIT, NULL, 0) = 85 recvfrom(67, "\272\0\0\1", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(67, "\205\246\377\1\0\0\0\1!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0root\0\24\v\10A\216\"\344i\31'\331UMa\"\356\4\3640!\331mysql_native_password\0i\3_os\5Linux\f_client_name\10libmysql\4_pid\00533058\17_client_version\t5.7.23-23\t_platform\6x86_64\fprogram_name\5mysql", 186, MSG_DONTWAIT, NULL, NULL) = 186 sendto(67, "\7\0\0\2\0\0\0\2\0\0\0", 11, MSG_DONTWAIT, NULL, 0) = 11 recvfrom(67, "!\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(67, "\3select @@version_comment limit 1", 33, MSG_DONTWAIT, NULL, NULL) = 33 sendto(67, "\1\0\0\1\1'\0\0\2\3def\0\0\0\21@@version_comment\0\f!\0009\0\0\0\375\0\0\37\0\0\24\0\0\3\23Source distribution\7\0\0\4\376\0\0\2\0\0\0", 83, MSG_DONTWAIT, NULL, 0) = 83 recvfrom(67, 0x7f9a9000a730, 4, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable) poll([{fd=67, events=POLLIN|POLLPRI}], 1, 28800000) = 1 ([{fd=67, revents=POLLIN}])
接受到shelect 的查询语句,我们可以看到 会stat ./cwdtest/test.frm 这个文件,这里是 获取文件信息,并在去访问./cwdtest/test.TRG,发现提示No such file or directory。
recvfrom(67, "\33\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(67, "\3select * from cwdtest.test", 27, MSG_DONTWAIT, NULL, NULL) = 27 stat("./cwdtest/test.frm", {st_mode=S_IFREG|0640, st_size=8590, ...}) = 0 access("./cwdtest/test.TRG", F_OK) = -1 ENOENT (No such file or directory) sendto(67, "\1\0\0\1\2-\0\0\2\3def\7cwdtest\4test\4test\4col1\4col1\f!\0\36\0\0\0\375\1\20\0\0\0-\0\0\3\3def\7cwdtest\4test\4test\4col2\4col2\f!\0\36\0\0\0\375\0\0\0\0\0\n\0\0\4\0\10aaaaaaaa\t\0\0\5\7ccccccc\373\7\0\0\6\376\0\0\"\0\0\0", 141, MSG_DONTWAIT, NULL, 0) = 141 recvfrom(67, 0x7f9a9000a730, 4, MSG_DONTWAIT, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable) poll([{fd=67, events=POLLIN|POLLPRI}], 1, 28800000) = 1 ([{fd=67, revents=POLLIN|POLLHUP}]) recvfrom(67, "\1\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4 recvfrom(67, "\1", 1, MSG_DONTWAIT, NULL, NULL) = 1 shutdown(67, SHUT_RDWR) = 0 close(67) = 0 futex(0x1dca184, FUTEX_WAIT_PRIVATE, 46, NULL(END)
来看看./cwdtest/test.frm 和
./cwdtest/test.TRG两个文件:
frm是MySQL的表结构定义文件,通过hexdump可以查看其中16进制数据
[root@cwdtest1 cwdtest]# hexdump -C -v test.frm
00002130 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 00002140 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 00 | .| 00002150 04 00 05 63 6f 6c 31 00 05 00 05 63 6f 6c 32 00 |...col1....col2.| 00002160 04 05 1e 1e 00 02 00 00 00 40 00 00 00 0f 21 00 |.........@....!.| 00002170 00 05 05 1e 1e 00 21 00 00 00 80 00 00 00 0f 21 |......!........!| 00002180 00 00 ff 63 6f 6c 31 ff 63 6f 6c 32 ff 00 |...col1.col2..|
以上列信息整理可得:
04 05 1e 1e 00 02 00 00 00 40 00 00 00 0f 21 00 00 --- 字段col1
05 05 1e 1e 00 21 00 00 00 80 00 00 00 0f 21 00 00-----字段col2
以col1字段为例:
其中04代表
列序号(初始列序号为4),
1e 表示字段长度,1e转化成十进制是30,表中是字是
varchar(
10
),字符集是utf8占3bit,所以长度是10*3=30.
40表示不可为空,(DEFAULT NULL 80,NOT NULL 40,DEFAULT 'VALUE' 00)
0f表示字段类型是varhcar 21表示字符集是utf8
表创建语句:
| test | CREATE TABLE `test` ( `col1` varchar(10) NOT NULL, `col2` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
TRG文件是mysql中记录触发器的定义,很明显这里test表并没有创建触发器。
sendto(67, "\1\0\0\1\2-\0\0\2\3def\7cwdtest\4test\4test\4col1\4col1\f!\0\36\0\0\0\375\1\20\0\0\0-\0\0\3\3def\7cwdtest\4test\4test\4col2\4col2\f!\0\36\0\0\0\375\0\0\0\0\0\n\0\0\4\0\10aaaaaaaa\t\0\0\5\7ccccccc\373\7\0\0\6\376\0\0\"\0\0\0", 141, MSG_DONTWAIT, NULL, 0) = 141
之后便是调用sendto函数,往客户端发送结果。
当退出时便是关闭。
shutdown(67, SHUT_RDWR) = 0
close(67) = 0
在以上的trace日志里每个函数操作的对象基本都是67,67则是文件描述符,而这里对应的是socket。
[root@cwdtest1 fd]# ls -rtl 672
lrwx------ 1 root root 64 Jan 19 11:19 67 -> socket:[16206507]
本文标题:MYSQLsql执行过程的一些跟踪分析(一)
地址分享:http://cdiso.cn/article/ggiise.html