5.8.4.1 mysqld DTrace 探测参考

MySQL 支持以下静态探测器,组织成功能组。

表 5.5 MySQL DTrace 探测器

团体 探头
联系 connection-start,connection-done
命令 command-start,command-done
询问 query-start,query-done
查询解析 query-parse-start, query-parse-done
查询缓存 query-cache-hit,query-cache-miss
查询执行 query-exec-start,query-exec-done
行级 insert-row-start,insert-row-done
update-row-start,update-row-done
delete-row-start,delete-row-done
行读取 read-row-start,read-row-done
索引读取 index-read-row-start, index-read-row-done
handler-rdlock-start, handler-rdlock-done
handler-wrlock-start, handler-wrlock-done
handler-unlock-start, handler-unlock-done
文件排序 filesort-start,filesort-done
陈述 select-start,select-done
insert-start,insert-done
insert-select-start, insert-select-done
update-start,update-done
multi-update-start, multi-update-done
delete-start,delete-done
multi-delete-start, multi-delete-done
网络 net-read-start, net-read-done, net-write-start, net-write-done
密钥缓存 keycache-read-start,,,,,,,, keycache-read-block_ keycache-read-done_ keycache-read-hit_ keycache-read-miss_ keycache-write-start_ keycache-write-block_ keycache-write-done

笔记

从探测器中提取参数数据时,每个参数都可用作 ,以 开头。为了在定义中识别每个参数,它们都提供了一个描述性名称,但您必须使用相应的 参数访问信息。 argNarg0argN

5.8.4.1.1 连接探针

connection-start和 探测包含来自客户端 的connection-done连接,无论该连接是通过套接字连接还是网络连接。

connection-start(connectionid, user, host)
connection-done(status, connectionid)
  • connection-start:在客户端完成连接并成功登录/验证后触发。参数包含连接信息:

    • connectionidunsigned long包含连接 ID 的 。这与 的输出中显示为 Id值 的进程 ID 相同SHOW PROCESSLIST

    • user: 认证时使用的用户名。匿名用户的值为空。

    • host:客户端连接的主机。对于使用 Unix 套接字建立的连接,该值为空。

  • connection-done:在与客户端的连接关闭时触发。论点是:

    • status:连接关闭时的状态。注销操作的值为 0;连接的任何其他终止都具有非零值。

    • connectionid:已关闭连接的连接 ID。

以下 D 脚本量化并总结了单个连接的平均持续时间,并提供了一个计数,每 60 秒转储一次信息:

#!/usr/sbin/dtrace -s


mysql*:::connection-start
{
  self->start = timestamp;
}

mysql*:::connection-done
/self->start/
{
  @ = quantize(((timestamp - self->start)/1000000));
  self->start = 0;
}

tick-60s
{
  printa(@);
}

在具有大量客户端的服务器上执行时,您可能会看到类似于以下内容的输出:

  1  57413                        :tick-60s

           value  ------------- Distribution ------------- count
              -1 |                                         0
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 30011
               1 |                                         59
               2 |                                         5
               4 |                                         20
               8 |                                         29
              16 |                                         18
              32 |                                         27
              64 |                                         30
             128 |                                         11
             256 |                                         10
             512 |                                         1
            1024 |                                         6
            2048 |                                         8
            4096 |                                         9
            8192 |                                         8
           16384 |                                         2
           32768 |                                         1
           65536 |                                         1
          131072 |                                         0
          262144 |                                         1
524288 |                                         0
5.8.4.1.2 命令探测器

命令探测在执行客户端命令之前和之后执行,包括在此期间可能执行的任何 SQL 语句。命令包括DB的初始化、 COM_CHANGE_USER操作的使用(MySQL协议支持)、prepared statements的操作等操作。其中许多命令仅由来自各种连接器(如 PHP 和 Java)的 MySQL 客户端 API 使用。

command-start(connectionid, command, user, host)
command-done(status)
  • command-start:当命令被提交到服务器时触发。

    • connectionid:执行命令的客户端的连接ID。

    • command:一个整数,表示已执行的命令。下表显示了可能的值。

      价值 姓名 描述
      00 COM_睡眠 内螺纹状态
      01 COM_QUIT 关闭连接
      02 COM_INIT_DB 选择数据库 ( USE ...)
      03 COM_QUERY 执行查询
      04 COM_FIELD_LIST 获取字段列表
      05 COM_CREATE_DB 创建数据库(已弃用)
      06 COM_DROP_DB 删除数据库(已弃用)
      07 COM_REFRESH 刷新连接
      08 COM_SHUTDOWN 关闭服务器
      09 COM_STATISTICS 获取统计数据
      10 COM_PROCESS_INFO 获取进程 ( SHOW PROCESSLIST)
      11 COM_CONNECT 初始化连接
      12 COM_PROCESS_KILL 杀死进程
      13 COM_DEBUG 获取调试信息
      14 COM_PING
      15 COM_TIME 内螺纹状态
      16 COM_DELAYED_INSERT 内螺纹状态
      17 COM_CHANGE_USER 更改用户
      18 COM_BINLOG_DUMP 由副本或mysqlbinlog用于启动二进制日志读取
      19 COM_TABLE_DUMP 由副本用于获取源表信息
      20 COM_CONNECT_OUT 由副本用于记录与服务器的连接
      21 COM_REGISTER_SLAVE 在注册期间由副本使用
      22 COM_STMT_PREPARE 准备一份声明
      23 COM_STMT_EXECUTE 执行语句
      24 COM_STMT_SEND_LONG_DATA 客户端在请求扩展数据时使用
      25 COM_STMT_CLOSE 关闭准备好的语句
      26 COM_STMT_RESET 重置准备好的语句
      27 COM_SET_OPTION 设置服务器选项
      28 COM_STMT_FETCH 获取准备好的语句
    • user:执行命令的用户。

    • host: 客户端主机。

  • command-done:命令执行完成时触发。如果命令成功执行,status 则参数包含 0,如果语句在正常完成之前终止,则参数包含 1。

和探测器最好command-startcommand-done语句探测器结合使用,以了解总体执行时间。

5.8.4.1.3 查询探针

当服务器接收到特定查询并且查询已完成并且信息已成功发送到客户端时,将触发 query-start和 探测器。query-done

query-start(query, connectionid, database, user, host)
query-done(status)
  • query-start:从客户端接收到查询字符串后触发。论点是:

    • query:提交查询的全文。

    • connectionid: 提交查询的客户端的连接 ID。连接 ID 等于客户端首次连接时返回的连接 ID 和Id输出中的值SHOW PROCESSLIST

    • database:正在执行查询的数据库名称。

    • user:用于连接到服务器的用户名。

    • host:客户端的主机名。

  • query-done:一旦执行了查询并且信息已返回给客户端,就会触发。探测器包含单个参数 , status当查询成功执行时返回 0,如果出现错误则返回 1。

您可以使用以下 D 脚本获取每个查询的执行时间的简单报告:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-20s %-20s %-40s %-9s\n", "Who", "Database", "Query", "Time(ms)");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->connid = arg1;
   self->db    = copyinstr(arg2);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->querystart = timestamp;
}

mysql*:::query-done
{
   printf("%-20s %-20s %-40s %-9d\n",self->who,self->db,self->query,
          (timestamp - self->querystart) / 1000000);
}

执行上述脚本时,您应该对查询的执行时间有一个基本的了解:

$> ./query.d
Who                  Database             Query                                    Time(ms)
root@localhost       test                 select * from t1 order by i limit 10     0
root@localhost       test                 set global query_cache_size=0            0
root@localhost       test                 select * from t1 order by i limit 10     776
root@localhost       test                 select * from t1 order by i limit 10     773
root@localhost       test                 select * from t1 order by i desc limit 10 795
5.8.4.1.4 查询解析探测

query parsing probes在原始SQL语句被解析之前,当语句的解析和处理语句所需的执行模型的确定已经完成时触发:

query-parse-start(query)
query-parse-done(status)
  • query-parse-start:在 MySQL 查询解析器解析语句之前触发。单个参数query是包含原始查询全文的字符串。

  • query-parse-done: 当原语句解析完成时触发。是描述操作状态的 status整数。A0表示查询已成功解析。A 1表示查询解析失败。

例如,您可以使用以下 D 脚本监视解析给定查询的执行时间:

#!/usr/sbin/dtrace -s

#pragma D option quiet

mysql*:::query-parse-start
{
   self->parsestart = timestamp;
   self->parsequery = copyinstr(arg0);
}

mysql*:::query-parse-done
/arg0 == 0/
{
   printf("Parsing %s: %d microseconds\n", self->parsequery,((timestamp - self->parsestart)/1000));
}

mysql*:::query-parse-done
/arg0 != 0/
{
   printf("Error parsing %s: %d microseconds\n", self->parsequery,((timestamp - self->parsestart)/1000));
}

在上面的脚本中,使用了一个谓词, query-parse-done以便根据探测器的状态值生成不同的输出。

运行脚本并监视执行时:

$> ./query-parsing.d
Error parsing select from t1 join (t2) on (t1.i = t2.i) order by t1.s,t1.i limit 10: 36 ms
Parsing select * from t1 join (t2) on (t1.i = t2.i) order by t1.s,t1.i limit 10: 176 ms
5.8.4.1.5 查询缓存探测

执行任何查询时都会触发查询缓存探测器。当 query-cache-hit查询缓存中存在查询时触发查询,可用于返回查询缓存信息。参数包含原始查询文本和从查询缓存返回的查询行数。如果查询不在查询缓存中,或者未启用查询缓存,则会 query-cache-miss触发探测。

query-cache-hit(query, rows)
query-cache-miss(query)
  • query-cache-hit:在查询缓存中找到查询时触发。第一个参数query包含查询的原始文本。第二个参数 rows是一个整数,包含缓存查询中的行数。

  • query-cache-miss:在查询缓存中找不到查询时触发。第一个参数query包含查询的原始文本。

查询缓存探测器最好与主查询上的探测器结合使用,以便您可以确定对指定查询使用或不使用查询缓存之间的时间差异。例如下面的D脚本中,在监控时将查询和查询缓存信息合并为信息输出:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-20s %-20s %-40s %2s %-9s\n", "Who", "Database", "Query", "QC", "Time(ms)");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->connid = arg1;
   self->db    = copyinstr(arg2);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->querystart = timestamp;
   self->qc = 0;
}

mysql*:::query-cache-hit
{
   self->qc = 1;
}

mysql*:::query-cache-miss
{
   self->qc = 0;
}

mysql*:::query-done
{
   printf("%-20s %-20s %-40s %-2s %-9d\n",self->who,self->db,self->query,(self->qc ? "Y" : "N"),
          (timestamp - self->querystart) / 1000000);
}

执行脚本时,您可以看到查询缓存的效果。最初禁用查询缓存。如果您设置查询缓存大小然后多次执行查询,您应该会看到查询缓存被用于返回查询数据:

$> ./query-cache.d
root@localhost       test                 select * from t1 order by i limit 10     N  1072
root@localhost                            set global query_cache_size=262144       N  0
root@localhost       test                 select * from t1 order by i limit 10     N  781
root@localhost       test                 select * from t1 order by i limit 10     Y  0
5.8.4.1.6 查询执行探测

查询执行探测器在查询实际执行开始时触发,在解析和检查查询缓存之后但在任何特权检查或优化之前。通过比较开始和完成探测之间的差异,您可以监控实际花费在查询服务上的时间(而不是仅仅处理查询的解析和其他元素)。

query-exec-start(query, connectionid, database, user, host, exec_type)
query-exec-done(status)
笔记

query-start和 的参数中提供的信息 query-exec-start几乎相同,并且经过专门设计,因此您可以选择监视整个查询过程(使用query-start)或仅监视执行(使用query-exec-start),同时公开有关用户、客户端和正在执行的查询的核心信息.

  • query-exec-start:开始执行单个查询时触发。论点是:

    • query:提交查询的全文。

    • connectionid: 提交查询的客户端的连接 ID。连接 ID 等于客户端首次连接时返回的连接 ID 和Id输出中的值SHOW PROCESSLIST

    • database:正在执行查询的数据库名称。

    • user:用于连接到服务器的用户名。

    • host:客户端的主机名。

    • exec_type: 执行类型。执行类型是根据查询的内容和提交的位置来确定的。每种类型的值如下表所示。

      价值 描述
      0 从 sql_parse 执行的查询,顶级查询。
      1个 执行准备好的语句
      2个 执行游标语句
      3个 在存储过程中执行查询
  • query-exec-done:查询执行完成时触发。探测器包含单个参数 ,status当查询成功执行时返回 0,如果出现错误则返回 1。

5.8.4.1.7 行级探测

每次将*row-{start,done}行操作下推到存储引擎时都会触发探测器。例如,如果您执行一条 INSERT包含 100 行数据的语句,那么对于每行插入, insert-row-start和 探测将分别触发 100 次。insert-row-done

insert-row-start(database, table)
insert-row-done(status)

update-row-start(database, table)
update-row-done(status)

delete-row-start(database, table)
delete-row-done(status)
  • insert-row-start:在将行插入表之前触发。

  • insert-row-done:在向表中插入一行后触发。

  • update-row-start:在表中更新行之前触发。

  • update-row-done:在表中更新行之前触发。

  • delete-row-start:在从表中删除行之前触发。

  • delete-row-done:在从表中删除行之前触发。

探针支持的参数对于每种情况下 的对应start和 探针是一致的:done

  • database: 数据库名称。

  • table: 表名。

  • status:状态;0 表示成功或 1 表示失败。

因为行级探测是针对每个单独的行访问触发的,这些探测每秒可能被触发数千次,这可能对监控脚本和 MySQL 都产生不利影响。DTrace 环境应限制对这些探测器的触发,以防止性能受到不利影响。要么谨慎使用探测器,要么使用计数器或聚合函数来报告这些探测器,然后在脚本终止时或作为query-doneor query-exec-done探测器的一部分提供摘要。

以下示例脚本总结了较大查询中每行操作的持续时间:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-2s %-10s %-10s %9s %9s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur ms", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->rowdur = 0;
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000000;
   printf("%2d %-10s %-10s %9d %9d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
}

mysql*:::query-done
/ self->rowdur /
{
   printf("%34s %9d %s\n", "", (self->rowdur/1000000), "-> Row ops");
}

mysql*:::insert-row-start
{
   self->rowstart = timestamp;
}

mysql*:::delete-row-start
{
   self->rowstart = timestamp;
}

mysql*:::update-row-start
{
   self->rowstart = timestamp;
}

mysql*:::insert-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

mysql*:::delete-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

mysql*:::update-row-done
{
   self->rowdur += (timestamp-self->rowstart);
}

使用将数据插入表的查询运行上述脚本,您可以监控执行原始行插入所花费的确切时间:

St Who        DB            ConnID    Dur ms Query
 0 @localhost test              13     20767 insert into t1(select * from t2)
                                        4827 -> Row ops
5.8.4.1.8 读取行探测器

每次发生行读取操作时,都会在存储引擎级别触发读取行探测。这些探测器在每个存储引擎中指定( *row-start与存储引擎接口中的探测器相反)。因此,这些探测器可用于监视单个存储引擎行级操作和性能。因为这些探测是围绕存储引擎行读取接口触发的,所以在基本查询期间它们可能会被命中很多次。

read-row-start(database, table, scan_flag)
read-row-done(status)
  • read-row-startdatabase: 当存储引擎从指定的and中读取一行时触发 table。当scan_flag读取是表扫描的一部分(即顺序读取)时设置为 1 (true),或者当读取是特定记录时设置为 0 (false)。

  • read-row-done:当存储引擎中的行读取操作完成时触发。成功时返回 0 , status失败时返回正值。

5.8.4.1.9 索引探针

每次使用指定表的索引之一读取一行时,都会触发索引探测。探测器在表的相应存储引擎中触发。

index-read-row-start(database, table)
index-read-row-done(status)
  • index-read-row-startdatabase: 当存储引擎从指定的and中读取一行时触发 table

  • index-read-row-done:当存储引擎中的索引行读取操作完成时触发。成功时返回 0 ,status失败时返回正值。

5.8.4.1.10 锁定探针

每当 MySQL 使用由表的引擎类型定义的表上的相应锁定机制为表请求外部锁定时,将调用锁定探测器。有三种不同类型的锁,读锁、写锁和解锁操作。使用探针,您可以确定外部锁定例程的持续时间(即存储引擎实现锁定所花费的时间,包括等待另一个锁变为空闲的任何时间)和锁定/解锁过程的总持续时间.

handler-rdlock-start(database, table)
handler-rdlock-done(status)

handler-wrlock-start(database, table)
handler-wrlock-done(status)

handler-unlock-start(database, table)
handler-unlock-done(status)
  • handler-rdlock-startdatabase:在指定的和上请求读取锁定时触发 table

  • handler-wrlock-startdatabase:在指定的和上请求写锁时触发 table

  • handler-unlock-startdatabase:在指定的和上发出解锁请求时触发 table

  • handler-rdlock-done:读锁定请求完成时触发。如果status 锁定操作成功或 >0失败则为 0。

  • handler-wrlock-done:写锁定请求完成时触发。如果 status锁定操作成功或>0失败则为 0。

  • handler-unlock-done:解锁请求完成时触发。如果status解锁操作成功或 >0失败则为 0。

您可以使用数组来监视单个表的锁定和解锁,然后使用以下脚本计算整个表锁定的持续时间:

#!/usr/sbin/dtrace -s

#pragma D option quiet

mysql*:::handler-rdlock-start
{
   self->rdlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   self->lockmap[this->lockref] = self->rdlockstart;
   printf("Start: Lock->Read   %s.%s\n",copyinstr(arg0),copyinstr(arg1));
}

mysql*:::handler-wrlock-start
{
   self->wrlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   self->lockmap[this->lockref] = self->rdlockstart;
   printf("Start: Lock->Write  %s.%s\n",copyinstr(arg0),copyinstr(arg1));
}

mysql*:::handler-unlock-start
{
   self->unlockstart = timestamp;
   this->lockref = strjoin(copyinstr(arg0),strjoin("@",copyinstr(arg1)));
   printf("Start: Lock->Unlock %s.%s (%d ms lock duration)\n",
          copyinstr(arg0),copyinstr(arg1),
          (timestamp - self->lockmap[this->lockref])/1000000);
}

mysql*:::handler-rdlock-done
{
   printf("End:   Lock->Read   %d ms\n",
          (timestamp - self->rdlockstart)/1000000);
}

mysql*:::handler-wrlock-done
{
   printf("End:   Lock->Write  %d ms\n",
          (timestamp - self->wrlockstart)/1000000);
}

mysql*:::handler-unlock-done
{
   printf("End:   Lock->Unlock %d ms\n",
          (timestamp - self->unlockstart)/1000000);
}

执行时,您应该获得有关锁定过程本身的持续时间以及特定表上的锁的信息:

Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (25743 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (1 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
Start: Lock->Unlock test.t2 (1 ms lock duration)
End:   Lock->Unlock 0 ms
Start: Lock->Read   test.t2
End:   Lock->Read   0 ms
5.8.4.1.11 文件排序探测器

只要将文件排序操作应用于表,就会触发文件排序探测器。有关文件排序及其发生条件的更多信息,请参阅 第 8.2.1.14 节,“ORDER BY 优化”

filesort-start(database, table)
filesort-done(status, rows)
  • filesort-start:在表上开始文件排序操作时触发。探测器的两个参数databasetable标识正在排序的表。

  • filesort-done:当文件排序操作完成时触发。提供了两个参数,status(0 表示成功,1 表示失败)和在文件排序过程中排序的行数。

下面的脚本就是一个例子,除了主查询的持续时间之外,它还跟踪文件排序过程的持续时间:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-2s %-10s %-10s %9s %18s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur microsec", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->filesort = 0;
   self->fsdb = "";
   self->fstable = "";
}

mysql*:::filesort-start
{
  self->filesort = timestamp;
  self->fsdb = copyinstr(arg0);
  self->fstable = copyinstr(arg1);
}

mysql*:::filesort-done
{
   this->elapsed = (timestamp - self->filesort) /1000;
   printf("%2d %-10s %-10s %9d %18d Filesort on %s\n",
          arg0, self->who, self->fsdb,
          self->connid, this->elapsed, self->fstable);
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000;
   printf("%2d %-10s %-10s %9d %18d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
}

ORDER BY使用触发文件排序的子句 对大表执行查询,然后在表上创建索引,然后重复相同的查询,您可以看到执行速度的差异:

St Who        DB            ConnID       Dur microsec Query
 0 @localhost test              14           11335469 Filesort on t1
 0 @localhost test              14           11335787 select * from t1 order by i limit 100
 0 @localhost test              14          466734378 create index t1a on t1 (i)
 0 @localhost test              14              26472 select * from t1 order by i limit 100
5.8.4.1.12 语句探测

提供了单独的语句探测器以提供有关不同语句类型的特定信息。对于开始探测,查询字符串作为唯一参数提供。根据语句类型,相应的完成探测提供的信息可能会有所不同。对于所有完成的探测,提供了操作的状态(0 成功、>0失败)。对于SELECTINSERTINSERT ... (SELECT FROM ...)DELETEDELETE FROM t1,t2操作,返回受影响的行数。

对于UPDATEand UPDATE t1,t2 ...语句,提供匹配的行数和实际更改的行数。这是因为相应 WHERE子句实际匹配的行数和更改的行数可能不同。如果值已经与新设置匹配,MySQL 不会更新行的值。

select-start(query)
select-done(status,rows)

insert-start(query)
insert-done(status,rows)

insert-select-start(query)
insert-select-done(status,rows)

update-start(query)
update-done(status,rowsmatched,rowschanged)

multi-update-start(query)
multi-update-done(status,rowsmatched,rowschanged)

delete-start(query)
delete-done(status,rows)

multi-delete-start(query)
multi-delete-done(status,rows)
  • select-startSELECT: 在语句 之前触发 。

  • select-doneSELECT: 在语句 结束时触发 。

  • insert-startINSERT: 在语句 之前触发 。

  • insert-doneINSERT: 在语句 结束时触发 。

  • insert-select-startINSERT ... SELECT: 在语句 之前触发。

  • insert-select-doneINSERT ... SELECT: 在语句 结束时触发。

  • update-startUPDATE: 在语句 之前触发 。

  • update-doneUPDATE: 在语句 结束时触发 。

  • multi-update-startUPDATE:在涉及多个表 的语句之前触发 。

  • multi-update-doneUPDATE:在涉及多个表 的语句结束时触发。

  • delete-startDELETE: 在语句 之前触发 。

  • delete-doneDELETE: 在语句 结束时触发 。

  • multi-delete-startDELETE:在涉及多个表 的语句之前触发 。

  • multi-delete-doneDELETE:在涉及多个表 的语句结束时触发。

语句探测的参数是:

  • query: 查询字符串。

  • status:查询的状态。 0为了成功, >0为了失败。

  • rows: 语句影​​响的行数。这将返回为 找到 SELECT的行数、为 删除的行DELETE数以及为 成功插入的行数 INSERT

  • rowsmatchedWHERE:与操作的子句 匹配的行数UPDATE

  • rowschanged:操作期间实际更改的行数 UPDATE

您可以使用这些探测器来监视这些语句类型的执行,而不必监视执行这些语句的用户或客户端。一个简单的例子是跟踪执行时间:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
   printf("%-60s %-8s %-8s %-8s\n", "Query", "RowsU", "RowsM", "Dur (ms)");
}

mysql*:::update-start, mysql*:::insert-start,
mysql*:::delete-start, mysql*:::multi-delete-start,
mysql*:::multi-delete-done, mysql*:::select-start,
mysql*:::insert-select-start, mysql*:::multi-update-start
{
    self->query = copyinstr(arg0);
    self->querystart = timestamp;
}

mysql*:::insert-done, mysql*:::select-done,
mysql*:::delete-done, mysql*:::multi-delete-done, mysql*:::insert-select-done
/ self->querystart /
{
    this->elapsed = ((timestamp - self->querystart)/1000000);
    printf("%-60s %-8d %-8d %d\n",
           self->query,
           0,
           arg1,
           this->elapsed);
    self->querystart = 0;
}

mysql*:::update-done, mysql*:::multi-update-done
/ self->querystart /
{
    this->elapsed = ((timestamp - self->querystart)/1000000);
    printf("%-60s %-8d %-8d %d\n",
           self->query,
           arg1,
           arg2,
           this->elapsed);
    self->querystart = 0;
}

执行时,您可以看到基本的执行时间和行匹配:

Query                                                        RowsU    RowsM    Dur (ms)
select * from t2                                             0        275      0
insert into t2 (select * from t2)                            0        275      9
update t2 set i=5 where i > 75                               110      110      8
update t2 set i=5 where i < 25                               254      134      12
delete from t2 where i < 5                                   0        0        0

另一种方法是使用 DTrace 中的聚合函数将各个语句的执行时间聚合在一起:

#!/usr/sbin/dtrace -s

#pragma D option quiet


mysql*:::update-start, mysql*:::insert-start,
mysql*:::delete-start, mysql*:::multi-delete-start,
mysql*:::multi-delete-done, mysql*:::select-start,
mysql*:::insert-select-start, mysql*:::multi-update-start
{
    self->querystart = timestamp;
}

mysql*:::select-done
{
        @statements["select"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::insert-done, mysql*:::insert-select-done
{
        @statements["insert"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::update-done, mysql*:::multi-update-done
{
        @statements["update"] = sum(((timestamp - self->querystart)/1000000));
}

mysql*:::delete-done, mysql*:::multi-delete-done
{
        @statements["delete"] = sum(((timestamp - self->querystart)/1000000));
}

tick-30s
{
        printa(@statements);
}

刚刚显示的脚本汇总了执行每个操作所花费的时间,可用于帮助对标准测试套件进行基准测试。

 delete                                                            0
  update                                                            0
  insert                                                           23
  select                                                         2484

  delete                                                            0
  update                                                            0
  insert                                                           39
  select                                                        10744

  delete                                                            0
  update                                                           26
  insert                                                           56
  select                                                        10944

  delete                                                            0
  update                                                           26
  insert                                                         2287
  select                                                        15985
5.8.4.1.13 网络探测

网络探测器监视通过网络从 MySQL 服务器和所有类型的客户端传输的信息。探针定义如下:

net-read-start()
net-read-done(status, bytes)
net-write-start(bytes)
net-write-done(status)
  • net-read-start:当网络读取操作开始时触发。

  • net-read-done:网络读取操作完成时触发。status是一个integer 表示操作返回状态的 , 表示 0成功和1 失败。该bytes参数是一个整数,指定在该过程中读取的字节数。

  • net-start-bytes:当数据写入网络套接字时触发。单个参数 bytes指定写入网络套接字的字节数。

  • net-write-done:网络写操作完成时触发。单个参数status是一个整数,表示操作的返回状态, 0成功和1 失败。

您可以使用网络探测来监视在执行期间读取和写入网络客户端所花费的时间。下面的 D 脚本提供了一个例子。计算读取或写入的累积时间和字节数。请注意,动态变量大小已增加(使用dynvarsize选项)以应对网络读/写的单个探测器的快速触发。

#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option dynvarsize=4m

dtrace:::BEGIN
{
   printf("%-2s %-30s %-10s %9s %18s %-s \n",
          "St", "Who", "DB", "ConnID", "Dur microsec", "Query");
}

mysql*:::query-start
{
   self->query = copyinstr(arg0);
   self->who   = strjoin(copyinstr(arg3),strjoin("@",copyinstr(arg4)));
   self->db    = copyinstr(arg2);
   self->connid = arg1;
   self->querystart = timestamp;
   self->netwrite = 0;
   self->netwritecum = 0;
   self->netwritebase = 0;
   self->netread = 0;
   self->netreadcum = 0;
   self->netreadbase = 0;
}

mysql*:::net-write-start
{
   self->netwrite += arg0;
   self->netwritebase = timestamp;
}

mysql*:::net-write-done
{
   self->netwritecum += (timestamp - self->netwritebase);
   self->netwritebase = 0;
}

mysql*:::net-read-start
{
   self->netreadbase = timestamp;
}

mysql*:::net-read-done
{
   self->netread += arg1;
   self->netreadcum += (timestamp - self->netreadbase);
   self->netreadbase = 0;
}

mysql*:::query-done
{
   this->elapsed = (timestamp - self->querystart) /1000000;
   printf("%2d %-30s %-10s %9d %18d %s\n",
          arg0, self->who, self->db,
          self->connid, this->elapsed, self->query);
   printf("Net read: %d bytes (%d ms) write: %d bytes (%d ms)\n",
               self->netread, (self->netreadcum/1000000),
               self->netwrite, (self->netwritecum/1000000));
}

在带有远程客户端的机器上执行上述脚本时,您可以看到执行查询所花费的大约三分之一的时间与将查询结果写回客户端有关。

St Who                            DB            ConnID       Dur microsec Query
 0 root@::ffff:198.51.100.108      test              31               3495 select * from t1 limit 1000000
Net read: 0 bytes (0 ms) write: 10000075 bytes (1220 ms)
5.8.4.1.14 密钥缓存探测

当使用与 MyISAM 存储引擎一起使用的索引键缓存时,将触发键缓存探测。存在探针以监视何时将数据读入 keycache,缓存的 key 数据从缓存写入缓存文件,或何时访问 keycache。

Keycache 使用情况指示何时从索引文件读取数据或将数据写入缓存,并且可用于监视分配给 keycache 的内存的使用效率。在一系列查询中读取大量 keycache 可能表明 keycache 太小而无法访问数据大小。

keycache-read-start(filepath, bytes, mem_used, mem_free)
keycache-read-block(bytes)
keycache-read-hit()
keycache-read-miss()
keycache-read-done(mem_used, mem_free)
keycache-write-start(filepath, bytes, mem_used, mem_free)
keycache-write-block(bytes)
keycache-write-done(mem_used, mem_free)

当从索引文件中读取数据 到keycache时,进程首先初始化读取操作 keycache-read-start(用读 ( )。读取操作完成后,读取将停止并显示 。 keycache-read-blockkeycache-read-hitkeycache-read-misskeycache-read-done

只有当指定的键不在键缓存中时,才能将数据从索引文件读入键缓存。

  • keycache-read-start:开始keycache读取操作时触发。从指定的数据中读取filepath,读取指定的数量bytesmem_used和 表示密钥缓存当前使用的 mem_avail内存以及密钥缓存中可用的内存量。

  • keycache-read-block:当keycache bytes从索引文件中读取到指定数量的数据块到keycache中时触发。

  • keycache-read-hit:当从索引文件中读取的数据块与请求的关键数据匹配时触发。

  • keycache-read-miss:当从索引文件中读取的数据块与所需的关键数据不匹配时触发。

  • keycache-read-done:当keycache读取操作完成时触发。mem_used和 表示密钥缓存当前使用的 mem_avail内存以及密钥缓存中可用的内存量。

INSERT当在、 UPDATE或操作 期间更新索引信息时,将发生 Keycache 写入DELETE ,并且缓存的密钥信息被刷新回索引文件。

  • keycache-write-start:开始keycache写操作时触发。数据写入指定filepath,读取指定数量bytesmem_used和 表示密钥缓存当前使用的 mem_avail内存以及密钥缓存中可用的内存量。

  • keycache-write-block:当keycache从keycache中写入指定数量的数据块bytes到索引文件时触发。

  • keycache-write-done: keycache 写入操作完成时触发。mem_used和 表示密钥缓存当前使用的 mem_avail内存以及密钥缓存中可用的内存量。