1. 程式人生 > >mysql的悲觀和樂觀鎖分析

mysql的悲觀和樂觀鎖分析

我們在操作資料庫的時候,可能會由於併發問題而引起的資料的不一致性(資料衝突),這個時候就有了鎖!!!

樂觀鎖顧明思議,想法很樂觀,在更新資料時,認為這波操作不會導致衝突,別的sql也不會對此操作進行更改,所以我線更新資料,等待提交的時候再去判斷是否衝突。

樂觀鎖需要我們自己去實現,資料庫設計上,需要給一個狀態的欄位,比如version,我們需要更新一條資料,那就先去查詢這條資料得到裡面的version,然後進行更新操作,等到我們提交更新的時候,判斷查詢出來的version是否與之前的version一致,一致則更新, 同時,version+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};


悲觀鎖:

一般很少用到,因為會造成訪問資料庫的時間較長,併發性不好,處理少一點的併發還行。

悲觀鎖從資料處理更新開始,就將資料鎖住了,更新完後才釋放。因此鎖的消耗的時間更長。


共享鎖其實是悲觀鎖的一種延伸,其實悲觀鎖,資料庫已經實現了,要想使用共享鎖,執行語句後面加上lock in share mode就代表對某些資源加上共享鎖了。其它執行語句也可以進行加共享鎖。共享鎖也就是讀鎖。指的是對於多個不同的事務,對同一個資源共享同一個鎖,可以都有這個鎖的鑰匙,都能開開。

比如說select * from papapa where id=1 lock in share mode;

在另一邊執行,update set name='1' where id=1;

此時就會報錯。。

[SQL]update city set name="666" where id ="1";[Err] 1205 - Lock wait timeout exceeded; try restarting transaction

在上一條記錄還沒有commit之前,這條id=1的記錄被鎖住了,只有在上一個事務釋放掉鎖後才能進行操作,或用共享鎖才能對此資料進行操作。


排他鎖:寫鎖,對於同一個資源只能有一把鎖,不能再加其它的封鎖。字面理解就是排除其它的鎖。排斥。

在需要執行的語句後面加上for update就可以了。