恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
写代码前先问5个为什么:从数据库崩溃到研发流程优化
首页
资讯中心
/
写代码前先问5个为什么:从数据库崩溃到研发流程优化
写代码前先问5个为什么:从数据库崩溃到研发流程优化
发布时间:2026/10/6 10:27:45
那次事故发生在周四下午两点十七分我刚从食堂回到工位手机上的告警群就开始疯狂震动。支付订单表的数据积压、接口响应时间直线飙升、数据库连接数被打满紧接着就是一连串的宕机提示。等我们手忙脚乱地重启服务、清理会话、恢复数据之后已经是晚上九点多了。整个下午用户在下单时要么转圈圈要么直接提示系统繁忙客服那边被打爆了电话运营同事急得直接冲到技术区找人对线。事后复盘时我们发现引起崩溃的代码其实很“简单”某个同事在给订单查询加过滤条件时直接对一张千万级数据的表做了一个非索引字段的模糊匹配。按照常规思路开发修复Bug、上线补丁、写个复盘报告这事就算翻篇了。但那天晚上团队里的老张提出了一个非常尖锐的问题”我们为什么要等到线上出问题了才去翻这段代码为什么这段代码能通过评审”于是就有了后来的那条铁规写代码前先问5个“为什么”。1. 事故复盘从“数据库打满”到“需求没对齐”1.1 表面故障与深层根因的距离复盘会上我们用了5 Why分析法一层层往下挖。第一层系统为什么崩溃因为数据库连接池被打满。第二层连接池为什么被打满因为新上线的接口里有个慢查询平均耗时接近11秒请求全部卡在数据库上。第三层为什么会出现这种慢查询因为对存储过程生成的时间戳字段做了字符串开头的模糊匹配索引完全失效。第四层为什么这个SQL能写出来因为开发同学没有查看执行计划没有评估数据量级。第五层为什么他没有评估数据量级因为需求里只说了“查询用户最近产生的异常订单”没有明确数量级和性能要求他按平时几千行的小表思路去写了。这轮问答走完我们发现“问题代码”只是冰山一角。深藏在水面下的是需求评审流于形式、代码评审只看逻辑不看性能、开发没有SQL审查意识、测试环境数据量太小根本没暴露风险。真正引发系统崩溃的不是某一个开发者的手滑而是一整条研发链条上的多个环节同时失守。我把那次复盘的过程整理成了一个表格贴在团队内部文档库里每次新人入职都先看一遍。表格长这样层数追问问题得到的回答1 Why系统为什么崩溃数据库连接池被打满服务无法响应新请求2 Why连接池为什么被打满慢查询把连接长期占住请求全堵在SQL上3 Why为什么会有这个慢查询对无索引字段做前缀模糊匹配全表扫描4 Why为什么这SQL能上线代码评审没人看执行计划开发也没自查5 Why为什么没自查需求只有功能描述没有任何性能指标抛开那张表格里冷冰冰的因果链那次复盘真正让我警觉的是“人”这一层的状态。那个写问题代码的同事不是新手他之前负责过好几个核心模块属于“靠谱”那一类。但那天他说了一句话“我以为这个接口是内部监控用的一天没几个请求。”这句话暴露了一个本质问题他在动手写代码时脑子里的场景假设和实际生产环境的场景假设完全不是一回事。如果他在写第一行代码之前先问自己一句”这个接口会被怎么调用、多久调用一次、最多返回多少条数据”那个慢查询压根不会出生。1.2 5 Why 不是“连问五句为什么”那么简单很多文章讲5 Why举的例子都是“杰斐逊纪念堂墙面为什么风化”那种经典案例。一到实操中最常见的误区就是把它当成“连问五个为什么”的机械练习问到最后得到的答案全靠编。我在那次复盘里最大的感受是5 Why的有效性取决于每追问一层时能不能拿到真实的数据和证据而不是坐在一起凭感觉瞎推。比如复盘时有人说到“连接池被打满”立刻就有人跳出来说“应该把连接池从100调到200”。如果停在那一层我们最多算是打了个补丁。但问题是“为什么打到100就被打满了而不是正常波动”于是我们去看监控曲线发现打满前的15分钟那个慢查询就已经开始拖垮其他接口了。每往下一层都要带着“证据”去问而不是带着“解决方案”去问。那次之后我们还给5 Why加了一条配套规则写代码之前问的为什么必须有对应的事实支撑不能用“我猜”“我觉得”来回答。这个要求听着简单做起来很难因为人在被追问的时候本能反应就是快点给个台阶下。如果你不把“凭据”作为硬条件五个为什么问下来很可能只得到一个“因为运气不好”式的结论。2. 写代码前的五个“为什么”一条可直接抄走的开工自检清单2.1 第一问这个功能为什么存在动手写代码之前第一件事不是打开IDE建文件而是想清楚这个功能为什么会出现。它来自哪个需求是用户反馈的痛点、业务方的规划、还是某次数据异常带来的补救措施这决定了代码的生命力和气质。有一次我们做一个订单导出功能需求文档写得特别简单“支持按时间范围导出订单明细”。开发同学拿到就开干了做出来一个联调界面但因为没有考虑“为什么要导出”“导出的数据去做什么”导致交付后才发现业务方是要给财务做对账用的需要包含支付流水号、优惠分摊金额、税费明细。这些字段在原始订单表里都有但导出模板里根本没放。改模板、重新测试、再次发布一来一回又折腾了两天。所以第一问的实操方法是把需求文档里的“做什么”翻译成“为什么做”然后写出这个功能上线后的预期使用者画像和使用频率。如果写不出这三行字说明需求还没想清楚先别碰键盘。2.2 第二问这个功能为什么用这种方案实现需求明确之后第二个“为什么”是问技术选型的。同一个功能可以用同步接口、异步消息、定时任务、事件驱动等多种方案实现。为什么要选当前这一种是基于团队技术栈的延续性、性能要求还是因为某个约定俗成举个例子用户上传头像后要生成三种尺寸的缩略图。常规做法是同步处理上传接口直接返回处理结果。但如果用户量上来了同步处理会导致上传接口响应很慢。这时候改成异步任务加对象存储回调体验会好很多。如果没问“为什么用同步方案”上线后被流量一压马上就露怯。这个“为什么”还包含另一层含义为什么不用现成的公共组件而选择自己写很多系统崩溃的隐患就是开发觉得“自己写也不复杂”于是绕过公司内部的公共库单独造了一个轮子。轮子的逻辑没测试全、没有负载保护、没有降级方案平时验不出问题一到高峰就出事。2.3 第三问为什么现在做、现在写是对的时机第三个“为什么”是关于节奏的。这个需求为什么要在当前迭代做是因为业务优先级确实高还是因为开发手上刚好空出来当前的基础设施、依赖服务、数据准备是否已经就绪我见过最典型的反面案例是新功能依赖的数据表还没来得及做数据清洗开发已经按“数据可用”的前提把代码写完了。联调时发现数据缺得离谱代码里加了一堆判空和默认值兜底导致业务逻辑被各种特殊分支绕晕最后变成一个谁也动不了的“屎山”。如果动手前先问一句“现在做这个前置条件都齐了吗”很多返工是可以直接避免的。这个为什么的潜台词是让开发者对“项目节奏”保持敏感而不是被动地跟着排期走。2.4 第四问为什么这个改动只影响A而不影响B没有局部思维是很多生产故障的源头。代码从来不是孤岛你改的每一个字段、每一条SQL、每一个接口签名都可能被其他模块依赖。第四问要求你在动手前把改动链路完整地走一遍它影响哪些上游服务、哪些下游服务、哪些数据表、哪些定时任务。我统计过团队近半年线上的P2级以上事故超过60%都跟“改了一处其他模块没感知”有关。最常见的场景是有人给某个接口增加了一个必填参数自己内部调用的地方全部改好了但没排查其他系统是否也在调用这个接口。等别家系统凌晨跑批时报错排查到凌晨三点才发现是接口签名变了。为了避免这种情况我们现在的做法是写代码前必须查调用链把“谁在调我、我在调谁”梳理出来。如果有跨系统调用还得走一遍接口文档确认字段变更的兼容方案。这一步放在写代码之前成本极低收益却非常可观。2.5 第五问为什么我不能花更少的代价验证这个改动第五个“为什么”是问验证成本和可测试性的。你打算怎么证明这段代码是对的靠编译通过、靠本地自测还是靠上线后等用户反馈很多开发在写代码前根本没想过这个问题写完就提测测出问题再改改完再看影响面等于把验证成本全部堆在测试和线上。更好的做法是动手前想清楚可测试性的方案。这个函数能不能写单元测试这个接口要不要输出日志方便联调这次改动对已有功能的影响是否可以通过对比测试来验证如果代码写完后很难验证那说明设计本身有问题应该先回到第二问去调整方案而不是硬着头皮往下写。上面五个问题如果单独拿出来看每个都很简单。但把它们串在一起作为“写代码前的固定仪式”就会产生完全不同的效果。它逼着开发者在键盘落地前先把脑子里的思路拎清楚。3. 5 Why 融入研发流程的落地方式3.1 需求评审加入“根因预判”环节先说需求侧。过去我们开需求评审会前端、后端、测试、产品坐在一起主要听产品经理讲完了“要做什么”然后各自领任务就散会了。系统崩溃之后我们给评审会加了一个固定环节每个需求开发要用5 Why的方式做一次“根因预判”。产品讲完需求后开发轮流追问“这个需求为什么存在”“为什么不在上个迭代做”“用户为什么需要这个功能”“如果这个功能不做最坏情况是什么”听起来像是在找茬但实际上是从各个角度把需求的边界摸清楚。很多不成熟的需求在这种追问下会自己暴露问题。比如有次评审会上产品提出“用户签到页要展示广告”我们连问了几个为什么最后发现这个需求其实是为了提升广告位点击率而不是为了用户体验。基于这个根因我们把方案改成了“在签到结果页展示相关度更高的推荐内容”点击率目标反而实现了。这个过程非常有意思如果不做5 Why团队就停留在“接需求、排期、开发”的流水线上没人对需求的“合理性”负责。一旦开始追问根因很多表面的伪需求就会自动坍塌团队的研发精力自然就聚焦到真正重要的事情上了。3.2 代码评审变成“答辩会”而不是“走过场”代码评审是质量门禁但大多数团队的评审是“看有没有低级错误”而不是“看设计是否经得起推敲”。我们把5 Why引入评审后评审被改成了答辩形式提交代码的同学要面对评审人提出的追问比如“你这个循环为什么要放这里”、“这个缓存为什么要设置2分钟的过期时间”、“为什么不用布隆过滤器而是直接用Set”刚开始开发们很不适应觉得这是在“刁难人”。但执行了几周后效果很明显提交上来的代码质量提升了一大截因为每个人都会在提测之前自己先模拟一遍“如果评审问这个我该怎么说”。很多隐蔽的问题在“预答辩”的阶段就被自己发现并修掉了。为了让评审有效我们还定了一条硬性约定如果代码作者答不上来“为什么这样写”默认代码不合格打回重新补充设计说明。这条规则看似强硬但一次运行下来团队里没一个人提出反对。因为大家心里都清楚写代码时敷衍一个“为什么”上线后就要花十倍的代价去填坑。3.3 复盘会从“追责”转向“系统性根因”系统崩溃后的那次复盘是我们团队复盘文化的一个分水岭。以前复盘语气是“谁的锅”最后的结论往往是“某某需要注意”。这样的复盘不光让人抵触而且没有任何建设性。引入5 Why之后复盘会变成了“共同挖矿”每个与会者都可以提问每个回答都要提供证据大家的目标不是找一个人来背锅而是把链条上的每一个断点都找出来。从那以后我们复盘时有一个不成立的规定拿到“人粗心大意”这一层必须继续往下挖因为“粗心”不是根因只是表象。继续问下去往往会发现问题出在流程、工具、沟通机制或者环境约束上。把系统性根因挖出来之后对应的改进措施才能落地。比如我们在一次复盘中发现某个模块频繁出Bug是因为这个模块的前任维护者离职后没有留下任何设计文档。于是我们立了一条规矩核心模块必须补文档没有文档的情况下修改代码前必须花时间“考古”先搞懂旧逻辑为什么存在再谈改动。4. 常见问题与避坑心得4.1 五个问不下去怎么办实操中5 Why最常见的卡住场景是“问了两层就没人能回答了”。技术团队的知识分布是不均匀的负责需求的同学并不知道数据库索引的原理后端的同学也不一定清楚前端的渲染机制。如果你问的人刚好回答不了场面就会一下子冷下来。我的处理方法是把“5 Why”改成“5 Why协同问答”——问不下去的那一层不要逼当事人在会上硬想而是把这个“为什么”分摊给所有与会者谁了解这块就由谁来回答。如果所有人都答不上来那就把它标记为一个“知识盲区”后续安排专项调研。这样做不会卡节奏还能顺便把团队的隐性知识盲区暴露出来。4.2 问出“甩锅链条”或“虚假归因”怎么办5 Why用起来还有一个常见的坑问到最后变成了“甩锅链条”。比如“为什么没发现问题因为测试没测出来为什么测试没测出来因为测试用例没覆盖为什么测试用例没覆盖因为测试资源不够”。看起来很合理但每一层都在指认别人没有一层的答案是落在自己能改的动作上。遇到这种情况我习惯加一个约束每一层的答案必须落在“可执行的改进动作”上。比如“测试用例没覆盖”对应的可执行动作是“新增接口性能测试的门禁卡点”那这个答案就是有效的。如果答案是“因为测试不认真”那就不能停在这一层还是要继续往下挖直到挖到一个“明天就可以做”的具体事项为止。虚假归因也很常见。比如“为什么数据库响应慢因为磁盘IO瓶颈”但事实上响应慢是因为SQL扫描行数过大。如果第一层归因就错了后面的四个Why只能越走越偏。所以每层回答都必须有监控数据、日志或者代码来佐证这就回到了复盘会上“没有证据不推进”的原则。4.3 5 Why 是否适合所有“写代码之前”的场景有人会问如果每个功能都要问5个为什么那效率从哪里来我的回答是5 Why不是让你每次写代码都花一小时做头脑风暴而是要形成一种快速的“思维条件反射”。熟练之后面对简单需求你可能几十秒就把五个问题在脑子里过了一遍“这个功能为什么存在因为用户要导出报表。为什么用同步导出因为数据量小、操作简单。为什么现在做因为本周迭代刚好有空档。为什么只影响报表模块因为查过调用链了。为什么用现在的验证方案因为导出文件可以用自动化脚本比对。”这五个问题已经保底信息足够就不需要写任何纸质文档了。如果是复杂需求再把这些问法落实到文档里逐条展开。所以5 Why其实是一把“标尺”它帮你快速判断一个需求是大是小、是安全还是危险。越依赖“问过这个为什么”的团队对复杂任务的判断越敏锐反之团队写代码就像蒙眼走路走到哪倒在哪。4.4 与AI辅助写代码的关系为什么变成了新常态下的必修课这几年团队里越来越多同学在用AI辅助写代码热搜里也常见“AI写代码最强”“AI写代码规则设定”之类的讨论。很多人以为AI来了写代码的门槛变低了但我的实际感受恰好相反AI写得越快写代码前问“为什么”就越重要。AI可以帮你很快生成一段CRUD代码也能帮你补一个函数、写一条SQL但它不会主动替你想清楚“这个接口为什么会在这张表上做模糊查询”、“这个字段的分布情况会不会导致慢查询”更不会告诉你这个功能为什么存在、为什么用这种方案落地。如果你没有在指令里把“为什么”表达清楚AI生成的东西大概率是“代码正确但上下文缺失”的半成品。我团队里的用法是让AI写代码之前先让它基于需求生成一份“问题清单”把我们技术方案涉及的关键决策点全部列出来。比如“这张表的数据量预期是多少查询条件是否需要避免全表扫描同步还是异步是否需要幂等”然后把这些问题在提示词里说清楚AI才能产出真正有质量的东西。这也是为什么现在大家聊“提示词工程”聊得特别多提示词的本质其实就是把你心里的那五个“为什么”翻译给AI听。5. 后续的扩展思考从“写代码前”扩展到“整个研发链路”铁规如果只停留在“写代码前”作用仍然有限。我们团队在执行了一个季度之后把5 Why的思路进一步扩展到了整个研发链路。在需求阶段用5 Why判断真伪需求和优先级在技术设计阶段用5 Why审视方案取舍和潜在风险在编码阶段用5 Why做开工自检在Code Review阶段用5 Why做答辩在测试阶段用5 Why评估测试用例设计是否覆盖到了使用场景在上线阶段用5 Why制定回滚和监控方案。最明显的变化是团队每天的“突发救火”变少了。以前几乎每周都要为线上问题焦头烂额后来变成了一个月可能才一两次。这个数字变化的背后不是因为某一个人的技术能力突飞猛进而是“想清楚再做”变成了一种集体习惯。落到个人层面我现在无论是看代码还是写代码都已经离不开那几个“为什么”了。被领导质问的时候能用上它评审别人的代码时能用上它指导新人时能用上它就连自己在午休前快速浏览一段老代码时也会下意识地在心里问一句这段代码当初为什么要这样写如果答不上来我就知道自己该去翻历史记录了。最后再分享一张我们贴在工位旁边的小卡片。“先问5个为什么再写第一行代码”——这个习惯不一定保证你永远不犯错但能保证你犯的每一个错都是“有的放矢”的错事后都有复盘的价值。我还记得那次系统崩溃复盘结束时老张说了一句话“今天我们花四个小时问为什么是为了以后不再花一整个晚上填坑。”这句话我一直记到现在也一直在用。