Skip to content

智能统计

Jesse edited this page Aug 31, 2020 · 5 revisions

trace缓存空间介绍

Arkproxy 支持对 SQL 语句的统计与全日志记录。 分为两种记录模式,包括统计类型的 digest cache 功能与SQL全日志记录的 sql cache,分别有两个参数控制:proxy_digest_trace,proxy_sql_trace。 参数 proxy_sql_trace 需要依赖 proxy_digest_trace,只有proxy_digest_trace 打开了,proxy_sql_trace 打开之后才能起作用。这两个参数都是可以动态打开或者关闭的,也就是立即生效,方便在Arkproxy运行的过程中,还可以调整相关参数。

在Arkproxy内部,维护了一个缓存空间,与缓存空间相关的参数有 proxy_trace_queue_array_length,proxy_trace_hash_size、 proxy_trace_client_queue_size、proxy_format_thread_num等,在缓存创建好之后,这些参数还是可以动态修改,但修改之后,在当前缓存空间中,是不会起作用的。

Arkproxy 提供了可以动态调整缓存空间大小的方法,即通过管理 Shell 端口手动配置。

Arkproxy 可以通过命令来手动关闭缓存空间,命令为:config trace sql cache close;这个命令是用来关闭 SQL Cache 的,也就是类似 general log 的功能。关闭这个缓存的前提是,需要将参数 proxy_sql_trace 关闭,同时还要等待 SQL Cache 中的任务已经完成,防止丢失里面的数据。如果都没有问题,则可以成功关闭 SQL cache。而此时的操作,是不会影响 digest cache 的,这个缓存空间还是会正常运行并记录。

如果想调整 digest 相关的参数,则需要使用另一个命令手动将 digest cache 关闭,但此时需要注意的是,关闭这个缓存,arkproxy 同时也会将 sql cache 关闭,也就是这个命令会将整个 trace 的缓存空间关闭并释放。命令 config trace cache close;

如果报如下错误:

mysql> config trace cache close; 

ERROR 2084 (HY000): proxy config error: 'please set variable proxy_sql_trace and proxy_digest_trace to OFF first'. 

则按照报错信息来操作,需要将两个参数都关闭之后,再来重试。

如果报如下错误:

mysql> config trace cache close; 
ERROR 2084 (HY000): proxy config error: 'please wait the sql trace cache is empty'. 

此时,可能是因为 sql cache 还有任务没有执行完成,需要等待一会儿重新再试一次即可。当然如果等待时间有点长,则可以通过调整相关参数,可以加速cache中记录的处理。在关闭缓存之后,此时就可以根据自己的需求,来调整相应的参数,比如线程数,trace队列大小等,然后就可以再次创建了,创建过程,也是通过命令来实现的。

通过这个 config trace cache create; 命令,就可以实现对 digest cache 的创建,需要注意的是,这里创建的只是 digest cache ,而不会去创建sql cache的。当然创建过程与参数proxy_digest_trace及proxy_sql_trace也没有关系,这两个参数与缓存是完全独立的。创建过程不会报错。

如果已经创建了,则直接返回。创建之后,就可以通过将参数 proxy_digest_trace 设置为ON,此时可以观察对应的 proxy_namespace 库或者配置的后端数据库的 mysql.query_digest 表的变化了。如果只是创建了缓存,而参数 proxy_digest_trace 并没有开启,则不会生成相应的 digest 数据。

相应地,创建 SQL Cache 也是一样的,通过下面的命令来实现: config trace sql cache create; 与关闭的区别是,sql cache 的创建动作,是会将 digest cache 同时创建起来,因为sql cache 会依赖 digest。创建完成之后,arkproxy 还是不会生成相应信息的,此时需要将两个参数打开,然后再去观察相应位置的数据变化。比如 mysql.query_digest,mysql.query_sql 或者在proxy_namespace 所配置的数据库下面。

在创建或者关闭 digest 缓存的时候,都是可以通过命令来查看其状态的。比如:show trace status 这个命令。

各字段含义如下:

column 含义
Empty_Count 空闲缓存对象个数
Busy_Count 处于被占用状态
Format_Count 正在处理digest合并或者入库等信息
Reset_Count 对象已经被使用过,目前也处于空闲状态,表示目前已经可以再次被使用。

如果能看到有结果集,则说明当前已经创建了 trace digest 缓存。如果结果集为空,则没有创建,需要手动创建。

show trace full status 这个命令展示的数据是一个详细的使用情况,但不是每次都会展示所有的缓存对象,只会展示状态为Busy和Format两种状态的对象缓存情况。

各字段含义如下:

column 含义
Array_Index 表示的是当前对象在整个缓存空间的序列号(以0为起点)
Thread_ID 表示的是当前使用这个对象的Arkproxy中的连接ID
Queue_State 队列状态
Enqueue_Index 表示的是前缓存对象中,所管理的任务队列的入队位置
Dequeue_Index 表示的是前缓存对象中,所管理的任务队列的出队位置
Digest_Sum 表示的是处理过的任务总数

Trace 写入到 Kafka

参数 proxy_trace_storage 设置为Kafka时,打开 Trace 之后,Trace 包括两个模块,分别是 Trace Digest 和 Trace SQL,这两个模块分别属于两个Topic,订阅名称为 trace_digest 和 trace_sql,在启动之后,可以通过订阅这两个topic来拿到对应的 JSON 数据,JSON 数据内容和 MySQL 存储方式的对应两个表的存储内容相同。会存储到配置的参数proxy_trace_storage_host:proxy_trace_storage_port 数据库。

Trace 写入到 MySQL

参数 proxy_trace_storage 设置为 MySQL 时,Trace 产生的信息就会存储到 MySQL,库名通过proxy_namespace 来指定,存储到 query_digest 和 query_sql 表。

表结构如下:

CREATE TABLE `query_digest` ( 
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'auto increment', 
`schemaname` varchar(65) NOT NULL COMMENT 'db name', 
`username` varchar(65) NOT NULL COMMENT 'user name', 
`digest` varchar(65) NOT NULL COMMENT 'hash key', 
`formatsql` text COMMENT 'format sql', 
`count` bigint(20) NOT NULL COMMENT 'sum of sql', 
`first_seen` bigint(20) NOT NULL COMMENT 'first_seen', 
`last_seen` bigint(20) NOT NULL COMMENT 'last_seen', 
`sum_time` bigint(20) NOT NULL COMMENT 'sum of sql time', 
`min_time` bigint(20) NOT NULL COMMENT 'min time per sql', 
`max_time` bigint(20) NOT NULL COMMENT 'max time per sql', 
PRIMARY KEY (`id`), 
UNIQUE KEY `uniq_digest` (`digest`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='digest table'; 

这个表用来统计同一个 digest(digest 是将参数常里值变为?之后,再加上用户名 username 和数据库名 schemaname 这三者做的 hash)的语句的统计信息,包括格式化后的 SQL:formatsql、出现次数 count、第一次出现时间 first_seen、最后一次出现时间 last_seen、总的时间 sum_time、最小时间 min_time、最大时间 max_time 等。

CREATE TABLE `query_sql` ( 
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'auto increment', 
`schemaname` varchar(65) NOT NULL COMMENT 'db name', 
`client_ip` varchar(65) NOT NULL COMMENT 'client ip', 
`username` varchar(65) NOT NULL COMMENT 'user name', 
`sql_key` varchar(65) NOT NULL COMMENT 'hash key', 
`digest` varchar(65) NOT NULL COMMENT 'digest hash key', 
`origin_sql` text COMMENT 'origin sql', 
`affect_rows` bigint(20) NOT NULL COMMENT 'affect rows', 
`appear_ts` bigint(20) NOT NULL COMMENT 'appear timestamp', 
`exe_time` bigint(20) NOT NULL COMMENT 'sum of sql time', 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='origin sql table';

这个表用来存储类似 mysql 的general log,所有的语句都会存储起来,包括数据库名schemaname、客户端连接 IP client_ip、用户名 username、SQL 的 HASH 值 sql_key、与query_digest 表中 digest 列对应的 digest 值,可以用来连接查询找到对应的不同所有的 SQL 语句、原始SQL语句 origin_sql、影响行数 affect_rows、出现时间 appear_ts、执行时间 exe_time。

trace日志打印到 kafka

操作步骤

  1. 在配置文件修改 trace 接收端为 kafka,将已经搭建好的 kafka 环境添加进去。
proxy_trace_storage                      = KAFKA
proxy_trace_storage_host                 = 10.0.0.101
proxy_trace_storage_port                 = 19092
  1. 重新启动arkproxy(参数支持在线修改,不过需要关闭trace后重新创建生效)
  2. trace digest 和 trace SQL 分别属于 trace_digest 和 trace_sql 两个 topic,可以在kafka中订阅这两个topic来获取JSON数据用于后续分析。

trace_kafka1 trace_kafka2

trace日志打印到MySQL

操作步骤

  1. 参数 proxy_digest_trace & proxy_sql_trace 默认关闭,支持动态开启,默认相关配置表在MySQL 集群的 mysql 数据库中。
set  global proxy_digest_trace=on;
set  global proxy_sql_trace=on;
config flush;
config write outfile '/etc/arkproxy.cnf'; 
mysql> show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| proxy_user                |
| query_digest              |
| query_sql                 |

digest 的统计情况 select * from query_digest; trace_mysql1

如果要看具体的SQL,可以统一 digest列,进行 where 过滤: 可以很清晰的看到,执行时的时间点,执行时间等 trace_mysql2

  1. 如果统计信息设置到远程数据库,可以配置下列参数到远程 统计之后的信息会被存储到 proxy_config_host:proxy_config_port 所设置的目标数据库中。
proxy_config_host                        =
proxy_config_passwd                      =
proxy_config_port                        = 0
proxy_config_user                        =
Clone this wiki locally