作者:王悦
Copyright ? 2021 wingYue
本文来源:原稿
*爱可生开源社区生产,原创内容未经授权不得随意使用。请联系小编,注明来源。
最近使用了 bcc 工具集中的 dbslower ,这个工具可以探测 MySQL 慢指定阈值 query ,使用非常方便。
使用举例:
因为这个工具是一个 python 所以打开学习内部机制。
第一段是一些使用案例:
这里我们关注这两个:
dbslower mysql -p 480 -m 30 # trace MySQL queries slower than 30ms dbslower mysql -x $(which mysqld) # trace MySQL queries with uprobes
检测慢日志也是,一是提供 pid ,二是提供二进制文件地址,粗看下面只是用法不同,其实完全走向了不同的机制。
让我们看下一段
本段用于确认最终使用的机制 mode ,如果提供 pid ,那么 mode=“MYSQL57” ,若提供二进制地址,则 mode=“USDT” 。
这里 USDT 指的是(Userland Statically Defined Tracing)也就是说,当使用用户态静态探针时, pid 实际实际使用时 USDT 静态探针机制,另一种动态探针机制用于二进制文件。为了继续理解下面的段落,让我们来看看静态探针和动态探针是什么意思。
探针的分类
探针大致可以分为两类,静态探针和动态探针。
例如,我们在上面看到的静态探针 USDT ,对应 MySQL 中,则是 MySQL DTrace 实现这种探针需要在编译过程中提前定义并打开。
需要说明的是 MySQL DTrace 在 MySQL5.7.18 被弃用,在 MySQL8.0 它被完全删除能在早期版本中进行 DTrace 检测。MySQL 的 DTrace 有很多探针,比如 query-start 和 query-done 例如,用于检测一个句子的执行过程 connection-start 和 connection-done 用于检测客户端连接的过程需要在代码中实现。使用探针需要增加编译参数 -DENABLE_DTRACE=1。
让我们看一个官方的官方示例:
https://dev.MySQL.com/doc/refman/5.7/en/dba-DTrace-server.html
这里使用了 query-start 和 query-done 这两个探针获得句子执行时间
编辑 DTrace 脚本
执行效果
不幸的是,新版本的静态探针 MySQL 没了,我们就不深究了。
除静态探针外,还有动态探针,如bfs常用于技术 uprobes 和 kprobes ,这种探悉代码,这种探针更灵活,可以在程序运行时动态添加。
我使用 MySQL8.0 作为一个实验环境,我简单地写了一个使用 uprobes 打印 query 的示例。
这里的关键在于{ printf("%s\n", str(*arg1)); }
,意思是打印 dispatch_command方 指向法律第二参数的内容。
同样的原理,改变函数,动态打印我们想要的任何变量,或者用探针写一些 bpf 脚本,可以实现很多功能,非常好用。
回到我们身边 dbslower 脚本上来。事实上,脚本同时实现了静态探针和动态探针两种机制。
当我们使用 pid 时,比如dbslower MySQL -p 480 -m 30
,变量 mode 值为 “USDT” ,进入上图 else 段落,即使用query__start
和query__done
当探针被触发时,将这两个静态探针挂载到相应的处理函数中query_start
和query_end
,这两个处理函数中的逻辑非常简单,即获得相应的逻辑 query 内容、记录时间等,有兴趣的话可以去脚本查看,这里就不列了。
另一方面,当我们使用二进制文件地址时,例如dbslower MySQL -x $(which MySQLd)
,变量 mode 值为 “MYSQL57” ,进入上图if段落,mysql_func_name 脚本赋予的值是 dispatch_command 函数,即使用 bfp ,在函数 dispatch_command 动态探针在执行前后插入。同样,当探针被触发时,将其挂载到相应的处理函数中query_start
和query_end
计算时间。
总结
- dbslower 探针检测脚本 MySQL query 执行时间。
- 当 dbslower 使用 pid 静态探针机制的实际使用需要在编译过程中打开-DENABLE_DTRACE=1 ,且该机制在 MySQL 删除了新版本,需要特别注意。
- 当 dbslower 使用 mysqld 二进制路径实际上采用了动态探针机制,在程序运行过程中可以动态添加动态探针,无论是新旧版本 MySQL 都可以用。
- bpf 的 uprobe 动态探针非常灵活。熟练使用后,一些故障排除场景是一个很大的武器。缺点是大多数情况下需要配置代码。