1. MySQL运维实战概述
MySQL作为最流行的开源关系型数据库之一,在企业级应用中扮演着关键角色。我在过去8年的DBA工作中发现,90%的生产环境问题都集中在20%的常见场景里。这篇文章将分享这些高频问题的诊断思路和解决方案,涵盖性能瓶颈、连接异常、数据一致性等核心痛点。
不同于官方文档的理论说明,这里的内容全部来自真实生产环境的案例总结。每个解决方案都经过至少3次以上实际验证,特别适合中小规模MySQL集群(1-10个节点)的运维场景。无论你是刚接触MySQL的新手,还是需要快速排查问题的开发人员,这些实战经验都能帮你节省大量试错时间。
2. 连接类问题排查
2.1 连接数耗尽(Too many connections)
上周刚处理过一个典型案例:某电商网站在大促时前端突然报"Can't connect to MySQL server",但数据库服务器CPU/内存都正常。这就是典型的连接数耗尽问题,通过以下步骤快速定位:
查看当前连接数上限:
SHOW VARIABLES LIKE 'max_connections';默认值151对于高并发场景往往不够
检查实际连接数:
SHOW STATUS LIKE 'Threads_connected';紧急处理(无需重启):
SET GLOBAL max_connections = 500;
重要提示:临时调整后务必修改my.cnf永久生效,否则重启后配置会丢失
深度优化建议:
- 使用连接池(如HikariCP)控制应用层连接
- 为不同业务设置专用账号,通过PROXY_USER限制单账号连接数
- 监控Threads_connected与max_connections比值,超过70%就要预警
2.2 连接超时(Wait timeout)
当出现"ERROR 3024 (HY000): Connection timeout"时,需要检查以下参数:
SHOW VARIABLES LIKE '%timeout%';重点关注三个参数:
- wait_timeout(非交互连接超时)
- interactive_timeout(交互连接超时)
- lock_wait_timeout(元数据锁超时)
典型误区和解决方案:
- 应用连接池中的连接因超时被服务器断开,但连接池不知情继续分配
- 解决方案:在连接池配置testOnBorrow/testWhileIdle
- 长事务导致超时:优化事务粒度,避免单个事务执行过久
3. 性能类问题排查
3.1 慢查询分析
慢查询是性能问题的首要嫌疑对象,按这个流程排查:
确认慢查询日志开启:
SHOW VARIABLES LIKE 'slow_query%';临时开启(生产环境慎用):
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1; -- 单位秒使用mysqldumpslow工具分析:
mysqldumpslow -s t /var/lib/mysql/mysql-slow.log
优化实战技巧:
- 对于JOIN操作,检查EXPLAIN中的type列,确保至少是range级别
- 警惕隐式类型转换:WHERE user_id = '123'(user_id是int时)
- 分页优化:避免LIMIT 10000,10,改用WHERE id > last_id LIMIT 10
3.2 CPU利用率飙升
当CPU持续高于80%时,按以下顺序排查:
查看当前活跃线程:
SHOW PROCESSLIST;识别高CPU查询:
SELECT * FROM sys.session WHERE cpu_time > 1000 ORDER BY cpu_time DESC;检查锁竞争:
SHOW ENGINE INNODB STATUS\G
典型案例:
- 全表扫描:添加缺失索引
- 排序操作:优化ORDER BY子句
- 锁等待:调整事务隔离级别或拆分热点行
4. 数据一致性问题
4.1 主从复制延迟
复制延迟(Seconds_Behind_Master)是MySQL复制架构的常见痛点。最近处理的一个案例中,从库延迟持续在2小时以上,通过以下步骤解决:
确认延迟原因:
SHOW SLAVE STATUS\G检查关键指标:
- IO线程状态
- SQL线程状态
- Last_IO_Error/Last_SQL_Error
优化方案对比表:
| 方案 | 适用场景 | 优缺点 |
|---|---|---|
| 调整sync_binlog | IO瓶颈 | 安全性vs性能权衡 |
| 启用并行复制 | 多核服务器 | 需5.7+版本 |
| 使用GTID | 复杂拓扑 | 简化故障转移 |
4.2 数据损坏修复
当遇到InnoDB表损坏时(报错Table is crashed),按这个流程恢复:
尝试自动修复:
REPAIR TABLE damaged_table;使用备份恢复:
mysqlbinlog /var/log/mysql/mysql-bin.000123 > recovery.sql终极方案(需停机):
innodb_force_recovery = 6 # 在my.cnf中设置
警告:innodb_force_recovery是最后手段,可能造成数据丢失
5. 存储空间问题
5.1 磁盘空间告急
当收到磁盘空间报警时,快速定位大表:
查看数据库大小:
SELECT table_schema, SUM(data_length)/1024/1024 AS size_mb FROM information_schema.tables GROUP BY table_schema;查找碎片化严重的表:
SELECT ENGINE, TABLE_NAME, DATA_FREE/1024/1024 AS free_mb FROM information_schema.tables WHERE DATA_FREE > 100*1024*1024;
清理策略:
- 归档历史数据:使用pt-archiver工具
- 在线收缩表空间:ALTER TABLE ... ENGINE=InnoDB
- 清理二进制日志:PURGE BINARY LOGS BEFORE '2023-01-01'
5.2 表空间膨胀
InnoDB的物理文件增长后不会自动收缩,需要特殊处理:
检查实际数据量:
SELECT COUNT(*) FROM large_table;重建表(在线操作):
ALTER TABLE large_table ENGINE=InnoDB;
注意事项:
- 确保有足够磁盘空间(需要额外临时空间)
- 大表操作建议在低峰期进行
- 考虑使用pt-online-schema-change减少锁时间
6. 监控与预防体系
6.1 关键指标监控
这些指标应该纳入你的监控系统:
性能指标:
- QPS/TPS
- 慢查询率
- 连接数使用率
资源指标:
- InnoDB缓冲池命中率
- 临时表创建数
- 行锁等待时间
推荐采集频率:
- 基础指标:15秒
- 慢查询统计:5分钟
- 全量状态变量:1小时
6.2 自动化巡检脚本
分享一个我日常使用的巡检脚本框架:
#!/bin/bash # 检查连接数 check_connections() { local used=$(mysql -e "SHOW STATUS LIKE 'Threads_connected'" | awk 'NR==2{print $2}') local max=$(mysql -e "SHOW VARIABLES LIKE 'max_connections'" | awk 'NR==2{print $2}') echo "连接数使用率: $((100*used/max))%" } # 检查复制状态 check_replication() { mysql -e "SHOW SLAVE STATUS\G" | grep -E 'Running|Behind' }把这个脚本加入cron,配合邮件报警就能建立基础防护网。根据我的经验,这套简单的监控能提前发现80%的潜在问题。