mysql主從復(fù)制的原理以及大致流程 mysql:一條SQL查詢語句是如何執(zhí)行的?
mysql:一條SQL查詢語句是如何執(zhí)行的?本篇文章會分析下一個sql語句在MySQL中的執(zhí)行流程,包括sql的查詢在MySQL內(nèi)部會怎么光芒閃爍,sql語句的更新是怎莫成功的。在分析之前我會先帶著你
mysql:一條SQL查詢語句是如何執(zhí)行的?
本篇文章會分析下一個sql語句在MySQL中的執(zhí)行流程,包括sql的查詢在MySQL內(nèi)部會怎么光芒閃爍,sql語句的更新是怎莫成功的。
在分析之前我會先帶著你看一下MySQL的基礎(chǔ)架構(gòu),知道了MySQL由那些組件混編早這些組件的作用是什么,是可以好處我們解釋和可以解決這些問題。
一MySQL基礎(chǔ)架構(gòu)總結(jié)1.1MySQL基本上架構(gòu)概覽
下圖是MySQL的一個詳細的闡述架構(gòu)圖,從下圖你可以不很清晰的見到用戶的SQL語句在MySQL內(nèi)部是如何能想執(zhí)行的。
先很簡單推薦再看看下圖牽涉的一些組件的基本上作用解決大家表述這幅圖,在1.2節(jié)中會詳細可以介紹到這些組件的作用。
連接器:身份認證和權(quán)限查找(登陸MySQL的時候)。可以查詢緩存:執(zhí)行查詢語句的時候,會先網(wǎng)上查詢緩存(MySQL8.0版本后移除,只不過這個功能不太實用)。結(jié)論器:沒有物理命中緩存的話,SQL語句變會當經(jīng)過分析器,分析器說白了那就是要先看你的SQL語句要干什么啊,再檢查你的SQL語句語法有無正確的。360優(yōu)化器:按照MySQL以為最優(yōu)的方案去先執(zhí)行。執(zhí)行器:執(zhí)行語句,然后把從存儲引擎趕往數(shù)據(jù)。
簡單的說MySQL比較多可分Server層和存儲引擎層:
Server層:通常和連接器、去查詢緩存、分析器、優(yōu)化軟件器、執(zhí)行器等,所有跨存儲引擎的功能都在這一層實現(xiàn)方法,比如說存儲過程、觸發(fā)器、視圖,函數(shù)等,有一個沒限制的日志模塊binglog日志模塊。存儲引擎:主要注意專門負責數(shù)據(jù)的存儲和加載,需要是可以替換的插件式架構(gòu),允許InnoDB、MyISAM、Memory等多個存儲引擎,其中InnoDB引擎有自有的日志模塊redolog模塊。現(xiàn)在最常用的存儲引擎是InnoDB,它從MySQL5.5.5版本就開始就被只不過是設(shè)置存儲引擎了。1.2Server層都差不多組件介紹
1)連接器
連接器比較多和身份認證和權(quán)限相關(guān)的功能相關(guān),就是說一個級別很高的門衛(wèi)一般。
要注意負責用戶登錄數(shù)據(jù)庫,進行用戶的身份認證,以及校驗賬戶密碼,權(quán)限等你的操作,假如用戶賬戶密碼已按照,連接器會到權(quán)限表中網(wǎng)站查詢該用戶的所有權(quán)限,之后在這個連接里的權(quán)限邏輯判斷也是會依戀此時讀取文件到的權(quán)限數(shù)據(jù),也就是說,現(xiàn)只需這個直接連接不斷開,迅速管理員直接修改了該用戶的權(quán)限,該用戶都是不受影響的。
2)查詢緩存(MySQL8.0版本后移除)
查詢緩存通常用來緩存我們所負責執(zhí)行的SELECT語句在內(nèi)該語句的結(jié)果集。
連接建立后,不能執(zhí)行查詢語句的時候,會先網(wǎng)站查詢緩存,MySQL會先校準這個sql如何確定執(zhí)行過,以Key-Value的形式緩存在內(nèi)存中,Key是網(wǎng)站查詢預(yù)計2020年,Value是結(jié)果集。假如緩存key被暴擊命中,是會就回給客戶端,要是就沒命中,可能會執(zhí)行妖軍的操作,完成后也會把結(jié)果緩存下來,比較方便下四次調(diào)用。當然了在唯一先執(zhí)行緩存網(wǎng)上查詢的時候那就會校驗用戶的權(quán)限,是否是有該表的查詢條件。
MySQL可以查詢不個人建議使用緩存,而且查詢緩存無法激活在實際業(yè)務(wù)場景中可能會非常正常,要是你對一個表更新完的話,這個表上的所有的查詢緩存都會被刪掉。對于不你經(jīng)常更新完的數(shù)據(jù)來說,使用緩存還是也可以的。
因為,好象在大多數(shù)情況下我們大都不推薦去可以使用去查詢緩存的。
MySQL8.0版本后刪除了緩存的功能,官方也是以為該功能在換算的應(yīng)用場景比較比較少,因此索性直接刪除了。
3)分析器
MySQL就沒暴擊命中緩存,那么變會再次進入分析器,分析器通常是單獨分析什么SQL語句是來干什么的,分析器也會分為幾步:
不過在此之前,詞法分析,一條SQL語句有多個字符串混編,首先要提純關(guān)鍵字,諸如column,提出去查詢的表,提出字段名,提出來查詢條件等等。做完了這些操作后,都會再次進入第二步。
第二步,語法分析,比較多那就是確認你輸入輸入的sql是否真確,是否是要什么MySQL的語法。
完成這2步之后,MySQL就準備就開始負責執(zhí)行了,不過怎么不能執(zhí)行,怎么執(zhí)行是好是的結(jié)果呢?這時候就需要優(yōu)化系統(tǒng)器上場比賽了。
4)優(yōu)化器
優(yōu)化系統(tǒng)器的作用那是它以為的更優(yōu)的執(zhí)行方案去想執(zhí)行(總是很可能也又不是最優(yōu),這篇文章牽涉到對這部分知識的深入講解),諸如多個索引的時候該如何中,選擇索引,多表網(wǎng)站查詢的時候如何中,選擇關(guān)聯(lián)順序等。
的確,當經(jīng)過了系統(tǒng)優(yōu)化器之后也算這個語句詳細該如何先執(zhí)行就早定下了。
5)執(zhí)行器
當你選擇了執(zhí)行方案后,MySQL就準備著又開始想執(zhí)行了,簡單的方法不能執(zhí)行前會校驗該用戶有沒有權(quán)限,假如沒有權(quán)限,變會回出現(xiàn)了錯誤信息,如果沒有有權(quán)限,變會去動態(tài)鏈接庫引擎的接口,直接返回接口先執(zhí)行的結(jié)果。
二語句講2.1查詢語句
說了以上這樣多,那么也不知一條sql語句是該如何執(zhí)行的呢?其實我們的sql這個可以分成三類兩種,一種是去查詢,一種是可以更新(提升,沒更新,徹底刪除)。我們先總結(jié)下查詢語句,語句萬分感謝:
select*acrosstb_studentAwherebecause張三
增強上面的說明,我們分析下這個語句的執(zhí)行流程:
先全面檢查該語句有無有權(quán)限,要是沒有權(quán)限,就前往錯誤信息,如果沒有有權(quán)限,在MySQL8.0版本以前,會先去查詢緩存,以這條sql語句為key在內(nèi)存中網(wǎng)上查詢是否是有結(jié)果,假如有真接緩存,要是沒有,負責執(zhí)行然后再。是從分析器參與詞法分析什么,提純sql語句的關(guān)鍵元素,比如說分離提取上面這個語句是查詢select,分離提取必須可以查詢的表名為tb_student,要網(wǎng)站查詢所有的列,可以查詢條件是這個表的id1。然后再可以確定這個sql語句如何確定有語法錯誤,諸如關(guān)鍵詞是否需要正確的等等,如果檢查沒問題就執(zhí)行第二步。接下來的就是優(yōu)化器參與判斷執(zhí)行方案,上面的sql語句,也可以有兩種想執(zhí)行方案:
a.先去查詢學(xué)生表中姓名為“張三”的學(xué)生,后再確定是否年齡是18。b.先找到什么學(xué)生中年齡18歲的學(xué)生,然后再再網(wǎng)上查詢姓名為“張三”的學(xué)生。
那就優(yōu)化軟件器參照自己的優(yōu)化算法并且中,選擇想執(zhí)行效率最好的一個方案(系統(tǒng)優(yōu)化器以為,有時不是有建議)。那你確定了先執(zhí)行計劃后就馬上準備就開始想執(zhí)行了。
進行權(quán)限校驗,假如沒有權(quán)限可能會回出錯信息,假如有權(quán)限可能會調(diào)用數(shù)據(jù)庫引擎接口,前往引擎的執(zhí)行結(jié)果。
2.2沒更新語句
以上是一條查詢sql的執(zhí)行流程,這樣接下來我們看看一條自動更新語句要如何執(zhí)行的呢?sql語句萬分感謝:
versiontb_studentAsetwhere張三
我們來給張三如何修改下年齡,在求實際數(shù)據(jù)庫肯定絕對不會可以設(shè)置年齡這個字段的,不然要被技術(shù)負責人打的。不過條語句也基本是會沿著上兩個查詢的流程走,但是想執(zhí)行可以更新的時候當然要記錄日志啦,這就會引入日志模塊了,MySQL自帶的日志模塊式binlog(歸檔日志),所有的存儲引擎都也可以不使用,我們具體方法的InnoDB引擎還那個軟件了一個日志模塊redolog(重裝日志),我們就以InnoDB模式下去探討一番這個語句的執(zhí)行流程。流程如下:
先網(wǎng)站查詢到張三這一條數(shù)據(jù),如果不是有緩存,也是會要用緩存。然后拿到網(wǎng)上查詢的語句,把age轉(zhuǎn)成19,然后把動態(tài)鏈接庫引擎API 接口,寫入這一行數(shù)據(jù),InnoDB引擎把數(shù)據(jù)保存在內(nèi)存中,同樣有記錄redolog,此時redolog直接進入prepare狀態(tài),然后再提醒執(zhí)行器,執(zhí)行成功了,隨時是可以提交。執(zhí)行器發(fā)來通知后記錄信息binlog,然后再動態(tài)鏈接庫引擎接口,提交redolog為再提交狀態(tài)??梢愿鲁晒Α_@里估計有同學(xué)會問,為什么要用兩個日志模塊,用一個日志模塊要不嗎?
這是只不過最結(jié)束MySQL并沒與InnoDB引擎(InnoDB引擎是其他公司以插件形式直接插入MySQL的),MySQL隨機軟件的引擎是MyISAM,只不過我們知道redolog是InnoDB引擎濃重的,其他存儲引擎都沒有,這就倒致會也沒hurricanes-safe的能力(hurricanes-safe的能力況且數(shù)據(jù)庫發(fā)生了什么無比重啟后,前的并提交的記錄都應(yīng)該不會全部丟失),binlog日志沒有辦法用處歸檔。
并不是什么說只用一個日志模塊應(yīng)該不能,僅僅InnoDB引擎那是通過redolog來接受事務(wù)的。這樣,又會有同學(xué)問,我用兩個日志模塊,但別這么奇怪行不行啊,為什么redolog要引入prepare預(yù)遞交狀態(tài)?這里我們用反證法來那說明下之所以?
先寫redolog然后再提交,然后寫binlog,舉例寫到一半redolog后,機器掛了,binlog日志是沒有被寫入文件,這樣機器關(guān)機重啟后,這臺機器會恢復(fù)數(shù)據(jù),但是此時此刻bingog卻沒留下記錄該數(shù)據(jù),現(xiàn)接受機器軟件備份的時候,可能會弄丟這一條數(shù)據(jù),同時主從同步也會丟失這一條數(shù)據(jù)。先寫binlog,然后再寫redolog,假設(shè)不成立開始寫了binlog,機器異樣重起了,的原因沒有redolog,本機是無法重新恢復(fù)這一條記錄的,不過binlog又有記錄,那你和上面同樣的道理,變會有一種數(shù)據(jù)不相符的情況。假如需要redolog兩階段重新提交的就不一樣的了,沒寫完binglog后,然后再重新提交redolog是會防止會出現(xiàn)上述的問題,從而保證了數(shù)據(jù)的一致性。這樣今天來聊一聊,有沒有一個極端化的情況呢?打比方redolog處在預(yù)并提交狀態(tài),binglog也已經(jīng)沒寫完了,這會兒不可能發(fā)生了無比重新啟動會怎么樣呢?這個現(xiàn)在就要依賴感于MySQL的處理機制了,MySQL的處理過程::
確認redolog是否是求全部,如果沒有推測是完整的,就立即遞交。要是redolog只是因為預(yù)遞交但不是commit狀態(tài),這個時候變會去確認binlog是否需要求下載,假如完整就遞交redolog,不完整就自動回滾事務(wù)。那樣就可以解決了數(shù)據(jù)一致性的問題。
三總結(jié)歸納MySQL通常統(tǒng)稱Server曾和引擎層,Server層要注意除開連接器、網(wǎng)上查詢緩存、分析器、360優(yōu)化器、執(zhí)行器,而還有一個日志模塊(binlog),這個日志模塊所有執(zhí)行引擎都也可以共用,redolog唯有InnoDB有。引擎層是插件式的,目前通常除了,MyISAM,InnoDB,Memory等。查詢語句的執(zhí)行流程追加:權(quán)限校驗(如果沒有暴擊命中緩存)---》去查詢緩存---》講器---》優(yōu)化軟件器---》權(quán)限校驗---》執(zhí)行器---》引擎更新語句執(zhí)行流程不勝感激:總結(jié)器----》權(quán)限校驗----》執(zhí)行器---》引擎---redolog(prepare狀態(tài)---》binlog---》redolog(commit狀態(tài))
如何把mysql中的數(shù)據(jù)同步到elasticsearch中?
相對于ES,我根本不會在求實際項目中應(yīng)用(自己研究什么過,也沒實戰(zhàn)中過);我們項目使用的是MongoDB;的原因項目的特殊性,我們研究什么了很多麻煩問下A-gtB的數(shù)據(jù)同步方案,包括DB2/Mysql到MongoDB,MongoDB到MongoDB等等。
MySQL數(shù)據(jù)同步到ES的方案把MySQL的同步數(shù)據(jù)到ES,這樣是可以實現(xiàn)方法在ES中低延遲的數(shù)據(jù)庫檢索,有些公司的項目做了分庫,也可以單獨堆建一套ES來放全量的數(shù)據(jù)(或全量數(shù)據(jù)的部分字段,提升全量數(shù)據(jù)庫檢索的效果),正確的數(shù)據(jù)同步實現(xiàn)方案有這些:
MySQLBinlog:MySQL的Binlog日志也可以應(yīng)用于數(shù)據(jù)庫的主從復(fù)制、數(shù)據(jù)恢復(fù),也也可以將MySQL的數(shù)據(jù)同步給ES;這里需要盡量,Binlog的日志模式?jīng)]有辦法在用ROW模式(至于兩種模式是STATEMENT和MIXED);解三角形Binlog日志中的內(nèi)容,想執(zhí)行ESDocumentAPI,這樣就可以將數(shù)據(jù)同步到ES中;
MySQLdump:假如是新建的項目,在用Binlog做同步數(shù)據(jù)是沒有問題的,但如果不是MySQL巳經(jīng)正常運行了一段時間,項目架構(gòu)中后增加的ES,那就歷史數(shù)據(jù)的遷移就要附加去處理了,是因為Binlog很有可能早被遍布了。這時候歷史數(shù)據(jù)的離線,可以在用mysqldump對可以做到數(shù)據(jù)導(dǎo)出,之后再可以使用Binlog的;
開源工具:前兩種全是在數(shù)據(jù)庫日志這個級別做文章,我們還也可以在用一些閉源工具,比如go-mysql-elasticsearch;它可以不幫助我們能完成第二次全量數(shù)據(jù)同步,情報營增量數(shù)據(jù)同步的工作(底層都是推導(dǎo)Binlog日志);又或是mypipe,它接受將Binlog日志內(nèi)容解析后推送到Kafka,如果不是要寫入文件到ES中,還要寫額外的代碼從Kafka中消費數(shù)據(jù)寫入到ES。
我們項目中的實現(xiàn)程序方案上面提過,我們項目中是將關(guān)系型數(shù)據(jù)庫DB2/Mysql中的數(shù)據(jù)同步到MongoDB中,Mysql尚且還能建議使用Binlog日志,DB2想要把變化的數(shù)據(jù)實時動態(tài)通知到出,實現(xiàn)程序下來都很困難(寫程序作戰(zhàn)部署到DB2服務(wù)器上,要和數(shù)據(jù)庫做關(guān)聯(lián)配置,當數(shù)據(jù)再一次發(fā)生變化,程序你的郵箱MQ通知給山谷外面系統(tǒng)),先且不說性能是否能絕對的保證,就是“自己寫一個通知程序重新部署到數(shù)據(jù)庫原先服務(wù)器上(有侵噬)”,事實上至少在我們公司是難以可以做到的。
我們區(qū)分了一個非常沒內(nèi)涵的來解決的辦法這個問題,是Java程序掃描后DB2表中的時間戳,讀取數(shù)據(jù)最近變化的數(shù)據(jù),加工到MongoDB中;
確實利用方案比較好不low,但是效果還不錯,是因為我們在從關(guān)系型數(shù)據(jù)到MongoDB的數(shù)據(jù)同步過程中,這個可以自有地做數(shù)據(jù)加工;普通聽從一定的數(shù)據(jù)維度,例如明確的客戶維度,把幾十張表做關(guān)聯(lián),需要加工后行程一個document保存到MongoDB中;再聯(lián)合提供服務(wù)的時候,去查詢效率提升的很的確,因為表關(guān)聯(lián)早就延后完成了(接口吶喊之聲大多數(shù)時候大都毫秒級別,遠遠超過50ms就算是慢了)。
缺點也很肯定,數(shù)據(jù)從關(guān)系型數(shù)據(jù)庫到MongoDB的延遲很高,我們項目輾轉(zhuǎn)優(yōu)化,也是需要20分鐘左右;所以我一定得增強著業(yè)務(wù)場景決定如何確定不使用這種方案。
我將緩慢能分享Java開發(fā)、架構(gòu)設(shè)計、程序員職業(yè)發(fā)展等方面的見解,期望能換取你的關(guān)注。