不可能每天都是好日子,有了不順心的日子,好日子纔會閃閃發亮。mysql
對於行鎖和表鎖的含義區別,在面試中應該是高頻出現的,咱們應該對MySQL中的鎖有一個系統的認識,更詳細的須要自行查閱資料,本篇爲歸納性的總結回答。面試
MySQL經常使用引擎有MyISAM和InnoDB,而InnoDB是mysql默認的引擎。MyISAM不支持行鎖,而InnoDB支持行鎖和表鎖。sql
如何加鎖? 併發
MyISAM在執行查詢語句(SELECT)前,會自動給涉及的全部表加讀鎖,在執行更新操做(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖,這個過程並不須要用戶干預,所以用戶通常不須要直接用LOCK TABLE命令給MyISAM表顯式加鎖。線程
顯式加鎖:設計
上共享鎖(讀鎖)的寫法:lock in share mode
,例如:code
select math from zje where math>60 lock in share mode;
上排它鎖(寫鎖)的寫法:for update
,例如:索引
select math from zje where math >60 for update;
不會出現死鎖,發生鎖衝突概率高,併發低。進程
MyISAM在執行查詢語句(select)前,會自動給涉及的全部表加讀鎖,在執行增刪改操做前,會自動給涉及的表加寫鎖。事務
MySQL的表級鎖有兩種模式:
讀鎖會阻塞寫,寫鎖會阻塞讀和寫
MyISAM不適合作寫爲主表的引擎,由於寫鎖後,其它線程不能作任何操做,大量的更新會使查詢很可貴到鎖,從而形成永遠阻塞
會出現死鎖,發生鎖衝突概率低,併發高。
在MySQL的InnoDB引擎支持行鎖,與Oracle不一樣,MySQL的行鎖是經過索引加載的,也就是說,行鎖是加在索引響應的行上的,要是對應的SQL語句沒有走索引,則會全表掃描,行鎖則沒法實現,取而代之的是表鎖,此時其它事務沒法對當前表進行更新或插入操做。
CREATE TABLE `user` ( `name` VARCHAR(32) DEFAULT NULL, `count` INT(11) DEFAULT NULL, `id` INT(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 -- 這裏,咱們建一個user表,主鍵爲id -- A經過主鍵執行插入操做,但事務未提交 update user set count=10 where id=1; -- B在此時也執行更新操做 update user set count=10 where id=2; -- 因爲是經過主鍵選中的,爲行級鎖,A和B操做的不是同一行,B執行的操做是能夠執行的 -- A經過name執行插入操做,但事務未提交 update user set count=10 where name='xxx'; -- B在此時也執行更新操做 update user set count=10 where id=2; -- 因爲是經過非主鍵或索引選中的,升級爲爲表級鎖, -- B則沒法對該表進行更新或插入操做,只有當A提交事務後,B纔會成功執行
若是在一條select語句後加上for update,則查詢到的數據會被加上一條排它鎖,其它事務能夠讀取,但不能進行更新和插入操做
-- A用戶對id=1的記錄進行加鎖 select * from user where id=1 for update; -- B用戶沒法對該記錄進行操做 update user set count=10 where id=1; -- A用戶commit之後則B用戶能夠對該記錄進行操做
行鎖的實現須要注意:
行鎖場景:
A用戶消費,service層先查詢該用戶的帳戶餘額,若餘額足夠,則進行後續的扣款操做;這種狀況查詢的時候應該對該記錄進行加鎖。
不然,B用戶在A用戶查詢後消費前先一步將A用戶帳號上的錢轉走,而此時A用戶已經進行了用戶餘額是否足夠的判斷,則可能會出現餘額已經不足但卻扣款成功的狀況。
爲了不此狀況,須要在A用戶操做該記錄的時候進行for update加鎖
當咱們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內並不存在的記錄,叫作間隙
InnoDB也會對這個"間隙"加鎖,這種鎖機制就是所謂的間隙鎖
-- 用戶A update user set count=8 where id>2 and id<6 -- 用戶B update user set count=10 where id=5;
若是用戶A在進行了上述操做後,事務還未提交,則B沒法對2~6之間的記錄進行更新或插入記錄,會阻塞,當A將事務提交後,B的更新操做會執行。