MySQL为什么有时候会抖动一下?

一、InnoDB 刷脏页(最常见原因)

现象

  • 监控可见磁盘 I/O 突增,TPS 短暂下降。
  • SHOW ENGINE INNODB STATUSBUFFER POOL AND MEMORYModified db pages 值较高。

原因

  • 脏页积累:内存中的脏页(修改后未刷盘的数据页)积累到阈值(默认 75%),触发后台刷盘。
  • Redo Log 切换:Redo Log 写满切换时强制刷脏页(Checkpoint 机制)。

解决方案

  1. 调整刷盘速度

    ini 复制代码
    innodb_io_capacity = 2000        # 根据磁盘性能设置(SSD 建议 2000~20000)
    innodb_max_dirty_pages_pct = 60  # 降低脏页比例阈值
  2. 优化 Redo Log

    ini 复制代码
    innodb_log_file_size = 4G        # 增大 Redo Log 文件(减少切换频率)
    innodb_log_files_in_group = 3    # 增加日志文件数量
  3. 监控脏页状态

    sql 复制代码
    SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';

二、日志系统(Redo Log/Binlog)压力

现象

  • 事务提交延迟,SHOW PROCESSLIST 显示大量事务处于 query end 状态。
  • 监控显示磁盘写入延迟高。

原因

  • Redo Log 刷盘策略innodb_flush_log_at_trx_commit=1 时每次提交同步刷盘,I/O 压力大。
  • Binlog 刷盘策略sync_binlog=1 导致每次提交同步刷 Binlog。

解决方案

  1. 平衡一致性与性能

    ini 复制代码
    innodb_flush_log_at_trx_commit = 2  # 提交时写 OS 缓存,每秒刷盘(牺牲少量持久性)
    sync_binlog = 1000                  # 每 1000 次提交刷一次 Binlog
  2. 使用高性能磁盘:SSD 提升日志写入速度。


三、查询性能突增

现象

  • CPU 使用率或锁等待时间突增。
  • 慢查询日志中突然出现复杂查询。

原因

  • 低效 SQL 突然执行:全表扫描、未命中索引的查询。
  • 锁竞争加剧:热点行更新导致锁等待。

解决方案

  1. 捕获慢查询

    ini 复制代码
    slow_query_log = ON
    long_query_time = 0.5
  2. 优化 SQL

    • 添加缺失索引。
    • 重写复杂查询,避免全表扫描。
  3. 减少锁冲突

    • 使用 innodb_autoinc_lock_mode=2(交错自增锁)。
    • 缩短事务长度,尽快提交。

四、内存不足或 Swap 触发

现象

  • 内存使用率接近 100%,vmstat 显示 si/so(Swap 换入换出)值高。
  • SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_wait%' 显示等待次数。

原因

  • Buffer Pool 不足:频繁从磁盘加载数据页。
  • 系统内存竞争:其他进程占用内存,触发 Swap。

解决方案

  1. 扩大 Buffer Pool

    ini 复制代码
    innodb_buffer_pool_size = 系统内存的 70%~80%
  2. 禁用 Swap

    bash 复制代码
    sysctl vm.swappiness=0
  3. 优化内存分配

    ini 复制代码
    innodb_buffer_pool_instances = 8  # 减少锁争用

五、后台维护任务

现象

  • 定期出现性能波动(如每天凌晨)。
  • SHOW PROCESSLIST 显示 OPTIMIZE TABLEANALYZE TABLE

原因

  • 统计信息更新ANALYZE TABLE 导致临时资源消耗。
  • 表优化操作OPTIMIZE TABLE 重建表文件。

解决方案

  1. 调整维护计划

    • 在业务低峰期执行 OPTIMIZEANALYZE
  2. 启用持久化统计信息

    ini 复制代码
    innodb_stats_persistent = ON
    innodb_stats_auto_recalc = ON

六、硬件或系统层问题

现象

  • 磁盘延迟高(iostat -x 显示 await 值突增)。
  • 网络波动(如云服务器网络带宽突增)。

解决方案

  1. 监控硬件指标
    • 磁盘健康度(SMART 状态)。
    • 网络带宽使用情况。
  2. 升级硬件
    • 更换 SSD 提升 I/O 能力。
    • 增加内存避免 Swap。

七、诊断工具与命令

  1. 实时状态分析

    bash 复制代码
    # 查看系统资源
    top
    iostat -x 1
    vmstat 1
    
    # 查看 InnoDB 状态
    SHOW ENGINE INNODB STATUS\G
  2. 历史趋势分析

    • 使用 Prometheus + Grafana 监控 MySQL 和系统指标。
    • 开启 Performance Schema 记录历史查询。

总结:按优先级排查

  1. 检查刷脏页 → 调整 innodb_io_capacity 和 Redo Log 配置。
  2. 优化日志刷盘策略 → 平衡 innodb_flush_log_at_trx_commitsync_binlog
  3. 捕获慢查询 → 优化 SQL 和索引。
  4. 检查内存压力 → 扩大 Buffer Pool,禁用 Swap。
  5. 排查硬件问题 → 监控磁盘和网络。
相关推荐
拉不动的猪41 分钟前
# 关于初学者对于JS异步编程十大误区
前端·javascript·面试
熊猫钓鱼>_>3 小时前
Java面向对象核心面试技术考点深度解析
java·开发语言·面试·面向对象··class·oop
进击的野人5 小时前
CSS选择器与层叠机制
css·面试
T___T7 小时前
全方位解释 JavaScript 执行机制(从底层到实战)
前端·面试
9号达人7 小时前
普通公司对账系统的现实困境与解决方案
java·后端·面试
勤劳打代码8 小时前
条分缕析 —— 通过 Demo 深入浅出 Provider 原理
flutter·面试·dart
努力学算法的蒟蒻8 小时前
day10(11.7)——leetcode面试经典150
面试
进击的野人9 小时前
JavaScript 中的数组映射方法与面向对象特性深度解析
javascript·面试
南山安9 小时前
以腾讯面试题深度剖析JavaScript:从数组map方法到面向对象本质
javascript·面试
橘颂TA11 小时前
【剑斩OFFER】算法的暴力美学——二分查找
算法·leetcode·面试·职场和发展·c/c++