这个Bug,你是不是上次就没改好? 当项目经理(兼职产品)在钉钉上@我,风轻云淡地打出你提个事故报告吧,说明一下是修复了又重新复现,还是第一次时,我的脑子嗡的一下——心想完了,这锅怕是要砸我头上了。
看似美好的优化
首先,得交代下背景。
我们之前优化或者说重构了对账模块。
原方案: 实时查询订单相关的N张表,又慢又复杂还各种计算。
新方案: 我们定义规则,DBA团队每天T+1 + 实时把数据清洗到对账表里。我们只需要查这张干净的表就行。
这个架构升级,看起来很美好,性能上去了,代码也清晰了。
被现金退款干翻的现实
一切都很完美,直到上周,有商户反馈:对账数据不对!
我立刻去排查。
很快,技术问题定位了: 一个诡异的幽灵Bug!
商户通过微信/支付宝收款,这没问题。 但当这笔订单后续发生了现金退款时, 我们的系统,错误地把这笔现金退款的金额,记在了原始的微信/支付宝渠道上!
导致商户的线上渠道(微信/支付宝)的账面金额平白无故少了钱,跟他们实际提现的数据根本对不上! ,数据能对上才有鬼。
锅是怎么到我头上的?
技术问题不难定位。 难的是人的问题。
这个锅,为什么到我头上了? 因为真空!
流程真空: 这个模块当初压根就没测试!(不是QA没介入,是我们很早就已经没有测试了)
产品/验收真空: 负责这个模块的,是我们的项目经理...兼职的产品! 他自己都不记得当初的需求逻辑了!最要命的是,当初还是他自己验收通过的!
责任真空: DBA团队只负责清洗,他们不背业务逻辑的锅!
所以绕了一大圈,穿过流程、产品、DBA... 自然而然地,精准砸在了我这个开发身上。
那句必杀的提问
如果只是背锅,我也认了。裸奔纯靠自测和产品验收,出问题可不就是开发背嘛。
但杀人诛心的来了!
那个兼职PM(那个自己验收通过的PM!)@我:
@我,这个现金退款的问题,我好像有点印象,前段时间是不是出现过? 你提个事故报告吧,说明一下是复现了,还是第一次?
他是个天才! 这是必死局!
我如果回答是复现了:
翻译:你上次没修好!代码质量有问题!这锅你背死!
我如果回答是第一次:
翻译:你这次没考虑到!需求理解有问题!这锅你还是背死!
我怎么回答都是死!
最要命的是... 我的脑子里...确实有点印象... 我好像...真的...修复过...
老油条绝不相信记忆
在那一瞬间,我慌了。 但是作为一个小公司的老油条!
一定要明白永远不要相信你的记忆,尤其是在高压和甩锅现场! 你的记忆会欺骗你,它会根据当前的指控,伪造出合理的回忆!
我顶住压力,在钉钉上回了一句:
稍等,我查下上下文,这个逻辑有点复杂。
(翻译:别催,老子在找证据!)
我立刻去查!查的不是代码,是工单! 因为我们修改线上数据需要提交工单。
果不其然!被我找到了!
证据一: 前几个月,我确实处理过!但我是直接修改了对应的对账表数据!
然后,我马上去查Git Log,查那几天的前后分支提交情况!
证据二(Git Log): 一根毛的代码提交记录都没有!
真相大白! 我的记忆偏差了:我只记得我处理过,却忘了我是用数据订正(Data Patch)的土炮方式处理的!
我根本没改过代码!
釜底抽薪:从Bug到逻辑缺陷
证据链完整了。 我该怎么回?
A选项(菜鸟死法):
@PM 我查了,我没改代码,我是改的数据库。
(翻译:锅还是我的,只是我上次偷懒了,治标不治本。 -> 死路一条!)
B选项:
结合现在证据推理还原当时情况。 做过这种通过数据清洗进行优化的同学们都懂: 标准操作是:如果是逻辑问题,应该是去修改源表(比如订单表),然后重新触发DBA的清洗逻辑,让数据自动刷新到对账表。
我为什么反着干? 因为当时重跑清洗逻辑没用!
唯一的推论: DBA团队的清洗逻辑本身就是错的!
清洗逻辑处理不了微信付现金退款这个场景,所以源表数据对了也没用! 我才会去强行修改最终的对账表!
这个锅,完美地甩出去了!
降低影响:私信PM,搞定收工
证据链完整了。 但汇报是艺术!
背景分析:
PM很忙,他没空去核实DBA的细节。 他信任我的排查。 他只想要结论和立刻修复!
核心思路:
- 这不是我的代码Bug,这是DBA的数据逻辑缺陷!
- 这不是修复,这是历史遗留的临时数据订正!
- 这不是事故,这是二期优化需求!
我立刻私信PM(最好不要在群里公开处刑DBA):
@PM 查清楚了,这个事比想象的复杂点,我得跟你同步下。
确实之前出现过,是历史遗留问题。
我查了工单
和Git Log(截图附上),上次我没改代码,是跑了数据订正,直接改的对账表。 (摆证据,证明我没修复失误。)
我之所以直接改数据,是因为我发现源表数据是对的,但DBA的清洗逻辑(V1版)本身就处理不了现金退款这个场景。我改源表重跑也没用。
所以,这不是我代码复现了,而是DBA的清洗逻辑一直还没改。加上这个场景商户用的比较少,所以暴露了。
5.(给方案)要彻底解决,DBA那边的清洗规则也要调整。我先紧急修复一下保证线上没问题,但这事得排个二期优化,不然下次还得爆。
事故报告我来写,我会写成历史数据逻辑缺陷导致,你看OK不?
小公司的生存法则
一场必死局,就这么被我乾坤大挪移了。
锅, 从我的代码Bug,变成了DBA的逻辑缺陷/项目的二期需求。
责任, 从我的修复失误,变成了PM的需求优先级。
我, 从背锅侠,变成了主动推进项目、逻辑缜密的积极贡献者!
最后,总结几条小公司的生存法则:
永远不要相信你的高压记忆,马上去查证据(工单、Git Log、聊天记录、需求文档)。
你的操作就是证据:你如何修复的(改源表 vs 改结果表),反过来证明了锅在哪里!
永远不要在真空流程下干活(没有测试、兼职产品、自己验收)。干了,就要留下所有的书面证据!
学会重新定义问题:把你的Bug(点),上升到DBA的逻辑(面);把修复,偷换概念成升级!
永远不要自己背决策锅。把决策权还给产品经理,他才是背得动需求锅的人!
私信永远比公屏好用!