Java如何?對Mysql資料庫的行鎖

來源:互聯網
上載者:User

標籤:

情境如下:    使用者賬戶有餘額,當發生交易時,需要即時更新喻額。這裡如果發生並發問題,那麼會造成使用者餘額和實際交易的不一致,這對公司和客戶來說都是很危險的。那麼如何避免:    網上查了下,有以下兩種方法:    1、使用悲觀鎖            當需要變更餘額時,通過代碼在事務中對當前需要更新的記錄設定for update行鎖,然後開始正常的查詢和更新操作            這樣,其他的事務只能等待該事務完成後方可操作            當然要特別注意,如果使用了Spring的事務註解,需要配置一下:
    <!-- (交易管理)transaction manager, use JtaTransactionManager for global tx -->      <bean id="transactionManager"          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">          <property name="dataSource" ref="dataSource" />      </bean>    <!-- 使用annotation定義事務 -->     <tx:annotation-driven transaction-manager="transactionManager" />

 在指定代碼處添加事務註解

@Transactional    @Override    public boolean increaseBalanceByLock(Long userId, BigDecimal amount)        throws ValidateException {        long time = System.currentTimeMillis();        //擷取對記錄的鎖定        UserBalance balance = userBalanceDao.getLock(userId);        LOGGER.info("[lock] start. time: {}", time);        if (null == balance) {            throw new ValidateException(                ValidateErrorCode.ERRORCODE_BALANCE_NOTEXIST,                "user balance is not exist");        }        boolean result = userBalanceDao.increaseBalanceByLock(balance, amount);        long timeEnd = System.currentTimeMillis();        LOGGER.info("[lock] end. time: {}", timeEnd);        return result;    }

MyBatis中的鎖定方式,實際測試該方法確實可以有效控制,不過在大並發量的情況下,可能會有效能問題吧

  <select id="getLock" resultMap="BaseResultMap" parameterType="java.lang.Long">        <![CDATA[            select * from user_balance where id=#{id,jdbcType=BIGINT} for update;        ]]>    </select>

 

    2、使用樂觀鎖            這個方法也同樣可以解決情境中描述的問題(我認為比較適合并不頻繁的操作):            設計表的時候增加一個version(版本控制欄位),每次需要更新喻額的時候,先擷取對象,update的時候根據version和id為條件去更新,如果更新回來的數量為0,說明version已經變更            需要重複一次更新操作,如下:sql指令碼            
update user_balance set Balance = #{balance,jdbcType=DECIMAL},Version = Version+1 where Id = #{id,jdbcType=BIGINT} and Version = #{version,jdbcType=BIGINT}

 這是一種不使用資料庫鎖的方法,解決方式也很巧妙。當然,在大量並發的情況下,一次扣款需要重複多次的操作才能成功,還是有不足之處的。不知道還有沒有更好的方法。

Java如何?對Mysql資料庫的行鎖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.