問題:
在高併發的系統下,對數據庫進行更行時,如果沒有防重機制做攔截,就會導致數據被更新多次,從而影響更新後程序的後續操作。
解決方案:
方案一:
方案詳情:加鎖查詢攔截,在更新前,加鎖(分佈式系統用分佈式鎖、也可用數據庫鎖等),查詢需要更新的數據是否存在且未被 更新,根據查詢結果做更新操作,更新後釋放鎖;
適用情況:對數據需要進行多次更新,或多箇中間狀態都可以對數據進行操作;
方案優勢:保證數據更新的一致性;
方案缺點:系統性能消耗大,鎖機制影響系統的效率;
僞代碼示例:
//本示例以分佈式系統爲例,單系統下直接使用Lock或synchronized鎖即可
eg:
// 用redis加鎖
redis.set(key, value);
// 查詢要更新的數據
int result = select * from table where 條件;
// 更新操作
if(result == 1){
//判斷數據是否已經被更新
if(未被更行){
//更新
update table set XXX=x2 where 條件;
}
}
// 釋放鎖
redis.del(key);
方案二(推薦):
方案詳情:數據庫層面攔截,直接在更新數據時帶狀態更新數據,根據更新後成功與否做後續操作;
適用情況:明確知道更新數據前或後的狀態,且不會在更新時多次發生狀態變化,保證前後一致性;
方案優勢:簡單,保證數據更新的一致性,且對效率影響較小;
方案缺點:系統性能消耗大,鎖機制影響系統的效率;
僞代碼示例:
// 數據庫層的sql語句限制即可
int result = update table set 更新的內容 where 原數據的內容 != 更新的內容;
// 更新成功
if(result == 1){
// 執行更新成功後的操作
}else{
// 執行更新失敗後的操作
}
原因:
高併發的情況下,多個請求對同一條數據進行更新操作,易導致數據被多次更新,影響數據庫的正確性;
相關知識點:
1.sql語句;
2.分佈式鎖;
代碼示例:
如解決方案中的僞代碼示例。