博客1:
根本決解辦法只有一個:隊列,別的說的沒有用:https://www.cnblogs.com/sheseido/p/5038562.html
博客2:https://www.cnblogs.com/laoyeye/p/8097684.html
1、使用版本號實現樂觀鎖
版本號的實現方式有兩種,一個是數據版本機制,一個是時間戳機制。具體如下。
下單操作包括3步驟:
1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根據商品信息生成訂單
3.修改商品status爲2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
2、使用條件限制實現樂觀鎖
UPDATE t_goods
SET num = num - #{buyNum}
WHERE
id = #{id}
AND num - #{buyNum} >= 0
AND STATUS = 1
博客3:https://www.cnblogs.com/ssskkk/p/8673374.html
問題引入
當事務的隔離級別是REPEATABLE_READ情況下:當前事務不能select到併發事務中已經提交的事務。
當事務的隔離級別是READ COMMITTED情況下:當前事務能select到併發事務中已經提交的事務。
Mysql默認的事務隔離級別爲repeatable_read :https://www.cnblogs.com/kangshuai/p/5735374.html
讀:在一個事物裏面的select語句 不會受到其他事務(不管其他事務有沒有commit)的影響。
寫:對一條記錄而言,一個事務一旦update一條記錄,其他事務只能等待這個事務commit才能update那條記錄。
樂觀鎖處理併發的原理 重點
1)一個事物中的select語句可能不會收到其他事物的影響,也就是可能查不到其他併發中未提交的事物(即使提交了 如果是REPEATABLE_READ也查不到)。所以兩個事物共同執行時產生了併發的衝突。
2)雖然這個被併發的字段通過select查不出來,但是在where條件語句中 這個字段會受到其他事物的影響 。所以可以利用這點 可以讀到併發事物影響的數據 ,從而做出判斷,防止併發。
所以可用下面方式處理(利用樂觀鎖處理事物的併發)
數據庫增加一個鎖的處理列(版本號),查詢的時候多查一個版本號, update的時候 where條件附加一個版本號條件並且更新時候並且把版本號+1,處理流程
1)select num,version from table;
2)update table set num=num-1 ,version =version+1 where condition=? version=#{version}
3)Query OK, 1 rows affected (0.04 sec) | 注意:1 rows affected
update的時候 where條件附加一個版本號條件並且更新時候並且把版本號+1: update table set num=num-1 ,version =version+1 where condition=? version=#{version}
如果出現了查詢時候的版本號和where條件的版本號不一致 說明其他事物併發影響到了版本號 version,此時update語句的影響行數(Query OK, 1 rows affected (0.04 sec))是0 然後做異常處理。()