mysql三层体系
Mysql:是單進程多線程數據庫。
MySQL分層:
| mysql分三層:網絡連接層, sql層,存儲引擎層,而網絡連接層與sql層合稱server層,故mysql又分server層合儲存引擎層。 第一層:處理網絡鏈接,鏈接的網絡認證。當客戶端鏈接到服務器的時候,每個客戶端鏈接都有一個線程,這個鏈接的查詢只會在該線程中執行。 第二層:是SQL的查詢解析,分析,和優化,緩存以及所有的內置函數,所有存儲引擎的功能都在這一層實現,比如存儲過程。MySQL在解析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。 | 
儲存引擎層說明:
| 1、根據上層獲取數據的方法(執行計劃),將數據提取出來。 2、重新再交給SQL層。 3、是MYSQL數據庫的核心,關系到數據庫性能。 4、存儲引擎是基于表的,而不是數據庫。 | 
常見的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; 
 ( 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 test2G; Create Table: CREATE TABLE `test2` ( `id` int(11) DEFAULT NULL, `name` varchar(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 
注意:MySQL的系統表,user等不能轉化為InnoDB格式,他們必須采用MyISAM格式!!
總結
 
                            
                        - 上一篇: HBuilder与夜神模拟器连接步骤
- 下一篇: java pdfBox给PDF添加图片水
