1、分類
MySQL的鎖機制不一樣的存儲引擎支持不一樣的鎖機制,分爲表級鎖、行級鎖、頁面鎖。MyISAM和MEMORY存儲引擎採用的是表級鎖(table-level locking);BDB存儲引擎採用的是頁面鎖(page-level locking),但也支持表級鎖;InnoDB存儲引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認狀況下是採用行級鎖mysql
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常 算法
2、表級鎖
MySQL的表級鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)。 sql
對MyISAM表的讀操做,不會阻塞其餘用戶對同一表的讀請求,但會阻塞對同一表的寫請求;對 MyISAM表的寫操做,則會阻塞其餘用戶對同一表的讀和寫操做。數據庫
MyISAM在執行查詢語句(SELECT)前,會自動給涉及的全部表加讀鎖,在執行更新操做 (UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖,這個過程並不須要用戶干預,所以,用戶通常不須要直接用LOCK TABLE命令給MyISAM表顯式加鎖。微信
3、行級鎖
InnoDB與MyISAM的最大不一樣有兩點:一是支持事務(TRANSACTION);二是採用了行級鎖。架構
行級鎖也支持讀鎖和寫鎖兩類。併發
一、如何加鎖?
mysql InnoDB引擎默認的修改數據語句:update,delete,insert都會自動給涉及到的數據加上排他鎖,select語句默認不會加任何鎖類型,若是加排他鎖可使用select …for update語句,加共享鎖可使用select … lock in share mode語句。因此加過排他鎖的數據行在其餘事務種是不能修改數據的,也不能經過for update和lock in share mode鎖的方式查詢數據,但能夠直接經過select …from…查詢數據,由於普通查詢沒有任何鎖機制。app
二、實現原理
InnoDB行鎖是經過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不一樣,後者是經過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特色意味着:只有經過索引條件檢索數據,並請求共享或排他鎖時,InnoDB才使用行級鎖,不然,InnoDB將使用表鎖! 高併發
四、鎖的算法
record lock:單個記錄的鎖。性能
gap lock:間隙鎖,鎖定一個範圍,不包括記錄自己
next-key lock:gap lock+record lock
默認隔離級別(可重複讀)下,默認加的是next-key lock(爲了解決幻讀問題),當索引中含有惟一屬性時(惟一索引,主鍵索引),會降級爲record lock。
在讀已提交隔離級別下,加的是record lock
一、例1
如今表z,有a,b兩列,a是主鍵,全表只有一個主鍵索引。如今記錄以下:(1,1)(3,1)(5,3)(7,6)(10,8)
select * from z where b=3 for update
由於b沒有索引,因此走得是全表掃描。有由於加鎖是經過對索引加鎖實現,由於沒有走索引,全部會鎖整個表,也就是表鎖
二、例2
如今表z,有a,b兩列,a是主鍵索引,b創建輔助索引。如今記錄以下:(1,1)(3,1)(5,3)(7,6)(10,8)
select * from z where a=3 for update
主鍵索引加的鎖是record lock,對記錄(3,1)加鎖
select * from z where b=3 for update
由於鎖是經過對索引加鎖實現的。因此這裏須要對主鍵索引和輔助索引加鎖,主鍵索引加的鎖會由next-key鎖退化成是record lock,輔助索引加的鎖是next-key lock,鎖定範圍是(1,3)、三、(3,6)
5、select的幾種類型
1、快照讀
讀取的是快照版本,也就是歷史版本。普通的SELECT就是快照讀
2、當前讀
讀取的是最新版本。
UPDATE、DELETE、INSERT、SELECT ... LOCK IN SHARE MODE、SELECT ... FOR UPDATE是當前讀。
默認的可重複讀隔離級別,使用的是快照讀
讀已提交使用的是當前讀
3、一致性非鎖定讀
實現原理是經過MVCC機制實現,若是讀取的行正處於update或delete中,讀操做不會去等待行上X鎖的釋放,而是去讀取行的快照數據。
MVCC,多版本併發控制技術。在 InnoDB 中,在每一行記錄的後面增長兩個隱藏列,記錄建立版本號和刪除版本號。經過版本號和行鎖,從而提升數據庫系統併發性能。
一致性非鎖定讀能夠極大的提升併發性能
不一樣的事務隔離級別,讀取的快照版本是有差異的
讀已提交隔離級別,老是讀取最新的快照版本。可能會產生幻讀
可重複讀隔離級別,老是讀取事務開始後第一次讀取的快照版本。能夠避免幻讀的產生
4、一致性鎖定讀
默認配置下,採用可重複讀的隔離級別,讀取數據採起的是一致性非鎖定讀。
可是某些場景下須要對讀取操做加鎖來保證嚴格的數據一致性,這時候能夠顯式的對讀取的記錄進行加鎖:
select *** for update(對讀取記錄加X鎖)
給索引記錄加鎖,這種狀況下跟UPDATE的加鎖狀況是同樣的
select *** lock in share model(對讀取記錄加S鎖)
給記錄假設共享鎖,這樣一來的話,其它事務只能讀不能修改,直到當前事務提交
做者:leon66666
出處:http://www.cnblogs.com/wangzhongqiu/
若是你以爲文章不錯,文末的贊 👍 又回來啦,記得給我「點贊」和「在看」哦~
本文分享自微信公衆號 - JAVA高級架構(gaojijiagou)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。