Skip to content

MySQL 状态查看故障诊断

状态查看是 MySQL 数据库运维中最基础、最重要的技能之一,它能够帮助 DBA 实时了解数据库的运行状态,快速定位和解决问题。本文将详细介绍 MySQL 状态查看的常用命令、重要指标分析、常见问题诊断和最佳实践,帮助 DBA 掌握状态查看的技能,有效诊断和解决数据库故障,兼顾不同 MySQL 版本的特性差异,贴合实际生产运维场景。

状态查看概述

什么是状态查看

状态查看是指通过 MySQL 提供的命令和工具,获取数据库运行时的各种状态信息,包括连接状态、查询状态、缓存状态、锁状态、复制状态等。

状态查看的重要性

  • 实时监控:实时了解数据库的运行状态
  • 故障诊断:快速定位和解决数据库问题
  • 性能优化:识别性能瓶颈,优化数据库性能
  • 容量规划:预测数据库资源需求
  • 安全监控:检测异常活动和安全威胁
  • 合规审计:提供数据库运行的审计证据

状态查看的常见场景

  • 日常监控:定期查看数据库状态,确保正常运行
  • 故障排查:当数据库出现问题时,查看状态信息定位原因
  • 性能优化:分析状态指标,识别性能瓶颈
  • 容量规划:根据状态指标预测资源需求
  • 变更验证:在数据库变更后,验证状态是否正常

MySQL 状态查看命令

SHOW STATUS 命令

作用:显示 MySQL 服务器的状态信息

语法

sql
SHOW STATUS [LIKE 'pattern'];
SHOW GLOBAL STATUS [LIKE 'pattern'];
SHOW SESSION STATUS [LIKE 'pattern'];

示例

sql
-- 查看所有状态指标
SHOW STATUS;

-- 查看全局状态指标
SHOW GLOBAL STATUS;

-- 查看连接相关状态指标
SHOW GLOBAL STATUS LIKE 'Threads_%';

-- 查看查询相关状态指标
SHOW GLOBAL STATUS LIKE 'Questions';
SHOW GLOBAL STATUS LIKE 'Queries';

-- 查看缓存相关状态指标
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%';

-- 查看锁相关状态指标
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_%';

SHOW VARIABLES 命令

作用:显示 MySQL 服务器的配置参数

语法

sql
SHOW VARIABLES [LIKE 'pattern'];
SHOW GLOBAL VARIABLES [LIKE 'pattern'];
SHOW SESSION VARIABLES [LIKE 'pattern'];

示例

sql
-- 查看所有配置参数
SHOW VARIABLES;

-- 查看全局配置参数
SHOW GLOBAL VARIABLES;

-- 查看连接相关配置参数
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL VARIABLES LIKE 'wait_timeout';

-- 查看缓存相关配置参数
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL VARIABLES LIKE 'key_buffer_size';

-- 查看日志相关配置参数
SHOW GLOBAL VARIABLES LIKE 'log_%';

SHOW PROCESSLIST 命令

作用:显示当前 MySQL 服务器的线程列表

语法

sql
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;

示例

sql
-- 查看当前线程列表
SHOW PROCESSLIST;

-- 查看完整的线程列表(包括完整的 SQL 语句)
SHOW FULL PROCESSLIST;

-- 使用 WHERE 子句过滤
SELECT * FROM information_schema.processlist WHERE Command != 'Sleep' AND Time > 10;

SHOW ENGINE INNODB STATUS 命令

作用:显示 InnoDB 引擎的详细状态信息

语法

sql
SHOW ENGINE INNODB STATUS [G];

示例

sql
-- 查看 InnoDB 状态信息
SHOW ENGINE INNODB STATUS\G;

主要内容

  • 事务信息
  • 锁信息
  • 缓冲池信息
  • 日志信息
  • 线程信息
  • 死锁信息

SHOW SLAVE STATUS 命令

作用:显示主从复制的状态信息

语法

sql
SHOW SLAVE STATUS [G];

示例

sql
-- 查看主从复制状态
SHOW SLAVE STATUS\G;

主要内容

  • 复制线程状态
  • 复制延迟
  • 二进制日志位置
  • 中继日志位置
  • 复制错误信息

其他常用命令

SHOW TABLE STATUS 命令

sql
-- 查看表状态
SHOW TABLE STATUS LIKE 'orders';
SHOW TABLE STATUS FROM mydb;

SHOW INDEX 命令

sql
-- 查看表的索引信息
SHOW INDEX FROM orders;

SHOW CREATE TABLE 命令

sql
-- 查看表的创建语句
SHOW CREATE TABLE orders;

SHOW GRANTS 命令

sql
-- 查看用户权限
SHOW GRANTS FOR 'root'@'localhost';

SELECT 命令查询系统表

sql
-- 从 information_schema 中查询信息
SELECT * FROM information_schema.tables WHERE table_schema = 'mydb';
SELECT * FROM information_schema.columns WHERE table_name = 'orders';

-- 从 performance_schema 中查询信息
SELECT * FROM performance_schema.threads WHERE processlist_user IS NOT NULL;
SELECT * FROM performance_schema.events_statements_summary_by_digest ORDER BY sum_timer_wait DESC LIMIT 10;

-- 从 sys 架构中查询信息
SELECT * FROM sys.innodb_lock_waits;
SELECT * FROM sys.statements_with_runtimes_in_95th_percentile;

版本差异与特性

MySQL 5.6

  • 状态命令:基础的 SHOW STATUS 和 SHOW VARIABLES 命令
  • Performance Schema:有限的性能监控功能,默认未启用
  • Sys Schema:不支持
  • InnoDB 状态:基础的 InnoDB 状态信息
  • 复制状态:基础的 SHOW SLAVE STATUS 信息

MySQL 5.7

  • 状态命令:增强的 SHOW STATUS 命令,包含更多指标
  • Performance Schema:增强的性能监控功能,默认启用
  • Sys Schema:引入 Sys Schema,提供更易用的监控视图
  • InnoDB 状态:增强的 InnoDB 状态信息,包含更多细节
  • 复制状态:增强的 SHOW SLAVE STATUS 信息,包含更多指标
  • 并行复制:支持基于数据库的并行复制

MySQL 8.0

  • 状态命令:进一步增强的 SHOW STATUS 命令
  • Performance Schema:进一步增强的性能监控功能,包含更多指标
  • Sys Schema:增强的 Sys Schema,提供更多监控视图
  • InnoDB 状态:增强的 InnoDB 状态信息,包含更多细节
  • 复制状态:增强的 SHOW SLAVE STATUS 信息,包含更多指标
  • 并行复制:支持基于写集的并行复制,性能更高
  • JSON 格式:支持 JSON 格式的状态信息输出

重要状态指标分析

连接状态指标

指标名称说明正常范围异常情况
Threads_connected当前连接数取决于 max_connections 设置,通常低于 max_connections 的 80%接近或超过 max_connections,可能导致连接失败
Threads_running当前运行中的线程数通常低于 CPU 核心数的 2-4 倍过高可能导致 CPU 使用率过高
Threads_created已创建的线程数较低,取决于 thread_cache_size 设置过高可能说明 thread_cache_size 配置不合理
Connections尝试连接的次数取决于业务量突然增加可能是异常连接尝试
Aborted_connects失败的连接尝试次数较低过高可能是认证失败或网络问题
Max_used_connections历史最大连接数低于 max_connections接近或超过 max_connections,需要调整配置

示例

sql
SHOW GLOBAL STATUS LIKE 'Threads_%';
SHOW GLOBAL STATUS LIKE 'Connections';
SHOW GLOBAL STATUS LIKE 'Aborted_connects';

查询状态指标

指标名称说明正常范围异常情况
Questions客户端执行的查询次数取决于业务量突然增加或减少可能是业务异常
Queries服务器执行的查询次数(包括内部查询)通常大于 Questions过高可能导致服务器负载过高
Slow_queries慢查询次数较低过高说明存在性能问题
Select_scan全表扫描次数较低过高说明缺少索引或索引使用不当
Select_full_join没有使用索引的连接次数0 或较低过高说明连接查询缺少索引
Sort_scan没有使用索引的排序次数较低过高说明排序操作缺少索引
Sort_merge_passes排序合并次数较低过高说明需要调整 sort_buffer_size

示例

sql
SHOW GLOBAL STATUS LIKE 'Questions';
SHOW GLOBAL STATUS LIKE 'Queries';
SHOW GLOBAL STATUS LIKE 'Slow_queries';
SHOW GLOBAL STATUS LIKE 'Select_scan';
SHOW GLOBAL STATUS LIKE 'Sort_scan';

缓存状态指标

指标名称说明正常范围异常情况
Innodb_buffer_pool_read_requestsInnoDB 缓冲池读取请求次数较高正常,说明缓冲池有效
Innodb_buffer_pool_reads从磁盘读取数据的次数较低过高说明缓冲池不足或命中率低
Innodb_buffer_pool_read_hit_rate缓冲池命中率高于 95%低于 90% 说明缓冲池配置不合理
Key_read_requests索引缓冲读取请求次数较高正常,说明索引缓冲有效
Key_reads从磁盘读取索引的次数较低过高说明 key_buffer_size 配置不足
Key_read_hit_rate索引缓冲命中率高于 95%低于 90% 说明 key_buffer_size 配置不合理
Qcache_hits查询缓存命中次数较高(如果启用了查询缓存)较低说明查询缓存配置不合理或不适合使用查询缓存
Qcache_inserts查询缓存插入次数较低(如果启用了查询缓存)过高说明查询缓存失效频繁

示例

sql
-- 计算 InnoDB 缓冲池命中率
SELECT 
  (1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)) * 100 AS innodb_buffer_pool_hit_rate
FROM information_schema.global_status;

-- 计算索引缓冲命中率
SELECT 
  (1 - (Key_reads / Key_read_requests)) * 100 AS key_buffer_hit_rate
FROM information_schema.global_status;

锁状态指标

指标名称说明正常范围异常情况
Innodb_row_lock_current_waits当前等待行锁的数量0 或较低过高说明存在锁竞争
Innodb_row_lock_waits行锁等待总次数较低过高说明锁竞争频繁
Innodb_row_lock_time行锁等待总时间(毫秒)较低过高说明锁等待时间长
Innodb_row_lock_time_avg平均行锁等待时间(毫秒)较低过高说明锁竞争严重
Innodb_row_lock_time_max最大行锁等待时间(毫秒)较低过高说明存在长时间锁等待
Table_locks_immediate立即获取表锁的次数较高正常,说明表锁竞争不严重
Table_locks_waited等待表锁的次数0 或较低过高说明表锁竞争严重

示例

sql
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_%';
SHOW GLOBAL STATUS LIKE 'Table_locks_%';

复制状态指标

指标名称说明正常范围异常情况
Slave_running从库复制状态ONOFF 说明复制停止
Seconds_Behind_Master从库延迟秒数0 或较低过高说明复制延迟严重
Slave_retried_transactions重试的事务次数0 或较低过高说明复制不稳定
Slave_last_heartbeat上次心跳时间最近时间长时间没有心跳说明复制可能中断

示例

sql
-- 查看复制状态
SHOW SLAVE STATUS\G;

-- 从 performance_schema 中查询复制状态
SELECT * FROM performance_schema.replication_applier_status_by_worker;
SELECT * FROM performance_schema.replication_connection_status;

InnoDB 状态指标

指标名称说明正常范围异常情况
Innodb_buffer_pool_pages_total缓冲池总页数取决于 innodb_buffer_pool_size 设置过大可能导致内存不足
Innodb_buffer_pool_pages_free缓冲池空闲页数适当比例,通常 5%-10%过多说明缓冲池过大,过少说明缓冲池不足
Innodb_data_reads数据读取次数取决于业务量过高可能说明 I/O 瓶颈
Innodb_data_writes数据写入次数取决于业务量过高可能说明 I/O 瓶颈
Innodb_data_fsyncsfsync 操作次数取决于 innodb_flush_log_at_trx_commit 和 sync_binlog 设置过高可能说明 I/O 瓶颈
Innodb_log_waits等待日志缓冲区空间的次数0 或较低过高说明 innodb_log_buffer_size 配置不足
Innodb_os_log_written写入重做日志的字节数取决于业务量过高可能说明 I/O 瓶颈

示例

sql
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_%';
SHOW GLOBAL STATUS LIKE 'Innodb_data_%';
SHOW GLOBAL STATUS LIKE 'Innodb_log_%';

常见问题的状态诊断

连接问题诊断

问题现象:客户端无法连接到 MySQL 服务器

诊断步骤

  1. 查看连接相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Threads_connected';
    SHOW GLOBAL STATUS LIKE 'Max_used_connections';
    SHOW GLOBAL VARIABLES LIKE 'max_connections';
    SHOW GLOBAL STATUS LIKE 'Aborted_connects';
  2. 查看当前连接情况
    sql
    SHOW PROCESSLIST;
  3. 检查防火墙配置
    bash
    firewall-cmd --list-ports
  4. 检查 MySQL 监听地址
    sql
    SHOW GLOBAL VARIABLES LIKE 'bind_address';

解决方案

  • 如果连接数达到 max_connections,增加 max_connections 配置
  • 如果存在大量空闲连接,调整 wait_timeout 配置
  • 如果 Aborted_connects 过高,检查认证和网络配置

性能下降诊断

问题现象:数据库响应缓慢,查询执行时间长

诊断步骤

  1. 查看查询相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Slow_queries';
    SHOW GLOBAL STATUS LIKE 'Select_scan';
    SHOW GLOBAL STATUS LIKE 'Sort_scan';
  2. 查看慢查询日志
    bash
    pt-query-digest /var/lib/mysql/slow.log > slow_report.txt
  3. 查看当前运行的查询
    sql
    SHOW FULL PROCESSLIST;
  4. 查看 InnoDB 状态
    sql
    SHOW ENGINE INNODB STATUS\G;
  5. 查看服务器负载
    bash
    top
    iostat -x 1
    vmstat 1

解决方案

  • 优化慢查询,添加必要的索引
  • 调整 MySQL 配置,如 innodb_buffer_pool_size、sort_buffer_size 等
  • 提升服务器硬件配置,如 CPU、内存、磁盘

锁问题诊断

问题现象:查询执行时间长,事务等待时间长

诊断步骤

  1. 查看锁相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_%';
    SHOW GLOBAL STATUS LIKE 'Table_locks_%';
  2. 查看当前锁等待情况
    sql
    SELECT * FROM sys.innodb_lock_waits;
    SELECT * FROM performance_schema.data_lock_waits;
  3. 查看 InnoDB 状态中的锁信息
    sql
    SHOW ENGINE INNODB STATUS\G;
  4. 查看当前事务
    sql
    SELECT * FROM information_schema.innodb_trx;

解决方案

  • 优化事务设计,保持事务短小
  • 优化查询,减少锁的持有时间
  • 调整隔离级别
  • 优化索引,减少锁的范围

复制问题诊断

问题现象:主从复制延迟或失败

诊断步骤

  1. 查看复制状态
    sql
    SHOW SLAVE STATUS\G;
  2. 查看复制相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Slave_%';
  3. 查看从库错误日志
    bash
    grep -i "slave" /var/log/mysql/error.log
  4. 查看性能_schema 中的复制信息
    sql
    SELECT * FROM performance_schema.replication_applier_status_by_worker;
    SELECT * FROM performance_schema.replication_connection_status;

解决方案

  • 如果复制停止,修复错误后重启复制
  • 如果复制延迟,调整从库配置,如增加 slave_parallel_workers
  • 如果存在复制错误,根据错误信息修复

内存问题诊断

问题现象:服务器内存使用率高,MySQL 服务可能崩溃

诊断步骤

  1. 查看内存相关配置
    sql
    SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
    SHOW GLOBAL VARIABLES LIKE 'key_buffer_size';
    SHOW GLOBAL VARIABLES LIKE 'query_cache_size';
    SHOW GLOBAL VARIABLES LIKE 'sort_buffer_size';
    SHOW GLOBAL VARIABLES LIKE 'read_buffer_size';
    SHOW GLOBAL VARIABLES LIKE 'read_rnd_buffer_size';
  2. 查看 InnoDB 缓冲池状态
    sql
    SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_%';
  3. 查看服务器内存使用情况
    bash
    free -h
    top
  4. 查看错误日志中的内存相关错误
    bash
    grep -i "memory" /var/log/mysql/error.log
    grep -i "buffer pool" /var/log/mysql/error.log

解决方案

  • 调整内存配置,避免超过服务器物理内存
  • 优化查询,减少内存使用
  • 增加服务器内存

I/O 问题诊断

问题现象:磁盘 I/O 使用率高,查询执行时间长

诊断步骤

  1. 查看 I/O 相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Innodb_data_%';
    SHOW GLOBAL STATUS LIKE 'Innodb_os_log_%';
  2. 查看服务器 I/O 使用情况
    bash
    iostat -x 1
    iotop
  3. 查看 InnoDB I/O 配置
    sql
    SHOW GLOBAL VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
    SHOW GLOBAL VARIABLES LIKE 'sync_binlog';
    SHOW GLOBAL VARIABLES LIKE 'innodb_io_capacity';
    SHOW GLOBAL VARIABLES LIKE 'innodb_io_capacity_max';
  4. 查看慢查询日志,找出 I/O 密集型查询
    bash
    pt-query-digest /var/lib/mysql/slow.log | grep -i "io"

解决方案

  • 调整 I/O 相关配置,如 innodb_flush_log_at_trx_commit、sync_binlog
  • 优化 I/O 密集型查询
  • 使用 SSD 硬盘,提高 I/O 性能
  • 调整 innodb_io_capacity 和 innodb_io_capacity_max 配置

状态查看的最佳实践

定期查看状态

  • 日常检查:每天查看一次关键状态指标
  • 峰值检查:在业务高峰期增加检查频率
  • 变更后检查:在数据库变更后立即查看状态
  • 故障后检查:在故障发生后详细检查状态

建立状态基线

  • 收集正常状态数据:在系统正常运行时,收集状态指标作为基线
  • 定期更新基线:随着业务增长和系统变更,定期更新基线
  • 对比异常状态:当系统出现问题时,与基线对比,找出异常指标

使用监控工具

  • 内置监控工具:Performance Schema、Sys Schema
  • 第三方监控工具
    • Prometheus + Grafana:提供丰富的监控指标和可视化仪表盘
    • Zabbix:通过插件监控 MySQL 状态
    • Nagios:通过插件监控 MySQL 状态
    • MySQL Enterprise Monitor:企业级监控解决方案

结合日志分析

  • 结合错误日志:状态查看与错误日志分析相结合,更全面地诊断问题
  • 结合慢查询日志:状态指标与慢查询日志相结合,定位性能问题
  • 结合二进制日志:状态指标与二进制日志相结合,分析数据变更

自动化状态检查

  1. 编写脚本:编写 Shell 或 Python 脚本,定期检查状态指标
  2. 配置 cron 任务:使用 cron 定期执行状态检查脚本
  3. 发送告警:当状态指标异常时,发送告警通知
  4. 生成报告:定期生成状态报告,便于分析和优化

自动化状态检查脚本示例

bash
#!/bin/bash

# MySQL 状态自动检查脚本

MYSQL_HOST="localhost"
MYSQL_USER="root"
MYSQL_PASS="password"
LOG_FILE="/var/log/mysql/status_check.log"
DATE=$(date +"%Y-%m-%d %H:%M:%S")

# 初始化日志
echo "[$DATE] MySQL 状态检查开始" >> $LOG_FILE

# 检查连接状态
CONNECTIONS=$(mysql -u $MYSQL_USER -p$MYSQL_PASS -h $MYSQL_HOST -e "SHOW GLOBAL STATUS LIKE 'Threads_connected';" | grep -v Variable_name | awk '{print $2}')
MAX_CONNECTIONS=$(mysql -u $MYSQL_USER -p$MYSQL_PASS -h $MYSQL_HOST -e "SHOW GLOBAL VARIABLES LIKE 'max_connections';" | grep -v Variable_name | awk '{print $2}')

# 检查慢查询
SLOW_QUERIES=$(mysql -u $MYSQL_USER -p$MYSQL_PASS -h $MYSQL_HOST -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';" | grep -v Variable_name | awk '{print $2}')

# 检查锁等待
LOCK_WAITS=$(mysql -u $MYSQL_USER -p$MYSQL_PASS -h $MYSQL_HOST -e "SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';" | grep -v Variable_name | awk '{print $2}')

# 记录检查结果
echo "[$DATE] 连接数: $CONNECTIONS/$MAX_CONNECTIONS, 慢查询数: $SLOW_QUERIES, 锁等待数: $LOCK_WAITS" >> $LOG_FILE

# 检查是否需要告警
if [ $CONNECTIONS -gt $((MAX_CONNECTIONS * 80 / 100)) ]; then
    echo "[$DATE] 连接数过高,需要告警" >> $LOG_FILE
    # 发送告警邮件(示例)
    # echo "MySQL 连接数过高: $CONNECTIONS/$MAX_CONNECTIONS" | mail -s "MySQL 告警" admin@example.com
fi

if [ $SLOW_QUERIES -gt 100 ]; then
    echo "[$DATE] 慢查询数过高,需要告警" >> $LOG_FILE
    # 发送告警邮件(示例)
    # echo "MySQL 慢查询数过高: $SLOW_QUERIES" | mail -s "MySQL 告警" admin@example.com
fi

if [ $LOCK_WAITS -gt 50 ]; then
    echo "[$DATE] 锁等待数过高,需要告警" >> $LOG_FILE
    # 发送告警邮件(示例)
    # echo "MySQL 锁等待数过高: $LOCK_WAITS" | mail -s "MySQL 告警" admin@example.com
fi

echo "[$DATE] MySQL 状态检查结束" >> $LOG_FILE
echo "=====================================" >> $LOG_FILE

状态指标告警

  • 设置合理的告警阈值:根据基线数据设置告警阈值
  • 配置多级告警:根据严重程度设置不同级别的告警
  • 选择合适的告警方式:邮件、短信、微信等
  • 建立告警处理流程:明确告警的处理步骤和责任人

案例分析

连接数过高诊断

问题描述:客户端无法连接到 MySQL 服务器,报错 "Too many connections"

诊断步骤

  1. 查看连接相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Threads_connected';
    -- 结果:Threads_connected = 1000
    
    SHOW GLOBAL VARIABLES LIKE 'max_connections';
    -- 结果:max_connections = 1000
    
    SHOW GLOBAL STATUS LIKE 'Max_used_connections';
    -- 结果:Max_used_connections = 1000
  2. 查看当前连接情况
    sql
    SHOW PROCESSLIST;
    -- 发现大量空闲连接,Command = 'Sleep',Time > 3600

解决方案

  1. 临时增加 max_connections 配置
    sql
    SET GLOBAL max_connections = 2000;
  2. 调整 wait_timeout 配置,减少空闲连接
    sql
    SET GLOBAL wait_timeout = 300;
    SET GLOBAL interactive_timeout = 300;
  3. 在配置文件中永久生效
    ini
    [mysqld]
    max_connections = 2000
    wait_timeout = 300
    interactive_timeout = 300

优化效果

  • 连接数恢复正常,客户端可以正常连接
  • 空闲连接自动回收,减少资源占用

性能下降诊断

问题描述:数据库响应缓慢,查询执行时间从 0.1 秒增加到 5 秒

诊断步骤

  1. 查看查询相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Slow_queries';
    -- 结果:Slow_queries = 1000(过去 24 小时)
    
    SHOW GLOBAL STATUS LIKE 'Select_scan';
    -- 结果:Select_scan = 5000(过去 24 小时)
  2. 分析慢查询日志
    bash
    pt-query-digest /var/lib/mysql/slow.log > slow_report.txt
    -- 发现大量全表扫描查询,主要是 orders 表的查询
  3. 查看 orders 表的索引
    sql
    SHOW INDEX FROM orders;
    -- 结果:只有主键索引,没有为 customer_id 和 order_date 添加索引
  4. 分析查询执行计划
    sql
    EXPLAIN SELECT * FROM orders WHERE customer_id = 1000 AND order_date > '2023-01-01';
    -- 结果:type = ALL(全表扫描)

解决方案

  1. 为 orders 表添加复合索引
    sql
    CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);
  2. 再次分析执行计划
    sql
    EXPLAIN SELECT * FROM orders WHERE customer_id = 1000 AND order_date > '2023-01-01';
    -- 结果:type = range(范围扫描)
  3. 监控慢查询日志,确认该查询不再被记录

优化效果

  • 查询执行时间从 5 秒降低到 0.1 秒
  • 慢查询数量显著减少
  • 数据库响应速度恢复正常

死锁诊断

问题描述:应用程序收到 "Deadlock found when trying to get lock; try restarting transaction" 错误

诊断步骤

  1. 查看锁相关状态指标
    sql
    SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';
    -- 结果:Innodb_row_lock_waits = 50(过去 1 小时)
    
    SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_time_avg';
    -- 结果:Innodb_row_lock_time_avg = 1000(毫秒)
  2. 查看 InnoDB 状态中的死锁信息
    sql
    SHOW ENGINE INNODB STATUS\G;
    -- 发现死锁信息,两个事务互相等待对方的锁
  3. 分析死锁产生的 SQL 语句
    sql
    -- 死锁中的事务 1:
    UPDATE orders SET status = 'paid' WHERE id = 1;
    UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 1;
    
    -- 死锁中的事务 2:
    UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 1;
    UPDATE orders SET status = 'paid' WHERE id = 1;

解决方案

  1. 优化事务设计,保持事务访问顺序一致
    sql
    -- 所有事务都先更新 orders 表,再更新 inventory 表
    UPDATE orders SET status = 'paid' WHERE id = 1;
    UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 1;
  2. 调整事务隔离级别
    sql
    SET GLOBAL transaction_isolation = 'READ-COMMITTED';
  3. 优化索引,减少锁的范围

优化效果

  • 死锁发生率显著降低
  • 应用程序不再收到死锁错误
  • 事务执行时间缩短

总结

状态查看是 MySQL 数据库运维中最基础、最重要的技能之一,它能够帮助 DBA 实时了解数据库的运行状态,快速定位和解决问题。通过本文的介绍,DBA 可以掌握 MySQL 状态查看的常用命令、重要指标分析、常见问题诊断和最佳实践,有效诊断和解决数据库故障。

在实际运维中,DBA 应该:

  • 定期查看状态:建立日常状态检查的习惯
  • 掌握重要指标:熟悉关键状态指标的含义和正常范围
  • 结合日志分析:将状态查看与日志分析相结合,更全面地诊断问题
  • 使用监控工具:利用监控工具自动化状态检查和告警
  • 建立基线数据:收集正常状态数据,作为异常判断的依据
  • 自动化状态检查:编写脚本,自动化状态检查和告警
  • 持续优化:根据状态分析结果,持续优化数据库配置和查询
  • 关注版本差异:根据 MySQL 版本选择合适的状态查看方法和指标

通过不断学习和实践,DBA 可以提高状态查看和故障诊断的能力,确保数据库系统的高可用性和可靠性。