前言:最近在準(zhǔn)備面試,復(fù)習(xí)到MySQL相關(guān)的知識战得,于是做了個總結(jié)充边,希望能對小伙伴們有所幫助,同時也是對自己學(xué)習(xí)的一個反思總結(jié)常侦。
1.MySQL的邏輯結(jié)構(gòu):
1.第一層:對客戶端的連接處理浇冰、安全認(rèn)證、授權(quán)等聋亡,每個客戶端連接都會在服務(wù)端擁有一個線程肘习,每個連接發(fā)起的查詢都會在對應(yīng)的單獨線程中執(zhí)行。
2.第二層:MySQL的核心服務(wù)功能層坡倔,包括查詢解析漂佩、分析、查詢緩存罪塔、內(nèi)置函數(shù)投蝉、存儲過程、觸發(fā)器征堪、視圖等墓拜,select操作會先檢查是否命中查詢緩存,命中則直接返回緩存數(shù)據(jù)请契,否則解析查詢并創(chuàng)建對應(yīng)的解析樹咳榜。
3.第三層:存儲引擎,負(fù)責(zé)數(shù)據(jù)的存儲和提取爽锥,MySQL服務(wù)器通過API與存儲引擎通信涌韩,屏蔽了各種引擎之間的差異,常見的存儲引擎有:InnoDB氯夷、MyISAM臣樱,兩者的詳細(xì)介紹以后會繼續(xù)深入分析。
2.MySQL中的鎖:
MySQL在處理并發(fā)讀寫的時候,分別使用共享鎖(寫鎖)和排它鎖(讀鎖)對共享資源高并發(fā)操作雇毫,在加鎖的時候玄捕,最好能鎖定所需數(shù)據(jù),控制鎖的粒度棚放、提高并發(fā)能力枚粘,MySQL提供了兩種重要的鎖策略:
標(biāo)記鎖:鎖定整張表,在對表進(jìn)行插入更新刪除操作時飘蚯,需要先獲得寫鎖馍迄,鎖定整張表,其他讀寫操作都會被阻塞局骤。讀鎖之間不會阻塞攀圈。
行級鎖:鎖定數(shù)據(jù)所在行,行級鎖只在存儲引擎層實現(xiàn)峦甩,可以很好支持并發(fā)處理赘来。
3.MySQL的事務(wù):
事務(wù)的實現(xiàn)原理:MySQL中的事務(wù)是在存儲引擎中實現(xiàn)的,所以上層的服務(wù)是不會管理事務(wù)的凯傲。默認(rèn)情況下撕捍,MySQL自身提供了兩種事務(wù)型的存儲引擎,分別是InnnoDB和NDB Cluster泣洞。
在默認(rèn)情況下忧风,MySQL事務(wù)采用自動提交模式,即如果沒有顯示的開啟一個事務(wù)球凰,那么每一次的查詢都將被當(dāng)做一個事務(wù)執(zhí)行自動提交狮腿。當(dāng)然,也可以通過設(shè)置來改變這種自動提交的模式呕诉。如果想開啟自動提交缘厢,可以通過命令SET AUTOCOMMIT = 1或SET AUTOCOMMIT =ON來設(shè)置;關(guān)閉自動提交模式甩挫,可以通過命令SET AUTOCOMMIT = 0或SET AUTOCOMMIT = OFF來設(shè)置贴硫。
InnoDB存儲引擎采用的是兩階段鎖定協(xié)議,在事務(wù)執(zhí)行的過程中伊者,InnoDB會根據(jù)隔離級別在需要加鎖的時候自定加鎖英遭,鎖只有在事務(wù)提交或回滾的時候才會釋放。當(dāng)然亦渗,也可以顯示的加鎖挖诸,如使用SELECT FOR UPDATE,也可以使用服務(wù)層實現(xiàn)的LOCK TABLES和UNLOCK TABLES法精。事務(wù)日志:即一種特殊的操作記錄日志多律,存儲引擎在修改表數(shù)據(jù)的時候痴突,只修改內(nèi)存中的拷貝,然后將修改行為記錄保存到硬盤上的事務(wù)日志中狼荞,對事務(wù)日志的保存操作采用追加的方式辽装,保存操作是順序IO,相對于存儲引擎直接將數(shù)據(jù)持久化到硬盤的隨機IO高效的多相味。事務(wù)日志保存后拾积,內(nèi)存中被修改的數(shù)據(jù)在后臺可以慢慢的持久化到硬盤。如果事務(wù)日志保存成功了攻走,而內(nèi)存中被修改的數(shù)據(jù)沒有成功的寫入硬盤,發(fā)生了系統(tǒng)崩潰此再,存儲引擎會在重啟時自動恢復(fù)這部分?jǐn)?shù)據(jù)昔搂。
事務(wù)的特性:ACID
原子性:一個事務(wù)的所有操作要么全部執(zhí)行要么全部失敗回滾
一致性:事務(wù)執(zhí)行結(jié)果使數(shù)據(jù)庫從一個一致性狀態(tài)變成另一個一致性狀態(tài)
隔離性:事務(wù)操作提交之前,操作結(jié)果對其他事務(wù)不可見
持久性:事務(wù)提交后输拇,所有的修改操作會永久保存到數(shù)據(jù)庫中
-
事務(wù)的隔離級別:SQL標(biāo)準(zhǔn)定義了四種隔離級別摘符,分別是read uncommitter,read committed策吠,repeatable read逛裤,serializable,可以通過set transaction isolation level命令來設(shè)置隔離級別
臟讀:事務(wù)未提交的數(shù)據(jù)能被其他事務(wù)讀到
不可重復(fù)讀:一個事務(wù)前后兩次讀取某數(shù)據(jù)中間時刻猴抹,有事務(wù)修改了數(shù)據(jù)带族,導(dǎo)致兩次讀取的數(shù)據(jù)不一致
幻讀:事務(wù)在讀取某范圍內(nèi)數(shù)據(jù),其他事務(wù)在范圍內(nèi)插入了新記錄蟀给,導(dǎo)致事務(wù)內(nèi)兩次讀取的數(shù)據(jù)會不一致
隔離級別的實現(xiàn)原理:
未提交讀:讀數(shù)據(jù)的時候不加鎖蝙砌,寫數(shù)據(jù)的時候加行級別的共享鎖,提交時釋放鎖跋理。行級別的共享鎖不會對讀產(chǎn)生影響择克,但可以防止連個同時的寫操作
已提交讀:事務(wù)讀取數(shù)據(jù)時(讀到數(shù)據(jù)的時候)加行級共享鎖鎖,讀完釋放鎖前普;事務(wù)寫數(shù)據(jù)的時候(寫操作發(fā)生瞬間)肚邢,加行級獨占鎖,讀完后立即釋放鎖拭卿。由于事務(wù)寫操作加獨占鎖骡湖,因此事務(wù)寫操作時,讀操作也不能進(jìn)行峻厚,因此不能讀到事務(wù)的未提交數(shù)據(jù)勺鸦,避免了臟讀的問題,但由于讀操作的鎖加在讀上面(鎖的粒度較心磕尽)换途,而不是事務(wù)之上懊渡,所以在同一事務(wù)的兩次讀操作之間可以插入其他事務(wù)的寫操作,所以可能發(fā)生不可重復(fù)讀的問題
可重復(fù)讀:與已提交讀不同的是军拟,事務(wù)讀取數(shù)據(jù)在讀操作開始瞬間就加上了行級鎖共享鎖剃执,而且在事務(wù)結(jié)束的時候才釋放(鎖的粒度與已提交鎖不一樣),鎖加在事務(wù)上懈息,解決了不可重讀問題肾档,事務(wù)寫操作加獨占鎖,同上辫继,但是由于加的是行級鎖怒见,所以會出現(xiàn)幻讀問題
可串行化:在讀操作時,加表級共享鎖姑宽,事務(wù)結(jié)束時釋放遣耍,寫操作時,加表級獨占鎖炮车,事務(wù)結(jié)束時釋放舵变。該隔離級別下可能會導(dǎo)致大量的超時和鎖競爭問題。
4.MySQL中的死鎖:
指多個事務(wù)在同一資源上相互占用瘦穆,并請求鎖定對方所占用的資源纪隙,從而導(dǎo)致的惡性循環(huán)條件,數(shù)據(jù)庫系統(tǒng)為解決這個問題實現(xiàn)了死鎖檢測和死鎖超時機制扛或,在MySQL的InnoDB存儲引擎中绵咱,解決死鎖的方法是將持有最少行級排它鎖的事務(wù)進(jìn)行回滾。
5.多版本并發(fā)控制MVCC:
基于對并發(fā)性能的考慮熙兔,MySQL的大多數(shù)事務(wù)型存儲引擎都實現(xiàn)了多版本并發(fā)控制麸拄,可以簡單的認(rèn)為MVCC是行級鎖的一個變種,但是它在很多情況下避免了加鎖操作黔姜,降低了開銷拢切。
InnoDB的MVCC是通過在每行記錄后添加兩個隱藏列來實現(xiàn)的,一個列用于保存行的創(chuàng)建時間秆吵,一個列用于保存行的過期時間淮椰,這兩個時間在實際存儲的時候,存儲的是系統(tǒng)版本號纳寂。每開始一個新事務(wù)主穗,系統(tǒng)版本號都將遞增。需要注意的是MVCC只能在Read Committed和Repeatable Read隔離級別下正常工作毙芜。
6.MySQL存儲引擎:
MySQL自身和第三方提供了多種存儲引擎忽媒,每種存儲引擎優(yōu)勢各不相同,可以根據(jù)實際業(yè)務(wù)需要來選擇對應(yīng)的存儲引擎腋粥。
InnoDB是MySQL的默認(rèn)事務(wù)型存儲引擎晦雨,主要用來處理大量的短期型事務(wù)架曹。它采用MVCC來支持高并發(fā),默認(rèn)的事務(wù)隔離級別是Repeatable Read闹瞧,并通過間隙鎖策略防止幻讀的出現(xiàn)绑雄。InnoDB表是基于聚簇索引建立的,而聚簇索引可以提高對主鍵查詢的性能奥邮,但是它的二級索引(非主鍵索引)中必須包含主鍵万牺,如果主鍵列很大,并且有很多個二級索引洽腺,那么這些索引將會占用很大的空間和資源脚粟,所以在創(chuàng)建主鍵的時候盡量的小。
在MySQL5.1及之前的版本中蘸朋,MyISAM是默認(rèn)的存儲引擎核无,它提供了全文索引、壓縮度液、空間函數(shù)等功能厕宗,但是它不支持事務(wù)和行級鎖画舌,并且崩潰后無法安全恢復(fù)堕担,而InnoDB引擎是可以自動崩潰恢復(fù)的。MyISAM在并發(fā)的情況下曲聂,對整張表加鎖霹购,讀操作會對需要讀的所有表加共享鎖,寫入時對表加排它鎖朋腋。
感謝閱讀~