mysql三層體系

Mysql:是單進程多線程數據庫。mysql

MySQL分層:算法

mysql分三層:網絡鏈接層, sql層, 存儲引擎層,而網絡鏈接層與sql層合稱server層,故mysql又分server層合儲存引擎層。

第一層:
處理網絡連接,連接的網絡認證。當客戶端連接到服務器的時候,每一個客戶端連接都有一個線程,這個連接的查詢只會在該線程中執行。

第二層:是SQL的查詢解析,分析,和優化,緩存以及全部的內置函數,全部存儲引擎的功能都在這一層實現,好比存儲過程。MySQL在解析SQL的時候,會在服務器層建立解析樹,而後經過查詢重寫,決定表的讀取順序,以及選擇合適的索引等等。雖然優化策略是服務器層決定的,可是統計信息是存儲引擎層提供的。sql

第三層:存儲引擎層,存儲引擎負責MySQL中數據的存儲和提取,存儲引擎不會互相通訊。數據庫

 

第1層網絡鏈接層介紹:網絡鏈接層主要有鏈接池和線程池。緩存

網絡鏈接層的做用:安全

 鏈接與線程處理,好比鏈接處理、受權認證、安全等。(通訊協議,線程,驗證)


mysql的鏈接管理方式:
服務器

Mysql-Server同時支持3種鏈接管理方式,包括No-Threads,One-Thread-Per-Connection和Pool-Threads。
No-Threads:表示處理鏈接使用主線程處理,不額外建立線程,這種方式主要用於調試;
One-Thread-Per-Connection:是線程池出現之前最經常使用的方式,爲每個鏈接建立一個線程服務;
Pool-Threads:則是線程池方式。

爲何有鏈接池和線程池?網絡

 每建立一個新的會話(或連接),mysql內部建立一個新的用戶線程來提供服務,當鏈接被銷燬,線程也被銷燬.即一個鏈接有一個線程.這種建立連接和銷燬連接都會消耗cpu性能.爲了下降這種消耗,有了鏈接池和線程池.

鏈接池(connection pool):數據結構

鏈接池:在客戶端部署。客戶端建立預先建立必定的鏈接,利用這些鏈接服務於客戶端全部的DB請求。若是某一個時刻,空閒的鏈接數小於DB的請求數,則須要將請求排隊,等待空閒鏈接處理。經過鏈接池能夠複用鏈接,避免鏈接的頻繁建立和釋放,從而減小請求的平均響應時間,而且在請求繁忙時,經過請求排隊,能夠緩衝應用對DB的衝擊。當鏈接斷開,鏈接將回歸鏈接池。

線程池(thread pool):多線程

 線程池:在服務器端部署。經過建立必定數量的線程服務DB請求,有了線程池,當有了新鏈接,能夠直接從線程池裏拿線程,斷開時,也不銷燬線程,而是回放進線程池。與一個線程服務一個鏈接的方式對比,線程池服務的最小單位是語句,即一個線程能夠對應多個活躍的鏈接。經過線程池,能夠將server端的服務線程數控制在必定的範圍,減小了系統資源的競爭和線程上下切換帶來的消耗,同時也避免出現高鏈接數致使的高併發問題。
說明:在mysql社區版無線程池功能. 在第三方perconadb 和mysql商業版有其功能.

線程池帶來的問題1:調度死鎖(解決方法是添加優先級隊列)

引入線程池解決了多線程高併發的問題,但也帶來一個隱患。假設,A,B兩個事務被分配到不一樣的group中執行,A事務已經開始,而且持有鎖,但因爲A所在的group比較繁忙,致使A執行一條語句後,不能當即得到調度執行;而B事務依賴A事務釋放鎖資源,雖然B事務能夠被調度起來,但因爲沒法得到鎖資源,致使仍然須要等待,這就是所謂的調度死鎖。因爲一個group會同時處理多個鏈接,但多個鏈接不是對等的。好比,有的鏈接是第一次發送請求;而有的鏈接對應的事務已經開啓,而且持有了部分鎖資源。爲了減小鎖資源爭用,後者顯然應該比前者優先處理,以達到儘早釋放鎖資源的目的。所以在group裏面,能夠添加一個優先級隊列,將已經持有鎖的鏈接,或者已經開啓的事務的鏈接發起的請求放入優先隊列,工做線程首先從優先隊列獲取任務執行。

線程池帶來的問題2:大查詢處理解決方法是設置thread_pool_oversubscribe

某個group裏面的鏈接都是大查詢,那麼group裏面的工做線程數很快就會達到thread_pool_oversubscribe參數設置值,對於後續的鏈接請求,則會響應不及時(沒有更多的鏈接來處理),這時候group就發生了stall。經過前面分析知道,timer線程會按期檢查這種狀況,並建立一個新的worker線程來處理請求。若是長查詢來源於業務請求,則此時全部group都面臨這種問題,此時主機可能會因爲負載過大,致使hang住的狀況。這種狀況線程池自己無能爲力,由於源頭多是爛SQL併發,或者SQL沒有走對執行計劃致使,經過其餘方法,好比SQL高低水位限流或者SQL過濾手段能夠應急處理。可是,還有另一種狀況,就是dump任務。不少下游依賴於數據庫的原始數據,一般經過dump命令將數據拉到下游,而這種dump任務一般都是耗時比較長,因此也能夠認爲是大查詢。若是dump任務集中在一個group內,並致使其餘正常業務請求沒法當即響應,這個是不能容忍的,由於此時數據庫並無壓力,只是由於採用了線程池策略,才致使了請求響應不及時,爲了解決這個問題,咱們將group中處理dump任務的線程不計入thread_pool_oversubscribe累計值,避免上述問題。

鏈接池和線程池說明:

鏈接池主要用來管理客戶端的鏈接,避免重複的鏈接/斷開操做,是將空閒的鏈接緩存起來,能夠複用。從而減小了鏈接mysql server/斷開mysql server的開銷與成本,從而提高性能。

可是mysql的鏈接池不能獲取mysql server的查詢處理能力以及當前的負載狀況。

線程池:線程池的操做是在mysql server端,而且設計就是用來管理當前併發的鏈接和查詢。

thread pool到底可以提高多少性能?

根據Oracle Mysql官方的性能測試:

在併發達到128個鏈接之後.沒有線程池的Mysql性能會迅速下降。使用線程池之後,性能不會出現波動,會一直保持在較好的狀態運行。

在讀寫模式下,128個鏈接之後,有線程池的Mysql比沒有線程池的Mysql性能高出60倍。

在只讀模式下,512個鏈接之後,有線程池的Mysql比沒有線程池的Mysql性能高出18倍。

何時能夠考慮使用thread_pool?

 show global status like '%threads_running%';其值是mysql server當前併發執行語句的數量,若是這個值一直保持在40左右的區間,那麼能夠考慮使用thread pool。

若是你使用了innodb_thread_concurrency參數來控制併發的事物量,那麼使用線程池將會得到更好的效果。

若是你的工做是有不少短鏈接組成的,那麼使用線程池是有益的。

 

第2層sql處理層(SQL Layer):主要有SQL Interface、Parser、Optimizer、Cache和Buffer

Sql層功能:
功能:解析器,受權,優化器,查詢執行,查詢高速緩存,查詢日誌記錄,跨存儲引擎功能。

1.解析器:解析SQL語法,造成語法樹

2.受權:SQL的權限驗證  *.*對於指定的庫和表

3.優化器:CBO(基於成本的優化),根據統計信息--> SQL改寫 --->執行計劃(即選哪一種算法執行)

sql層處理數據流程:

用戶傳入sql-----查詢緩存(命中緩存可直接返回結果)----解析器(生成sql解析樹)----預處理器(可能sql等價改寫)-----查詢優化器(生成sql執行計劃)----查詢執行引擎----結果返回給用戶。

 

SQL接口:(SQL Interface)

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


解析器:(Parser)--生成sql解析樹

SQL命令傳遞到解析器的時候會被解析器驗證和解析(進行語義和語法的分析,分解成數據結構,若是在分解構成中遇到錯誤,那麼就說明這個sql語句是不合理的 ),生成sql解析樹。解析器是由Lex和YACC實現的,是一個很長的腳本。

 

查詢優化器:(Optimizer) --生成執行計劃

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

選取-投影-聯接:

用一個例子就能夠理解: select uid,name from user where gender = 1;

這個select 查詢先根據where 語句進行選取,而不是先將表所有查詢出來之後再進行gender過濾。

這個select查詢先根據uid和name進行屬性投影,而不是將屬性所有取出之後再進行過濾。

將這兩個查詢條件聯接起來生成最終查詢結果。

 

查詢緩存功能(Cache和Buffer):(建議關閉)

當執行sql的時候,sql第一次被執行,而後再次執行的時候若是相同的sql,能夠不進行解析,直接返回結果,提升查詢效率.

關閉查詢緩存:query_cache_type = 0    query_cache_size = 0

侷限性比較大,任何查詢結果有變動,都須要進行更新,對於mysql性能影響比較嚴重,整個更新過程的鎖顆粒度的比較高,還持有全局鎖,效率很低.

建議:是否使用查詢緩存,不用.(在mysql8.0裏沒了查詢緩存功能.)

問題:如何計算和提升查詢緩存命中率?

 

第3層儲存引擎層(StorEngine Layer):

儲存引擎層功能:

存儲引擎,也稱爲表類型,真正的負責了MySQL中數據的存儲和提取,儲存引擎層由多種存儲引擎共同組成。它們負責存儲和獲取全部存儲在MySQL中的數據。就像Linux衆多的文件系統 同樣。每一個存儲引擎都有本身的優勢和缺陷。服務器是經過存儲引擎API來與它們交互的。存儲引擎不能解析SQL,互相之間也不能通訊。僅僅是簡單的響應服務器 的請求。存儲引擎不會互相通訊。不一樣的存儲引擎採用不一樣的技術(存儲機制、索引機制、鎖定機制)存儲數據。
MySQL的存儲引擎是插件式的,也就是說,用戶能夠隨時切換MySQL的存儲引擎:針對表或針對庫均可(經過SQL語句命令)。MySQL集合了多種引擎:MyISAM、InnoDB、BDB、Merge、Memory等,默認的是InnoDB。

儲存引擎層說明:

一、根據上層獲取數據的方法(執行計劃),將數據提取出來。

二、從新再交給SQL層。

三、是MYSQL數據庫的核心,關係到數據庫性能。

四、存儲引擎是基於表的,而不是數據庫。

常見的MySQL的存儲引擎及特色:

 存儲引擎                   特色

InnoDB          持事務安全。可是對比MyISAM引擎,寫的處效率會差些

MyISAM          支持事務,插速度般innodb快一些

Memory          數據存儲於內存之中

CSV            數據存儲爲CSV件格式,不進轉換

查看mysql儲存引擎:

mysql> show plugins;           ---查看插件及其狀態
mysql> show engines;          ---查看目前支持的儲存引擎


InnoDB和MyISAM區別:

 InnoDB                                                                                MyISAM

索引組織表                              堆表

鎖                                  表鎖

物理結構不一樣,數據索引在起(.frm)       物理結構不一樣,數據索引分開(.MYD .MYI)

支持事務                             不支持事務

支持外鍵                             不支持外鍵

MVCC多版本控制                           

INNODB緩存索引和數據                     MyISAM只緩存索引塊

說明:

 經過對開關binlog前後的測試發現,其實MySIAM的插性能要好於INNODB,這和MySIAM不支持事務,鎖開銷也較有關。 可是MySiam的表鎖讓該引擎不能在併發下工做,由於會形成的鎖衝突。在線業務OLTP業務,強烈不建議使MySIAM的存儲引擎,併發效率很低。

建立表時指定儲存引擎:

create table test1

(

id int,

name varchar(11)

)engine=innodb;


 create table test2

(

id int,

name varchar(11)

)engine=myisam ;

 


InnoDB的物理存儲結構:

 test1.frm        #表結構文件

test1.ibd   #表數據文件(存儲數據和索引)

MySIAM的物理存儲結構:

 test2.frm        #表結構文件

test2.MYD   #表數據文件

test2.MYI   #表索引文件

修改MyISAM表結構到InnoDB表:

 alter table test2 engine = innodb;

show create table test2\G;

Create Table: CREATE TABLE `test2` (

`id` int(11) DEFAULT NULL,

`name` varchar(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8


注意: MySQL 的系統表, user 等不能轉化爲 InnoDB 格式,他們必須採用 MyISAM 格式!!

相關文章
相關標籤/搜索