首先我們來看看mariadb的鎖定概念,所謂鎖就是當一個進程或事務在操作某一資源時,為了防止其他用戶或者進程或事務對其進行資源操作,導致資源搶占而發生衝突,通常在A進程操作該資源時,會對該資源進行加鎖,實現多進程或多用戶操作同一資源時,不會發生衝突;通常情況鎖的類型分讀鎖和寫鎖,所謂讀鎖就是共用鎖... ...
首先我們來看看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存儲引擎的行級鎖依賴索引,如果沒有索引,就相當於表級鎖;對於排它鎖來講,獲取到排它鎖的事務是可以正常修改更新以及加共用鎖,對於沒有獲取到排它鎖的事務,是不能夠對有鎖的行進行修改更新以及加鎖的操作;對於共用鎖來講,對於當前事務(加鎖操作的事務)是可以正常修改更新有鎖的行,對於其他事務,是不可修改和更新有鎖的行;