MYSQL sql执行过程的一些跟踪分析(一)
发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,与oracle或其他的数据库都差不多,一条sql的执行主要还是要经历了解析、优化、执行这几个过程,稍微具体下总结,MYSQL的主要过程如下: 客户端发起连接-----连接器,主要分配线程,验证权限--
千家信息网最后更新 2025年11月07日MYSQL sql执行过程的一些跟踪分析(一)与oracle或其他的数据库都差不多,一条sql的执行主要还是要经历了解析、优化、执行这几个过程,稍微具体下总结,MYSQL的主要过程如下: 客户端发起连接-----连接器,主要分配线程,验证权限----分析器,对sql语句语法进行分析-----优化器,生成准确的执行计划-----执行器,执行语句,发起读写数据,返回结果--之后对数据读写是io线程与存储引擎的交互 在客户端连接部分,涉及到TCP三次握手过程,我已在《MYSQL 连接登录过程分析》中尝试进行分析。 http://blog.itpub.net/29863023/viewspace-2216731/ 尝试用strace追踪mysqld进程,观察发起一个连接去执行sql时的情况:
frm是MySQL的表结构定义文件,通过hexdump可以查看其中16进制数据
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]
[root@cwdtest1 ~]# strace -f -F -ff -o mysqld-strace -s 1024 -p 62509strace: Process 62509 attached with 32 threads....strace: Process 33059 attached
[root@cwdtest1 /]# mysql -uroot -pcwdrootmysql: [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 24Server version: 5.7.23-23-log Source distributionCopyright (c) 2009-2018 Percona LLC and/or its affiliatesCopyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.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> exitBye
从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: NULLPROCESSLIST_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) = 0gettid() = 33059setsockopt(67, SOL_TCP, TCP_NODELAY, [1], 4) = -1 EOPNOTSUPP (Operation not supported)setsockopt(67, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0open("/dev/urandom", O_RDONLY) = 68read(68, "'\275|\274\277\200Uw\2205\3)M\4E\364C\372\210\222\235\345\33I\216\252\206M\336C;\372", 32) = 32close(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) = 85recvfrom(67, "\272\0\0\1", 4, MSG_DONTWAIT, NULL, NULL) = 4recvfrom(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) = 186sendto(67, "\7\0\0\2\0\0\0\2\0\0\0", 11, MSG_DONTWAIT, NULL, 0) = 11recvfrom(67, "!\0\0\0", 4, MSG_DONTWAIT, NULL, NULL) = 4recvfrom(67, "\3select @@version_comment limit 1", 33, MSG_DONTWAIT, NULL, NULL) = 33sendto(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) = 83recvfrom(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) = 4recvfrom(67, "\3select * from cwdtest.test", 27, MSG_DONTWAIT, NULL, NULL) = 27stat("./cwdtest/test.frm", {st_mode=S_IFREG|0640, st_size=8590, ...}) = 0access("./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) = 141recvfrom(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) = 4recvfrom(67, "\1", 1, MSG_DONTWAIT, NULL, NULL) = 1shutdown(67, SHUT_RDWR) = 0close(67) = 0futex(0x1dca184, FUTEX_WAIT_PRIVATE, 46, NULL (END) 来看看./cwdtest/test.frm 和 ./cwdtest/test.TRG两个文件:frm是MySQL的表结构定义文件,通过hexdump可以查看其中16进制数据
[root@cwdtest1 cwdtest]# hexdump -C -v test.frm00002130 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]
文件
过程
分析
字段
线程
数据
语句
信息
客户
客户端
函数
字符
字符集
序号
结果
触发器
长度
尝试
验证
明显
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
4g移动网络安全风险场景
山西财智通软件开发有限公司
西安软件开发合伙人
江苏5g专业服务器机柜云空间
智能垃圾分类系统软件开发
社交软件分享功能数据库设计
桓台工具软件开发
网络安全技术岗位专业测试题
大专计算机网络技术都学什么
计算机客户服务器模式
360网页怎么不记录数据库
西安华为软件开发薪资待遇
url 服务器地址
网络安全坐标图片
网络安全快乐伴我成长手抄报
vue获取数据库图片路径
运维日常中经常往数据库中加表吗
运程管理服务器
医院网络安全培训通知模板
南昌高性能服务器
广东广电网络技术学院
嵌入式软件开发的技术原理
江苏5g专业服务器机柜云空间
如何调网易云游戏平台的服务器
企业资源管理系统数据库实训
向服务器发起一个http请求
内蒙古有网络技术有限公司
网络安全法25条的理解
北京惠普服务器虚拟化建设
南昌高性能服务器