記錄一個有意思的問題……
阿新 • • 發佈:2018-01-17
插入數據 暴露 dynamic ring 一個表 意義 發現 無法 操作
今天業務開發出現了一個有意思的問題:
一段操作邏輯裏,兩次update同一個表,如果兩次updated偶成功,則對另一個表進行一次insert操作
兩次update是用的同一個方法,傳入參數對象屬性值不同。
現象:
a.數據庫裏數據更新操作成功
b.insert操作,時而成功時而失敗。
c.如果從頭debug跟進每個處理邏輯,插入數據一定處理成功。
處理邏輯
private void deal(){
DataBO dataBO = new DataBO();
dataBO.setId(23);
dataBO.setXxx("XXX");
dataBo.setYyy ("YYY");
boolean result = update(dataBO);
if(!result)
return;
dataBO = new DataBO();
dataBO.setId(23);
dataBO.setOneStatus(0);
dataBO.setTwoStatus(0);
result = update(dataBO);
if(!result)
return;
//插入數據
insert();
}
update方法
public boolean update(DataBO dataBO){
return dataDAO.updateById(dataBO) > 0;
}
BO
public class DataBO{
private Long id;
private int isDeleted;
private int oneStatus;
private int twoStatus;
private String xxx;
private String yyy;
private Date gmtCreated;
private Date gmtModified;
}
mapper
<update id="updateById" parameterClass="DataBO" >
update data_table set gmt_modified = now()
<dynamic prepend="" >
<isNotEmpty prepend="," property="gmtCreated">
gmt_created = #gmtCreated#
</isNotEmpty>
<isNotEmpty prepend="," property="gmtModified">
gmt_modified = #gmtModified#
</isNotEmpty>
<isNotEmpty prepend="," property="isDeleted">
is_deleted = #isDeleted#
</isNotEmpty>
<isNotEmpty prepend="," property="xxx">
xxx = #xxx#
</isNotEmpty>
<isNotEmpty prepend="," property="yyy">
yyy = #yyy#
</isNotEmpty>
<isNotEmpty prepend="," property="oneStatus">
one_status = #oneStatus#
</isNotEmpty>
<isNotEmpty prepend="," property="twoStatus">
two_status = #twoStatus#
</isNotEmpty>
</dynamic>
where id = #id#
</update>·
分析定位
表象是,數據庫裏數據更新明明操作成功了,但插入失敗了。
Debug無法復現,就打印了些日誌來分析,結果是第二次更新沒有成功,影響條數為0
copy日誌中的sql去數據庫客戶端執行,操作成功:
update data_table set gmt_modified = now() ,one_status =0,two_status=0,where id = 23;
所以核心問題就是為什麽程序裏執行更新操作會時常失敗。
排查發現:
- 數據庫update操作,當原數據庫記錄數據與傳入參數沒有任何變化時,不執行操作,影響記錄數為0
- 傳入參數兩個int屬性,初始化時會被置為0,導致第二個update需要更新的字段都與數據庫記錄一致,
isNotEmpty
條件判斷無意義 - 成功失敗的關鍵,在於now()的取值,若兩次更新時間一樣,則所有參數一致,更新失敗。所以在客戶端操作更新成功,debug拉開了時間差異,也會更新成功
這樣一段邏輯,到處都是坑,但就是各種錯誤寫法/用法聚集一起,才露出了這種“大新聞”的表象,只要一個條件不符合,這個問題的復雜程度都要降低很多,更容易排查。
比如,屬性值類型不用int,或者檢查方式更嚴謹,或者沒有gmt_modified = now()
這個條件(哪怕是復制到客戶端測試的時候沒有這個條件,問題也都早就暴露出來了)……
記錄一個有意思的問題……