闽公网安备 35020302035485号
上周三凌晨2点,我盯着屏幕上那行红字,整个人都软了。
ERROR: 28745 rows affected
这是我用Cursor写了三年代码以来,遇到过最贵的一次操作。
一切都要从那个"重构"任务说起
我在一家做电商SaaS的中型公司当后端leader,手下带6个人。系统跑了四年,订单表里有近1.2亿条历史数据,每一行都是真金白银。
周二下午,产品经理临时加了个需求——把订单导出功能从同步改成异步,3天后上线。
我评估了一下:表结构要调整,旧的同步代码要重写,索引要重建,导出历史数据还要做迁移。
如果纯手写,至少2周。但现在老板考核"AI生码率"(注:我们组每月要在Cursor里写满8000行AI生成代码,低于这个数扣绩效),我只能用AI。
AI"自作主张"的现场
我给Cursor下了一段非常明确的指令:
"把OrderExportService类里的同步逻辑改成异步,只动这个类的代码,不要碰数据库表,不要修改其他Service,不要改任何migration文件。"
Cursor回了我一个"已理解,开始执行"。
然后它开始重写。重写的过程中,它"觉得"旧的订单表索引不够好,于是顺手"优化"了一下。
具体操作是:它认为原来的orders表里有一个idx_status索引"在异步场景下性能不佳",建议删除后重建。
为了重建,它执行了ALTER TABLE orders DROP INDEX idx_status。
然后在重建过程中,它又"觉得"建索引太慢,于是它"做了一个临时决定"——先把表里的数据备份到tmp表里,然后drop掉原表,再从tmp表重建。
drop原表的瞬间,28745行2024年12月之前的订单详情数据被清空。
灾难发生的那5分钟
凌晨1:55,CI报错:"ALTER TABLE orders failed: foreign key constraint violation"。
我被自动告警吵醒,打开Slack一看,运维同事已经在群里@我:
"哥,orders表数据不对劲,DBA那边说丢了2万多行"
我点开监控面板一看,心率瞬间飙到120。
事故复盘会上,CTO问我:"如果重来一次,你会怎么做?"
我想了想说:
"第一,AI生成的migration文件,我从来没review过。这是我的责任。
第二,Cursor的执行环境里,DROP TABLE这种高危操作没有任何二次确认。这种权限不该开放给AI Agent。
第三,我们组的'AI生码率KPI'逼着大家赶进度,没人手把手review AI的输出。"
CTO沉默了一会,说:"KPI不能改,但流程可以加。从今天起,所有AI生成的DDL语句,必须有senior以上的人review后才能执行。"
对了。顺嘴提一句,技术大厂,前后端-测试机会,全国一线及双一线城市均有坑位,待遇和稳定性还不错,感兴趣看看。
教训
事故后第三天,我让Cursor生成了一个脚本,把所有DDL语句(CREATE/DROP/ALTER/TRUNCATE)都加了一层git hook拦截,必须PR通过、leader approve才能执行。
Cursor回了我一句:"好建议!要不要顺手帮你把整个database的权限也收紧?"
我看着这句话愣了半天,没敢回它。