mysql之innodb引擎之lock鎖

目錄

鎖的類型

行鎖

意向鎖

事務中的讀

1.鎖定讀:

2.非鎖定讀

鎖的算法

鎖超時

死鎖

鎖的表


鎖的類型

mysql鎖一般有兩種類型,一種是latch,該鎖是mysql程序的線程鎖,快速釋放,相當於java裏面的syn.還有一種是lock,這種鎖是針對innodb事務的,分爲行鎖和表鎖.

行鎖

行鎖分爲S鎖和X鎖,S鎖是共享鎖,X鎖是排他鎖.如下圖

S 共享 事務讀某行
X 排他 事務修改某行

它們的兼容性,S鎖之間兼容,只要有X鎖就不兼容。如下

  S X
S
X

舉個例子,如果有一個事務針對某行啓動了一個共享鎖S,那麼另一個事務也希望啓動共享鎖S要讀改行,那是暢通無阻的,但是如果另一個事務希望啓動X鎖去修改,那麼會被阻塞,直到S鎖釋放。

意向鎖

行鎖是細粒度地鎖。在添加行鎖之前,爲了效率,還要添加粗粒度的鎖-意向鎖,代表着我將要加哪一塊數據鎖了。mysql的意向鎖比較簡單,就是表級別的,如下:

IS 意向共享 事務將要進一步對數據加S鎖
IX 意向排他 事務將要進一步對數據加X鎖

 

他們之間的兼容性如下:

  IS IX S X
IS Y Y Y N
IX Y Y N N
S Y N Y N
X N N N N

事務中的讀

1.鎖定讀:

由於事務具有隔離性,所以事務內讀取數據有可能不是最新的。那麼如何在事務裏每次都能夠讀取到最新的數據呢?其實依據上面的知識就可以,

這需要了解lock in share mode和for update的用法,其中lock in share mode開啓了S鎖,for update開啓了X鎖。

大概如下sql語句在事務中開啓了S鎖:

select name from user where id = 1 lock in share mode

那麼由於兼容性問題,不管是lock in share mode還是for update,在遇到其他X鎖時,都會被阻塞,直到其他X鎖釋放,便獲取到了最新的數據,並且給改行加上S/X鎖。

那麼這就是所謂的一致性鎖定讀。讀的就是最新的。

2.非鎖定讀

在面對事務中普通的讀,讀出來的又是什麼樣的呢?

這個要看事務的隔離級別了。

如果隔離級別是repatable,這是innodb的默認隔離級別,讀出來的是當前事務開啓時的快照。所以即使有其他事務修改,依然讀的是老數據。

如果隔離級別 是read commited,讀出來的是所有事務裏面最新提交的快照。以至於這能產生幻讀。

 

鎖的算法

innodb鎖的算法主要有三種:

record lock行鎖,這是一種基礎算法

gap  lock間隙鎖,這是一種基礎算法,跟索引息息相關的

next-key lock mysql使用的就是這種算法,結合record和gap的鎖。

 

這個我明白的不多,先舉例子說明下gap鎖吧:

如果某個索引key有 1 3 5 9 四個索引值。

gap會分區間(0,1)(1,3)(3,5)(5,9)(9,...)

注意區間是小括號,都不包括區間點。

如果此時要鎖定3,gap鎖其實不會去鎖定3,而是會鎖定(1,3)這個區間,是區間點前面那個區間,注意不包括3這個區間點.

但next-key是升級版,如果要鎖定3,nextkey會鎖定(1,3】和(3,5),這相當於包括了3以及前後兩個區間,這鎖了一大片區域。我們知道這一大片區域實際上是不存在的,是數據庫缺少的記錄,如果要加鎖,那就只能是爲了insert語句,那麼gap的目的就呼之欲出了,就是爲了數據插入的串行化。

另外,如果索引是唯一索引,next-key會降級爲record lock,不再加區間,而是隻有該行。

 

鎖超時

加鎖是有時間限制的,如果超時了就釋放掉,也可以設置超時回滾。

innodb_lcok_wait_timeout=60  動態
innodb_rollback_on_timeout=OFF 靜態

死鎖

怎麼產生死鎖?如下AB兩個操作

A:

begin;

select * from user where id = 1 for update

B:

begin;

select * from user where id = 2 for update

select * from user where id = 1 for update //B被鎖

A:

select * from user where id = 2 for update //A被鎖

通過上面有超時時間,我們可以知道即使是死鎖,到了超時時間就自動釋放了,其實並不影響什麼,但是在併發裏,如果什麼都不做的話會嚴重影響性能。所以innodb就做了一個自動檢測死鎖的機制,一旦發生死鎖,立即檢測到並報異常,且必然回滾。

innodb檢測死鎖的機制是採用環形檢測

 

鎖的表

怎麼排查鎖,很好的是,innodb下有專門的表存放鎖:

information_schema.INNODB_TRX

information_schema.INNODB_LOCKS

information_schema.INNODB_LOCK_WAITS

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