1. 程式人生 > >mysql的鎖機制

mysql的鎖機制

自動啟動 升級問題 共存 技術 med lec 自動 style log

MySQL有三種鎖的級別:頁級、表級、行級。

MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);

BDB存儲引擎采用的是頁面鎖(page-levellocking),但也支持表級鎖;

InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認情況下是采用行級鎖。

MySQL這3種鎖的特性可大致歸納如下:

表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,並發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,並發度也最高。
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,並發度一般。

InnoDB 是行鎖、不存在鎖升級問題、也就是、鎖住 1 行和鎖住 1 千萬行的開銷是一樣

表級鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨占寫鎖(Table Write Lock)。鎖模式的兼容性:

對MyISAM表的讀操作,不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;
對MyISAM表的寫操作,則會阻塞其他用戶對同一表的讀和寫操作;

MyISAM在執行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執行更新操作(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖,這個過程並不需要用戶幹預,因此,用戶一般不需要直接用LOCK TABLE命令給MyISAM表顯式加鎖。

查看鎖的情況:

show status like ‘table%‘;

Table_locks_immediate:產生表級鎖定的次數;
Table_locks_waited:出現表級鎖定爭用而發生等待的次數;

產生的鎖定次數是自動啟動之後開始計算的。

等待時間過長,表示鎖的爭用情況比較嚴重

行級鎖定同樣分為兩種類型,共享鎖和排他鎖,而在鎖定機制的實現過程中為了讓行級鎖定和表級鎖定共存,InnoDB也同樣使用了意向鎖(表級鎖定)的概念,也就有了意向共享鎖和意向排他鎖這兩種。

技術分享

如果一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之,如果兩者不兼容,該事務就要等待鎖釋放。意向鎖是innodb自動添加的

InnoDB行鎖是通過給索引上的索引項加鎖來實現的,只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖

(1)在不通過索引條件查詢的時候,InnoDB確實使用的是表鎖,而不是行鎖。
(2)由於MySQL的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現鎖沖突的。
(3)當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB都會使用行鎖來對數據加鎖。
(4)即便在條件中使用了索引字段,但是否使用索引來檢索數據是由MySQL通過判斷不同執行計劃的代價來決定的,如果MySQL認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB將使用表鎖,而不是行鎖。因此,在分析鎖沖突時,別忘了檢查SQL的執行計劃,以確認是否真正使用了索引。

查看鎖的情況
show status like ‘InnoDB_row_lock%‘;
InnoDB 的行級鎖定狀態變量不僅記錄了鎖定等待次數,還記錄了鎖定總時長,每次平均時長,以及最大時長,此外還有一個非累積狀態量顯示了當前正在等待鎖定的等待數量。
InnoDB_row_lock_current_waits:當前正在等待鎖定的數量;
InnoDB_row_lock_time:從系統啟動到現在鎖定總時間長度;
InnoDB_row_lock_time_avg:每次等待所花平均時間;
InnoDB_row_lock_time_max:從系統啟動到現在等待最常的一次所花的時間;
InnoDB_row_lock_waits:系統啟動後到現在總共等待的次數;
對於這5個狀態變量,比較重要的主要是InnoDB_row_lock_time_avg(等待平均時長),InnoDB_row_lock_waits(等待總次數)以及InnoDB_row_lock_time(等待總時長)這三項。尤其是當等待次數很高,而且每次等待時長也不小的時候,我們就需要分析系統中為什麽會有如此多的等待,然後根據分析結果著手指定優化計劃。

mysql的鎖機制