一場小型產品發布事故是如何釀成的


問題描述

早上一到公司,接到運維部門同事報的一個高優先級問題工單,描述如下:

“報銷單號關聯單子的審批記錄沒有了,但財務已做帳,導致相關審批人員需要重新審批。”

在正規大型互聯網,數據丟失可算是嚴重級別為最高級0的問題了吧。

分析原因

這種問題從產品上線6個月前到現在都沒出現過,突然出現了,肯定是什么原因導致的。
事出一定有原因,找出原因是重中之重。數據丟失鐵定是由於在代碼中有刪除數據的行為。
於是優先鎖定所有有刪除操作的地方,由於整個項目倉儲層是Dapper來實現的,所以通過表關鍵詞全局搜索,根據肉眼逐條排查包含Delete的語句的方法,記錄下來作為嫌疑對象。於是從200多個搜索結果中,得到一組7個方法的嫌疑清單,接下來分兩手行動。

  • 主線1.日志中查找出蛛絲馬跡。看是否是在某種特殊情況下, 用戶非常規操作造成。由於系統有記錄所有操作的日志功能,但數據量無疑是巨大的,可以以時間為主線,根據單號,主鍵,嫌疑方法等關鍵詞來過濾記錄。
  • 主線2. 逐個代碼審查刪除邏輯前后上下文的相關代碼,看是否存在漏洞造成誤刪的情況。

經過幾小時的排查,得到的結果令人沮喪。

  • 關於日志,排查中發現日志有一些缺失,有一些行為數據並沒有記錄下來,而且記錄的數據有一些是不准確的,比如方法執行時間居然30000毫秒,實際上只有幾時毫秒。沒能從中找到關鍵信息。
  • 關於嫌疑清單,7處含刪除邏輯的方法中均有限制條件,所有行為沒有異常情況。

於是得出一下疑點:
疑點1. 日志為什么有錯誤?
疑點2. 誤刪邏輯並不存在於這7處,那問題會在哪里?

先說說疑點2的分支解決方案:
分支1. 由於這次報的錯誤在三個月前均沒有發現,在上周五發布的時候就出現了這個問題,所以可以懷疑是否是在這次發布造成的影響。根據錯誤數據產生的時間,推測位於某個發布節點的前后。
分支2. 查看數據庫系統的日志功能,操作系統日志,是否有記錄刪除行為。
分支3. 咨詢產品主要開發人員,程序功能上是否存在別處的刪除邏輯行為。
分支4. 嫌疑列表范圍不夠,要擴大排查范圍,逐個逐條排查關鍵詞相關的位置,大約200個地方。
分支5. 向用戶收集相關操作線索(操作行為較復雜),根據用戶填寫的數據,模擬用戶的操作過程,嘗試重現錯誤的發生。
分支6. 是否存在人為操作數據的情況,運維人員常常會幫用戶直接修改數據

上述解決方案涉及到角色包含DBA,開發,測試,運維,項目經理,客戶,用戶。 軟件工程中的含,客戶管理,項目管理,代碼審查,版本管理,UAT測試,發布規范,系統架構等。
這在大型項目中一定是一個大事件,幸運的事這個項目不大,實際使用用戶才2000人。

正如你們期待的,分支1~6 均未找到Root Cause。

  • 小公司的項目,追求速度,發布不規范,所以沒有記錄任何發布日志,在上線前也沒有系統的UAT測試,發布頻次高,修復速度快,有時候甚至一天發布2~3次,更改正式庫數據操作也比較頻繁。
  • 系統和數據庫系統自帶的日志功能並沒有精細化記錄所有數據的操作,只有一些關鍵數據,所以參考意義不大。
  • 產品開發人員只對自己做的功能有認知,對出現這個問題原因,他們也表示不理解
  • 所有相關信息篩查過,均為發現問題,所以才導致往下的排查 素手無策
  • 用戶對產品沒有開發人員熟悉,自己的操作也是界面上能看到的操作,所有操作都是正常 合理的,理論上不存在非常規行為。
  • 理論上不存在,在企業內部要但法律責任,開發,測試,運維人員沒有動機。
  • 模擬用戶操作
    所以,各方面壓力就來了,客戶的領導直接找到我們大Boss,大Boss來詢問具體情況,我們也如上述一一交代,尚未有可行解決方案。

妥協解決方案

數據丟失,一定是某個地方讓其丟失,正如我們學的哲學,這是事物的,不以人的意志為轉移的。

我們要做的僅僅是為了找出這個地方,那么除了監控所有行為,產生更精細化的日志,追蹤用戶所有操作,別無他法。
所以我給的方案是在所有刪除邏輯前后插入審計日志, 后續再次發現這個問題時 在跟蹤查詢。

另一個日志審計記錄不全的問題,是由於在框架底層設計時某次不經意將局部使用對象改為了全局靜態單例對象,導致數據和時間記錄的異常。
這屬於低級錯誤,不再贅述。 我們在改底層架構時一定要謹慎,謹慎,再謹慎。

轉折點

很多事情很難解釋,往往在你一籌莫展的時候,突然問題就自然而然解決了。

在第二天的UAT環境,不斷的模擬測試用戶操作的數據,測試日志,不經意間被一個開發人員看到。她指出“為什么審批歷史記錄中,每一項后跟着一個撤回按鈕,不是測試才會有么”。
瞬間理解了,為什么審批的記錄信息一次性丟失, 90%以上找到了問題點。
於是去審計日志表查詢撤回共計74條。排重后約30多條記錄被撤銷影響。
解釋一下:
這個測試功能是給測試人員和UAT人員使用的功能,我們產品被多家企業使用,在產品上除企業特殊業務功能外的其它功能都是一樣的。
所以會存在產品升級引發業務相關問題,這個問題是其中之一,只不過比較嚴重罷了。

之所以我沒有意識到這個問題是由於在平常工作時主要時間花費在實現核心功能,項目管理,程序架構上,反而忽略了對團隊的代碼審查
最終找到影響點:
后台代碼完全不可能通過表的關鍵詞找到,因為它調用了存儲過程... 萬萬沒想到。
產品開啟前,我們就規定不使用存儲過程,以確保各個數據庫的兼容性,便捷性。沒想到這里有一處調用了存儲過程,原因還是由於沒有審查代碼漏過了。

教訓

  1. 不能因為發布頻繁,就不做日志管理,版本管理,可以不像大公司有一個專門的配置管理人員,我們可以在關鍵點上做到即可。例如,寫發布日志,只需記錄關鍵點(時間/版本/功能點描述)
  2. 不能因為發布多就不做測試,至少要做到發布后各個功能的抽樣檢查,以最小的代價來確保功能不受影響。
  3. 后台鑒權代碼非常重要,尤其是增刪改行為,一定要有足夠的授權驗證和方法執行條件檢查,假如后台有權限驗證,即使前台功能放開了,后台也無法正常執行,那么這個事故也不可能發生。這在企業內部系統中往往是夠用就行,安全性方面太欠考慮了。
  4. 代碼審查必須要做,每天花少量時間過一下昨天的所有簽入,這樣在全局上就能意識到這里有這個功能,出現問題也可以第一時間聯想到。
  5. 日志功能要穩定齊全,否則缺少部分日志數據,對問題調查會帶來麻煩。
  6. 產品升級前的測試,還是務必要做的。
  7. 改底層架構時,要足夠充分的測試。

結束語

創業就像爬山系了根繩子,中間任何一處斷了,就掛了。成功的條件是所有條件都需要滿足,是充分不是必要。
這次的事故也是如此,所有的因素加一起(6個分支),才導致最終的發生。
雖然道理,我們都懂。然而身處不同的環境,面對的情況不同,事情不是由我們來決定的。
小公司看似不成章法,但是所做的事都是切實的解決了企業的各種業務問題,及時的,高效的。
重要的是挑關鍵的點,抓住就好,也不可能用大公司的那套來適應小公司。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM