簡體   English   中英

檢查和更新表中的記錄時潛在的並發問題

[英]Potential concurrency issue while checking and updating a record in table

就是這種情況

成員必須兌換令牌才能訪問(解鎖)給定項目。 相關的數據庫表是:

表格1

Table MEMBER_BALANCE: MEMBER_ID, TOKEN_BALANCE

表2

Table UNLOCKED_ITEM: MEMBER_ID, DATE_UNLOCKED, ITEM_ID

我需要執行的檢查或約束是

  1. 當用戶嘗試解鎖商品時,TOKEN_BALANCE必須> 0,並且
  2. 用戶之前未解鎖相同的物品。

我的直覺是在MemberService.java中編寫一個簡單的方法:

@Transactional
public void unlockItem(Member member, Item item){
    memberBalanceDAO.decrementBalance(member);
    itemDAO.unlockItem(member, item);
}

我已經通過在UNLOCKED_ITEM表上的MEMBER_ID / ITEM_ID對上添加unique約束來處理第二個要求。

我認為,我唯一需要照顧的是,用戶試圖同時解鎖許多物品,而未滿足TOKEN_BALANCE要求。 例如, TOKEN_BALANCE為1,但是用戶單擊以同時虛擬地解鎖兩個項目。

下面是我的MemberBalanceDAO.decrementBalance方法:

@Transactional
public void decrementBalance(Member member) {
    MemberBalance memberBalance = this.findMemberBalance(member);
    if (memberBalance.getTokens() >= 1) {
        memberBalance.setTokens(memberBalance.getTokens() - 1);
        this.save(memberBalance);
    } else {
        throw new SomeCustomRTException("No balance");
    }
}

我認為這不會保護我免受TOKEN_BALANCE = 1個用例的影響。 我擔心同時有多個解鎖請求。 如果余額為1,那么我可以同時調用兩次decrementBalance()並將余額都提交為0,但是也可以成功調用兩次itemDAO.unlockItem(...) ,對嗎?

我應該如何實施呢? 我應該將服務級別方法的事務設置isolation = Isolation.SERIALIZABLE嗎? 還是有一種更清潔/更好的方式來解決這個問題?

我寧願建議您在member_balance表中引入version列。 請參閱文檔樂觀鎖定

如前所述,您無法修改架構; 您可以使用無版本的樂觀鎖,如此處所述

或者,您可能想要進行悲觀鎖定,如此處所述 然后,您可以修改方法decrementBalance() ,以在那里獲取成員余額,請不要使用findMemberBalance() 例如,

@Transactional
public void decrementBalance(Member member) {
    MemberBalance memberBalance = entityManager.find(
        MemberBalance.class, member.id, LockModeType.PESSIMISTIC_WRITE,             
        Collections.singletonMap( "javax.persistence.lock.timeout", 200 ) //If not supported, the Hibernate dialect ignores this query hint.
    );
    if (memberBalance.getTokens() >= 1) {
        memberBalance.setTokens(memberBalance.getTokens() - 1);
        this.save(memberBalance);
    } else {
        throw new SomeCustomRTException("No balance");
    }
}

注意:它可能無法按原樣工作; 只是為您提供一些提示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM