前段時間,商城在做促銷活動的時候,我們的測試人員也買了一些商品,但是時隔多天一直沒有收到快遞,很是納悶。經過開發同學的確認,該訂單的郵遞地址為:北京市火星區xxx,電話號碼15555555555,這顯然不是一個合理的郵寄地址。由於之前確認過線上並不存在SQL注入的可能性,因此只可能是線上的正常流程影響了訂單的郵寄地址。在Check線上流程的時候,發現一個巨大的bug,這個bug看似平淡無奇,但實際上影響范圍很大。
這裡我們簡單說一下,商城建立的初期,只有添加用戶常用地址的功能,並沒有刪除和更改地址的功能,也就是說,地址一旦被添加後,則這個地址的id、地址信息都是只讀的、不變的,因而當時為了節約空間,直接在訂單中引用了用戶地址的id號,作為用戶提交訂單時地址的快照,也就是說,數據庫表是這樣的結構:
問題就出在這裡!
隨著商城的優化,產品MM覺得對於用戶的常用地址,編輯和刪除應該是正常的操作,而由於中間隔了大約一個月的時間,因此在添加此功能的時候,完全忘記了用戶的訂單是使用的是用戶地址的id來關聯的,這時就帶來一個很大的問題:用戶可能一時糊塗(或者新奇),把自己的地址改成一個並不存在的地址,這樣實際上也就隱式的修改了訂單的地址!這樣的設計,當然是錯誤的。
知道了原因,也就知道了解決方案:那就是在生成訂單的時候,並不是簡單的保存地址的id,而應該記錄當時地址的快照信息。為了盡量減少訂單表的大小,專門抽出一個單獨的表order_addr記錄訂單的地址信息。這樣在查找訂單信息時,不必要的地址信息不會拖慢整個訂單表查詢,而在需要查找地址信息時,只需簡單的join查詢即可。
現在的表實際上是這樣的關聯關系:
這樣修改過後,用戶對常用地址的修改,刪除等都不會影響訂單的狀態了。
有時候看似很簡單的問題,可能有著很多潛在的陷阱,這個問題也警示我們:越是簡單的問題,越不能掉以輕心,全方位思考應該是我們做任何事情應該養成的良好習慣。