跳转至

监控Mysql

📌 Mysql监控配置

改配置文件后重启服务: systemctl restart mysqld

log_output = table  # 将慢查询日志保存到表中
slow_query_log = 1  # 开启慢查询
long_query_time = 1  # 慢查询超时时间为1秒
max_connections = 512  # 最大连接数,要求适中
innodb_print_all_deadlocks = ON  # 开启死锁日志记录
临时修改环境变量

在mysql里执行: set global max_connections=1000;

🚁 相关变量查询语句

# 查看数据库中与慢查询相关的变量
show variables like '%slow_query%';

# 长查询的执行时间阈值,超过该时间的查询被记录为慢查询
show variables like '%long_query%';

# 查询数据库中的最大连接数
show variables like '%max_connections%';

# 查询数据库中的连接数历史峰值
show variables like '%max_used_connections%';

📌 需要关注的指标

Current QPS - 每秒处理查询数

🚁 Connections

连接数;常见的连接池被打满的原因(按发生概率排列):

  1. 代码层的连接泄漏: 因代码缺陷或异常处理不当,未能正确将连接归还给连接池。如finally中无close(),异常导致事务未回滚且连接未释放;或流式处理未及时关闭。

    特征:系统刚重启时正常,随着运行时间推移,连接数呈线性上升,最终在某次业务高峰瞬间被打满。

  2. DB瓶颈: 慢SQL与长事务,持续占用连接。

  3. 僵尸连接: 未开启keepalive或检测间隔太长,遇到网络抖动或数据库重启时,连接池未能及时感知,导致僵尸连接占用名额。
  4. 配置不合理: 最大连接数太小。
  5. 瞬时流量: 极少数情况,在没有代码缺陷、SQL性能优良、网络正常的前提下,纯粹的流量暴增(如秒杀瞬间)导致并发请求数超过连接池容量。

    特征:流量回落后连接数迅速下降,且报错集中在峰值的那几秒钟,日常运行完全正常。

结合现象分析

现象特征 (池满) 核心原因 排查命令与工具 分析技巧与特别关注
高CPU + 低内存 计算密集型:复杂算法、死循环、频繁GC(GC线程也会消耗CPU) 1. thread -n 3:找出CPU占用最高的前N个线程。
2. trace:追踪热点方法调用栈,定位耗时方法。
3. profiler:生成CPU火焰图,看哪些方法占据了“平顶”。
特别关注:thread -n显示的是CPU时间占比,要结合nid(十六进制线程ID)与系统top -H -p命令对应。如果是GC线程高频,应用jvm命令查看GC详情。
高CPU + 高内存 STW(Stop-The-World) 或 内存泄漏:频繁Full GC导致业务线程暂停,CPU耗在GC上;或内存泄漏加剧GC压力 1. jvm:查看GC频率和耗时,确认是否频繁Full GC。
2. profiler:生成CPU火焰图,看“平顶”是否在GC相关方法(如G1YoungGen)。
3. heapdump:导出堆转储,用MAT分析泄漏对象。
特别关注:若CPU火焰图显示GC占用大量CPU,先解决内存泄漏问题;否则CPU和内存会互相恶化。
低CPU + 低内存 I/O或锁阻塞:线程等待数据库、RPC、文件IO、Redis等外部资源,或等待锁释放 1. thread -b:检测死锁和锁阻塞。
2. trace:追踪方法调用,查看耗时是否卡在外部调用上。
3. logger / ognl:动态调整日志级别,验证是否为同步日志输出导致的IO阻塞。
特别关注:查看dashboardWAITING/TIMED_WAITING状态的线程数。可以使用thread -n -1查看所有线程状态分布,快速定位大量阻塞线程。
低CPU + 高内存 死锁/阻塞导致的内存泄漏:线程因死锁或等待无限资源而停滞,未完成任务在队列中积压,任务对象占用内存 1. thread -b:首选命令,检测死锁或找出阻塞其他线程的锁持有者。
2. jvm:查看GC情况,确认内存增长是否因对象无法回收。
3. heapdump:导出堆转储,分析堆积的对象类型(通常是Runnable或任务对象)。
特别关注:thread -b输出为空时,考虑排查GC线程导致的假性阻塞(即STW)。使用jvm命令查看GC耗时,若远高于阈值,则内存问题由GC引发,而非死锁。

🔧 补充:通用排查思路

无论哪种场景,建议遵循以下顺序:

  1. dashboard -i 5000:全局观察线程、内存、GC的实时趋势。
  2. thread:根据CPU/状态筛选嫌疑线程。
  3. jvm:确认GC是否成为瓶颈。
  4. heapdump(内存高时)或 trace/watch(CPU高或阻塞时):深入定位代码级问题。

🚁 Slow Queries

Y轴是慢查询数量,需要设置慢查询阈值(如1秒),默认10秒。

慢查询超时时间常见范围:

系统类型 推荐阈值 说明
高并发 OLTP(如电商、支付) 0.1s ~ 0.3s 核心交易接口要求毫秒级响应,超过200ms的SQL即需优化
一般业务系统(如后台管理) 0.5s ~ 1s 用户可接受秒内响应,1秒是常见警戒线
报表/分析类(OLAP) 1s ~ 3s 或更高 复杂查询允许更长时间,但需结合业务容忍度

🔧 慢查询的分析方法

1.定位:取执行时间大于阈值的sql,找扫描行数多,或扫描行数远大于返回行数的sql

SELECT START_TIME, USER_HOST, QUERY_TIME, LOCK_TIME, DB, SQL_TEXT
FROM MYSQL.SLOW_LOG
ORDER BY START_TIME DESC LIMIT 10;

2.分析:explain sql看执行计划,关注字段

  • type,all、index需要优化,最好是range或ref
  • extra,出现文件排序或使用临时表需优化
  • rows,预扫行数,越大说明索引过滤差
  • filter,数值说低说明索引选取可能不对,回表代价大

注:适用于Mysql, Tidb,pg的执行计划无以上字段,而是以树形结构展示。

3.根因

  • 索引失效,如模糊匹配、函数运算
  • 统计信息失效
  • 深度分页,如limit 100000, 10(跳过前10万行取10条记录,应改成where条件过滤where id > {id} order by id limit 10

回表

首先,数据挂在聚簇索引的叶子节点

  • 未覆盖索引时,根据查询条件拿到id,再回到聚簇索引随机io(这里就是回表),以id匹配数据行。
  • 覆盖索引时,理想情况在叶子节点拿到匹配记录,无回表操作。

4.如何优化:

  • 添加合适的索引,避免SELECT *
  • 拆分复杂查询,持续监控并优化慢SQL
  • 定期执行ANALYZE TABLE,更新统计信息帮助优化器选择更优执行计划

🚁 Table Locks

表级锁,控制并发访问的机制,防止同时对一个表进行读写。

包含以下指标:

  • Table_locks_immediate
    表示一个线程请求表锁时,立即获得锁的次数。即:无需等待,直接加锁成功。

  • Table_locks_waited
    表示一个线程请求表锁时,需要等待其他线程释放锁的次数。即:发生锁竞争,出现阻塞。

理想状态下,Table_locks_immediate 应远大于 Table_locks_waited

若后者持续增长,说明存在较多锁竞争,可能影响并发性能。

优化建议

  • 优先使用InnoDB存储引擎: 支持行级锁,大幅减少锁冲突。
  • 优化慢查询、添加合适索引。
  • 尽量避免长事务,及时提交事务以释放锁资源。
  • 设置报警规则,当Table_locks_waited突增时及时通知。

🔧 锁竞争

激烈锁竞争会导致线程阻塞,间接导致线程池资源耗尽,表现为系统响应慢。

可能造成锁竞争的原因:

  1. 代码层面: 锁粒度太大,如为保护某个共享变量而锁住大方法或类
  2. 数据库层面: 写语句缺索引,导致锁升级为大量行锁甚至全表锁
  3. 大事务: 大量sql+非db操作,其中某个环节慢导致锁升级
  4. 热点行竞争: 如秒杀场景多个订单并发操作同一商品
如何优化锁竞争

锁竞争的本质: 执行慢 + 热点竞争,因此解决思路包括减少冲突(拆分热点、异步化)、加快冲突解决(索引优化、缩小事务、缩短锁持续时间)

针对代码

  • 缩小锁粒度,只锁需要保护的最小代码块
  • 使用无锁、原子性质的数据结构如AtomicInteger
  • 避免锁内IO,减少锁占用时间
  • 固定锁获取顺序,防止死锁

针对DB

  • 确保索引有效
  • 拆分大事务,尽快提交以释放锁
  • 优化热点行:使用异步扣减或队列(如redis lua脚本预扣减,再异步同步至db)
  • 使用乐观锁(版本号机制)代替悲观锁(for update),失败则重试

🔧 死锁

死锁,同样分为代码/DB层面,具体原因如事务A锁表1等表2,事务B锁表2等表1,互相等对方释放锁。

发生死锁时,内存不释放,大量死锁线程积压后,会耗尽内存触发OOM。

大量死锁时的表现

  • 指标: CPU使用率不高,内存占用持续增长。
  • 业务: 事务无法提交或回滚,破坏数据一致性,服务无响应。