半夜两点被叫起来,应用报"数据库连接失败",所有报表白屏。这是每个后端和运维都经历过的场景。数据库问题排查这件事看起来很吓人,但大部分情况下,真正让你卡住的不是问题本身有多难,而是你根本不知道从哪下手,只能靠重启、重启、再重启碰运气。我整理这份"01-08-22 数据库问题排查完全指南",就是想把这些年处理Oracle、MySQL、PostgreSQL、SQLite以及国产数据库问题时积累的排查链路一次性讲清楚——从连接故障、慢查询、死锁,到数据迁移、安装配置,每个环节都给出可落地的操作步骤和判断依据。
这篇内容主要面向两类人:一是刚接手数据库运维的后端开发,数据库出问题的时候往往是最慌的;二是需要自己扛项目的全栈或独立开发者,没有专职DBA,出了问题只能自己上。不管你是哪种,看完以后至少能建立一套自己的排查思路,而不是遇到问题就百度一条命令试一条。
1. 排查数据库问题前,先把"现象"翻译成"故障层"
1.1 为什么要先分层
我见过太多人拿到一个数据库报错就开始瞎试:先重启数据库服务,不行就重启应用,再不行就重装客户端。这种碰运气式的排查最大的问题是,你根本没有定位问题的层面,只是在赌。
数据库访问链路其实是固定的:客户端/应用 -> 网络连接 -> 数据库实例 -> SQL解析执行 -> 存储引擎 -> 物理文件。任何一个环节出问题,应用层的表现往往都是"连接失败"或"查询超时"——这是因为上层应用把底层的多种异常统一包装成了几个常见错误码。所以排查的第一步,是把这个链路在脑子里过一遍,确认问题到底发生在哪一层。
我一般把故障划分为四个层面:
| 故障层 | 典型现象 | 常见原因 |
|---|---|---|
| 网络层 | 连接超时、TNS无法解析 | 防火墙、端口不通、DNS问题 |
| 服务层 | 连接被拒绝、认证失败 | 实例没起、监听挂了、密码错 |
| SQL层 | 查询慢、锁等待 | 索引缺失、执行计划差、并发冲突 |
| 数据/存储层 | 磁盘满、表损坏、数据文件丢失 | 空间耗尽、异常断电、误删 |
1.2 每一层最直接的验证动作
确定了怀疑的层面,就要用最快的动作去验证,而不是打开一堆工具慢慢地看。
网络层:先 ping 通不通,再测端口。很多数据库端口在云厂商的安全组、本机防火墙、甚至公司办公网的出口策略上被挡了。Windows 下用 telnet,Linux 下用 nc,一条命令就能确认端口是否可达。有些时候 ping 通了但端口不通,说明主机活着但监听进程没起来,或者安全组挡了端口。
服务层:查看数据库进程是否存活、监听状态是否正常、日志里有没有报错。Oracle 看 lsnrctl status,MySQL 看 systemctl status mysqld 或者直接看 error log,PostgreSQL 看 pg_ctl status。这里要特别注意,进程活着不代表数据库可用,很多数据库实例会陷入"假死"状态——进程在,但无法接受新连接。
SQL层:如果连接本身没问题,但某些业务操作很慢或卡住,就要看慢查询日志、执行计划、会话等待事件。这个层面的排查是性能问题的主战场,后面单独展开。
数据/存储层:检查磁盘空间、表空间使用率、文件系统权限。我遇到过不止一次数据库自己没问题,是挂载的数据盘满了,导致数据库无法写入。用 df -h 和 df -i 同时看,因为 inode 满了同样会出问题,而且更容易被忽略。
1.3 一个被忽略的原则:制造最小复现
排查问题的时候,不要直接在应用里试,那样变量太多。从数据库客户端(mysql、psql、sqlplus、DBeaver)去连一下,如果能连上并执行简单查询,说明数据库本身是好的,问题在应用侧;如果客户端也连不上,再按上面的层次逐层排查。这种最小复现的方法能帮你快速把排查范围缩小一半。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 连接故障排查:从"应用报错"倒推到"连接池打满"
2.1 常见连接报错的真实含义
连接类故障是数据库问题里出现频率最高的一类。Java 项目最常见的报错是 Communications link failure,Oracle 项目常见的是 ORA-12541: TNS:no listener,MySQL 常见的还有 Too many connections,PostgreSQL 则是 sorry, too many clients already。这些报错看着不同,但本质上对应的故障层完全不一样。
我整理了一个快速对照表:
| 报错信息 | 问题层 | 优先检查 |
|---|---|---|
| Communications link failure | 网络/服务 | 端口、实例状态 |
| ORA-12541 TNS:no listener | 服务层 | Oracle监听是否启动 |
| ORA-01034: ORACLE not available | 服务层 | 实例是否mount/open |
| Access denied for user | 认证 | 账号密码、权限 |
| Too many connections | 连接池/资源 | max_connections、活跃连接数 |
| Connection refused | 服务层 | 进程是否存 |
