mysql的樂觀鎖與悲觀鎖

樂觀鎖

老是認爲不會產生併發問題,每次去取數據的時候總認爲不會有其餘線程對數據進行修改,所以不會上鎖,可是在更新時會判斷其餘線程在這以前有沒有對數據進行修改,通常會使用版本號機制或CAS操做實現。mysql

例如:sql

有這樣一個表:數據庫

每次更新時update在條件後再附加一個時間爲條件:併發

update user_info set password='somelog' where username='somelog' and time='2018-07-11';

  

由於若是併發操做,同一刻查詢的時間同樣,可是先插入時將時間更改,那麼後更新的操做就不能進行,由於time的值被前一個操做更改了。spa

這就是樂觀鎖的實現原理,更新時附加一個版本號。線程

 

悲觀鎖

老是假設最壞的狀況,每次取數據時都認爲其餘線程會修改,因此都會加鎖(讀鎖、寫鎖、行鎖等),當其餘線程想要訪問數據時,都須要阻塞掛起。能夠依靠數據庫實現,如行鎖、讀鎖和寫鎖等,都是在操做以前加鎖,在Java中,synchronized的思想也是悲觀鎖。
注:要使用數據庫的悲觀鎖,咱們必須關閉mysql數據庫的自動提交屬性,由於MySQL默認使用autocommit模式,也就是說,當你執行一個更新操做後,MySQL會馬上將結果進行提交。code

悲觀鎖分爲兩種:共享鎖和排它鎖blog

共享鎖是其它事務能夠讀可是不能寫
排他鎖是隻有本身得事務有權限對此數據進行讀寫事務

 

SQL寫法
共享鎖(S):it

SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;

排他鎖(X):

SELECT * FROM table_name WHERE ... FOR UPDATE;

加鎖必須先開啓事務:begin;(開啓事務)->加鎖、操做->commit;(提交事務,歸還鎖)

 

加鎖分爲顯式加鎖與隱式加鎖,上面的寫法是顯式加鎖。mysql在執行insert、update會自動加鎖,mysql對select卻不會加鎖。

 例如:

不加鎖

select * from data where username=‘somelog’;

加排它鎖:

select * from data where username=‘somelog’ for update;

若是一個事務加了排它鎖以後,另一個事務不加鎖的select也能夠查詢到數據

以上能夠看出,鎖不是針對事務的,排它鎖只有一把,誰拿了誰就能夠進行更新,可是沒有拿到鎖的事務只要在select不加上排它鎖也能夠查詢到數據。

相關文章
相關標籤/搜索