Mysql基礎(chǔ)架構(gòu)之日志文件和數(shù)據(jù)文件

上一篇文章講述了Mysql的基本框架,和sql執(zhí)行的流程,這篇文章首先分析下每個(gè)流程的具體細(xì)節(jié),然后介紹日志文件和數(shù)據(jù)文件


截圖 (2).png

以下面語(yǔ)句作為例子來(lái)分析流程中每一步的具體細(xì)節(jié):
select * from t1 where id=10000;

連接器

mysql>mysql -uroot -p

連接器負(fù)責(zé)建立、管理、維護(hù)連接,獲取權(quán)限,當(dāng)輸入上面的命令的時(shí)候會(huì)要求輸入密碼,賬戶密碼校驗(yàn)通過(guò)之后就是建立連接,同時(shí)獲取該賬戶的權(quán)限,也就是說(shuō)當(dāng)這時(shí)管理修改了該用戶的權(quán)限的話,對(duì)于當(dāng)前連接也是沒(méi)有影響的。

查詢緩存

當(dāng)連接建立完成之后,會(huì)先到查詢緩存中查看時(shí)候有緩存存在,select語(yǔ)句的hash值作為key,查詢結(jié)果作為value,當(dāng)key存在于緩存當(dāng)中時(shí),直接返回value,當(dāng)key不存在時(shí)候會(huì)繼續(xù)執(zhí)行后面的流程,流程執(zhí)行結(jié)束之后,將查詢結(jié)果放入查詢緩存中,值得注意的是查詢緩存往往利大于弊,因?yàn)椴樵兙彺媸l繁,當(dāng)表中有數(shù)據(jù)更新時(shí),mysql就會(huì)清除查詢緩存,所以不建議使用查詢緩存,mysql8之后也將查詢緩存功能刪除了

分析器

當(dāng)查詢緩存中不存在key時(shí)流程進(jìn)入到分析器中,分析器主要負(fù)責(zé)詞法分析和語(yǔ)法分析,首先會(huì)做詞法分析,輸入的一條SQL語(yǔ)句是由多個(gè)字符串和空格組成的,MYSQL需要識(shí)別出字符串是什么,代表什么意思,如關(guān)鍵詞select,識(shí)別出來(lái)這是一個(gè)查詢語(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è)選擇:

  1. 先從t1表中取出a=10的記錄,然后根據(jù)code關(guān)聯(lián)到t2,再判斷t2的a是否等于10
  2. 先從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é)果集返回給客戶端
至此,這個(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)制日志、查詢?nèi)罩?、慢查詢?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日志文件的完整名稱: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ù)。

通用查詢?nèi)罩荆╣eneral query log)

默認(rèn)情況下是關(guān)閉的,由于通用查詢?nèi)罩緯?huì)記錄用戶的所有操作,其中還包括增刪改查等信息,在并發(fā)操作的大的環(huán)境下會(huì)產(chǎn)生大量的信息從而導(dǎo)致不必要的磁盤IO,會(huì)影響mysql的性能,如果不是為了調(diào)試數(shù)據(jù)庫(kù)的目的建議生產(chǎn)環(huán)境不要開(kāi)啟查詢?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
#記錄類型 table:將日志存入數(shù)據(jù)庫(kù),file:將日志存入文件
log_output=(TABLE|FILE|NONE)

慢查詢?nèi)罩荆╯how query log)

默認(rèn)是關(guān)閉的,可以通過(guò)如下設(shè)置進(jìn)行開(kāi)啟:

#開(kāi)啟慢查詢?nèi)罩?slow_query_log=ON
#慢查詢的閾值
long_query_time=1
#日志文件如果沒(méi)有給出file_name,默認(rèn)為主機(jī)名,后綴為-slow.log,如果給出了文件名,但不是絕對(duì)路徑、文件則寫入數(shù)據(jù)目錄
slow_query_log_file=file_name

記錄執(zhí)行時(shí)間超過(guò)long_query_time秒的所有查詢,便于收集查詢時(shí)間比較長(zhǎng)的SQL語(yǔ)句

重做日志(redo log)

作用:確保事務(wù)的持久性。防止在發(fā)生故障的時(shí)間點(diǎ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的落盤并不是隨著事務(wù)的提交才寫入的,而是在事務(wù)的執(zhí)行過(guò)程中,便開(kāi)始寫入redo log文件中
什么時(shí)候釋放:當(dāng)對(duì)應(yīng)的事務(wù)的臟頁(yè)寫入到磁盤之后,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的?前面說(shuō)了是在事務(wù)開(kāi)始之后逐步寫盤的,之所以說(shuō)重做日志是在事務(wù)開(kāi)始之后逐步寫入,而不一定是事務(wù)提交才寫入,原因就是重做日志有一個(gè)緩存區(qū)innodb_log_buffer,默認(rèn)大小為8M,innodb存儲(chǔ)引擎先將重做日志寫入innodb_log_buffer中。然后通過(guò)三種方式將innodb日志緩沖區(qū)的日志刷新到磁盤 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)名稱是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ù)文件寫入是隨機(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

公眾號(hào)二維碼:
qrcode_for_gh_3d746d8ff050_258 (1).jpg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容