【MySQL基礎架構和運行原理☞基礎】

1.MySQL 的前世此生mysql

      MySQL 是一個開放源代碼的關係數據庫管理系統。原開發者爲瑞典的 MySQL AB 公司,最先是在 2001 年 MySQL3.23 進入到管理員的視野並在以後得到普遍的應用。 2008 年 MySQL 公司被 Sun 公司收購併發佈了首個收購以後的版本 MySQL5.1 ,該版本引入分區、基於行復制以及plugin API 。移除了原有的 BerkeyDB 引擎,同時, Oracle 收購 InnoDB Oy 發佈了 InnoDB plugin,這後來發展成爲著名的 InnoDB 引擎。 2010 年 Oracle 收購 Sun 公司,這也使得 MySQL 納入 Oracle 門下,以後 Oracle 發佈了收購之後的首個版本 5.5 ,該版本主要改善集中在性能、擴展性、複製、分區以及對 windows 的支持。目前版本已發展到 5.7。算法

   和其它數據庫相比, MySQL 有點不同凡響,它的架構能夠在多種不一樣場景中應用併發揮良好做用。主要體如今存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構能夠根據業務的需求和實際須要選擇合適的存儲引擎。sql

二、MySQL總體邏輯架構數據庫

 

第一層,即最上一層,所包含的服務並非MySQL所獨有的技術。它們都是服務於C/S程序或者是這些程序所須要的 :鏈接處理,身份驗證,安全性等等。windows

第二層,值得關注。這是MySQL的核心部分。一般叫作 SQL Layer。在 MySQL據庫系統處理底層數據以前的全部工做都是在這一層完成的,包括權限判斷, sql解析,行計劃優化, query cache 的處理以及全部內置的函數(如日期,時間,數學運算,加密)等等。各個存儲引擎提供的功能都集中在這一層,如存儲過程,觸發器,視 圖等。緩存

第三層,包括了存儲引擎。一般叫作StorEngine Layer ,也就是底層數據存取操做實現部分,由多種存儲引擎共同組成。它們負責存儲和獲取全部存儲在MySQL中的數據。就像Linux衆多的文件系統 同樣。每一個存儲引擎都有本身的優勢和缺陷。服務器是經過存儲引擎API來與它們交互的。這個接口隱藏 了各個存儲引擎不一樣的地方。對於查詢層儘量的透明。這個API包含了不少底層的操做。如開始一個事 物,或者取出有特定主鍵的行。存儲引擎不能解析SQL,互相之間也不能通訊。僅僅是簡單的響應服務器 的請求。安全

鏈接管理和安全bash

在服務器內部,每一個client鏈接都有本身的線程。這個鏈接的查詢都在一個單獨的線程中執行。這些線程輪流運行在某一個CPU內核(多核CPU)或者CPU中。服務器緩存了線程,所以不須要爲每一個client鏈接單首創建和銷燬線程 。服務器

當clients(也就是應用程序)鏈接到了MySQL服務器。服務器須要對它進行認證(Authenticate)。認證是基於用戶名,主機,以及密碼。對於使用了SSL(安全套接字層)的鏈接,還使用了X.509證書。clients一鏈接上,服務器就驗證它的權限 (如是否容許客戶端能夠查詢world數據庫下的Country表的數據)。數據結構

優化和執行

MySQL會解析查詢,並建立了一個內部數據結構(解析樹)。而後對其進行各類優化。這些優化包括了,查詢語句的重寫,讀表的順序,索引的選擇等等。用戶能夠經過查詢語句的關鍵詞傳遞給優化器以便提示使用哪一種優化方式,這樣即影響了優化器的優化方式。另外,用戶也能夠請求服務器給出優化過程的各類說明,以獲知服務器的優化策略,爲用戶提供了參數基準,以便用戶能夠重寫查詢,架構和修改相關服務器配置,便於mysql更高效的運行。

優化器並是不關心表使用了哪一種存儲引擎,可是存儲引擎對服務器優化查詢的方式是有影響的。優化器須要知道存儲引擎的一些特性:具體操做的性能和開銷方面的信息,以及表內數據的統計信息。例如,存儲引擎支持哪些索引類型,這對於查詢是很是有用的。

在解析查詢以前,要查詢緩存,這個緩存只能保存查詢信息以及結果數據。若是請求一個查詢在緩存 中存在,就不須要解析,優化和執行查詢了。直接返回緩存中所存放的這個查詢的結果。

3.MySQL邏輯模塊組成

雖然從上圖1看起來 MySQL 架構很是的簡單,就是簡單的兩部分而已,但實際上每一層 中都含有各自的不少小模塊,尤爲是第二層 SQL Layer ,結構至關複雜的。下面咱們就分別 針對 SQL Layer 和 Storage Engine Layer 作一個簡單的分析。

3.1.Connectors

 指的是不一樣語言中與SQL的交互

3.2 Management Serveices & Utilities: 

系統管理和控制工具

3.3 Connection Pool: 鏈接池

管理緩衝用戶鏈接,線程處理等須要緩存的需求。

負責監聽對 MySQL Server 的各類請求,接收鏈接請求,轉發全部鏈接請求到線程管理模塊。每個鏈接上 MySQL Server 的客戶端請求都會被分配(或建立)一個鏈接線程爲其單獨服務。而鏈接線程的主要工做就是負責 MySQL Server 與客戶端的通訊,
接受客戶端的命令請求,傳遞 Server 端的結果信息等。線程管理模塊則負責管理維護這些鏈接線程。包括線程的建立,線程的 cache 等。

3.4 SQL Interface: SQL接口。

接受用戶的SQL命令,而且返回用戶須要查詢的結果。好比select from就是調用SQL Interface

3.5 Parser: 解析器。

SQL命令傳遞到解析器的時候會被解析器驗證和解析。解析器是由Lex和YACC實現的,是一個很長的腳本。

在 MySQL中咱們習慣將全部 Client 端發送給 Server 端的命令都稱爲 query ,在 MySQL Server 裏面,鏈接線程接收到客戶端的一個 Query 後,會直接將該 query 傳遞給專門負責將各類 Query 進行分類而後轉發給各個對應的處理模塊。
主要功能:
a . 將SQL語句進行語義和語法的分析,分解成數據結構,而後按照不一樣的操做類型進行分類,而後作出針對性的轉發到後續步驟,之後SQL語句的傳遞和處理就是基於這個結構的。
b.  若是在分解構成中遇到錯誤,那麼就說明這個sql語句是不合理的

3.6 Optimizer: 查詢優化器。

SQL語句在查詢以前會使用查詢優化器對查詢進行優化。就是優化客戶端請求的 query(sql語句) ,根據客戶端請求的 query 語句,和數據庫中的一些統計信息,在一系列算法的基礎上進行分析,得出一個最優的策略,告訴後面的程序如何取得這個 query 語句的結果

他使用的是「選取-投影-聯接」策略進行查詢。
       用一個例子就能夠理解: select uid,name from user where gender = 1;
       這個select 查詢先根據where 語句進行選取,而不是先將表所有查詢出來之後再進行gender過濾
       這個select查詢先根據uid和name進行屬性投影,而不是將屬性所有取出之後再進行過濾
       將這兩個查詢條件聯接起來生成最終查詢結果

3.7 Cache和Buffer: 查詢緩存。

他的主要功能是將客戶端提交 給MySQL 的 Select 類 query 請求的返回結果集 cache 到內存中,與該 query 的一個 hash 值 作
一個對應。該 Query 所取數據的基表發生任何數據的變化以後, MySQL 會自動使該 query 的Cache 失效。在讀寫比例很是高的應用系統中, Query Cache 對性能的提升是很是顯著的。固然它對內存的消耗也是很是大的。

若是查詢緩存有命中的查詢結果,查詢語句就能夠直接去查詢緩存中取數據。這個緩存機制是由一系列小緩存組成的。好比表緩存,記錄緩存,key緩存,權限緩存等

3.8 、存儲引擎接口

存儲引擎接口模塊能夠說是 MySQL 數據庫中最有特點的一點了。目前各類數據庫產品中,基本上只有 MySQL 能夠實現其底層數據存儲引擎的插件式管理。這個模塊實際上只是 一個抽象類,但正是由於它成功地將各類數據處理高度抽象化,才成就了今天 MySQL 可插拔存儲引擎的特點。

     從圖2還能夠看出,MySQL區別於其餘數據庫的最重要的特色就是其插件式的表存儲引擎。MySQL插件式的存儲引擎架構提供了一系列標準的管理和服務支持,這些標準與存儲引擎自己無關,多是每一個數據庫系統自己都必需的,如SQL分析器和優化器等,而存儲引擎是底層物理結構的實現,每一個存儲引擎開發者均可以按照本身的意願來進行開發。
    注意:存儲引擎是基於表的,而不是數據庫。

4 併發控制

    數據庫中有多個操做須要修改同一數據時,不可避免的會產生數據的髒讀。這時就須要數據庫具備良好的併發控制能力,這一切在MySQL中都是由服務器和存儲引擎來實現的。

解決併發問題最有效的方案是引入了鎖的機制,鎖在功能上分爲共享鎖(shared lock)和排它鎖(exclusive lock)即一般說的讀鎖和寫鎖。當一個select語句在執行時能夠施加讀鎖,這樣就能夠容許其它的select操做進行,由於在這個過程當中數據信息是不會被改變的這樣就可以提升數據庫的運行效率。當須要對數據更新時,就須要施加寫鎖了,不在容許其它的操做進行,以避免產生數據的髒讀和幻讀。鎖一樣有粒度大小,有表級鎖(table lock)和行級鎖(row lock),分別在數據操做的過程當中完成行的鎖定和表的鎖定。這些根據不一樣的存儲引擎所具備的特性也是不同的。

MySQL大多數事務型的存儲引擎都不僅是簡單的行級鎖,基於性能的考慮,他們通常在行級鎖基礎上實現了多版本併發控制(MVCC)。這一方案也被Oracle等主流的關係數據庫採用。它是經過保存數據中某個時間點的快照來實現的,這樣就保證了每一個事務看到的數據都是一致的。詳細的實現原理能夠參考《高性能MySQL》第三版。

4.1 讀寫鎖

在處理併發讀或寫時,能夠經過實現一個由兩種類型的鎖組成的鎖系統來解決問題。這兩種類型的鎖一般被稱爲共享鎖或和排他鎖,也叫讀鎖和寫鎖

讀鎖是共享的,或者說是相互不阻塞的。多個客戶在同一時刻能夠同時讀取同一個資源而不相互干擾

寫鎖是排他的,一個寫鎖會阻塞其餘的寫鎖和讀鎖,

Mysql鎖的內部管理是透明的

4.2. 鎖粒度

一種提升共享資源併發性的方式就是讓鎖定對象更有選擇性。儘可能只鎖定須要修改的部分數據,而不是全部的資源。更理想的方式是,只對會修改的數據片進行精確的鎖定。在給定的資源上,鎖定的數據量越少,則系統的併發程度越高。所謂的鎖策略,就是在鎖的開銷和數據的安全性之間尋求平衡。下面將介紹兩種最重要的鎖策略。

表鎖

表鎖的Mysql中最基本的鎖策略,而且是開銷最小的策略。它會鎖定整張表,一個用戶在對錶進行寫操做前,須要先獲取寫鎖,這會阻塞其餘用戶對該表的全部讀寫操做。

行級鎖

行級鎖能夠最大程度地支持併發處理(同時也帶來了最大的鎖開銷),行級鎖只在存儲引擎層實現,而Mysql服務器層沒有實現。

4.3 事務

簡單的說事務就是一組原子性的SQL語句。能夠將這組語句理解成一個工做單元,要麼所有執行要麼都不執行。默認MySQL中自動提交時開啓的(start transaction)。

事務具備ACID的特性:

原子性:事務中的全部操做要麼所有提交成功,要麼所有失敗回滾。好比你從取款機取錢,這個事務能夠分紅兩個步驟:1劃卡,2出錢.不可能劃了卡,而錢卻沒出來.這兩步必須同時完成.要麼就不完成. 

一致性:數據庫老是從給一個一致性的狀態轉換到另外一個一致性的狀態。例如,完整性約束了a+b=10,一個事務改變了a,那麼b也應該隨之改變.無論數據怎麼改變。必定是符合約束。

隔離性:一個事務所作的修改在提交以前對其它事務是不可見的,兩個以上的事務不會出現交錯執行的狀態.由於這樣可能會致使數據不一致。

持久性:一旦事務提交,其所作的修改便會永久保存在數據庫中,即硬盤上。

事務的隔離級別:

READ UNCOMMITTED(讀未提交):事務中的修改即便未提交也是對其它事務可見。

READ COMMITTED(讀提交):事務提交後所作的修改纔會被另外一個事務看見,可能產生一個事務中兩次查詢的結果不一樣。

REPEATABLE READ(可重讀):只有當前事務提交才能看見另外一個事務的修改結果。解決了一個事務中兩次查詢的結果不一樣的問題。

SERIALIZABLE(串行化):只有一個事務提交以後纔會執行另外一個事務。

查詢並修改隔離級別:

死鎖:

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

對於死鎖的處理:MySQL的部分存儲引擎可以檢測到死鎖的循環依賴併產生相應的錯誤。InnoDB引擎解決的死鎖的方案是將持有最少寫鎖的事務進行回滾。

爲了提供回滾或者撤銷未提交的變化的能力,許多數據源採用日誌機制。例如:sql server使用一個預寫事務日誌,在將數據應用於(或提交到)實際數據頁面前,先寫在事務日誌上。可是,其餘一些數據源不是關係型數據庫管理系統,他們管理未提交事務的方式徹底不一樣。只要事務回滾時,數據源能夠撤銷全部未提交的改變,那麼這種技術可用於事務管理。

經常使用MySQL存儲引擎介紹:

InnoDB引擎:

將數據存儲在表空間中,表空間由一系列的數據文件組成,由InnoDb管理,支持每一個表的數據和索引存放在單獨文件中(innodb_file_per_table);

支持事務,採用MVCC來控制併發,並實現標準的4個事務隔離級別,支持外鍵;

索引基於聚簇索引創建,對主鍵查詢有較高性能;

數據文件的平臺無關性,支持數據在不一樣的架構平臺移植;

可以經過一些工具支持真正的熱備,如XtraBackup等;

內部進行自身優化如採起可預測性預讀,可以自動在內存中建立bash索引等。

MyISAM引擎:

MySQL5.1默認,不支持事務和行級鎖

提供大量的特性如全文索引、空間函數、壓縮、延遲更新等

數據庫故障後,安全恢復性高

對於只讀數據能夠忍受故障恢復,MyISAM依然很是適用

日誌服務器的場景也比較適用,只需插入和數據讀取操做

不支持單表一個文件,會將全部的數據和索引內容分別存放在兩個文件中

MyISAM對整張表加鎖而不是對行,因此不適用寫操做比較多的場景

支持索引緩存不支持數據緩存

相關文章
相關標籤/搜索