Mysql 中Dtrace的应用

Dtrace是一个非常好的动态跟踪工具,并且在Mysql当中就是支持Dtrace的;尤其是performance_schema中信息的采集;有关Dtrace的基本知识,语法等可以参考dtrace的官方文档:http://dtrace.org/guide/chp-user.html 初次使用dtrace可能会感觉无从下手,这里分享下自己经验;

注:测试环境为:Mysql 8,MAC os 10.10.5 ;

在mac 中有一个命令 dtruss ,实际它的最终来源是dtrace,需要高权限才能执行;所以对dtrace 熟悉后可以直接使用dtrace;

[HuSi@HuoSi]mysql8 $ sudo dtrace -l -m mysqld 
sudo: cannot get working directory
Password:
   ID   PROVIDER            MODULE                          FUNCTION NAME
dtrace: failed to match :mysqld::: No probe matches description

这里想看看有关Mysql的模块信息,但是你会发现此时什么都没有,下面可以启动mysql 后再检查:

[HuSi@HuoSi]mysql8 $ pgrep -x mysqld 
[HuSi@HuoSi]mysql8 $ ./mysqlstart start
Starting MySQL
 SUCCESS! 
[HuSi@HuoSi]mysql8 $ pgrep -x mysqld
16279
[close_connection(THD*, unsigned int, bool, bool)] connection-done
 5458 mysql16279            mysqld _Z22thd_prepare_connectionP3THD [ha_myisammrg::index_read_map(unsigned char*, unsigned char const*, unsigned long, ha_rkey_function)] index-read-row-done
 5479 mysql16279            mysqld _ZN9ha_myisam15index_next_sameEPhPKhj 

----省略N行-----

[Sql_cmd_delete_multi::execute(THD*)] multi-delete-start
 9772 mysql16279            mysqld _ZN14Sql_cmd_update26execute_multi_table_updateEP3THD [Sql_cmd_update::execute_multi_table_update(THD*)] multi-update-done
 9773 mysql16279            mysqld _ZN14Sql_cmd_update26execute_multi_table_updateEP3THD [execute_sqlcom_select(THD*, TABLE_LIST*)] select-start
 9949 mysql16279            mysqld _ZN14Sql_cmd_update23try_single_table_updateEP3THDPb [Sql_cmd_update::try_single_table_update(THD*, bool*)] update-done
 9950 mysql16279            mysqld _ZN7handler13ha_update_rowEPKhPh [handler::ha_update_row(unsigned char const*, unsigned char*)] update-row-done
 9951 mysql16279            mysqld _ZN7handler13ha_update_rowEPKhPh [handler::ha_update_row(unsigned char const*, unsigned char*)] update-row-start
 9952 mysql16279            mysqld _ZN14Sql_cmd_update23try_single_table_updateEP3THDPb [Sql_cmd_update::try_single_table_update(THD*, bool*)] update-start

当Mysql启动后可看到dtrace 可以跟踪的具体函数;实际上在Mysql的官方文档里面归类介绍了可以进行Dtrace跟踪的函数;目前5.7 的文档中是有的,但是8 的文档中还没加入Dtrace的有关内容,但是不影响具体的功能;官方介绍的比较笼统,如果是初学者可能会感到困惑,那怎么具体使用Dtrace呢?下面来看看;比如我想查看跟 parse 有关的函数:

[HuSi@HuoSi]mysql8 $ sudo dtrace -l -m mysqld  | grep parse 
 9784 mysql16279            mysqld _Z11mysql_parseP3THDP12Parser_state [mysql_parse(THD*, Parser_state*)] query-exec-done
 9788 mysql16279            mysqld _Z11mysql_parseP3THDP12Parser_state [mysql_parse(THD*, Parser_state*)] query-exec-start
 9791 mysql16279            mysqld _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx [parse_sql(THD*, Parser_state*, Object_creation_ctx*)] query-parse-done
 9792 mysql16279            mysqld _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx [parse_sql(THD*, Parser_state*, Object_creation_ctx*)] query-parse-start

这里选取一条来说明下:9792 mysql16279 mysqld _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx [parse_sql(THD*, Parser_state*, Object_creation_ctx*)] query-parse-start

需要关注的是:parse_sql(THD*, Parser_state*, Object_creation_ctx*),parse_sql 是函数名称,括号里是相关的参数,比如像看看这个函数具体的做什么:

[HuSi@HuoSi]mysql8 $ sudo dtrace -n 'mysql*:::query-parse-start {printf ("%Y   %s\n ",walltimestamp,copyinstr(arg0));}'
dtrace: description 'mysql*:::query-parse-start ' matched 1 probe

此时数据库没有执行任何的解析所以是没有结果的,下面执行几个简单的sql:

[HuSi@HuoSi]mysql8 $ bin/mysql -uroot -proot 
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 4
Server version: 8.0.0-dmr-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, 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> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from test;
+------+---------------------------------------+
| id   | name                                  |
+------+---------------------------------------+
|    1 | jjjjjj                                |
|   12 | jjjj                                  |
|   19 | uuuuuu                                |
|   19 | uuuuuu-------                         |
..................
.....................
|   21 | uuuuuu-------==========oooooljljl     |
|   21 | uuuuuu-------==========oooooljljl     |
|   21 | uuuuuu-------==========oooooljljl     |
|   21 | uuuuuu-------==========oooooljljl     |
|   21 | uuuuuu-------==========oooooljljl     |
|   21 | rectest1                              |
|   21 | rectest1                              |
|   21 | rectest1                              |
|   21 | rectest1                              |
+------+---------------------------------------+
42 rows in set (0.00 sec)

mysql> 

此时dtrace 显示的数据为: 

[HuSi@HuoSi]mysql8 $ sudo dtrace -n 'mysql*:::query-parse-start {printf ("%Y   %s\n ",walltimestamp,copyinstr(arg0));}'
dtrace: description 'mysql*:::query-parse-start ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:19   SELECT DATABASE()
 
  2   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:19   show databases
 
  1   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:19   show databases
 
  1   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:19   show tables
 
  0   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:19   show tables
 
  0   9792 _Z9parse_sqlP3THDP12Parser_stateP19Object_creation_ctx:query-parse-start 2016 Dec  2 11:31:45   select * from test
 

在使用Dtrace 时需要注意的一个问题是:copyinstr(arg0) 这里,这个argxxx 这个好理解就是第几个参数,第一个参数是arg0,然后依次的即可,但是如果使用copyinstr,可能会显示乱码等问题,这里可以参考官方文档的第33章节有比较详细的描述;有了上面的例子,其它的mysql的相关函数,基本就这么来就可以,这样就可以能看到你想要的内容了;

关于Dtrace 确实很有用,但是这个不是什么独孤九剑,懂一定有好处,不懂也无害,毕竟使用的地方较少,不能当做一个炫耀的资本,感觉有点类似 oracle bbed似得,只不过 dtrace 使用的范围更广;与源码的结合可以更快的更清晰的掌握相关内容;配合使用Dtrace后,也可以减少学习的枯燥程度;

那么大家可以思考如下的场景:

Mysql监控,常用监控项 OS 层面设置就可以了,如果是db层面的,实际是查询db中的各种信息得来的,如直接使用Dtrace呢,比如想做审计,审计所有解析的 sql,以及解析时间,执行时间等等,用Dtrace 写个脚本然后直接发送给监控系统;还有DB 竞争分析等等;

最后推荐一篇文章:

http://dtrace.org/blogs/brendan/2011/06/23/mysql-performance-schema-and-dtrace/

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注