MySQL的架構

1、MySQL邏輯架構數據庫

前言:爲了充分發揮MySQL的性能並順利地使用,就必須理解其設計緩存

 

MySQL最重要、最不同凡響的特性是它的存儲引擎架構,這種架構的設計將查詢處理及其餘系統任務和數據的存儲/提取相分離。因此這種處理和存儲分離的設計能夠在使用時根據性能、特性,以及其餘需求來選擇數據存儲的方式安全

 

一、MySQL的邏輯架構圖服務器

1.一、鏈接管理與安全性架構

1.二、優化與執行併發

 

二、併發控制函數

2.一、讀寫鎖高併發

  共享鎖(讀鎖)、排他鎖(寫鎖)工具

2.二、鎖粒度性能

  表鎖、行級鎖

 

三、事務

3.一、 ACID

3.二、隔離級別

  未提交讀(髒讀)  事務能夠讀取未提交的數據,性能不比其餘級別好太多,如非必要通常不使用

  提交讀(不可重複讀)  一個事務從開始直到提交以前,所做的任何修改對其餘事務都是不可見的  

  可重複讀(MySQL的默認事務隔離級別)  解決了髒讀問題,保證了在同一個事務中屢次讀取一樣記錄的結果是一致的。但可重複讀會出現幻讀問題,當一個事務在讀取某個範圍內的記錄時,另一個事務又在該範圍內插入了新的記錄,這時當以前的事務再去讀取該範圍的記錄時,就產生了幻行

  可串行化(最高隔離級別)  強制事務串行執行,避免了幻讀的問題,在讀取的每一行數據上都加鎖,因此可能致使大量的超時和鎖爭用的問題。只有在很是須要確保數據的一致性並且能夠接受沒有併發的狀況下,才考慮採用該級別

3.三、死鎖

  死鎖是指兩個或者多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而致使惡性循環的現象

  爲了解決這種問題,數據庫系統實現了各類死鎖檢測和死鎖超時機制。InnoDB目前處理死鎖的方式是,將持有最少行級排他鎖的事務進行回滾

  鎖的行爲和順序是和存儲引擎相關的。死鎖發生之後,只有部分或者徹底回滾其中一個事務,才能打破死鎖。因此應用程序在設計時必須考慮如何處理死鎖,大多數狀況下只需從新執行因死鎖回滾的事務便可。

3.四、事務日誌

  事務日誌能夠幫助提升事務的效率。

  使用事務日誌,存儲引擎在修改表的數據時只須要修改其內存拷貝,再把該修改行爲 記錄到 持久在硬盤上的事務日誌中,而不用每次都將修改的數據自己持久到磁盤。

  事務日誌採用的是追加的方式,所以寫日誌的操做是磁盤上一小塊區域內的順序I/O,而不像隨機I/O須要在磁盤的多個地方移動磁頭,因此採用事務日誌的方式相對來講要快得多

  在事務日誌持久之後,內存中被修改的數據在後臺能夠慢慢地刷回到磁盤。一般稱爲預寫式日誌,全部其實修改數據須要寫兩次磁盤(一次是事務日誌持久化到磁盤,一次是修改數據刷回到磁盤)

3.五、MySQL中的事務

  MySQL提供了兩種事務型的存儲引擎:InnoDB和NDB Cluster。另外還有一些第三方存儲引擎也支持事務,比較知名的包括XtraDB和PBXT

  MySQL默認採用自動提交模式。若是不是顯式地開始一個事務,則每一個查詢都被看成一個事務執行提交操做。

 

四、多版本併發控制

  MySQL的大多數事務型存儲引擎實現的都不是簡單的行級鎖。基於提高併發性能的考慮,它們通常都同時實現了多版本併發控制(MVCC)

  MVCC的實現,是經過保存數據在某個時間點的快照來實現的。也就是說,無論須要執行多長時間,每一個事務看到的數據都是一致的。由於事實上根據事務開始的時間不一樣,每一個事務對同一張表,同一時刻看到的數據多是不同的

  不一樣存儲引擎的MVCC實現是不一樣的,典型的有樂觀(optimistic)併發控制和悲觀(pessimistic)併發控制。

  悲觀鎖的理解:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做。悲觀鎖的實現,每每依靠底層提供的鎖機制;悲觀鎖會致使其它全部須要鎖的線程掛起,等待持有鎖的線程釋放鎖。

  樂觀鎖的理解:假設不會發生併發衝突,每次不加鎖而是假設沒有衝突而去完成某項操做,只在提交操做時檢查是否違反數據完整性。缺點是不能解決髒讀的問題,因此一般樂觀鎖與提交讀的隔離等級共同使用。

  InnoDB的MVCC,是經過在每行記錄後面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的建立時間,一個保存行的過時時間(或刪除時間),實際上存儲的不是實際的時間值,而是系統版本號。每開始一個新事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會做爲事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

  以可重複讀(REPEATABLE READ)隔離級別爲例,解析MVCC具體如何操做:

  SELECT

    InnoDB會根據如下兩個條件檢查每行記錄:

    一、只查找版本早於當前事務版本的數據行(行的系統版本號小於或等於事務的系統版本號),確保事務讀取的行,要麼是在事務開始前已經存在,要麼是事務自身插入或者修改過

    二、行的刪除版本要麼未定義,要麼大於當前事務版本號,確保事務讀取到的行,在事務開始以前未被刪除。

    只有符合這兩個條件的記錄,才能返回做爲查詢結果

  INSERT

    爲新插入的每一行保存當前系統版本號做爲行版本號

  DELETE

    爲刪除的每一行保存當前系統版本號做爲行刪除標識

  UPDATE

    爲插入一行新記錄,保存當前系統版本號做爲行版本號,同時保存當前系統版本號到原來的行做爲行刪除標識

  優缺點:保存兩個額外系統版本號,使大多數讀操做均可以不用加鎖。使讀數據操做很簡單,性能很好。不足之處是每行記錄都須要額外的存儲空間,須要作更多的行檢查工做,以及一些額外的維護工做

  MVCC只在可重複讀和提交讀兩個隔離級別下工做。由於未提交讀老是讀取最新的數據行,而不是符合當前事務版本的數據行。而可串行化則會對全部讀取的行都加鎖。

 

五、MySQL的存儲引擎

  在文件系統中,MySQL將每一個數據庫保存爲數據目錄下的一個子目錄。建立表時,MySQL會在數據庫子目錄下建立一個和表同名的.frm文件保存表的定義。由於MySQL使用文件系統的目錄和文件來保存數據庫和表的定義,大小寫敏感性和具體的平臺密切相關。

  不一樣的存儲引擎保存數據和索引的方式是不一樣的,但表的定義則是在MySQL服務層統一處理。

5.一、InnoDB存儲引擎

  InnoDB是MySQL的默認事務型引擎,也是最重要、使用最普遍的存儲引擎。

  InnoDB的性能和自動崩潰恢復特性,使得它在非事務型存儲的需求中也很流行。

  InnoDB的數據存儲在表空間中,表空間是由InnoDB管理的一個黑盒子,由一系列的數據文件組成。

  InnoDB採用MVCC來支持高併發,並實現了四個標準的隔離等級。其默認級別是可重複讀,而且經過間隙鎖策略防止幻讀的出現。間隙鎖使得InnoDB不只僅鎖定查詢涉及的行,還會對索引中的間隙進行鎖定,以防止幻影行的插入。

  InnoDB表是基於聚簇索引創建的。聚簇索引對主鍵查詢有很高的性能,不過它的二級索引(非主鍵索引)中必須包含主鍵列,因此若是主鍵列很大的話,其餘的全部索引都會很大。所以,若表上的索引較多的話,主鍵應當儘量的小。

  InnoDB內部作了不少優化,包括從磁盤讀取數據時採用的可預測性預讀,可以自動在內存中建立hash索引以加速讀操做的自適應哈希索引,以及可以加速插入操做的插入緩衝區等。

  做爲事務型的存儲引擎,InnoDB經過一些機制和工具支持真正的熱備份,MySQL的其餘存儲引擎不支持熱備份。

 5.二、MyISAM存儲引擎

  在MySQL 5.1及以前的版本,MyISAM是默認的存儲引擎。提供大量的特性,包括全文索引、壓縮、空間函數(GIS)等,但不支持事務和行級鎖,一個毫無疑問的缺陷就是崩潰後沒法安全恢復。

  MyISAM引擎設計簡單,數據以緊密格式存儲,因此在某些場景下的性能很好。但最典型的性能問題仍是表鎖問題,若是全部的查詢都長期處於鎖定狀態,那麼查詢的速度無疑是很慢的。

5.三、MySQL內建的其餘存儲引擎

  Archive引擎,是一個針對高速插入和壓縮作了優化的簡單引擎。只支持INSERT和SELECT操做,會緩存全部的寫並利用zlib對插入的行進行壓縮,因此比MyISAM表的磁盤I/O更少。每次SELECT查詢都須要執行全表掃描,適合日誌和數據採集類應用或者在一些須要更快速的INSERT操做的場合下使用。支持行級鎖和專用的緩衝區,因此能夠實現高併發的插入。

  CSV引擎,能夠將普通的CSV文件(逗號分割值的文件)做爲MySQL的表來處理,但不支持索引。將數據存儲爲CSV文件,而後複製到MySQL數據目錄下,就能在MySQL中打開使用。將數據寫入到一個CSV引擎表,其餘外部程序也能從表的數據文件中讀取CSV格式的數據。所以CSV引擎能夠做爲一種數據交換的機制,很是有用。

  Memory引擎,若是須要快速地訪問數據,而且這些數據不會被修改,重啓之後丟失也沒有關係,那麼使用Memory表是很是有用。比MyISAM錶快一個數量級,由於數據保存在內存中,不須要進行磁盤I/O。Memory表的結構在重啓之後還會保留,但數據會丟失。應用場景爲用於查找或者映射表、緩存週期性聚合數據的結果、用於保存數據分析中產生的中間數據。支持Hash索引,所以查找操做很是快。是表級鎖,所以併發寫入性能較低。不支持BLOB或TEXT類型的列,而且每行的長度固定,即便指定VARCHAR列,實際存儲也會轉成CHAR,可能致使部份內存的浪費。若是MySQL在執行查詢中須要使用臨時表保存中間結果,內部使用的臨時表就是Memory表。若是中間結果超出Memory表的限制,或者含有BLOB或TEXT字段,則臨時表會轉換成MyISAM表。

5.四、第三方存儲引擎

  OLTP類引擎

    XtraDB存儲引擎是基於InnoDB引擎的一個改進版本,已經包含在Percona Server和MariaDB中,它的改進主要集中在性能、可測量性和操做靈活性方面。

  面向列的存儲引擎

    MySQL默認是面向行的,每一行的數據是一塊兒存儲的,服務器的查詢也是以行爲單位處理的。而在大數據量處理時,面向列的方式可能效率更高。若是不須要整行的數據,能夠傳輸更少的數據,若是每一行都單獨存儲,那麼壓縮的效率也會更高。

    Infobright是最有名的面向列的存儲引擎,是爲數據分析和數據倉庫應用設計的。

5.五、選擇合適的引擎

5.六、轉換表的引擎

  將表的存儲引擎轉換成另外的一種引擎有不少方法,下面講述其中的三種方法:

  一、ALTER TABLE

    ALTER TABLE mytable ENGINE = InnoDB;

    優勢:能夠適用任何存儲引擎

    缺點:執行時間長,MySQL會按行將數據從原表複製到一張新的表中,期間可能會消耗系統全部的I/O能力,因此替代方案採用導出與導入,手工進行表的複製

    注意:若是轉換表的存儲引擎,將會失去和原引擎相關的全部特性。

  二、導出與導入

    使用工具將數據導出到文件,而後修改文件中CREATE TABLE 語句的存儲引擎選項,注意同時修改表名。注意在CREATE TABLE 語句前的DROP TABLE語句,不注意可能會致使數據丟失。

  三、建立與查詢(CREATE和SELECT)

    綜合第一種的高效和第二種的安全,不須要導出整個表的數據,先建立一個新的存儲引擎表,而後利用INSERT...SELECT語法來導數據:

    CREATE TABLE innodb_table LIKE myisam_table;

    ALTER TABLE innodb_table ENGINE=InnoDB;

    INSERT INTO innodb_table SELECT * FROM myisam_table;

    若是數據量不大,這樣作工做得很好。若是數據量大,能夠考慮分批處理,針對每一段數據執行事務提交操做。

    

    假設有主鍵字段id,重複運行如下語句(最小值x和最大值y進行相應的替換)將數據導入到新表:

    START TRANSACTION;

    INSERT INTO innodb_table SELECT * FROM myisam_table WHERE id BETWEEN x AND y;

    COMMIT;

    新表是原表的一個全量複製,原表還在。若是須要能夠刪除原表,若是有必要,能夠在執行的過程當中對原表加鎖,以確保新表和原表的數據一致。

相關文章
相關標籤/搜索