MySQL服務(wù)器邏輯架構(gòu)
MySQL的存儲引擎架構(gòu)將查詢處理與數(shù)據(jù)的存儲/提取相分離。下面是MySQL的邏輯架構(gòu)圖:
第一層負責(zé)連接管理、授權(quán)認證、安全等等。
每個客戶端的連接都對應(yīng)著服務(wù)器上的一個線程。服務(wù)器上維護了一個線程池,避免為每個連接都創(chuàng)建銷毀一個線程。當(dāng)客戶端連接到MySQL服務(wù)器時,服務(wù)器對其進行認證??梢酝ㄟ^用戶名和密碼的方式進行認證,也可以通過SSL證書進行認證。登錄認證通過后,服務(wù)器還會驗證該客戶端是否有執(zhí)行某個查詢的權(quán)限。
第二層負責(zé)解析查詢(編譯SQL)
并對其進行優(yōu)化(如調(diào)整表的讀取順序,選擇合適的索引等)。對于SELECT語句,在解析查詢前,服務(wù)器會先檢查查詢緩存,如果能在其中找到對應(yīng)的查詢結(jié)果,則無需再進行查詢解析、優(yōu)化等過程,直接返回查詢結(jié)果。存儲過程、觸發(fā)器、視圖等都在這一層實現(xiàn)。
第三層是存儲引擎
存儲引擎負責(zé)在MySQL中存儲數(shù)據(jù)、提取數(shù)據(jù)、開啟一個事務(wù)等等。存儲引擎通過API與上層進行通信,這些API屏蔽了不同存儲引擎之間的差異,使得這些差異對上層查詢過程透明。存儲引擎不會去解析SQL。
并發(fā)控制
無論何時,只要存在多個查詢需要在同一時刻修改數(shù)據(jù),都會產(chǎn)生并發(fā)控制問題。解決這類問題,有一個經(jīng)典的方法,讀寫鎖,分為讀鎖和寫鎖,也叫共享鎖和排他鎖。
讀鎖是共享的,互補阻塞;寫鎖匙排他的,一個寫鎖會阻塞其他的寫鎖和讀鎖。
鎖策略
問題是加鎖需要消耗資源,頻繁的加鎖解鎖會使得系統(tǒng)性能受到影響,所謂鎖策略,就是在鎖的開銷和安全性之間尋求平衡。下面介紹兩種最重要的鎖策略。
表鎖
表鎖匙MySQL中最基本的鎖策略,并且是開銷最小的策略。表鎖會鎖定整張表,一個用戶在對表進行寫操作(插入、更新、刪除)前,需要獲得寫鎖。
行級鎖
行級鎖可以最大程度地支持并發(fā)處理(同時也帶來了最大的鎖開銷)。行級鎖只在存儲引擎層實現(xiàn),而MySQL服務(wù)器層沒有實現(xiàn)。
事務(wù)
事務(wù)就是一組原子性的SQL查詢,或者說一個獨立的工作單元。
除非通過嚴格的ACID測試,否則空談事務(wù)的概念是不夠的。ACID表示原子性(atomicity),一致性(consistency),隔離性(isolation)和持久性(durability)。
- 原子性
整個事務(wù)中的所有操作要么全部成功,要么全部失敗。
- 一致性
數(shù)據(jù)庫總是從一個一致性狀態(tài)到另一個一致性狀態(tài)。
- 隔離性
一個事務(wù)所做的修改在最終提交以前,對其他事務(wù)是不可見的。
- 持久性
一旦事務(wù)提交,則其所做的修改就會永久保存到數(shù)據(jù)庫中。
隔離級別
在SQL標準中定義了四種隔離級別,每一種級別都規(guī)定了一個事務(wù)中所做的修改,哪些在事務(wù)和事務(wù)是可見的,哪些是不可見的。
下面簡單介紹四種隔離級別:
- READ UNCOMMITTED(未提交讀)
在這個級別中,事務(wù)中的修改,即使沒有提交,對其他事務(wù)也都是可見的,事務(wù)可以讀取未提交的事務(wù),這樣被稱為臟讀(Dirty Read)。
- READ COMMITTED(提交讀)
一個事務(wù)從開始直到提交之前,所做的修改對其他事務(wù)都是不可見的,這也叫不可重復(fù)讀(nonrepeatable read),因為兩次同樣的查詢,可能會得到不一樣的結(jié)果。
- REPEATABLE READ(可重復(fù)讀)
可重復(fù)讀是MySQL默認的事務(wù)隔離級別,雖然他解決了臟讀的問題,但還是無法解決另一個幻讀(Phantom Read)的問題。
所謂幻讀,指的是當(dāng)某個事物在讀取某個范圍之內(nèi)的記錄時,另外一個事務(wù)又在該范圍內(nèi)插入了新的記錄,當(dāng)之前的事務(wù)再次讀取該范圍的記錄時,會產(chǎn)生幻行,
- SERIALIZABLE(可串行化)
SERIALIZABLE是最高的隔離級別,它通過強制事務(wù)串行執(zhí)行,避免了前面的幻讀問題。簡單來說就是,SERIALIZABLE會在讀取的每一行數(shù)據(jù)上都加鎖,所以可能導(dǎo)致大量的超時和鎖爭用的問題。
死鎖
死鎖是指兩個或者多個事務(wù)在同一資源上相互占用,并請求鎖定對方占用的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。
左圖那兩輛車造成死鎖了嗎?不是!右圖四輛車造成死鎖了嗎?是!
多版本并發(fā)控制
多版本并發(fā)控制(MVVC),能夠避免加鎖操作,因此開銷更低。MVVC的實現(xiàn),是通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)的,典型的有樂觀并發(fā)控制和悲觀并發(fā)控制。
InnoDB的MVVC,是通過在每行記錄后面保存兩個隱藏的列來實現(xiàn)的,這兩個列分別保存了行的創(chuàng)建時間和過期時間(或刪除時間),當(dāng)然不是具體時間,而是系統(tǒng)版本號。
MVVC只在REPETABLE READ和READ COMMITED兩個隔離級別下工作。其他兩個隔離級別都和MVVC不兼容,因為READ UNCOMMITED總是讀取最新行的數(shù)據(jù),而不是符合當(dāng)前事務(wù)版本的數(shù)據(jù)行。而SERIALIZABLE則會對所有讀取的行都加鎖。
存儲引擎
- InnoDB是MySQL的默認事務(wù)型引擎。
- MyISAM存儲引擎是MySQL5.1及之前的版本,但MyISAM不支持事務(wù)和行級鎖,且有一個毫無疑問的缺陷就是崩潰后無法安全恢復(fù)。