半夜两点,手机嗡嗡震个不停。你揉着惺忪睡眼,打开电脑一看——数据库又报错了。这种场景,凡是跟数据打过交道的人,都经历过。报错信息满屏飘红,像天书一样,每个单词都认识,连在一起就不知道在说什么。更让人抓狂的是,同一个报错,上午刚处理完,下午又冒出来了。

说实话,数据库报错这事儿,真不是啥洪水猛兽。大多数时候,它只是一些固定的套路。我见过太多人一见报错就慌,恨不得把服务器重启十遍,结果问题没解决,数据还丢了。今天就把我这些年踩过的坑、填过的坑,整理成五大常见问题,给你一个速解指南。
第一个坑:连接不上数据库。 这个报错最常见,也最让人头疼。你检查了服务状态,看着明明是 running ,可就是连不上。这时候别急着重启,先 ping 一下,看网络通不通。然后 telnet 一下端口,我遇到过好多次,问题往往出在防火墙把端口挡了。还有个容易忽略的点——数据库的连接数可能已经满了。MySQL 有个 max_connections 参数,默认 151 ,如果没调过,分分钟就会被塞满。解决办法也简单:登录进去,把连接数调大,或者优化程序,别老占着连接不放。记住,连接不上数据库,八成是网络、端口、连接数这三个地方出问题,排查顺序别搞反了。
第二个坑:锁表了。 这个报错出现的频率,跟第一个不相上下。你执行一条 UPDATE 语句,结果卡在那里半天不动,抛出 Lock wait timeout exceeded 。换句话说,有人在抢这个表,你等不到。这种情况在业务高峰期特别常见,有人开启了事务却忘了提交,把表锁得死死的。怎么排查?用 SHOW PROCESSLIST 看看哪个线程在跑长事务,找到它 kill 掉。但这只是治标,治本的办法是让开发把事务粒度缩小,别在一个事务里跑半天。另外,检查一下索引,如果更新语句没用上索引,会导致全表扫描,锁的范围变大,性能差不说,还容易锁表。
第三个坑:磁盘满了。 这个报错特别隐蔽,因为 MySQL 或 PostgreSQL 在报错时不会直接说“磁盘满了”,而是给你 “Table is full” 或 “No space left on device” 之类的提示。我见过同事排查一个下午,才发现是日志文件把磁盘撑爆了。处理起来也不难:先用 df -h 看看使用率,如果已经到 90% 以上,大概率就是这个问题。找出大文件,通常是 binlog 或慢查询日志,该清理的清理,该归档的归档。但这里有个坑,binlog 不能直接 rm ,要用 PURGE 命令,不然容易出大问题。建议给数据库单独挂个盘,别和系统盘混在一起,否则系统日志也可能把数据库拖死。
第四个坑:字符集乱码。 这个报错最让人哭笑不得,因为程序不报错,数据也正常写入,但查出来的全是问号或乱码。根源在于数据库、表、连接三层的字符集没统一。你建库时用了 utf8mb4 ,但连接时用了 latin1 ,数据自然就乱套了。解决办法是把这三层的字符集统一起来,推荐全部使用 utf8mb4 ,它支持 Emoji,对中文也很友好。改完后,记得把之前乱码的数据修复一下,这个比较麻烦,得写脚本处理。但好在,这种问题预防比处理容易得多,新项目一开始就定好字符集规范,就不会有这些破事。
第五个坑:主从不同步。 这个报错在读写分离架构里特别常见。你往主库写了一笔数据,从库查不到,或者从库直接报 SQL 线程停了。排查时,先去从库上执行 SHOW SLAVE STATUS ,看看有没有报错信息。我见过最多的情况,是主从的 binlog 格式不一致,或者主从的数据库版本不一致,导致 SQL 执行失败。处理办法是,找到出错的那条 SQL,手动在从库上补一下,然后跳过这个错误,继续同步。但你要明白,这只是应急,根本解法是保持主从版本一致,binlog 格式统一,最好使用 ROW 格式。另外,从库的硬件配置


