當前位置:成語大全網 - 書法字典 - java如何在Mysql數據庫上實現行鎖(Java代碼實現數據庫鎖)

java如何在Mysql數據庫上實現行鎖(Java代碼實現數據庫鎖)

這裏舉個例子來說明。

場景如下:

用戶帳戶中有余額。當交易發生時,余額需要實時更新。如果這裏出現並發問題,就會造成用戶余額和實際交易的不壹致,這對公司和客戶都是非常危險的。

那麽如何避免:

網上查後,有兩種方式:

1,使用悲觀鎖

當需要更改余額時,通過代碼為當前需要更新的記錄在事務中設置forupdate行鎖,然後開始正常的查詢和更新操作。

這樣交易完成後才能操作其他交易。

當然要特別註意。如果您使用Spring的事務註釋,您需要配置它:

class="org..jdbc.datasource。

在指定代碼處添加交易註釋。

@

@覆蓋

publicboolean(LonguserId,BigDecimalamount)

投擲{

longtime =系統。();

//獲取記錄上的鎖

UserBalancebalance=。getLock(userId);

logger . info("[lock]start . time:{ } ",time);

if(null==balance){

thrownew(

。ERRORCODE_BALANCE_NOTEXIST," uselbalancesinotexist ");

}

booleanresult=。(余額,金額);

longtimeEnd=System。();

LOGGER.info("[lock]end.time:{} ",time end);

返回結果;

}

實際測試可以有效控制MyBatis中的鎖定模式,但在大並發的情況下可能會出現性能問題。

select * from user _ balance where id = # { id,jdbcType = BIGINT } forupdate

]]

2.使用樂觀鎖定

這種方法也可以解決場景中描述的問題(我覺得更適合不頻繁的操作):

設計表格時,會添加壹個版本(版本控制字段)。每次需要更新余額時,先獲取對象。更新時,根據版本和id進行更新。如果更新次數為0,則版本已經更改。

您需要如下重復更新操作:sql腳本

update user _ balancesetBalance = # { balance,jdbcType=DECIMAL},Version = Version 1其中Id=#{id,jdbcType=BIGINT}和Version=#{version,JDBC type = BIGINT }

這是壹種不使用數據庫鎖的方法,解決方案也很巧妙。當然,在大量並發的情況下,壹次推演需要重復多次才能成功,還是有不足之處的。不知道有沒有更好的辦法。