MySQL的詳細講解
Mysql的架構與歷史
MySQL的邏輯架構
第二層的架構是所有的跨引擎的功能實現的地方,例如:存儲,觸發器,視圖等。
第三層半酣了 存儲引擎,負責MySQL中的數據存儲和提取。
連接管理與安全性
每個客戶端連接都會在伺服器進程中擁有一個執行緒,這個連接的查詢只會在這個單獨的執行緒中執行,該執行緒只能輪流在某個CPU核心或者CPU中運行。伺服器會負責快取執行緒,因此不需要為每一個新建的連接創建或者銷毀執行緒。當客戶端(應用)連接MySQL伺服器時,伺服器需要對其進行認證。
優化與執行
解析查詢,內部會創建數據結構(解析樹),然後對其優化,選擇合適的索引,可以請求優化器的解釋,優化器不關心用的什麼引擎,但是存儲的引擎對優化查詢是有影響的,對於select語句,解析查詢的時候,先查快取,命中了就返回快取的結果集。
並發控制
倆個層面的並發控制:伺服器層與存儲引擎層。
簡單的處理就是上鎖,例如讀寫鎖。
鎖力度
一種提高共享資源的並發性的方式是讓鎖定對象更具有選擇性。但是問題是加鎖也是需要消耗資源的,所以需要把握平衡。MySQL提供了多種選擇:有著自己的鎖策略和鎖粒度。
表鎖
表鎖是MySQL中最基本的鎖策略,並且是開銷最小的策略。它會鎖定整張表。
行級鎖
行級鎖可以最大程度地支援並發處理(同時也帶來了最大的鎖開銷)。行級鎖只在存儲引擎層實現,而MySQL伺服器層沒有實現,伺服器層完全不了解存儲引擎中的鎖實現。
事務
ACID
這裡討論一下隔離性,實際比想像的要複雜。在SQL標準中定義了四種隔離級別,每一種級別都規定了一個事務中所做的修改,哪些在事務內和事務間是可見的,哪些是不可見的。較低級別的隔離通常可以執行更高的並發,系統的開銷也更低。
讀未提交 | 一個事務還沒提交時,它做的變更就能被別的事務看到 | 直接返回記錄上的最新值,沒有視圖概念 |
讀提交 | 一個事務執行過程中看到的數據,總是跟這個事務在啟動時看到的數據是一致的 | 這個視圖是在每個 SQL 語句開始執行的時候創建的 |
可重複讀 | 未提交變更對其他事務是不可見的 | 這個視圖是在事務啟動時創建的,整個事務存在期間都用這個視圖 |
串列化 | 顧名思義是對於同一行記錄,「寫」會加「寫鎖」,「讀」會加「讀鎖」。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。 | 直接用加鎖的方式來避免並行訪問 |
Read Uncommitted(讀取未提交內容)
在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。
本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。
Read Committed(讀取提交內容)
這是大多數資料庫系統的默認隔離級別(但不是MySQL默認的)。
它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。
這種隔離級別 也支援所謂的不可重複讀(Nonrepeatable Read),
因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在並發讀取數據時,會看到同樣的數據行。
不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。
簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另一個事務又在該範圍內插入了新行,
當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。
InnoDB和Falcon存儲引擎通過多版本並發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串列化)
這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。
簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
事務日誌
你可將MVCC看成行級別鎖的一種妥協,它在許多情況下避免了使用鎖,同時可以提供更小的開銷。根據實現的不同,它可以允許非阻塞式讀,在寫操作進行時只鎖定必要的記錄。
MVCC會保存某個時間點上的數據快照。這意味著事務可以看到一個一致的數據視圖,不管他們需要跑多久。這同時也意味著不同的事務在同一個時間點看到的同一個表的數據可能是不同的。