MySQL卡死排查与安全重启最佳实践
1. MySQL卡死时盲目重启的风险当MySQL服务突然卡死时很多初级DBA的第一反应是立即重启服务。这种条件反射式的操作实际上隐藏着巨大风险。我曾处理过一个电商平台的案例他们在促销活动期间遇到MySQL卡死后直接重启导致订单表的InnoDB引擎损坏最终丢失了237笔交易数据。事后分析发现当时MySQL正在进行事务提交的IO操作强制中断导致双写缓冲(Double Write Buffer)机制失效。重要提示MySQL在5.5版本后默认使用InnoDB引擎其事务特性决定了强制重启可能造成数据页部分写入(partial page write)问题。这种损坏往往不会立即显现可能在后续使用中突然爆发。强制重启主要带来三类问题活跃事务丢失未完成的事务会直接回滚但已提交事务可能因未持久化到磁盘而丢失索引损坏B树结构可能在重组过程中被中断导致查询出现幻读主从同步中断GTID执行位置可能出现偏差需要重建复制关系2. 专业排查的7个关键步骤2.1 检查系统资源占用首先通过SSH连接到服务器如果还能连接执行以下命令组合top -c -b -n 1 | head -20 vmstat 1 5 iostat -dx 1 5重点关注指标CPUus值持续70%可能SQL执行问题sy值高可能锁竞争内存swap使用率20%将导致严重性能下降IOawait10ms表示磁盘响应慢%util80%说明磁盘饱和典型案例某金融系统MySQL卡死发现是备份脚本与业务高峰重叠导致IO等待达到98%通过iotop -oP定位到是xtrabackup进程占用了大量IO资源。2.2 分析MySQL进程状态使用管理员账号连接MySQL如果还能连接SHOW PROCESSLIST; SHOW ENGINE INNODB STATUS\G关键观察点State列Waiting for table metadata lock表示DDL阻塞Time列执行时间300秒的查询需要警惕InnoDB状态SEMAPHORES部分显示信号量等待情况特殊技巧当无法连接时可以用gdb抓取mysqld进程的堆栈gdb -p $(pidof mysqld) -ex thread apply all bt -batch2.3 检查锁等待情况执行锁监控命令SELECT * FROM sys.innodb_lock_waits; SELECT * FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE %FOR UPDATE% OR SQL_TEXT LIKE %LOCK IN SHARE MODE%;常见锁场景处理行锁等待kill阻塞会话元数据锁检查未提交的长事务间隙锁调整隔离级别或索引设计我曾遇到一个UPDATE语句没走索引导致锁全表通过EXPLAIN FORMATJSON发现缺失索引添加后解决。2.4 验证磁盘空间执行以下检查df -h # 查看分区使用率 du -sh /var/lib/mysql # 确认数据目录大小 ls -lh /var/lib/mysql/ibdata* # 检查系统表空间临界值参考分区使用90%时EXT4文件系统性能急剧下降InnoDB表空间自动扩展失败会导致事务中止临时目录(/tmp)满会使排序操作失败应急方案# 临时清理binlog PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY; # 在线收缩表空间 ALTER TABLE orders ENGINEInnoDB;2.5 检查连接数风暴查看连接数情况SHOW VARIABLES LIKE max_connections; SHOW STATUS LIKE Threads_connected;处理方案突发流量设置连接池大小限制连接泄漏检查应用代码是否未关闭连接慢查询堆积优化长时间运行的查询某社交平台遇到过连接数超过5000导致MySQL僵死最终发现是PHP-FPM配置了持久连接但未设置回收策略。2.6 分析错误日志日志位置通常位于/var/log/mysqld.log/var/lib/mysql/hostname.err关键搜索命令grep -i error\|warning\|crash /var/log/mysqld.log | tail -50常见错误模式InnoDB: Database page corruption需要从备份恢复[ERROR] Got timeout reading communication packets网络问题Cant create thread系统线程数限制2.7 评估复制状态主从架构检查命令SHOW SLAVE STATUS\G SHOW MASTER STATUS;关键指标Seconds_Behind_Master 300秒需警惕Last_IO_Error显示网络问题Slave_SQL_Running_State卡在Applying batch处理方案STOP SLAVE; SET GLOBAL sql_slave_skip_counter 1; START SLAVE;3. 安全重启的标准化流程当确认必须重启时应按此顺序操作通知业务方停止写入设置MySQL为只读模式SET GLOBAL read_only ON;优雅停止MySQLmysqladmin -uroot -p shutdown启动后立即检查CHECK TABLE orders,order_details EXTENDED;验证关键业务表数据完整性某次升级失败的回滚案例中我们通过mysqlbinlog解析出最后100个成功事务手动重放避免了数据丢失。4. 预防性维护建议监控配置设置CPU80%持续5分钟报警磁盘空间预警阈值设为85%长事务监控(60秒)参数优化innodb_io_capacity 2000 # SSD建议值 innodb_flush_neighbors 0 # SSD禁用相邻页刷新 table_open_cache 4000 # 避免频繁开表定期维护ANALYZE TABLE orders; OPTIMIZE TABLE session_data;架构设计读写分离减轻主库压力热点数据使用Redis缓存大表分库分表在最近一次大促中我们通过提前增加只读实例和调整innodb_buffer_pool_size到物理内存的80%成功应对了平时5倍的流量冲击。