行級鎖定是目前各大資料庫管理軟體所實現的鎖定顆粒度最小的,所以發生鎖定資源爭用的概率也最小,能夠給予應用程式盡可能大的併發處理能力而提高一些需要高併發應用系統的整體效能。1.什麼叫做悲觀鎖呢?但是由於鎖定資源的顆粒度很小,所以每次獲取鎖和釋放鎖消耗的資源也更多,帶來的消耗自然也就更大了。此外,行級鎖定也最容易發生死鎖。
1.1 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,先把坑佔了,防止被人搶用2.如何在程式中加入行鎖呢?1.2 先上鎖,在更新資料,完成後釋放鎖
1.3 適合多寫和寫衝突比較多的場景
2.1 開啟資料庫事務
2.2 在資料庫事務鎖定中操作行
select
* from t where id=? *
*for update*
*
select 語句後面加入了for update 關鍵字會等待行鎖釋放後在返回查詢結果集,併發執行緒進行資料更新的時候遇到for update 關鍵字就會進行 阻塞 等待 直到行鎖釋放
2.3 在事務中對庫存、金額字段進行扣減,然後進行資料更新
update t set number=? where id=?
2.4 提交事務,釋放行鎖
優點:unsigned 是表示無符號資料型別,非負數穩定可靠,不會出現超賣現象
缺點:1.需要查詢和重新計算,效能差,鎖等待阻塞
2.鎖堵塞等待會導致客戶端延遲或者超時
3.事務重試會增加網路和系統的開銷
1.將庫存欄位設為無符號整型
create table red_envelope_goods
( id int(11
) unsigned primary key not null auto_increment,
num int(11
) unsigned ,
money decimal(10
,3) unsigned
) engine=innodb default charset=utf8;
樂觀鎖假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測
樂觀鎖的實現方式:
使用資料版本(version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加乙個版本標識,一般是通過為資料庫表增加乙個數字型別的樂觀鎖「version」
欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料
1.假設資料不會被他人修改,自己操作時驗證一哈資料的版本case 語句2 先比較在更新
3適合寫入比較少的場景
2.where 語句
超賣現象及解決
本專案的超賣類似於電商的秒殺超賣現象 1.不同使用者在讀請求的時候,發現商品庫存足夠,然後同時發起請求,進行秒殺操作,減庫存,導致庫存減為負數。2.同乙個使用者在有庫存的時候,連續發出多個請求,兩個請求同時存在,於是生成多個訂單。對於第一種超賣現象 1 最簡單的方法,更新資料庫減庫存的時候,進行庫存...
庫存超賣的解決方案
update sku info set kc kc 1 where sku id and kc 0 在高併發下,多人搶同一庫存,由於資料庫讀寫可以並行執行的原因,會導致修改庫存時,庫存不足出現超賣。悲觀鎖解決 在select加乙個行鎖,與更新庫存操作互斥,保證查詢庫存時,庫存不被修改 在查詢和更新庫...
mysql 樂觀鎖 超賣 秒殺超賣解決方案
方案一 redis事務處理 multi 我們可以使用redis中的監聽 watch 方法,去監聽庫存數量,一旦庫存數量在其他客戶端發生改變,後續操作則會失敗。watch key1 key2 監聽key1 key2有沒有變化,如果有變,則事務取消 方案二 redis分布式鎖 分布式鎖確保只有乙個執行緒...