阿里面試官:請說一下MySQL鎖的機制

1、概述

1.鎖的定義

(1)鎖是計算機協調多個進程或線程併發訪問某一資源的機制面試

(2)在數據庫中,除傳統的計算機資源(如CPU、RAM、I/O等)的爭用之外,數據也是一種供許多用戶共享的資源數據庫

(3)如何保證數據併發訪問的一致性、有效性是全部數據庫必須解決的一個問題,鎖衝突也是影響數據庫併發訪問性能的一個重要因素。session

2.鎖的分類

1)數據操做的類型

讀鎖(共享鎖):針對同一份數據,多個讀操做能夠同時進行而不會互相影響數據結構

寫鎖(排它鎖):當前寫操做沒有完成前,它會阻斷其餘寫鎖和讀鎖併發

2)數據操做的顆粒度

行鎖性能

表鎖優化

頁鎖atom

2、表鎖

1.特色

偏向MyISAM存儲引擎,開銷小,加鎖快,不會出現死鎖;鎖定力度大,發生鎖衝突機率高,併發度最低。線程

2.案例分析

#加鎖方式
lock table 表名1 read(write),表名2 read(write);
#查看錶上加過的鎖 0表示未上鎖
show open tables;
#釋放鎖
unlock tables;

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;

2)加讀鎖

在session 1中加鎖
#給mylock表加讀鎖
lock table mylock read;
#查詢mylock表  能夠展現全部數據
select * from mylock;
#在當前會話中不能讀取別的表:Table 'tbl_emp' was not locked with LOCK TABLES
select * from tbl_emp;

在session 2中讀取和修改設計

#能夠查詢
select * from mylock;
#修改mylock表會出先等待,直到mylock表釋放鎖
update mylock set name='aaa' where id = 1;

結論:當前session爲當前表加寫讀鎖

1.當前 session只能讀取當前表,不能更新當前表。而且不能操做其餘表的讀和寫

2.其餘 session只能讀取當前表,不能更新當前表(阻塞)。能夠操做其餘表的讀和寫。

3)加寫鎖

在session 1中添加寫鎖

#給mylock表加寫鎖
lock table mylock write;
#查詢mylock表  能夠展現全部數據
select * from mylock;
#在當前會話中不能讀取別的表:Table 'tbl_emp' was not locked with LOCK TABLES
select * from tbl_emp;

在session 2中讀取和更新

#在session 2中沒法讀取數據和更新數據,一直阻塞;直到session中unlock tables解鎖
select * from mylock;

結論:當前session爲當前表加寫鎖

1.當前session只能操做當前表的讀和寫,不能操做其餘表的讀和寫

2.其餘session不能操做當前表的讀和寫(阻塞),能夠操做其餘表。

4)總結

1.MyIsam在執行查詢語句(SELECT)前,會自動給涉及的全部表加讀鎖,在執行增刪改操做前,會自動給涉及的表加寫鎖。

2.對MyISAM表的讀操做(加讀鎖),不會阻塞其餘進程對同一表的讀請求,但會阻塞對同一表的寫請求。只有當讀鎖釋放後,纔會執行其它進程的寫操做。

3.對MyISAM表的寫操做(加寫鎖),會阻塞其餘進程對同一表的讀和寫操做,只有當寫鎖釋放後,纔會執行其它進程的讀寫操做。

4.簡而言之,就是讀鎖會阻塞寫,可是不會堵塞讀。而寫鎖則會把讀和寫都堵塞。

3、行鎖

1.特色

(1)偏向InnoDB存儲引擎,開銷大,加鎖慢;會出現死鎖(間隙鎖);鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。

(2)InnoDB與MyISam的最大不一樣有兩個:1.支持事務;2.採用行級鎖。

2.事務

1)事務(Transation)及其ACID

事務是由一組SQL語句組成的邏輯處理單元,事務具備如下4個屬性,一般簡稱爲事務的ACID屬性。

原子性(Atomicity)

事務是一個原子操做單元,其對數據的修改,要麼全都執行,要麼全都不執行。

一致性(Consistent)

在事務開始和完成時,數據都必須保持一致狀態。這意味着全部相關的數據規則都必須應用於事務的修改,以保持數據的完整性;事務結束時,全部的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。

隔離性(Isolation)

數據庫系統提供必定的隔離機制,保證事務在不受外部併發操做影響的「獨立」環境執行。這意味着事務處理過程當中的中間狀態對外部是不可見的,反之亦然。

持久性(Durability)

事務院成以後,它對於數據的修改是永久性的,即便出現系統故障也可以保持。

2)事務隔離級別

MySQL查看事務隔離級別:show variables like 'tx_isolation';

髒讀

事務A讀取到了事務B已修改但還沒有提交的的數據,還在這個數據基礎上作了操做。

不可重複讀

事務A讀取到了事務B已經提交的修改數據,不符合隔離性

幻讀

第一個事務對必定範圍的數據進行批量修改,第二個事務在這個範圍內增長一條數據,這時候第一個事務就會丟失對新新增數據的修改

3.鎖案例

1)建立表

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);

2)操做同一行數據

操做同一行數據時:當上一個事務修改未提交時,第二個事務也去修改會處於阻塞。

3)操做不一樣行數據

操做不一樣行時:即便上一個事務修改未提交,第二個事務也能修改,互不影響。

4)索引失效,表鎖

修改 test_innodb_lock 中的數據,varchar 不用 ’ ’ ,致使系統自動轉換類型,致使索引失效,會出現表鎖。

4.間隙鎖

1)介紹

當咱們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫作「間隙(GAP)」
InnoDB也會對這個「間隙」加鎖,這種鎖機制是所謂的間隙鎖(Next-Key鎖)

2)示例

4.鎖定某一行

select xxx ... for update 鎖定某一行後,其它的操做會被阻塞,直到鎖定行的會話提交commit。

5.總結

(1)Innodb存儲引擎因爲實現了行級鎖定,雖然在鎖定機制的實現方面所帶來的性能損耗可能比表級鎖定會要更高一些,可是在總體併發處理能力方面要遠遠優於MyISAM的表級鎖定的。

(2)當系統併發量較高的時候,Innodb的總體性能和MyISAM相比就會有比較明顯的優點了。

(3)可是,Innodb的行級鎖定一樣也有其脆弱的一面,當咱們使用不當的時候(索引失效,致使行鎖變表鎖),可能會讓Innodb的總體性能表現不只不能比MyISAM高,甚至可能會更差。

6.分析

show status like 'innodb_row_lock%';

(1)Innodb_row_lock_current_waits:當前正在等待鎖定的數量;

(2)Innodb_row_lock_time:從系統啓動到如今鎖定總時間長度;

(3)Innodb_row_lock_time_avg:每次等待所花平均時間;

(4)Innodb_row_lock_time_max:從系統啓動到如今等待最常的一次所花的時間;

(5)Innodb_row_lock_waits:系統啓動後到如今總共等待的次數;

7.行鎖優化

(1)儘量讓全部數據檢索都經過索引來完成,避免無索引行鎖升級爲表鎖

(2)合理設計索引,儘可能縮小鎖的範圍

(3)儘量減小檢索條件,避免間隙鎖

(4)儘可能控制事務大小,減小鎖定資源量和時間長度

(5)儘量低級別事務隔離

4、頁鎖

1.開銷和加鎖時間界於表鎖和行鎖之間:會出現死鎖;

2.鎖定粒度界於表鎖和行鎖之間,併發度通常。

最後

我這邊整理了一份:MySQL相關資料文檔以及知識圖譜、Java的系統化資料,(包括Java核心知識點、面試專題和20年最新的互聯網真題、電子書等)有須要的朋友能夠關注公衆號【程序媛小琬】便可獲取。

相關文章
相關標籤/搜索