MySQL出现慢查询或者主从延迟的问题,怎么做根因分析?

针对 MySQL 的慢查询和主从延迟问题,进行根因分析可以遵循一套系统化的排查流程。这两个问题虽然表现不同,但根源常常交织在一起。

🐢 慢查询根因分析

慢查询通常是导致数据库整体性能下降和主从延迟的直接原因。排查的核心在于定位分析

1. 定位慢查询

首先,需要开启慢查询日志来捕获执行时间过长的 SQL 语句。

开启慢查询日志:可以通过修改配置文件或动态设置来开启。

sql 复制代码
-- 动态开启慢查询日志(无需重启)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 设置阈值为1秒,可根据业务调整
SET GLOBAL log_queries_not_using_indexes = 'ON'; -- 记录未使用索引的查询,非常有用
  • 分析慢查询日志 :原始的慢查询日志可能非常庞大,需要使用工具进行分析。
    • pt-query-digest (推荐) :Percona Toolkit 中的工具,功能强大,能生成详细的分析报告,按总耗时、执行频率等对 SQL 进行排序,快速定位最耗资源的 SQL。

      bash 复制代码
      pt-query-digest /path/to/mysql-slow.log > slow_report.txt
    • mysqldumpslow :MySQL 自带的工具,可以对慢查询日志进行汇总和排序。

      bash 复制代码
      mysqldumpslow -s t -t 10 /path/to/mysql-slow.log 
      # 按平均查询时间排序,取前10条
2. 分析根因

定位到具体的慢 SQL 后,下一步是分析它为什么慢。

  • 使用 EXPLAIN 分析执行计划 :这是最关键的一步。EXPLAIN 可以展示 MySQL 如何执行一条查询,帮助你判断是否存在全表扫描、索引使用不当等问题。

    sql 复制代码
    1EXPLAIN SELECT * FROM orders WHERE user_id = 1001 AND status = 'paid';
    • 关注重点
      • type:连接类型。ALL 表示全表扫描,性能最差;index 表示全索引扫描;range 表示索引范围扫描,是较好的结果。
      • key:实际使用的索引。如果为 NULL,则说明没有使用索引。
      • rows:MySQL 估计需要扫描的行数。数值越大,性能越差。
      • Extra:额外信息。Using filesort(需要额外排序)和 Using temporary(使用了临时表)通常意味着性能瓶颈。
  • 检查锁竞争:慢查询也可能是因为等待锁。可以通过以下命令查看当前的锁等待情况。

    sql 复制代码
    SELECT * FROM information_schema.innodb_lock_waits;

🔗 主从延迟根因分析

主从延迟的本质是从库重放事务的速度跟不上主库生成事务的速度。分析的关键在于判断延迟发生在哪个环节。

1. 确认延迟状态

使用 SHOW SLAVE STATUS\G 命令查看从库的复制状态,重点关注以下指标:

  • Seconds_Behind_Master:最直观的延迟秒数,但不够精确。
  • Master_Log_File / Read_Master_Log_Pos:从库的 I/O 线程已经读取到的主库 Binlog 文件和位置。
  • Relay_Master_Log_File / Exec_Master_Log_Pos:从库的 SQL 线程已经执行完的主库 Binlog 文件和位置。

通过对比 Read_Master_Log_PosExec_Master_Log_Pos,可以判断延迟的瓶颈:

  • 如果两者差距不大,但都落后于主库,问题可能出在网络传输或主库写入压力过大。
  • 如果 Read_Master_Log_Pos 远大于 Exec_Master_Log_Pos,说明 I/O 线程正常,但 SQL 线程执行过慢,这是最常见的情况。
2. 排查延迟根因

当确定是 SQL 线程执行过慢时,可以从以下几个方面深入排查:

排查方向 具体操作与说明
从库负载与资源 1. 检查系统负载 :使用 topiostat -x 1 等命令查看从库的 CPU、I/O 使用率。如果 %util 接近 100%,说明磁盘 I/O 是瓶颈。 2. 检查额外负载:确认从库是否承担了繁重的报表查询或备份任务,挤占了复制线程的资源。
SQL 线程执行情况 1. 检查中继日志堆积SHOW GLOBAL STATUS LIKE 'Relay_log_space'; 如果该值持续增长,说明中继日志在堆积,SQL 线程处理不过来。 2. 查看当前执行的 SQLSHOW PROCESSLIST; 查看 Command 列为 Slave_SQL 的线程正在执行什么 SQL,这通常就是导致延迟的慢查询。
主库写入压力 1. 大事务 :主库上的批量更新/删除、大表 DDL 操作会生成巨大的 Binlog 事件,从库需要很长时间才能重放。 2. 高并发写入:主库写入 QPS 过高,Binlog 生成速度远超从库处理能力。
复制配置 1. 检查并行复制 :执行 SHOW VARIABLES LIKE 'slave_parallel_workers';。如果值为 0 或 1,说明是单线程复制,在 MySQL 5.7+ 版本中应开启并行复制(如设置为 LOGICAL_CLOCK 模式)以提升性能。 2. 检查其他参数 :如 innodb_buffer_pool_size 是否过小,导致缓存命中率低。
相关推荐
2401_887724501 天前
CSS如何设置文字溢出显示省略号_利用text-overflowellipsis
jvm·数据库·python
m0_747854521 天前
golang如何实现应用启动耗时分析_golang应用启动耗时分析实现思路
jvm·数据库·python
雪碧聊技术1 天前
下午题_试题二
数据库
解救女汉子1 天前
如何截断SQL小数位数_使用TRUNCATE函数控制精度
jvm·数据库·python
2301_803875611 天前
如何用 objectStore.get 根据主键 ID 获取数据库单条数据
jvm·数据库·python
weixin_458580121 天前
如何修改AWR保留时间_将默认8天保留期延长至30天的设置
jvm·数据库·python
qq_654366981 天前
C#怎么实现OAuth2.0授权_C#如何对接第三方快捷登录【核心】
jvm·数据库·python
justjinji1 天前
如何用 CSS 变量配合 JS setProperty 实现动态换肤功能
jvm·数据库·python
2301_803875611 天前
C#怎么使用TopLevel顶级语句 C#顶级语句怎么写如何省略Main方法简化控制台程序【语法】
jvm·数据库·python
九皇叔叔1 天前
MySQL 8.0 测试库安装
数据库·mysql