MySQL學習筆記(五):MySQL表級鎖和行級鎖

一:概述web

相對其餘數據庫而言,MySQL的鎖機制比較簡單,其最顯著的特色是不一樣的存儲引擎支持不一樣的鎖機制。好比,MyISAM和MEMORY存儲引擎採用的是表級鎖(table-level locking);InnoDB存儲引擎既支持行級鎖( row-level locking),也支持表級鎖,但默認狀況下是採用行級鎖。數據庫

MySQL主要的兩種鎖的特性可大體概括以下:
 表級鎖: 開銷小,加鎖快;不會出現死鎖(由於MyISAM會一次性得到SQL所需的所有鎖);鎖定粒度大,發生鎖衝突的機率最高,併發度最低。
 行級鎖: 開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。

session

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

 

二:MyISAM鎖細述高併發

(1). 鎖模式優化

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

(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) 在程序以批量方式處理數據時,若是事先對數據排序,保證每一個線程按固定的順序來處理記錄,也能夠大大的下降出現死鎖的可能。

相關文章
相關標籤/搜索