比如update table1 set filed1 = field1 - 1 where field - 1 >= 0 and id = 1,請問大家這條陳述句高并發會有風險嗎。
例如出現這種情況,filed1 = 1時,兩條陳述句同時判斷field1 =1,這時候都會做減法 1-1一次,0-1一次。
我覺得這條陳述句的成敗就在于讀的時候是不是排他鎖行或者表,但是沒有專業的思路
uj5u.com熱心網友回復:
不用擔心, 會排隊,當兩個相同KEY的update 陳述句, 是排它行鎖 .
可以用兩個客戶端, 交叉執行以下進行測驗:
START TRANSACTION
update table1 set filed1 = field1 - 1 where field - 1 >= 0 and id = 1
COMMIT
uj5u.com熱心網友回復:
最上邊的陳述句有點問題,where field應該是field1, 還是從新寫一個沒有歧義的update mytable set myfiled = myfield - 1 where myfield - 1 >= 0 and id = 1
uj5u.com熱心網友回復:
謝謝,雖然update會加鎖,但是會不會有可能內部執行的是讀值和賦值兩個程序呢,就像這樣的
START TRANSACTION
1、select myfield from mytable where id = 1 ; 得要myfield的值是比如是1,計算出結果myfiled - 1 = 0
2、update mytable set myfield = 0 where 0>=0 and id = 1;
COMMIT
這時候如果同時并發讀,讀出來的A執行1,讀到值為1,B讀到值為1,A加排它鎖執行2 update mytable set myfield = 0 where 0>=0 and id = 1 釋放排它鎖,B加鎖執行2 update mytable set myfield = 0 where 0>=0 and id = 1 釋放排它鎖。
這樣無形中對資料庫執行了兩遍 update mytable set myfield = 0 where 0>=0 and id = 1,雖然結果對于這一行是不影響的。
但是如果事務中還有3、insert into。。。。。。 ,這句根據2回傳的成功行數去操作,兩個都發生了1行變動,那么就生成兩條insert,其實就想要一條的。
uj5u.com熱心網友回復:
您擔心的問題,應該不會存在,建議修改一下陳述句,會讓直行效率有所提高。先用id和field增加索引,然后修改陳述句如下:
update table1 set filed1 = field1 - 1 where field >= 1 and id = 1 ;
uj5u.com熱心網友回復:
謝謝,我今天打算實踐一下,看看現象,雖然不能搞定里邊的原理,但是如果出現錯誤就證明不行。
uj5u.com熱心網友回復:
經過mybatis+spring注解事務寫的代碼,和用jmeter并發測驗(原諒我沒有建立專門的表測驗,只用了sys_user表的為int型別的user_sex性別欄位作為測驗欄位),結果顯示,當user_sex減到0時,對應的insert的條數不多不少等于目標欄位的條數,所以現象上說明這條陳述句是沒有并發風險的,原理上請大神們深入的解釋下吧。我之所以提出這個問題,原因是前兩天去面試一家知名電商企業,討論到減庫存的問題時,我說我用這種做法,他說這樣在超高并發下會出現問題,他建議用樂觀鎖方式,將時間戳直接拼到where條件中,但是我認為樂觀鎖在高并發時會造成大量的where條件不成立。
@Transactional
public int updateSexCount(User user) {
//并發減庫存
int a = userDao.updateSexCount(user);
if (a >0) {
//如果上條成功,這里就增加一條資料
shopService.insert(new Shop());
}
return a;
}
<update id="updateSexCount" parameterType="xxxx">
update sys_user set user_sex=user_sex - 1 where id = #{id} and user_sex - 1 >=0
</update>
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/68507.html
標籤:MySQL
下一篇:主鍵唯一性,添加或替換記錄
