目录
[1. global_variables ------ 变量兼容](#1. global_variables —— 变量兼容)
[2. stats_memory_metrics ------ 内存使用监控](#2. stats_memory_metrics —— 内存使用监控)
[三、MySQL 统计表](#三、MySQL 统计表)
[1. stats_mysql_processlist ------ 实时查询监控](#1. stats_mysql_processlist —— 实时查询监控)
[2. stats_mysql_query_digest ------ 慢查询聚合分析](#2. stats_mysql_query_digest —— 慢查询聚合分析)
[3. stats_mysql_commands_counters ------ 命令类型统计](#3. stats_mysql_commands_counters —— 命令类型统计)
[4. stats_mysql_global ------ 全局指标](#4. stats_mysql_global —— 全局指标)
[5. stats_mysql_connection_pool ------ 后端连接池](#5. stats_mysql_connection_pool —— 后端连接池)
[6. stats_mysql_free_connections ------ 空闲连接详情](#6. stats_mysql_free_connections —— 空闲连接详情)
[7. stats_mysql_errors ------ 后端错误追踪](#7. stats_mysql_errors —— 后端错误追踪)
[8. stats_mysql_query_rules ------ 规则命中统计](#8. stats_mysql_query_rules —— 规则命中统计)
[9. stats_mysql_users ------ 用户连接统计](#9. stats_mysql_users —— 用户连接统计)
[10. stats_mysql_client_host_cache ------ 客户端失败缓存](#10. stats_mysql_client_host_cache —— 客户端失败缓存)
[11. stats_mysql_gtid_executed ------ GTID 执行追踪](#11. stats_mysql_gtid_executed —— GTID 执行追踪)
[12. stats_mysql_prepared_statements_info ------ 预处理语句](#12. stats_mysql_prepared_statements_info —— 预处理语句)
[四、DBA 日常监控](#四、DBA 日常监控)
[1. 进程状态监控(替代 SHOW PROCESSLIST)](#1. 进程状态监控(替代 SHOW PROCESSLIST))
[2. 慢查询监控](#2. 慢查询监控)
[3. 长时间运行查询监控](#3. 长时间运行查询监控)
[4. 事务监控](#4. 事务监控)
[5. 连接负载分布](#5. 连接负载分布)
[6. 后端健康监控](#6. 后端健康监控)
[7. 错误追踪](#7. 错误追踪)
[8. 连接池效率](#8. 连接池效率)
[1. 慢查询配置](#1. 慢查询配置)
[2. 告警阈值建议](#2. 告警阈值建议)
[3. 日常巡检 SQL 集合](#3. 日常巡检 SQL 集合)
[七、MySQL 与 ProxySQL 监控对照表](#七、MySQL 与 ProxySQL 监控对照表)
一、概述
ProxySQL 的 stats 库提供了两类统计表:
- 通用统计表:与具体数据库协议无关的 ProxySQL 自身指标。
- MySQL 统计表:针对 MySQL 流量的运行时统计,包括查询性能、连接池、后端健康、错误率等。
访问方式:所有统计表都需要连接 ProxySQL 管理端口(缺省6033),通过 stats. 前缀访问,例如:
sql
SELECT * FROM stats.stats_mysql_processlist;
二、通用统计表
这些表涵盖了非特定于 MySQL、PostgreSQL 或 ProxySQL 集群的通用统计信息,为客户端库提供了一个兼容性适配层。它们展示了 ProxySQL 内部内存使用情况的视图,以及全局 TLS 和代理级别的指标。
1. global_variables ------ 变量兼容
用途:有些 MySQL 客户端(比如 PHP 的 PDO、Python 的 MySQLdb 等)在建立连接后,会习惯性地执行一句 SELECT @@max_allowed_packet 来确认服务端能接收多大的数据包,所以 ProxySQL 在 stats.global_variables 表里硬编码了这唯一的一行数据:
sql
ProxySQL Admin> select * from stats.global_variables;
+--------------------------+----------------+
| variable_name | variable_value |
+--------------------------+----------------+
| mysql-max_allowed_packet | 4194304 |
+--------------------------+----------------+
1 row in set (0.00 sec)
这是一个静态的"摆设",专门用来应付某些"一上来就查系统变量"的客户端,防止它们报错。表中的值没有意义。
表结构:
sql
CREATE TABLE global_variables (
Variable_Name VARCHAR NOT NULL PRIMARY KEY,
Variable_Value VARCHAR NOT NULL
)
2. stats_memory_metrics ------ 内存使用监控
此表显示 ProxySQL 内部各种结构的内存使用情况。目前只跟踪了少数结构:SQLite、认证模块、查询摘要。最重要的监控值是与 jemalloc(ProxySQL 内置的内存分配器)相关的值。
表结构:
sql
CREATE TABLE stats_memory_metrics (
Variable_Name VARCHAR NOT NULL PRIMARY KEY,
Variable_Value VARCHAR NOT NULL
)
Jemalloc 指标:
-
jemalloc_allocated: 应用程序分配的字节数 -
jemalloc_active: 应用程序分配的页面中的字节数 -
jemalloc_mapped: 分配器映射的扩展块中的字节数 -
jemalloc_metadata: 专用于元数据的字节数 -
jemalloc_resident: 分配器映射的物理驻留数据页面中的字节数 -
jemalloc_retained: 保留以供将来重用的虚拟内存映射中的字节数
其他内存指标:
-
Auth_memory: 认证模块用于存储用户凭证和属性的内存 -
SQLite3_memory_bytes: 嵌入式 SQLite 使用的内存 -
query_digest_memory: 用于存储与stats_mysql_query_digest相关数据的内存 -
mysql_query_rules_memory: 查询规则使用的内存 -
mysql_firewall_users_table: 防火墙用户查找表使用的内存 -
mysql_firewall_users_config: 防火墙用户配置使用的内存 -
mysql_firewall_rules_table: 防火墙规则查找表使用的内存 -
mysql_firewall_rules_config: 防火墙规则配置使用的内存 -
stack_memory_mysql_threads: MySQL 工作线程内存 * 栈大小 -
stack_memory_admin_threads: 管理连接内存 * 栈大小 -
stack_memory_cluster_threads: ProxySQL 集群线程内存 * 栈大小
三、MySQL 统计表
1. stats_mysql_processlist ------ 实时查询监控
用途 :提供当前 ProxySQL 连接正在执行的操作信息,相当于 MySQL 的 SHOW PROCESSLIST。
表结构:
sql
CREATE TABLE stats.stats_mysql_processlist (
ThreadID INT NOT NULL,
SessionID INTEGER PRIMARY KEY,
user VARCHAR,
db VARCHAR,
cli_host VARCHAR,
cli_port VARCHAR,
hostgroup VARCHAR,
l_srv_host VARCHAR,
l_srv_port VARCHAR,
srv_host VARCHAR,
srv_port VARCHAR,
command VARCHAR,
time_ms INT NOT NULL,
info VARCHAR,
status_flags INT,
extended_info VARCHAR
);
字段语义:
| 字段 | 说明 |
|---|---|
ThreadID |
ProxySQL 内部线程 ID(从 0 开始编号) |
SessionID |
会话全局唯一标识符,可用于 KILL 连接 |
user |
客户端连接 ProxySQL 使用的 MySQL 用户名 |
db |
当前选中的 schema |
cli_host / cli_port |
客户端与 ProxySQL 之间的 TCP 连接地址 |
hostgroup |
当前主机组(查询路由的目标) |
srv_host / srv_port |
后端 MySQL 服务器地址 |
command |
正在执行的 MySQL 命令类型 |
time_ms |
当前命令状态已持续的毫秒数 |
info |
实际执行的查询文本 |
extended_info |
JSON 对象,包含详细的连接和会话信息(autocommit、charset、transaction 状态等) |
提示 :ProxySQL 也支持
SHOW PROCESSLIST和SHOW FULL PROCESSLIST命令。
2. stats_mysql_query_digest ------ 慢查询聚合分析
用途 :这是慢查询监控的核心表 。基于 SQL 指纹(参数替换为 ?)聚合统计,用于识别慢查询模式和优化目标。ProxySQL 会把结构相同、但参数值不同的 SQL 语句归为同一类来统计。"SQL 指纹" 就是把 SQL 语句里的具体数值去掉,替换成 ?,只保留它的"骨架"。
表结构:
sql
CREATE TABLE stats.stats_mysql_query_digest (
hostgroup INT,
schemaname VARCHAR NOT NULL,
username VARCHAR NOT NULL,
client_address VARCHAR NOT NULL,
digest VARCHAR NOT NULL,
digest_text VARCHAR NOT NULL,
count_star INTEGER NOT NULL,
first_seen INTEGER NOT NULL,
last_seen INTEGER NOT NULL,
sum_time INTEGER NOT NULL,
min_time INTEGER NOT NULL,
max_time INTEGER NOT NULL,
sum_rows_affected INTEGER NOT NULL,
sum_rows_sent INTEGER NOT NULL,
PRIMARY KEY(hostgroup, schemaname, username, client_address, digest)
);
字段语义:
| 字段 | 说明 |
|---|---|
hostgroup |
查询发送的目标主机组;-1 表示查询缓存命中 |
schemaname |
被查询的 schema |
username |
客户端连接 ProxySQL 使用的用户名 |
client_address |
客户端地址(需启用 mysql-query_digests_track_hostname=true) |
digest |
十六进制哈希,唯一标识参数化后的查询模式 |
digest_text |
参数化后的查询文本(参数替换为 ?) |
count_star |
执行总次数 |
first_seen / last_seen |
Unix 时间戳,首次/最后看到的时间 |
sum_time |
总执行时间(微秒) |
min_time / max_time |
最小/最大执行时间(微秒) |
sum_rows_affected |
影响的总行数 |
sum_rows_sent |
发送给客户端的总行数(不含查询缓存) |
重要 :表中的时间是从 ProxySQL 接收到客户端查询,到 ProxySQL 准备好向客户端发送结果之间的时间。包含了 charset 变更、schema 切换、等待连接、后端故障转移等所有开销,最接近客户端感知的延迟。
启用条件 :需要 mysql-commands_stats 和 mysql-query_digests 均为 true(默认启用,建议不要禁用)。
3. stats_mysql_commands_counters ------ 命令类型统计
用途:按 SQL 命令类型(SELECT、INSERT、UPDATE 等)分类统计,并按执行时间分桶。
表结构:
sql
CREATE TABLE stats.stats_mysql_commands_counters (
Command VARCHAR NOT NULL,
Total_Time_us INT NOT NULL,
Total_cnt INT NOT NULL,
cnt_100us INT NOT NULL,
cnt_500us INT NOT NULL,
cnt_1ms INT NOT NULL,
cnt_5ms INT NOT NULL,
cnt_10ms INT NOT NULL,
cnt_50ms INT NOT NULL,
cnt_100ms INT NOT NULL,
cnt_500ms INT NOT NULL,
cnt_1s INT NOT NULL,
cnt_5s INT NOT NULL,
cnt_10s INT NOT NULL,
cnt_INFs INT NOT NULL,
PRIMARY KEY(Command)
);
字段语义:
| 字段 | 说明 |
|---|---|
Command |
SQL 命令类型(如 SELECT、INSERT、UPDATE、FLUSH、KILL 等) |
Total_Time_us |
该类命令总耗时(微秒) |
Total_cnt |
执行总次数 |
cnt_100us |
在 100 微秒内完成的次数 |
cnt_500us |
在 100-500 微秒内完成的次数 |
| ... | 以此类推,直到 cnt_10s |
cnt_INFs |
执行时间超过 10 秒的次数 |
注意 :统计需要
mysql-commands_stats=true(默认启用),建议不要禁用。
4. stats_mysql_global ------ 全局指标
用途:最重要的统计表之一,导出 ProxySQL 内部的各种全局计数器。
表结构:
sql
CREATE TABLE stats.stats_mysql_global (
Variable_Name VARCHAR NOT NULL PRIMARY KEY,
Variable_Value VARCHAR NOT NULL
);
关键指标分类:
运行时间和连接
| 指标 | 说明 |
|---|---|
ProxySQL_Uptime |
ProxySQL 运行秒数 |
Active_Transactions |
当前正在处理事务的客户端连接数 |
Client_Connections_connected |
当前连接的客户端数 |
Client_Connections_created |
累计创建的客户端连接数 |
Client_Connections_aborted |
失败或异常关闭的客户端连接数 |
Server_Connections_connected |
当前后端连接数 |
Server_Connections_created |
累计创建的后端连接数 |
查询统计
| 指标 | 说明 |
|---|---|
Questions |
客户端请求/语句总数 |
Slow_queries |
超过 mysql-long_query_time 毫秒的慢查询数 |
Queries_backends_bytes_sent |
发送给后端的字节总数 |
Queries_backends_bytes_recv |
从后端接收的字节总数 |
连接池
| 指标 | 说明 |
|---|---|
ConnPool_get_conn_success |
从连接池成功获取连接的次数 |
ConnPool_get_conn_failure |
从连接池获取连接失败的次数 |
ConnPool_get_conn_immediate |
从本地连接池缓存立即获取的连接数 |
预处理语句
| 指标 | 说明 |
|---|---|
Com_frontend_stmt_prepare |
客户端执行的 PREPARE 数量 |
Com_frontend_stmt_execute |
客户端执行的 EXECUTE 数量 |
Stmt_Client_Active_Total |
客户端正在使用的预处理语句总数 |
Stmt_Client_Active_Unique |
客户端正在使用的唯一预处理语句数 |
Stmt_Cached |
ProxySQL 缓存了元数据的全局预处理语句数 |
查询缓存
| 指标 | 说明 |
|---|---|
Query_Cache_Memory_bytes |
查询缓存使用的内存 |
Query_Cache_Entries |
查询缓存中的条目数 |
Query_Cache_count_GET |
查询缓存的读请求次数 |
Query_Cache_count_GET_OK |
查询缓存读请求成功的次数 |
监控健康
| 指标 | 说明 |
|---|---|
MySQL_Monitor_connect_check_OK/ERR |
连接检查成功/失败次数 |
MySQL_Monitor_ping_check_OK/ERR |
Ping 检查成功/失败次数 |
MySQL_Monitor_read_only_check_OK/ERR |
只读检查成功/失败次数 |
错误与拒绝
| 指标 | 说明 |
|---|---|
Access_Denied_Max_Connections |
因达到最大连接数被拒绝的连接数 |
Access_Denied_Max_User_Connections |
因达到用户级最大连接数被拒绝的连接数 |
Access_Denied_Wrong_Password |
因密码错误被拒绝的连接数 |
5. stats_mysql_connection_pool ------ 后端连接池
用途:导出后端服务器的连接池统计,包括连接使用情况、查询量和延迟。
表结构:
sql
CREATE TABLE stats.stats_mysql_connection_pool (
hostgroup VARCHAR,
srv_host VARCHAR,
srv_port VARCHAR,
status VARCHAR,
ConnUsed INT,
ConnFree INT,
ConnOK INT,
ConnERR INT,
MaxConnUsed INT,
Queries INT,
Queries_GTID_sync INT,
Bytes_data_sent INT,
Bytes_data_recv INT,
Latency_us INT
);
字段语义:
| 字段 | 说明 |
|---|---|
hostgroup |
后端服务器所属主机组 |
status |
后端状态:ONLINE、SHUNNED、OFFLINE_SOFT、OFFLINE_HARD |
ConnUsed |
当前正在使用的连接数 |
ConnFree |
连接池中保持的空闲连接数 |
ConnOK |
成功建立的总连接数 |
ConnERR |
失败的连接尝试总数 |
MaxConnUsed |
同时使用的连接数历史峰值 |
Queries |
路由到该后端的查询总数 |
Latency_us |
Monitor 报告的当前 ping 延迟(微秒) |
6. stats_mysql_free_connections ------ 空闲连接详情
用途:提供连接池中每个空闲连接的详细信息。
表结构:
sql
CREATE TABLE stats.stats_mysql_free_connections (
fd INT NOT NULL,
hostgroup INT NOT NULL,
srv_host VARCHAR NOT NULL,
srv_port INT NOT NULL,
user VARCHAR NOT NULL,
schema VARCHAR,
init_connect VARCHAR,
time_zone VARCHAR,
sql_mode VARCHAR,
autocommit VARCHAR,
idle_ms INT,
statistics VARCHAR,
mysql_info VARCHAR
);
关键字段 :fd(文件描述符)、user、schema、idle_ms(空闲毫秒数)
7. stats_mysql_errors ------ 后端错误追踪
用途:追踪后端服务器在查询执行期间报告的错误,按错误号聚合。
表结构:
sql
CREATE TABLE stats.stats_mysql_errors (
hostgroup INT NOT NULL,
hostname VARCHAR NOT NULL,
port INT NOT NULL,
username VARCHAR NOT NULL,
client_address VARCHAR NOT NULL,
schemaname VARCHAR NOT NULL,
errno INT NOT NULL,
count_star INTEGER NOT NULL,
first_seen INTEGER NOT NULL,
last_seen INTEGER NOT NULL,
last_error VARCHAR NOT NULL DEFAULT '',
PRIMARY KEY (hostgroup, hostname, port, username, schemaname, errno)
);
关键字段 :hostname、errno、count_star、last_error
8. stats_mysql_query_rules ------ 规则命中统计
用途:显示每条查询规则匹配流量的次数。
表结构:
sql
CREATE TABLE stats.stats_mysql_query_rules (
rule_id INTEGER PRIMARY KEY,
hits INT NOT NULL
);
注意 :
hits值在每次LOAD MYSQL QUERY RULES TO RUNTIME时重置。
9. stats_mysql_users ------ 用户连接统计
用途:报告用户的当前前端连接数和允许的最大连接数。
表结构:
sql
CREATE TABLE stats.stats_mysql_users (
username VARCHAR PRIMARY KEY,
frontend_connections INT NOT NULL,
frontend_max_connections INT NOT NULL
);
10. stats_mysql_client_host_cache ------ 客户端失败缓存
用途 :记录客户端连接失败的记录(需启用 mysql-client_host_cache_size > 0)。
表结构:
sql
CREATE TABLE stats.stats_mysql_client_host_cache (
client_address VARCHAR NOT NULL,
error_count INT NOT NULL,
last_updated BIGINT NOT NULL
);
11. stats_mysql_gtid_executed ------ GTID 执行追踪
用途:提供后端节点上 GTID 执行情况,用于一致性读路由。
表结构:
sql
CREATE TABLE stats.stats_mysql_gtid_executed (
hostname VARCHAR NOT NULL,
port INT NOT NULL DEFAULT 3306,
gtid_executed VARCHAR,
events INT NOT NULL
);
12. stats_mysql_prepared_statements_info ------ 预处理语句
用途:提供跨客户端和后端连接的预处理语句全局映射信息。
表结构:
sql
CREATE TABLE stats.stats_mysql_prepared_statements_info (
global_stmt_id INT NOT NULL,
hostgroup INT NOT NULL,
schemaname VARCHAR NOT NULL,
username VARCHAR NOT NULL,
digest VARCHAR NOT NULL,
ref_count_client INT NOT NULL,
ref_count_server INT NOT NULL,
num_columns INT NOT NULL,
num_params INT NOT NULL,
query VARCHAR NOT NULL
);
关键字段 :global_stmt_id、ref_count_client、ref_count_server
四、DBA 日常监控
1. 进程状态监控(替代 SHOW PROCESSLIST)
MySQL 原生命令:
sql
SELECT state, COUNT(*) FROM information_schema.processlist GROUP BY state;
ProxySQL 等效实现:
sql
-- 按 command 分组统计
SELECT command, COUNT(*) AS count
FROM stats.stats_mysql_processlist
GROUP BY command;
-- 查看活跃查询(排除 Sleep)
SELECT command, COUNT(*) AS active_count
FROM stats.stats_mysql_processlist
WHERE command != 'Sleep'
GROUP BY command;
2. 慢查询监控
sql
-- 查看慢查询总数
SELECT variable_name, variable_value
FROM stats.stats_mysql_global
WHERE variable_name = 'Slow_queries';
-- 按总耗时排序的 TOP 慢查询
SELECT
digest_text,
count_star AS exec_count,
ROUND(sum_time/1000000, 2) AS total_sec,
ROUND((sum_time/count_star)/1000, 2) AS avg_ms,
ROUND(max_time/1000, 2) AS max_ms
FROM stats.stats_mysql_query_digest
WHERE count_star > 0
ORDER BY sum_time DESC
LIMIT 10;
-- 按平均延迟排序的慢查询
SELECT
digest_text,
count_star,
ROUND((sum_time/count_star)/1000, 2) AS avg_ms
FROM stats.stats_mysql_query_digest
WHERE count_star > 0
ORDER BY avg_ms DESC
LIMIT 10;
3. 长时间运行查询监控
sql
-- 执行时间超过 10 秒的查询
SELECT SessionID, user, db, command, time_ms, SUBSTR(info, 1, 200) AS query
FROM stats.stats_mysql_processlist
WHERE command != 'Sleep' AND time_ms > 10000
ORDER BY time_ms DESC;
-- 执行时间 TOP 10
SELECT SessionID, user, db, time_ms, SUBSTR(info, 1, 200) AS query
FROM stats.stats_mysql_processlist
WHERE command != 'Sleep'
ORDER BY time_ms DESC
LIMIT 10;
4. 事务监控
sql
-- 查看当前正在执行的事务
SELECT SessionID, user, db, time_ms,
JSON_EXTRACT(extended_info, '$.conn.autocommit') AS autocommit,
JSON_EXTRACT(extended_info, '$.conn.status.transaction') AS in_transaction,
SUBSTR(info, 1, 100) AS query
FROM stats.stats_mysql_processlist
WHERE JSON_EXTRACT(extended_info, '$.conn.status.transaction') = true;
-- 查看 autocommit=0 的连接(可能的长事务)
SELECT SessionID, user, db, time_ms,
JSON_EXTRACT(extended_info, '$.conn.autocommit') AS autocommit
FROM stats.stats_mysql_processlist
WHERE JSON_EXTRACT(extended_info, '$.conn.autocommit') = 'false';
5. 连接负载分布
sql
-- 按用户分组统计连接数
SELECT user, COUNT(*) AS connections
FROM stats.stats_mysql_processlist
GROUP BY user
ORDER BY connections DESC;
-- 按后端服务器分组统计
SELECT srv_host, srv_port, COUNT(*) AS backend_connections
FROM stats.stats_mysql_processlist
WHERE srv_host IS NOT NULL
GROUP BY srv_host, srv_port;
6. 后端健康监控
sql
-- 查看后端服务器状态
SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnERR, Latency_us
FROM stats.stats_mysql_connection_pool
ORDER BY status DESC, Latency_us DESC;
-- 查看被 SHUNNED 的后端
SELECT hostgroup, srv_host, status, ConnERR
FROM stats.stats_mysql_connection_pool
WHERE status = 'SHUNNED';
7. 错误追踪
sql
-- 最常见的后端错误
SELECT hostgroup, hostname, errno, count_star, last_error
FROM stats.stats_mysql_errors
ORDER BY count_star DESC
LIMIT 10;
-- 特定错误类型查询
SELECT * FROM stats.stats_mysql_errors WHERE errno = 1045;
8. 连接池效率
sql
-- 连接池命中率
SELECT
(SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='ConnPool_get_conn_success') AS pool_hits,
(SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='ConnPool_get_conn_failure') AS pool_misses,
ROUND(100 * (SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='ConnPool_get_conn_success') /
NULLIF((SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='ConnPool_get_conn_success') +
(SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='ConnPool_get_conn_failure'), 0), 2) AS hit_rate_pct;
-- 连接复用率(前端连接数 vs 后端连接数)
SELECT
(SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='Client_Connections_connected') AS frontend,
(SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='Server_Connections_connected') AS backend,
ROUND(100 * (SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='Server_Connections_connected') /
NULLIF((SELECT variable_value FROM stats.stats_mysql_global
WHERE variable_name='Client_Connections_connected'), 0), 2) AS reuse_ratio;
五、最佳实践
1. 慢查询配置
(1)确认统计功能已启用
sql
SELECT variable_name, variable_value FROM global_variables
WHERE variable_name IN ('mysql-commands_stats', 'mysql-query_digests');
-- 期望均为 'true'
(2)设置慢查询阈值
sql
-- 默认 1000 毫秒 = 1 秒,调整为 500 毫秒
UPDATE global_variables SET variable_value='500' WHERE variable_name='mysql-long_query_time';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
(3)启用客户端地址追踪
sql
UPDATE global_variables SET variable_value='true' WHERE variable_name='mysql-query_digests_track_hostname';
LOAD MYSQL VARIABLES TO RUNTIME;
2. 告警阈值建议
| 监控项 | 建议阈值 | 告警含义 | 来源表 |
|---|---|---|---|
Client_Connections_aborted 增量 |
>100/分钟 | 客户端连接异常 | stats_mysql_global |
ConnPool_get_conn_failure 比例 |
>5% | 连接池不足或后端故障 | stats_mysql_global |
后端 Latency_us |
>10000 (10ms) | 网络或后端响应慢 | stats_mysql_connection_pool |
后端 status = SHUNNED |
任何 | 后端被临时屏蔽 | stats_mysql_connection_pool |
Slow_queries 增量 |
>10/分钟 | 存在慢查询 | stats_mysql_global |
Access_Denied_* 增量 |
>5/分钟 | 可能存在攻击或配置错误 | stats_mysql_global |
query_digest_memory |
>500MB | 查询摘要占用内存过高 | stats_memory_metrics |
MySQL_Monitor_*_ERR 增量 |
>0 | 健康检查失败 | stats_mysql_global |
3. 日常巡检 SQL 集合
sql
-- ============================================================
-- ProxySQL 2.6.5 每日巡检 SQL
-- ============================================================
-- 1. 系统概览
SELECT
MAX(CASE WHEN Variable_Name = 'ProxySQL_Uptime' THEN Variable_Value END) AS uptime_sec,
MAX(CASE WHEN Variable_Name = 'Client_Connections_connected' THEN Variable_Value END) AS frontend_conns,
MAX(CASE WHEN Variable_Name = 'Server_Connections_connected' THEN Variable_Value END) AS backend_conns,
MAX(CASE WHEN Variable_Name = 'Questions' THEN Variable_Value END) AS total_queries,
MAX(CASE WHEN Variable_Name = 'Slow_queries' THEN Variable_Value END) AS slow_queries
FROM stats.stats_mysql_global
WHERE Variable_Name IN ('ProxySQL_Uptime', 'Client_Connections_connected',
'Server_Connections_connected', 'Questions', 'Slow_queries');
-- 2. 进程状态分组
SELECT COALESCE(command, 'Unknown') AS state, COUNT(*) AS count
FROM stats.stats_mysql_processlist
GROUP BY command
ORDER BY count DESC;
-- 3. 长时间运行查询(超过 10 秒)
SELECT SessionID, user, db, time_ms, SUBSTR(info, 1, 200) AS query
FROM stats.stats_mysql_processlist
WHERE command != 'Sleep' AND time_ms > 10000
ORDER BY time_ms DESC;
-- 4. 当前事务列表
SELECT SessionID, user, db, time_ms,
JSON_EXTRACT(extended_info, '$.conn.autocommit') AS autocommit,
JSON_EXTRACT(extended_info, '$.conn.status.transaction') AS in_transaction
FROM stats.stats_mysql_processlist
WHERE JSON_EXTRACT(extended_info, '$.conn.status.transaction') = true;
-- 5. 连接负载分布(按用户)
SELECT user, COUNT(*) AS connections
FROM stats.stats_mysql_processlist
GROUP BY user
ORDER BY connections DESC;
-- 6. 后端服务器健康状态
SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnERR, Latency_us
FROM stats.stats_mysql_connection_pool
ORDER BY status DESC, Latency_us DESC;
-- 7. 慢查询统计 TOP 5
SELECT digest_text,
count_star AS exec_count,
ROUND(sum_time/1000000, 2) AS total_sec,
ROUND((sum_time/count_star)/1000, 2) AS avg_ms
FROM stats.stats_mysql_query_digest
WHERE count_star > 0
ORDER BY sum_time DESC
LIMIT 5;
-- 8. 错误统计 TOP 5
SELECT hostgroup, hostname, errno, count_star, last_error
FROM stats.stats_mysql_errors
ORDER BY count_star DESC
LIMIT 5;
-- 9. 连接池效率
SELECT
(SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='ConnPool_get_conn_success') AS pool_hits,
(SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='ConnPool_get_conn_failure') AS pool_misses,
ROUND(100 * (SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='ConnPool_get_conn_success') /
NULLIF((SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='ConnPool_get_conn_success') +
(SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='ConnPool_get_conn_failure'), 0), 2) AS hit_rate_pct;
-- 10. 内存使用概览
SELECT variable_name, variable_value
FROM stats.stats_memory_metrics
WHERE variable_name IN ('SQLite3_memory_bytes', 'query_digest_memory',
'jemalloc_active', 'stack_memory_mysql_threads');
六、常见问题(FAQ)
Q1: 查询 stats_mysql_query_digest 没有数据?
检查步骤:
-
确认有查询流量经过 ProxySQL
-
检查变量:
sqlSELECT variable_value FROM global_variables WHERE variable_name IN ('mysql-commands_stats', 'mysql-query_digests');两者都应为
true -
若刚启动,等待几秒让数据积累
Q2: stats_mysql_processlist 中的 time_ms 单位是什么?
答:毫秒(milliseconds)。
Q3: 如何 KILL 一个卡住的查询?
答 :先从 stats_mysql_processlist 获取 SessionID,然后执行:
sql
KILL CONNECTION <SessionID>;
Q4: stats_mysql_query_digest 中的 sum_time 单位是什么?
答:微秒(microseconds)。除以 1,000,000 得秒,除以 1,000 得毫秒。
Q5: 如何在不重启 ProxySQL 的情况下重置统计?
答 :使用各个 _reset 表:
sql
SELECT * FROM stats.stats_mysql_query_digest_reset;
SELECT * FROM stats.stats_mysql_connection_pool_reset;
SELECT * FROM stats.stats_mysql_errors_reset;
注意 :
stats_mysql_global没有_reset表,需要重启才能完全重置。
Q6: 慢查询统计中 hostgroup = -1 表示什么?
答:表示该查询是从查询缓存(Query Cache)中命中的,没有实际发送到后端服务器。
Q7: 2.6.5 版本中 stats_proxysql_global 和 stats_tls_certificates 表存在吗?
答 :不存在。这两个表是在 ProxySQL 3.0.7 版本中引入的。
Q8: ProxySQL 能否监控锁等待?
答:不能直接监控。ProxySQL 不提供锁等待信息(锁信息在后端 MySQL 中)。建议:
-
通过 ProxySQL 路由到后端 MySQL 查询
information_schema.INNODB_TRX -
或直接连接后端 MySQL 查看
SHOW ENGINE INNODB STATUS
Q9: 为什么 Com_backend_stmt_close 始终为 0?
答 :在当前实现中,ProxySQL 从不主动关闭预处理语句(关闭需要网络往返,效率低下)。当后端连接达到 mysql-max_stmts_per_connection 并归还到连接池被重置时,会隐式关闭所有预处理语句。
Q10: 如何查询 stats 库中的表?
答 :使用 SELECT * FROM stats.表名 的格式,例如:
sql
SELECT * FROM stats.stats_mysql_processlist;
七、MySQL 与 ProxySQL 监控对照表
| 监控目的 | MySQL 原生命令 | ProxySQL 2.6.5 等效命令 |
|---|---|---|
| 查看当前连接 | SHOW PROCESSLIST |
SELECT * FROM stats.stats_mysql_processlist |
| 按状态分组 | SELECT state,COUNT(*) FROM information_schema.processlist GROUP BY state |
SELECT command,COUNT(*) FROM stats.stats_mysql_processlist GROUP BY command |
| 慢查询数量 | SHOW GLOBAL STATUS LIKE 'Slow_queries' |
SELECT * FROM stats.stats_mysql_global WHERE variable_name='Slow_queries' |
| 连接数 | SHOW GLOBAL STATUS LIKE 'Threads_connected' |
SELECT * FROM stats.stats_mysql_global WHERE variable_name='Client_Connections_connected' |
| 查询计数器 | SHOW GLOBAL STATUS LIKE 'Questions' |
SELECT * FROM stats.stats_mysql_global WHERE variable_name='Questions' |
| 用户连接分布 | SELECT user,COUNT(*) FROM information_schema.processlist GROUP BY user |
SELECT user,COUNT(*) FROM stats.stats_mysql_processlist GROUP BY user |
| 运行时间最长查询 | SELECT * FROM information_schema.processlist ORDER BY time DESC |
SELECT * FROM stats.stats_mysql_processlist ORDER BY time_ms DESC |
| 后端延迟 | SHOW SLAVE STATUS 中的 Seconds_Behind_Master |
SELECT Latency_us FROM stats.stats_mysql_connection_pool |
| 全局状态 | SHOW GLOBAL STATUS |
SELECT * FROM stats.stats_mysql_global |
| 内存使用 | SHOW VARIABLES LIKE 'innodb_buffer_pool_size' |
SELECT * FROM stats.stats_memory_metrics |
八、总结
ProxySQL 2.6.5 的 stats 库提供了全面的 MySQL 流量监控能力:
| 监控需求 | 使用表 |
|---|---|
| 实时查询 | stats_mysql_processlist |
| 慢查询分析 | stats_mysql_query_digest |
| 命令类型分布 | stats_mysql_commands_counters |
| 全局指标 | stats_mysql_global |
| 连接池健康 | stats_mysql_connection_pool、stats_mysql_free_connections |
| 错误追踪 | stats_mysql_errors |
| 规则命中 | stats_mysql_query_rules |
| 用户连接限制 | stats_mysql_users |
| 内存监控 | stats_memory_metrics |
| GTID 一致性 | stats_mysql_gtid_executed |
| 预处理语句 | stats_mysql_prepared_statements_info |
建议将 [3. 日常巡检 SQL 集合](#3. 日常巡检 SQL 集合) 的 SQL 纳入自动化监控系统,以便及时发现和定位问题。