主从复制中断表现为Seconds_Behind_Master为NULL或持续增长,说明SQL线程停止或卡住;连接数打满需排查应用层连接泄漏;ibdata1暴涨源于innodb_file_per_table关闭且无法在线收缩;慢查询CPU飙升多因Sending data状态下的低效执行,需优化索引与分页逻辑。

主从复制中断:Seconds_Behind_Master 为 NULL 或持续增长
这通常不是延迟变大,而是复制已停止。执行 SHOW SLAVE STATUS\G 后看到 Seconds_Behind_Master: NULL,说明 SQL 线程没在运行;若数值持续上涨,大概率是 IO 线程正常但 SQL 线程卡住。
- 先检查
Slave_IO_Running和Slave_SQL_Running是否都为Yes;任一为No就得查错 - 常见原因包括:从库遇到主库上不存在的表(如误删)、主键冲突、DDL 语句不兼容(如
ALTER TABLE ... ALGORITHM=INPLACE在旧版本不支持)、GTID 模式下跳过事务失败 - 修复前务必确认
Relay_Log_File和Relay_Log_Pos,避免盲目START SLAVE导致数据不一致 - 若因唯一键冲突中断,不要直接
SET GLOBAL sql_slave_skip_counter = 1(仅适用于基于位置的复制),GTID 模式下必须用gtid_next+BEGIN; COMMIT;跳过
连接数打满:Too many connections 错误频繁出现
不是简单调大 max_connections 就能解决。真正的问题往往藏在应用层——连接未释放、长事务阻塞、或监控脚本高频探测。
- 先查当前活跃连接:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep';,重点关注TIME值大的线程 - 检查是否有未提交事务:
SELECT * FROM information_schema.INNODB_TRX;,长时间TRX_STATE = 'RUNNING'的事务会占用连接并阻塞后续操作 - 应用侧常见陷阱:Java 中
Connection没在finally块里close();Python 的with未正确包裹数据库操作;PHP 的mysql_connect()(已废弃)反复新建连接 - 临时缓解可用
KILL杀掉异常连接,但长期要加连接池(如 HikariCP)、设wait_timeout和interactive_timeout缩短空闲连接生命周期
InnoDB 表空间暴涨:ibdata1 不停增长且无法收缩
ibdata1 是共享表空间,默认存储数据字典、undo log、系统表等。一旦启用 innodb_file_per_table = OFF,所有表数据都会写进它,且 MySQL 不提供在线 shrink 功能。
- 确认是否启用了独立表空间:
SHOW VARIABLES LIKE 'innodb_file_per_table';,值为OFF是隐患源头 - 如果已经暴涨,不能直接删
ibdata1——会导致实例启动失败;必须导出全部数据(mysqldump --all-databases --single-transaction),停库,清空数据目录,修改配置启用innodb_file_per_table = ON,再重装导入 - 新部署务必默认开启
innodb_file_per_table;已有实例可逐个迁移:ALTER TABLE tbl_name ENGINE=InnoDB;(需确保磁盘有足够空间做重建) - 注意 undo log 也会撑大
ibdata1,MySQL 5.7+ 可通过innodb_undo_tablespaces拆分,8.0+ 支持innodb_undo_log_truncate自动截断
慢查询导致 CPU 飙升:show processlist 显示大量 Sending data 状态
Sending data 并非网络传输,而是指 MySQL 正在处理查询结果(如排序、分组、生成临时表)。该状态耗时长,基本等于执行本身慢,不是网络问题。
- 开启慢日志:
SET GLOBAL slow_query_log = ON;,配合long_query_time = 1捕获 >1 秒的查询 - 重点看执行计划:
EXPLAIN FORMAT=TREE SELECT ...(8.0+)或EXPLAIN ANALYZE(8.0.18+),确认是否走了索引、是否用到 filesort / temporary - 典型诱因:
ORDER BY RAND()、SELECT *配合大 LIMIT、JOIN 多张大表没关联字段索引、JSON 字段全表扫描(JSON_CONTAINS()无虚拟列索引) - 优化优先级:加复合索引 > 改写查询逻辑(如用游标分页替代
LIMIT offset, size) > 开启innodb_buffer_pool_size(建议设为物理内存 70%~80%)
SELECT id, name, created_at FROM users WHERE status = 1 ORDER BY created_at DESC LIMIT 100000, 20;
这种写法在 OFFSET 很大时,MySQL 仍要扫描前 100020 行。改成用上一页最大 created_at 值做条件更高效:
SELECT id, name, created_at FROM users WHERE status = 1 AND created_at < '2023-01-01 12:00:00' ORDER BY created_at DESC LIMIT 20;
真实故障里,最常被忽略的是配置与业务节奏的错配——比如凌晨批量 job 用默认 innodb_lock_wait_timeout=50,而报表任务实际需要 300 秒,结果大量锁等待超时回滚,反而加剧并发压力。









