Mariadb之顯式使用表鎖和行級鎖

1874發表於2020-06-27

  首先我們來看看mariadb的鎖定概念,所謂鎖就是當一個程式或事務在操作某一資源時,為了防止其他使用者或者程式或事務對其進行資源操作,導致資源搶佔而發生衝突,通常在A程式操作該資源時,會對該資源進行加鎖,實現多程式或多使用者操作同一資源時,不會發生衝突;通常情況鎖的型別分讀鎖和寫鎖,所謂讀鎖就是共享鎖,它可以實現多個讀操作共享;而寫鎖就是排它鎖,獨佔鎖,一旦加了寫鎖,其他使用者的讀寫操作將被阻塞,直到該寫鎖被釋放或者因超時而被釋放,在其他使用者進行的讀寫操作,此時就會被執行;對於鎖定範圍來講,它又可以分為,表鎖和行鎖,從字面意思就可以理解到,表鎖就是針對整張表所施加的鎖,而這種鎖定力度相當粗糙,併發相對就比較低,但是維持鎖狀態鎖消耗的成本資源就較小;對於行鎖來說,它針對的範圍就是行級別所施加的鎖,這種鎖的粒度就相對要精細,同時併發相對較高,但是維護鎖狀態消耗的成本資源就相對要大;對於mysql來講又鎖分為儲存引擎級別的鎖和mysql server級別的鎖,儲存引擎級別的鎖指的是對於何時施加鎖或者釋放鎖由儲存引擎自行決定;mysql server級別鎖指的是使用者使用命令可自行決定施加鎖或釋放鎖;簡單講就是允許使用者顯式請求加鎖或釋放鎖;顯式鎖就是使用者手動用命令施加的鎖,隱式鎖指的是由儲存引擎根據需要自行施加的鎖;對於innodb儲存引擎來講,它支援事務,行級鎖;而早期的MyISAM儲存引擎它不支援事務,對鎖的粒度是表級鎖,不支援行級鎖;

  顯示鎖的使用

  1)LOCK TABLES

    指令使用語法:

    LOCK TABLES  tbl_name  read|write, tbl_name read|write, ...

  示例:

  提示:以上語句表示對test_tb這張表施加讀鎖操作,這意味著其他使用者或程式都不能對該表進行寫的操作,只能讀,因為讀鎖上共享鎖;

  測試:對test_tb表進行寫操作,看看是否能夠寫進去?

  提示:從上面的提示,它告訴我們test_tb這張表施加了讀鎖,不允許更新;這說明施加讀鎖,對於寫的操作就不能進行;

  測試:對test_tb表進行讀操作,看看是否能夠進行呢?

  提示:可以看到加了讀鎖的表,對於讀操作上可以繼續進行的;

  測試:對test_tb表施加寫鎖

  提示:釋放鎖用unlock tables即可釋放剛才的讀鎖;

  測試:對test_tb進行寫操作,看看是否能夠進行?

  提示:在當前終端(加寫鎖所在終端)上是可以進行讀寫操作的;

  測試:在其他終端看看是否能夠對test_tb表進行讀寫操作呢?

  提示:從上面的截圖可以看到當我們重新啟動一個終端對test_tb進行寫操作,它一直處於阻塞狀態;

  提示:對於對操作也是同樣的效果;一直阻塞著;

  總結:對於施加讀鎖的表,是可以進行讀操作的,但是不能進行寫操作,包括當前終端也不能寫操作;對於施加寫鎖的表,在當前施加鎖的終端上是可以對其進行讀寫操作的,但是在別的終端讀寫操作都將阻塞;

  除了以上指令來對錶進行加鎖外,還可以使用 flush tables指令來加讀鎖,具體語法請看下面;

  FLUSH TABLES tbl_name,... [WITH READ LOCK];

  測試:加讀鎖

  提示:以上flush tables 只能加讀鎖,不能加寫鎖;

  行級鎖:SELECT cluase [FOR UPDATE | LOCK IN SHARE MODE]

  行級排它鎖

  提示:以上紅框中的內容就是給第一行加了一個排它鎖,這意味著該事務沒有提交,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排它鎖,但是獲取排它鎖的事務是可以對資料就行讀取和修改。

  提示:可以看到我們重新啟動一個事務,然後對第一行進行更新操作,語句就阻塞在哪裡了;說明行級排它鎖對其他事務來講是不允許對加鎖的行進行寫操作;預設情況updeate更新會預設加上排它鎖,因為對於第一行來講,已經有一個排它鎖了,所以其他事務就不能對其在加其他鎖;而對於select語句來講,它執行時預設會加任何鎖的,所以我們執行select語句是可以正常的檢視第一行資料;如果我們在select後面手動加鎖,它也會阻塞的;如下

  提示:從上面的截圖資訊可以看到,我們手動加上排它鎖,查詢語句也不會順利執行;從上面資訊還可以瞭解到,我們對第二行也沒法進行操作,這又是為什麼呢?

  提示:我們檢視test_tb這張表上的索引資訊,發現沒有索引,然後我們在上面建立了一個索引;建立索引時,需要把前面的事務提交了,才可建立成功,否則一直鎖在哪裡的;接下來我們在建立一個事務,把第一行加上排它鎖,然後在對第二行操作看看是否還會一直阻塞呢?

  提示:可以看到當我們建立就了索引後,再對第一行加鎖,然後更新第二行就可以正常更新了 ,對第一行還是處於阻塞狀態;這說明innodb儲存引擎的行級鎖的實現其實是依靠其對應的索引,所以如果操作的行並沒有用到索引,那麼用的還是表級鎖。施加行級排它鎖後,其他事務將不能對其在施加任何鎖;那麼對於獲取到排它鎖的是否能夠正常操作呢?

  提示:對於獲取到排它鎖的事務,是可以正常更新修改的;也可以給對應行施加其他鎖;

  行級共享鎖

  提示:以上紅框中的內容表示給第一行施加共享鎖,這意味著在其他事務鎖可以共享這把鎖看到資料,但是不能更新修改資料;

  測試:在當前事務中更新資料,看看是否可更新?

  提示:在當前事務中是可以正常修改資料的;也能正常檢視資料;

  在其他事務中修改資料,看看是否可修改?

  提示:可以看到在其他事務中,就不能對有共享鎖的行進行修改操作,但是可以正常讀;

  總結:innodb儲存引擎的行級鎖依賴索引,如果沒有索引,就相當於表級鎖;對於排它鎖來講,獲取到排它鎖的事務是可以正常修改更新以及加共享鎖,對於沒有獲取到排它鎖的事務,是不能夠對有鎖的行進行修改更新以及加鎖的操作;對於共享鎖來講,對於當前事務(加鎖操作的事務)是可以正常修改更新有鎖的行,對於其他事務,是不可修改和更新有鎖的行;

相關文章