mysql樂觀鎖與悲觀鎖

聲明,此處文章主要根據這個整理,具體可以參考這篇博客。

https://www.jianshu.com/p/f5ff017db62a

此處介紹幾個概念
mysql中innodb引擎支持事務和行鎖,mysiam引擎不支持事務,只支持表鎖。

只有在事務中的操作,纔有鎖。

InnoDB行鎖是通過給索引上的索引項加鎖來實現的
這一點MySQL與Oracle不同,後者是通過在數據塊中對相應數據行加鎖來實現的。
InnoDB這種行鎖實現特點意味着:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!

排它鎖,悲觀鎖,即只加鎖後,除了不能更改數據外,還不能查詢數據
使用如下:
在事務中,增加for update作爲查詢,顯式調用排它鎖
select * from tab_no_index where id = 1 for update;

樂觀鎖,指不能更改數據,但是允許查詢
一般在事務中的操作,沒有for update,都是樂觀鎖。

悲觀鎖,樂觀鎖是一種概念,不是範圍。行鎖,表鎖才表示範圍,不要混淆兩者。
可以存在悲觀行所,樂觀行鎖等。

以下轉自他人博客內容:
以下爲對於秒殺商品的一個加鎖例子(java代碼,數據庫加鎖)
這裏寫圖片描述

多線程併發情況下,會存在超賣的可能。箭頭所指處有併發問題,兩個線程進來,同時查到有,然後都執行更新邏輯,導致賣了兩件(其實只有1件)

悲觀鎖

查詢的時候帶上for update,導致其他事務無法更新也無法查詢。其他並發進來的線程,只能等待,效率低。
public boolean updateStock(Long productId){
//先鎖定商品庫存記錄
ProductStock product = query(“SELECT * FROM tb_product_stock WHERE product_id=#{productId} FOR UPDATE”, productId);
if (product.getNumber() > 0) {
int updateCnt = update(“UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId}”, productId);
if(updateCnt > 0){ //更新庫存成功
return true;
}
}
return false;
}

樂觀鎖

增加了版本號的條件,只有版本號一致,才能更新,否則更新失敗。
public boolean updateStock(Long productId){
int updateCnt = 0;
while (updateCnt == 0) {
ProductStock product = query(“SELECT * FROM tb_product_stock WHERE product_id=#{productId}”, productId);
if (product.getNumber() > 0) {
updateCnt = update(“UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId} AND version=#{version}”, productId, product.getNumber());
if(updateCnt > 0){ //更新庫存成功
return true;
}
} else { //賣完啦
return false;
}
}
return false;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章