前段时间,商城在做促销活动的时候,我们的测试人员也买了一些商品,但是时隔多天一直没有收到快递,很是纳闷。经过开发同学的确认,该订单的邮递地址为:北京市火星区xxx,电话号码15555555555,这显然不是一个合理的邮寄地址。由于之前确认过线上并不存在SQL注入的可能性,因此只可能是线上的正常流程影响了订单的邮寄地址。在Check线上流程的时候,发现一个巨大的bug,这个bug看似平淡无奇,但实际上影响范围很大。
这里我们简单说一下,商城建立的初期,只有添加用户常用地址的功能,并没有删除和更改地址的功能,也就是说,地址一旦被添加后,则这个地址的id、地址信息都是只读的、不变的,因而当时为了节约空间,之间在订单中引用了用户地址的id号,作为用户提交订单时地址的快照,也就是说,数据库表是这样的结构:
问题就出在这里!
随着商城的优化,产品MM觉得对于用户的常用地址,编辑和删除应该是正常的操作,而由于中间隔了大约一个月的时间,因此在添加此功能的时候,完全忘记了用户的订单是使用的是用户地址的id来关联的,这时就带来一个很大的问题:用户可能一时糊涂(或者新奇),把自己的地址改成一个并不存在的地址,这样实际上也就隐式的修改了订单的地址!这样的设计,当然是错误的。
知道了原因,也就知道了解决方案:那就是在生成订单的时候,并不是简单的保存地址的id,而应该记录当时地址的快照信息。为了尽量减少订单表的大小,专门抽出一个单独的表order_addr记录订单的地址信息。这样在查找订单信息时,不必要的地址信息不会拖慢整个订单表查询,而在需要查找地址信息时,只需简单的join查询即可。
现在的表实际上是这样的关联关系:
这样修改过后,用户对常用地址的修改,删除等都不会影响订单的状态了。
有时候看似很简单的问题,可能有着很多潜在的陷阱,这个问题也警示我们:越是简单的问题,越不能掉以轻心,全方位思考应该是我们做任何事情应该养成的良好习惯。