第一章—MySQL架構與歷史
MySQL邏輯架構
- 第一層是客戶端連線,例如mysql命令列工具
- 第二層是MySQL核心服務
- 第三層是儲存引擎,負責資料的儲存與提取
優化與執行
- MySQL會解析查詢,並建立內部資料結構(解析樹),然後對其進行優化,例如:重寫查詢、決定表的讀取順序、選擇合適的索引等。
- 併發控制
- MySQL在伺服器層與儲存引擎層處理併發
- 通過加鎖的方式來解決資源競爭:表鎖與行級鎖
- 表鎖:鎖定整張表。使用者在對錶進行寫操作(插入、刪除、更新)的時候,會先獲得表的寫鎖(其他使用者被阻塞),操作結束後(commit)會自動釋放寫鎖。但,要是使用者獲取的是讀鎖,就不會阻塞其他使用者。只有拿到寫鎖的時候,既會阻塞其他使用者的寫,又會阻塞讀。
- 行級鎖:鎖定某一行。MySQL只在儲存引擎層實現,沒有在伺服器層實現。
- 只有在你增刪改查時匹配的條件欄位帶有索引,innodb才會使用行級鎖,在你增刪改查時匹配的條件欄位不帶有索引時,innodb使用的將是表級鎖。
事務
- 事務就是一組原子性的sql查詢。
- 事務的特性:ACID
- 原子性(atomicity)
- 事務被視為不可分割的最小單元,事務的所有操作要麼全部提交成功,要麼全部失敗回滾。
- 回滾可以用日誌來實現,日誌記錄著事務所執行的修改操作,在回滾時反向執行這些修改操作即可。
- 一致性(consistency)
- 資料庫在事務執行前後都保持一致性狀態。
- 在一致性狀態下,所有事務對一個數據的讀取結果都是相同的
- 隔離性(isolation)
- 一個事務所做的修改在最終提交以前,對其它事務是不可見的。或者說其他事務無法干擾。
- 永續性(durability)
- 只有滿足一致性,事務的執行結果才是正確的。
- 在無併發的情況下,事務序列執行,隔離性一定能夠滿足。此時只要能滿足原子性,就一定能滿足一致性。
- 在併發的情況下,多個事務並行執行,事務不僅要滿足原子性,還需要滿足隔離性,才能滿足一致性。
- 事務滿足持久化是為了能應對資料庫崩潰的情況。
隔離性的級別
未提交讀(READ UNCOMMITTED)
- 在此隔離級別下,對資料進行修改時,即使沒有提交資料,其他事務也可以讀取本事務,最後導致它讀取到了不正確的資料,也就是髒讀
- 此隔離級別雖然效能高,但會導致很多問題,一般不使用它
提交讀(READ COMMITTED)
- 此隔離級別是大多數資料庫系統的預設隔離級別(但MySQL不是的),它從開始到結束對其他事務都是不可見的,其他事務無法干涉
- 有時候也稱為不可重複讀
可重複讀(REPEATABLE READ)
- 同一個事務中多次讀取同樣資料的結果是一樣的
- 這是MySQL的預設隔離級別
- 解決了髒讀的問題,但無法解決幻讀的問題
- 幻讀:A事務讀取某表的100行資料,讀完後還沒繼續操作時B對這張表又插入一條新的資料,然後如果A要再次讀取這個表的100行資料,但是發現多了一行,就好像出現了幻覺一樣。這就叫幻讀。
- 幻讀是由插入或者刪除引起的
可序列化 (SERIALIZABLE)
- 序列執行事務,是最高的隔離級別。
- 一般不使用它。除非要求極高的資料一致性,並且可接受沒有併發
併發一致性問題
在併發環境下,事務的隔離性很難保證,因此會出現很多併發一致性問題。
產生併發不一致性問題主要原因是破壞了事務的隔離性,解決方法是通過併發控制來保證隔離性。
併發控制可以通過封鎖來實現,但是封鎖操作需要使用者自己控制,相當複雜。
因此,資料庫管理系統提供了事務的隔離級別,讓使用者以一種更輕鬆的方式處理併發一致性問題。
丟失修改
- T1 和 T2 兩個事務都對一個數據進行修改,T1 先修改,T2 隨後修改,T2 的修改覆蓋了 T1 的修改。
- 讀髒資料 T1 修改一個數據,T2 隨後讀取這個資料。如果 T1 撤銷了這次修改,那麼 T2 讀取的資料是髒資料。
幻影讀
- T1 讀取某個範圍的資料,T2 在這個範圍內插入新的資料,T1 再次讀取這個範圍的資料,此時讀取的結果和和第一次讀取的結果不同。(幻影讀一般是由於增加、刪除、更新導致的)
多版本併發控制(MVCC)
- MVCC是行級鎖的一種,但是他可以在大多數情況下避免加鎖操作,開銷更低,而且實現了非阻塞的讀操作
- innoDB使用MVCC處理高併發
儲存引擎
innoDB
innoDB是 MySQL 預設的事務型儲存引擎,只有在需要它不支援的特性時,才考慮使用其它儲存引擎。
實現了四個標準的隔離級別,預設級別是可重複讀(REPEATABLE READ)。在可重複讀隔離級別下,通過多版本併發控制(MVCC)+ 間隙鎖(Next-Key Locking)防止幻影讀。
主索引是聚簇索引,在索引中儲存了資料,從而避免直接讀取磁碟,因此對查詢效能有很大的提升。
內部做了很多優化,包括從磁碟讀取資料時採用的可預測性讀、能夠加快讀操作並且自動建立的自適應雜湊索引、能夠加速插入操作的插入緩衝區等。
支援真正的線上熱備份。其它儲存引擎不支援線上熱備份,要獲取一致性檢視需要停止對所有表的寫入,而在讀寫混合場景中,停止寫入可能也意味著停止讀取
MyISAM
設計簡單,資料以緊密格式儲存。對於只讀資料,或者表比較小、可以容忍修復操作,則依然可以使用它。
提供了大量的特性,包括壓縮表、空間資料索引等。
不支援事務。
不支援行級鎖,只能對整張表加鎖,讀取時會對需要讀到的所有表加共享鎖,寫入時則對錶加排它鎖。但在表有讀取操作的同時,也可以往表中插入新的記錄,這被稱為併發插入(CONCURRENT INSERT)。
可以手工或者自動執行檢查和修復操作,但是和事務恢復以及崩潰恢復不同,可能導致一些資料丟失,而且修復操作是非常慢的。
如果指定了 DELAY_KEY_WRITE 選項,在每次修改執行完成時,不會立即將修改的索引資料寫入磁碟,而是會寫到記憶體中的鍵緩衝區,只有在清理鍵緩衝區或者關閉表的時候才會將對應的索引塊寫入磁碟。這種方式可以極大的提升寫入效能,但是在資料庫或者主機崩潰時會造成索引損壞,需要執行修復操作。
區別
- 事務:InnoDB 是事務型的,可以使用 Commit 和 Rollback 語句。
- 併發:MyISAM 只支援表級鎖,而 InnoDB 還支援行級鎖。
- 外來鍵:InnoDB 支援外來鍵。
- 備份:InnoDB 支援線上熱備份。
- 崩潰恢復:MyISAM 崩潰後發生損壞的概率比 InnoDB 高很多,而且恢復的速度也更慢。
- 其它特性:MyISAM 支援壓縮表和空間資料索引。