上一篇文章講述了Mysql的基本框架,和sql執(zhí)行的流程匹表,這篇文章首先分析下每個(gè)流程的具體細(xì)節(jié)门坷,然后介紹日志文件和數(shù)據(jù)文件
以下面語(yǔ)句作為例子來(lái)分析流程中每一步的具體細(xì)節(jié):
select * from t1 where id=10000;
連接器
mysql>mysql -uroot -p
連接器負(fù)責(zé)建立、管理袍镀、維護(hù)連接默蚌,獲取權(quán)限,當(dāng)輸入上面的命令的時(shí)候會(huì)要求輸入密碼苇羡,賬戶(hù)密碼校驗(yàn)通過(guò)之后就是建立連接绸吸,同時(shí)獲取該賬戶(hù)的權(quán)限,也就是說(shuō)當(dāng)這時(shí)管理修改了該用戶(hù)的權(quán)限的話设江,對(duì)于當(dāng)前連接也是沒(méi)有影響的锦茁。
查詢(xún)緩存
當(dāng)連接建立完成之后,會(huì)先到查詢(xún)緩存中查看時(shí)候有緩存存在叉存,select語(yǔ)句的hash值作為key码俩,查詢(xún)結(jié)果作為value,當(dāng)key存在于緩存當(dāng)中時(shí)歼捏,直接返回value稿存,當(dāng)key不存在時(shí)候會(huì)繼續(xù)執(zhí)行后面的流程,流程執(zhí)行結(jié)束之后瞳秽,將查詢(xún)結(jié)果放入查詢(xún)緩存中瓣履,值得注意的是查詢(xún)緩存往往利大于弊,因?yàn)椴樵?xún)緩存失效太頻繁练俐,當(dāng)表中有數(shù)據(jù)更新時(shí)袖迎,mysql就會(huì)清除查詢(xún)緩存,所以不建議使用查詢(xún)緩存腺晾,mysql8之后也將查詢(xún)緩存功能刪除了
分析器
當(dāng)查詢(xún)緩存中不存在key時(shí)流程進(jìn)入到分析器中瓢棒,分析器主要負(fù)責(zé)詞法分析和語(yǔ)法分析,首先會(huì)做詞法分析丘喻,輸入的一條SQL語(yǔ)句是由多個(gè)字符串和空格組成的脯宿,MYSQL需要識(shí)別出字符串是什么,代表什么意思泉粉,如關(guān)鍵詞select连霉,識(shí)別出來(lái)這是一個(gè)查詢(xún)語(yǔ)句榴芳,字符串t1識(shí)別為表名t1,id識(shí)別為例id跺撼。之后就是做語(yǔ)法分析窟感,根據(jù)詞法分析結(jié)果,語(yǔ)法分析器會(huì)根據(jù)語(yǔ)法規(guī)則歉井,判斷是你輸入的這個(gè)SQL語(yǔ)句是否滿足Mysql語(yǔ)法柿祈,如果語(yǔ)法不對(duì),就會(huì)收到語(yǔ)法錯(cuò)誤提醒
優(yōu)化器
經(jīng)過(guò)了分析器之后Mysql就知道你要做什么了哩至,在開(kāi)始執(zhí)行之前Mysql還會(huì)經(jīng)過(guò)優(yōu)化器的處理躏嚎,例如索引的選擇,多表join的時(shí)候菩貌,選擇那個(gè)表作為驅(qū)動(dòng)表卢佣,例如下面的語(yǔ)句
mysql>select * from t1 join t2 on t1.code = t2.code where t1.a=10 and t2.a=10;
當(dāng)執(zhí)行這條語(yǔ)句的時(shí)候Mysql有兩個(gè)選擇:
- 先從t1表中取出a=10的記錄,然后根據(jù)code關(guān)聯(lián)到t2箭阶,再判斷t2的a是否等于10
- 先從t2表中取出a=10的記錄虚茶,然后根據(jù)code關(guān)聯(lián)到t1,再判斷t1的a是否等于10
很明顯兩種方法的執(zhí)行結(jié)果是一樣的仇参,但是執(zhí)行效率會(huì)有不同, 優(yōu)化器要做的就是選擇最優(yōu)的方案
執(zhí)行器
Mysql經(jīng)過(guò)了優(yōu)化器之后嘹叫,就進(jìn)入了執(zhí)行器階段,開(kāi)始執(zhí)行語(yǔ)句诈乒,執(zhí)行之前會(huì)先判斷是否有執(zhí)行權(quán)限待笑,如果沒(méi)有則會(huì)報(bào)錯(cuò),如果有權(quán)限抓谴,則會(huì)打開(kāi)表繼續(xù)執(zhí)行暮蹂,執(zhí)行就會(huì)調(diào)用具體引擎的接口,比如我們這個(gè)例子中id字段沒(méi)有索引癌压,則執(zhí)行器的執(zhí)行流程如下:
調(diào)用InnoDB引起的接口取出表中的第一行仰泻,判斷id是不是等于10,如果不是則跳過(guò)滩届,如果是則將這行存在結(jié)果集中
調(diào)用引擎接口取下一行集侯,重復(fù)相同的邏輯判斷,知道渠道這個(gè)表的最后一行
執(zhí)行器將上述遍歷過(guò)程中所有滿足條件的行組成記錄集作為結(jié)果集返回給客戶(hù)端
至此帜消,這個(gè)語(yǔ)句就執(zhí)行完成了
Mysql的物理結(jié)構(gòu)
mysql是通過(guò)文件系統(tǒng)對(duì)數(shù)據(jù)和索引進(jìn)行存儲(chǔ)的
mysql從物理結(jié)構(gòu)上可以分為日志文件和數(shù)據(jù)索引文件
日志文件
Mysql通過(guò)日志記錄了數(shù)據(jù)庫(kù)操作信息和錯(cuò)誤信息棠枉,常用的日志文件有錯(cuò)誤日志、二進(jìn)制日志泡挺、查詢(xún)?nèi)罩颈惭取⒙樵?xún)?nèi)罩竞褪聞?wù)Redo日志、中繼日志等
可以通過(guò)命令查看當(dāng)前數(shù)據(jù)庫(kù)中的日志使用信息:
show VARIABLES like 'log_%';
錯(cuò)誤日志(errorlog)
默認(rèn)是開(kāi)啟的娄猫,Mysql5.5.7之后無(wú)法關(guān)閉錯(cuò)誤日志贱除,錯(cuò)誤日志記錄了運(yùn)行過(guò)程中遇到的所有的嚴(yán)重錯(cuò)誤信息以及Mysql每次啟動(dòng)和關(guān)閉的詳細(xì)信息生闲,
錯(cuò)誤日志可以通過(guò)log-error和log-warnings來(lái)定義,其中l(wèi)og-err是定義是否啟用錯(cuò)誤日志的功能和錯(cuò)誤日志的存儲(chǔ)位置月幌,log-warings是定義是否將警告信息也定義至錯(cuò)誤日志中
log-error=/var/log/mysqld.log
#使用1|0來(lái)定義啟動(dòng)和關(guān)閉
log_waring=1
二進(jìn)制日志
默認(rèn)是關(guān)閉的碍讯,可以通過(guò)下面的配置開(kāi)啟
log-bin=mysql-bin
其中mysql-bin是binlong日志文件的basename,binlog日志文件的完整名稱(chēng):mysql-bin-000001.log
binlog記錄了數(shù)據(jù)庫(kù)的所有的ddl語(yǔ)句和dml語(yǔ)句扯躺,但不包括select語(yǔ)句內(nèi)容捉兴,語(yǔ)句以事件的形式保存,描述了數(shù)據(jù)的變更順序录语,binlog還包括了每個(gè)更新語(yǔ)句的執(zhí)行時(shí)間信息倍啥,如果是DDL,則直接記錄到binlog日志钦无,而DML語(yǔ)句必須通過(guò)失誤提交才能記錄到binlog日志中逗栽。
binlog主要用于實(shí)現(xiàn)mysql的主從復(fù)制盖袭、數(shù)據(jù)備份失暂、數(shù)據(jù)恢復(fù)。
通用查詢(xún)?nèi)罩荆╣eneral query log)
默認(rèn)情況下是關(guān)閉的鳄虱,由于通用查詢(xún)?nèi)罩緯?huì)記錄用戶(hù)的所有操作弟塞,其中還包括增刪改查等信息,在并發(fā)操作的大的環(huán)境下會(huì)產(chǎn)生大量的信息從而導(dǎo)致不必要的磁盤(pán)IO拙已,會(huì)影響mysql的性能决记,如果不是為了調(diào)試數(shù)據(jù)庫(kù)的目的建議生產(chǎn)環(huán)境不要開(kāi)啟查詢(xún)?nèi)罩?br> show global VARIABLES like 'general_Log';
開(kāi)啟方式如下:
#啟動(dòng)或關(guān)閉
general_log=(ON|OFF)
#日志文件變量,如果general_log_file沒(méi)有指定倍踪,默認(rèn)名是host_name.log
general_log_file=/path/to/file
#記錄類(lèi)型 table:將日志存入數(shù)據(jù)庫(kù)系宫,file:將日志存入文件
log_output=(TABLE|FILE|NONE)
慢查詢(xún)?nèi)罩荆╯how query log)
默認(rèn)是關(guān)閉的,可以通過(guò)如下設(shè)置進(jìn)行開(kāi)啟:
#開(kāi)啟慢查詢(xún)?nèi)罩?slow_query_log=ON
#慢查詢(xún)的閾值
long_query_time=1
#日志文件如果沒(méi)有給出file_name建车,默認(rèn)為主機(jī)名扩借,后綴為-slow.log,如果給出了文件名缤至,但不是絕對(duì)路徑潮罪、文件則寫(xiě)入數(shù)據(jù)目錄
slow_query_log_file=file_name
記錄執(zhí)行時(shí)間超過(guò)long_query_time秒的所有查詢(xún),便于收集查詢(xún)時(shí)間比較長(zhǎng)的SQL語(yǔ)句
重做日志(redo log)
作用:確保事務(wù)的持久性领斥。防止在發(fā)生故障的時(shí)間點(diǎn)嫉到,尚有葬爺未寫(xiě)入磁盤(pán),在重啟myslq服務(wù)的時(shí)候月洛,根據(jù)redo log進(jìn)行重做何恶,從而達(dá)到事務(wù)的持久性這一特性
內(nèi)容:物理格式的日志,記錄的是物理數(shù)據(jù)頁(yè)面的修改的信息嚼黔,其中redo log是順序?qū)懭雛edo log file的物理文件中的导而。
什么時(shí)候產(chǎn)生:事務(wù)開(kāi)啟之后就會(huì)產(chǎn)生redo log忱叭,redo log的落盤(pán)并不是隨著事務(wù)的提交才寫(xiě)入的,而是在事務(wù)的執(zhí)行過(guò)程中今艺,便開(kāi)始寫(xiě)入redo log文件中
什么時(shí)候釋放:當(dāng)對(duì)應(yīng)的事務(wù)的臟頁(yè)寫(xiě)入到磁盤(pán)之后韵丑,redo log的使命也就是完成了,重做日志占用的空間就可以重用(被覆蓋)
對(duì)應(yīng)的物理文件:默認(rèn)情況下虚缎,對(duì)應(yīng)的物理文件位于數(shù)據(jù)庫(kù)的data目錄下的ib_logfile1&ib_logfile2撵彻,innodb_log_group_home_dir指定日志文件組所在的路徑,默認(rèn)是/实牡,表示數(shù)據(jù)庫(kù)的數(shù)據(jù)目錄下陌僵。innodb_log_files_in_group指定重做日志文件組中的文件的數(shù)量,innodb_log_file_size指定重做日志文件的大小
其他:很重要的一點(diǎn)创坞,redo log是什么時(shí)候?qū)懕P(pán)的碗短?前面說(shuō)了是在事務(wù)開(kāi)始之后逐步寫(xiě)盤(pán)的,之所以說(shuō)重做日志是在事務(wù)開(kāi)始之后逐步寫(xiě)入题涨,而不一定是事務(wù)提交才寫(xiě)入偎谁,原因就是重做日志有一個(gè)緩存區(qū)innodb_log_buffer,默認(rèn)大小為8M纲堵,innodb存儲(chǔ)引擎先將重做日志寫(xiě)入innodb_log_buffer中巡雨。然后通過(guò)三種方式將innodb日志緩沖區(qū)的日志刷新到磁盤(pán) 1、每秒一次執(zhí)行刷新innodb_log_buffer到重做日志文件席函。2铐望、每個(gè)事務(wù)提交時(shí)會(huì)將重做日志刷新到重做日志文件。3茂附、當(dāng)重做日志緩存可用空間少于一半是正蛙,重做日志緩存被刷新到重做日志文件
回滾日志(undo log)
作用:保存了事務(wù)發(fā)生之前的一個(gè)數(shù)據(jù)版本,可以用于回滾营曼,同時(shí)可以提供多版本并發(fā)控制下的讀(MVCC)乒验,也即非鎖定讀(快照讀)
內(nèi)容:邏輯格式的日志,在執(zhí)行undo的時(shí)候溶推,僅僅是將數(shù)據(jù)從邏輯上恢復(fù)至事務(wù)之前的狀態(tài)徊件,而不是從物理頁(yè)面上操作實(shí)現(xiàn)的,這一點(diǎn)是不同于redo log的
什么時(shí)候產(chǎn)生:事務(wù)開(kāi)始之前蒜危,將當(dāng)前的版本生成undo log虱痕,undo也會(huì)產(chǎn)生redo來(lái)保證undo log的可靠性
什么時(shí)候釋放:當(dāng)事務(wù)提交之后,undo log并不能立馬被刪除辐赞,而是放入待清理的鏈表部翘,有purge線程判斷是否由其他事務(wù)在使用undo段中的表上一個(gè)事務(wù)之前的版本信息。決定是否可以清理undo log的日志空間
對(duì)應(yīng)的物理文件:Mysql5.6之前响委,undo表空間位于共享表空間的回滾段中新思,共享表空間的默認(rèn)名稱(chēng)是ibdata窖梁,位于數(shù)據(jù)文件目錄中,Mysql5.6之后夹囚,undo表空間可以配置成獨(dú)立的文件纵刘,但是提前需要在配置文件中配置,
中繼日志(relay log)
是在主從復(fù)制環(huán)境中產(chǎn)生的日志
主要作用是為了叢機(jī)可以從中繼日志中獲取到主機(jī)同步過(guò)來(lái)的SQL語(yǔ)句荸哟,然后執(zhí)行到從機(jī)中假哎。
數(shù)據(jù)文件
數(shù)據(jù)文件寫(xiě)入是隨機(jī)IO
InnoDB數(shù)據(jù)文件
.frm文件:主要存放與表相關(guān)的數(shù)據(jù)信息,主要包括表結(jié)構(gòu)的定義信息
.ibd:使用獨(dú)享表空間存儲(chǔ)數(shù)據(jù)和索引信息鞍历,一張表對(duì)應(yīng)一個(gè)ibd文件
ibdata文件:使用共享表空間存儲(chǔ)數(shù)據(jù)和索引信息舵抹,所有表共同使用一個(gè)或者多個(gè)ibdata文件
MyISAM數(shù)據(jù)文件
.frm文件:主要存放與表相關(guān)的數(shù)據(jù)信息,主要包括表結(jié)構(gòu)的定義信息
.myd文件:主要用來(lái)存儲(chǔ)表數(shù)據(jù)信息
.myi文件:主要用來(lái)存儲(chǔ)表數(shù)據(jù)文件中任何索引的數(shù)據(jù)樹(shù)
更多技術(shù)文章可關(guān)注個(gè)人公眾號(hào): 碼農(nóng)Fly