高性能mysql學習筆記

此文已由做者朱笑天受權網易雲社區發佈。
mysql

歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。sql


筆者在工做之餘閱讀了一下高性能mysql,如下的內容對mysql的介紹以及書中涉及一些概念的總結概括。數據庫

1.mysql架構
緩存

1.最上層負責連接處理、認證受權、安全等安全

2.中間一層涵蓋了mysql的大多數核心功能。包括查詢解析、分析、優化、緩存、內置函數;全部的誇存儲引擎的功能都在這一層實現(存儲過程、觸發器、視圖等)服務器

3.第三層包含了存儲引擎,存儲引擎與上層使用API進行通信,引擎之間不會有交互。數據結構

1.1鏈接層多線程

    當MySQL啓動,等待客戶端鏈接,每個客戶端鏈接請求,服務器都會新建一個線程處理,每一個線程獨立,擁有各自的內存處理空間。架構

a.鏈接處理流程併發

    這裏寫圖片描述

b.認證流程

  鏈接到服務器,服務器須要對其進行驗證,也就是用戶名、IP、密碼驗證,一旦鏈接成功,還要驗證是否具備執行某個特定查詢的權限。

這裏寫圖片描述

1.2sql處理層

    這一層主要功能有:SQL語句的解析、優化,緩存的查詢,MySQL內置函數的實現,跨存儲引擎功能,例如:存儲過程、觸發器、視圖等。

a.執行過程:

    這裏寫圖片描述

1.若是是查詢語句(select語句),首先會查詢緩存是否已有相應結果,有則返回結果,無則進行下一步(若是不是查詢語句,一樣調到下一步); 
2.解析查詢,建立一個內部數據結構(解析樹),這個解析樹主要用來SQL語句的語義與語法解析;
3.優化:優化SQL語句,例如重寫查詢,決定表的讀取順序,以及選擇須要的索引等。這一階段用戶是能夠查詢的,查詢服務器優化器是如何進行優化的,便於用戶重構查詢和修改相關配置,達到最優化。這一階段還涉及到存儲引擎,優化器會詢問存儲引擎,好比某個操做的開銷信息、是否對特定索引有查詢優化等。

1.3 存儲引擎

    存儲引擎,主要用來存儲數據的,不一樣的存儲引擎採用不一樣的技術(存儲機制、索引機制、鎖定機制)存儲數據,這主要是爲了知足數據存儲要求,好比有的數據不須要大量的改動,只用來查詢,而有的數據則須要經常修改(數據插入、刪除、更新),針對各類業務狀況,爲了更好的數據處理效率採用不一樣的數據存儲技術(即不一樣存儲引擎)。 
  MySQL的存儲引擎是插件式的,也就是說,用戶能夠隨時切換MySQL的存儲引擎:針對表或針對庫均可(經過SQL語句命令)。這種靈活性也是爲何MySQL受到歡迎的一個重要緣由。MySQL集合了多種引擎:MyISAM、InnoDB、BDB、Merge、Memory等,默認的是InnoDB(MySQL5.5開始,之前是MyISAM)。

2.併發控制

    MySQL是多線程應用,而且共享存儲數據,很顯然,當兩個及以上線程對同一塊數據進行寫將會發生數據不一致等各類問題,好比,同時對一個表增長一條記錄,後一個增長的記錄可能會覆蓋前一條,形成數據丟失。若僅僅是讀不會發生錯誤,可是當讀寫一同,就有可能發生讀錯誤,因此,對讀也是須要必要的控制。

    以上問題就須要併發控制來解決,所謂的併發,就是每一次只容許一個線程對某一塊數據(能夠是某個數據庫,或某張表,或表裏某條記錄)寫,實現併發控制有多種方式,MySQL採用的是鎖以及MVCC(多版本控制)。 

    a.讀寫鎖

    MySQL提供了兩種鎖實現併發控制:讀鎖和寫鎖。讀鎖是共享的,也叫共享鎖(也叫S鎖),相互不會阻塞,多個讀鎖(多個線程用戶)能夠同一時刻讀取統一資源;寫鎖則是排他的,也叫排他鎖(也叫X鎖),同一時間一個資源只能有一個寫鎖,也就是說,寫鎖會阻塞其餘寫鎖和讀鎖。即讀鎖上面能夠加讀鎖,但不能加寫鎖,而寫鎖則不能加任何鎖。 

  每次操做數據先判斷該數據是否加鎖,加了什麼鎖,而後以此判斷是否容許本次操做執行,但這樣是否是以爲很麻煩?很耗性能?因此纔有了數據庫事務隔離級別,統一設置一個隔離級別,數據庫系統會根據隔離級別隱式的給數據加鎖,而後根據這個級別來判斷本次操做執行權限。

    b.樂觀鎖悲觀鎖

    悲觀鎖:操做前,悲觀地認爲所操做數據在操做期間會被其餘事務修改,因此,在操做前我要先給我操做的數據加鎖才放心。至於加的是讀鎖仍是寫鎖則看具體應用場景。 

 樂觀鎖:操做前,樂觀地認爲所操做數據在操做期間不會被其餘事務修改,只在最後更新的時候(若是操做是更新的話)查看原始數據是否被修改,若是沒修改,更新數據,不然失敗。至於如何知道原始數據被修改,這就是涉及到具體實現方式了,最經常使用的就是MVCC。

    理論上,儘可能鎖定須要修改的部分,而不是全部的數據,鎖定的數據單元越小,系統的併發控制度越高,好比行級鎖,修改的時候只鎖定這一行記錄,這個時候其餘線程對該表的其餘記錄修改不影響。可是,加鎖也是須要消耗資源的,鎖的各類操做:得到鎖、檢查鎖狀態、釋放鎖等都會增長開銷,越細粒度的鎖開銷越大,過多的所操做所帶來的是性能急劇降低。 

 因此咱們要採用一種鎖策略來平衡併發度和系統性能,MySQL因爲存儲引擎的插件式,每一個存儲引擎能夠實現本身的鎖策略,因此不須要通用的鎖策略,只須要在相應應用場景下選擇相應的存儲引擎便可。 

    表鎖:

    MySQL最基本的鎖策略,顧名思義,對整張表加讀鎖和寫鎖。通常由MySQL服務器層實現,若是這個時候存儲引擎層還有鎖,優先表鎖。

   行級鎖:

 更大細粒度的鎖,只鎖住一行記錄,即對不一樣行記錄可併發操做。行級鎖只由存儲引擎層實現,MySQL服務器層沒有實現。

3.事務

    一個實現了事務處理系統(保證事務的ACID)的數據庫,相比沒有實現的,須要更強的CPU處理能力、更大的內存和更多的存儲空間,可是有些場景是不太須要事務處理能力的,也就不須要具備事務處理能力的數據庫(由於他們須要更大的資源)。 

    MySQL中InnoDB、NDB cluster存儲引擎實現了事務功能,固然還有其餘第三方存儲引擎也實現了,默認下采用自動提交模式,即若不顯式開始一個事務,每個操做當作一個事務進行操做,能夠經過設置AUTOCOMMIT變量來啓用或禁用自動提交模式,若是禁用了則需顯式執行COMMIT或ROLLBACK結束事務。

    下面針對connection_type值的不一樣作的一些實驗:

create table test(a int, primary key (a))engine=innodb;

set @@completion_type=1; 

begin;

insert into test select 1;

commit work;

insert into test select 2;

insert into test select 2;

rollback;

獲得以下結果:

    測試中,將completion_type設置成1,第一次經過commit work來insert這條記錄。以後insert 2的時候並無啓用begin(start transaction)來開啓一個事務,以後再插入一條重複的記錄2,這時會拋出異常rollback後,最後發現只有1這樣一條記錄,2並無被insert進去。由於completion_type爲1的時候,commit work會開啓另一個事務,所以2個insert語句是在同一個事務裏面的,因此回滾後就沒有insert進去。

set @@completion_type=2;

begin;

insert into test select 3;

commit work;

select @@versison;

經過上面的測試發現,completion_type設置成2時,commit work以後,再經過select獲取db服務器版本信息的時候出現2006的error,說明以及斷開了與db的鏈接。

參數completion_type爲2時,commit work等同於commit and release。當事務提交時候會自動斷開與db的鏈接。

待續。。。


免費體驗雲安全(易盾)內容安全、驗證碼等服務

更多網易技術、產品、運營經驗分享請點擊




相關文章:
【推薦】 如何準確又通俗易懂地解釋大數據及其應用價值?
【推薦】 分佈式存儲系統可靠性系列二:系統估算示例

相關文章
相關標籤/搜索