这篇原本是一些零散面试题笔记。问题本身不差,但如果只是把答案堆在一起,读者很难带走东西。
我把它重新整理成一套面试回答框架:
遇到问题时,先确认现象;
再分层定位;
最后说清楚影响范围和解决价值。
下面按常见面试题来整理。
1. 如何确认一个 Bug
不要一上来就说“页面报错了”“接口挂了”。
确认 Bug 至少要回答四个问题:
能不能稳定复现?
是否符合需求预期?
问题属于哪一层?
影响范围有多大?
稳定复现
一个合格的 Bug 描述应该包含:
操作步骤
输入数据
环境信息
前置条件
实际结果
预期结果
比如:
环境:测试环境 v1.3.2
账号:普通用户
步骤:
1. 登录系统
2. 进入订单页
3. 选择已取消订单
4. 点击再次支付
预期:按钮不可点击,或提示订单状态不允许支付
实际:进入支付页,提交后接口返回 500
这样的描述,开发、测试、产品都能复现和讨论。
如果只写:
订单支付有问题
这个信息量太低。
是否符合需求
不是所有“看起来不对”的现象都是 Bug。
要确认:
需求文档怎么写?
接口文档怎么定义?
历史版本行为是什么?
产品有没有特殊规则?
比如按钮置灰可能不是 Bug,而是产品定义:
未实名认证用户不能发起提现。
所以确认 Bug 的第一步不是甩锅,而是确认“实际行为”和“预期行为”是否真的不一致。
2. 如何定位一个 Bug 属于哪一层
排查问题时,可以按层次走:
前端页面
-> 请求参数
-> 接口返回
-> 后端日志
-> 数据库数据
-> 缓存/MQ/第三方服务
-> 环境配置
举个例子:登录失败。
不要只说“登录不了”,可以这样排:
1. 前端是否真的发起请求?
2. 请求地址和请求方法是否正确?
3. 参数是否包含 username/password/captcha/token?
4. 接口返回的是 401、403、400 还是 500?
5. 后端日志有没有异常?
6. 数据库里账号状态是否正常?
7. Redis 里的验证码/session/token 是否过期?
8. 是否只有某个环境失败?
这就是“分层排查”。
面试时这样答,比直接背“看日志、看接口”更有条理。
3. HTTP 状态码怎么区分
常见几个状态码可以这样理解:
| 状态码 | 含义 | 常见场景 |
| --- | --- | --- |
| 400 | 请求参数有问题 | 参数缺失、格式错误、字段类型不对 |
| 401 | 未认证 | 没登录、token 过期、没有携带凭证 |
| 403 | 已认证但无权限 | 登录了,但角色权限不够 |
| 500 | 服务端程序异常 | 空指针、SQL 异常、代码未处理异常 |
| 503 | 服务暂时不可用 | 服务维护、限流、依赖服务不可用 |
最容易混的是401和403:
401 = 你是谁,我不知道。
403 = 我知道你是谁,但你不能访问。
比如:
未登录访问后台接口 -> 401
普通用户访问管理员接口 -> 403
这个区分在登录、权限、网关排查里很常见。
4. 登录功能无法登录,怎么排查
登录问题很适合用分层思路。
可以按这个顺序:
页面输入
-> 前端校验
-> 请求参数
-> 验证码/session
-> 账号密码校验
-> token 生成
-> cookie/localStorage 写入
-> 后续接口是否携带凭证
常见问题:
前端没有发请求
请求参数字段名错了
验证码过期
账号被禁用
密码加密方式前后端不一致
后端生成 token 失败
浏览器没有写入 cookie
跨域导致 cookie 没带上
面试回答可以这样组织:
我会先看浏览器 Network,确认请求有没有发出去;
再看请求参数和响应状态码;
如果接口返回异常,就结合后端日志和数据库账号状态排查;
如果登录接口成功但后续仍然未登录,就重点看 token/cookie 是否写入,以及后续请求是否携带凭证。
这比一句“看日志”更像真实做过排查。
5. left join、right join、inner join 怎么讲
可以先用一句话:
inner join 取匹配成功的数据;
left join 保留左表全部数据;
right join 保留右表全部数据。
假设有两张表:
user
id name
1 Tom
2 Jack
order
id user_id amount
10 1 99
inner join
select *
from user u
inner join order o on u.id = o.user_id;
只返回能匹配上的数据:
Tom 有订单,所以返回 Tom + order。
Jack 没订单,所以不返回。
left join
select *
from user u
left join order o on u.id = o.user_id;
左表user全保留:
Tom 有订单,返回订单数据。
Jack 没订单,order 字段为 null。
right join
select *
from user u
right join order o on u.id = o.user_id;
右表order全保留。
实际开发里left join更常见,因为我们通常会从“主表”出发,把关联表补上。
6. 数据库索引怎么讲
索引不是“让所有查询都变快”的魔法。
更准确地说:
索引用额外的数据结构,帮助数据库减少扫描范围。
MySQL InnoDB 常见索引结构是 B+Tree。
它适合磁盘存储的原因是:
树高相对低;
范围查询方便;
叶子节点有序;
每次查询可以减少大量无效扫描。
常见索引类型:
主键索引 primary key
唯一索引 unique
普通索引 index
联合索引 composite index
全文索引 fulltext
索引优点:
提高查询速度
提高排序/分组效率
提高连接查询效率
保证唯一性
索引缺点:
占用磁盘空间
降低写入性能
增加维护成本
可能因为写法不当失效
常见索引失效场景:
索引列上使用函数
隐式类型转换
like 以 % 开头
联合索引不满足最左匹配
OR 条件使用不当
字段区分度太低
使用 != 或 <> 导致优化器不走索引
面试时不要只背“索引能加快查询”。最好补一句:
索引提升读性能,但会牺牲写性能和空间,所以要围绕高频查询、过滤条件、排序字段来设计。
7. 印象最深的 Bug 怎么讲
这个问题不要随便讲一个小 Bug。
好的回答应该体现:
问题背景
排查过程
定位方法
解决方案
复盘收益
可以套这个结构:
当时遇到的问题是……
现象是……
我先通过……确认复现路径;
然后从前端请求、接口返回、后端日志、数据库数据几层排查;
最后定位到……
解决后我们补了……
这件事让我意识到……
重点不是 Bug 多复杂,而是你能不能展示自己的排查思路。
8. 总结
这些题看起来很杂,其实底层都在考同一件事:
你遇到问题时,有没有结构化定位能力。
可以记住这条主线:
先确认现象;
再判断预期;
然后分层定位;
最后评估影响和复盘。
不管是 Bug、登录失败、状态码、SQL Join 还是索引,面试官真正想看的都不是背诵,而是你能不能把问题讲清楚。