Mysql的行級鎖 -- 共享鎖和排他鎖

在已經開啓事務的前提下:
共享鎖
A用戶使用了共享鎖,B用戶可以使用共享鎖或者不用鎖能查詢到數據,但是使用排他鎖就會報錯
A更新數據,但是會一直在等待,假如1s後B也更新數據,這時就會陷入死鎖報錯退出。然後A就能更新成功了
排他鎖
A用戶使用了排他鎖,B用戶就使用排他鎖或者共享鎖來獲取數據,會一直等待中
A用戶更新數據並提交事務,此時B用戶用戶獲得鎖成功並查得數據


InnoDb的鎖的一些注意事項

1. 在不通過索引條件查詢的時候,InnoDB確實使用的是表鎖,而不是行鎖

像我們平常通過id查詢這個就是通過索引條件查詢,因爲一般來說id都會做爲主鍵,主鍵會創建索引
如果通過user_name來查詢這個就不是通過索引條件查詢,除非你給user_name加一個索引就可以

2. 由於MySQL的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現鎖衝突的。應用設計的時候要注意這一點。
3. 當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB都會使用行鎖來對數據加鎖。

行鎖與表鎖的區別:

行鎖顧名思義標識該條數據被鎖,無法被獲得鎖的操作更新或者訪問
表鎖表示整個表都無法被未獲得鎖的操作更新或者訪問

更深入瞭解可以看這個Innodb鎖機制


以下內容爲轉載

mysql鎖機制分爲表級鎖和行級鎖,
行級鎖中的共享鎖(select … lock in share mode)與排他鎖(select …for update)進行分享交流

共享鎖又稱爲讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務對於同一數據可以共享一把鎖,都能訪問到數據,但是隻能讀不能修改。

排他鎖又稱爲寫鎖,簡稱X鎖,顧名思義,排他鎖就是不能與其他所並存,如一個事務獲取了一個數據行的排他鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務是可以對數據就行讀取和修改。

對於共享鎖大家可能很好理解,就是多個事務只能讀數據不能改數據,對於排他鎖大家的理解可能就有些差別,我當初就犯了一個錯誤,以爲排他鎖鎖住一行數據後,其他事務就不能讀取和修改該行數據,其實不是這樣的。

排他鎖指的是一個事務在一行數據加上排他鎖後,其他事務不能再在其上加其他的鎖。mysql InnoDB引擎默認的修改數據語句,update,delete,insert都會自動給涉及到的數據加上排他鎖,select語句默認不會加任何鎖類型,如果加排他鎖可以使用select …for update語句,加共享鎖可以使用select … lock in share mode語句。

所以加過排他鎖的數據行在其他事務種是不能修改數據的,也不能通過for update和lock in share mode鎖的方式查詢數據,但可以直接通過select …from…查詢數據,因爲普通查詢沒有任何鎖機制。

說了這麼多,咱們來看下以下簡單的例子:

我們有如下測試數據

image

現在我們對id=1的數據行排他查詢,這裏會使用begin開啓事務,而不會看見我關閉事務,這樣做是用來測試,因爲提交事務或回滾事務就會釋放鎖。

打開一個查詢窗口

image

會查詢到一條數據,現在打開另一個查詢窗口,對同一數據分別使用排他查和共享鎖查詢兩種方式查詢

排他查

image

共享查

image

我們看到開了排他鎖查詢和共享鎖查詢都會處於阻塞狀態,因爲id=1的數據已經被加上了排他鎖,此處阻塞是等待排他鎖釋放。

如果我們直接使用以下查詢呢

image

我們看到是可以查詢到數據的。

我們再看一下一個事務獲取了共享鎖,在其他查詢中也只能加共享鎖或不加鎖。

image

image

image

我們看到是可以查詢數據的,但加排他鎖就查不到,因爲排他鎖與共享鎖不能存在同一數據上。

最後我們驗證下上面說的mysql InnoDb引擎中update,delete,insert語句自動加排他鎖的問題,

image

image

此時共享查詢處於阻塞,等待排它鎖的釋放,但是用普通查詢能查到數據,因爲沒用上鎖機制不與排他鎖互斥,但查到的數據是修改數據之前的老數據。

image

然後我們提交數據,釋放排他鎖看下修改後的數據,此時可用排他查,共享查和普通查詢, 因爲事務提交後該行數據釋放排他鎖,下面就只顯示普通查詢,其他的同學們自己去驗證。

image

image

可以看到結果與預期的一樣。

個人博客

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