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 |
从探测器中提取参数数据时,每个参数都可用作
,以 开头。为了在定义中识别每个参数,它们都提供了一个描述性名称,但您必须使用相应的
参数访问信息。
arg
N
arg0
arg
N
connection-start
和
探测包含来自客户端
的connection-done
连接,无论该连接是通过套接字连接还是网络连接。
connection-start(connectionid, user, host)
connection-done(status, connectionid)
connection-start
:在客户端完成连接并成功登录/验证后触发。参数包含连接信息:connectionid
:unsigned 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
命令探测在执行客户端命令之前和之后执行,包括在此期间可能执行的任何 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-start
与
command-done
语句探测器结合使用,以了解总体执行时间。
当服务器接收到特定查询并且查询已完成并且信息已成功发送到客户端时,将触发
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
query parsing probes在原始SQL语句被解析之前,当语句的解析和处理语句所需的执行模型的确定已经完成时触发:
query-parse-start(query)
query-parse-done(status)
query-parse-start
:在 MySQL 查询解析器解析语句之前触发。单个参数query
是包含原始查询全文的字符串。query-parse-done
: 当原语句解析完成时触发。是描述操作状态的status
整数。A0
表示查询已成功解析。A1
表示查询解析失败。
例如,您可以使用以下 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
执行任何查询时都会触发查询缓存探测器。当
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
查询执行探测器在查询实际执行开始时触发,在解析和检查查询缓存之后但在任何特权检查或优化之前。通过比较开始和完成探测之间的差异,您可以监控实际花费在查询服务上的时间(而不是仅仅处理查询的解析和其他元素)。
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。
每次将*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-done
or
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
每次发生行读取操作时,都会在存储引擎级别触发读取行探测。这些探测器在每个存储引擎中指定(
*row-start
与存储引擎接口中的探测器相反)。因此,这些探测器可用于监视单个存储引擎行级操作和性能。因为这些探测是围绕存储引擎行读取接口触发的,所以在基本查询期间它们可能会被命中很多次。
read-row-start(database, table, scan_flag)
read-row-done(status)
read-row-start
database
: 当存储引擎从指定的and中读取一行时触发table
。当scan_flag
读取是表扫描的一部分(即顺序读取)时设置为 1 (true),或者当读取是特定记录时设置为 0 (false)。read-row-done
:当存储引擎中的行读取操作完成时触发。成功时返回 0 ,status
失败时返回正值。
每次使用指定表的索引之一读取一行时,都会触发索引探测。探测器在表的相应存储引擎中触发。
index-read-row-start(database, table)
index-read-row-done(status)
index-read-row-start
database
: 当存储引擎从指定的and中读取一行时触发table
。index-read-row-done
:当存储引擎中的索引行读取操作完成时触发。成功时返回 0 ,status
失败时返回正值。
每当 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-start
database
:在指定的和上请求读取锁定时触发table
。handler-wrlock-start
database
:在指定的和上请求写锁时触发table
。handler-unlock-start
database
:在指定的和上发出解锁请求时触发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
只要将文件排序操作应用于表,就会触发文件排序探测器。有关文件排序及其发生条件的更多信息,请参阅 第 8.2.1.14 节,“ORDER BY 优化”。
filesort-start(database, table)
filesort-done(status, rows)
filesort-start
:在表上开始文件排序操作时触发。探测器的两个参数database
和table
标识正在排序的表。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
提供了单独的语句探测器以提供有关不同语句类型的特定信息。对于开始探测,查询字符串作为唯一参数提供。根据语句类型,相应的完成探测提供的信息可能会有所不同。对于所有完成的探测,提供了操作的状态(0
成功、>0
失败)。对于SELECT
、
INSERT
、
INSERT ... (SELECT
FROM ...)
、DELETE
和DELETE FROM
t1,t2
操作,返回受影响的行数。
对于UPDATE
and
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-start
SELECT
: 在语句 之前触发 。select-done
SELECT
: 在语句 结束时触发 。insert-start
INSERT
: 在语句 之前触发 。insert-done
INSERT
: 在语句 结束时触发 。insert-select-start
INSERT ... SELECT
: 在语句 之前触发。insert-select-done
INSERT ... SELECT
: 在语句 结束时触发。update-start
UPDATE
: 在语句 之前触发 。update-done
UPDATE
: 在语句 结束时触发 。multi-update-start
UPDATE
:在涉及多个表 的语句之前触发 。multi-update-done
UPDATE
:在涉及多个表 的语句结束时触发。delete-start
DELETE
: 在语句 之前触发 。delete-done
DELETE
: 在语句 结束时触发 。multi-delete-start
DELETE
:在涉及多个表 的语句之前触发 。multi-delete-done
DELETE
:在涉及多个表 的语句结束时触发。
语句探测的参数是:
您可以使用这些探测器来监视这些语句类型的执行,而不必监视执行这些语句的用户或客户端。一个简单的例子是跟踪执行时间:
#!/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
网络探测器监视通过网络从 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)
当使用与 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-block
keycache-read-hit
keycache-read-miss
keycache-read-done
只有当指定的键不在键缓存中时,才能将数据从索引文件读入键缓存。
keycache-read-start
:开始keycache读取操作时触发。从指定的数据中读取filepath
,读取指定的数量bytes
。mem_used
和 表示密钥缓存当前使用的mem_avail
内存以及密钥缓存中可用的内存量。keycache-read-block
:当keycachebytes
从索引文件中读取到指定数量的数据块到keycache中时触发。keycache-read-hit
:当从索引文件中读取的数据块与请求的关键数据匹配时触发。keycache-read-miss
:当从索引文件中读取的数据块与所需的关键数据不匹配时触发。keycache-read-done
:当keycache读取操作完成时触发。mem_used
和 表示密钥缓存当前使用的mem_avail
内存以及密钥缓存中可用的内存量。
INSERT
当在、
UPDATE
或操作
期间更新索引信息时,将发生 Keycache 写入DELETE
,并且缓存的密钥信息被刷新回索引文件。
keycache-write-start
:开始keycache写操作时触发。数据写入指定filepath
,读取指定数量bytes
。mem_used
和 表示密钥缓存当前使用的mem_avail
内存以及密钥缓存中可用的内存量。keycache-write-block
:当keycache从keycache中写入指定数量的数据块bytes
到索引文件时触发。keycache-write-done
: keycache 写入操作完成时触发。mem_used
和 表示密钥缓存当前使用的mem_avail
内存以及密钥缓存中可用的内存量。