MySQL複習筆記(05):MySQL表級鎖和行級鎖

郭藝賓發表於2020-09-26

一:概述 

相對其他資料庫而言,MySQL的鎖機制比較簡單,其最顯著的特點是不同的儲存引擎支援不同的鎖機制。比如,MyISAM和MEMORY儲存引擎採用的是表級鎖(table-level locking);InnoDB儲存引擎既支援行級鎖( row-level locking),也支援表級鎖,但預設情況下是採用行級鎖。

MySQL主要的兩種鎖的特性可大致歸納如下:

 表級鎖: 開銷小,加鎖快;不會出現死鎖(因為MyISAM會一次性獲得SQL所需的全部鎖);鎖定粒度大,發生鎖衝突的概率最高,併發度最低。

 行級鎖: 開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。

考慮上述特點,表級鎖使用與併發性不高,以查詢為主,少量更新的應用,比如小型的web應用;而行級鎖適用於高併發環境下,對事務完整性要求較高的系統,如線上事務處理系統。

 

二:MyISAM鎖細述

(1). 鎖模式

MySQL的表級鎖有兩種模式: 表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)。

(2).  如何加鎖

當MyISAM在執行查詢語句時,會自動給涉及到表加讀鎖,在執行更新操作時,會加寫鎖。當然使用者也可以用LOCK TABLE 去顯式的加鎖。顯式的加鎖一般是應用於:需要在一個時間點實現多個表的一致性讀取,不然的話,可能讀第一個表時,其他表由於還沒進行讀操作,沒有自動加鎖,可能資料會發生改變。並且顯示加鎖後只能訪問加鎖的表,不能訪問其他表。

(3). 併發插入

MyISAM儲存引擎有個系統變數 concurrent_insert,專門用來控制併發插入的行為,可以取 0 , 1 , 2。

0表示不允許併發插入,1表示表中間沒有刪除的行時可以在表末尾插入,2表示總是可以插入。

一般如果對併發要求比較高的情況下,可以設定為2,總是可以插入,然後定期在資料庫空閒時間對錶進行optimize。

(4). 鎖的排程

需要注意的是,其中讀操作不會阻塞其他使用者對同一表的讀請求,但會阻塞對同一表的寫請求;並且當寫鎖和讀鎖同時被申請時,優先獲得寫鎖,這也這正是表級鎖發生鎖衝突概率最高的原因,因為寫鎖可能會一直阻塞讀鎖,所以不適合有大量寫操作的環境下工作。這一問題可以通過設定low-priority-updates這一啟動引數來降低寫的優先順序。

雖然寫鎖優先於讀鎖獲取,但是長時間的查詢操作也可能會讓寫操作餓死,所以儘量避免一條SQL語句執行所有的查詢,應該進行必要的分解。

 

三:InnoDB鎖細述

由於InnoDB支援事務,並預設是使用行級鎖,所以InnoDB的鎖問題和MyISAM鎖問題還是有蠻大差別的。

(1). 鎖模式

共享鎖(S)和排他鎖(X),分別類似於MyISAM的讀鎖和寫鎖。對於 UPDATE、 DELETE 和 INSERT 語句,InnoDB會自動給涉及資料集加排他鎖(X);對於普通 SELECT 語句,InnoDB不會加任何鎖。

(2). 如何加鎖

可以顯式的加鎖,用lock in share mode 顯式的加共享鎖,用 for update 顯式的加排他鎖。

需要注意的是,如果執行緒A加了共享鎖後,執行緒B對同一個表加了共享鎖,那麼兩個執行緒需要進行更新操作時會產生死鎖。所以,進行更新操作時最好加排他鎖。

(3). InnoDB行鎖的實現方式——索引加鎖

這一點與Oracle不同,所以這也意味著(重要):1. 只有通過索引條件檢索資料時,InnoDB才會使用行級鎖,否則會使用表級鎖。 2. 即使是訪問不同行的記錄,如果使用的是相同的索引鍵,會發生鎖衝突。 3. 如果資料表建有多個索引時,可以通過不同的索引鎖定不同的行。

(4). 間隙鎖

InnoDB支援事務,為了滿足隔離級別的要求,InnoDB有個間隙鎖,當使用範圍查詢時,InnoDB會給滿足key範圍要求,但實際並不存在的記錄加鎖。例如:select * from user where id > 100 for updata 會給ID>100的記錄加排他鎖,滿足這個範圍,但不存在的記錄,會加間隙鎖,這樣可以避免幻讀,避免讀取的時候插入滿足條件的記錄。

(5). 隔離級別與鎖

一般來說,隔離級別越高,加鎖就越嚴格。這樣,產生鎖衝突的概率就越大,一般實際應用中,通過優化應用邏輯,選用 可提交讀 級別就夠了。對於一些確實需要更高隔離級別的事務,再通過set session transaction isolation level+"級別" 來動態改變滿足需求。

 

四:死鎖

MyISAM是沒有死鎖問題的,因為他會一次性獲得所有的鎖。InnoDB發生死鎖後一般能自動檢測到,並使一個事務釋放鎖並回退,另一個事務獲得鎖,繼續完成事務。

在應用中,可以通過如下方式來儘可能的避免死鎖:

(1) 如果不同的程式會併發的存取多個表,應儘量約定以相同的順序來訪問表,這樣可以大大降低產生死鎖的機會。

(2) 在程式以批量方式處理資料時,如果事先對資料排序,保證每個執行緒按固定的順序來處理記錄,也可以大大的降低出現死鎖的可能。

 

 

 

原文連結:https://www.cnblogs.com/zhanht/p/5431273.html

相關文章