0、概要
- 1、談一談MySQL的讀寫鎖
- 2、隔離級別與鎖的關(guān)系
- 3、按照鎖的粒度分數(shù)據(jù)庫鎖有哪些?鎖機制與InnoDB鎖算法
- 4、從鎖的類別上分MySQL都有哪些鎖呢?像上面那樣子進行鎖定豈不是有點阻礙并發(fā)效率了
- 5、MySQL中InnoDB引擎的行鎖是怎么實現(xiàn)的?
- 6、InnoDB存儲引擎的鎖的算法有三種
- 7、什么是死鎖?怎么解決?
- 8、數(shù)據(jù)庫的樂觀鎖和悲觀鎖是什么?怎么實現(xiàn)的?
#1、談一談MySQL的讀寫鎖
出現(xiàn)概率:
在處理并發(fā)讀或?qū)憰r,可以通過實現(xiàn)一個由兩種類型組成的鎖系統(tǒng)來解決問題。這兩種類型的鎖通常被稱為共享鎖和排它鎖,也叫讀鎖和寫鎖。讀鎖是共享的,相互不阻塞,多個客戶在同一時刻可以同時讀取同一個資源而不相互干擾。寫鎖則是排他的,也就是說一個寫鎖會阻塞其他的寫鎖和讀鎖,確保在給定時間內(nèi)只有一個用戶能執(zhí)行寫入并防止其他用戶讀取正在寫入的同一資源。
在實際的數(shù)據(jù)庫系統(tǒng)中,每時每刻都在發(fā)生鎖定,當(dāng)某個用戶在修改某一部分?jǐn)?shù)據(jù)時,MySQL 會通過鎖定防止其他用戶讀取同一數(shù)據(jù)。寫鎖比讀鎖有更高的優(yōu)先級,一個寫鎖請求可能會被插入到讀鎖隊列的前面,但是讀鎖不能插入到寫鎖前面。
#2、隔離級別與鎖的關(guān)系
出現(xiàn)概率:
在Read Uncommitted級別下,讀取數(shù)據(jù)不需要加共享鎖,這樣就不會跟被修改的數(shù)據(jù)上的排他鎖沖突
在Read Committed級別下,讀操作需要加共享鎖,但是在語句執(zhí)行完以后釋放共享鎖;
在Repeatable Read級別下,讀操作需要加共享鎖,但是在事務(wù)提交之前并不釋放共享鎖,也就是必須等待事務(wù)執(zhí)行完畢以后才釋放共享鎖。
SERIALIZABLE 是限制性最強的隔離級別,因為該級別鎖定整個范圍的鍵,并一直持有鎖,直到事務(wù)完成。
#3、按照鎖的粒度分?jǐn)?shù)據(jù)庫鎖有哪些?鎖機制與InnoDB鎖算法
出現(xiàn)概率:
在關(guān)系型數(shù)據(jù)庫中,可以按照鎖的粒度把數(shù)據(jù)庫鎖分為行級鎖(INNODB引擎)、表級鎖(MYISAM引擎)和頁級鎖(BDB引擎 )。
MyISAM和InnoDB存儲引擎使用的鎖:
MyISAM采用表級鎖(table-level locking)。
InnoDB支持行級鎖(row-level locking)和表級鎖,默認(rèn)為行級鎖
行級鎖,表級鎖和頁級鎖對比
行級鎖 行級鎖是Mysql中鎖定粒度最細的一種鎖,表示只針對當(dāng)前操作的行進行加鎖。行級鎖能大大減少數(shù)據(jù)庫操作的沖突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分為共享鎖 和 排他鎖。
特點:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。
表級鎖 表級鎖是MySQL中鎖定粒度最大的一種鎖,表示對當(dāng)前操作的整張表加鎖,它實現(xiàn)簡單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級鎖定。表級鎖定分為表共享讀鎖(共享鎖)與表獨占寫鎖(排他鎖)。
特點:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)出鎖沖突的概率最高,并發(fā)度最低。
頁級鎖 頁級鎖是MySQL中鎖定粒度介于行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但沖突多,行級沖突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。
特點:開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般
回復(fù): mysql免費獲取最新Mysql面試題匯總(含答案)。
#4、從鎖的類別上分MySQL都有哪些鎖呢?像上面那樣子進行鎖定豈不是有點阻礙并發(fā)效率了
出現(xiàn)概率:
從鎖的類別上來講,有共享鎖和排他鎖。
共享鎖: 又叫做讀鎖。當(dāng)用戶要進行數(shù)據(jù)的讀取時,對數(shù)據(jù)加上共享鎖。共享鎖可以同時加上多個。
排他鎖: 又叫做寫鎖。當(dāng)用戶要進行數(shù)據(jù)的寫入時,對數(shù)據(jù)加上排他鎖。排他鎖只可以加一個,他和其他的排他鎖,共享鎖都相斥。
用上面的例子來說就是用戶的行為有兩種,一種是來看房,多個用戶一起看房是可以接受的。一種是真正的入住一晚,在這期間,無論是想入住的還是想看房的都不可以。
鎖的粒度取決于具體的存儲引擎,InnoDB實現(xiàn)了行級鎖,頁級鎖,表級鎖。
他們的加鎖開銷從大到小,并發(fā)能力也是從大到小。
#5、MySQL中InnoDB引擎的行鎖是怎么實現(xiàn)的?
出現(xiàn)概率:
答:InnoDB是基于索引來完成行鎖
select * from tab_with_index where id = 1 for update;
for update 可以根據(jù)條件來完成行鎖鎖定,并且 id 是有索引鍵的列,如果 id 不是索引鍵那么InnoDB將完成表鎖,并發(fā)將無從談起
#6、InnoDB存儲引擎的鎖的算法有三種
- Record lock:單個行記錄上的鎖
- Gap lock:間隙鎖,鎖定一個范圍,不包括記錄本身
- Next-key lock:record+gap 鎖定一個范圍,包含記錄本身
#7、什么是死鎖?
出現(xiàn)概率:
死鎖是指兩個或多個事務(wù)在同一資源上相互占用,并請求鎖定對方的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。
回復(fù): mysql免費獲取最新Mysql面試題匯總(含答案)。
#8、常見的解決死鎖的方法
出現(xiàn)概率:
死鎖是指多個事務(wù)在同一資源上相互占用并請求鎖定對方占用的資源而導(dǎo)致惡性循環(huán)的現(xiàn)象。當(dāng)多個事務(wù)試圖以不同順序鎖定資源時就可能會產(chǎn)生死鎖,多個事務(wù)同時鎖定同一個資源時也會產(chǎn)生死鎖。
為了解決死鎖問題,數(shù)據(jù)庫系統(tǒng)實現(xiàn)了各種死鎖檢測和死鎖超時機制。越復(fù)雜的系統(tǒng),例如InnoDB 存儲引擎,越能檢測到死鎖的循環(huán)依賴,并立即返回一個錯誤。這種解決方式很有效,否則死鎖會導(dǎo)致出現(xiàn)非常慢的查詢。還有一種解決方法,就是當(dāng)查詢的時間達到鎖等待超時的設(shè)定后放棄鎖請求,這種方式通常來說不太好。InnoDB 目前處理死鎖的方法是將持有最少行級排它鎖的事務(wù)進行回滾。
死鎖發(fā)生之后,只有部分或者完全回滾其中一個事務(wù),才能打破死鎖。對于事務(wù)型系統(tǒng)這是無法避免的,所以應(yīng)用程序在設(shè)計時必須考慮如何處理死鎖。大多數(shù)情況下只需要重新執(zhí)行因死鎖回滾的事務(wù)即可。
#9、數(shù)據(jù)庫的樂觀鎖和悲觀鎖是什么?怎么實現(xiàn)的?
出現(xiàn)概率:
數(shù)據(jù)庫管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個事務(wù)同時存取數(shù)據(jù)庫中同一數(shù)據(jù)時不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫的統(tǒng)一性。樂觀并發(fā)控制(樂觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段。
悲觀鎖:假定會發(fā)生并發(fā)沖突,屏蔽一切可能違反數(shù)據(jù)完整性的操作。在查詢完數(shù)據(jù)的時候就把事務(wù)鎖起來,直到提交事務(wù)。實現(xiàn)方式:使用數(shù)據(jù)庫中的鎖機制
樂觀鎖:假設(shè)不會發(fā)生并發(fā)沖突,只在提交操作時檢查是否違反數(shù)據(jù)完整性。在修改數(shù)據(jù)的時候把事務(wù)鎖起來,通過version的方式來進行鎖定。實現(xiàn)方式:樂一般會使用版本號機制或CAS算法實現(xiàn)。
兩種鎖的使用場景
從上面對兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點,不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下(多讀場景),即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。
但如果是多寫的情況,一般會經(jīng)常產(chǎn)生沖突,這就會導(dǎo)致上層應(yīng)用會不斷的進行retry,這樣反倒是降低了性能,所以一般多寫的場景下用悲觀鎖就比較合適。