人人都会AI编程

22.4 常见故障:连接失败、主从中断、性能突降、数据损坏

更新时间:2026-07-10

数据库故障是运维工作中无法回避的一环。这一节不追求理论完备,聚焦四种最常遇到的故障类型,展开实用的排查思路和处理方法。

22.4.1 连接失败

应用程序报“无法连接数据库”是最高频的告警之一。原因可能有以下几种:

1. 服务端连接数耗尽

MySQL 的 max_connections 限制了最大并发连接数。当连接数达到上限时,新的连接请求会被拒绝,报错 Too many connections

  • 排查:在服务器上执行 SHOW VARIABLES LIKE 'max_connections'; 查看上限,再执行 SHOW STATUS LIKE 'Threads_connected'; 查看当前连接数。如果当前连接数接近上限,就是瓶颈所在。
  • 处理:首先,尝试通过 kill 命令杀掉空闲连接或异常长事务的连接,临时救急;其次,排查连接池配置是否合理(比如应用端连接池是否忘记回收连接、连接数量是否配置过高);长期方案是适当调大 max_connections(需考虑内存消耗,每个连接约消耗数 MB),或启用 MySQL 的线程池功能分摊压力。

2. 网络问题或防火墙阻断

  • 排查:从应用服务器 telnet <mysql_ip> 3306 测试端口通断。如果无法连通,检查网络策略、安全组规则、服务器防火墙(iptables/firewalld),确认 3306 端口是否对应用服务器的 IP 开放。
  • 处理:修正防火墙规则或安全组配置。同时检查 MySQL 的 bind-address 配置,如果绑定为 127.0.0.1 则只允许本地连接,需改为 0.0.0.0 或指定内网 IP。

3. 认证失败或权限不足

  • 表现:报错 Access denied for user 'xxx'@'host'
  • 排查:确认用户名、密码、主机名是否正确。特别要注意 MySQL 的用户是由用户名和来源主机共同标识的,user@'%'user@'localhost' 是两个不同的用户,权限也可能不同。执行 SELECT user, host FROM mysql.user WHERE user='your_user'; 查看用户列表。
  • 处理:使用 ALTER USERGRANT 修正密码和权限。如果是密码认证插件问题(比如 MySQL 8.0 默认使用 caching_sha2_password,而旧驱动不支持),可改用 mysql_native_password 或升级客户端驱动。

4. DNS 解析超时

当服务器开启 skip_name_resolve=OFF 时,MySQL 会对客户端 IP 进行反向 DNS 解析,若 DNS 服务器不可达会造成连接挂起。

  • 处理:建议在 my.cnf 中设置 skip_name_resolve=ON,跳过 DNS 解析,直接用 IP 匹配权限,提升连接速度并避免此类故障。

22.4.2 主从中断

主从复制中断是运维人员经常需要处理的故障,典型表现是 SHOW SLAVE STATUS\GSlave_IO_RunningSlave_SQL_RunningNo

常见原因与处理:

1. SQL 线程报错(主键冲突、记录不存在等)

  • 典型错误号1062(Duplicate entry)、1032(更新或删除时找不到记录)。
  • 原因:从库被人为写入了数据,或主从数据不一致。
  • 处理:首先判断报错的行是否可以被覆盖。如果确认可以跳过,用 SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; 跳过该事件,然后重启 SQL 线程(START SLAVE SQL_THREAD;)。但跳过是治标不治本,之后需要检查整表数据一致性(可用 pt-table-checksum 工具),然后通过 pt-table-sync 修复差异。预防此类问题的关键是:严格杜绝在从库直接写入数据,设置 read_only=ONsuper_read_only=ON

2. IO 线程连接不上主库

  • 表现Slave_IO_Running: Connecting 一直持续,或有网络相关错误信息。
  • 排查:检查主库的复制用户密码是否正确、网络是否通畅、主库实例是否运行、max_connections 是否已满、防火墙是否断开。
  • 处理:使用 CHANGE MASTER TO 重新指定正确的连接信息,或解决网络问题后重启 IO 线程。

3. 主从数据延迟过大导致事务不可用

半同步复制或异步复制下,如果从库硬件较差、网络延迟高或存在大事务,会导致从库落后主库很多。虽不算中断,但影响业务准确性。

  • 处理:优化大事务拆分;确认 sync_binloginnodb_flush_log_at_trx_commit 不是绝对的串行瓶颈;增加从库硬件资源;使用并行复制(MySQL 5.7+ 基于 LOGICAL_CLOCK 的并行复制,8.0 基于 WRITESET 的并行复制),设置 slave_parallel_workers > 1

4. 主库 binlog 被清理

从库长时间中断,拉取的 binlog 文件已在主库被 PURGE BINARY LOGS 删除,IO 线程会报错无法找到日志。

  • 处理:只能重新搭建从库,通过全量备份恢复从库后再追增量。预防措施:根据复制延迟和备份策略设置合理的 expire_logs_daysbinlog_expire_logs_seconds(8.0),确保 binlog 保留时间大于最长允许中断时间。

22.4.3 性能突降

数据库突然变慢,CPU、IO 或内存飙高。

1. 慢查询集中爆发

  • 排查:查看慢查询日志,用 mysqldumpslow 或 pt-query-digest 分析。同时观察 SHOW FULL PROCESSLIST,大量线程处于 Sending dataCreating sort index 状态。
  • 处理:紧急 kill 掉特别慢的查询,与开发确认是否有新上线 SQL 或业务流量高峰。快速优化手段包括:强制使用索引(FORCE INDEX)或临时增加索引;长期方案是优化 SQL,添加合适的索引。

2. 锁等待风暴

  • 表现:大量查询处于 Waiting for table metadata lockLock wait timeout
  • 排查:查询 SHOW ENGINE INNODB STATUS 中的 LATEST DETECTED DEADLOCKTRANSACTIONS,找出切锁等待链。或查询 sys.innodb_lock_waits(MySQL 8.0)查看当前锁等待关系。
  • 处理:kill 掉阻塞者(持有锁却长时间不提交的会话)。为防止再发,缩短事务,避免在事务中执行交互性操作或慢查询。

3. 缓冲区命中率下降

  • 现象:磁盘 I/O 异常高,查询延迟陡增,可能是缓冲池被大量冷数据污染(比如全表扫描大表)。
  • 排查:查看缓冲池命中率(SHOW STATUS LIKE 'Innodb_buffer_pool_read_requests';Innodb_buffer_pool_reads,用 read_requests / (read_requests + reads) 算命中率,通常需在 99% 以上)。
  • 处理:杀掉全表扫描的会话,考虑增大 innodb_buffer_pool_size,或使用更合适的索引避免全表扫描。

4. 突然的 CPU 飙升

  • 可能原因:大量连接断开和重建、SQL 不优化导致需要大量计算、或内部竞争(如自适应哈希索引锁争用)。
  • 处理:检视 SHOW PROCESSLIST 和系统 CPU 火焰图(perf 工具),调整 innodb_thread_concurrency 等参数控制并发度,关闭自适应哈希索引(innodb_adaptive_hash_index=OFF)临时解决争用,长期靠 SQL 优化。

5. 主从切换后性能变化

新主库的硬件配置可能不如原主库,或者数据页缓存未预热,导致大量 I/O。此时需要预留缓冲池预热时间,或使用 MySQL 的缓冲池预加载功能。

22.4.4 数据损坏

数据损坏是最严重的故障,可能导致实例无法启动或查询报错。

1. InnoDB 表空间损坏

  • 现象:查询报错 Tablespace is missingInnoDB: Database page corruption detected,或 MySQL 启动失败。
  • 常见原因:硬件故障(磁盘坏道、内存错误)、突然断电、操作系统 bug、强行 kill -9 导致数据页部分写入。
  • 处理步骤
  1. 首先尝试强制恢复模式。在 my.cnf 中设置 innodb_force_recovery(值为 1~6,从 1 开始逐渐增大试),让 MySQL 能够尽量启动并执行 SELECT 导出数据。注意此模式下不允许任何修改操作。
  2. mysqldump 备份所有数据后,重建实例并恢复。
  3. 如果个别页损坏,可尝试使用 MySQL 企业版或 Percona Toolkit 中的 innodb_recovery 工具修复页,但修复不一定保证数据完整,损失的数据需结合 binlog 或人工补救。
  4. 预防措施:使用带电池的 RAID 卡,开启 innodb_doublewrite=ON(默认开启),使用 ECC 内存,避免强制断电。

2. 磁盘空间耗尽导致写入失败

  • 现象ERROR 1114 (HY000): The table 'xxx' is full 或 binlog 写满磁盘。
  • 处理:紧急清理不必要的日志文件(慢日志、错误日志、旧的 binlog)、临时释放空间。用 PURGE BINARY LOGS TO 'xxx' 删除已备份过的 binlog。同时扩容磁盘或迁移数据到更大磁盘。

3. 误删除数据

  • 情形DROP TABLEDELETE 误操作,未开 binlog 或备份。
  • 应对:如果有延迟从库或备份,立即停止从库同步并抢救数据。否则启用 binlog 使用 mysqlbinlog 解析日志进行反向生成撤消 SQL,或基于时间点的闪回工具(如 binlog2sql)。根本预防:设置回收站机制,上线 DROP 审核流程,开启 sql_safe_updates 模式(SET SQL_SAFE_UPDATES=1)限制不带限制条件的 UPDATE/DELETE。

4. MyISAM 表损坏

虽然目前几乎都已改用 InnoDB,若遇到遗留 MyISAM 表损坏,可用 REPAIR TABLE tablename 命令在线修复。若损坏严重,需用 myisamchk -r 工具在停服后修复。


面对故障,最重要的不是记住每一个解决命令,而是建立清晰的排查思路:先定位现象 → 确认影响范围 → 运用日志与状态视图诊断根因 → 快速止血 → 长期优化。 任何时候,优先保证数据安全和服务可用,然后才是复盘改进。