數據庫字段未更新

場景

  • 內推過來的用戶,賬號狀態爲未激活,只有當用戶通過手機走註冊流程,才激活賬號(正常狀態)

發現問題原因

  • 新需求:
需要對剛註冊用用戶實時打標(涉及業務知識可忽略),之前發MQ邏輯是在完成註冊時發,這裏的註冊包括賬號是未激活狀態的註冊。
考慮到這樣做不合理,所以將發MQ消息放在用戶註冊時才處理。
  • 修改後測試
由於註冊需要發送驗證碼後才能調用手機註冊接口,想到麻煩,將代碼推送到測試環境驗證,結果第一個手機從未激活到激活狀態正常;但當第二個未激活手機註冊時,發現數據庫還是未激活狀態
又測試同一個手機號也是一樣的問題
結果在線上測試問題一致,未激活到激活時,賬號狀態未更新

問題分析

  • ORM層使用mybatis-plus(3.0.2)
  • 最先想到可能是plus版本問題,升級到最新版本(3.3.1) 問題依然存在
// 最初通過如下修改狀態
User user = new User();
user.setId(123);
user.setStatus(0);
user.updateById();
/**
 * 因爲通過設置狀態爲0,plus不會封裝條件(status = 0)
 * 之後通過本地測試,未激活到激活流程,測試OK(但這裏是單元測試,只運行一次)。測試環境第一次運行都是OK的,至於原因可能是mybatis-plus對查詢做了緩存(僅猜測,沒深究)
 * 又嘗試過使用對象的 user.saveOrUpdate userManger.insertOrUpdate 等原始方法,就連手寫SQL,都是同樣問題
 **/
 user.saveOrUpdate();
 userManger.insertOrUpdate();
 userManger.updateInactivated(Integer id, Map<String, String> options);
  • 嘗試加sql打印日誌 參見配置
  • 增加配置後,依然沒有輸出SQL(如果在這一層深究,可以提前一半時間解決),然後懷疑是數據庫原因…
  • 因爲剛好這段時間DBA升級MySQL版本到 5.7.29-32-log
    在這裏插入圖片描述
  • 賬號狀態字段配置 非空,默認值0
    在這裏插入圖片描述
  • 猜測可能是由於默認值引起的
默認值0,剛好是我要設置的值
那就在代碼層面臨時使用新值替換賬號狀態爲正常情況,之前0表示賬號正常,現在將4也作爲賬號正常測試
到測試環境後,第一次也是正常的,後續次數測試問題依舊存在
  • 取消數據庫賬號狀態默認值,設置可爲空
問題依舊
  • 後來想到註冊之後立馬登錄,會構造登錄會話,寫入最後登錄IP,時間等
// 公共登錄方法很少修改,沒有想到是這個方法的問題
// 公共登錄方法有這麼一個邏輯
User user = userManager.getById(id);
user.setLastLoginIp("127.255.255.255");
...
user.updateById();

  • 打印日誌 – 設置狀態後,在從庫取出賬號狀態,一路都是0(正常)
  • 在修改最後登錄IP時(userManager.getById(id)),打印日誌狀態不是0(問題根源在此)
  • 將這裏getById修改爲 User user = new User(); user.setId(123); 即可

問題解決

  • 底層通過get、select等方法,走從庫查詢,insert、update、delete方法走主庫修改,主從同步存在一定延遲
  • 這裏涉及到主從配置 參照mybatis-plus多數據源配置
  • 如果能將SQL輸出的問題進行到底,問題解決節省一大半時間
  • 在家測試,連VPN巨慢,後天在公司分析下沒有輸出SQL的原因
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章