天天看點

高性能mysql學習筆記

此文已由作者朱笑天授權網易雲社群釋出。

歡迎通路網易雲社群,了解更多網易技術産品營運經驗。

筆者在工作之餘閱讀了一下高性能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;

rollback;

得到如下結果:

高性能mysql學習筆記

    測試中,将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;

insert into test select 3;

select @@versison;

高性能mysql學習筆記

通過上面的測試發現,completion_type設定成2時,commit work之後,再通過select擷取db伺服器版本資訊的時候出現2006的error,說明以及斷開了與db的連接配接。

參數completion_type為2時,commit work等同于commit and release。當事務送出時候會自動斷開與db的連接配接。

待續。。。

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

更多網易技術、産品、營運經驗分享請點選。

相關文章:

【推薦】 當Shell遇上了NodeJS