總結之:CentOS 6.5 MySQL數據庫的基礎以及深刻詳解

前言mysql

   早期MySQL AB公司在2009年10億美圓賣給了sun公司,然而不幸的是sun在2010年被Oracle收購了,而sun被Oracle收購的時候,而不少人都知道Oracle都是把競爭對手收下來打入冷宮,再也不銷售,這是它一慣的手法了,雖然承諾5年內不會對MySQL下手,但5年很快就過去了。

   MySQL的原做者在sun被Oracle收購了以後就另立門戶,在MySQL的基礎上提供了另一個分支,就是MariaDB,Maria是做者的小女兒,因此以做者的小女兒的名字命名的數據;MariaDB在兼容MySQL的基礎上還整合了開源社區中很強大的支持力量,而percona公司致力於MySQL的優化,並且還取得了不扉的成績的一個組織,percona在改進早期的InnoDB的基礎上提供了加強版的xtradb,這是加強版的InnoDB,而MariDB中用的就是xtradb還再也不是InnoDB了,此外MariaDB中還引入了像MyISAM的加強版、改進版,因此MariaDB在存儲引擎上可能在着不小的差別,但這種差別是在前面的基礎上進化而來的,因此MySQL的知識依然適用於MariaDB,總的來講,MariaDB比MySQL有過之而無不及。

SQL:Structure Query Language 結構查詢語言
   DDL(數據定義語言):CREATE, DROP, ALTER
   DML(數據操縱語言):SELECT, INSERT, UPDATE,
   DCL(數據控制語言):GRANT, REVOKE

   所謂關係型模型:就是二維關係結構,有所謂的行和列組成的表,一張或多張表組合起來的數據庫。算法


MySQL在內部是如何工做的:
   第一層:這一層是負責跟用戶請求進行鏈接的,每一個客戶端鏈接都會在這層上擁有一個線程,mysql是單進程多純種模型的,mysql的線程有不少種類型,一類是負責跟用戶鏈接的叫鏈接線程,另外一類是不斷的把緩衝池中的數據同步的磁盤中去的叫刷寫線程,甚至不一樣的存儲引擎背後還維持着多種線程,因此mysql的線程有不少種,那麼負責跟用戶創建鏈接的咱們一般叫做鏈接線程。
mysql支持的併發鏈接數是有限的,由於咱們的資源是有限的,mysql尤爲是MariaDB在對線程管理時是經過線程池(thread pool)來實現的,其實不少基於線程的機制都是基於線程池來管理的,mysql在啓動時會在池子中建立一些空閒的線程,當用戶請求到來時就會使用這些空閒的線程接收用戶的請求,來一個用戶鏈接給他一個線程,當mysql的鏈接達到上限時,新進來的鏈接就要排隊,mysql或MariaDB維持有一個隊列,前面處理的線程一旦完成了線程就會空閒下來了,空閒下來的線程不會被銷燬,而是把裏面的數據清理一下,還原成原來的樣子,再接收新的用戶請求,因此mysql的這種機制就叫線程重用。
   而在客戶端跟mysql服務器端鏈接時要經過mysql協議創建通訊,mysql這個協議通常來說有兩種格式,http協議是文件格式的,而https是二進制的,因此咱們的協議就是這兩種格式,然而mysql協議這兩個格式的協議都支持,可是二進制格式的協議要高效一些,因此支持兩種格式的默認都是二進制格式的,mysql協議默認是明文的,而二進制其實就是經過二進制編碼以後的格式而,若是用一個反編碼工具就很容易就破解了這種格式的數據,因此數據不安全,這們咱們就引入加密了,將他的協議基於ssl加密後發送。

   第二層:MySQL的解析,Parser是個解析器,也叫分析器,他的主要功能就是分析查詢語句的,首先要作詞法分析,要把select語句切割成一片片的片斷,再作語法分析,看看整個句子有沒有語法錯誤,甚至還要作語意分析,這些都是由分析器來完成的,固然mysql並無開發本身的分析器,yacc,lex,mysql直接借用了這些分析器作二次開發並整合到mysql中去的,分析器就是分析語句確保語句沒有問題、還有請求權限也沒有問題,接着分析完了以後交給優化器(Optimizer)作優化了,優化器所要作的操做包括重寫查詢,若是查詢語句不夠好就會被重寫,把語句重構建一下,但返回的結果必定是同樣的,優化器還包括決定表的讀取順序,若是咱們作多表查詢的話就要有個前後順序了,若是你寫的查詢語句的前後是A,B,C,但優化器認爲B,A,C更高效,因而優化器就會調整表的讀取順序的,另一個若是咱們在多張表上查詢時有多個索引,優化器也會從中選擇一個開銷最小的索引,可是優化器也是能夠接受用戶建議的,若是咱們知道怎麼寫可讓查詢語句更優秀,那咱們就儘量寫的優秀來影響人優化器。
   mysql在查詢時到底有沒有用到索引而且用到了什麼樣的索引是能夠用一個語句作分析的,叫explain,因此explain是咱們未來去作mysql語句優化或者作查看mysql是否可以按照咱們預設的目的去使用索引的一個很是重要的分析工具,固然explain的結果也只是參考

   第三層:優化器並不關心mysql底層那個張真正使用什麼存儲引擎的,可是咱們知道,存儲引擎根據他的工做特性的不一樣提供的性能表現也不相同,但好在優化器會經過向存儲引擎的API發起調用請求讓存儲引擎返回這個存儲引擎下所對應的表的統計數據來判斷這個張的查詢開銷有多大,並基於此做爲判斷,因此說Optimizer能夠跟存儲引擎交互,並利用存儲引擎內部的統計數據作出優化決策的,這裏咱們說的是廣義上的查詢,UPDATE,INSERT,DELETE,這些都要查詢,而若是是真正的查詢語句的話mysql還可使用Query Cache來發揮功效的,因此Query Cache只對咱們的select語句有效,只有select纔會被緩存下來。
sql


SQL Layer 中包含了多個子模塊,下面我將逐個作一下簡單的介紹:數據庫


邏輯模塊組成api

1 、初始化模塊
   顧名思議,初始化模塊就是在MySQL Server啓動的時候,對整個系統作各類各樣的初始化操做,好比各類 buffer,cache 結構的初始化和內存空間的申請,各類系統變量的初始化設定,各類存儲引擎的初始化設置,等等。
2 、核心 API
   核心 API 模塊主要是爲了提供一些須要很是高效的底層操做功能的優化實現,包括各類底層數據結構的實現,特殊算法的實現,字符串處理,數字處理等,小文件 I/O ,格式化輸出,以及最重要的內存管理部分。核心 API 模塊的全部源代碼都集中在 mysys 和 strings文件夾下面,有興趣的讀者能夠研究研究。
3 、網絡交互模塊
   底層網絡交互模塊抽象出底層網絡交互所使用的接口 api ,實現底層網絡數據的接收與發送,以方便其餘各個模塊調用,以及對這一部分的維護。全部源碼都在 vio 文件夾下面。
4 、 Client & Server 交互協議模塊
   任何 C/S 結構的軟件系統,都確定會有本身獨有的信息交互協議, MySQL 也不例外。 MySQL的 Client & Server 交互協議模塊部分,實現了客戶端與 MySQL 交互過程當中的全部協議。
固然這些協議都是創建在現有的 OS 和網絡協議之上的,如 TCP/IP 以及 Unix Socket 。
5 、用戶模塊
   用戶模塊所實現的功能,主要包括用戶的登陸鏈接權限控制和用戶的受權管理。他就像MySQL 的大門守衛同樣,決定是否給來訪者 「 開門 」 。
6 、訪問控制模塊
   造訪客人進門了就能夠想幹嗎就幹嗎麼?爲了安全考慮,確定不能如此隨意。這時候就須要訪問控制模塊實時監控客人的每個動做,給不一樣的客人以不一樣的權限。訪問控制模塊實現的功能就是根據用戶模塊中各用戶的受權信息,以及數據庫自身特有的各類約束,來控制用戶對數據的訪問。用戶模塊和訪問控制模塊二者結合起來,組成了 MySQL 整個數據庫系統的權限安全管理的功能。
7 、鏈接管理、鏈接線程和線程管理
   鏈接管理模塊負責監聽對 MySQL Server 的各類請求,接收鏈接請求,轉發全部鏈接請求到線程管理模塊。每個鏈接上 MySQL Server 的客戶端請求都會被分配(或建立)一個鏈接線程爲其單獨服務。而鏈接線程的主要工做就是負責 MySQL Server 與客戶端的通訊,接受客戶端的命令請求,傳遞 Server 端的結果信息等。線程管理模塊則負責管理維護這些鏈接線程。包括線程的建立,線程的 cache 等。
8 、 Query 解析和轉發模塊
   在 MySQL 中咱們習慣將全部 Client 端發送給 Server 端的命令都稱爲 query ,在 MySQ LServer 裏面,鏈接線程接收到客戶端的一個 Query 後,會直接將該 query 傳遞給專門負責將各類 Query 進行分類而後轉發給各個對應的處理模塊,這個模塊就是 query 解析和轉發模塊。其主要工做就是將 query 語句進行語義和語法的分析,而後按照不一樣的操做類型進行 分類,而後作出針對性的轉發。
9 、 Query Cache 模塊
   Query Cache 模塊在 MySQL 中是一個很是重要的模塊,他的主要功能是將客戶端提交給MySQL 的 Select 類 query 請求的返回結果集 cache 到內存中,與該 query 的一個 hash 值作一個對應。該 Query 所取數據的基表發生任何數據的變化以後, MySQL 會自動使該 query 的Cache 失效。在讀寫比例很是高的應用系統中, Query Cache 對性能的提升是很是顯著的。固然它對內存的消耗也是很是大的。
10 、 Query 優化器模塊
   Query 優化器,顧名思義,就是優化客戶端請求的 query ,根據客戶端請求的 query 語句,和數據庫中的一些統計信息,在一系列算法的基礎上進行分析,得出一個最優的策略,告訴後面的程序如何取得這個 query 語句的結果。
11 、表變動管理模塊
   表變動管理模塊主要是負責完成一些 DML 和 DDL 的 query ,如: update , delte , inse rt ,create table , alter table 等語句的處理。
12 、表維護模塊
   表的狀態檢查,錯誤修復,以及優化和分析等工做都是表維護模塊須要作的事情。
13 、系統狀態管理模塊
   系統狀態管理模塊負責在客戶端請求系統狀態的時候,將各類狀態數據返回給用戶, 像DBA 經常使用的各類 show status 命令, show variables 命令等,所獲得的結果都是由這個模塊返回的。
14 、表管理器
   這個模塊從名字上看來很容易和上面的表變動和表維護模塊相混淆,可是其功能與變動及維護模塊卻徹底不一樣。你們知道,每個 MySQL 的表都有一個表的定義文件,也就是 *.f rm文件。表管理器的工做主要就是維護這些文件,以及一個 cache ,該 cache 中的主要內容是各個表的結構信息。此外它還維護 table 級別的鎖管理。
15 、日誌記錄模塊
   日誌記錄模塊主要負責整個系統級別的邏輯層的日誌的記錄,包括error log , binar ylog , slow query log 等。
16 、複製模塊
   複製模塊又可分爲 Master 模塊和 Slave 模塊兩部分, Master 模塊主要負責在Replication 環境中讀取 Master 端的 binary 日誌,以及與 Slave 端的 I/O 線程交互等工 做。Slave 模塊比 Master 模塊所要作的事情稍多一些,在系統中主要體如今兩個線程上面。一個是負責從 Master 請求和接受 binary 日誌,並寫入本地 relay log 中的 I/O 線程。另外 一個是負責從 relay log 中讀取相關日誌事件,而後解析成能夠在 Slave 端正確執行並獲得和Master 端徹底相同的結果的命令並再交給 Slave 執行的 SQL 線程。
17 、存儲引擎接口模塊
   存儲引擎接口模塊能夠說是 MySQL 數據庫中最有特點的一點了。目前各類數據庫產品中,基本上只有 MySQL 能夠實現其底層數據存儲引擎的插件式管理。這個模塊實際上只是一個抽象類,但正是由於它成功地將各類數據處理高度抽象化,才成就了今天 MySQL 可插拔存儲引擎的特點。緩存

瞭解到整個處理過程以後,咱們能夠將以上各個模塊的關係圖:安全

wKioL1NL0U-haf6sAAQYnBky8CM633.jpg


各模塊工做配合
   在瞭解了 MySQL 的各個模塊以後,咱們再看看 MySQL 各個模塊間是如何相互協同工做 的 。接下來,咱們經過啓動 MySQL ,客戶端鏈接,請求 query ,獲得返回結果,最後退出,這樣一整個過程來進行分析。

   當咱們執行啓動 MySQL 命令以後, MySQL 的初始化模塊就從系統配置文件中讀取系統 參數和命令行參數,並按照參數來初始化整個系統,如申請並分配 buffer ,初始化全局變量 ,以及各類結構等。同時各個存儲引擎也被啓動,並進行各自的初始化工做。當整個系統初始化結束後,由鏈接管理模塊接手。鏈接管理模塊會啓動處理客戶端鏈接請求的監聽程序,包括 tcp/ip 的網絡監聽,還有 unix 的 socket 。這時候,MySQL Server 就基本啓動完成,準備好接受客戶端請求了。

   當鏈接管理模塊監聽到客戶端的鏈接請求(藉助網絡交互模塊的相關功能),雙方經過Client & Server 交互協議模塊所定義的協議 「 寒暄 」 幾句以後,鏈接管理模塊就會將鏈接請求轉發給線程管理模塊,去請求一個鏈接線程。

   線程管理模塊立刻又會將控制交給鏈接線程模塊,告訴鏈接線程模塊:如今我這邊有鏈接請求過來了,須要創建鏈接,你趕快處理一下。鏈接線程模塊在接到鏈接請求後,首先會檢查當前鏈接線程池中是否有被 cache 的空閒鏈接線程,若是有,就取出一個和客戶端請求鏈接上,若是沒有空閒的鏈接線程,則創建一個新的鏈接線程與客戶端請求鏈接。固然, 鏈接線程模塊並非在收到鏈接請求後立刻就會取出一個鏈接線程連和客戶端鏈接,而是首先經過調用用戶模塊進行受權檢查,只有客戶端請求經過了受權檢查後,他纔會將客戶端請求和負責請求的鏈接線程連上。

   在 MySQL 中,將客戶端請求分爲了兩種類型:一種是 query ,須要調用 Parser 也就是Query 解析和轉發模塊的解析纔可以執行的請求;一種是 command ,不須要調用 Parser 就能夠直接執行的請求。若是咱們的初始化配置中打開了 Full Query Logging 的功能,那麼Query 解析與轉發模塊會調用日誌記錄模塊將請求寫入日誌,無論是一個 Query 類型的請求仍是一個 command 類型的請求,都會被記錄進入日誌,因此出於性能考慮,通常不多打開 FullQuery Logging 的功能。

   當客戶端請求和鏈接線程 「 互換暗號(互通協議) 」 接上頭以後,鏈接線程就開始處理客戶端請求發送過來的各類命令(或者 query ),接受相關請求。它將收到的 query 語句轉給 Query 解析和轉發模塊, Query 解析器先對 Query 進行基本的語義和語法解析,而後根據命令類型的不一樣,有些會直接處理,有些會分發給其餘模塊來處理。

   若是是一個 Query 類型的請求,會將控制權交給 Query 解析器。 Query 解析器首先分 析看是否是一個 select 類型的 query ,若是是,則調用查詢緩存模塊,讓它檢查該 query 在query cache 中是否已經存在。若是有,則直接將 cache 中的數據返回給鏈接線程模塊, 而後經過與客戶端的鏈接的線程將數據傳輸給客戶端。若是不是一個能夠被 cache 的 query類型,或者 cache 中沒有該 query 的數據,那麼 query 將被繼續傳回 query 解析器,讓 qu ery解析器進行相應處理,再經過 query 分發 器分發給相關處理模塊。

   若是解析器解析結果是一條未被 cache 的 select 語句,則將控制權交給 Optimizer ,也就是 Query 優化器模塊,若是是 DML 或者是 DDL 語句,則會交給表變動管理模塊,若是是一些更新統計信息、檢測、修復和整理類的 query 則會交給表維護模塊去處理,複製相關 的query 則轉交給複製模塊去進行相應的處理,請求狀態的 query 則轉交給了狀態收集報告模塊。實際上表變動管理模塊根據所對應的處理請求的不一樣,是分別由 insert 處理器、 delete處理器、 update 處理器、 create 處理器,以及 alt er 處理器這些小模塊來負責不一樣的 DML和 DDL 的。

   在各個模塊收到 Query 解析與分發模塊分發過來的請求後,首先會經過訪問控制模塊檢查鏈接用戶是否有訪問目標表以及目標字段的權限,若是有,就會調用表管理模塊請求相 應的表,並獲取對應的鎖。表管理模塊首先會查看該表是否已經存在於 table cache 中,如 果已經打開則直接進行鎖相關的處理,若是沒有在 cache 中,則須要再打開表文件獲取鎖, 而後將打開的表交給表變動管理模塊。

   當表變動管理模塊 「 獲取 」 打開的表以後,就會根據該表的相關 meta 信息,判斷表的存儲引擎類型和其餘相關信息。根據表的存儲引擎類型,提交請求給存儲引擎接口模塊, 調用對應的存儲引擎實現模塊,進行相應處理。

   不過,對於表變動管理模塊來講,可見的僅是存儲引擎接口模塊所提供的一系列 「 標準 」接口,底層存儲引擎實現模塊的具體實現,對於表變動管理模塊來講是透明的。他只須要 調用對應的接口,並指明表類型,接口模塊會根據表類型調用正確的存儲引擎來進行相應的處理。

   當一條 query 或者一個 command 處理完成(成功或者失敗)以後,控制權都會交還給鏈接線程模塊。若是處理成功,則將處理結果(多是一個 Result set ,也多是成功或者失敗的標識)經過鏈接線程反饋給客戶端。若是處理過程當中發生錯誤,也會將相應的錯誤信息發送給客戶端,而後鏈接線程模塊會進行相應的清理工做,並繼續等待後面的請求,重複上面提到的過程,或者完成客戶端斷開鏈接的請求。

   若是在上面的過程當中,相關模塊使數據庫中的數據發生了變化,並且 MySQL 打開了 bin-log 功能,則對應的處理模塊還會調用日誌處理模塊將相應的變動語句以更新事件的形式記錄到相關參數指定的二進制日誌文件中。

   在上面各個模塊的處理過程當中,各自的核心運算處理功能部分都會高度依賴整個 MySQL的核心 API 模塊,好比內存管理,文件 I/O ,數字和字符串處理等等。
bash



wKioL1NL1HuyVHcgAAEZXN61lPI271.jpg

   一、客戶端與服務器端的交互永遠是經過協議來完成的,這裏的就是mysql協議,不管是經過API的方式,仍是經過專用庫的方式,必然要經過客戶端和服務器端的鏈接創建,而且將全部的查詢需求發送給服務器端,服務器端mysql經過他的工做方式,單進程多線程模型,服務器端將會使用一個線程來接收客戶端的請求。
   二、等服務器端接收到客戶端所發來的查詢語句後,首先會在服務器內部或本地檢查緩存是否命中,若是緩存命中,就當即將結果返回給客戶端,若是查詢緩存是沒有找到相對應的緩存,那這個查詢過程是白白消耗掉的,因此使用緩存的標準應該在資源開銷的3成以上,緩存並不是都是必要的、也並不是緩存存在在有效,由於它也佔用資源開銷的
   三、若是緩存沒有命中,將由緩存交給解析器,解析器負責解析以後將會交給解析樹的工具,在必要的狀況下解析樹配合預處理器進行解析,解析完這後就會有多個路徑,然後優化器將會選擇開銷最小的一條路進行下一步操做,進而將改寫後的結果交給查詢計劃,其實就是交給查詢執行引擎的,而mysql數據庫又是多用戶鏈接的,而咱們的查詢引擎只有一個,若是交給查詢引擎的查詢不少的話那就要排隊的,在隊列中,但查詢引擎並不能到磁盤中去讀取數據,取數據都是從表中取出來的、而表默認都是存儲在磁盤中的,因此查詢執行引擎僅僅是將優化器選擇好了的查詢語句轉換成查詢引擎的API調用,調用的是相對應的存儲引擎,存儲引擎根據查詢執行引擎的API調用獲取對方所需求的數據,將數據返回給執行引擎,再層層返回給客戶端。
   緩存與否也是能夠被判斷的,而咱們寫查詢語時也能夠明確指定是否須要緩存,固然,指定緩存也未必就能夠緩存,只是咱們定義某些查詢語句指望被緩存。服務器


Mysql SQL_MODE:SQL模型經常使用的有三種,SQL模型簡單來說就是定義MySQL的工做機制的,像上面說超出了字符長度是截取呢仍是不讓插入,這須要咱們定義,這種模型還能夠在必定的程度上模擬其它數據庫的工做特性的。mysql默認使用空模式

   TRADITIONAL:表示使用傳統模式
   STRICT_TRANS_TABLES:僅對支持事物的表使用嚴格模式
   STRICT_ALL_TABLES:對全部表都使用嚴格模式,嚴格模式就是當超出字符時就不容許插入數據了
   mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode';查看當前數據中使用哪一種模式
設定服務器變量的值:經常使用僅用於支持動態的變量,並不是全部的服務器的變量的值均可以設定

支持修改的服務器變量有兩類:
動態變量:能夠在mysql運行時修改
靜態變量:於配置文件中修改其值,並重啓後方能生效
修改服務器變量:服務器變量從其做用或生效範圍來說,有兩類:
全局變量:mysql全局設定,或者服務器級別,修改以後不會當即生效,僅對新創建的會話有效。
會話變量:會話級別,僅對當前會話有效,退出後即失效。
會話創建時,從全局繼承各變量
查看服務器變量:如下是查看服務器變量的三種方法    網絡

mysql > show{GLOBAL|SESSION} VARIABLES [LIKE ‘’];
mysql > SELECT @@{GLOBAL|SESSION}.VARLABLE_NAME;
mysql > select* from information_schema.global_variables where variables_name=’SOME_VARIABLES_NAME’;
修改全局變量僅管理員有權限,或者被受權,大多數普通用戶僅可以修改會話變量
mysql > set SQL_MODE=’’;設置sql_mode模塊是否記用
mysql > set {GLOBAL|SESSION} VARIABLE_NAME=’VALUE’;
mysql > show table status like ‘t3’ \G:查看某表上的存儲引擎相關信息
mysql > show engines;顯示當前服務器上的存儲引擎
MariaDB [test]>CREATE TABLE t1 (Name VARCHAR(30) NOT NULL, Age TINYINT UNSIGNED NOTNULL,PRIMARY KEY(Name,Age)) ENGINE='InnoDB';建立表t1,指定表的存儲引擎爲InnoDB

注意:不管是全局仍是會話級別的動態變量修改,在重啓mysql後都會失效,想永久有效,可定義有配置文件中相應段中[mysqld]


MYSQL中字符大小寫的問題:
   一、SQL關鍵字及函數名不區分字符大小寫,但爲了提升緩存的命中率,習慣最好要統一;
   二、數據庫、表及視圖名稱在大小寫區分與與否取決於低層OS及FS;
   三、存儲過程、存儲函數及事件調度器的名字不區分大小寫,但觸發器區分大小寫;
   四、表的別名是區分字符大小寫的;
   五、String values,對字段中的數據,若是字段類型爲Binary類型,則區分大小寫;非Binary不區分大小寫;


結束

   整理了一下有關MySQL的一些基礎理論知識以及工做原理,都是文字,長篇大論的,不過認真看來仍是比較基礎的,因爲時間問題,若有作得不到之處還望多多指點。

相關文章
相關標籤/搜索