MySQL學習筆記5---MySQL 鎖機制
阿新 • • 發佈:2020-11-22
8、MySQL 鎖機制
8.1、概述
鎖的分類
從資料操作的型別(讀、寫)分
- 讀鎖(共享鎖):針對同一份資料,多個讀操作可以同時進行而不會互相影響
- 寫鎖(排它鎖):當前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖。
從對資料操作的顆粒度
- 表鎖
- 行鎖
8.2、表鎖
特點:偏向MyISAM儲存引擎,開銷小,加鎖快,無死鎖,鎖定粒度大,發生鎖衝突的概率最高,併發最低。
8.2.1、讀鎖
create table mylock ( id int not null primary key auto_increment, name varchar(20) default '' ) engine myisam; insert into mylock(name) values('a'); insert into mylock(name) values('b'); insert into mylock(name) values('c'); insert into mylock(name) values('d'); insert into mylock(name) values('e'); select * from mylock;
8.2.2、寫鎖
SHOW STATUS like 'table%';
- MyISAM 的讀寫鎖排程是寫優先,所以不適合作為以寫為主的引擎。因為寫鎖後,其他執行緒不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成永久阻塞。
8.3、行鎖
特點:偏向InnoDB儲存引擎,開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
InnoDB與MyISAM的最大不同有兩點:一是支援事務(TRANSACTION);二是採用了行級鎖
CREATE TABLE test_innodb_lock (a INT(11),b VARCHAR(16))ENGINE=INNODB; INSERT INTO test_innodb_lock VALUES(1,'b2'); INSERT INTO test_innodb_lock VALUES(3,'3'); INSERT INTO test_innodb_lock VALUES(4, '4000'); INSERT INTO test_innodb_lock VALUES(5,'5000'); INSERT INTO test_innodb_lock VALUES(6, '6000'); INSERT INTO test_innodb_lock VALUES(7,'7000'); INSERT INTO test_innodb_lock VALUES(8, '8000'); INSERT INTO test_innodb_lock VALUES(9,'9000'); INSERT INTO test_innodb_lock VALUES(1,'b1'); CREATE INDEX test_innodb_a_ind ON test_innodb_lock(a); CREATE INDEX test_innodb_lock_b_ind ON test_innodb_lock(b); SELECT * from test_innodb_lock;
- 索引失效導致行鎖變表鎖
8.4、間隙鎖
什麼是間隙鎖?
當我們用範圍條件而不是相等條件檢索資料,並請求共享或排他鎖時,InnoDB會給符合條件的已有資料記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做“間隙”;
InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(Next-Key鎖)。
面試題:如何鎖定一行?
-
select * from test where a = 8 for update #其他session對這行的操作將被阻塞
8.5、優化建議
- 儘可能讓所有資料檢索都通過索引來完成,避免無索引行鎖升級為表鎖
- 合理設計索引,儘量縮小鎖的範圍
- 儘可能較少檢索條件,避免間隙鎖
- 儘量控制事務大小,減少鎖定資源量和時間長度
- 儘可能低級別事務隔離
據檢索都通過索引來完成,避免無索引行鎖升級為表鎖
- 合理設計索引,儘量縮小鎖的範圍
- 儘可能較少檢索條件,避免間隙鎖
- 儘量控制事務大小,減少鎖定資源量和時間長度
- 儘可能低級別事務隔離